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/api.h"
6
7 #include <algorithm> // For min
8 #include <cmath> // For isnan.
9 #include <limits>
10 #include <sstream>
11 #include <string>
12 #include <utility> // For move
13 #include <vector>
14
15 #include "include/v8-callbacks.h"
16 #include "include/v8-cppgc.h"
17 #include "include/v8-date.h"
18 #include "include/v8-embedder-state-scope.h"
19 #include "include/v8-extension.h"
20 #include "include/v8-fast-api-calls.h"
21 #include "include/v8-function.h"
22 #include "include/v8-json.h"
23 #include "include/v8-locker.h"
24 #include "include/v8-primitive-object.h"
25 #include "include/v8-profiler.h"
26 #include "include/v8-unwinder-state.h"
27 #include "include/v8-util.h"
28 #include "include/v8-wasm.h"
29 #include "src/api/api-inl.h"
30 #include "src/api/api-natives.h"
31 #include "src/base/functional.h"
32 #include "src/base/logging.h"
33 #include "src/base/platform/platform.h"
34 #include "src/base/platform/time.h"
35 #include "src/base/safe_conversions.h"
36 #include "src/base/utils/random-number-generator.h"
37 #include "src/baseline/baseline-batch-compiler.h"
38 #include "src/builtins/accessors.h"
39 #include "src/builtins/builtins-utils.h"
40 #include "src/codegen/compiler.h"
41 #include "src/codegen/cpu-features.h"
42 #include "src/codegen/script-details.h"
43 #include "src/common/assert-scope.h"
44 #include "src/common/globals.h"
45 #include "src/compiler-dispatcher/lazy-compile-dispatcher.h"
46 #include "src/date/date.h"
47 #include "src/objects/primitive-heap-object.h"
48 #if V8_ENABLE_WEBASSEMBLY
49 #include "src/debug/debug-wasm-objects.h"
50 #endif // V8_ENABLE_WEBASSEMBLY
51 #include "src/debug/liveedit.h"
52 #include "src/deoptimizer/deoptimizer.h"
53 #include "src/execution/embedder-state.h"
54 #include "src/execution/execution.h"
55 #include "src/execution/frames-inl.h"
56 #include "src/execution/isolate-inl.h"
57 #include "src/execution/messages.h"
58 #include "src/execution/microtask-queue.h"
59 #include "src/execution/simulator.h"
60 #include "src/execution/v8threads.h"
61 #include "src/execution/vm-state-inl.h"
62 #include "src/handles/global-handles.h"
63 #include "src/handles/persistent-handles.h"
64 #include "src/heap/embedder-tracing.h"
65 #include "src/heap/heap-inl.h"
66 #include "src/heap/heap-write-barrier.h"
67 #include "src/heap/safepoint.h"
68 #include "src/init/bootstrapper.h"
69 #include "src/init/icu_util.h"
70 #include "src/init/startup-data-util.h"
71 #include "src/init/v8.h"
72 #include "src/json/json-parser.h"
73 #include "src/json/json-stringifier.h"
74 #include "src/logging/counters-scopes.h"
75 #include "src/logging/metrics.h"
76 #include "src/logging/runtime-call-stats-scope.h"
77 #include "src/logging/tracing-flags.h"
78 #include "src/numbers/conversions-inl.h"
79 #include "src/objects/api-callbacks.h"
80 #include "src/objects/contexts.h"
81 #include "src/objects/embedder-data-array-inl.h"
82 #include "src/objects/embedder-data-slot-inl.h"
83 #include "src/objects/hash-table-inl.h"
84 #include "src/objects/heap-object.h"
85 #include "src/objects/js-array-buffer-inl.h"
86 #include "src/objects/js-array-inl.h"
87 #include "src/objects/js-collection-inl.h"
88 #include "src/objects/js-promise-inl.h"
89 #include "src/objects/js-regexp-inl.h"
90 #include "src/objects/js-weak-refs-inl.h"
91 #include "src/objects/module-inl.h"
92 #include "src/objects/objects-inl.h"
93 #include "src/objects/oddball.h"
94 #include "src/objects/ordered-hash-table-inl.h"
95 #include "src/objects/property-descriptor.h"
96 #include "src/objects/property-details.h"
97 #include "src/objects/property.h"
98 #include "src/objects/prototype.h"
99 #include "src/objects/shared-function-info.h"
100 #include "src/objects/slots.h"
101 #include "src/objects/smi.h"
102 #include "src/objects/synthetic-module-inl.h"
103 #include "src/objects/templates.h"
104 #include "src/objects/value-serializer.h"
105 #include "src/parsing/parse-info.h"
106 #include "src/parsing/parser.h"
107 #include "src/parsing/pending-compilation-error-handler.h"
108 #include "src/parsing/scanner-character-streams.h"
109 #include "src/profiler/cpu-profiler.h"
110 #include "src/profiler/heap-profiler.h"
111 #include "src/profiler/heap-snapshot-generator-inl.h"
112 #include "src/profiler/profile-generator-inl.h"
113 #include "src/profiler/tick-sample.h"
114 #include "src/regexp/regexp-utils.h"
115 #include "src/runtime/runtime.h"
116 #include "src/sandbox/external-pointer.h"
117 #include "src/sandbox/sandbox.h"
118 #include "src/snapshot/code-serializer.h"
119 #include "src/snapshot/embedded/embedded-data.h"
120 #include "src/snapshot/snapshot.h"
121 #include "src/snapshot/startup-serializer.h" // For SerializedHandleChecker.
122 #include "src/strings/char-predicates-inl.h"
123 #include "src/strings/string-hasher.h"
124 #include "src/strings/unicode-inl.h"
125 #include "src/tracing/trace-event.h"
126 #include "src/utils/detachable-vector.h"
127 #include "src/utils/version.h"
128 #include "src/web-snapshot/web-snapshot.h"
129
130 #if V8_ENABLE_WEBASSEMBLY
131 #include "src/trap-handler/trap-handler.h"
132 #include "src/wasm/streaming-decoder.h"
133 #include "src/wasm/value-type.h"
134 #include "src/wasm/wasm-engine.h"
135 #include "src/wasm/wasm-js.h"
136 #include "src/wasm/wasm-objects-inl.h"
137 #include "src/wasm/wasm-result.h"
138 #include "src/wasm/wasm-serialization.h"
139 #endif // V8_ENABLE_WEBASSEMBLY
140
141 #if V8_OS_LINUX || V8_OS_DARWIN || V8_OS_FREEBSD
142 #include <signal.h>
143 #include "include/v8-wasm-trap-handler-posix.h"
144 #include "src/trap-handler/handler-inside-posix.h"
145 #endif
146
147 #if V8_OS_WIN
148 #include <windows.h>
149
150 // This has to come after windows.h.
151 #include <versionhelpers.h>
152
153 #include "include/v8-wasm-trap-handler-win.h"
154 #include "src/trap-handler/handler-inside-win.h"
155 #if defined(V8_OS_WIN64)
156 #include "src/base/platform/wrappers.h"
157 #include "src/diagnostics/unwinding-info-win64.h"
158 #endif // V8_OS_WIN64
159 #endif // V8_OS_WIN
160
161 // Has to be the last include (doesn't have include guards):
162 #include "src/api/api-macros.h"
163
164 #define TRACE_BS(...) \
165 do { \
166 if (i::FLAG_trace_backing_store) PrintF(__VA_ARGS__); \
167 } while (false)
168
169 namespace v8 {
170
171 static OOMErrorCallback g_oom_error_callback = nullptr;
172
GetScriptOriginForScript(i::Isolate * isolate,i::Handle<i::Script> script)173 static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate,
174 i::Handle<i::Script> script) {
175 i::Handle<i::Object> scriptName(script->GetNameOrSourceURL(), isolate);
176 i::Handle<i::Object> source_map_url(script->source_mapping_url(), isolate);
177 i::Handle<i::Object> host_defined_options(script->host_defined_options(),
178 isolate);
179 ScriptOriginOptions options(script->origin_options());
180 bool is_wasm = false;
181 #if V8_ENABLE_WEBASSEMBLY
182 is_wasm = script->type() == i::Script::TYPE_WASM;
183 #endif // V8_ENABLE_WEBASSEMBLY
184 v8::ScriptOrigin origin(
185 reinterpret_cast<v8::Isolate*>(isolate), Utils::ToLocal(scriptName),
186 script->line_offset(), script->column_offset(),
187 options.IsSharedCrossOrigin(), script->id(),
188 Utils::ToLocal(source_map_url), options.IsOpaque(), is_wasm,
189 options.IsModule(), Utils::ToLocal(host_defined_options));
190 return origin;
191 }
192
HostDefinedOptions() const193 Local<PrimitiveArray> ScriptOrigin::HostDefinedOptions() const {
194 // TODO(cbruni, chromium:1244145): remove once migrated to the context.
195 Utils::ApiCheck(!host_defined_options_->IsFixedArray(),
196 "ScriptOrigin::HostDefinedOptions",
197 "HostDefinedOptions is not a PrimitiveArray, please use "
198 "ScriptOrigin::GetHostDefinedOptions()");
199 i::Handle<i::FixedArray> options =
200 Utils::OpenHandle(*host_defined_options_.As<FixedArray>());
201 return Utils::PrimitiveArrayToLocal(options);
202 }
203
204 // --- E x c e p t i o n B e h a v i o r ---
205
FatalProcessOutOfMemory(i::Isolate * isolate,const char * location)206 void i::FatalProcessOutOfMemory(i::Isolate* isolate, const char* location) {
207 i::V8::FatalProcessOutOfMemory(isolate, location, false);
208 }
209
210 // When V8 cannot allocate memory FatalProcessOutOfMemory is called. The default
211 // OOM error handler is called and execution is stopped.
FatalProcessOutOfMemory(i::Isolate * isolate,const char * location,bool is_heap_oom)212 void i::V8::FatalProcessOutOfMemory(i::Isolate* isolate, const char* location,
213 bool is_heap_oom) {
214 char last_few_messages[Heap::kTraceRingBufferSize + 1];
215 char js_stacktrace[Heap::kStacktraceBufferSize + 1];
216 i::HeapStats heap_stats;
217
218 if (isolate == nullptr) {
219 isolate = Isolate::TryGetCurrent();
220 }
221
222 if (isolate == nullptr) {
223 // If the Isolate is not available for the current thread we cannot retrieve
224 // memory information from the Isolate. Write easy-to-recognize values on
225 // the stack.
226 memset(last_few_messages, 0x0BADC0DE, Heap::kTraceRingBufferSize + 1);
227 memset(js_stacktrace, 0x0BADC0DE, Heap::kStacktraceBufferSize + 1);
228 memset(&heap_stats, 0xBADC0DE, sizeof(heap_stats));
229 // Give the embedder a chance to handle the condition. If it doesn't,
230 // just crash.
231 if (g_oom_error_callback) g_oom_error_callback(location, is_heap_oom);
232 FATAL("Fatal process out of memory: %s", location);
233 UNREACHABLE();
234 }
235
236 memset(last_few_messages, 0, Heap::kTraceRingBufferSize + 1);
237 memset(js_stacktrace, 0, Heap::kStacktraceBufferSize + 1);
238
239 intptr_t start_marker;
240 heap_stats.start_marker = &start_marker;
241 size_t ro_space_size;
242 heap_stats.ro_space_size = &ro_space_size;
243 size_t ro_space_capacity;
244 heap_stats.ro_space_capacity = &ro_space_capacity;
245 size_t new_space_size;
246 heap_stats.new_space_size = &new_space_size;
247 size_t new_space_capacity;
248 heap_stats.new_space_capacity = &new_space_capacity;
249 size_t old_space_size;
250 heap_stats.old_space_size = &old_space_size;
251 size_t old_space_capacity;
252 heap_stats.old_space_capacity = &old_space_capacity;
253 size_t code_space_size;
254 heap_stats.code_space_size = &code_space_size;
255 size_t code_space_capacity;
256 heap_stats.code_space_capacity = &code_space_capacity;
257 size_t map_space_size;
258 heap_stats.map_space_size = &map_space_size;
259 size_t map_space_capacity;
260 heap_stats.map_space_capacity = &map_space_capacity;
261 size_t lo_space_size;
262 heap_stats.lo_space_size = &lo_space_size;
263 size_t code_lo_space_size;
264 heap_stats.code_lo_space_size = &code_lo_space_size;
265 size_t global_handle_count;
266 heap_stats.global_handle_count = &global_handle_count;
267 size_t weak_global_handle_count;
268 heap_stats.weak_global_handle_count = &weak_global_handle_count;
269 size_t pending_global_handle_count;
270 heap_stats.pending_global_handle_count = &pending_global_handle_count;
271 size_t near_death_global_handle_count;
272 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
273 size_t free_global_handle_count;
274 heap_stats.free_global_handle_count = &free_global_handle_count;
275 size_t memory_allocator_size;
276 heap_stats.memory_allocator_size = &memory_allocator_size;
277 size_t memory_allocator_capacity;
278 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
279 size_t malloced_memory;
280 heap_stats.malloced_memory = &malloced_memory;
281 size_t malloced_peak_memory;
282 heap_stats.malloced_peak_memory = &malloced_peak_memory;
283 size_t objects_per_type[LAST_TYPE + 1] = {0};
284 heap_stats.objects_per_type = objects_per_type;
285 size_t size_per_type[LAST_TYPE + 1] = {0};
286 heap_stats.size_per_type = size_per_type;
287 int os_error;
288 heap_stats.os_error = &os_error;
289 heap_stats.last_few_messages = last_few_messages;
290 heap_stats.js_stacktrace = js_stacktrace;
291 intptr_t end_marker;
292 heap_stats.end_marker = &end_marker;
293 if (isolate->heap()->HasBeenSetUp()) {
294 // BUG(1718): Don't use the take_snapshot since we don't support
295 // HeapObjectIterator here without doing a special GC.
296 isolate->heap()->RecordStats(&heap_stats, false);
297 if (!FLAG_correctness_fuzzer_suppressions) {
298 char* first_newline = strchr(last_few_messages, '\n');
299 if (first_newline == nullptr || first_newline[1] == '\0')
300 first_newline = last_few_messages;
301 base::OS::PrintError("\n<--- Last few GCs --->\n%s\n", first_newline);
302 base::OS::PrintError("\n<--- JS stacktrace --->\n%s\n", js_stacktrace);
303 }
304 }
305 Utils::ReportOOMFailure(isolate, location, is_heap_oom);
306 if (g_oom_error_callback) g_oom_error_callback(location, is_heap_oom);
307 // If the fatal error handler returns, we stop execution.
308 FATAL("API fatal error handler returned after process out of memory");
309 }
310
ReportApiFailure(const char * location,const char * message)311 void Utils::ReportApiFailure(const char* location, const char* message) {
312 i::Isolate* isolate = i::Isolate::TryGetCurrent();
313 FatalErrorCallback callback = nullptr;
314 if (isolate != nullptr) {
315 callback = isolate->exception_behavior();
316 }
317 if (callback == nullptr) {
318 base::OS::PrintError("\n#\n# Fatal error in %s\n# %s\n#\n\n", location,
319 message);
320 base::OS::Abort();
321 } else {
322 callback(location, message);
323 }
324 isolate->SignalFatalError();
325 }
326
ReportOOMFailure(i::Isolate * isolate,const char * location,bool is_heap_oom)327 void Utils::ReportOOMFailure(i::Isolate* isolate, const char* location,
328 bool is_heap_oom) {
329 OOMErrorCallback oom_callback = isolate->oom_behavior();
330 if (oom_callback == nullptr) {
331 // TODO(wfh): Remove this fallback once Blink is setting OOM handler. See
332 // crbug.com/614440.
333 FatalErrorCallback fatal_callback = isolate->exception_behavior();
334 if (fatal_callback == nullptr) {
335 base::OS::PrintError("\n#\n# Fatal %s OOM in %s\n#\n\n",
336 is_heap_oom ? "javascript" : "process", location);
337 #ifdef V8_FUZZILLI
338 exit(0);
339 #else
340 base::OS::Abort();
341 #endif // V8_FUZZILLI
342 } else {
343 fatal_callback(location,
344 is_heap_oom
345 ? "Allocation failed - JavaScript heap out of memory"
346 : "Allocation failed - process out of memory");
347 }
348 } else {
349 oom_callback(location, is_heap_oom);
350 }
351 isolate->SignalFatalError();
352 }
353
SetSnapshotDataBlob(StartupData * snapshot_blob)354 void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
355 i::V8::SetSnapshotBlob(snapshot_blob);
356 }
357
358 namespace {
359
360 #ifdef V8_SANDBOXED_POINTERS
361 // ArrayBufferAllocator to use when sandboxed pointers are used in which case
362 // all ArrayBuffer backing stores need to be allocated inside the sandbox.
363 // Note, the current implementation is extremely inefficient as it uses the
364 // BoundedPageAllocator. In the future, we'll need a proper allocator
365 // implementation.
366 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
367 public:
ArrayBufferAllocator()368 ArrayBufferAllocator() { CHECK(page_allocator_); }
369
Allocate(size_t length)370 void* Allocate(size_t length) override {
371 return page_allocator_->AllocatePages(nullptr, RoundUp(length, page_size_),
372 page_size_,
373 PageAllocator::kReadWrite);
374 }
375
AllocateUninitialized(size_t length)376 void* AllocateUninitialized(size_t length) override {
377 return Allocate(length);
378 }
379
Free(void * data,size_t length)380 void Free(void* data, size_t length) override {
381 page_allocator_->FreePages(data, RoundUp(length, page_size_));
382 }
383
384 private:
385 PageAllocator* page_allocator_ = internal::GetArrayBufferPageAllocator();
386 const size_t page_size_ = page_allocator_->AllocatePageSize();
387 };
388
389 #else
390
391 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
392 public:
393 void* Allocate(size_t length) override {
394 #if V8_OS_AIX && _LINUX_SOURCE_COMPAT
395 // Work around for GCC bug on AIX
396 // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
397 void* data = __linux_calloc(length, 1);
398 #else
399 void* data = base::Calloc(length, 1);
400 #endif
401 return data;
402 }
403
404 void* AllocateUninitialized(size_t length) override {
405 #if V8_OS_AIX && _LINUX_SOURCE_COMPAT
406 // Work around for GCC bug on AIX
407 // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
408 void* data = __linux_malloc(length);
409 #else
410 void* data = base::Malloc(length);
411 #endif
412 return data;
413 }
414
415 void Free(void* data, size_t) override { base::Free(data); }
416
417 void* Reallocate(void* data, size_t old_length, size_t new_length) override {
418 #if V8_OS_AIX && _LINUX_SOURCE_COMPAT
419 // Work around for GCC bug on AIX
420 // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
421 void* new_data = __linux_realloc(data, new_length);
422 #else
423 void* new_data = base::Realloc(data, new_length);
424 #endif
425 if (new_length > old_length) {
426 memset(reinterpret_cast<uint8_t*>(new_data) + old_length, 0,
427 new_length - old_length);
428 }
429 return new_data;
430 }
431 };
432 #endif // V8_SANDBOXED_POINTERS
433
434 struct SnapshotCreatorData {
SnapshotCreatorDatav8::__anon48d2745d0111::SnapshotCreatorData435 explicit SnapshotCreatorData(Isolate* isolate)
436 : isolate_(isolate),
437 default_context_(),
438 contexts_(isolate),
439 created_(false) {}
440
castv8::__anon48d2745d0111::SnapshotCreatorData441 static SnapshotCreatorData* cast(void* data) {
442 return reinterpret_cast<SnapshotCreatorData*>(data);
443 }
444
445 ArrayBufferAllocator allocator_;
446 Isolate* isolate_;
447 Persistent<Context> default_context_;
448 SerializeInternalFieldsCallback default_embedder_fields_serializer_;
449 PersistentValueVector<Context> contexts_;
450 std::vector<SerializeInternalFieldsCallback> embedder_fields_serializers_;
451 bool created_;
452 };
453
454 } // namespace
455
SnapshotCreator(Isolate * isolate,const intptr_t * external_references,StartupData * existing_snapshot)456 SnapshotCreator::SnapshotCreator(Isolate* isolate,
457 const intptr_t* external_references,
458 StartupData* existing_snapshot) {
459 SnapshotCreatorData* data = new SnapshotCreatorData(isolate);
460 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
461 internal_isolate->set_array_buffer_allocator(&data->allocator_);
462 internal_isolate->set_api_external_references(external_references);
463 internal_isolate->enable_serializer();
464 isolate->Enter();
465 const StartupData* blob = existing_snapshot
466 ? existing_snapshot
467 : i::Snapshot::DefaultSnapshotBlob();
468 if (blob && blob->raw_size > 0) {
469 internal_isolate->set_snapshot_blob(blob);
470 i::Snapshot::Initialize(internal_isolate);
471 } else {
472 internal_isolate->InitWithoutSnapshot();
473 }
474 data_ = data;
475 // Disable batch compilation during snapshot creation.
476 internal_isolate->baseline_batch_compiler()->set_enabled(false);
477 }
478
SnapshotCreator(const intptr_t * external_references,StartupData * existing_snapshot)479 SnapshotCreator::SnapshotCreator(const intptr_t* external_references,
480 StartupData* existing_snapshot)
481 : SnapshotCreator(Isolate::Allocate(), external_references,
482 existing_snapshot) {}
483
~SnapshotCreator()484 SnapshotCreator::~SnapshotCreator() {
485 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
486 Isolate* isolate = data->isolate_;
487 isolate->Exit();
488 isolate->Dispose();
489 delete data;
490 }
491
GetIsolate()492 Isolate* SnapshotCreator::GetIsolate() {
493 return SnapshotCreatorData::cast(data_)->isolate_;
494 }
495
SetDefaultContext(Local<Context> context,SerializeInternalFieldsCallback callback)496 void SnapshotCreator::SetDefaultContext(
497 Local<Context> context, SerializeInternalFieldsCallback callback) {
498 DCHECK(!context.IsEmpty());
499 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
500 DCHECK(!data->created_);
501 DCHECK(data->default_context_.IsEmpty());
502 Isolate* isolate = data->isolate_;
503 CHECK_EQ(isolate, context->GetIsolate());
504 data->default_context_.Reset(isolate, context);
505 data->default_embedder_fields_serializer_ = callback;
506 }
507
AddContext(Local<Context> context,SerializeInternalFieldsCallback callback)508 size_t SnapshotCreator::AddContext(Local<Context> context,
509 SerializeInternalFieldsCallback callback) {
510 DCHECK(!context.IsEmpty());
511 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
512 DCHECK(!data->created_);
513 Isolate* isolate = data->isolate_;
514 CHECK_EQ(isolate, context->GetIsolate());
515 size_t index = data->contexts_.Size();
516 data->contexts_.Append(context);
517 data->embedder_fields_serializers_.push_back(callback);
518 return index;
519 }
520
AddData(i::Address object)521 size_t SnapshotCreator::AddData(i::Address object) {
522 DCHECK_NE(object, i::kNullAddress);
523 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
524 DCHECK(!data->created_);
525 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_);
526 i::HandleScope scope(isolate);
527 i::Handle<i::Object> obj(i::Object(object), isolate);
528 i::Handle<i::ArrayList> list;
529 if (!isolate->heap()->serialized_objects().IsArrayList()) {
530 list = i::ArrayList::New(isolate, 1);
531 } else {
532 list = i::Handle<i::ArrayList>(
533 i::ArrayList::cast(isolate->heap()->serialized_objects()), isolate);
534 }
535 size_t index = static_cast<size_t>(list->Length());
536 list = i::ArrayList::Add(isolate, list, obj);
537 isolate->heap()->SetSerializedObjects(*list);
538 return index;
539 }
540
AddData(Local<Context> context,i::Address object)541 size_t SnapshotCreator::AddData(Local<Context> context, i::Address object) {
542 DCHECK_NE(object, i::kNullAddress);
543 DCHECK(!SnapshotCreatorData::cast(data_)->created_);
544 i::Handle<i::Context> ctx = Utils::OpenHandle(*context);
545 i::Isolate* isolate = ctx->GetIsolate();
546 i::HandleScope scope(isolate);
547 i::Handle<i::Object> obj(i::Object(object), isolate);
548 i::Handle<i::ArrayList> list;
549 if (!ctx->serialized_objects().IsArrayList()) {
550 list = i::ArrayList::New(isolate, 1);
551 } else {
552 list = i::Handle<i::ArrayList>(
553 i::ArrayList::cast(ctx->serialized_objects()), isolate);
554 }
555 size_t index = static_cast<size_t>(list->Length());
556 list = i::ArrayList::Add(isolate, list, obj);
557 ctx->set_serialized_objects(*list);
558 return index;
559 }
560
561 namespace {
ConvertSerializedObjectsToFixedArray(Local<Context> context)562 void ConvertSerializedObjectsToFixedArray(Local<Context> context) {
563 i::Handle<i::Context> ctx = Utils::OpenHandle(*context);
564 i::Isolate* isolate = ctx->GetIsolate();
565 if (!ctx->serialized_objects().IsArrayList()) {
566 ctx->set_serialized_objects(i::ReadOnlyRoots(isolate).empty_fixed_array());
567 } else {
568 i::Handle<i::ArrayList> list(i::ArrayList::cast(ctx->serialized_objects()),
569 isolate);
570 i::Handle<i::FixedArray> elements = i::ArrayList::Elements(isolate, list);
571 ctx->set_serialized_objects(*elements);
572 }
573 }
574
ConvertSerializedObjectsToFixedArray(i::Isolate * isolate)575 void ConvertSerializedObjectsToFixedArray(i::Isolate* isolate) {
576 if (!isolate->heap()->serialized_objects().IsArrayList()) {
577 isolate->heap()->SetSerializedObjects(
578 i::ReadOnlyRoots(isolate).empty_fixed_array());
579 } else {
580 i::Handle<i::ArrayList> list(
581 i::ArrayList::cast(isolate->heap()->serialized_objects()), isolate);
582 i::Handle<i::FixedArray> elements = i::ArrayList::Elements(isolate, list);
583 isolate->heap()->SetSerializedObjects(*elements);
584 }
585 }
586 } // anonymous namespace
587
CreateBlob(SnapshotCreator::FunctionCodeHandling function_code_handling)588 StartupData SnapshotCreator::CreateBlob(
589 SnapshotCreator::FunctionCodeHandling function_code_handling) {
590 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
591 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_);
592 Utils::ApiCheck(!data->created_, "v8::SnapshotCreator::CreateBlob",
593 "CreateBlob() cannot be called more than once on the same "
594 "SnapshotCreator.");
595 Utils::ApiCheck(
596 !data->default_context_.IsEmpty(), "v8::SnapshotCreator::CreateBlob",
597 "CreateBlob() cannot be called before the default context is set.");
598
599 const int num_additional_contexts = static_cast<int>(data->contexts_.Size());
600 const int num_contexts = num_additional_contexts + 1; // The default context.
601
602 // Create and store lists of embedder-provided data needed during
603 // serialization.
604 {
605 i::HandleScope scope(isolate);
606 // Convert list of context-independent data to FixedArray.
607 ConvertSerializedObjectsToFixedArray(isolate);
608
609 // Convert lists of context-dependent data to FixedArray.
610 ConvertSerializedObjectsToFixedArray(
611 data->default_context_.Get(data->isolate_));
612 for (int i = 0; i < num_additional_contexts; i++) {
613 ConvertSerializedObjectsToFixedArray(data->contexts_.Get(i));
614 }
615
616 // We need to store the global proxy size upfront in case we need the
617 // bootstrapper to create a global proxy before we deserialize the context.
618 i::Handle<i::FixedArray> global_proxy_sizes =
619 isolate->factory()->NewFixedArray(num_additional_contexts,
620 i::AllocationType::kOld);
621 for (int i = 0; i < num_additional_contexts; i++) {
622 i::Handle<i::Context> context =
623 v8::Utils::OpenHandle(*data->contexts_.Get(i));
624 global_proxy_sizes->set(i,
625 i::Smi::FromInt(context->global_proxy().Size()));
626 }
627 isolate->heap()->SetSerializedGlobalProxySizes(*global_proxy_sizes);
628 }
629
630 // We might rehash strings and re-sort descriptors. Clear the lookup cache.
631 isolate->descriptor_lookup_cache()->Clear();
632
633 // If we don't do this then we end up with a stray root pointing at the
634 // context even after we have disposed of the context.
635 isolate->heap()->CollectAllAvailableGarbage(
636 i::GarbageCollectionReason::kSnapshotCreator);
637 {
638 i::HandleScope scope(isolate);
639 isolate->heap()->CompactWeakArrayLists();
640 }
641
642 i::Snapshot::ClearReconstructableDataForSerialization(
643 isolate, function_code_handling == FunctionCodeHandling::kClear);
644
645 i::GlobalSafepointScope global_safepoint(isolate);
646 i::DisallowGarbageCollection no_gc_from_here_on;
647
648 // Create a vector with all contexts and clear associated Persistent fields.
649 // Note these contexts may be dead after calling Clear(), but will not be
650 // collected until serialization completes and the DisallowGarbageCollection
651 // scope above goes out of scope.
652 std::vector<i::Context> contexts;
653 contexts.reserve(num_contexts);
654 {
655 i::HandleScope scope(isolate);
656 contexts.push_back(
657 *v8::Utils::OpenHandle(*data->default_context_.Get(data->isolate_)));
658 data->default_context_.Reset();
659 for (int i = 0; i < num_additional_contexts; i++) {
660 i::Handle<i::Context> context =
661 v8::Utils::OpenHandle(*data->contexts_.Get(i));
662 contexts.push_back(*context);
663 }
664 data->contexts_.Clear();
665 }
666
667 // Check that values referenced by global/eternal handles are accounted for.
668 i::SerializedHandleChecker handle_checker(isolate, &contexts);
669 CHECK(handle_checker.CheckGlobalAndEternalHandles());
670
671 // Create a vector with all embedder fields serializers.
672 std::vector<SerializeInternalFieldsCallback> embedder_fields_serializers;
673 embedder_fields_serializers.reserve(num_contexts);
674 embedder_fields_serializers.push_back(
675 data->default_embedder_fields_serializer_);
676 for (int i = 0; i < num_additional_contexts; i++) {
677 embedder_fields_serializers.push_back(
678 data->embedder_fields_serializers_[i]);
679 }
680
681 data->created_ = true;
682 return i::Snapshot::Create(isolate, &contexts, embedder_fields_serializers,
683 global_safepoint, no_gc_from_here_on);
684 }
685
CanBeRehashed() const686 bool StartupData::CanBeRehashed() const {
687 DCHECK(i::Snapshot::VerifyChecksum(this));
688 return i::Snapshot::ExtractRehashability(this);
689 }
690
IsValid() const691 bool StartupData::IsValid() const { return i::Snapshot::VersionIsValid(this); }
692
SetDcheckErrorHandler(DcheckErrorCallback that)693 void V8::SetDcheckErrorHandler(DcheckErrorCallback that) {
694 v8::base::SetDcheckFunction(that);
695 }
696
SetFlagsFromString(const char * str)697 void V8::SetFlagsFromString(const char* str) {
698 SetFlagsFromString(str, strlen(str));
699 }
700
SetFlagsFromString(const char * str,size_t length)701 void V8::SetFlagsFromString(const char* str, size_t length) {
702 i::FlagList::SetFlagsFromString(str, length);
703 i::FlagList::EnforceFlagImplications();
704 }
705
SetFlagsFromCommandLine(int * argc,char ** argv,bool remove_flags)706 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
707 using HelpOptions = i::FlagList::HelpOptions;
708 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags,
709 HelpOptions(HelpOptions::kDontExit));
710 }
711
712 RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
713
RegisteredExtension(std::unique_ptr<Extension> extension)714 RegisteredExtension::RegisteredExtension(std::unique_ptr<Extension> extension)
715 : extension_(std::move(extension)) {}
716
717 // static
Register(std::unique_ptr<Extension> extension)718 void RegisteredExtension::Register(std::unique_ptr<Extension> extension) {
719 RegisteredExtension* new_extension =
720 new RegisteredExtension(std::move(extension));
721 new_extension->next_ = first_extension_;
722 first_extension_ = new_extension;
723 }
724
725 // static
UnregisterAll()726 void RegisteredExtension::UnregisterAll() {
727 RegisteredExtension* re = first_extension_;
728 while (re != nullptr) {
729 RegisteredExtension* next = re->next();
730 delete re;
731 re = next;
732 }
733 first_extension_ = nullptr;
734 }
735
736 namespace {
737 class ExtensionResource : public String::ExternalOneByteStringResource {
738 public:
ExtensionResource()739 ExtensionResource() : data_(nullptr), length_(0) {}
ExtensionResource(const char * data,size_t length)740 ExtensionResource(const char* data, size_t length)
741 : data_(data), length_(length) {}
data() const742 const char* data() const override { return data_; }
length() const743 size_t length() const override { return length_; }
Dispose()744 void Dispose() override {}
745
746 private:
747 const char* data_;
748 size_t length_;
749 };
750 } // anonymous namespace
751
RegisterExtension(std::unique_ptr<Extension> extension)752 void RegisterExtension(std::unique_ptr<Extension> extension) {
753 RegisteredExtension::Register(std::move(extension));
754 }
755
Extension(const char * name,const char * source,int dep_count,const char ** deps,int source_length)756 Extension::Extension(const char* name, const char* source, int dep_count,
757 const char** deps, int source_length)
758 : name_(name),
759 source_length_(source_length >= 0
760 ? source_length
761 : (source ? static_cast<int>(strlen(source)) : 0)),
762 dep_count_(dep_count),
763 deps_(deps),
764 auto_enable_(false) {
765 source_ = new ExtensionResource(source, source_length_);
766 CHECK(source != nullptr || source_length_ == 0);
767 }
768
ConfigureDefaultsFromHeapSize(size_t initial_heap_size_in_bytes,size_t maximum_heap_size_in_bytes)769 void ResourceConstraints::ConfigureDefaultsFromHeapSize(
770 size_t initial_heap_size_in_bytes, size_t maximum_heap_size_in_bytes) {
771 CHECK_LE(initial_heap_size_in_bytes, maximum_heap_size_in_bytes);
772 if (maximum_heap_size_in_bytes == 0) {
773 return;
774 }
775 size_t young_generation, old_generation;
776 i::Heap::GenerationSizesFromHeapSize(maximum_heap_size_in_bytes,
777 &young_generation, &old_generation);
778 set_max_young_generation_size_in_bytes(
779 std::max(young_generation, i::Heap::MinYoungGenerationSize()));
780 set_max_old_generation_size_in_bytes(
781 std::max(old_generation, i::Heap::MinOldGenerationSize()));
782 if (initial_heap_size_in_bytes > 0) {
783 i::Heap::GenerationSizesFromHeapSize(initial_heap_size_in_bytes,
784 &young_generation, &old_generation);
785 // We do not set lower bounds for the initial sizes.
786 set_initial_young_generation_size_in_bytes(young_generation);
787 set_initial_old_generation_size_in_bytes(old_generation);
788 }
789 if (i::kPlatformRequiresCodeRange) {
790 set_code_range_size_in_bytes(
791 std::min(i::kMaximalCodeRangeSize, maximum_heap_size_in_bytes));
792 }
793 }
794
ConfigureDefaults(uint64_t physical_memory,uint64_t virtual_memory_limit)795 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
796 uint64_t virtual_memory_limit) {
797 size_t heap_size = i::Heap::HeapSizeFromPhysicalMemory(physical_memory);
798 size_t young_generation, old_generation;
799 i::Heap::GenerationSizesFromHeapSize(heap_size, &young_generation,
800 &old_generation);
801 set_max_young_generation_size_in_bytes(young_generation);
802 set_max_old_generation_size_in_bytes(old_generation);
803
804 if (virtual_memory_limit > 0 && i::kPlatformRequiresCodeRange) {
805 set_code_range_size_in_bytes(
806 std::min(i::kMaximalCodeRangeSize,
807 static_cast<size_t>(virtual_memory_limit / 8)));
808 }
809 }
810
811 namespace internal {
812
GlobalizeTracedReference(i::Isolate * isolate,i::Address * obj,internal::Address * slot,GlobalHandleStoreMode store_mode)813 i::Address* GlobalizeTracedReference(i::Isolate* isolate, i::Address* obj,
814 internal::Address* slot,
815 GlobalHandleStoreMode store_mode) {
816 API_RCS_SCOPE(isolate, TracedGlobal, New);
817 #ifdef DEBUG
818 Utils::ApiCheck((slot != nullptr), "v8::GlobalizeTracedReference",
819 "the address slot must be not null");
820 #endif
821 i::Handle<i::Object> result =
822 isolate->global_handles()->CreateTraced(*obj, slot, store_mode);
823 #ifdef VERIFY_HEAP
824 if (i::FLAG_verify_heap) {
825 i::Object(*obj).ObjectVerify(isolate);
826 }
827 #endif // VERIFY_HEAP
828 return result.location();
829 }
830
MoveTracedReference(internal::Address ** from,internal::Address ** to)831 void MoveTracedReference(internal::Address** from, internal::Address** to) {
832 GlobalHandles::MoveTracedReference(from, to);
833 }
834
CopyTracedReference(const internal::Address * const * from,internal::Address ** to)835 void CopyTracedReference(const internal::Address* const* from,
836 internal::Address** to) {
837 GlobalHandles::CopyTracedReference(from, to);
838 }
839
DisposeTracedReference(internal::Address * location)840 void DisposeTracedReference(internal::Address* location) {
841 GlobalHandles::DestroyTracedReference(location);
842 }
843
844 } // namespace internal
845
846 namespace api_internal {
847
GlobalizeReference(i::Isolate * isolate,i::Address * obj)848 i::Address* GlobalizeReference(i::Isolate* isolate, i::Address* obj) {
849 API_RCS_SCOPE(isolate, Persistent, New);
850 i::Handle<i::Object> result = isolate->global_handles()->Create(*obj);
851 #ifdef VERIFY_HEAP
852 if (i::FLAG_verify_heap) {
853 i::Object(*obj).ObjectVerify(isolate);
854 }
855 #endif // VERIFY_HEAP
856 return result.location();
857 }
858
CopyGlobalReference(i::Address * from)859 i::Address* CopyGlobalReference(i::Address* from) {
860 i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(from);
861 return result.location();
862 }
863
MoveGlobalReference(internal::Address ** from,internal::Address ** to)864 void MoveGlobalReference(internal::Address** from, internal::Address** to) {
865 i::GlobalHandles::MoveGlobal(from, to);
866 }
867
MakeWeak(i::Address * location,void * parameter,WeakCallbackInfo<void>::Callback weak_callback,WeakCallbackType type)868 void MakeWeak(i::Address* location, void* parameter,
869 WeakCallbackInfo<void>::Callback weak_callback,
870 WeakCallbackType type) {
871 i::GlobalHandles::MakeWeak(location, parameter, weak_callback, type);
872 }
873
MakeWeak(i::Address ** location_addr)874 void MakeWeak(i::Address** location_addr) {
875 i::GlobalHandles::MakeWeak(location_addr);
876 }
877
ClearWeak(i::Address * location)878 void* ClearWeak(i::Address* location) {
879 return i::GlobalHandles::ClearWeakness(location);
880 }
881
AnnotateStrongRetainer(i::Address * location,const char * label)882 void AnnotateStrongRetainer(i::Address* location, const char* label) {
883 i::GlobalHandles::AnnotateStrongRetainer(location, label);
884 }
885
DisposeGlobal(i::Address * location)886 void DisposeGlobal(i::Address* location) {
887 i::GlobalHandles::Destroy(location);
888 }
889
Eternalize(Isolate * v8_isolate,Value * value)890 Value* Eternalize(Isolate* v8_isolate, Value* value) {
891 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
892 i::Object object = *Utils::OpenHandle(value);
893 int index = -1;
894 isolate->eternal_handles()->Create(isolate, object, &index);
895 return reinterpret_cast<Value*>(
896 isolate->eternal_handles()->Get(index).location());
897 }
898
FromJustIsNothing()899 void FromJustIsNothing() {
900 Utils::ApiCheck(false, "v8::FromJust", "Maybe value is Nothing.");
901 }
902
ToLocalEmpty()903 void ToLocalEmpty() {
904 Utils::ApiCheck(false, "v8::ToLocalChecked", "Empty MaybeLocal.");
905 }
906
InternalFieldOutOfBounds(int index)907 void InternalFieldOutOfBounds(int index) {
908 Utils::ApiCheck(0 <= index && index < kInternalFieldsInWeakCallback,
909 "WeakCallbackInfo::GetInternalField",
910 "Internal field out of bounds.");
911 }
912
913 } // namespace api_internal
914
915 // --- H a n d l e s ---
916
HandleScope(Isolate * isolate)917 HandleScope::HandleScope(Isolate* isolate) { Initialize(isolate); }
918
Initialize(Isolate * isolate)919 void HandleScope::Initialize(Isolate* isolate) {
920 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
921 // We do not want to check the correct usage of the Locker class all over the
922 // place, so we do it only here: Without a HandleScope, an embedder can do
923 // almost nothing, so it is enough to check in this central place.
924 // We make an exception if the serializer is enabled, which means that the
925 // Isolate is exclusively used to create a snapshot.
926 Utils::ApiCheck(
927 !internal_isolate->was_locker_ever_used() ||
928 internal_isolate->thread_manager()->IsLockedByCurrentThread() ||
929 internal_isolate->serializer_enabled(),
930 "HandleScope::HandleScope",
931 "Entering the V8 API without proper locking in place");
932 i::HandleScopeData* current = internal_isolate->handle_scope_data();
933 isolate_ = internal_isolate;
934 prev_next_ = current->next;
935 prev_limit_ = current->limit;
936 current->level++;
937 }
938
~HandleScope()939 HandleScope::~HandleScope() {
940 i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_);
941 }
942
operator new(size_t)943 void* HandleScope::operator new(size_t) { base::OS::Abort(); }
operator new[](size_t)944 void* HandleScope::operator new[](size_t) { base::OS::Abort(); }
operator delete(void *,size_t)945 void HandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
operator delete[](void *,size_t)946 void HandleScope::operator delete[](void*, size_t) { base::OS::Abort(); }
947
NumberOfHandles(Isolate * isolate)948 int HandleScope::NumberOfHandles(Isolate* isolate) {
949 return i::HandleScope::NumberOfHandles(
950 reinterpret_cast<i::Isolate*>(isolate));
951 }
952
CreateHandle(i::Isolate * isolate,i::Address value)953 i::Address* HandleScope::CreateHandle(i::Isolate* isolate, i::Address value) {
954 return i::HandleScope::CreateHandle(isolate, value);
955 }
956
EscapableHandleScope(Isolate * v8_isolate)957 EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) {
958 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
959 escape_slot_ =
960 CreateHandle(isolate, i::ReadOnlyRoots(isolate).the_hole_value().ptr());
961 Initialize(v8_isolate);
962 }
963
Escape(i::Address * escape_value)964 i::Address* EscapableHandleScope::Escape(i::Address* escape_value) {
965 i::Heap* heap = reinterpret_cast<i::Isolate*>(GetIsolate())->heap();
966 Utils::ApiCheck(i::Object(*escape_slot_).IsTheHole(heap->isolate()),
967 "EscapableHandleScope::Escape", "Escape value set twice");
968 if (escape_value == nullptr) {
969 *escape_slot_ = i::ReadOnlyRoots(heap).undefined_value().ptr();
970 return nullptr;
971 }
972 *escape_slot_ = *escape_value;
973 return escape_slot_;
974 }
975
operator new(size_t)976 void* EscapableHandleScope::operator new(size_t) { base::OS::Abort(); }
operator new[](size_t)977 void* EscapableHandleScope::operator new[](size_t) { base::OS::Abort(); }
operator delete(void *,size_t)978 void EscapableHandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
operator delete[](void *,size_t)979 void EscapableHandleScope::operator delete[](void*, size_t) {
980 base::OS::Abort();
981 }
982
SealHandleScope(Isolate * isolate)983 SealHandleScope::SealHandleScope(Isolate* isolate)
984 : isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
985 i::HandleScopeData* current = isolate_->handle_scope_data();
986 prev_limit_ = current->limit;
987 current->limit = current->next;
988 prev_sealed_level_ = current->sealed_level;
989 current->sealed_level = current->level;
990 }
991
~SealHandleScope()992 SealHandleScope::~SealHandleScope() {
993 i::HandleScopeData* current = isolate_->handle_scope_data();
994 DCHECK_EQ(current->next, current->limit);
995 current->limit = prev_limit_;
996 DCHECK_EQ(current->level, current->sealed_level);
997 current->sealed_level = prev_sealed_level_;
998 }
999
operator new(size_t)1000 void* SealHandleScope::operator new(size_t) { base::OS::Abort(); }
operator new[](size_t)1001 void* SealHandleScope::operator new[](size_t) { base::OS::Abort(); }
operator delete(void *,size_t)1002 void SealHandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
operator delete[](void *,size_t)1003 void SealHandleScope::operator delete[](void*, size_t) { base::OS::Abort(); }
1004
IsModule() const1005 bool Data::IsModule() const { return Utils::OpenHandle(this)->IsModule(); }
IsFixedArray() const1006 bool Data::IsFixedArray() const {
1007 return Utils::OpenHandle(this)->IsFixedArray();
1008 }
1009
IsValue() const1010 bool Data::IsValue() const {
1011 i::DisallowGarbageCollection no_gc;
1012 i::Object self = *Utils::OpenHandle(this);
1013 if (self.IsSmi()) return true;
1014 i::HeapObject heap_object = i::HeapObject::cast(self);
1015 DCHECK(!heap_object.IsTheHole());
1016 if (heap_object.IsSymbol()) {
1017 return !i::Symbol::cast(heap_object).is_private();
1018 }
1019 return heap_object.IsPrimitiveHeapObject() || heap_object.IsJSReceiver();
1020 }
1021
IsPrivate() const1022 bool Data::IsPrivate() const {
1023 return Utils::OpenHandle(this)->IsPrivateSymbol();
1024 }
1025
IsObjectTemplate() const1026 bool Data::IsObjectTemplate() const {
1027 return Utils::OpenHandle(this)->IsObjectTemplateInfo();
1028 }
1029
IsFunctionTemplate() const1030 bool Data::IsFunctionTemplate() const {
1031 return Utils::OpenHandle(this)->IsFunctionTemplateInfo();
1032 }
1033
IsContext() const1034 bool Data::IsContext() const { return Utils::OpenHandle(this)->IsContext(); }
1035
Enter()1036 void Context::Enter() {
1037 i::Handle<i::Context> env = Utils::OpenHandle(this);
1038 i::Isolate* isolate = env->GetIsolate();
1039 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1040 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
1041 impl->EnterContext(*env);
1042 impl->SaveContext(isolate->context());
1043 isolate->set_context(*env);
1044 }
1045
Exit()1046 void Context::Exit() {
1047 i::Handle<i::Context> env = Utils::OpenHandle(this);
1048 i::Isolate* isolate = env->GetIsolate();
1049 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1050 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
1051 if (!Utils::ApiCheck(impl->LastEnteredContextWas(*env), "v8::Context::Exit()",
1052 "Cannot exit non-entered context")) {
1053 return;
1054 }
1055 impl->LeaveContext();
1056 isolate->set_context(impl->RestoreContext());
1057 }
1058
BackupIncumbentScope(Local<Context> backup_incumbent_context)1059 Context::BackupIncumbentScope::BackupIncumbentScope(
1060 Local<Context> backup_incumbent_context)
1061 : backup_incumbent_context_(backup_incumbent_context) {
1062 DCHECK(!backup_incumbent_context_.IsEmpty());
1063
1064 i::Handle<i::Context> env = Utils::OpenHandle(*backup_incumbent_context_);
1065 i::Isolate* isolate = env->GetIsolate();
1066
1067 js_stack_comparable_address_ =
1068 i::SimulatorStack::RegisterJSStackComparableAddress(isolate);
1069
1070 prev_ = isolate->top_backup_incumbent_scope();
1071 isolate->set_top_backup_incumbent_scope(this);
1072 }
1073
~BackupIncumbentScope()1074 Context::BackupIncumbentScope::~BackupIncumbentScope() {
1075 i::Handle<i::Context> env = Utils::OpenHandle(*backup_incumbent_context_);
1076 i::Isolate* isolate = env->GetIsolate();
1077
1078 i::SimulatorStack::UnregisterJSStackComparableAddress(isolate);
1079
1080 isolate->set_top_backup_incumbent_scope(prev_);
1081 }
1082
1083 STATIC_ASSERT(i::Internals::kEmbedderDataSlotSize == i::kEmbedderDataSlotSize);
1084
EmbedderDataFor(Context * context,int index,bool can_grow,const char * location)1085 static i::Handle<i::EmbedderDataArray> EmbedderDataFor(Context* context,
1086 int index, bool can_grow,
1087 const char* location) {
1088 i::Handle<i::Context> env = Utils::OpenHandle(context);
1089 i::Isolate* isolate = env->GetIsolate();
1090 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
1091 bool ok = Utils::ApiCheck(env->IsNativeContext(), location,
1092 "Not a native context") &&
1093 Utils::ApiCheck(index >= 0, location, "Negative index");
1094 if (!ok) return i::Handle<i::EmbedderDataArray>();
1095 // TODO(ishell): remove cast once embedder_data slot has a proper type.
1096 i::Handle<i::EmbedderDataArray> data(
1097 i::EmbedderDataArray::cast(env->embedder_data()), isolate);
1098 if (index < data->length()) return data;
1099 if (!Utils::ApiCheck(can_grow && index < i::EmbedderDataArray::kMaxLength,
1100 location, "Index too large")) {
1101 return i::Handle<i::EmbedderDataArray>();
1102 }
1103 data = i::EmbedderDataArray::EnsureCapacity(isolate, data, index);
1104 env->set_embedder_data(*data);
1105 return data;
1106 }
1107
GetNumberOfEmbedderDataFields()1108 uint32_t Context::GetNumberOfEmbedderDataFields() {
1109 i::Handle<i::Context> context = Utils::OpenHandle(this);
1110 ASSERT_NO_SCRIPT_NO_EXCEPTION(context->GetIsolate());
1111 Utils::ApiCheck(context->IsNativeContext(),
1112 "Context::GetNumberOfEmbedderDataFields",
1113 "Not a native context");
1114 // TODO(ishell): remove cast once embedder_data slot has a proper type.
1115 return static_cast<uint32_t>(
1116 i::EmbedderDataArray::cast(context->embedder_data()).length());
1117 }
1118
SlowGetEmbedderData(int index)1119 v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) {
1120 const char* location = "v8::Context::GetEmbedderData()";
1121 i::Handle<i::EmbedderDataArray> data =
1122 EmbedderDataFor(this, index, false, location);
1123 if (data.is_null()) return Local<Value>();
1124 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1125 i::Handle<i::Object> result(i::EmbedderDataSlot(*data, index).load_tagged(),
1126 isolate);
1127 return Utils::ToLocal(result);
1128 }
1129
SetEmbedderData(int index,v8::Local<Value> value)1130 void Context::SetEmbedderData(int index, v8::Local<Value> value) {
1131 const char* location = "v8::Context::SetEmbedderData()";
1132 i::Handle<i::EmbedderDataArray> data =
1133 EmbedderDataFor(this, index, true, location);
1134 if (data.is_null()) return;
1135 i::Handle<i::Object> val = Utils::OpenHandle(*value);
1136 i::EmbedderDataSlot::store_tagged(*data, index, *val);
1137 DCHECK_EQ(*Utils::OpenHandle(*value),
1138 *Utils::OpenHandle(*GetEmbedderData(index)));
1139 }
1140
SlowGetAlignedPointerFromEmbedderData(int index)1141 void* Context::SlowGetAlignedPointerFromEmbedderData(int index) {
1142 const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()";
1143 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1144 i::HandleScope handle_scope(isolate);
1145 i::Handle<i::EmbedderDataArray> data =
1146 EmbedderDataFor(this, index, false, location);
1147 if (data.is_null()) return nullptr;
1148 void* result;
1149 Utils::ApiCheck(
1150 i::EmbedderDataSlot(*data, index).ToAlignedPointer(isolate, &result),
1151 location, "Pointer is not aligned");
1152 return result;
1153 }
1154
SetAlignedPointerInEmbedderData(int index,void * value)1155 void Context::SetAlignedPointerInEmbedderData(int index, void* value) {
1156 const char* location = "v8::Context::SetAlignedPointerInEmbedderData()";
1157 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1158 i::Handle<i::EmbedderDataArray> data =
1159 EmbedderDataFor(this, index, true, location);
1160 bool ok =
1161 i::EmbedderDataSlot(*data, index).store_aligned_pointer(isolate, value);
1162 Utils::ApiCheck(ok, location, "Pointer is not aligned");
1163 DCHECK_EQ(value, GetAlignedPointerFromEmbedderData(index));
1164 }
1165
1166 // --- T e m p l a t e ---
1167
InitializeTemplate(i::TemplateInfo that,int type,bool do_not_cache)1168 static void InitializeTemplate(i::TemplateInfo that, int type,
1169 bool do_not_cache) {
1170 that.set_number_of_properties(0);
1171 that.set_tag(type);
1172 int serial_number =
1173 do_not_cache ? i::TemplateInfo::kDoNotCache : i::TemplateInfo::kUncached;
1174 that.set_serial_number(serial_number);
1175 }
1176
Set(v8::Local<Name> name,v8::Local<Data> value,v8::PropertyAttribute attribute)1177 void Template::Set(v8::Local<Name> name, v8::Local<Data> value,
1178 v8::PropertyAttribute attribute) {
1179 auto templ = Utils::OpenHandle(this);
1180 i::Isolate* isolate = templ->GetIsolate();
1181 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1182 i::HandleScope scope(isolate);
1183 auto value_obj = Utils::OpenHandle(*value);
1184
1185 Utils::ApiCheck(!value_obj->IsJSReceiver() || value_obj->IsTemplateInfo(),
1186 "v8::Template::Set",
1187 "Invalid value, must be a primitive or a Template");
1188
1189 // The template cache only performs shallow clones, if we set an
1190 // ObjectTemplate as a property value then we can not cache the receiver
1191 // template.
1192 if (value_obj->IsObjectTemplateInfo()) {
1193 templ->set_serial_number(i::TemplateInfo::kDoNotCache);
1194 }
1195
1196 i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name),
1197 value_obj,
1198 static_cast<i::PropertyAttributes>(attribute));
1199 }
1200
SetPrivate(v8::Local<Private> name,v8::Local<Data> value,v8::PropertyAttribute attribute)1201 void Template::SetPrivate(v8::Local<Private> name, v8::Local<Data> value,
1202 v8::PropertyAttribute attribute) {
1203 Set(Utils::ToLocal(Utils::OpenHandle(reinterpret_cast<Name*>(*name))), value,
1204 attribute);
1205 }
1206
SetAccessorProperty(v8::Local<v8::Name> name,v8::Local<FunctionTemplate> getter,v8::Local<FunctionTemplate> setter,v8::PropertyAttribute attribute,v8::AccessControl access_control)1207 void Template::SetAccessorProperty(v8::Local<v8::Name> name,
1208 v8::Local<FunctionTemplate> getter,
1209 v8::Local<FunctionTemplate> setter,
1210 v8::PropertyAttribute attribute,
1211 v8::AccessControl access_control) {
1212 // TODO(verwaest): Remove |access_control|.
1213 DCHECK_EQ(v8::DEFAULT, access_control);
1214 auto templ = Utils::OpenHandle(this);
1215 auto isolate = templ->GetIsolate();
1216 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1217 DCHECK(!name.IsEmpty());
1218 DCHECK(!getter.IsEmpty() || !setter.IsEmpty());
1219 i::HandleScope scope(isolate);
1220 i::ApiNatives::AddAccessorProperty(
1221 isolate, templ, Utils::OpenHandle(*name),
1222 Utils::OpenHandle(*getter, true), Utils::OpenHandle(*setter, true),
1223 static_cast<i::PropertyAttributes>(attribute));
1224 }
1225
1226 // --- F u n c t i o n T e m p l a t e ---
InitializeFunctionTemplate(i::FunctionTemplateInfo info,bool do_not_cache)1227 static void InitializeFunctionTemplate(i::FunctionTemplateInfo info,
1228 bool do_not_cache) {
1229 InitializeTemplate(info, Consts::FUNCTION_TEMPLATE, do_not_cache);
1230 info.set_flag(0);
1231 }
1232
1233 static Local<ObjectTemplate> ObjectTemplateNew(
1234 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor,
1235 bool do_not_cache);
1236
PrototypeTemplate()1237 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
1238 auto self = Utils::OpenHandle(this);
1239 i::Isolate* i_isolate = self->GetIsolate();
1240 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1241 i::Handle<i::HeapObject> result(self->GetPrototypeTemplate(), i_isolate);
1242 if (result->IsUndefined(i_isolate)) {
1243 // Do not cache prototype objects.
1244 result = Utils::OpenHandle(
1245 *ObjectTemplateNew(i_isolate, Local<FunctionTemplate>(), true));
1246 i::FunctionTemplateInfo::SetPrototypeTemplate(i_isolate, self, result);
1247 }
1248 return ToApiHandle<ObjectTemplate>(result);
1249 }
1250
SetPrototypeProviderTemplate(Local<FunctionTemplate> prototype_provider)1251 void FunctionTemplate::SetPrototypeProviderTemplate(
1252 Local<FunctionTemplate> prototype_provider) {
1253 auto self = Utils::OpenHandle(this);
1254 i::Isolate* i_isolate = self->GetIsolate();
1255 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1256 i::Handle<i::FunctionTemplateInfo> result =
1257 Utils::OpenHandle(*prototype_provider);
1258 Utils::ApiCheck(self->GetPrototypeTemplate().IsUndefined(i_isolate),
1259 "v8::FunctionTemplate::SetPrototypeProviderTemplate",
1260 "Protoype must be undefined");
1261 Utils::ApiCheck(self->GetParentTemplate().IsUndefined(i_isolate),
1262 "v8::FunctionTemplate::SetPrototypeProviderTemplate",
1263 "Prototype provider must be empty");
1264 i::FunctionTemplateInfo::SetPrototypeProviderTemplate(i_isolate, self,
1265 result);
1266 }
1267
EnsureNotPublished(i::Handle<i::FunctionTemplateInfo> info,const char * func)1268 static void EnsureNotPublished(i::Handle<i::FunctionTemplateInfo> info,
1269 const char* func) {
1270 DCHECK_IMPLIES(info->instantiated(), info->published());
1271 Utils::ApiCheck(!info->published(), func,
1272 "FunctionTemplate already instantiated");
1273 }
1274
Inherit(v8::Local<FunctionTemplate> value)1275 void FunctionTemplate::Inherit(v8::Local<FunctionTemplate> value) {
1276 auto info = Utils::OpenHandle(this);
1277 EnsureNotPublished(info, "v8::FunctionTemplate::Inherit");
1278 i::Isolate* i_isolate = info->GetIsolate();
1279 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1280 Utils::ApiCheck(info->GetPrototypeProviderTemplate().IsUndefined(i_isolate),
1281 "v8::FunctionTemplate::Inherit",
1282 "Protoype provider must be empty");
1283 i::FunctionTemplateInfo::SetParentTemplate(i_isolate, info,
1284 Utils::OpenHandle(*value));
1285 }
1286
FunctionTemplateNew(i::Isolate * isolate,FunctionCallback callback,v8::Local<Value> data,v8::Local<Signature> signature,int length,ConstructorBehavior behavior,bool do_not_cache,v8::Local<Private> cached_property_name=v8::Local<Private> (),SideEffectType side_effect_type=SideEffectType::kHasSideEffect,const MemorySpan<const CFunction> & c_function_overloads={},uint8_t instance_type=0,uint8_t allowed_receiver_instance_type_range_start=0,uint8_t allowed_receiver_instance_type_range_end=0)1287 static Local<FunctionTemplate> FunctionTemplateNew(
1288 i::Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
1289 v8::Local<Signature> signature, int length, ConstructorBehavior behavior,
1290 bool do_not_cache,
1291 v8::Local<Private> cached_property_name = v8::Local<Private>(),
1292 SideEffectType side_effect_type = SideEffectType::kHasSideEffect,
1293 const MemorySpan<const CFunction>& c_function_overloads = {},
1294 uint8_t instance_type = 0,
1295 uint8_t allowed_receiver_instance_type_range_start = 0,
1296 uint8_t allowed_receiver_instance_type_range_end = 0) {
1297 i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct(
1298 i::FUNCTION_TEMPLATE_INFO_TYPE, i::AllocationType::kOld);
1299 i::Handle<i::FunctionTemplateInfo> obj =
1300 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
1301 {
1302 // Disallow GC until all fields of obj have acceptable types.
1303 i::DisallowGarbageCollection no_gc;
1304 i::FunctionTemplateInfo raw = *obj;
1305 InitializeFunctionTemplate(raw, do_not_cache);
1306 raw.set_length(length);
1307 raw.set_undetectable(false);
1308 raw.set_needs_access_check(false);
1309 raw.set_accept_any_receiver(true);
1310 if (!signature.IsEmpty()) {
1311 raw.set_signature(*Utils::OpenHandle(*signature));
1312 }
1313 raw.set_cached_property_name(
1314 cached_property_name.IsEmpty()
1315 ? i::ReadOnlyRoots(isolate).the_hole_value()
1316 : *Utils::OpenHandle(*cached_property_name));
1317 if (behavior == ConstructorBehavior::kThrow) raw.set_remove_prototype(true);
1318 raw.SetInstanceType(instance_type);
1319 raw.set_allowed_receiver_instance_type_range_start(
1320 allowed_receiver_instance_type_range_start);
1321 raw.set_allowed_receiver_instance_type_range_end(
1322 allowed_receiver_instance_type_range_end);
1323 }
1324 if (callback != nullptr) {
1325 Utils::ToLocal(obj)->SetCallHandler(callback, data, side_effect_type,
1326 c_function_overloads);
1327 }
1328 return Utils::ToLocal(obj);
1329 }
1330
New(Isolate * isolate,FunctionCallback callback,v8::Local<Value> data,v8::Local<Signature> signature,int length,ConstructorBehavior behavior,SideEffectType side_effect_type,const CFunction * c_function,uint16_t instance_type,uint16_t allowed_receiver_instance_type_range_start,uint16_t allowed_receiver_instance_type_range_end)1331 Local<FunctionTemplate> FunctionTemplate::New(
1332 Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
1333 v8::Local<Signature> signature, int length, ConstructorBehavior behavior,
1334 SideEffectType side_effect_type, const CFunction* c_function,
1335 uint16_t instance_type, uint16_t allowed_receiver_instance_type_range_start,
1336 uint16_t allowed_receiver_instance_type_range_end) {
1337 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1338 // Changes to the environment cannot be captured in the snapshot. Expect no
1339 // function templates when the isolate is created for serialization.
1340 API_RCS_SCOPE(i_isolate, FunctionTemplate, New);
1341
1342 if (!Utils::ApiCheck(
1343 !c_function || behavior == ConstructorBehavior::kThrow,
1344 "FunctionTemplate::New",
1345 "Fast API calls are not supported for constructor functions.")) {
1346 return Local<FunctionTemplate>();
1347 }
1348
1349 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1350 return FunctionTemplateNew(
1351 i_isolate, callback, data, signature, length, behavior, false,
1352 Local<Private>(), side_effect_type,
1353 c_function ? MemorySpan<const CFunction>{c_function, 1}
1354 : MemorySpan<const CFunction>{},
1355 instance_type, allowed_receiver_instance_type_range_start,
1356 allowed_receiver_instance_type_range_end);
1357 }
1358
NewWithCFunctionOverloads(Isolate * isolate,FunctionCallback callback,v8::Local<Value> data,v8::Local<Signature> signature,int length,ConstructorBehavior behavior,SideEffectType side_effect_type,const MemorySpan<const CFunction> & c_function_overloads)1359 Local<FunctionTemplate> FunctionTemplate::NewWithCFunctionOverloads(
1360 Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
1361 v8::Local<Signature> signature, int length, ConstructorBehavior behavior,
1362 SideEffectType side_effect_type,
1363 const MemorySpan<const CFunction>& c_function_overloads) {
1364 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1365 API_RCS_SCOPE(i_isolate, FunctionTemplate, New);
1366
1367 if (!Utils::ApiCheck(
1368 c_function_overloads.size() == 0 ||
1369 behavior == ConstructorBehavior::kThrow,
1370 "FunctionTemplate::NewWithCFunctionOverloads",
1371 "Fast API calls are not supported for constructor functions.")) {
1372 return Local<FunctionTemplate>();
1373 }
1374
1375 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1376 return FunctionTemplateNew(i_isolate, callback, data, signature, length,
1377 behavior, false, Local<Private>(),
1378 side_effect_type, c_function_overloads);
1379 }
1380
NewWithCache(Isolate * isolate,FunctionCallback callback,Local<Private> cache_property,Local<Value> data,Local<Signature> signature,int length,SideEffectType side_effect_type)1381 Local<FunctionTemplate> FunctionTemplate::NewWithCache(
1382 Isolate* isolate, FunctionCallback callback, Local<Private> cache_property,
1383 Local<Value> data, Local<Signature> signature, int length,
1384 SideEffectType side_effect_type) {
1385 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1386 API_RCS_SCOPE(i_isolate, FunctionTemplate, NewWithCache);
1387 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1388 return FunctionTemplateNew(i_isolate, callback, data, signature, length,
1389 ConstructorBehavior::kAllow, false, cache_property,
1390 side_effect_type);
1391 }
1392
New(Isolate * isolate,Local<FunctionTemplate> receiver)1393 Local<Signature> Signature::New(Isolate* isolate,
1394 Local<FunctionTemplate> receiver) {
1395 return Utils::SignatureToLocal(Utils::OpenHandle(*receiver));
1396 }
1397
New(Isolate * isolate,Local<FunctionTemplate> receiver)1398 Local<AccessorSignature> AccessorSignature::New(
1399 Isolate* isolate, Local<FunctionTemplate> receiver) {
1400 return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
1401 }
1402
1403 #define SET_FIELD_WRAPPED(isolate, obj, setter, cdata) \
1404 do { \
1405 i::Handle<i::Object> foreign = FromCData(isolate, cdata); \
1406 (obj)->setter(*foreign); \
1407 } while (false)
1408
SetCallHandler(FunctionCallback callback,v8::Local<Value> data,SideEffectType side_effect_type,const MemorySpan<const CFunction> & c_function_overloads)1409 void FunctionTemplate::SetCallHandler(
1410 FunctionCallback callback, v8::Local<Value> data,
1411 SideEffectType side_effect_type,
1412 const MemorySpan<const CFunction>& c_function_overloads) {
1413 auto info = Utils::OpenHandle(this);
1414 EnsureNotPublished(info, "v8::FunctionTemplate::SetCallHandler");
1415 i::Isolate* isolate = info->GetIsolate();
1416 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1417 i::HandleScope scope(isolate);
1418 i::Handle<i::CallHandlerInfo> obj = isolate->factory()->NewCallHandlerInfo(
1419 side_effect_type == SideEffectType::kHasNoSideEffect);
1420 SET_FIELD_WRAPPED(isolate, obj, set_callback, callback);
1421 SET_FIELD_WRAPPED(isolate, obj, set_js_callback, obj->redirected_callback());
1422 if (data.IsEmpty()) {
1423 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1424 }
1425 obj->set_data(*Utils::OpenHandle(*data));
1426 if (c_function_overloads.size() > 0) {
1427 // Stores the data for a sequence of CFunction overloads into a single
1428 // FixedArray, as [address_0, signature_0, ... address_n-1, signature_n-1].
1429 i::Handle<i::FixedArray> function_overloads =
1430 isolate->factory()->NewFixedArray(static_cast<int>(
1431 c_function_overloads.size() *
1432 i::FunctionTemplateInfo::kFunctionOverloadEntrySize));
1433 int function_count = static_cast<int>(c_function_overloads.size());
1434 for (int i = 0; i < function_count; i++) {
1435 const CFunction& c_function = c_function_overloads.data()[i];
1436 i::Handle<i::Object> address =
1437 FromCData(isolate, c_function.GetAddress());
1438 function_overloads->set(
1439 i::FunctionTemplateInfo::kFunctionOverloadEntrySize * i, *address);
1440 i::Handle<i::Object> signature =
1441 FromCData(isolate, c_function.GetTypeInfo());
1442 function_overloads->set(
1443 i::FunctionTemplateInfo::kFunctionOverloadEntrySize * i + 1,
1444 *signature);
1445 }
1446 i::FunctionTemplateInfo::SetCFunctionOverloads(isolate, info,
1447 function_overloads);
1448 }
1449 info->set_call_code(*obj, kReleaseStore);
1450 }
1451
1452 namespace {
1453
1454 template <typename Getter, typename Setter>
MakeAccessorInfo(i::Isolate * isolate,v8::Local<Name> name,Getter getter,Setter setter,v8::Local<Value> data,v8::AccessControl settings,v8::Local<AccessorSignature> signature,bool is_special_data_property,bool replace_on_access)1455 i::Handle<i::AccessorInfo> MakeAccessorInfo(
1456 i::Isolate* isolate, v8::Local<Name> name, Getter getter, Setter setter,
1457 v8::Local<Value> data, v8::AccessControl settings,
1458 v8::Local<AccessorSignature> signature, bool is_special_data_property,
1459 bool replace_on_access) {
1460 i::Handle<i::AccessorInfo> obj = isolate->factory()->NewAccessorInfo();
1461 SET_FIELD_WRAPPED(isolate, obj, set_getter, getter);
1462 DCHECK_IMPLIES(replace_on_access,
1463 is_special_data_property && setter == nullptr);
1464 if (is_special_data_property && setter == nullptr) {
1465 setter = reinterpret_cast<Setter>(&i::Accessors::ReconfigureToDataProperty);
1466 }
1467 SET_FIELD_WRAPPED(isolate, obj, set_setter, setter);
1468 i::Address redirected = obj->redirected_getter();
1469 if (redirected != i::kNullAddress) {
1470 SET_FIELD_WRAPPED(isolate, obj, set_js_getter, redirected);
1471 }
1472
1473 i::Handle<i::Name> accessor_name = Utils::OpenHandle(*name);
1474 if (!accessor_name->IsUniqueName()) {
1475 accessor_name = isolate->factory()->InternalizeString(
1476 i::Handle<i::String>::cast(accessor_name));
1477 }
1478 i::DisallowGarbageCollection no_gc;
1479 i::AccessorInfo raw_obj = *obj;
1480 if (data.IsEmpty()) {
1481 raw_obj.set_data(i::ReadOnlyRoots(isolate).undefined_value());
1482 } else {
1483 raw_obj.set_data(*Utils::OpenHandle(*data));
1484 }
1485 raw_obj.set_name(*accessor_name);
1486 raw_obj.set_is_special_data_property(is_special_data_property);
1487 raw_obj.set_replace_on_access(replace_on_access);
1488 if (settings & ALL_CAN_READ) raw_obj.set_all_can_read(true);
1489 if (settings & ALL_CAN_WRITE) raw_obj.set_all_can_write(true);
1490 raw_obj.set_initial_property_attributes(i::NONE);
1491 if (!signature.IsEmpty()) {
1492 raw_obj.set_expected_receiver_type(*Utils::OpenHandle(*signature));
1493 }
1494 return obj;
1495 }
1496
1497 } // namespace
1498
InstanceTemplate()1499 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
1500 i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this, true);
1501 if (!Utils::ApiCheck(!handle.is_null(),
1502 "v8::FunctionTemplate::InstanceTemplate()",
1503 "Reading from empty handle")) {
1504 return Local<ObjectTemplate>();
1505 }
1506 i::Isolate* isolate = handle->GetIsolate();
1507 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1508 if (handle->GetInstanceTemplate().IsUndefined(isolate)) {
1509 Local<ObjectTemplate> templ =
1510 ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle));
1511 i::FunctionTemplateInfo::SetInstanceTemplate(isolate, handle,
1512 Utils::OpenHandle(*templ));
1513 }
1514 i::Handle<i::ObjectTemplateInfo> result(
1515 i::ObjectTemplateInfo::cast(handle->GetInstanceTemplate()), isolate);
1516 return Utils::ToLocal(result);
1517 }
1518
SetLength(int length)1519 void FunctionTemplate::SetLength(int length) {
1520 auto info = Utils::OpenHandle(this);
1521 EnsureNotPublished(info, "v8::FunctionTemplate::SetLength");
1522 auto isolate = info->GetIsolate();
1523 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1524 info->set_length(length);
1525 }
1526
SetClassName(Local<String> name)1527 void FunctionTemplate::SetClassName(Local<String> name) {
1528 auto info = Utils::OpenHandle(this);
1529 EnsureNotPublished(info, "v8::FunctionTemplate::SetClassName");
1530 auto isolate = info->GetIsolate();
1531 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1532 info->set_class_name(*Utils::OpenHandle(*name));
1533 }
1534
SetAcceptAnyReceiver(bool value)1535 void FunctionTemplate::SetAcceptAnyReceiver(bool value) {
1536 auto info = Utils::OpenHandle(this);
1537 EnsureNotPublished(info, "v8::FunctionTemplate::SetAcceptAnyReceiver");
1538 auto isolate = info->GetIsolate();
1539 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1540 info->set_accept_any_receiver(value);
1541 }
1542
ReadOnlyPrototype()1543 void FunctionTemplate::ReadOnlyPrototype() {
1544 auto info = Utils::OpenHandle(this);
1545 EnsureNotPublished(info, "v8::FunctionTemplate::ReadOnlyPrototype");
1546 auto isolate = info->GetIsolate();
1547 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1548 info->set_read_only_prototype(true);
1549 }
1550
RemovePrototype()1551 void FunctionTemplate::RemovePrototype() {
1552 auto info = Utils::OpenHandle(this);
1553 EnsureNotPublished(info, "v8::FunctionTemplate::RemovePrototype");
1554 auto isolate = info->GetIsolate();
1555 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1556 info->set_remove_prototype(true);
1557 }
1558
1559 // --- O b j e c t T e m p l a t e ---
1560
New(Isolate * isolate,v8::Local<FunctionTemplate> constructor)1561 Local<ObjectTemplate> ObjectTemplate::New(
1562 Isolate* isolate, v8::Local<FunctionTemplate> constructor) {
1563 return New(reinterpret_cast<i::Isolate*>(isolate), constructor);
1564 }
1565
ObjectTemplateNew(i::Isolate * isolate,v8::Local<FunctionTemplate> constructor,bool do_not_cache)1566 static Local<ObjectTemplate> ObjectTemplateNew(
1567 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor,
1568 bool do_not_cache) {
1569 API_RCS_SCOPE(isolate, ObjectTemplate, New);
1570 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1571 i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct(
1572 i::OBJECT_TEMPLATE_INFO_TYPE, i::AllocationType::kOld);
1573 i::Handle<i::ObjectTemplateInfo> obj =
1574 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
1575 {
1576 // Disallow GC until all fields of obj have acceptable types.
1577 i::DisallowGarbageCollection no_gc;
1578 i::ObjectTemplateInfo raw = *obj;
1579 InitializeTemplate(raw, Consts::OBJECT_TEMPLATE, do_not_cache);
1580 raw.set_data(0);
1581 if (!constructor.IsEmpty()) {
1582 raw.set_constructor(*Utils::OpenHandle(*constructor));
1583 }
1584 }
1585 return Utils::ToLocal(obj);
1586 }
1587
New(i::Isolate * isolate,v8::Local<FunctionTemplate> constructor)1588 Local<ObjectTemplate> ObjectTemplate::New(
1589 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor) {
1590 return ObjectTemplateNew(isolate, constructor, false);
1591 }
1592
1593 // Ensure that the object template has a constructor. If no
1594 // constructor is available we create one.
EnsureConstructor(i::Isolate * isolate,ObjectTemplate * object_template)1595 static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
1596 i::Isolate* isolate, ObjectTemplate* object_template) {
1597 i::Object obj = Utils::OpenHandle(object_template)->constructor();
1598 if (!obj.IsUndefined(isolate)) {
1599 i::FunctionTemplateInfo info = i::FunctionTemplateInfo::cast(obj);
1600 return i::Handle<i::FunctionTemplateInfo>(info, isolate);
1601 }
1602 Local<FunctionTemplate> templ =
1603 FunctionTemplate::New(reinterpret_cast<Isolate*>(isolate));
1604 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
1605 i::FunctionTemplateInfo::SetInstanceTemplate(
1606 isolate, constructor, Utils::OpenHandle(object_template));
1607 Utils::OpenHandle(object_template)->set_constructor(*constructor);
1608 return constructor;
1609 }
1610
1611 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,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)1612 static void TemplateSetAccessor(
1613 Template* template_obj, v8::Local<Name> name, Getter getter, Setter setter,
1614 Data data, AccessControl settings, PropertyAttribute attribute,
1615 v8::Local<AccessorSignature> signature, bool is_special_data_property,
1616 bool replace_on_access, SideEffectType getter_side_effect_type,
1617 SideEffectType setter_side_effect_type) {
1618 auto info = Utils::OpenHandle(template_obj);
1619 auto isolate = info->GetIsolate();
1620 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1621 i::HandleScope scope(isolate);
1622 i::Handle<i::AccessorInfo> accessor_info =
1623 MakeAccessorInfo(isolate, name, getter, setter, data, settings, signature,
1624 is_special_data_property, replace_on_access);
1625 {
1626 i::DisallowGarbageCollection no_gc;
1627 i::AccessorInfo raw = *accessor_info;
1628 raw.set_initial_property_attributes(
1629 static_cast<i::PropertyAttributes>(attribute));
1630 raw.set_getter_side_effect_type(getter_side_effect_type);
1631 raw.set_setter_side_effect_type(setter_side_effect_type);
1632 }
1633 i::ApiNatives::AddNativeDataProperty(isolate, info, accessor_info);
1634 }
1635
SetNativeDataProperty(v8::Local<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Local<Value> data,PropertyAttribute attribute,AccessControl settings,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)1636 void Template::SetNativeDataProperty(v8::Local<String> name,
1637 AccessorGetterCallback getter,
1638 AccessorSetterCallback setter,
1639 v8::Local<Value> data,
1640 PropertyAttribute attribute,
1641 AccessControl settings,
1642 SideEffectType getter_side_effect_type,
1643 SideEffectType setter_side_effect_type) {
1644 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1645 Local<AccessorSignature>(), true, false,
1646 getter_side_effect_type, setter_side_effect_type);
1647 }
1648
SetNativeDataProperty(v8::Local<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Local<Value> data,PropertyAttribute attribute,v8::Local<AccessorSignature> signature,AccessControl settings,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)1649 void Template::SetNativeDataProperty(
1650 v8::Local<String> name, AccessorGetterCallback getter,
1651 AccessorSetterCallback setter, v8::Local<Value> data,
1652 PropertyAttribute attribute, v8::Local<AccessorSignature> signature,
1653 AccessControl settings, SideEffectType getter_side_effect_type,
1654 SideEffectType setter_side_effect_type) {
1655 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1656 signature, true, false, getter_side_effect_type,
1657 setter_side_effect_type);
1658 }
1659
SetNativeDataProperty(v8::Local<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,v8::Local<Value> data,PropertyAttribute attribute,AccessControl settings,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)1660 void Template::SetNativeDataProperty(v8::Local<Name> name,
1661 AccessorNameGetterCallback getter,
1662 AccessorNameSetterCallback setter,
1663 v8::Local<Value> data,
1664 PropertyAttribute attribute,
1665 AccessControl settings,
1666 SideEffectType getter_side_effect_type,
1667 SideEffectType setter_side_effect_type) {
1668 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1669 Local<AccessorSignature>(), true, false,
1670 getter_side_effect_type, setter_side_effect_type);
1671 }
1672
SetNativeDataProperty(v8::Local<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,v8::Local<Value> data,PropertyAttribute attribute,v8::Local<AccessorSignature> signature,AccessControl settings,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)1673 void Template::SetNativeDataProperty(
1674 v8::Local<Name> name, AccessorNameGetterCallback getter,
1675 AccessorNameSetterCallback setter, v8::Local<Value> data,
1676 PropertyAttribute attribute, v8::Local<AccessorSignature> signature,
1677 AccessControl settings, SideEffectType getter_side_effect_type,
1678 SideEffectType setter_side_effect_type) {
1679 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1680 signature, true, false, getter_side_effect_type,
1681 setter_side_effect_type);
1682 }
1683
SetLazyDataProperty(v8::Local<Name> name,AccessorNameGetterCallback getter,v8::Local<Value> data,PropertyAttribute attribute,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)1684 void Template::SetLazyDataProperty(v8::Local<Name> name,
1685 AccessorNameGetterCallback getter,
1686 v8::Local<Value> data,
1687 PropertyAttribute attribute,
1688 SideEffectType getter_side_effect_type,
1689 SideEffectType setter_side_effect_type) {
1690 TemplateSetAccessor(this, name, getter,
1691 static_cast<AccessorNameSetterCallback>(nullptr), data,
1692 DEFAULT, attribute, Local<AccessorSignature>(), true,
1693 true, getter_side_effect_type, setter_side_effect_type);
1694 }
1695
SetIntrinsicDataProperty(Local<Name> name,Intrinsic intrinsic,PropertyAttribute attribute)1696 void Template::SetIntrinsicDataProperty(Local<Name> name, Intrinsic intrinsic,
1697 PropertyAttribute attribute) {
1698 auto templ = Utils::OpenHandle(this);
1699 i::Isolate* isolate = templ->GetIsolate();
1700 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1701 i::HandleScope scope(isolate);
1702 i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name),
1703 intrinsic,
1704 static_cast<i::PropertyAttributes>(attribute));
1705 }
1706
SetAccessor(v8::Local<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Local<Value> data,AccessControl settings,PropertyAttribute attribute,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)1707 void ObjectTemplate::SetAccessor(v8::Local<String> name,
1708 AccessorGetterCallback getter,
1709 AccessorSetterCallback setter,
1710 v8::Local<Value> data, AccessControl settings,
1711 PropertyAttribute attribute,
1712 SideEffectType getter_side_effect_type,
1713 SideEffectType setter_side_effect_type) {
1714 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1715 Local<AccessorSignature>(),
1716 i::FLAG_disable_old_api_accessors, false,
1717 getter_side_effect_type, setter_side_effect_type);
1718 }
1719
SetAccessor(v8::Local<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,v8::Local<Value> data,AccessControl settings,PropertyAttribute attribute,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)1720 void ObjectTemplate::SetAccessor(v8::Local<Name> name,
1721 AccessorNameGetterCallback getter,
1722 AccessorNameSetterCallback setter,
1723 v8::Local<Value> data, AccessControl settings,
1724 PropertyAttribute attribute,
1725 SideEffectType getter_side_effect_type,
1726 SideEffectType setter_side_effect_type) {
1727 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1728 Local<AccessorSignature>(),
1729 i::FLAG_disable_old_api_accessors, false,
1730 getter_side_effect_type, setter_side_effect_type);
1731 }
1732
SetAccessor(v8::Local<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Local<Value> data,AccessControl settings,PropertyAttribute attribute,v8::Local<AccessorSignature> signature,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)1733 void ObjectTemplate::SetAccessor(v8::Local<String> name,
1734 AccessorGetterCallback getter,
1735 AccessorSetterCallback setter,
1736 v8::Local<Value> data, AccessControl settings,
1737 PropertyAttribute attribute,
1738 v8::Local<AccessorSignature> signature,
1739 SideEffectType getter_side_effect_type,
1740 SideEffectType setter_side_effect_type) {
1741 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1742 signature, i::FLAG_disable_old_api_accessors, false,
1743 getter_side_effect_type, setter_side_effect_type);
1744 }
1745
SetAccessor(v8::Local<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,v8::Local<Value> data,AccessControl settings,PropertyAttribute attribute,v8::Local<AccessorSignature> signature,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)1746 void ObjectTemplate::SetAccessor(v8::Local<Name> name,
1747 AccessorNameGetterCallback getter,
1748 AccessorNameSetterCallback setter,
1749 v8::Local<Value> data, AccessControl settings,
1750 PropertyAttribute attribute,
1751 v8::Local<AccessorSignature> signature,
1752 SideEffectType getter_side_effect_type,
1753 SideEffectType setter_side_effect_type) {
1754 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1755 signature, i::FLAG_disable_old_api_accessors, false,
1756 getter_side_effect_type, setter_side_effect_type);
1757 }
1758
1759 template <typename Getter, typename Setter, typename Query, typename Descriptor,
1760 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)1761 static i::Handle<i::InterceptorInfo> CreateInterceptorInfo(
1762 i::Isolate* isolate, Getter getter, Setter setter, Query query,
1763 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1764 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1765 auto obj = i::Handle<i::InterceptorInfo>::cast(isolate->factory()->NewStruct(
1766 i::INTERCEPTOR_INFO_TYPE, i::AllocationType::kOld));
1767 obj->set_flags(0);
1768
1769 if (getter != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_getter, getter);
1770 if (setter != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_setter, setter);
1771 if (query != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_query, query);
1772 if (descriptor != nullptr)
1773 SET_FIELD_WRAPPED(isolate, obj, set_descriptor, descriptor);
1774 if (remover != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_deleter, remover);
1775 if (enumerator != nullptr)
1776 SET_FIELD_WRAPPED(isolate, obj, set_enumerator, enumerator);
1777 if (definer != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_definer, definer);
1778 obj->set_can_intercept_symbols(
1779 !(static_cast<int>(flags) &
1780 static_cast<int>(PropertyHandlerFlags::kOnlyInterceptStrings)));
1781 obj->set_all_can_read(static_cast<int>(flags) &
1782 static_cast<int>(PropertyHandlerFlags::kAllCanRead));
1783 obj->set_non_masking(static_cast<int>(flags) &
1784 static_cast<int>(PropertyHandlerFlags::kNonMasking));
1785 obj->set_has_no_side_effect(
1786 static_cast<int>(flags) &
1787 static_cast<int>(PropertyHandlerFlags::kHasNoSideEffect));
1788
1789 if (data.IsEmpty()) {
1790 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1791 }
1792 obj->set_data(*Utils::OpenHandle(*data));
1793 return obj;
1794 }
1795
1796 template <typename Getter, typename Setter, typename Query, typename Descriptor,
1797 typename Deleter, typename Enumerator, typename Definer>
CreateNamedInterceptorInfo(i::Isolate * isolate,Getter getter,Setter setter,Query query,Descriptor descriptor,Deleter remover,Enumerator enumerator,Definer definer,Local<Value> data,PropertyHandlerFlags flags)1798 static i::Handle<i::InterceptorInfo> CreateNamedInterceptorInfo(
1799 i::Isolate* isolate, Getter getter, Setter setter, Query query,
1800 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1801 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1802 auto interceptor =
1803 CreateInterceptorInfo(isolate, getter, setter, query, descriptor, remover,
1804 enumerator, definer, data, flags);
1805 interceptor->set_is_named(true);
1806 return interceptor;
1807 }
1808
1809 template <typename Getter, typename Setter, typename Query, typename Descriptor,
1810 typename Deleter, typename Enumerator, typename Definer>
CreateIndexedInterceptorInfo(i::Isolate * isolate,Getter getter,Setter setter,Query query,Descriptor descriptor,Deleter remover,Enumerator enumerator,Definer definer,Local<Value> data,PropertyHandlerFlags flags)1811 static i::Handle<i::InterceptorInfo> CreateIndexedInterceptorInfo(
1812 i::Isolate* isolate, Getter getter, Setter setter, Query query,
1813 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1814 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1815 auto interceptor =
1816 CreateInterceptorInfo(isolate, getter, setter, query, descriptor, remover,
1817 enumerator, definer, data, flags);
1818 interceptor->set_is_named(false);
1819 return interceptor;
1820 }
1821
1822 template <typename Getter, typename Setter, typename Query, typename Descriptor,
1823 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)1824 static void ObjectTemplateSetNamedPropertyHandler(
1825 ObjectTemplate* templ, Getter getter, Setter setter, Query query,
1826 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1827 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1828 i::Isolate* isolate = Utils::OpenHandle(templ)->GetIsolate();
1829 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1830 i::HandleScope scope(isolate);
1831 auto cons = EnsureConstructor(isolate, templ);
1832 EnsureNotPublished(cons, "ObjectTemplateSetNamedPropertyHandler");
1833 auto obj =
1834 CreateNamedInterceptorInfo(isolate, getter, setter, query, descriptor,
1835 remover, enumerator, definer, data, flags);
1836 i::FunctionTemplateInfo::SetNamedPropertyHandler(isolate, cons, obj);
1837 }
1838
SetHandler(const NamedPropertyHandlerConfiguration & config)1839 void ObjectTemplate::SetHandler(
1840 const NamedPropertyHandlerConfiguration& config) {
1841 ObjectTemplateSetNamedPropertyHandler(
1842 this, config.getter, config.setter, config.query, config.descriptor,
1843 config.deleter, config.enumerator, config.definer, config.data,
1844 config.flags);
1845 }
1846
MarkAsUndetectable()1847 void ObjectTemplate::MarkAsUndetectable() {
1848 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1849 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1850 i::HandleScope scope(isolate);
1851 auto cons = EnsureConstructor(isolate, this);
1852 EnsureNotPublished(cons, "v8::ObjectTemplate::MarkAsUndetectable");
1853 cons->set_undetectable(true);
1854 }
1855
SetAccessCheckCallback(AccessCheckCallback callback,Local<Value> data)1856 void ObjectTemplate::SetAccessCheckCallback(AccessCheckCallback callback,
1857 Local<Value> data) {
1858 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1859 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1860 i::HandleScope scope(isolate);
1861 auto cons = EnsureConstructor(isolate, this);
1862 EnsureNotPublished(cons, "v8::ObjectTemplate::SetAccessCheckCallback");
1863
1864 i::Handle<i::Struct> struct_info = isolate->factory()->NewStruct(
1865 i::ACCESS_CHECK_INFO_TYPE, i::AllocationType::kOld);
1866 i::Handle<i::AccessCheckInfo> info =
1867 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1868
1869 SET_FIELD_WRAPPED(isolate, info, set_callback, callback);
1870 info->set_named_interceptor(i::Object());
1871 info->set_indexed_interceptor(i::Object());
1872
1873 if (data.IsEmpty()) {
1874 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1875 }
1876 info->set_data(*Utils::OpenHandle(*data));
1877
1878 i::FunctionTemplateInfo::SetAccessCheckInfo(isolate, cons, info);
1879 cons->set_needs_access_check(true);
1880 }
1881
SetAccessCheckCallbackAndHandler(AccessCheckCallback callback,const NamedPropertyHandlerConfiguration & named_handler,const IndexedPropertyHandlerConfiguration & indexed_handler,Local<Value> data)1882 void ObjectTemplate::SetAccessCheckCallbackAndHandler(
1883 AccessCheckCallback callback,
1884 const NamedPropertyHandlerConfiguration& named_handler,
1885 const IndexedPropertyHandlerConfiguration& indexed_handler,
1886 Local<Value> data) {
1887 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1888 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1889 i::HandleScope scope(isolate);
1890 auto cons = EnsureConstructor(isolate, this);
1891 EnsureNotPublished(cons,
1892 "v8::ObjectTemplate::SetAccessCheckCallbackWithHandler");
1893
1894 i::Handle<i::Struct> struct_info = isolate->factory()->NewStruct(
1895 i::ACCESS_CHECK_INFO_TYPE, i::AllocationType::kOld);
1896 i::Handle<i::AccessCheckInfo> info =
1897 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1898
1899 SET_FIELD_WRAPPED(isolate, info, set_callback, callback);
1900 auto named_interceptor = CreateNamedInterceptorInfo(
1901 isolate, named_handler.getter, named_handler.setter, named_handler.query,
1902 named_handler.descriptor, named_handler.deleter, named_handler.enumerator,
1903 named_handler.definer, named_handler.data, named_handler.flags);
1904 info->set_named_interceptor(*named_interceptor);
1905 auto indexed_interceptor = CreateIndexedInterceptorInfo(
1906 isolate, indexed_handler.getter, indexed_handler.setter,
1907 indexed_handler.query, indexed_handler.descriptor,
1908 indexed_handler.deleter, indexed_handler.enumerator,
1909 indexed_handler.definer, indexed_handler.data, indexed_handler.flags);
1910 info->set_indexed_interceptor(*indexed_interceptor);
1911
1912 if (data.IsEmpty()) {
1913 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1914 }
1915 info->set_data(*Utils::OpenHandle(*data));
1916
1917 i::FunctionTemplateInfo::SetAccessCheckInfo(isolate, cons, info);
1918 cons->set_needs_access_check(true);
1919 }
1920
SetHandler(const IndexedPropertyHandlerConfiguration & config)1921 void ObjectTemplate::SetHandler(
1922 const IndexedPropertyHandlerConfiguration& config) {
1923 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1924 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1925 i::HandleScope scope(isolate);
1926 auto cons = EnsureConstructor(isolate, this);
1927 EnsureNotPublished(cons, "v8::ObjectTemplate::SetHandler");
1928 auto obj = CreateIndexedInterceptorInfo(
1929 isolate, config.getter, config.setter, config.query, config.descriptor,
1930 config.deleter, config.enumerator, config.definer, config.data,
1931 config.flags);
1932 i::FunctionTemplateInfo::SetIndexedPropertyHandler(isolate, cons, obj);
1933 }
1934
SetCallAsFunctionHandler(FunctionCallback callback,Local<Value> data)1935 void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback,
1936 Local<Value> data) {
1937 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1938 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1939 i::HandleScope scope(isolate);
1940 auto cons = EnsureConstructor(isolate, this);
1941 EnsureNotPublished(cons, "v8::ObjectTemplate::SetCallAsFunctionHandler");
1942 i::Handle<i::CallHandlerInfo> obj = isolate->factory()->NewCallHandlerInfo();
1943 SET_FIELD_WRAPPED(isolate, obj, set_callback, callback);
1944 SET_FIELD_WRAPPED(isolate, obj, set_js_callback, obj->redirected_callback());
1945 if (data.IsEmpty()) {
1946 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1947 }
1948 obj->set_data(*Utils::OpenHandle(*data));
1949 i::FunctionTemplateInfo::SetInstanceCallHandler(isolate, cons, obj);
1950 }
1951
InternalFieldCount() const1952 int ObjectTemplate::InternalFieldCount() const {
1953 return Utils::OpenHandle(this)->embedder_field_count();
1954 }
1955
SetInternalFieldCount(int value)1956 void ObjectTemplate::SetInternalFieldCount(int value) {
1957 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1958 if (!Utils::ApiCheck(i::Smi::IsValid(value),
1959 "v8::ObjectTemplate::SetInternalFieldCount()",
1960 "Invalid embedder field count")) {
1961 return;
1962 }
1963 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1964 if (value > 0) {
1965 // The embedder field count is set by the constructor function's
1966 // construct code, so we ensure that there is a constructor
1967 // function to do the setting.
1968 EnsureConstructor(isolate, this);
1969 }
1970 Utils::OpenHandle(this)->set_embedder_field_count(value);
1971 }
1972
IsImmutableProto() const1973 bool ObjectTemplate::IsImmutableProto() const {
1974 return Utils::OpenHandle(this)->immutable_proto();
1975 }
1976
SetImmutableProto()1977 void ObjectTemplate::SetImmutableProto() {
1978 auto self = Utils::OpenHandle(this);
1979 i::Isolate* isolate = self->GetIsolate();
1980 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1981 self->set_immutable_proto(true);
1982 }
1983
IsCodeLike() const1984 bool ObjectTemplate::IsCodeLike() const {
1985 return Utils::OpenHandle(this)->code_like();
1986 }
1987
SetCodeLike()1988 void ObjectTemplate::SetCodeLike() {
1989 auto self = Utils::OpenHandle(this);
1990 i::Isolate* isolate = self->GetIsolate();
1991 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1992 self->set_code_like(true);
1993 }
1994
1995 // --- S c r i p t s ---
1996
1997 // Internally, UnboundScript is a SharedFunctionInfo, and Script is a
1998 // JSFunction.
1999
CachedData(const uint8_t * data_,int length_,BufferPolicy buffer_policy_)2000 ScriptCompiler::CachedData::CachedData(const uint8_t* data_, int length_,
2001 BufferPolicy buffer_policy_)
2002 : data(data_),
2003 length(length_),
2004 rejected(false),
2005 buffer_policy(buffer_policy_) {}
2006
~CachedData()2007 ScriptCompiler::CachedData::~CachedData() {
2008 if (buffer_policy == BufferOwned) {
2009 delete[] data;
2010 }
2011 }
2012
StreamedSource(std::unique_ptr<ExternalSourceStream> stream,Encoding encoding)2013 ScriptCompiler::StreamedSource::StreamedSource(
2014 std::unique_ptr<ExternalSourceStream> stream, Encoding encoding)
2015 : impl_(new i::ScriptStreamingData(std::move(stream), encoding)) {}
2016
2017 ScriptCompiler::StreamedSource::~StreamedSource() = default;
2018
BindToCurrentContext()2019 Local<Script> UnboundScript::BindToCurrentContext() {
2020 auto function_info =
2021 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
2022 i::Isolate* isolate = function_info->GetIsolate();
2023 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2024 i::Handle<i::JSFunction> function =
2025 i::Factory::JSFunctionBuilder{isolate, function_info,
2026 isolate->native_context()}
2027 .Build();
2028 return ToApiHandle<Script>(function);
2029 }
2030
GetId() const2031 int UnboundScript::GetId() const {
2032 auto function_info = i::SharedFunctionInfo::cast(*Utils::OpenHandle(this));
2033 API_RCS_SCOPE(function_info.GetIsolate(), UnboundScript, GetId);
2034 return i::Script::cast(function_info.script()).id();
2035 }
2036
GetLineNumber(int code_pos)2037 int UnboundScript::GetLineNumber(int code_pos) {
2038 i::Handle<i::SharedFunctionInfo> obj =
2039 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
2040 i::Isolate* isolate = obj->GetIsolate();
2041 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2042 API_RCS_SCOPE(isolate, UnboundScript, GetLineNumber);
2043 if (obj->script().IsScript()) {
2044 i::Handle<i::Script> script(i::Script::cast(obj->script()), isolate);
2045 return i::Script::GetLineNumber(script, code_pos);
2046 } else {
2047 return -1;
2048 }
2049 }
2050
GetScriptName()2051 Local<Value> UnboundScript::GetScriptName() {
2052 i::Handle<i::SharedFunctionInfo> obj =
2053 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
2054 i::Isolate* isolate = obj->GetIsolate();
2055 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2056 API_RCS_SCOPE(isolate, UnboundScript, GetName);
2057 if (obj->script().IsScript()) {
2058 i::Object name = i::Script::cast(obj->script()).name();
2059 return Utils::ToLocal(i::Handle<i::Object>(name, isolate));
2060 } else {
2061 return Local<String>();
2062 }
2063 }
2064
GetSourceURL()2065 Local<Value> UnboundScript::GetSourceURL() {
2066 i::Handle<i::SharedFunctionInfo> obj =
2067 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
2068 i::Isolate* isolate = obj->GetIsolate();
2069 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2070 API_RCS_SCOPE(isolate, UnboundScript, GetSourceURL);
2071 if (obj->script().IsScript()) {
2072 i::Object url = i::Script::cast(obj->script()).source_url();
2073 return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
2074 } else {
2075 return Local<String>();
2076 }
2077 }
2078
GetSourceMappingURL()2079 Local<Value> UnboundScript::GetSourceMappingURL() {
2080 i::Handle<i::SharedFunctionInfo> obj =
2081 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
2082 i::Isolate* isolate = obj->GetIsolate();
2083 API_RCS_SCOPE(isolate, UnboundScript, GetSourceMappingURL);
2084 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2085 if (obj->script().IsScript()) {
2086 i::Object url = i::Script::cast(obj->script()).source_mapping_url();
2087 return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
2088 } else {
2089 return Local<String>();
2090 }
2091 }
2092
Run(Local<Context> context)2093 MaybeLocal<Value> Script::Run(Local<Context> context) {
2094 return Run(context, Local<Data>());
2095 }
2096
Run(Local<Context> context,Local<Data> host_defined_options)2097 MaybeLocal<Value> Script::Run(Local<Context> context,
2098 Local<Data> host_defined_options) {
2099 auto v8_isolate = context->GetIsolate();
2100 auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2101 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
2102 ENTER_V8(isolate, context, Script, Run, MaybeLocal<Value>(),
2103 InternalEscapableScope);
2104 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
2105 i::NestedTimedHistogramScope execute_timer(isolate->counters()->execute(),
2106 isolate);
2107 i::AggregatingHistogramTimerScope histogram_timer(
2108 isolate->counters()->compile_lazy());
2109 auto fun = i::Handle<i::JSFunction>::cast(Utils::OpenHandle(this));
2110
2111 // TODO(crbug.com/1193459): remove once ablation study is completed
2112 base::ElapsedTimer timer;
2113 base::TimeDelta delta;
2114 if (i::FLAG_script_delay > 0) {
2115 delta = v8::base::TimeDelta::FromMillisecondsD(i::FLAG_script_delay);
2116 }
2117 if (i::FLAG_script_delay_once > 0 && !isolate->did_run_script_delay()) {
2118 delta = v8::base::TimeDelta::FromMillisecondsD(i::FLAG_script_delay_once);
2119 isolate->set_did_run_script_delay(true);
2120 }
2121 if (i::FLAG_script_delay_fraction > 0.0) {
2122 timer.Start();
2123 } else if (delta.InMicroseconds() > 0) {
2124 timer.Start();
2125 while (timer.Elapsed() < delta) {
2126 // Busy wait.
2127 }
2128 }
2129
2130 if (V8_UNLIKELY(i::FLAG_experimental_web_snapshots)) {
2131 i::Handle<i::HeapObject> maybe_script =
2132 handle(fun->shared().script(), isolate);
2133 if (maybe_script->IsScript() &&
2134 i::Script::cast(*maybe_script).type() == i::Script::TYPE_WEB_SNAPSHOT) {
2135 i::WebSnapshotDeserializer deserializer(
2136 reinterpret_cast<i::Isolate*>(v8_isolate),
2137 i::Handle<i::Script>::cast(maybe_script));
2138 deserializer.Deserialize();
2139 RETURN_ON_FAILED_EXECUTION(Value);
2140 Local<Value> result = v8::Undefined(v8_isolate);
2141 RETURN_ESCAPED(result);
2142 }
2143 }
2144
2145 i::Handle<i::Object> receiver = isolate->global_proxy();
2146 // TODO(cbruni, chromium:1244145): Remove once migrated to the context.
2147 i::Handle<i::Object> options(
2148 i::Script::cast(fun->shared().script()).host_defined_options(), isolate);
2149 Local<Value> result;
2150 has_pending_exception = !ToLocal<Value>(
2151 i::Execution::CallScript(isolate, fun, receiver, options), &result);
2152
2153 if (i::FLAG_script_delay_fraction > 0.0) {
2154 delta = v8::base::TimeDelta::FromMillisecondsD(
2155 timer.Elapsed().InMillisecondsF() * i::FLAG_script_delay_fraction);
2156 timer.Restart();
2157 while (timer.Elapsed() < delta) {
2158 // Busy wait.
2159 }
2160 }
2161
2162 RETURN_ON_FAILED_EXECUTION(Value);
2163 RETURN_ESCAPED(result);
2164 }
2165
GetResourceName()2166 Local<Value> ScriptOrModule::GetResourceName() {
2167 i::Handle<i::ScriptOrModule> obj = Utils::OpenHandle(this);
2168 i::Isolate* isolate = i::GetIsolateFromWritableObject(*obj);
2169 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2170 i::Handle<i::Object> val(obj->resource_name(), isolate);
2171 return ToApiHandle<Value>(val);
2172 }
2173
GetHostDefinedOptions()2174 Local<PrimitiveArray> ScriptOrModule::GetHostDefinedOptions() {
2175 return HostDefinedOptions().As<PrimitiveArray>();
2176 }
2177
HostDefinedOptions()2178 Local<Data> ScriptOrModule::HostDefinedOptions() {
2179 i::Handle<i::ScriptOrModule> obj = Utils::OpenHandle(this);
2180 i::Isolate* isolate = i::GetIsolateFromWritableObject(*obj);
2181 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2182 i::Handle<i::Object> val(obj->host_defined_options(), isolate);
2183 return ToApiHandle<Data>(val);
2184 }
2185
GetUnboundScript()2186 Local<UnboundScript> Script::GetUnboundScript() {
2187 i::DisallowGarbageCollection no_gc;
2188 i::Handle<i::JSFunction> obj = Utils::OpenHandle(this);
2189 i::SharedFunctionInfo sfi = (*obj).shared();
2190 i::Isolate* isolate = sfi.GetIsolate();
2191 return ToApiHandle<UnboundScript>(i::handle(sfi, isolate));
2192 }
2193
GetResourceName()2194 Local<Value> Script::GetResourceName() {
2195 i::DisallowGarbageCollection no_gc;
2196 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2197 i::SharedFunctionInfo sfi = (*func).shared();
2198 i::Isolate* isolate = func->GetIsolate();
2199 CHECK(sfi.script().IsScript());
2200 return ToApiHandle<Value>(
2201 i::handle(i::Script::cast(sfi.script()).name(), isolate));
2202 }
2203
2204 // static
New(Isolate * v8_isolate,int length)2205 Local<PrimitiveArray> PrimitiveArray::New(Isolate* v8_isolate, int length) {
2206 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2207 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2208 Utils::ApiCheck(length >= 0, "v8::PrimitiveArray::New",
2209 "length must be equal or greater than zero");
2210 i::Handle<i::FixedArray> array = isolate->factory()->NewFixedArray(length);
2211 return ToApiHandle<PrimitiveArray>(array);
2212 }
2213
Length() const2214 int PrimitiveArray::Length() const {
2215 i::Handle<i::FixedArray> array = Utils::OpenHandle(this);
2216 return array->length();
2217 }
2218
Set(Isolate * v8_isolate,int index,Local<Primitive> item)2219 void PrimitiveArray::Set(Isolate* v8_isolate, int index,
2220 Local<Primitive> item) {
2221 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2222 i::Handle<i::FixedArray> array = Utils::OpenHandle(this);
2223 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2224 Utils::ApiCheck(index >= 0 && index < array->length(),
2225 "v8::PrimitiveArray::Set",
2226 "index must be greater than or equal to 0 and less than the "
2227 "array length");
2228 i::Handle<i::Object> i_item = Utils::OpenHandle(*item);
2229 array->set(index, *i_item);
2230 }
2231
Get(Isolate * v8_isolate,int index)2232 Local<Primitive> PrimitiveArray::Get(Isolate* v8_isolate, int index) {
2233 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2234 i::Handle<i::FixedArray> array = Utils::OpenHandle(this);
2235 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2236 Utils::ApiCheck(index >= 0 && index < array->length(),
2237 "v8::PrimitiveArray::Get",
2238 "index must be greater than or equal to 0 and less than the "
2239 "array length");
2240 i::Handle<i::Object> i_item(array->get(index), isolate);
2241 return ToApiHandle<Primitive>(i_item);
2242 }
2243
CheckCast(v8::Data * that)2244 void v8::PrimitiveArray::CheckCast(v8::Data* that) {
2245 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2246 Utils::ApiCheck(
2247 obj->IsFixedArray(), "v8::PrimitiveArray::Cast",
2248 "Value is not a PrimitiveArray. This is a temporary issue, v8::Data and "
2249 "v8::PrimitiveArray will not be compatible in the future.");
2250 }
2251
Length() const2252 int FixedArray::Length() const {
2253 i::Handle<i::FixedArray> self = Utils::OpenHandle(this);
2254 return self->length();
2255 }
2256
Get(Local<Context> context,int i) const2257 Local<Data> FixedArray::Get(Local<Context> context, int i) const {
2258 i::Handle<i::FixedArray> self = Utils::OpenHandle(this);
2259 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
2260 CHECK_LT(i, self->length());
2261 i::Handle<i::Object> entry(self->get(i), isolate);
2262 return ToApiHandle<Data>(entry);
2263 }
2264
GetSpecifier() const2265 Local<String> ModuleRequest::GetSpecifier() const {
2266 i::Handle<i::ModuleRequest> self = Utils::OpenHandle(this);
2267 i::Isolate* isolate = self->GetIsolate();
2268 return ToApiHandle<String>(i::handle(self->specifier(), isolate));
2269 }
2270
GetSourceOffset() const2271 int ModuleRequest::GetSourceOffset() const {
2272 return Utils::OpenHandle(this)->position();
2273 }
2274
GetImportAssertions() const2275 Local<FixedArray> ModuleRequest::GetImportAssertions() const {
2276 i::Handle<i::ModuleRequest> self = Utils::OpenHandle(this);
2277 i::Isolate* isolate = self->GetIsolate();
2278 return ToApiHandle<FixedArray>(i::handle(self->import_assertions(), isolate));
2279 }
2280
GetStatus() const2281 Module::Status Module::GetStatus() const {
2282 i::Handle<i::Module> self = Utils::OpenHandle(this);
2283 switch (self->status()) {
2284 case i::Module::kUnlinked:
2285 case i::Module::kPreLinking:
2286 return kUninstantiated;
2287 case i::Module::kLinking:
2288 return kInstantiating;
2289 case i::Module::kLinked:
2290 return kInstantiated;
2291 case i::Module::kEvaluating:
2292 case i::Module::kEvaluatingAsync:
2293 return kEvaluating;
2294 case i::Module::kEvaluated:
2295 return kEvaluated;
2296 case i::Module::kErrored:
2297 return kErrored;
2298 }
2299 UNREACHABLE();
2300 }
2301
GetException() const2302 Local<Value> Module::GetException() const {
2303 Utils::ApiCheck(GetStatus() == kErrored, "v8::Module::GetException",
2304 "Module status must be kErrored");
2305 i::Handle<i::Module> self = Utils::OpenHandle(this);
2306 i::Isolate* isolate = self->GetIsolate();
2307 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2308 return ToApiHandle<Value>(i::handle(self->GetException(), isolate));
2309 }
2310
GetModuleRequests() const2311 Local<FixedArray> Module::GetModuleRequests() const {
2312 i::Handle<i::Module> self = Utils::OpenHandle(this);
2313 if (self->IsSyntheticModule()) {
2314 // Synthetic modules are leaf nodes in the module graph. They have no
2315 // ModuleRequests.
2316 return ToApiHandle<FixedArray>(
2317 self->GetReadOnlyRoots().empty_fixed_array_handle());
2318 } else {
2319 i::Isolate* isolate = self->GetIsolate();
2320 i::Handle<i::FixedArray> module_requests(
2321 i::Handle<i::SourceTextModule>::cast(self)->info().module_requests(),
2322 isolate);
2323 return ToApiHandle<FixedArray>(module_requests);
2324 }
2325 }
2326
SourceOffsetToLocation(int offset) const2327 Location Module::SourceOffsetToLocation(int offset) const {
2328 i::Handle<i::Module> self = Utils::OpenHandle(this);
2329 i::Isolate* isolate = self->GetIsolate();
2330 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2331 i::HandleScope scope(isolate);
2332 Utils::ApiCheck(
2333 self->IsSourceTextModule(), "v8::Module::SourceOffsetToLocation",
2334 "v8::Module::SourceOffsetToLocation must be used on an SourceTextModule");
2335 i::Handle<i::Script> script(
2336 i::Handle<i::SourceTextModule>::cast(self)->GetScript(), isolate);
2337 i::Script::PositionInfo info;
2338 i::Script::GetPositionInfo(script, offset, &info, i::Script::WITH_OFFSET);
2339 return v8::Location(info.line, info.column);
2340 }
2341
GetModuleNamespace()2342 Local<Value> Module::GetModuleNamespace() {
2343 Utils::ApiCheck(
2344 GetStatus() >= kInstantiated, "v8::Module::GetModuleNamespace",
2345 "v8::Module::GetModuleNamespace must be used on an instantiated module");
2346 i::Handle<i::Module> self = Utils::OpenHandle(this);
2347 auto isolate = self->GetIsolate();
2348 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2349 i::Handle<i::JSModuleNamespace> module_namespace =
2350 i::Module::GetModuleNamespace(isolate, self);
2351 return ToApiHandle<Value>(module_namespace);
2352 }
2353
GetUnboundModuleScript()2354 Local<UnboundModuleScript> Module::GetUnboundModuleScript() {
2355 i::Handle<i::Module> self = Utils::OpenHandle(this);
2356 Utils::ApiCheck(
2357 self->IsSourceTextModule(), "v8::Module::GetUnboundModuleScript",
2358 "v8::Module::GetUnboundModuleScript must be used on an SourceTextModule");
2359 auto isolate = self->GetIsolate();
2360 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2361 return ToApiHandle<UnboundModuleScript>(i::handle(
2362 i::Handle<i::SourceTextModule>::cast(self)->GetSharedFunctionInfo(),
2363 isolate));
2364 }
2365
ScriptId() const2366 int Module::ScriptId() const {
2367 i::Module self = *Utils::OpenHandle(this);
2368 Utils::ApiCheck(self.IsSourceTextModule(), "v8::Module::ScriptId",
2369 "v8::Module::ScriptId must be used on an SourceTextModule");
2370 ASSERT_NO_SCRIPT_NO_EXCEPTION(self.GetIsolate());
2371 return i::SourceTextModule::cast(self).GetScript().id();
2372 }
2373
IsGraphAsync() const2374 bool Module::IsGraphAsync() const {
2375 Utils::ApiCheck(
2376 GetStatus() >= kInstantiated, "v8::Module::IsGraphAsync",
2377 "v8::Module::IsGraphAsync must be used on an instantiated module");
2378 i::Module self = *Utils::OpenHandle(this);
2379 auto isolate = self.GetIsolate();
2380 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2381 return self.IsGraphAsync(isolate);
2382 }
2383
IsSourceTextModule() const2384 bool Module::IsSourceTextModule() const {
2385 return Utils::OpenHandle(this)->IsSourceTextModule();
2386 }
2387
IsSyntheticModule() const2388 bool Module::IsSyntheticModule() const {
2389 return Utils::OpenHandle(this)->IsSyntheticModule();
2390 }
2391
GetIdentityHash() const2392 int Module::GetIdentityHash() const { return Utils::OpenHandle(this)->hash(); }
2393
InstantiateModule(Local<Context> context,Module::ResolveModuleCallback callback)2394 Maybe<bool> Module::InstantiateModule(Local<Context> context,
2395 Module::ResolveModuleCallback callback) {
2396 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
2397 ENTER_V8(isolate, context, Module, InstantiateModule, Nothing<bool>(),
2398 i::HandleScope);
2399 has_pending_exception = !i::Module::Instantiate(
2400 isolate, Utils::OpenHandle(this), context, callback, nullptr);
2401 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
2402 return Just(true);
2403 }
2404
Evaluate(Local<Context> context)2405 MaybeLocal<Value> Module::Evaluate(Local<Context> context) {
2406 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
2407 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
2408 ENTER_V8(isolate, context, Module, Evaluate, MaybeLocal<Value>(),
2409 InternalEscapableScope);
2410 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
2411 i::NestedTimedHistogramScope execute_timer(isolate->counters()->execute(),
2412 isolate);
2413 i::AggregatingHistogramTimerScope timer(isolate->counters()->compile_lazy());
2414
2415 i::Handle<i::Module> self = Utils::OpenHandle(this);
2416 Utils::ApiCheck(self->status() >= i::Module::kLinked, "Module::Evaluate",
2417 "Expected instantiated module");
2418
2419 Local<Value> result;
2420 has_pending_exception = !ToLocal(i::Module::Evaluate(isolate, self), &result);
2421 RETURN_ON_FAILED_EXECUTION(Value);
2422 RETURN_ESCAPED(result);
2423 }
2424
CreateSyntheticModule(Isolate * isolate,Local<String> module_name,const std::vector<Local<v8::String>> & export_names,v8::Module::SyntheticModuleEvaluationSteps evaluation_steps)2425 Local<Module> Module::CreateSyntheticModule(
2426 Isolate* isolate, Local<String> module_name,
2427 const std::vector<Local<v8::String>>& export_names,
2428 v8::Module::SyntheticModuleEvaluationSteps evaluation_steps) {
2429 auto i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2430 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
2431 i::Handle<i::String> i_module_name = Utils::OpenHandle(*module_name);
2432 i::Handle<i::FixedArray> i_export_names = i_isolate->factory()->NewFixedArray(
2433 static_cast<int>(export_names.size()));
2434 for (int i = 0; i < i_export_names->length(); ++i) {
2435 i::Handle<i::String> str = i_isolate->factory()->InternalizeString(
2436 Utils::OpenHandle(*export_names[i]));
2437 i_export_names->set(i, *str);
2438 }
2439 return v8::Utils::ToLocal(
2440 i::Handle<i::Module>(i_isolate->factory()->NewSyntheticModule(
2441 i_module_name, i_export_names, evaluation_steps)));
2442 }
2443
SetSyntheticModuleExport(Isolate * isolate,Local<String> export_name,Local<v8::Value> export_value)2444 Maybe<bool> Module::SetSyntheticModuleExport(Isolate* isolate,
2445 Local<String> export_name,
2446 Local<v8::Value> export_value) {
2447 auto i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2448 i::Handle<i::String> i_export_name = Utils::OpenHandle(*export_name);
2449 i::Handle<i::Object> i_export_value = Utils::OpenHandle(*export_value);
2450 i::Handle<i::Module> self = Utils::OpenHandle(this);
2451 Utils::ApiCheck(self->IsSyntheticModule(),
2452 "v8::Module::SyntheticModuleSetExport",
2453 "v8::Module::SyntheticModuleSetExport must only be called on "
2454 "a SyntheticModule");
2455 ENTER_V8_NO_SCRIPT(i_isolate, isolate->GetCurrentContext(), Module,
2456 SetSyntheticModuleExport, Nothing<bool>(), i::HandleScope);
2457 has_pending_exception =
2458 i::SyntheticModule::SetExport(i_isolate,
2459 i::Handle<i::SyntheticModule>::cast(self),
2460 i_export_name, i_export_value)
2461 .IsNothing();
2462 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
2463 return Just(true);
2464 }
2465
2466 namespace {
2467
GetScriptDetails(i::Isolate * isolate,Local<Value> resource_name,int resource_line_offset,int resource_column_offset,Local<Value> source_map_url,Local<Data> host_defined_options,ScriptOriginOptions origin_options)2468 i::ScriptDetails GetScriptDetails(
2469 i::Isolate* isolate, Local<Value> resource_name, int resource_line_offset,
2470 int resource_column_offset, Local<Value> source_map_url,
2471 Local<Data> host_defined_options, ScriptOriginOptions origin_options) {
2472 i::ScriptDetails script_details(Utils::OpenHandle(*(resource_name), true),
2473 origin_options);
2474 script_details.line_offset = resource_line_offset;
2475 script_details.column_offset = resource_column_offset;
2476 script_details.host_defined_options =
2477 host_defined_options.IsEmpty()
2478 ? isolate->factory()->empty_fixed_array()
2479 : Utils::OpenHandle(*(host_defined_options));
2480 if (!source_map_url.IsEmpty()) {
2481 script_details.source_map_url = Utils::OpenHandle(*(source_map_url));
2482 }
2483 return script_details;
2484 }
2485
2486 } // namespace
2487
CompileUnboundInternal(Isolate * v8_isolate,Source * source,CompileOptions options,NoCacheReason no_cache_reason)2488 MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundInternal(
2489 Isolate* v8_isolate, Source* source, CompileOptions options,
2490 NoCacheReason no_cache_reason) {
2491 auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2492 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
2493 ENTER_V8_NO_SCRIPT(isolate, v8_isolate->GetCurrentContext(), ScriptCompiler,
2494 CompileUnbound, MaybeLocal<UnboundScript>(),
2495 InternalEscapableScope);
2496
2497 i::Handle<i::String> str = Utils::OpenHandle(*(source->source_string));
2498
2499 i::Handle<i::SharedFunctionInfo> result;
2500 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileScript");
2501 i::ScriptDetails script_details = GetScriptDetails(
2502 isolate, source->resource_name, source->resource_line_offset,
2503 source->resource_column_offset, source->source_map_url,
2504 source->host_defined_options, source->resource_options);
2505
2506 i::MaybeHandle<i::SharedFunctionInfo> maybe_function_info;
2507 if (options == kConsumeCodeCache) {
2508 if (source->consume_cache_task) {
2509 // Take ownership of the internal deserialization task and clear it off
2510 // the consume task on the source.
2511 DCHECK_NOT_NULL(source->consume_cache_task->impl_);
2512 std::unique_ptr<i::BackgroundDeserializeTask> deserialize_task =
2513 std::move(source->consume_cache_task->impl_);
2514 maybe_function_info =
2515 i::Compiler::GetSharedFunctionInfoForScriptWithDeserializeTask(
2516 isolate, str, script_details, deserialize_task.get(), options,
2517 no_cache_reason, i::NOT_NATIVES_CODE);
2518 source->cached_data->rejected = deserialize_task->rejected();
2519 } else {
2520 DCHECK(source->cached_data);
2521 // AlignedCachedData takes care of pointer-aligning the data.
2522 auto cached_data = std::make_unique<i::AlignedCachedData>(
2523 source->cached_data->data, source->cached_data->length);
2524 maybe_function_info =
2525 i::Compiler::GetSharedFunctionInfoForScriptWithCachedData(
2526 isolate, str, script_details, cached_data.get(), options,
2527 no_cache_reason, i::NOT_NATIVES_CODE);
2528 source->cached_data->rejected = cached_data->rejected();
2529 }
2530 } else {
2531 // Compile without any cache.
2532 maybe_function_info = i::Compiler::GetSharedFunctionInfoForScript(
2533 isolate, str, script_details, options, no_cache_reason,
2534 i::NOT_NATIVES_CODE);
2535 }
2536
2537 has_pending_exception = !maybe_function_info.ToHandle(&result);
2538 RETURN_ON_FAILED_EXECUTION(UnboundScript);
2539 RETURN_ESCAPED(ToApiHandle<UnboundScript>(result));
2540 }
2541
CompileUnboundScript(Isolate * v8_isolate,Source * source,CompileOptions options,NoCacheReason no_cache_reason)2542 MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundScript(
2543 Isolate* v8_isolate, Source* source, CompileOptions options,
2544 NoCacheReason no_cache_reason) {
2545 Utils::ApiCheck(
2546 !source->GetResourceOptions().IsModule(),
2547 "v8::ScriptCompiler::CompileUnboundScript",
2548 "v8::ScriptCompiler::CompileModule must be used to compile modules");
2549 return CompileUnboundInternal(v8_isolate, source, options, no_cache_reason);
2550 }
2551
Compile(Local<Context> context,Source * source,CompileOptions options,NoCacheReason no_cache_reason)2552 MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,
2553 Source* source,
2554 CompileOptions options,
2555 NoCacheReason no_cache_reason) {
2556 Utils::ApiCheck(
2557 !source->GetResourceOptions().IsModule(), "v8::ScriptCompiler::Compile",
2558 "v8::ScriptCompiler::CompileModule must be used to compile modules");
2559 auto isolate = context->GetIsolate();
2560 MaybeLocal<UnboundScript> maybe =
2561 CompileUnboundInternal(isolate, source, options, no_cache_reason);
2562 Local<UnboundScript> result;
2563 if (!maybe.ToLocal(&result)) return MaybeLocal<Script>();
2564 v8::Context::Scope scope(context);
2565 return result->BindToCurrentContext();
2566 }
2567
CompileModule(Isolate * isolate,Source * source,CompileOptions options,NoCacheReason no_cache_reason)2568 MaybeLocal<Module> ScriptCompiler::CompileModule(
2569 Isolate* isolate, Source* source, CompileOptions options,
2570 NoCacheReason no_cache_reason) {
2571 Utils::ApiCheck(options == kNoCompileOptions || options == kConsumeCodeCache,
2572 "v8::ScriptCompiler::CompileModule",
2573 "Invalid CompileOptions");
2574 Utils::ApiCheck(source->GetResourceOptions().IsModule(),
2575 "v8::ScriptCompiler::CompileModule",
2576 "Invalid ScriptOrigin: is_module must be true");
2577 MaybeLocal<UnboundScript> maybe =
2578 CompileUnboundInternal(isolate, source, options, no_cache_reason);
2579 Local<UnboundScript> unbound;
2580 if (!maybe.ToLocal(&unbound)) return MaybeLocal<Module>();
2581 i::Handle<i::SharedFunctionInfo> shared = Utils::OpenHandle(*unbound);
2582 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2583 return ToApiHandle<Module>(i_isolate->factory()->NewSourceTextModule(shared));
2584 }
2585
2586 // static
CompileFunction(Local<Context> context,Source * source,size_t arguments_count,Local<String> arguments[],size_t context_extension_count,Local<Object> context_extensions[],CompileOptions options,NoCacheReason no_cache_reason)2587 V8_WARN_UNUSED_RESULT MaybeLocal<Function> ScriptCompiler::CompileFunction(
2588 Local<Context> context, Source* source, size_t arguments_count,
2589 Local<String> arguments[], size_t context_extension_count,
2590 Local<Object> context_extensions[], CompileOptions options,
2591 NoCacheReason no_cache_reason) {
2592 return CompileFunctionInternal(context, source, arguments_count, arguments,
2593 context_extension_count, context_extensions,
2594 options, no_cache_reason, nullptr);
2595 }
2596
2597 // static
CompileFunctionInContext(Local<Context> context,Source * source,size_t arguments_count,Local<String> arguments[],size_t context_extension_count,Local<Object> context_extensions[],CompileOptions options,NoCacheReason no_cache_reason,Local<ScriptOrModule> * script_or_module_out)2598 MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext(
2599 Local<Context> context, Source* source, size_t arguments_count,
2600 Local<String> arguments[], size_t context_extension_count,
2601 Local<Object> context_extensions[], CompileOptions options,
2602 NoCacheReason no_cache_reason,
2603 Local<ScriptOrModule>* script_or_module_out) {
2604 return CompileFunctionInternal(
2605 context, source, arguments_count, arguments, context_extension_count,
2606 context_extensions, options, no_cache_reason, script_or_module_out);
2607 }
2608
CompileFunctionInternal(Local<Context> v8_context,Source * source,size_t arguments_count,Local<String> arguments[],size_t context_extension_count,Local<Object> context_extensions[],CompileOptions options,NoCacheReason no_cache_reason,Local<ScriptOrModule> * script_or_module_out)2609 MaybeLocal<Function> ScriptCompiler::CompileFunctionInternal(
2610 Local<Context> v8_context, Source* source, size_t arguments_count,
2611 Local<String> arguments[], size_t context_extension_count,
2612 Local<Object> context_extensions[], CompileOptions options,
2613 NoCacheReason no_cache_reason,
2614 Local<ScriptOrModule>* script_or_module_out) {
2615 Local<Function> result;
2616
2617 {
2618 PREPARE_FOR_EXECUTION(v8_context, ScriptCompiler, CompileFunction,
2619 Function);
2620 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
2621
2622 DCHECK(options == CompileOptions::kConsumeCodeCache ||
2623 options == CompileOptions::kEagerCompile ||
2624 options == CompileOptions::kNoCompileOptions);
2625
2626 i::Handle<i::Context> context = Utils::OpenHandle(*v8_context);
2627
2628 DCHECK(context->IsNativeContext());
2629
2630 i::Handle<i::FixedArray> arguments_list =
2631 isolate->factory()->NewFixedArray(static_cast<int>(arguments_count));
2632 for (int i = 0; i < static_cast<int>(arguments_count); i++) {
2633 i::Handle<i::String> argument = Utils::OpenHandle(*arguments[i]);
2634 if (!i::String::IsIdentifier(isolate, argument)) return Local<Function>();
2635 arguments_list->set(i, *argument);
2636 }
2637
2638 for (size_t i = 0; i < context_extension_count; ++i) {
2639 i::Handle<i::JSReceiver> extension =
2640 Utils::OpenHandle(*context_extensions[i]);
2641 if (!extension->IsJSObject()) return Local<Function>();
2642 context = isolate->factory()->NewWithContext(
2643 context,
2644 i::ScopeInfo::CreateForWithScope(
2645 isolate,
2646 context->IsNativeContext()
2647 ? i::Handle<i::ScopeInfo>::null()
2648 : i::Handle<i::ScopeInfo>(context->scope_info(), isolate)),
2649 extension);
2650 }
2651
2652 i::ScriptDetails script_details = GetScriptDetails(
2653 isolate, source->resource_name, source->resource_line_offset,
2654 source->resource_column_offset, source->source_map_url,
2655 source->host_defined_options, source->resource_options);
2656
2657 std::unique_ptr<i::AlignedCachedData> cached_data;
2658 if (options == kConsumeCodeCache) {
2659 DCHECK(source->cached_data);
2660 // ScriptData takes care of pointer-aligning the data.
2661 cached_data.reset(new i::AlignedCachedData(source->cached_data->data,
2662 source->cached_data->length));
2663 }
2664
2665 i::Handle<i::JSFunction> scoped_result;
2666 has_pending_exception =
2667 !i::Compiler::GetWrappedFunction(
2668 Utils::OpenHandle(*source->source_string), arguments_list, context,
2669 script_details, cached_data.get(), options, no_cache_reason)
2670 .ToHandle(&scoped_result);
2671 if (options == kConsumeCodeCache) {
2672 source->cached_data->rejected = cached_data->rejected();
2673 }
2674 RETURN_ON_FAILED_EXECUTION(Function);
2675 result = handle_scope.Escape(Utils::CallableToLocal(scoped_result));
2676 }
2677 // TODO(cbruni): remove script_or_module_out paramater
2678 if (script_or_module_out != nullptr) {
2679 i::Handle<i::JSFunction> function =
2680 i::Handle<i::JSFunction>::cast(Utils::OpenHandle(*result));
2681 i::Isolate* isolate = function->GetIsolate();
2682 i::Handle<i::SharedFunctionInfo> shared(function->shared(), isolate);
2683 i::Handle<i::Script> script(i::Script::cast(shared->script()), isolate);
2684 // TODO(cbruni, v8:12302): Avoid creating tempory ScriptOrModule objects.
2685 auto script_or_module = i::Handle<i::ScriptOrModule>::cast(
2686 isolate->factory()->NewStruct(i::SCRIPT_OR_MODULE_TYPE));
2687 script_or_module->set_resource_name(script->name());
2688 script_or_module->set_host_defined_options(script->host_defined_options());
2689 #ifdef V8_SCRIPTORMODULE_LEGACY_LIFETIME
2690 i::Handle<i::ArrayList> list =
2691 i::handle(script->script_or_modules(), isolate);
2692 list = i::ArrayList::Add(isolate, list, script_or_module);
2693 script->set_script_or_modules(*list);
2694 #endif // V8_SCRIPTORMODULE_LEGACY_LIFETIME
2695 *script_or_module_out = v8::Utils::ToLocal(script_or_module);
2696 }
2697 return result;
2698 }
2699
Run()2700 void ScriptCompiler::ScriptStreamingTask::Run() { data_->task->Run(); }
2701
StartStreaming(Isolate * v8_isolate,StreamedSource * source,v8::ScriptType type)2702 ScriptCompiler::ScriptStreamingTask* ScriptCompiler::StartStreaming(
2703 Isolate* v8_isolate, StreamedSource* source, v8::ScriptType type) {
2704 if (!i::FLAG_script_streaming) return nullptr;
2705 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2706 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2707 i::ScriptStreamingData* data = source->impl();
2708 std::unique_ptr<i::BackgroundCompileTask> task =
2709 std::make_unique<i::BackgroundCompileTask>(data, isolate, type);
2710 data->task = std::move(task);
2711 return new ScriptCompiler::ScriptStreamingTask(data);
2712 }
2713
ConsumeCodeCacheTask(std::unique_ptr<i::BackgroundDeserializeTask> impl)2714 ScriptCompiler::ConsumeCodeCacheTask::ConsumeCodeCacheTask(
2715 std::unique_ptr<i::BackgroundDeserializeTask> impl)
2716 : impl_(std::move(impl)) {}
2717
2718 ScriptCompiler::ConsumeCodeCacheTask::~ConsumeCodeCacheTask() = default;
2719
Run()2720 void ScriptCompiler::ConsumeCodeCacheTask::Run() { impl_->Run(); }
2721
StartConsumingCodeCache(Isolate * v8_isolate,std::unique_ptr<CachedData> cached_data)2722 ScriptCompiler::ConsumeCodeCacheTask* ScriptCompiler::StartConsumingCodeCache(
2723 Isolate* v8_isolate, std::unique_ptr<CachedData> cached_data) {
2724 if (!i::FLAG_concurrent_cache_deserialization) return nullptr;
2725 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2726 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2727 return new ScriptCompiler::ConsumeCodeCacheTask(
2728 std::make_unique<i::BackgroundDeserializeTask>(isolate,
2729 std::move(cached_data)));
2730 }
2731
2732 namespace {
CompileStreamedSource(i::Isolate * isolate,ScriptCompiler::StreamedSource * v8_source,Local<String> full_source_string,const ScriptOrigin & origin)2733 i::MaybeHandle<i::SharedFunctionInfo> CompileStreamedSource(
2734 i::Isolate* isolate, ScriptCompiler::StreamedSource* v8_source,
2735 Local<String> full_source_string, const ScriptOrigin& origin) {
2736 i::Handle<i::String> str = Utils::OpenHandle(*(full_source_string));
2737 i::ScriptDetails script_details =
2738 GetScriptDetails(isolate, origin.ResourceName(), origin.LineOffset(),
2739 origin.ColumnOffset(), origin.SourceMapUrl(),
2740 origin.GetHostDefinedOptions(), origin.Options());
2741 i::ScriptStreamingData* data = v8_source->impl();
2742 return i::Compiler::GetSharedFunctionInfoForStreamedScript(
2743 isolate, str, script_details, data);
2744 }
2745
2746 } // namespace
2747
Compile(Local<Context> context,StreamedSource * v8_source,Local<String> full_source_string,const ScriptOrigin & origin)2748 MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,
2749 StreamedSource* v8_source,
2750 Local<String> full_source_string,
2751 const ScriptOrigin& origin) {
2752 PREPARE_FOR_EXECUTION(context, ScriptCompiler, Compile, Script);
2753 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
2754 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
2755 "V8.CompileStreamedScript");
2756 i::Handle<i::SharedFunctionInfo> sfi;
2757 i::MaybeHandle<i::SharedFunctionInfo> maybe_sfi =
2758 CompileStreamedSource(isolate, v8_source, full_source_string, origin);
2759 has_pending_exception = !maybe_sfi.ToHandle(&sfi);
2760 if (has_pending_exception) isolate->ReportPendingMessages();
2761 RETURN_ON_FAILED_EXECUTION(Script);
2762 Local<UnboundScript> generic = ToApiHandle<UnboundScript>(sfi);
2763 if (generic.IsEmpty()) return Local<Script>();
2764 Local<Script> bound = generic->BindToCurrentContext();
2765 if (bound.IsEmpty()) return Local<Script>();
2766 RETURN_ESCAPED(bound);
2767 }
2768
CompileModule(Local<Context> context,StreamedSource * v8_source,Local<String> full_source_string,const ScriptOrigin & origin)2769 MaybeLocal<Module> ScriptCompiler::CompileModule(
2770 Local<Context> context, StreamedSource* v8_source,
2771 Local<String> full_source_string, const ScriptOrigin& origin) {
2772 PREPARE_FOR_EXECUTION(context, ScriptCompiler, Compile, Module);
2773 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
2774 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
2775 "V8.CompileStreamedModule");
2776 i::Handle<i::SharedFunctionInfo> sfi;
2777 i::MaybeHandle<i::SharedFunctionInfo> maybe_sfi =
2778 CompileStreamedSource(isolate, v8_source, full_source_string, origin);
2779 has_pending_exception = !maybe_sfi.ToHandle(&sfi);
2780 if (has_pending_exception) isolate->ReportPendingMessages();
2781 RETURN_ON_FAILED_EXECUTION(Module);
2782 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2783 RETURN_ESCAPED(
2784 ToApiHandle<Module>(i_isolate->factory()->NewSourceTextModule(sfi)));
2785 }
2786
CachedDataVersionTag()2787 uint32_t ScriptCompiler::CachedDataVersionTag() {
2788 return static_cast<uint32_t>(base::hash_combine(
2789 internal::Version::Hash(), internal::FlagList::Hash(),
2790 static_cast<uint32_t>(internal::CpuFeatures::SupportedFeatures())));
2791 }
2792
CreateCodeCache(Local<UnboundScript> unbound_script)2793 ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache(
2794 Local<UnboundScript> unbound_script) {
2795 i::Handle<i::SharedFunctionInfo> shared =
2796 i::Handle<i::SharedFunctionInfo>::cast(
2797 Utils::OpenHandle(*unbound_script));
2798 ASSERT_NO_SCRIPT_NO_EXCEPTION(shared->GetIsolate());
2799 DCHECK(shared->is_toplevel());
2800 return i::CodeSerializer::Serialize(shared);
2801 }
2802
2803 // static
CreateCodeCache(Local<UnboundModuleScript> unbound_module_script)2804 ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache(
2805 Local<UnboundModuleScript> unbound_module_script) {
2806 i::Handle<i::SharedFunctionInfo> shared =
2807 i::Handle<i::SharedFunctionInfo>::cast(
2808 Utils::OpenHandle(*unbound_module_script));
2809 ASSERT_NO_SCRIPT_NO_EXCEPTION(shared->GetIsolate());
2810 DCHECK(shared->is_toplevel());
2811 return i::CodeSerializer::Serialize(shared);
2812 }
2813
CreateCodeCacheForFunction(Local<Function> function)2814 ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCacheForFunction(
2815 Local<Function> function) {
2816 auto js_function =
2817 i::Handle<i::JSFunction>::cast(Utils::OpenHandle(*function));
2818 i::Handle<i::SharedFunctionInfo> shared(js_function->shared(),
2819 js_function->GetIsolate());
2820 ASSERT_NO_SCRIPT_NO_EXCEPTION(shared->GetIsolate());
2821 Utils::ApiCheck(shared->is_wrapped(),
2822 "v8::ScriptCompiler::CreateCodeCacheForFunction",
2823 "Expected SharedFunctionInfo with wrapped source code.");
2824 return i::CodeSerializer::Serialize(shared);
2825 }
2826
Compile(Local<Context> context,Local<String> source,ScriptOrigin * origin)2827 MaybeLocal<Script> Script::Compile(Local<Context> context, Local<String> source,
2828 ScriptOrigin* origin) {
2829 if (origin) {
2830 ScriptCompiler::Source script_source(source, *origin);
2831 return ScriptCompiler::Compile(context, &script_source);
2832 }
2833 ScriptCompiler::Source script_source(source);
2834 return ScriptCompiler::Compile(context, &script_source);
2835 }
2836
2837 // --- E x c e p t i o n s ---
2838
TryCatch(v8::Isolate * isolate)2839 v8::TryCatch::TryCatch(v8::Isolate* isolate)
2840 : isolate_(reinterpret_cast<i::Isolate*>(isolate)),
2841 next_(isolate_->try_catch_handler()),
2842 is_verbose_(false),
2843 can_continue_(true),
2844 capture_message_(true),
2845 rethrow_(false),
2846 has_terminated_(false) {
2847 ResetInternal();
2848 // Special handling for simulators which have a separate JS stack.
2849 js_stack_comparable_address_ = static_cast<internal::Address>(
2850 i::SimulatorStack::RegisterJSStackComparableAddress(isolate_));
2851 isolate_->RegisterTryCatchHandler(this);
2852 }
2853
~TryCatch()2854 v8::TryCatch::~TryCatch() {
2855 if (rethrow_) {
2856 v8::Isolate* isolate = reinterpret_cast<Isolate*>(isolate_);
2857 v8::HandleScope scope(isolate);
2858 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(isolate, Exception());
2859 if (HasCaught() && capture_message_) {
2860 // If an exception was caught and rethrow_ is indicated, the saved
2861 // message, script, and location need to be restored to Isolate TLS
2862 // for reuse. capture_message_ needs to be disabled so that Throw()
2863 // does not create a new message.
2864 isolate_->thread_local_top()->rethrowing_message_ = true;
2865 isolate_->RestorePendingMessageFromTryCatch(this);
2866 }
2867 isolate_->UnregisterTryCatchHandler(this);
2868 i::SimulatorStack::UnregisterJSStackComparableAddress(isolate_);
2869 reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc);
2870 DCHECK(!isolate_->thread_local_top()->rethrowing_message_);
2871 } else {
2872 if (HasCaught() && isolate_->has_scheduled_exception()) {
2873 // If an exception was caught but is still scheduled because no API call
2874 // promoted it, then it is canceled to prevent it from being propagated.
2875 // Note that this will not cancel termination exceptions.
2876 isolate_->CancelScheduledExceptionFromTryCatch(this);
2877 }
2878 isolate_->UnregisterTryCatchHandler(this);
2879 i::SimulatorStack::UnregisterJSStackComparableAddress(isolate_);
2880 }
2881 }
2882
operator new(size_t)2883 void* v8::TryCatch::operator new(size_t) { base::OS::Abort(); }
operator new[](size_t)2884 void* v8::TryCatch::operator new[](size_t) { base::OS::Abort(); }
operator delete(void *,size_t)2885 void v8::TryCatch::operator delete(void*, size_t) { base::OS::Abort(); }
operator delete[](void *,size_t)2886 void v8::TryCatch::operator delete[](void*, size_t) { base::OS::Abort(); }
2887
HasCaught() const2888 bool v8::TryCatch::HasCaught() const {
2889 return !i::Object(reinterpret_cast<i::Address>(exception_))
2890 .IsTheHole(isolate_);
2891 }
2892
CanContinue() const2893 bool v8::TryCatch::CanContinue() const { return can_continue_; }
2894
HasTerminated() const2895 bool v8::TryCatch::HasTerminated() const { return has_terminated_; }
2896
ReThrow()2897 v8::Local<v8::Value> v8::TryCatch::ReThrow() {
2898 if (!HasCaught()) return v8::Local<v8::Value>();
2899 rethrow_ = true;
2900 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_));
2901 }
2902
Exception() const2903 v8::Local<Value> v8::TryCatch::Exception() const {
2904 if (HasCaught()) {
2905 // Check for out of memory exception.
2906 i::Object exception(reinterpret_cast<i::Address>(exception_));
2907 return v8::Utils::ToLocal(i::Handle<i::Object>(exception, isolate_));
2908 } else {
2909 return v8::Local<Value>();
2910 }
2911 }
2912
StackTrace(Local<Context> context,Local<Value> exception)2913 MaybeLocal<Value> v8::TryCatch::StackTrace(Local<Context> context,
2914 Local<Value> exception) {
2915 i::Handle<i::Object> i_exception = Utils::OpenHandle(*exception);
2916 if (!i_exception->IsJSObject()) return v8::Local<Value>();
2917 PREPARE_FOR_EXECUTION(context, TryCatch, StackTrace, Value);
2918 auto obj = i::Handle<i::JSObject>::cast(i_exception);
2919 i::Handle<i::String> name = isolate->factory()->stack_string();
2920 Maybe<bool> maybe = i::JSReceiver::HasProperty(isolate, obj, name);
2921 has_pending_exception = maybe.IsNothing();
2922 RETURN_ON_FAILED_EXECUTION(Value);
2923 if (!maybe.FromJust()) return v8::Local<Value>();
2924 Local<Value> result;
2925 has_pending_exception =
2926 !ToLocal<Value>(i::JSReceiver::GetProperty(isolate, obj, name), &result);
2927 RETURN_ON_FAILED_EXECUTION(Value);
2928 RETURN_ESCAPED(result);
2929 }
2930
StackTrace(Local<Context> context) const2931 MaybeLocal<Value> v8::TryCatch::StackTrace(Local<Context> context) const {
2932 if (!HasCaught()) return v8::Local<Value>();
2933 return StackTrace(context, Exception());
2934 }
2935
Message() const2936 v8::Local<v8::Message> v8::TryCatch::Message() const {
2937 i::Object message(reinterpret_cast<i::Address>(message_obj_));
2938 DCHECK(message.IsJSMessageObject() || message.IsTheHole(isolate_));
2939 if (HasCaught() && !message.IsTheHole(isolate_)) {
2940 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_));
2941 } else {
2942 return v8::Local<v8::Message>();
2943 }
2944 }
2945
Reset()2946 void v8::TryCatch::Reset() {
2947 if (!rethrow_ && HasCaught() && isolate_->has_scheduled_exception()) {
2948 // If an exception was caught but is still scheduled because no API call
2949 // promoted it, then it is canceled to prevent it from being propagated.
2950 // Note that this will not cancel termination exceptions.
2951 isolate_->CancelScheduledExceptionFromTryCatch(this);
2952 }
2953 ResetInternal();
2954 }
2955
ResetInternal()2956 void v8::TryCatch::ResetInternal() {
2957 i::Object the_hole = i::ReadOnlyRoots(isolate_).the_hole_value();
2958 exception_ = reinterpret_cast<void*>(the_hole.ptr());
2959 message_obj_ = reinterpret_cast<void*>(the_hole.ptr());
2960 }
2961
SetVerbose(bool value)2962 void v8::TryCatch::SetVerbose(bool value) { is_verbose_ = value; }
2963
IsVerbose() const2964 bool v8::TryCatch::IsVerbose() const { return is_verbose_; }
2965
SetCaptureMessage(bool value)2966 void v8::TryCatch::SetCaptureMessage(bool value) { capture_message_ = value; }
2967
2968 // --- M e s s a g e ---
2969
Get() const2970 Local<String> Message::Get() const {
2971 auto self = Utils::OpenHandle(this);
2972 i::Isolate* isolate = self->GetIsolate();
2973 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2974 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2975 i::Handle<i::String> raw_result =
2976 i::MessageHandler::GetMessage(isolate, self);
2977 Local<String> result = Utils::ToLocal(raw_result);
2978 return scope.Escape(result);
2979 }
2980
GetIsolate() const2981 v8::Isolate* Message::GetIsolate() const {
2982 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2983 return reinterpret_cast<Isolate*>(isolate);
2984 }
2985
GetScriptOrigin() const2986 ScriptOrigin Message::GetScriptOrigin() const {
2987 auto self = Utils::OpenHandle(this);
2988 i::Isolate* isolate = self->GetIsolate();
2989 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2990 i::Handle<i::Script> script(self->script(), isolate);
2991 return GetScriptOriginForScript(isolate, script);
2992 }
2993
VerifyHostDefinedOptions() const2994 void ScriptOrigin::VerifyHostDefinedOptions() const {
2995 // TODO(cbruni, chromium:1244145): Remove checks once we allow arbitrary
2996 // host-defined options.
2997 USE(isolate_);
2998 if (host_defined_options_.IsEmpty()) return;
2999 Utils::ApiCheck(host_defined_options_->IsFixedArray(), "ScriptOrigin()",
3000 "Host-defined options has to be a PrimitiveArray");
3001 i::Handle<i::FixedArray> options =
3002 Utils::OpenHandle(*host_defined_options_.As<FixedArray>());
3003 for (int i = 0; i < options->length(); i++) {
3004 Utils::ApiCheck(options->get(i).IsPrimitive(), "ScriptOrigin()",
3005 "PrimitiveArray can only contain primtive values");
3006 }
3007 }
3008
GetScriptResourceName() const3009 v8::Local<Value> Message::GetScriptResourceName() const {
3010 ASSERT_NO_SCRIPT_NO_EXCEPTION(Utils::OpenHandle(this)->GetIsolate());
3011 return GetScriptOrigin().ResourceName();
3012 }
3013
GetStackTrace() const3014 v8::Local<v8::StackTrace> Message::GetStackTrace() const {
3015 auto self = Utils::OpenHandle(this);
3016 i::Isolate* isolate = self->GetIsolate();
3017 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3018 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
3019 i::Handle<i::Object> stackFramesObj(self->stack_frames(), isolate);
3020 if (!stackFramesObj->IsFixedArray()) return v8::Local<v8::StackTrace>();
3021 auto stackTrace = i::Handle<i::FixedArray>::cast(stackFramesObj);
3022 return scope.Escape(Utils::StackTraceToLocal(stackTrace));
3023 }
3024
GetLineNumber(Local<Context> context) const3025 Maybe<int> Message::GetLineNumber(Local<Context> context) const {
3026 auto self = Utils::OpenHandle(this);
3027 i::Isolate* isolate = self->GetIsolate();
3028 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3029 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3030 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3031 return Just(self->GetLineNumber());
3032 }
3033
GetStartPosition() const3034 int Message::GetStartPosition() const {
3035 auto self = Utils::OpenHandle(this);
3036 i::Isolate* isolate = self->GetIsolate();
3037 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3038 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3039 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3040 return self->GetStartPosition();
3041 }
3042
GetEndPosition() const3043 int Message::GetEndPosition() const {
3044 auto self = Utils::OpenHandle(this);
3045 i::Isolate* isolate = self->GetIsolate();
3046 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3047 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3048 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3049 return self->GetEndPosition();
3050 }
3051
ErrorLevel() const3052 int Message::ErrorLevel() const {
3053 auto self = Utils::OpenHandle(this);
3054 ASSERT_NO_SCRIPT_NO_EXCEPTION(self->GetIsolate());
3055 return self->error_level();
3056 }
3057
GetStartColumn() const3058 int Message::GetStartColumn() const {
3059 auto self = Utils::OpenHandle(this);
3060 i::Isolate* isolate = self->GetIsolate();
3061 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3062 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3063 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3064 return self->GetColumnNumber();
3065 }
3066
GetWasmFunctionIndex() const3067 int Message::GetWasmFunctionIndex() const {
3068 #if V8_ENABLE_WEBASSEMBLY
3069 auto self = Utils::OpenHandle(this);
3070 i::Isolate* isolate = self->GetIsolate();
3071 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3072 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3073 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3074 int start_position = self->GetColumnNumber();
3075 if (start_position == -1) return Message::kNoWasmFunctionIndexInfo;
3076
3077 i::Handle<i::Script> script(self->script(), isolate);
3078
3079 if (script->type() != i::Script::TYPE_WASM) {
3080 return Message::kNoWasmFunctionIndexInfo;
3081 }
3082
3083 auto debug_script = ToApiHandle<debug::Script>(script);
3084 return Local<debug::WasmScript>::Cast(debug_script)
3085 ->GetContainingFunction(start_position);
3086 #else
3087 return Message::kNoWasmFunctionIndexInfo;
3088 #endif // V8_ENABLE_WEBASSEMBLY
3089 }
3090
GetStartColumn(Local<Context> context) const3091 Maybe<int> Message::GetStartColumn(Local<Context> context) const {
3092 return Just(GetStartColumn());
3093 }
3094
GetEndColumn() const3095 int Message::GetEndColumn() const {
3096 auto self = Utils::OpenHandle(this);
3097 i::Isolate* isolate = self->GetIsolate();
3098 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3099 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3100 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3101 const int column_number = self->GetColumnNumber();
3102 if (column_number == -1) return -1;
3103 const int start = self->GetStartPosition();
3104 const int end = self->GetEndPosition();
3105 return column_number + (end - start);
3106 }
3107
GetEndColumn(Local<Context> context) const3108 Maybe<int> Message::GetEndColumn(Local<Context> context) const {
3109 return Just(GetEndColumn());
3110 }
3111
IsSharedCrossOrigin() const3112 bool Message::IsSharedCrossOrigin() const {
3113 auto self = Utils::OpenHandle(this);
3114 i::Isolate* isolate = self->GetIsolate();
3115 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3116 return self->script().origin_options().IsSharedCrossOrigin();
3117 }
3118
IsOpaque() const3119 bool Message::IsOpaque() const {
3120 auto self = Utils::OpenHandle(this);
3121 i::Isolate* isolate = self->GetIsolate();
3122 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3123 return self->script().origin_options().IsOpaque();
3124 }
3125
GetSource(Local<Context> context) const3126 MaybeLocal<String> Message::GetSource(Local<Context> context) const {
3127 auto self = Utils::OpenHandle(this);
3128 i::Isolate* isolate = self->GetIsolate();
3129 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3130 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3131 i::Handle<i::String> source(self->GetSource(), isolate);
3132 RETURN_ESCAPED(Utils::ToLocal(source));
3133 }
3134
GetSourceLine(Local<Context> context) const3135 MaybeLocal<String> Message::GetSourceLine(Local<Context> context) const {
3136 auto self = Utils::OpenHandle(this);
3137 i::Isolate* isolate = self->GetIsolate();
3138 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3139 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3140 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3141 RETURN_ESCAPED(Utils::ToLocal(self->GetSourceLine()));
3142 }
3143
PrintCurrentStackTrace(Isolate * isolate,std::ostream & out)3144 void Message::PrintCurrentStackTrace(Isolate* isolate, std::ostream& out) {
3145 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
3146 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
3147 i_isolate->PrintCurrentStackTrace(out);
3148 }
3149
3150 // --- S t a c k T r a c e ---
3151
GetFrame(Isolate * v8_isolate,uint32_t index) const3152 Local<StackFrame> StackTrace::GetFrame(Isolate* v8_isolate,
3153 uint32_t index) const {
3154 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3155 i::Handle<i::StackFrameInfo> info(
3156 i::StackFrameInfo::cast(Utils::OpenHandle(this)->get(index)), isolate);
3157 return Utils::StackFrameToLocal(info);
3158 }
3159
GetFrameCount() const3160 int StackTrace::GetFrameCount() const {
3161 return Utils::OpenHandle(this)->length();
3162 }
3163
CurrentStackTrace(Isolate * isolate,int frame_limit,StackTraceOptions options)3164 Local<StackTrace> StackTrace::CurrentStackTrace(Isolate* isolate,
3165 int frame_limit,
3166 StackTraceOptions options) {
3167 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
3168 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
3169 i::Handle<i::FixedArray> stackTrace =
3170 i_isolate->CaptureDetailedStackTrace(frame_limit, options);
3171 return Utils::StackTraceToLocal(stackTrace);
3172 }
3173
CurrentScriptNameOrSourceURL(Isolate * v8_isolate)3174 Local<String> StackTrace::CurrentScriptNameOrSourceURL(Isolate* v8_isolate) {
3175 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3176 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3177 i::Handle<i::String> name_or_source_url =
3178 isolate->CurrentScriptNameOrSourceURL();
3179 return Utils::ToLocal(name_or_source_url);
3180 }
3181
3182 // --- S t a c k F r a m e ---
3183
GetLocation() const3184 Location StackFrame::GetLocation() const {
3185 i::Handle<i::StackFrameInfo> self = Utils::OpenHandle(this);
3186 i::Isolate* isolate = self->GetIsolate();
3187 i::Handle<i::Script> script(self->script(), isolate);
3188 i::Script::PositionInfo info;
3189 CHECK(i::Script::GetPositionInfo(script,
3190 i::StackFrameInfo::GetSourcePosition(self),
3191 &info, i::Script::WITH_OFFSET));
3192 if (script->HasSourceURLComment()) {
3193 info.line -= script->line_offset();
3194 if (info.line == 0) {
3195 info.column -= script->column_offset();
3196 }
3197 }
3198 return {info.line, info.column};
3199 }
3200
GetScriptId() const3201 int StackFrame::GetScriptId() const {
3202 return Utils::OpenHandle(this)->script().id();
3203 }
3204
GetScriptName() const3205 Local<String> StackFrame::GetScriptName() const {
3206 i::Handle<i::StackFrameInfo> self = Utils::OpenHandle(this);
3207 i::Isolate* isolate = self->GetIsolate();
3208 i::Handle<i::Object> name(self->script().name(), isolate);
3209 if (!name->IsString()) return {};
3210 return Utils::ToLocal(i::Handle<i::String>::cast(name));
3211 }
3212
GetScriptNameOrSourceURL() const3213 Local<String> StackFrame::GetScriptNameOrSourceURL() const {
3214 i::Handle<i::StackFrameInfo> self = Utils::OpenHandle(this);
3215 i::Isolate* isolate = self->GetIsolate();
3216 i::Handle<i::Object> name_or_source_url(self->script().GetNameOrSourceURL(),
3217 isolate);
3218 if (!name_or_source_url->IsString()) return {};
3219 return Utils::ToLocal(i::Handle<i::String>::cast(name_or_source_url));
3220 }
3221
GetScriptSource() const3222 Local<String> StackFrame::GetScriptSource() const {
3223 i::Handle<i::StackFrameInfo> self = Utils::OpenHandle(this);
3224 i::Isolate* isolate = self->GetIsolate();
3225 if (!self->script().HasValidSource()) return {};
3226 i::Handle<i::PrimitiveHeapObject> source(self->script().source(), isolate);
3227 if (!source->IsString()) return {};
3228 return Utils::ToLocal(i::Handle<i::String>::cast(source));
3229 }
3230
GetScriptSourceMappingURL() const3231 Local<String> StackFrame::GetScriptSourceMappingURL() const {
3232 i::Handle<i::StackFrameInfo> self = Utils::OpenHandle(this);
3233 i::Isolate* isolate = self->GetIsolate();
3234 i::Handle<i::Object> source_mapping_url(self->script().source_mapping_url(),
3235 isolate);
3236 if (!source_mapping_url->IsString()) return {};
3237 return Utils::ToLocal(i::Handle<i::String>::cast(source_mapping_url));
3238 }
3239
GetFunctionName() const3240 Local<String> StackFrame::GetFunctionName() const {
3241 i::Handle<i::StackFrameInfo> self = Utils::OpenHandle(this);
3242 i::Isolate* isolate = self->GetIsolate();
3243 i::Handle<i::String> name(self->function_name(), isolate);
3244 if (name->length() == 0) return {};
3245 return Utils::ToLocal(name);
3246 }
3247
IsEval() const3248 bool StackFrame::IsEval() const {
3249 i::Handle<i::StackFrameInfo> self = Utils::OpenHandle(this);
3250 return self->script().compilation_type() == i::Script::COMPILATION_TYPE_EVAL;
3251 }
3252
IsConstructor() const3253 bool StackFrame::IsConstructor() const {
3254 return Utils::OpenHandle(this)->is_constructor();
3255 }
3256
IsWasm() const3257 bool StackFrame::IsWasm() const { return !IsUserJavaScript(); }
3258
IsUserJavaScript() const3259 bool StackFrame::IsUserJavaScript() const {
3260 return Utils::OpenHandle(this)->script().IsUserJavaScript();
3261 }
3262
3263 // --- J S O N ---
3264
Parse(Local<Context> context,Local<String> json_string)3265 MaybeLocal<Value> JSON::Parse(Local<Context> context,
3266 Local<String> json_string) {
3267 PREPARE_FOR_EXECUTION(context, JSON, Parse, Value);
3268 i::Handle<i::String> string = Utils::OpenHandle(*json_string);
3269 i::Handle<i::String> source = i::String::Flatten(isolate, string);
3270 i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
3271 auto maybe = source->IsOneByteRepresentation()
3272 ? i::JsonParser<uint8_t>::Parse(isolate, source, undefined)
3273 : i::JsonParser<uint16_t>::Parse(isolate, source, undefined);
3274 Local<Value> result;
3275 has_pending_exception = !ToLocal<Value>(maybe, &result);
3276 RETURN_ON_FAILED_EXECUTION(Value);
3277 RETURN_ESCAPED(result);
3278 }
3279
Stringify(Local<Context> context,Local<Value> json_object,Local<String> gap)3280 MaybeLocal<String> JSON::Stringify(Local<Context> context,
3281 Local<Value> json_object,
3282 Local<String> gap) {
3283 PREPARE_FOR_EXECUTION(context, JSON, Stringify, String);
3284 i::Handle<i::Object> object = Utils::OpenHandle(*json_object);
3285 i::Handle<i::Object> replacer = isolate->factory()->undefined_value();
3286 i::Handle<i::String> gap_string = gap.IsEmpty()
3287 ? isolate->factory()->empty_string()
3288 : Utils::OpenHandle(*gap);
3289 i::Handle<i::Object> maybe;
3290 has_pending_exception =
3291 !i::JsonStringify(isolate, object, replacer, gap_string).ToHandle(&maybe);
3292 RETURN_ON_FAILED_EXECUTION(String);
3293 Local<String> result;
3294 has_pending_exception =
3295 !ToLocal<String>(i::Object::ToString(isolate, maybe), &result);
3296 RETURN_ON_FAILED_EXECUTION(String);
3297 RETURN_ESCAPED(result);
3298 }
3299
3300 // --- V a l u e S e r i a l i z a t i o n ---
3301
WriteHostObject(Isolate * v8_isolate,Local<Object> object)3302 Maybe<bool> ValueSerializer::Delegate::WriteHostObject(Isolate* v8_isolate,
3303 Local<Object> object) {
3304 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3305 isolate->ScheduleThrow(*isolate->factory()->NewError(
3306 isolate->error_function(), i::MessageTemplate::kDataCloneError,
3307 Utils::OpenHandle(*object)));
3308 return Nothing<bool>();
3309 }
3310
GetSharedArrayBufferId(Isolate * v8_isolate,Local<SharedArrayBuffer> shared_array_buffer)3311 Maybe<uint32_t> ValueSerializer::Delegate::GetSharedArrayBufferId(
3312 Isolate* v8_isolate, Local<SharedArrayBuffer> shared_array_buffer) {
3313 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3314 isolate->ScheduleThrow(*isolate->factory()->NewError(
3315 isolate->error_function(), i::MessageTemplate::kDataCloneError,
3316 Utils::OpenHandle(*shared_array_buffer)));
3317 return Nothing<uint32_t>();
3318 }
3319
GetWasmModuleTransferId(Isolate * v8_isolate,Local<WasmModuleObject> module)3320 Maybe<uint32_t> ValueSerializer::Delegate::GetWasmModuleTransferId(
3321 Isolate* v8_isolate, Local<WasmModuleObject> module) {
3322 return Nothing<uint32_t>();
3323 }
3324
SupportsSharedValues() const3325 bool ValueSerializer::Delegate::SupportsSharedValues() const { return false; }
3326
GetSharedValueId(Isolate * v8_isolate,Local<Value> shared_value)3327 Maybe<uint32_t> ValueSerializer::Delegate::GetSharedValueId(
3328 Isolate* v8_isolate, Local<Value> shared_value) {
3329 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3330 isolate->ScheduleThrow(*isolate->factory()->NewError(
3331 isolate->error_function(), i::MessageTemplate::kDataCloneError,
3332 Utils::OpenHandle(*shared_value)));
3333 return Nothing<uint32_t>();
3334 }
3335
ReallocateBufferMemory(void * old_buffer,size_t size,size_t * actual_size)3336 void* ValueSerializer::Delegate::ReallocateBufferMemory(void* old_buffer,
3337 size_t size,
3338 size_t* actual_size) {
3339 *actual_size = size;
3340 return base::Realloc(old_buffer, size);
3341 }
3342
FreeBufferMemory(void * buffer)3343 void ValueSerializer::Delegate::FreeBufferMemory(void* buffer) {
3344 return base::Free(buffer);
3345 }
3346
3347 struct ValueSerializer::PrivateData {
PrivateDatav8::ValueSerializer::PrivateData3348 explicit PrivateData(i::Isolate* i, ValueSerializer::Delegate* delegate)
3349 : isolate(i), serializer(i, delegate) {}
3350 i::Isolate* isolate;
3351 i::ValueSerializer serializer;
3352 };
3353
ValueSerializer(Isolate * isolate)3354 ValueSerializer::ValueSerializer(Isolate* isolate)
3355 : ValueSerializer(isolate, nullptr) {}
3356
ValueSerializer(Isolate * isolate,Delegate * delegate)3357 ValueSerializer::ValueSerializer(Isolate* isolate, Delegate* delegate)
3358 : private_(
3359 new PrivateData(reinterpret_cast<i::Isolate*>(isolate), delegate)) {}
3360
~ValueSerializer()3361 ValueSerializer::~ValueSerializer() { delete private_; }
3362
WriteHeader()3363 void ValueSerializer::WriteHeader() { private_->serializer.WriteHeader(); }
3364
SetTreatArrayBufferViewsAsHostObjects(bool mode)3365 void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) {
3366 private_->serializer.SetTreatArrayBufferViewsAsHostObjects(mode);
3367 }
3368
WriteValue(Local<Context> context,Local<Value> value)3369 Maybe<bool> ValueSerializer::WriteValue(Local<Context> context,
3370 Local<Value> value) {
3371 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
3372 ENTER_V8(isolate, context, ValueSerializer, WriteValue, Nothing<bool>(),
3373 i::HandleScope);
3374 i::Handle<i::Object> object = Utils::OpenHandle(*value);
3375 Maybe<bool> result = private_->serializer.WriteObject(object);
3376 has_pending_exception = result.IsNothing();
3377 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
3378 return result;
3379 }
3380
Release()3381 std::pair<uint8_t*, size_t> ValueSerializer::Release() {
3382 return private_->serializer.Release();
3383 }
3384
TransferArrayBuffer(uint32_t transfer_id,Local<ArrayBuffer> array_buffer)3385 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id,
3386 Local<ArrayBuffer> array_buffer) {
3387 private_->serializer.TransferArrayBuffer(transfer_id,
3388 Utils::OpenHandle(*array_buffer));
3389 }
3390
WriteUint32(uint32_t value)3391 void ValueSerializer::WriteUint32(uint32_t value) {
3392 private_->serializer.WriteUint32(value);
3393 }
3394
WriteUint64(uint64_t value)3395 void ValueSerializer::WriteUint64(uint64_t value) {
3396 private_->serializer.WriteUint64(value);
3397 }
3398
WriteDouble(double value)3399 void ValueSerializer::WriteDouble(double value) {
3400 private_->serializer.WriteDouble(value);
3401 }
3402
WriteRawBytes(const void * source,size_t length)3403 void ValueSerializer::WriteRawBytes(const void* source, size_t length) {
3404 private_->serializer.WriteRawBytes(source, length);
3405 }
3406
ReadHostObject(Isolate * v8_isolate)3407 MaybeLocal<Object> ValueDeserializer::Delegate::ReadHostObject(
3408 Isolate* v8_isolate) {
3409 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3410 isolate->ScheduleThrow(*isolate->factory()->NewError(
3411 isolate->error_function(),
3412 i::MessageTemplate::kDataCloneDeserializationError));
3413 return MaybeLocal<Object>();
3414 }
3415
GetWasmModuleFromId(Isolate * v8_isolate,uint32_t id)3416 MaybeLocal<WasmModuleObject> ValueDeserializer::Delegate::GetWasmModuleFromId(
3417 Isolate* v8_isolate, uint32_t id) {
3418 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3419 isolate->ScheduleThrow(*isolate->factory()->NewError(
3420 isolate->error_function(),
3421 i::MessageTemplate::kDataCloneDeserializationError));
3422 return MaybeLocal<WasmModuleObject>();
3423 }
3424
SupportsSharedValues() const3425 bool ValueDeserializer::Delegate::SupportsSharedValues() const { return false; }
3426
GetSharedValueFromId(Isolate * v8_isolate,uint32_t shared_value_id)3427 MaybeLocal<Value> ValueDeserializer::Delegate::GetSharedValueFromId(
3428 Isolate* v8_isolate, uint32_t shared_value_id) {
3429 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3430 isolate->ScheduleThrow(*isolate->factory()->NewError(
3431 isolate->error_function(),
3432 i::MessageTemplate::kDataCloneDeserializationError));
3433 return MaybeLocal<Value>();
3434 }
3435
3436 MaybeLocal<SharedArrayBuffer>
GetSharedArrayBufferFromId(Isolate * v8_isolate,uint32_t id)3437 ValueDeserializer::Delegate::GetSharedArrayBufferFromId(Isolate* v8_isolate,
3438 uint32_t id) {
3439 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3440 isolate->ScheduleThrow(*isolate->factory()->NewError(
3441 isolate->error_function(),
3442 i::MessageTemplate::kDataCloneDeserializationError));
3443 return MaybeLocal<SharedArrayBuffer>();
3444 }
3445
3446 struct ValueDeserializer::PrivateData {
PrivateDatav8::ValueDeserializer::PrivateData3447 PrivateData(i::Isolate* i, base::Vector<const uint8_t> data,
3448 Delegate* delegate)
3449 : isolate(i), deserializer(i, data, delegate) {}
3450 i::Isolate* isolate;
3451 i::ValueDeserializer deserializer;
3452 bool supports_legacy_wire_format = false;
3453 };
3454
ValueDeserializer(Isolate * isolate,const uint8_t * data,size_t size)3455 ValueDeserializer::ValueDeserializer(Isolate* isolate, const uint8_t* data,
3456 size_t size)
3457 : ValueDeserializer(isolate, data, size, nullptr) {}
3458
ValueDeserializer(Isolate * isolate,const uint8_t * data,size_t size,Delegate * delegate)3459 ValueDeserializer::ValueDeserializer(Isolate* isolate, const uint8_t* data,
3460 size_t size, Delegate* delegate) {
3461 private_ = new PrivateData(reinterpret_cast<i::Isolate*>(isolate),
3462 base::Vector<const uint8_t>(data, size), delegate);
3463 }
3464
~ValueDeserializer()3465 ValueDeserializer::~ValueDeserializer() { delete private_; }
3466
ReadHeader(Local<Context> context)3467 Maybe<bool> ValueDeserializer::ReadHeader(Local<Context> context) {
3468 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
3469 ENTER_V8_NO_SCRIPT(isolate, context, ValueDeserializer, ReadHeader,
3470 Nothing<bool>(), i::HandleScope);
3471
3472 bool read_header = false;
3473 has_pending_exception = !private_->deserializer.ReadHeader().To(&read_header);
3474 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
3475 DCHECK(read_header);
3476
3477 static const uint32_t kMinimumNonLegacyVersion = 13;
3478 if (GetWireFormatVersion() < kMinimumNonLegacyVersion &&
3479 !private_->supports_legacy_wire_format) {
3480 isolate->Throw(*isolate->factory()->NewError(
3481 i::MessageTemplate::kDataCloneDeserializationVersionError));
3482 has_pending_exception = true;
3483 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
3484 }
3485
3486 return Just(true);
3487 }
3488
SetSupportsLegacyWireFormat(bool supports_legacy_wire_format)3489 void ValueDeserializer::SetSupportsLegacyWireFormat(
3490 bool supports_legacy_wire_format) {
3491 private_->supports_legacy_wire_format = supports_legacy_wire_format;
3492 }
3493
GetWireFormatVersion() const3494 uint32_t ValueDeserializer::GetWireFormatVersion() const {
3495 return private_->deserializer.GetWireFormatVersion();
3496 }
3497
ReadValue(Local<Context> context)3498 MaybeLocal<Value> ValueDeserializer::ReadValue(Local<Context> context) {
3499 PREPARE_FOR_EXECUTION(context, ValueDeserializer, ReadValue, Value);
3500 i::MaybeHandle<i::Object> result;
3501 if (GetWireFormatVersion() > 0) {
3502 result = private_->deserializer.ReadObjectWrapper();
3503 } else {
3504 result =
3505 private_->deserializer.ReadObjectUsingEntireBufferForLegacyFormat();
3506 }
3507 Local<Value> value;
3508 has_pending_exception = !ToLocal(result, &value);
3509 RETURN_ON_FAILED_EXECUTION(Value);
3510 RETURN_ESCAPED(value);
3511 }
3512
TransferArrayBuffer(uint32_t transfer_id,Local<ArrayBuffer> array_buffer)3513 void ValueDeserializer::TransferArrayBuffer(uint32_t transfer_id,
3514 Local<ArrayBuffer> array_buffer) {
3515 private_->deserializer.TransferArrayBuffer(transfer_id,
3516 Utils::OpenHandle(*array_buffer));
3517 }
3518
TransferSharedArrayBuffer(uint32_t transfer_id,Local<SharedArrayBuffer> shared_array_buffer)3519 void ValueDeserializer::TransferSharedArrayBuffer(
3520 uint32_t transfer_id, Local<SharedArrayBuffer> shared_array_buffer) {
3521 private_->deserializer.TransferArrayBuffer(
3522 transfer_id, Utils::OpenHandle(*shared_array_buffer));
3523 }
3524
ReadUint32(uint32_t * value)3525 bool ValueDeserializer::ReadUint32(uint32_t* value) {
3526 return private_->deserializer.ReadUint32(value);
3527 }
3528
ReadUint64(uint64_t * value)3529 bool ValueDeserializer::ReadUint64(uint64_t* value) {
3530 return private_->deserializer.ReadUint64(value);
3531 }
3532
ReadDouble(double * value)3533 bool ValueDeserializer::ReadDouble(double* value) {
3534 return private_->deserializer.ReadDouble(value);
3535 }
3536
ReadRawBytes(size_t length,const void ** data)3537 bool ValueDeserializer::ReadRawBytes(size_t length, const void** data) {
3538 return private_->deserializer.ReadRawBytes(length, data);
3539 }
3540
3541 // --- D a t a ---
3542
FullIsUndefined() const3543 bool Value::FullIsUndefined() const {
3544 i::Handle<i::Object> object = Utils::OpenHandle(this);
3545 bool result = object->IsUndefined();
3546 DCHECK_EQ(result, QuickIsUndefined());
3547 return result;
3548 }
3549
FullIsNull() const3550 bool Value::FullIsNull() const {
3551 i::Handle<i::Object> object = Utils::OpenHandle(this);
3552 bool result = object->IsNull();
3553 DCHECK_EQ(result, QuickIsNull());
3554 return result;
3555 }
3556
IsTrue() const3557 bool Value::IsTrue() const {
3558 i::Object object = *Utils::OpenHandle(this);
3559 if (object.IsSmi()) return false;
3560 return object.IsTrue();
3561 }
3562
IsFalse() const3563 bool Value::IsFalse() const {
3564 i::Object object = *Utils::OpenHandle(this);
3565 if (object.IsSmi()) return false;
3566 return object.IsFalse();
3567 }
3568
IsFunction() const3569 bool Value::IsFunction() const { return Utils::OpenHandle(this)->IsCallable(); }
3570
IsName() const3571 bool Value::IsName() const { return Utils::OpenHandle(this)->IsName(); }
3572
FullIsString() const3573 bool Value::FullIsString() const {
3574 bool result = Utils::OpenHandle(this)->IsString();
3575 DCHECK_EQ(result, QuickIsString());
3576 return result;
3577 }
3578
IsSymbol() const3579 bool Value::IsSymbol() const {
3580 return Utils::OpenHandle(this)->IsPublicSymbol();
3581 }
3582
IsArray() const3583 bool Value::IsArray() const { return Utils::OpenHandle(this)->IsJSArray(); }
3584
IsArrayBuffer() const3585 bool Value::IsArrayBuffer() const {
3586 i::Object obj = *Utils::OpenHandle(this);
3587 if (!obj.IsJSArrayBuffer()) return false;
3588 return !i::JSArrayBuffer::cast(obj).is_shared();
3589 }
3590
IsArrayBufferView() const3591 bool Value::IsArrayBufferView() const {
3592 return Utils::OpenHandle(this)->IsJSArrayBufferView();
3593 }
3594
IsTypedArray() const3595 bool Value::IsTypedArray() const {
3596 return Utils::OpenHandle(this)->IsJSTypedArray();
3597 }
3598
3599 #define VALUE_IS_TYPED_ARRAY(Type, typeName, TYPE, ctype) \
3600 bool Value::Is##Type##Array() const { \
3601 i::Handle<i::Object> obj = Utils::OpenHandle(this); \
3602 return obj->IsJSTypedArray() && \
3603 i::JSTypedArray::cast(*obj).type() == i::kExternal##Type##Array; \
3604 }
3605
TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)3606 TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)
3607
3608 #undef VALUE_IS_TYPED_ARRAY
3609
3610 bool Value::IsDataView() const {
3611 return Utils::OpenHandle(this)->IsJSDataView();
3612 }
3613
IsSharedArrayBuffer() const3614 bool Value::IsSharedArrayBuffer() const {
3615 i::Object obj = *Utils::OpenHandle(this);
3616 if (!obj.IsJSArrayBuffer()) return false;
3617 return i::JSArrayBuffer::cast(obj).is_shared();
3618 }
3619
IsObject() const3620 bool Value::IsObject() const { return Utils::OpenHandle(this)->IsJSReceiver(); }
3621
IsNumber() const3622 bool Value::IsNumber() const { return Utils::OpenHandle(this)->IsNumber(); }
3623
IsBigInt() const3624 bool Value::IsBigInt() const { return Utils::OpenHandle(this)->IsBigInt(); }
3625
IsProxy() const3626 bool Value::IsProxy() const { return Utils::OpenHandle(this)->IsJSProxy(); }
3627
3628 #define VALUE_IS_SPECIFIC_TYPE(Type, Check) \
3629 bool Value::Is##Type() const { \
3630 i::Handle<i::Object> obj = Utils::OpenHandle(this); \
3631 return obj->Is##Check(); \
3632 }
3633
VALUE_IS_SPECIFIC_TYPE(ArgumentsObject,JSArgumentsObject)3634 VALUE_IS_SPECIFIC_TYPE(ArgumentsObject, JSArgumentsObject)
3635 VALUE_IS_SPECIFIC_TYPE(BigIntObject, BigIntWrapper)
3636 VALUE_IS_SPECIFIC_TYPE(BooleanObject, BooleanWrapper)
3637 VALUE_IS_SPECIFIC_TYPE(NumberObject, NumberWrapper)
3638 VALUE_IS_SPECIFIC_TYPE(StringObject, StringWrapper)
3639 VALUE_IS_SPECIFIC_TYPE(SymbolObject, SymbolWrapper)
3640 VALUE_IS_SPECIFIC_TYPE(Date, JSDate)
3641 VALUE_IS_SPECIFIC_TYPE(Map, JSMap)
3642 VALUE_IS_SPECIFIC_TYPE(Set, JSSet)
3643 #if V8_ENABLE_WEBASSEMBLY
3644 VALUE_IS_SPECIFIC_TYPE(WasmMemoryObject, WasmMemoryObject)
3645 VALUE_IS_SPECIFIC_TYPE(WasmModuleObject, WasmModuleObject)
3646 #else
3647 bool Value::IsWasmMemoryObject() const { return false; }
3648 bool Value::IsWasmModuleObject() const { return false; }
3649 #endif // V8_ENABLE_WEBASSEMBLY
3650 VALUE_IS_SPECIFIC_TYPE(WeakMap, JSWeakMap)
3651 VALUE_IS_SPECIFIC_TYPE(WeakSet, JSWeakSet)
3652
3653 #undef VALUE_IS_SPECIFIC_TYPE
3654
3655 bool Value::IsBoolean() const { return Utils::OpenHandle(this)->IsBoolean(); }
3656
IsExternal() const3657 bool Value::IsExternal() const {
3658 i::Object obj = *Utils::OpenHandle(this);
3659 return obj.IsJSExternalObject();
3660 }
3661
IsInt32() const3662 bool Value::IsInt32() const {
3663 i::Object obj = *Utils::OpenHandle(this);
3664 if (obj.IsSmi()) return true;
3665 if (obj.IsNumber()) {
3666 return i::IsInt32Double(obj.Number());
3667 }
3668 return false;
3669 }
3670
IsUint32() const3671 bool Value::IsUint32() const {
3672 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3673 if (obj->IsSmi()) return i::Smi::ToInt(*obj) >= 0;
3674 if (obj->IsNumber()) {
3675 double value = obj->Number();
3676 return !i::IsMinusZero(value) && value >= 0 && value <= i::kMaxUInt32 &&
3677 value == i::FastUI2D(i::FastD2UI(value));
3678 }
3679 return false;
3680 }
3681
IsNativeError() const3682 bool Value::IsNativeError() const {
3683 return Utils::OpenHandle(this)->IsJSError();
3684 }
3685
IsRegExp() const3686 bool Value::IsRegExp() const {
3687 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3688 return obj->IsJSRegExp();
3689 }
3690
IsAsyncFunction() const3691 bool Value::IsAsyncFunction() const {
3692 i::Object obj = *Utils::OpenHandle(this);
3693 if (!obj.IsJSFunction()) return false;
3694 i::JSFunction func = i::JSFunction::cast(obj);
3695 return i::IsAsyncFunction(func.shared().kind());
3696 }
3697
IsGeneratorFunction() const3698 bool Value::IsGeneratorFunction() const {
3699 i::Object obj = *Utils::OpenHandle(this);
3700 if (!obj.IsJSFunction()) return false;
3701 i::JSFunction func = i::JSFunction::cast(obj);
3702 ASSERT_NO_SCRIPT_NO_EXCEPTION(func.GetIsolate());
3703 return i::IsGeneratorFunction(func.shared().kind());
3704 }
3705
IsGeneratorObject() const3706 bool Value::IsGeneratorObject() const {
3707 return Utils::OpenHandle(this)->IsJSGeneratorObject();
3708 }
3709
IsMapIterator() const3710 bool Value::IsMapIterator() const {
3711 return Utils::OpenHandle(this)->IsJSMapIterator();
3712 }
3713
IsSetIterator() const3714 bool Value::IsSetIterator() const {
3715 return Utils::OpenHandle(this)->IsJSSetIterator();
3716 }
3717
IsPromise() const3718 bool Value::IsPromise() const { return Utils::OpenHandle(this)->IsJSPromise(); }
3719
IsModuleNamespaceObject() const3720 bool Value::IsModuleNamespaceObject() const {
3721 return Utils::OpenHandle(this)->IsJSModuleNamespace();
3722 }
3723
ToString(Local<Context> context) const3724 MaybeLocal<String> Value::ToString(Local<Context> context) const {
3725 auto obj = Utils::OpenHandle(this);
3726 if (obj->IsString()) return ToApiHandle<String>(obj);
3727 PREPARE_FOR_EXECUTION(context, Object, ToString, String);
3728 Local<String> result;
3729 has_pending_exception =
3730 !ToLocal<String>(i::Object::ToString(isolate, obj), &result);
3731 RETURN_ON_FAILED_EXECUTION(String);
3732 RETURN_ESCAPED(result);
3733 }
3734
ToDetailString(Local<Context> context) const3735 MaybeLocal<String> Value::ToDetailString(Local<Context> context) const {
3736 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3737 if (obj->IsString()) return ToApiHandle<String>(obj);
3738 PREPARE_FOR_EXECUTION(context, Object, ToDetailString, String);
3739 Local<String> result =
3740 Utils::ToLocal(i::Object::NoSideEffectsToString(isolate, obj));
3741 RETURN_ON_FAILED_EXECUTION(String);
3742 RETURN_ESCAPED(result);
3743 }
3744
ToObject(Local<Context> context) const3745 MaybeLocal<Object> Value::ToObject(Local<Context> context) const {
3746 auto obj = Utils::OpenHandle(this);
3747 if (obj->IsJSReceiver()) return ToApiHandle<Object>(obj);
3748 PREPARE_FOR_EXECUTION(context, Object, ToObject, Object);
3749 Local<Object> result;
3750 has_pending_exception =
3751 !ToLocal<Object>(i::Object::ToObject(isolate, obj), &result);
3752 RETURN_ON_FAILED_EXECUTION(Object);
3753 RETURN_ESCAPED(result);
3754 }
3755
ToBigInt(Local<Context> context) const3756 MaybeLocal<BigInt> Value::ToBigInt(Local<Context> context) const {
3757 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3758 if (obj->IsBigInt()) return ToApiHandle<BigInt>(obj);
3759 PREPARE_FOR_EXECUTION(context, Object, ToBigInt, BigInt);
3760 Local<BigInt> result;
3761 has_pending_exception =
3762 !ToLocal<BigInt>(i::BigInt::FromObject(isolate, obj), &result);
3763 RETURN_ON_FAILED_EXECUTION(BigInt);
3764 RETURN_ESCAPED(result);
3765 }
3766
BooleanValue(Isolate * v8_isolate) const3767 bool Value::BooleanValue(Isolate* v8_isolate) const {
3768 return Utils::OpenHandle(this)->BooleanValue(
3769 reinterpret_cast<i::Isolate*>(v8_isolate));
3770 }
3771
ToBoolean(Isolate * v8_isolate) const3772 Local<Boolean> Value::ToBoolean(Isolate* v8_isolate) const {
3773 auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3774 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
3775 return ToApiHandle<Boolean>(
3776 isolate->factory()->ToBoolean(BooleanValue(v8_isolate)));
3777 }
3778
ToNumber(Local<Context> context) const3779 MaybeLocal<Number> Value::ToNumber(Local<Context> context) const {
3780 auto obj = Utils::OpenHandle(this);
3781 if (obj->IsNumber()) return ToApiHandle<Number>(obj);
3782 PREPARE_FOR_EXECUTION(context, Object, ToNumber, Number);
3783 Local<Number> result;
3784 has_pending_exception =
3785 !ToLocal<Number>(i::Object::ToNumber(isolate, obj), &result);
3786 RETURN_ON_FAILED_EXECUTION(Number);
3787 RETURN_ESCAPED(result);
3788 }
3789
ToInteger(Local<Context> context) const3790 MaybeLocal<Integer> Value::ToInteger(Local<Context> context) const {
3791 auto obj = Utils::OpenHandle(this);
3792 if (obj->IsSmi()) return ToApiHandle<Integer>(obj);
3793 PREPARE_FOR_EXECUTION(context, Object, ToInteger, Integer);
3794 Local<Integer> result;
3795 has_pending_exception =
3796 !ToLocal<Integer>(i::Object::ToInteger(isolate, obj), &result);
3797 RETURN_ON_FAILED_EXECUTION(Integer);
3798 RETURN_ESCAPED(result);
3799 }
3800
ToInt32(Local<Context> context) const3801 MaybeLocal<Int32> Value::ToInt32(Local<Context> context) const {
3802 auto obj = Utils::OpenHandle(this);
3803 if (obj->IsSmi()) return ToApiHandle<Int32>(obj);
3804 Local<Int32> result;
3805 PREPARE_FOR_EXECUTION(context, Object, ToInt32, Int32);
3806 has_pending_exception =
3807 !ToLocal<Int32>(i::Object::ToInt32(isolate, obj), &result);
3808 RETURN_ON_FAILED_EXECUTION(Int32);
3809 RETURN_ESCAPED(result);
3810 }
3811
ToUint32(Local<Context> context) const3812 MaybeLocal<Uint32> Value::ToUint32(Local<Context> context) const {
3813 auto obj = Utils::OpenHandle(this);
3814 if (obj->IsSmi()) return ToApiHandle<Uint32>(obj);
3815 Local<Uint32> result;
3816 PREPARE_FOR_EXECUTION(context, Object, ToUint32, Uint32);
3817 has_pending_exception =
3818 !ToLocal<Uint32>(i::Object::ToUint32(isolate, obj), &result);
3819 RETURN_ON_FAILED_EXECUTION(Uint32);
3820 RETURN_ESCAPED(result);
3821 }
3822
DecodeExternalPointerImpl(const i::Isolate * isolate,i::ExternalPointer_t encoded_pointer,ExternalPointerTag tag)3823 i::Address i::DecodeExternalPointerImpl(const i::Isolate* isolate,
3824 i::ExternalPointer_t encoded_pointer,
3825 ExternalPointerTag tag) {
3826 return i::DecodeExternalPointer(isolate, encoded_pointer, tag);
3827 }
3828
IsolateFromNeverReadOnlySpaceObject(i::Address obj)3829 i::Isolate* i::IsolateFromNeverReadOnlySpaceObject(i::Address obj) {
3830 return i::GetIsolateFromWritableObject(i::HeapObject::cast(i::Object(obj)));
3831 }
3832
ShouldThrowOnError(i::Isolate * isolate)3833 bool i::ShouldThrowOnError(i::Isolate* isolate) {
3834 return i::GetShouldThrow(isolate, Nothing<i::ShouldThrow>()) ==
3835 i::ShouldThrow::kThrowOnError;
3836 }
3837
CanHaveInternalField(int instance_type)3838 bool i::CanHaveInternalField(int instance_type) {
3839 return instance_type == i::Internals::kJSObjectType ||
3840 instance_type == i::Internals::kJSSpecialApiObjectType ||
3841 v8::internal::InstanceTypeChecker::IsJSApiObject(
3842 static_cast<v8::internal::InstanceType>(instance_type));
3843 }
3844
CheckInitializedImpl(v8::Isolate * external_isolate)3845 void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
3846 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
3847 Utils::ApiCheck(isolate != nullptr && !isolate->IsDead(),
3848 "v8::internal::Internals::CheckInitialized",
3849 "Isolate is not initialized or V8 has died");
3850 }
3851
CheckCast(Data * that)3852 void v8::Value::CheckCast(Data* that) {
3853 Utils::ApiCheck(that->IsValue(), "v8::Value::Cast", "Data is not a Value");
3854 }
3855
CheckCast(v8::Value * that)3856 void External::CheckCast(v8::Value* that) {
3857 Utils::ApiCheck(that->IsExternal(), "v8::External::Cast",
3858 "Value is not an External");
3859 }
3860
CheckCast(Value * that)3861 void v8::Object::CheckCast(Value* that) {
3862 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3863 Utils::ApiCheck(obj->IsJSReceiver(), "v8::Object::Cast",
3864 "Value is not an Object");
3865 }
3866
CheckCast(Value * that)3867 void v8::Function::CheckCast(Value* that) {
3868 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3869 Utils::ApiCheck(obj->IsCallable(), "v8::Function::Cast",
3870 "Value is not a Function");
3871 }
3872
CheckCast(v8::Data * that)3873 void v8::Boolean::CheckCast(v8::Data* that) {
3874 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3875 Utils::ApiCheck(obj->IsBoolean(), "v8::Boolean::Cast",
3876 "Value is not a Boolean");
3877 }
3878
CheckCast(v8::Data * that)3879 void v8::Name::CheckCast(v8::Data* that) {
3880 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3881 Utils::ApiCheck(obj->IsName(), "v8::Name::Cast", "Value is not a Name");
3882 }
3883
CheckCast(v8::Data * that)3884 void v8::String::CheckCast(v8::Data* that) {
3885 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3886 Utils::ApiCheck(obj->IsString(), "v8::String::Cast", "Value is not a String");
3887 }
3888
CheckCast(v8::Data * that)3889 void v8::Symbol::CheckCast(v8::Data* that) {
3890 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3891 Utils::ApiCheck(obj->IsSymbol(), "v8::Symbol::Cast", "Value is not a Symbol");
3892 }
3893
CheckCast(v8::Data * that)3894 void v8::Private::CheckCast(v8::Data* that) {
3895 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3896 Utils::ApiCheck(
3897 obj->IsSymbol() && i::Handle<i::Symbol>::cast(obj)->is_private(),
3898 "v8::Private::Cast", "Value is not a Private");
3899 }
3900
CheckCast(v8::Data * that)3901 void v8::FixedArray::CheckCast(v8::Data* that) {
3902 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3903 Utils::ApiCheck(obj->IsFixedArray(), "v8::FixedArray::Cast",
3904 "Value is not a FixedArray");
3905 }
3906
CheckCast(v8::Data * that)3907 void v8::ModuleRequest::CheckCast(v8::Data* that) {
3908 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3909 Utils::ApiCheck(obj->IsModuleRequest(), "v8::ModuleRequest::Cast",
3910 "Value is not a ModuleRequest");
3911 }
3912
CheckCast(v8::Data * that)3913 void v8::Module::CheckCast(v8::Data* that) {
3914 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3915 Utils::ApiCheck(obj->IsModule(), "v8::Module::Cast", "Value is not a Module");
3916 }
3917
CheckCast(v8::Data * that)3918 void v8::Number::CheckCast(v8::Data* that) {
3919 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3920 Utils::ApiCheck(obj->IsNumber(), "v8::Number::Cast()",
3921 "Value is not a Number");
3922 }
3923
CheckCast(v8::Data * that)3924 void v8::Integer::CheckCast(v8::Data* that) {
3925 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3926 Utils::ApiCheck(obj->IsNumber(), "v8::Integer::Cast",
3927 "Value is not an Integer");
3928 }
3929
CheckCast(v8::Data * that)3930 void v8::Int32::CheckCast(v8::Data* that) {
3931 Utils::ApiCheck(Value::Cast(that)->IsInt32(), "v8::Int32::Cast",
3932 "Value is not a 32-bit signed integer");
3933 }
3934
CheckCast(v8::Data * that)3935 void v8::Uint32::CheckCast(v8::Data* that) {
3936 Utils::ApiCheck(Value::Cast(that)->IsUint32(), "v8::Uint32::Cast",
3937 "Value is not a 32-bit unsigned integer");
3938 }
3939
CheckCast(v8::Data * that)3940 void v8::BigInt::CheckCast(v8::Data* that) {
3941 Utils::ApiCheck(Value::Cast(that)->IsBigInt(), "v8::BigInt::Cast",
3942 "Value is not a BigInt");
3943 }
3944
CheckCast(v8::Data * that)3945 void v8::Context::CheckCast(v8::Data* that) {
3946 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3947 Utils::ApiCheck(obj->IsContext(), "v8::Context::Cast",
3948 "Value is not a Context");
3949 }
3950
CheckCast(Value * that)3951 void v8::Array::CheckCast(Value* that) {
3952 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3953 Utils::ApiCheck(obj->IsJSArray(), "v8::Array::Cast", "Value is not an Array");
3954 }
3955
CheckCast(Value * that)3956 void v8::Map::CheckCast(Value* that) {
3957 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3958 Utils::ApiCheck(obj->IsJSMap(), "v8::Map::Cast", "Value is not a Map");
3959 }
3960
CheckCast(Value * that)3961 void v8::Set::CheckCast(Value* that) {
3962 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3963 Utils::ApiCheck(obj->IsJSSet(), "v8_Set_Cast", "Value is not a Set");
3964 }
3965
CheckCast(Value * that)3966 void v8::Promise::CheckCast(Value* that) {
3967 Utils::ApiCheck(that->IsPromise(), "v8::Promise::Cast",
3968 "Value is not a Promise");
3969 }
3970
CheckCast(Value * that)3971 void v8::Promise::Resolver::CheckCast(Value* that) {
3972 Utils::ApiCheck(that->IsPromise(), "v8::Promise::Resolver::Cast",
3973 "Value is not a Promise::Resolver");
3974 }
3975
CheckCast(Value * that)3976 void v8::Proxy::CheckCast(Value* that) {
3977 Utils::ApiCheck(that->IsProxy(), "v8::Proxy::Cast", "Value is not a Proxy");
3978 }
3979
CheckCast(Value * that)3980 void v8::WasmMemoryObject::CheckCast(Value* that) {
3981 Utils::ApiCheck(that->IsWasmMemoryObject(), "v8::WasmMemoryObject::Cast",
3982 "Value is not a WasmMemoryObject");
3983 }
3984
CheckCast(Value * that)3985 void v8::WasmModuleObject::CheckCast(Value* that) {
3986 Utils::ApiCheck(that->IsWasmModuleObject(), "v8::WasmModuleObject::Cast",
3987 "Value is not a WasmModuleObject");
3988 }
3989
~BackingStore()3990 v8::BackingStore::~BackingStore() {
3991 auto i_this = reinterpret_cast<const i::BackingStore*>(this);
3992 i_this->~BackingStore(); // manually call internal destructor
3993 }
3994
Data() const3995 void* v8::BackingStore::Data() const {
3996 return reinterpret_cast<const i::BackingStore*>(this)->buffer_start();
3997 }
3998
ByteLength() const3999 size_t v8::BackingStore::ByteLength() const {
4000 return reinterpret_cast<const i::BackingStore*>(this)->byte_length();
4001 }
4002
IsShared() const4003 bool v8::BackingStore::IsShared() const {
4004 return reinterpret_cast<const i::BackingStore*>(this)->is_shared();
4005 }
4006
4007 // static
Reallocate(v8::Isolate * isolate,std::unique_ptr<v8::BackingStore> backing_store,size_t byte_length)4008 std::unique_ptr<v8::BackingStore> v8::BackingStore::Reallocate(
4009 v8::Isolate* isolate, std::unique_ptr<v8::BackingStore> backing_store,
4010 size_t byte_length) {
4011 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
4012 API_RCS_SCOPE(i_isolate, ArrayBuffer, BackingStore_Reallocate);
4013 Utils::ApiCheck(byte_length <= i::JSArrayBuffer::kMaxByteLength,
4014 "v8::BackingStore::Reallocate", "byte_lenght is too large");
4015 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
4016 i::BackingStore* i_backing_store =
4017 reinterpret_cast<i::BackingStore*>(backing_store.get());
4018 if (!i_backing_store->Reallocate(i_isolate, byte_length)) {
4019 i::FatalProcessOutOfMemory(i_isolate, "v8::BackingStore::Reallocate");
4020 }
4021 return backing_store;
4022 }
4023
4024 // static
EmptyDeleter(void * data,size_t length,void * deleter_data)4025 void v8::BackingStore::EmptyDeleter(void* data, size_t length,
4026 void* deleter_data) {
4027 DCHECK_NULL(deleter_data);
4028 }
4029
GetBackingStore()4030 std::shared_ptr<v8::BackingStore> v8::ArrayBuffer::GetBackingStore() {
4031 i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
4032 std::shared_ptr<i::BackingStore> backing_store = self->GetBackingStore();
4033 if (!backing_store) {
4034 backing_store =
4035 i::BackingStore::EmptyBackingStore(i::SharedFlag::kNotShared);
4036 }
4037 std::shared_ptr<i::BackingStoreBase> bs_base = backing_store;
4038 return std::static_pointer_cast<v8::BackingStore>(bs_base);
4039 }
4040
Data() const4041 void* v8::ArrayBuffer::Data() const {
4042 i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
4043 return self->backing_store();
4044 }
4045
GetBackingStore()4046 std::shared_ptr<v8::BackingStore> v8::SharedArrayBuffer::GetBackingStore() {
4047 i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
4048 std::shared_ptr<i::BackingStore> backing_store = self->GetBackingStore();
4049 if (!backing_store) {
4050 backing_store = i::BackingStore::EmptyBackingStore(i::SharedFlag::kShared);
4051 }
4052 std::shared_ptr<i::BackingStoreBase> bs_base = backing_store;
4053 return std::static_pointer_cast<v8::BackingStore>(bs_base);
4054 }
4055
Data() const4056 void* v8::SharedArrayBuffer::Data() const {
4057 i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
4058 return self->backing_store();
4059 }
4060
CheckCast(Value * that)4061 void v8::ArrayBuffer::CheckCast(Value* that) {
4062 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4063 Utils::ApiCheck(
4064 obj->IsJSArrayBuffer() && !i::JSArrayBuffer::cast(*obj).is_shared(),
4065 "v8::ArrayBuffer::Cast()", "Value is not an ArrayBuffer");
4066 }
4067
CheckCast(Value * that)4068 void v8::ArrayBufferView::CheckCast(Value* that) {
4069 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4070 Utils::ApiCheck(obj->IsJSArrayBufferView(), "v8::ArrayBufferView::Cast()",
4071 "Value is not an ArrayBufferView");
4072 }
4073
4074 constexpr size_t v8::TypedArray::kMaxLength;
4075
CheckCast(Value * that)4076 void v8::TypedArray::CheckCast(Value* that) {
4077 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4078 Utils::ApiCheck(obj->IsJSTypedArray(), "v8::TypedArray::Cast()",
4079 "Value is not a TypedArray");
4080 }
4081
4082 #define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype) \
4083 void v8::Type##Array::CheckCast(Value* that) { \
4084 i::Handle<i::Object> obj = Utils::OpenHandle(that); \
4085 Utils::ApiCheck( \
4086 obj->IsJSTypedArray() && \
4087 i::JSTypedArray::cast(*obj).type() == i::kExternal##Type##Array, \
4088 "v8::" #Type "Array::Cast()", "Value is not a " #Type "Array"); \
4089 }
4090
TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST)4091 TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST)
4092
4093 #undef CHECK_TYPED_ARRAY_CAST
4094
4095 void v8::DataView::CheckCast(Value* that) {
4096 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4097 Utils::ApiCheck(obj->IsJSDataView(), "v8::DataView::Cast()",
4098 "Value is not a DataView");
4099 }
4100
CheckCast(Value * that)4101 void v8::SharedArrayBuffer::CheckCast(Value* that) {
4102 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4103 Utils::ApiCheck(
4104 obj->IsJSArrayBuffer() && i::JSArrayBuffer::cast(*obj).is_shared(),
4105 "v8::SharedArrayBuffer::Cast()", "Value is not a SharedArrayBuffer");
4106 }
4107
CheckCast(v8::Value * that)4108 void v8::Date::CheckCast(v8::Value* that) {
4109 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4110 Utils::ApiCheck(obj->IsJSDate(), "v8::Date::Cast()", "Value is not a Date");
4111 }
4112
CheckCast(v8::Value * that)4113 void v8::StringObject::CheckCast(v8::Value* that) {
4114 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4115 Utils::ApiCheck(obj->IsStringWrapper(), "v8::StringObject::Cast()",
4116 "Value is not a StringObject");
4117 }
4118
CheckCast(v8::Value * that)4119 void v8::SymbolObject::CheckCast(v8::Value* that) {
4120 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4121 Utils::ApiCheck(obj->IsSymbolWrapper(), "v8::SymbolObject::Cast()",
4122 "Value is not a SymbolObject");
4123 }
4124
CheckCast(v8::Value * that)4125 void v8::NumberObject::CheckCast(v8::Value* that) {
4126 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4127 Utils::ApiCheck(obj->IsNumberWrapper(), "v8::NumberObject::Cast()",
4128 "Value is not a NumberObject");
4129 }
4130
CheckCast(v8::Value * that)4131 void v8::BigIntObject::CheckCast(v8::Value* that) {
4132 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4133 Utils::ApiCheck(obj->IsBigIntWrapper(), "v8::BigIntObject::Cast()",
4134 "Value is not a BigIntObject");
4135 }
4136
CheckCast(v8::Value * that)4137 void v8::BooleanObject::CheckCast(v8::Value* that) {
4138 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4139 Utils::ApiCheck(obj->IsBooleanWrapper(), "v8::BooleanObject::Cast()",
4140 "Value is not a BooleanObject");
4141 }
4142
CheckCast(v8::Value * that)4143 void v8::RegExp::CheckCast(v8::Value* that) {
4144 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4145 Utils::ApiCheck(obj->IsJSRegExp(), "v8::RegExp::Cast()",
4146 "Value is not a RegExp");
4147 }
4148
NumberValue(Local<Context> context) const4149 Maybe<double> Value::NumberValue(Local<Context> context) const {
4150 auto obj = Utils::OpenHandle(this);
4151 if (obj->IsNumber()) return Just(obj->Number());
4152 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4153 ENTER_V8(isolate, context, Value, NumberValue, Nothing<double>(),
4154 i::HandleScope);
4155 i::Handle<i::Object> num;
4156 has_pending_exception = !i::Object::ToNumber(isolate, obj).ToHandle(&num);
4157 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(double);
4158 return Just(num->Number());
4159 }
4160
IntegerValue(Local<Context> context) const4161 Maybe<int64_t> Value::IntegerValue(Local<Context> context) const {
4162 auto obj = Utils::OpenHandle(this);
4163 if (obj->IsNumber()) {
4164 return Just(NumberToInt64(*obj));
4165 }
4166 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4167 ENTER_V8(isolate, context, Value, IntegerValue, Nothing<int64_t>(),
4168 i::HandleScope);
4169 i::Handle<i::Object> num;
4170 has_pending_exception = !i::Object::ToInteger(isolate, obj).ToHandle(&num);
4171 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int64_t);
4172 return Just(NumberToInt64(*num));
4173 }
4174
Int32Value(Local<Context> context) const4175 Maybe<int32_t> Value::Int32Value(Local<Context> context) const {
4176 auto obj = Utils::OpenHandle(this);
4177 if (obj->IsNumber()) return Just(NumberToInt32(*obj));
4178 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4179 ENTER_V8(isolate, context, Value, Int32Value, Nothing<int32_t>(),
4180 i::HandleScope);
4181 i::Handle<i::Object> num;
4182 has_pending_exception = !i::Object::ToInt32(isolate, obj).ToHandle(&num);
4183 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int32_t);
4184 return Just(num->IsSmi() ? i::Smi::ToInt(*num)
4185 : static_cast<int32_t>(num->Number()));
4186 }
4187
Uint32Value(Local<Context> context) const4188 Maybe<uint32_t> Value::Uint32Value(Local<Context> context) const {
4189 auto obj = Utils::OpenHandle(this);
4190 if (obj->IsNumber()) return Just(NumberToUint32(*obj));
4191 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4192 ENTER_V8(isolate, context, Value, Uint32Value, Nothing<uint32_t>(),
4193 i::HandleScope);
4194 i::Handle<i::Object> num;
4195 has_pending_exception = !i::Object::ToUint32(isolate, obj).ToHandle(&num);
4196 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(uint32_t);
4197 return Just(num->IsSmi() ? static_cast<uint32_t>(i::Smi::ToInt(*num))
4198 : static_cast<uint32_t>(num->Number()));
4199 }
4200
ToArrayIndex(Local<Context> context) const4201 MaybeLocal<Uint32> Value::ToArrayIndex(Local<Context> context) const {
4202 auto self = Utils::OpenHandle(this);
4203 if (self->IsSmi()) {
4204 if (i::Smi::ToInt(*self) >= 0) return Utils::Uint32ToLocal(self);
4205 return Local<Uint32>();
4206 }
4207 PREPARE_FOR_EXECUTION(context, Object, ToArrayIndex, Uint32);
4208 i::Handle<i::Object> string_obj;
4209 has_pending_exception =
4210 !i::Object::ToString(isolate, self).ToHandle(&string_obj);
4211 RETURN_ON_FAILED_EXECUTION(Uint32);
4212 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
4213 uint32_t index;
4214 if (str->AsArrayIndex(&index)) {
4215 i::Handle<i::Object> value;
4216 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
4217 value = i::Handle<i::Object>(i::Smi::FromInt(index), isolate);
4218 } else {
4219 value = isolate->factory()->NewNumber(index);
4220 }
4221 RETURN_ESCAPED(Utils::Uint32ToLocal(value));
4222 }
4223 return Local<Uint32>();
4224 }
4225
Equals(Local<Context> context,Local<Value> that) const4226 Maybe<bool> Value::Equals(Local<Context> context, Local<Value> that) const {
4227 i::Isolate* isolate = Utils::OpenHandle(*context)->GetIsolate();
4228 ENTER_V8(isolate, context, Value, Equals, Nothing<bool>(), i::HandleScope);
4229 auto self = Utils::OpenHandle(this);
4230 auto other = Utils::OpenHandle(*that);
4231 Maybe<bool> result = i::Object::Equals(isolate, self, other);
4232 has_pending_exception = result.IsNothing();
4233 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4234 return result;
4235 }
4236
StrictEquals(Local<Value> that) const4237 bool Value::StrictEquals(Local<Value> that) const {
4238 auto self = Utils::OpenHandle(this);
4239 auto other = Utils::OpenHandle(*that);
4240 return self->StrictEquals(*other);
4241 }
4242
SameValue(Local<Value> that) const4243 bool Value::SameValue(Local<Value> that) const {
4244 auto self = Utils::OpenHandle(this);
4245 auto other = Utils::OpenHandle(*that);
4246 return self->SameValue(*other);
4247 }
4248
TypeOf(v8::Isolate * external_isolate)4249 Local<String> Value::TypeOf(v8::Isolate* external_isolate) {
4250 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
4251 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
4252 API_RCS_SCOPE(isolate, Value, TypeOf);
4253 return Utils::ToLocal(i::Object::TypeOf(isolate, Utils::OpenHandle(this)));
4254 }
4255
InstanceOf(v8::Local<v8::Context> context,v8::Local<v8::Object> object)4256 Maybe<bool> Value::InstanceOf(v8::Local<v8::Context> context,
4257 v8::Local<v8::Object> object) {
4258 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4259 ENTER_V8(isolate, context, Value, InstanceOf, Nothing<bool>(),
4260 i::HandleScope);
4261 auto left = Utils::OpenHandle(this);
4262 auto right = Utils::OpenHandle(*object);
4263 i::Handle<i::Object> result;
4264 has_pending_exception =
4265 !i::Object::InstanceOf(isolate, left, right).ToHandle(&result);
4266 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4267 return Just(result->IsTrue(isolate));
4268 }
4269
Set(v8::Local<v8::Context> context,v8::Local<Value> key,v8::Local<Value> value)4270 Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context,
4271 v8::Local<Value> key, v8::Local<Value> value) {
4272 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4273 ENTER_V8(isolate, context, Object, Set, Nothing<bool>(), i::HandleScope);
4274 auto self = Utils::OpenHandle(this);
4275 auto key_obj = Utils::OpenHandle(*key);
4276 auto value_obj = Utils::OpenHandle(*value);
4277 has_pending_exception =
4278 i::Runtime::SetObjectProperty(isolate, self, key_obj, value_obj,
4279 i::StoreOrigin::kMaybeKeyed,
4280 Just(i::ShouldThrow::kDontThrow))
4281 .is_null();
4282 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4283 return Just(true);
4284 }
4285
Set(v8::Local<v8::Context> context,uint32_t index,v8::Local<Value> value)4286 Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context, uint32_t index,
4287 v8::Local<Value> value) {
4288 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4289 ENTER_V8(isolate, context, Object, Set, Nothing<bool>(), i::HandleScope);
4290 auto self = Utils::OpenHandle(this);
4291 auto value_obj = Utils::OpenHandle(*value);
4292 has_pending_exception = i::Object::SetElement(isolate, self, index, value_obj,
4293 i::ShouldThrow::kDontThrow)
4294 .is_null();
4295 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4296 return Just(true);
4297 }
4298
CreateDataProperty(v8::Local<v8::Context> context,v8::Local<Name> key,v8::Local<Value> value)4299 Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context,
4300 v8::Local<Name> key,
4301 v8::Local<Value> value) {
4302 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4303 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4304 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
4305 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
4306
4307 i::PropertyKey lookup_key(isolate, key_obj);
4308 i::LookupIterator it(isolate, self, lookup_key, i::LookupIterator::OWN);
4309 if (self->IsJSProxy()) {
4310 ENTER_V8(isolate, context, Object, CreateDataProperty, Nothing<bool>(),
4311 i::HandleScope);
4312 Maybe<bool> result =
4313 i::JSReceiver::CreateDataProperty(&it, value_obj, Just(i::kDontThrow));
4314 has_pending_exception = result.IsNothing();
4315 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4316 return result;
4317 } else {
4318 ENTER_V8_NO_SCRIPT(isolate, context, Object, CreateDataProperty,
4319 Nothing<bool>(), i::HandleScope);
4320 Maybe<bool> result =
4321 i::JSObject::CreateDataProperty(&it, value_obj, Just(i::kDontThrow));
4322 has_pending_exception = result.IsNothing();
4323 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4324 return result;
4325 }
4326 }
4327
CreateDataProperty(v8::Local<v8::Context> context,uint32_t index,v8::Local<Value> value)4328 Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context,
4329 uint32_t index,
4330 v8::Local<Value> value) {
4331 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4332 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4333 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
4334
4335 i::LookupIterator it(isolate, self, index, self, i::LookupIterator::OWN);
4336 if (self->IsJSProxy()) {
4337 ENTER_V8(isolate, context, Object, CreateDataProperty, Nothing<bool>(),
4338 i::HandleScope);
4339 Maybe<bool> result =
4340 i::JSReceiver::CreateDataProperty(&it, value_obj, Just(i::kDontThrow));
4341 has_pending_exception = result.IsNothing();
4342 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4343 return result;
4344 } else {
4345 ENTER_V8_NO_SCRIPT(isolate, context, Object, CreateDataProperty,
4346 Nothing<bool>(), i::HandleScope);
4347 Maybe<bool> result =
4348 i::JSObject::CreateDataProperty(&it, value_obj, Just(i::kDontThrow));
4349 has_pending_exception = result.IsNothing();
4350 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4351 return result;
4352 }
4353 }
4354
4355 struct v8::PropertyDescriptor::PrivateData {
PrivateDatav8::v8::PropertyDescriptor::PrivateData4356 PrivateData() : desc() {}
4357 i::PropertyDescriptor desc;
4358 };
4359
PropertyDescriptor()4360 v8::PropertyDescriptor::PropertyDescriptor() : private_(new PrivateData()) {}
4361
4362 // DataDescriptor
PropertyDescriptor(v8::Local<v8::Value> value)4363 v8::PropertyDescriptor::PropertyDescriptor(v8::Local<v8::Value> value)
4364 : private_(new PrivateData()) {
4365 private_->desc.set_value(Utils::OpenHandle(*value, true));
4366 }
4367
4368 // DataDescriptor with writable field
PropertyDescriptor(v8::Local<v8::Value> value,bool writable)4369 v8::PropertyDescriptor::PropertyDescriptor(v8::Local<v8::Value> value,
4370 bool writable)
4371 : private_(new PrivateData()) {
4372 private_->desc.set_value(Utils::OpenHandle(*value, true));
4373 private_->desc.set_writable(writable);
4374 }
4375
4376 // AccessorDescriptor
PropertyDescriptor(v8::Local<v8::Value> get,v8::Local<v8::Value> set)4377 v8::PropertyDescriptor::PropertyDescriptor(v8::Local<v8::Value> get,
4378 v8::Local<v8::Value> set)
4379 : private_(new PrivateData()) {
4380 DCHECK(get.IsEmpty() || get->IsUndefined() || get->IsFunction());
4381 DCHECK(set.IsEmpty() || set->IsUndefined() || set->IsFunction());
4382 private_->desc.set_get(Utils::OpenHandle(*get, true));
4383 private_->desc.set_set(Utils::OpenHandle(*set, true));
4384 }
4385
~PropertyDescriptor()4386 v8::PropertyDescriptor::~PropertyDescriptor() { delete private_; }
4387
value() const4388 v8::Local<Value> v8::PropertyDescriptor::value() const {
4389 DCHECK(private_->desc.has_value());
4390 return Utils::ToLocal(private_->desc.value());
4391 }
4392
get() const4393 v8::Local<Value> v8::PropertyDescriptor::get() const {
4394 DCHECK(private_->desc.has_get());
4395 return Utils::ToLocal(private_->desc.get());
4396 }
4397
set() const4398 v8::Local<Value> v8::PropertyDescriptor::set() const {
4399 DCHECK(private_->desc.has_set());
4400 return Utils::ToLocal(private_->desc.set());
4401 }
4402
has_value() const4403 bool v8::PropertyDescriptor::has_value() const {
4404 return private_->desc.has_value();
4405 }
has_get() const4406 bool v8::PropertyDescriptor::has_get() const {
4407 return private_->desc.has_get();
4408 }
has_set() const4409 bool v8::PropertyDescriptor::has_set() const {
4410 return private_->desc.has_set();
4411 }
4412
writable() const4413 bool v8::PropertyDescriptor::writable() const {
4414 DCHECK(private_->desc.has_writable());
4415 return private_->desc.writable();
4416 }
4417
has_writable() const4418 bool v8::PropertyDescriptor::has_writable() const {
4419 return private_->desc.has_writable();
4420 }
4421
set_enumerable(bool enumerable)4422 void v8::PropertyDescriptor::set_enumerable(bool enumerable) {
4423 private_->desc.set_enumerable(enumerable);
4424 }
4425
enumerable() const4426 bool v8::PropertyDescriptor::enumerable() const {
4427 DCHECK(private_->desc.has_enumerable());
4428 return private_->desc.enumerable();
4429 }
4430
has_enumerable() const4431 bool v8::PropertyDescriptor::has_enumerable() const {
4432 return private_->desc.has_enumerable();
4433 }
4434
set_configurable(bool configurable)4435 void v8::PropertyDescriptor::set_configurable(bool configurable) {
4436 private_->desc.set_configurable(configurable);
4437 }
4438
configurable() const4439 bool v8::PropertyDescriptor::configurable() const {
4440 DCHECK(private_->desc.has_configurable());
4441 return private_->desc.configurable();
4442 }
4443
has_configurable() const4444 bool v8::PropertyDescriptor::has_configurable() const {
4445 return private_->desc.has_configurable();
4446 }
4447
DefineOwnProperty(v8::Local<v8::Context> context,v8::Local<Name> key,v8::Local<Value> value,v8::PropertyAttribute attributes)4448 Maybe<bool> v8::Object::DefineOwnProperty(v8::Local<v8::Context> context,
4449 v8::Local<Name> key,
4450 v8::Local<Value> value,
4451 v8::PropertyAttribute attributes) {
4452 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4453 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4454 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
4455 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
4456
4457 i::PropertyDescriptor desc;
4458 desc.set_writable(!(attributes & v8::ReadOnly));
4459 desc.set_enumerable(!(attributes & v8::DontEnum));
4460 desc.set_configurable(!(attributes & v8::DontDelete));
4461 desc.set_value(value_obj);
4462
4463 if (self->IsJSProxy()) {
4464 ENTER_V8(isolate, context, Object, DefineOwnProperty, Nothing<bool>(),
4465 i::HandleScope);
4466 Maybe<bool> success = i::JSReceiver::DefineOwnProperty(
4467 isolate, self, key_obj, &desc, Just(i::kDontThrow));
4468 // Even though we said kDontThrow, there might be accessors that do throw.
4469 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4470 return success;
4471 } else {
4472 // If it's not a JSProxy, i::JSReceiver::DefineOwnProperty should never run
4473 // a script.
4474 ENTER_V8_NO_SCRIPT(isolate, context, Object, DefineOwnProperty,
4475 Nothing<bool>(), i::HandleScope);
4476 Maybe<bool> success = i::JSReceiver::DefineOwnProperty(
4477 isolate, self, key_obj, &desc, Just(i::kDontThrow));
4478 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4479 return success;
4480 }
4481 }
4482
DefineProperty(v8::Local<v8::Context> context,v8::Local<Name> key,PropertyDescriptor & descriptor)4483 Maybe<bool> v8::Object::DefineProperty(v8::Local<v8::Context> context,
4484 v8::Local<Name> key,
4485 PropertyDescriptor& descriptor) {
4486 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4487 ENTER_V8(isolate, context, Object, DefineOwnProperty, Nothing<bool>(),
4488 i::HandleScope);
4489 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4490 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
4491
4492 Maybe<bool> success = i::JSReceiver::DefineOwnProperty(
4493 isolate, self, key_obj, &descriptor.get_private()->desc,
4494 Just(i::kDontThrow));
4495 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4496 return success;
4497 }
4498
SetPrivate(Local<Context> context,Local<Private> key,Local<Value> value)4499 Maybe<bool> v8::Object::SetPrivate(Local<Context> context, Local<Private> key,
4500 Local<Value> value) {
4501 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4502 ENTER_V8_NO_SCRIPT(isolate, context, Object, SetPrivate, Nothing<bool>(),
4503 i::HandleScope);
4504 auto self = Utils::OpenHandle(this);
4505 auto key_obj = Utils::OpenHandle(reinterpret_cast<Name*>(*key));
4506 auto value_obj = Utils::OpenHandle(*value);
4507 if (self->IsJSProxy()) {
4508 i::PropertyDescriptor desc;
4509 desc.set_writable(true);
4510 desc.set_enumerable(false);
4511 desc.set_configurable(true);
4512 desc.set_value(value_obj);
4513 return i::JSProxy::SetPrivateSymbol(
4514 isolate, i::Handle<i::JSProxy>::cast(self),
4515 i::Handle<i::Symbol>::cast(key_obj), &desc, Just(i::kDontThrow));
4516 }
4517 auto js_object = i::Handle<i::JSObject>::cast(self);
4518 i::LookupIterator it(isolate, js_object, key_obj, js_object);
4519 has_pending_exception = i::JSObject::DefineOwnPropertyIgnoreAttributes(
4520 &it, value_obj, i::DONT_ENUM)
4521 .is_null();
4522 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4523 return Just(true);
4524 }
4525
Get(Local<v8::Context> context,Local<Value> key)4526 MaybeLocal<Value> v8::Object::Get(Local<v8::Context> context,
4527 Local<Value> key) {
4528 PREPARE_FOR_EXECUTION(context, Object, Get, Value);
4529 auto self = Utils::OpenHandle(this);
4530 auto key_obj = Utils::OpenHandle(*key);
4531 i::Handle<i::Object> result;
4532 has_pending_exception =
4533 !i::Runtime::GetObjectProperty(isolate, self, key_obj).ToHandle(&result);
4534 RETURN_ON_FAILED_EXECUTION(Value);
4535 RETURN_ESCAPED(Utils::ToLocal(result));
4536 }
4537
Get(Local<Context> context,uint32_t index)4538 MaybeLocal<Value> v8::Object::Get(Local<Context> context, uint32_t index) {
4539 PREPARE_FOR_EXECUTION(context, Object, Get, Value);
4540 auto self = Utils::OpenHandle(this);
4541 i::Handle<i::Object> result;
4542 has_pending_exception =
4543 !i::JSReceiver::GetElement(isolate, self, index).ToHandle(&result);
4544 RETURN_ON_FAILED_EXECUTION(Value);
4545 RETURN_ESCAPED(Utils::ToLocal(result));
4546 }
4547
GetPrivate(Local<Context> context,Local<Private> key)4548 MaybeLocal<Value> v8::Object::GetPrivate(Local<Context> context,
4549 Local<Private> key) {
4550 return Get(context, Local<Value>(reinterpret_cast<Value*>(*key)));
4551 }
4552
GetPropertyAttributes(Local<Context> context,Local<Value> key)4553 Maybe<PropertyAttribute> v8::Object::GetPropertyAttributes(
4554 Local<Context> context, Local<Value> key) {
4555 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4556 ENTER_V8(isolate, context, Object, GetPropertyAttributes,
4557 Nothing<PropertyAttribute>(), i::HandleScope);
4558 auto self = Utils::OpenHandle(this);
4559 auto key_obj = Utils::OpenHandle(*key);
4560 if (!key_obj->IsName()) {
4561 has_pending_exception =
4562 !i::Object::ToString(isolate, key_obj).ToHandle(&key_obj);
4563 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
4564 }
4565 auto key_name = i::Handle<i::Name>::cast(key_obj);
4566 auto result = i::JSReceiver::GetPropertyAttributes(self, key_name);
4567 has_pending_exception = result.IsNothing();
4568 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
4569 if (result.FromJust() == i::ABSENT) {
4570 return Just(static_cast<PropertyAttribute>(i::NONE));
4571 }
4572 return Just(static_cast<PropertyAttribute>(result.FromJust()));
4573 }
4574
GetOwnPropertyDescriptor(Local<Context> context,Local<Name> key)4575 MaybeLocal<Value> v8::Object::GetOwnPropertyDescriptor(Local<Context> context,
4576 Local<Name> key) {
4577 PREPARE_FOR_EXECUTION(context, Object, GetOwnPropertyDescriptor, Value);
4578 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
4579 i::Handle<i::Name> key_name = Utils::OpenHandle(*key);
4580
4581 i::PropertyDescriptor desc;
4582 Maybe<bool> found =
4583 i::JSReceiver::GetOwnPropertyDescriptor(isolate, obj, key_name, &desc);
4584 has_pending_exception = found.IsNothing();
4585 RETURN_ON_FAILED_EXECUTION(Value);
4586 if (!found.FromJust()) {
4587 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
4588 }
4589 RETURN_ESCAPED(Utils::ToLocal(desc.ToObject(isolate)));
4590 }
4591
GetPrototype()4592 Local<Value> v8::Object::GetPrototype() {
4593 auto self = Utils::OpenHandle(this);
4594 auto isolate = self->GetIsolate();
4595 i::PrototypeIterator iter(isolate, self);
4596 return Utils::ToLocal(i::PrototypeIterator::GetCurrent(iter));
4597 }
4598
GetPrototypeV2()4599 Local<Value> v8::Object::GetPrototypeV2() {
4600 auto self = Utils::OpenHandle(this);
4601 auto i_isolate = self->GetIsolate();
4602 i::PrototypeIterator iter(i_isolate, self);
4603 if (self->IsJSGlobalProxy()) {
4604 // Skip hidden prototype (i.e. JSGlobalObject).
4605 iter.Advance();
4606 }
4607 DCHECK(!i::PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4608 return Utils::ToLocal(i::PrototypeIterator::GetCurrent(iter));
4609 }
4610
4611 namespace {
4612
SetPrototypeImpl(v8::Object * this_,Local<Context> context,Local<Value> value,bool from_javascript)4613 Maybe<bool> SetPrototypeImpl(v8::Object* this_, Local<Context> context,
4614 Local<Value> value, bool from_javascript) {
4615 auto i_isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4616 auto self = Utils::OpenHandle(this_);
4617 auto value_obj = Utils::OpenHandle(*value);
4618 // TODO(333672197): turn this to DCHECK once it's no longer possible
4619 // to get JSGlobalObject via API.
4620 CHECK_IMPLIES(from_javascript, !value_obj->IsJSGlobalObject());
4621 if (self->IsJSObject()) {
4622 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
4623 // TODO(333672197): turn this to DCHECK once it's no longer possible
4624 // to get JSGlobalObject via API.
4625 CHECK_IMPLIES(from_javascript, !self->IsJSGlobalObject());
4626 auto result =
4627 i::JSObject::SetPrototype(i_isolate, i::Handle<i::JSObject>::cast(self),
4628 value_obj, from_javascript, i::kDontThrow);
4629 if (!result.FromJust()) return Nothing<bool>();
4630 return Just(true);
4631 }
4632 if (self->IsJSProxy()) {
4633 ENTER_V8(i_isolate, context, Object, SetPrototype, Nothing<bool>(), i::HandleScope);
4634 // We do not allow exceptions thrown while setting the prototype
4635 // to propagate outside.
4636 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(i_isolate));
4637 auto result =
4638 i::JSProxy::SetPrototype(i_isolate, i::Handle<i::JSProxy>::cast(self),
4639 value_obj, from_javascript, i::kThrowOnError);
4640 has_pending_exception = result.IsNothing();
4641 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4642 return Just(true);
4643 }
4644 // Wasm object or other kind of special object not supported here.
4645 return Nothing<bool>();
4646 }
4647
4648 } // namespace
4649
SetPrototypeV2(Local<Context> context,Local<Value> value)4650 Maybe<bool> v8::Object::SetPrototypeV2(Local<Context> context,
4651 Local<Value> value) {
4652 static constexpr bool from_javascript = true;
4653 return SetPrototypeImpl(this, context, value, from_javascript);
4654 }
4655
SetPrototype(Local<Context> context,Local<Value> value)4656 Maybe<bool> v8::Object::SetPrototype(Local<Context> context,
4657 Local<Value> value) {
4658 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4659 auto self = Utils::OpenHandle(this);
4660 auto value_obj = Utils::OpenHandle(*value);
4661 if (self->IsJSProxy()) {
4662 ENTER_V8(isolate, context, Object, SetPrototype, Nothing<bool>(),
4663 i::HandleScope);
4664 // We do not allow exceptions thrown while setting the prototype
4665 // to propagate outside.
4666 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
4667 auto result =
4668 i::JSProxy::SetPrototype(isolate, i::Handle<i::JSProxy>::cast(self),
4669 value_obj, false, i::kThrowOnError);
4670 has_pending_exception = result.IsNothing();
4671 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4672 } else {
4673 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
4674 auto result =
4675 i::JSObject::SetPrototype(isolate, i::Handle<i::JSObject>::cast(self),
4676 value_obj, false, i::kThrowOnError);
4677 if (result.IsNothing()) {
4678 isolate->clear_pending_exception();
4679 return Nothing<bool>();
4680 }
4681 }
4682 return Just(true);
4683 }
4684
FindInstanceInPrototypeChain(v8::Local<FunctionTemplate> tmpl)4685 Local<Object> v8::Object::FindInstanceInPrototypeChain(
4686 v8::Local<FunctionTemplate> tmpl) {
4687 auto self = Utils::OpenHandle(this);
4688 auto isolate = self->GetIsolate();
4689 i::PrototypeIterator iter(isolate, *self, i::kStartAtReceiver);
4690 auto tmpl_info = *Utils::OpenHandle(*tmpl);
4691 while (!tmpl_info.IsTemplateFor(iter.GetCurrent<i::JSObject>())) {
4692 iter.Advance();
4693 if (iter.IsAtEnd()) return Local<Object>();
4694 if (!iter.GetCurrent().IsJSObject()) return Local<Object>();
4695 }
4696 // IsTemplateFor() ensures that iter.GetCurrent() can't be a Proxy here.
4697 return Utils::ToLocal(i::handle(iter.GetCurrent<i::JSObject>(), isolate));
4698 }
4699
GetPropertyNames(Local<Context> context)4700 MaybeLocal<Array> v8::Object::GetPropertyNames(Local<Context> context) {
4701 return GetPropertyNames(
4702 context, v8::KeyCollectionMode::kIncludePrototypes,
4703 static_cast<v8::PropertyFilter>(ONLY_ENUMERABLE | SKIP_SYMBOLS),
4704 v8::IndexFilter::kIncludeIndices);
4705 }
4706
GetPropertyNames(Local<Context> context,KeyCollectionMode mode,PropertyFilter property_filter,IndexFilter index_filter,KeyConversionMode key_conversion)4707 MaybeLocal<Array> v8::Object::GetPropertyNames(
4708 Local<Context> context, KeyCollectionMode mode,
4709 PropertyFilter property_filter, IndexFilter index_filter,
4710 KeyConversionMode key_conversion) {
4711 PREPARE_FOR_EXECUTION(context, Object, GetPropertyNames, Array);
4712 auto self = Utils::OpenHandle(this);
4713 i::Handle<i::FixedArray> value;
4714 i::KeyAccumulator accumulator(
4715 isolate, static_cast<i::KeyCollectionMode>(mode),
4716 static_cast<i::PropertyFilter>(property_filter));
4717 accumulator.set_skip_indices(index_filter == IndexFilter::kSkipIndices);
4718 has_pending_exception = accumulator.CollectKeys(self, self).IsNothing();
4719 RETURN_ON_FAILED_EXECUTION(Array);
4720 value =
4721 accumulator.GetKeys(static_cast<i::GetKeysConversion>(key_conversion));
4722 DCHECK(self->map().EnumLength() == i::kInvalidEnumCacheSentinel ||
4723 self->map().EnumLength() == 0 ||
4724 self->map().instance_descriptors(isolate).enum_cache().keys() !=
4725 *value);
4726 auto result = isolate->factory()->NewJSArrayWithElements(value);
4727 RETURN_ESCAPED(Utils::ToLocal(result));
4728 }
4729
GetOwnPropertyNames(Local<Context> context)4730 MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context) {
4731 return GetOwnPropertyNames(
4732 context, static_cast<v8::PropertyFilter>(ONLY_ENUMERABLE | SKIP_SYMBOLS));
4733 }
4734
GetOwnPropertyNames(Local<Context> context,PropertyFilter filter,KeyConversionMode key_conversion)4735 MaybeLocal<Array> v8::Object::GetOwnPropertyNames(
4736 Local<Context> context, PropertyFilter filter,
4737 KeyConversionMode key_conversion) {
4738 return GetPropertyNames(context, KeyCollectionMode::kOwnOnly, filter,
4739 v8::IndexFilter::kIncludeIndices, key_conversion);
4740 }
4741
ObjectProtoToString(Local<Context> context)4742 MaybeLocal<String> v8::Object::ObjectProtoToString(Local<Context> context) {
4743 PREPARE_FOR_EXECUTION(context, Object, ObjectProtoToString, String);
4744 auto self = Utils::OpenHandle(this);
4745 Local<Value> result;
4746 has_pending_exception = !ToLocal<Value>(
4747 i::Execution::CallBuiltin(isolate, isolate->object_to_string(), self, 0,
4748 nullptr),
4749 &result);
4750 RETURN_ON_FAILED_EXECUTION(String);
4751 RETURN_ESCAPED(Local<String>::Cast(result));
4752 }
4753
GetConstructorName()4754 Local<String> v8::Object::GetConstructorName() {
4755 auto self = Utils::OpenHandle(this);
4756 // TODO(v8:12547): Support shared objects.
4757 DCHECK(!self->InSharedHeap());
4758 i::Handle<i::String> name =
4759 i::JSReceiver::GetConstructorName(self->GetIsolate(), self);
4760 return Utils::ToLocal(name);
4761 }
4762
SetIntegrityLevel(Local<Context> context,IntegrityLevel level)4763 Maybe<bool> v8::Object::SetIntegrityLevel(Local<Context> context,
4764 IntegrityLevel level) {
4765 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4766 ENTER_V8(isolate, context, Object, SetIntegrityLevel, Nothing<bool>(),
4767 i::HandleScope);
4768 auto self = Utils::OpenHandle(this);
4769 i::JSReceiver::IntegrityLevel i_level =
4770 level == IntegrityLevel::kFrozen ? i::FROZEN : i::SEALED;
4771 Maybe<bool> result =
4772 i::JSReceiver::SetIntegrityLevel(self, i_level, i::kThrowOnError);
4773 has_pending_exception = result.IsNothing();
4774 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4775 return result;
4776 }
4777
Delete(Local<Context> context,Local<Value> key)4778 Maybe<bool> v8::Object::Delete(Local<Context> context, Local<Value> key) {
4779 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4780 auto self = Utils::OpenHandle(this);
4781 auto key_obj = Utils::OpenHandle(*key);
4782 if (self->IsJSProxy()) {
4783 ENTER_V8(isolate, context, Object, Delete, Nothing<bool>(), i::HandleScope);
4784 Maybe<bool> result = i::Runtime::DeleteObjectProperty(
4785 isolate, self, key_obj, i::LanguageMode::kSloppy);
4786 has_pending_exception = result.IsNothing();
4787 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4788 return result;
4789 } else {
4790 // If it's not a JSProxy, i::Runtime::DeleteObjectProperty should never run
4791 // a script.
4792 ENTER_V8_NO_SCRIPT(isolate, context, Object, Delete, Nothing<bool>(),
4793 i::HandleScope);
4794 Maybe<bool> result = i::Runtime::DeleteObjectProperty(
4795 isolate, self, key_obj, i::LanguageMode::kSloppy);
4796 has_pending_exception = result.IsNothing();
4797 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4798 return result;
4799 }
4800 }
4801
DeletePrivate(Local<Context> context,Local<Private> key)4802 Maybe<bool> v8::Object::DeletePrivate(Local<Context> context,
4803 Local<Private> key) {
4804 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4805 // In case of private symbols, i::Runtime::DeleteObjectProperty does not run
4806 // any author script.
4807 ENTER_V8_NO_SCRIPT(isolate, context, Object, Delete, Nothing<bool>(),
4808 i::HandleScope);
4809 auto self = Utils::OpenHandle(this);
4810 auto key_obj = Utils::OpenHandle(*key);
4811 Maybe<bool> result = i::Runtime::DeleteObjectProperty(
4812 isolate, self, key_obj, i::LanguageMode::kSloppy);
4813 has_pending_exception = result.IsNothing();
4814 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4815 return result;
4816 }
4817
Has(Local<Context> context,Local<Value> key)4818 Maybe<bool> v8::Object::Has(Local<Context> context, Local<Value> key) {
4819 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4820 ENTER_V8(isolate, context, Object, Has, Nothing<bool>(), i::HandleScope);
4821 auto self = Utils::OpenHandle(this);
4822 auto key_obj = Utils::OpenHandle(*key);
4823 Maybe<bool> maybe = Nothing<bool>();
4824 // Check if the given key is an array index.
4825 uint32_t index = 0;
4826 if (key_obj->ToArrayIndex(&index)) {
4827 maybe = i::JSReceiver::HasElement(isolate, self, index);
4828 } else {
4829 // Convert the key to a name - possibly by calling back into JavaScript.
4830 i::Handle<i::Name> name;
4831 if (i::Object::ToName(isolate, key_obj).ToHandle(&name)) {
4832 maybe = i::JSReceiver::HasProperty(isolate, self, name);
4833 }
4834 }
4835 has_pending_exception = maybe.IsNothing();
4836 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4837 return maybe;
4838 }
4839
HasPrivate(Local<Context> context,Local<Private> key)4840 Maybe<bool> v8::Object::HasPrivate(Local<Context> context, Local<Private> key) {
4841 return HasOwnProperty(context, Local<Name>(reinterpret_cast<Name*>(*key)));
4842 }
4843
Delete(Local<Context> context,uint32_t index)4844 Maybe<bool> v8::Object::Delete(Local<Context> context, uint32_t index) {
4845 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4846 ENTER_V8(isolate, context, Object, Delete, Nothing<bool>(), i::HandleScope);
4847 auto self = Utils::OpenHandle(this);
4848 Maybe<bool> result = i::JSReceiver::DeleteElement(self, index);
4849 has_pending_exception = result.IsNothing();
4850 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4851 return result;
4852 }
4853
Has(Local<Context> context,uint32_t index)4854 Maybe<bool> v8::Object::Has(Local<Context> context, uint32_t index) {
4855 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4856 ENTER_V8(isolate, context, Object, Has, Nothing<bool>(), i::HandleScope);
4857 auto self = Utils::OpenHandle(this);
4858 auto maybe = i::JSReceiver::HasElement(isolate, self, index);
4859 has_pending_exception = maybe.IsNothing();
4860 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4861 return maybe;
4862 }
4863
4864 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,bool is_special_data_property,bool replace_on_access,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)4865 static Maybe<bool> ObjectSetAccessor(
4866 Local<Context> context, Object* self, Local<Name> name, Getter getter,
4867 Setter setter, Data data, AccessControl settings,
4868 PropertyAttribute attributes, bool is_special_data_property,
4869 bool replace_on_access, SideEffectType getter_side_effect_type,
4870 SideEffectType setter_side_effect_type) {
4871 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4872 ENTER_V8_NO_SCRIPT(isolate, context, Object, SetAccessor, Nothing<bool>(),
4873 i::HandleScope);
4874 if (!Utils::OpenHandle(self)->IsJSObject()) return Just(false);
4875 i::Handle<i::JSObject> obj =
4876 i::Handle<i::JSObject>::cast(Utils::OpenHandle(self));
4877 v8::Local<AccessorSignature> signature;
4878 i::Handle<i::AccessorInfo> info =
4879 MakeAccessorInfo(isolate, name, getter, setter, data, settings, signature,
4880 is_special_data_property, replace_on_access);
4881 info->set_getter_side_effect_type(getter_side_effect_type);
4882 info->set_setter_side_effect_type(setter_side_effect_type);
4883 if (info.is_null()) return Nothing<bool>();
4884 bool fast = obj->HasFastProperties();
4885 i::Handle<i::Object> result;
4886
4887 i::Handle<i::Name> accessor_name(info->name(), isolate);
4888 i::PropertyAttributes attrs = static_cast<i::PropertyAttributes>(attributes);
4889 has_pending_exception =
4890 !i::JSObject::SetAccessor(obj, accessor_name, info, attrs)
4891 .ToHandle(&result);
4892 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4893 if (result->IsUndefined(isolate)) return Just(false);
4894 if (fast) {
4895 i::JSObject::MigrateSlowToFast(obj, 0, "APISetAccessor");
4896 }
4897 return Just(true);
4898 }
4899
SetAccessor(Local<Context> context,Local<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,MaybeLocal<Value> data,AccessControl settings,PropertyAttribute attribute,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)4900 Maybe<bool> Object::SetAccessor(Local<Context> context, Local<Name> name,
4901 AccessorNameGetterCallback getter,
4902 AccessorNameSetterCallback setter,
4903 MaybeLocal<Value> data, AccessControl settings,
4904 PropertyAttribute attribute,
4905 SideEffectType getter_side_effect_type,
4906 SideEffectType setter_side_effect_type) {
4907 return ObjectSetAccessor(context, this, name, getter, setter,
4908 data.FromMaybe(Local<Value>()), settings, attribute,
4909 i::FLAG_disable_old_api_accessors, false,
4910 getter_side_effect_type, setter_side_effect_type);
4911 }
4912
SetAccessorProperty(Local<Name> name,Local<Function> getter,Local<Function> setter,PropertyAttribute attribute,AccessControl settings)4913 void Object::SetAccessorProperty(Local<Name> name, Local<Function> getter,
4914 Local<Function> setter,
4915 PropertyAttribute attribute,
4916 AccessControl settings) {
4917 // TODO(verwaest): Remove |settings|.
4918 DCHECK_EQ(v8::DEFAULT, settings);
4919 auto self = Utils::OpenHandle(this);
4920 i::Isolate* isolate = self->GetIsolate();
4921 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
4922 i::HandleScope scope(isolate);
4923 if (!self->IsJSObject()) return;
4924 i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter);
4925 i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true);
4926 if (setter_i.is_null()) setter_i = isolate->factory()->null_value();
4927 i::JSObject::DefineAccessor(i::Handle<i::JSObject>::cast(self),
4928 v8::Utils::OpenHandle(*name), getter_i, setter_i,
4929 static_cast<i::PropertyAttributes>(attribute));
4930 }
4931
SetNativeDataProperty(v8::Local<v8::Context> context,v8::Local<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,v8::Local<Value> data,PropertyAttribute attributes,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)4932 Maybe<bool> Object::SetNativeDataProperty(
4933 v8::Local<v8::Context> context, v8::Local<Name> name,
4934 AccessorNameGetterCallback getter, AccessorNameSetterCallback setter,
4935 v8::Local<Value> data, PropertyAttribute attributes,
4936 SideEffectType getter_side_effect_type,
4937 SideEffectType setter_side_effect_type) {
4938 return ObjectSetAccessor(context, this, name, getter, setter, data, DEFAULT,
4939 attributes, true, false, getter_side_effect_type,
4940 setter_side_effect_type);
4941 }
4942
SetLazyDataProperty(v8::Local<v8::Context> context,v8::Local<Name> name,AccessorNameGetterCallback getter,v8::Local<Value> data,PropertyAttribute attributes,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)4943 Maybe<bool> Object::SetLazyDataProperty(
4944 v8::Local<v8::Context> context, v8::Local<Name> name,
4945 AccessorNameGetterCallback getter, v8::Local<Value> data,
4946 PropertyAttribute attributes, SideEffectType getter_side_effect_type,
4947 SideEffectType setter_side_effect_type) {
4948 return ObjectSetAccessor(context, this, name, getter,
4949 static_cast<AccessorNameSetterCallback>(nullptr),
4950 data, DEFAULT, attributes, true, true,
4951 getter_side_effect_type, setter_side_effect_type);
4952 }
4953
HasOwnProperty(Local<Context> context,Local<Name> key)4954 Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context,
4955 Local<Name> key) {
4956 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4957 ENTER_V8(isolate, context, Object, HasOwnProperty, Nothing<bool>(),
4958 i::HandleScope);
4959 auto self = Utils::OpenHandle(this);
4960 auto key_val = Utils::OpenHandle(*key);
4961 auto result = i::JSReceiver::HasOwnProperty(isolate, self, key_val);
4962 has_pending_exception = result.IsNothing();
4963 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4964 return result;
4965 }
4966
HasOwnProperty(Local<Context> context,uint32_t index)4967 Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context, uint32_t index) {
4968 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4969 ENTER_V8(isolate, context, Object, HasOwnProperty, Nothing<bool>(),
4970 i::HandleScope);
4971 auto self = Utils::OpenHandle(this);
4972 auto result = i::JSReceiver::HasOwnProperty(isolate, self, index);
4973 has_pending_exception = result.IsNothing();
4974 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4975 return result;
4976 }
4977
HasRealNamedProperty(Local<Context> context,Local<Name> key)4978 Maybe<bool> v8::Object::HasRealNamedProperty(Local<Context> context,
4979 Local<Name> key) {
4980 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4981 ENTER_V8_NO_SCRIPT(isolate, context, Object, HasRealNamedProperty,
4982 Nothing<bool>(), i::HandleScope);
4983 auto self = Utils::OpenHandle(this);
4984 if (!self->IsJSObject()) return Just(false);
4985 auto key_val = Utils::OpenHandle(*key);
4986 auto result = i::JSObject::HasRealNamedProperty(
4987 isolate, i::Handle<i::JSObject>::cast(self), key_val);
4988 has_pending_exception = result.IsNothing();
4989 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4990 return result;
4991 }
4992
HasRealIndexedProperty(Local<Context> context,uint32_t index)4993 Maybe<bool> v8::Object::HasRealIndexedProperty(Local<Context> context,
4994 uint32_t index) {
4995 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4996 ENTER_V8_NO_SCRIPT(isolate, context, Object, HasRealIndexedProperty,
4997 Nothing<bool>(), i::HandleScope);
4998 auto self = Utils::OpenHandle(this);
4999 if (!self->IsJSObject()) return Just(false);
5000 auto result = i::JSObject::HasRealElementProperty(
5001 isolate, i::Handle<i::JSObject>::cast(self), index);
5002 has_pending_exception = result.IsNothing();
5003 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
5004 return result;
5005 }
5006
HasRealNamedCallbackProperty(Local<Context> context,Local<Name> key)5007 Maybe<bool> v8::Object::HasRealNamedCallbackProperty(Local<Context> context,
5008 Local<Name> key) {
5009 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
5010 ENTER_V8_NO_SCRIPT(isolate, context, Object, HasRealNamedCallbackProperty,
5011 Nothing<bool>(), i::HandleScope);
5012 auto self = Utils::OpenHandle(this);
5013 if (!self->IsJSObject()) return Just(false);
5014 auto key_val = Utils::OpenHandle(*key);
5015 auto result = i::JSObject::HasRealNamedCallbackProperty(
5016 isolate, i::Handle<i::JSObject>::cast(self), key_val);
5017 has_pending_exception = result.IsNothing();
5018 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
5019 return result;
5020 }
5021
HasNamedLookupInterceptor() const5022 bool v8::Object::HasNamedLookupInterceptor() const {
5023 auto self = *Utils::OpenHandle(this);
5024 if (self.IsJSObject()) return false;
5025 return i::JSObject::cast(self).HasNamedInterceptor();
5026 }
5027
HasIndexedLookupInterceptor() const5028 bool v8::Object::HasIndexedLookupInterceptor() const {
5029 auto self = *Utils::OpenHandle(this);
5030 if (self.IsJSObject()) return false;
5031 return i::JSObject::cast(self).HasIndexedInterceptor();
5032 }
5033
GetRealNamedPropertyInPrototypeChain(Local<Context> context,Local<Name> key)5034 MaybeLocal<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
5035 Local<Context> context, Local<Name> key) {
5036 PREPARE_FOR_EXECUTION(context, Object, GetRealNamedPropertyInPrototypeChain,
5037 Value);
5038 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
5039 if (!self->IsJSObject()) return MaybeLocal<Value>();
5040 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
5041 i::PrototypeIterator iter(isolate, self);
5042 if (iter.IsAtEnd()) return MaybeLocal<Value>();
5043 i::Handle<i::JSReceiver> proto =
5044 i::PrototypeIterator::GetCurrent<i::JSReceiver>(iter);
5045 i::PropertyKey lookup_key(isolate, key_obj);
5046 i::LookupIterator it(isolate, self, lookup_key, proto,
5047 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
5048 Local<Value> result;
5049 has_pending_exception = !ToLocal<Value>(i::Object::GetProperty(&it), &result);
5050 RETURN_ON_FAILED_EXECUTION(Value);
5051 if (!it.IsFound()) return MaybeLocal<Value>();
5052 RETURN_ESCAPED(result);
5053 }
5054
5055 Maybe<PropertyAttribute>
GetRealNamedPropertyAttributesInPrototypeChain(Local<Context> context,Local<Name> key)5056 v8::Object::GetRealNamedPropertyAttributesInPrototypeChain(
5057 Local<Context> context, Local<Name> key) {
5058 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
5059 ENTER_V8(isolate, context, Object,
5060 GetRealNamedPropertyAttributesInPrototypeChain,
5061 Nothing<PropertyAttribute>(), i::HandleScope);
5062 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
5063 if (!self->IsJSObject()) return Nothing<PropertyAttribute>();
5064 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
5065 i::PrototypeIterator iter(isolate, self);
5066 if (iter.IsAtEnd()) return Nothing<PropertyAttribute>();
5067 i::Handle<i::JSReceiver> proto =
5068 i::PrototypeIterator::GetCurrent<i::JSReceiver>(iter);
5069 i::PropertyKey lookup_key(isolate, key_obj);
5070 i::LookupIterator it(isolate, self, lookup_key, proto,
5071 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
5072 Maybe<i::PropertyAttributes> result =
5073 i::JSReceiver::GetPropertyAttributes(&it);
5074 has_pending_exception = result.IsNothing();
5075 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
5076 if (!it.IsFound()) return Nothing<PropertyAttribute>();
5077 if (result.FromJust() == i::ABSENT) return Just(None);
5078 return Just(static_cast<PropertyAttribute>(result.FromJust()));
5079 }
5080
GetRealNamedProperty(Local<Context> context,Local<Name> key)5081 MaybeLocal<Value> v8::Object::GetRealNamedProperty(Local<Context> context,
5082 Local<Name> key) {
5083 PREPARE_FOR_EXECUTION(context, Object, GetRealNamedProperty, Value);
5084 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
5085 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
5086 i::PropertyKey lookup_key(isolate, key_obj);
5087 i::LookupIterator it(isolate, self, lookup_key, self,
5088 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
5089 Local<Value> result;
5090 has_pending_exception = !ToLocal<Value>(i::Object::GetProperty(&it), &result);
5091 RETURN_ON_FAILED_EXECUTION(Value);
5092 if (!it.IsFound()) return MaybeLocal<Value>();
5093 RETURN_ESCAPED(result);
5094 }
5095
GetRealNamedPropertyAttributes(Local<Context> context,Local<Name> key)5096 Maybe<PropertyAttribute> v8::Object::GetRealNamedPropertyAttributes(
5097 Local<Context> context, Local<Name> key) {
5098 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
5099 ENTER_V8(isolate, context, Object, GetRealNamedPropertyAttributes,
5100 Nothing<PropertyAttribute>(), i::HandleScope);
5101 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
5102 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
5103 i::PropertyKey lookup_key(isolate, key_obj);
5104 i::LookupIterator it(isolate, self, lookup_key, self,
5105 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
5106 auto result = i::JSReceiver::GetPropertyAttributes(&it);
5107 has_pending_exception = result.IsNothing();
5108 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
5109 if (!it.IsFound()) return Nothing<PropertyAttribute>();
5110 if (result.FromJust() == i::ABSENT) {
5111 return Just(static_cast<PropertyAttribute>(i::NONE));
5112 }
5113 return Just<PropertyAttribute>(
5114 static_cast<PropertyAttribute>(result.FromJust()));
5115 }
5116
Clone()5117 Local<v8::Object> v8::Object::Clone() {
5118 auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
5119 auto isolate = self->GetIsolate();
5120 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
5121 i::Handle<i::JSObject> result = isolate->factory()->CopyJSObject(self);
5122 return Utils::ToLocal(result);
5123 }
5124
5125 namespace {
CreationContextImpl(i::Handle<i::JSReceiver> self)5126 Local<v8::Context> CreationContextImpl(i::Handle<i::JSReceiver> self) {
5127 i::Handle<i::Context> context;
5128 if (self->GetCreationContext().ToHandle(&context)) {
5129 return Utils::ToLocal(context);
5130 }
5131
5132 return Local<v8::Context>();
5133 }
5134 } // namespace
5135
CreationContext()5136 Local<v8::Context> v8::Object::CreationContext() {
5137 auto self = Utils::OpenHandle(this);
5138 return CreationContextImpl(self);
5139 }
5140
CreationContext(const PersistentBase<Object> & object)5141 Local<v8::Context> v8::Object::CreationContext(
5142 const PersistentBase<Object>& object) {
5143 auto self = Utils::OpenHandle(object.val_);
5144 return CreationContextImpl(self);
5145 }
5146
GetCreationContext()5147 MaybeLocal<v8::Context> v8::Object::GetCreationContext() {
5148 auto self = Utils::OpenHandle(this);
5149 i::Handle<i::Context> context;
5150 if (self->GetCreationContext().ToHandle(&context)) {
5151 return Utils::ToLocal(context);
5152 }
5153 return MaybeLocal<v8::Context>();
5154 }
5155
GetCreationContextChecked()5156 Local<v8::Context> v8::Object::GetCreationContextChecked() {
5157 Local<Context> context;
5158 Utils::ApiCheck(GetCreationContext().ToLocal(&context),
5159 "v8::Object::GetCreationContextChecked",
5160 "No creation context available");
5161 return context;
5162 }
5163
GetIdentityHash()5164 int v8::Object::GetIdentityHash() {
5165 i::DisallowGarbageCollection no_gc;
5166 auto self = Utils::OpenHandle(this);
5167 auto isolate = self->GetIsolate();
5168 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
5169 i::HandleScope scope(isolate);
5170 return self->GetOrCreateIdentityHash(isolate).value();
5171 }
5172
IsCallable() const5173 bool v8::Object::IsCallable() const {
5174 auto self = Utils::OpenHandle(this);
5175 return self->IsCallable();
5176 }
5177
IsConstructor() const5178 bool v8::Object::IsConstructor() const {
5179 auto self = Utils::OpenHandle(this);
5180 return self->IsConstructor();
5181 }
5182
IsApiWrapper() const5183 bool v8::Object::IsApiWrapper() const {
5184 auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
5185 // Objects with embedder fields can wrap API objects.
5186 return self->MayHaveEmbedderFields();
5187 }
5188
IsUndetectable() const5189 bool v8::Object::IsUndetectable() const {
5190 auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
5191 return self->IsUndetectable();
5192 }
5193
CallAsFunction(Local<Context> context,Local<Value> recv,int argc,Local<Value> argv[])5194 MaybeLocal<Value> Object::CallAsFunction(Local<Context> context,
5195 Local<Value> recv, int argc,
5196 Local<Value> argv[]) {
5197 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
5198 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
5199 ENTER_V8(isolate, context, Object, CallAsFunction, MaybeLocal<Value>(),
5200 InternalEscapableScope);
5201 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
5202 i::NestedTimedHistogramScope execute_timer(isolate->counters()->execute(),
5203 isolate);
5204 auto self = Utils::OpenHandle(this);
5205 auto recv_obj = Utils::OpenHandle(*recv);
5206 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
5207 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
5208 Local<Value> result;
5209 has_pending_exception = !ToLocal<Value>(
5210 i::Execution::Call(isolate, self, recv_obj, argc, args), &result);
5211 RETURN_ON_FAILED_EXECUTION(Value);
5212 RETURN_ESCAPED(result);
5213 }
5214
CallAsConstructor(Local<Context> context,int argc,Local<Value> argv[])5215 MaybeLocal<Value> Object::CallAsConstructor(Local<Context> context, int argc,
5216 Local<Value> argv[]) {
5217 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
5218 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
5219 ENTER_V8(isolate, context, Object, CallAsConstructor, MaybeLocal<Value>(),
5220 InternalEscapableScope);
5221 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
5222 i::NestedTimedHistogramScope execute_timer(isolate->counters()->execute(),
5223 isolate);
5224 auto self = Utils::OpenHandle(this);
5225 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
5226 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
5227 Local<Value> result;
5228 has_pending_exception = !ToLocal<Value>(
5229 i::Execution::New(isolate, self, self, argc, args), &result);
5230 RETURN_ON_FAILED_EXECUTION(Value);
5231 RETURN_ESCAPED(result);
5232 }
5233
New(Local<Context> context,FunctionCallback callback,Local<Value> data,int length,ConstructorBehavior behavior,SideEffectType side_effect_type)5234 MaybeLocal<Function> Function::New(Local<Context> context,
5235 FunctionCallback callback, Local<Value> data,
5236 int length, ConstructorBehavior behavior,
5237 SideEffectType side_effect_type) {
5238 i::Isolate* isolate = Utils::OpenHandle(*context)->GetIsolate();
5239 API_RCS_SCOPE(isolate, Function, New);
5240 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
5241 auto templ =
5242 FunctionTemplateNew(isolate, callback, data, Local<Signature>(), length,
5243 behavior, true, Local<Private>(), side_effect_type);
5244 return templ->GetFunction(context);
5245 }
5246
NewInstance(Local<Context> context,int argc,v8::Local<v8::Value> argv[]) const5247 MaybeLocal<Object> Function::NewInstance(Local<Context> context, int argc,
5248 v8::Local<v8::Value> argv[]) const {
5249 return NewInstanceWithSideEffectType(context, argc, argv,
5250 SideEffectType::kHasSideEffect);
5251 }
5252
NewInstanceWithSideEffectType(Local<Context> context,int argc,v8::Local<v8::Value> argv[],SideEffectType side_effect_type) const5253 MaybeLocal<Object> Function::NewInstanceWithSideEffectType(
5254 Local<Context> context, int argc, v8::Local<v8::Value> argv[],
5255 SideEffectType side_effect_type) const {
5256 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
5257 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
5258 ENTER_V8(isolate, context, Function, NewInstance, MaybeLocal<Object>(),
5259 InternalEscapableScope);
5260 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
5261 i::NestedTimedHistogramScope execute_timer(isolate->counters()->execute(),
5262 isolate);
5263 auto self = Utils::OpenHandle(this);
5264 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
5265 bool should_set_has_no_side_effect =
5266 side_effect_type == SideEffectType::kHasNoSideEffect &&
5267 isolate->debug_execution_mode() == i::DebugInfo::kSideEffects;
5268 if (should_set_has_no_side_effect) {
5269 CHECK(self->IsJSFunction() &&
5270 i::JSFunction::cast(*self).shared().IsApiFunction());
5271 i::Object obj =
5272 i::JSFunction::cast(*self).shared().get_api_func_data().call_code(
5273 kAcquireLoad);
5274 if (obj.IsCallHandlerInfo()) {
5275 i::CallHandlerInfo handler_info = i::CallHandlerInfo::cast(obj);
5276 if (!handler_info.IsSideEffectFreeCallHandlerInfo()) {
5277 handler_info.SetNextCallHasNoSideEffect();
5278 }
5279 }
5280 }
5281 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
5282 Local<Object> result;
5283 has_pending_exception = !ToLocal<Object>(
5284 i::Execution::New(isolate, self, self, argc, args), &result);
5285 if (should_set_has_no_side_effect) {
5286 i::Object obj =
5287 i::JSFunction::cast(*self).shared().get_api_func_data().call_code(
5288 kAcquireLoad);
5289 if (obj.IsCallHandlerInfo()) {
5290 i::CallHandlerInfo handler_info = i::CallHandlerInfo::cast(obj);
5291 if (has_pending_exception) {
5292 // Restore the map if an exception prevented restoration.
5293 handler_info.NextCallHasNoSideEffect();
5294 } else {
5295 DCHECK(handler_info.IsSideEffectCallHandlerInfo() ||
5296 handler_info.IsSideEffectFreeCallHandlerInfo());
5297 }
5298 }
5299 }
5300 RETURN_ON_FAILED_EXECUTION(Object);
5301 RETURN_ESCAPED(result);
5302 }
5303
Call(Local<Context> context,v8::Local<v8::Value> recv,int argc,v8::Local<v8::Value> argv[])5304 MaybeLocal<v8::Value> Function::Call(Local<Context> context,
5305 v8::Local<v8::Value> recv, int argc,
5306 v8::Local<v8::Value> argv[]) {
5307 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
5308 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
5309 ENTER_V8(isolate, context, Function, Call, MaybeLocal<Value>(),
5310 InternalEscapableScope);
5311 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
5312 i::NestedTimedHistogramScope execute_timer(isolate->counters()->execute(),
5313 isolate);
5314 auto self = Utils::OpenHandle(this);
5315 Utils::ApiCheck(!self.is_null(), "v8::Function::Call",
5316 "Function to be called is a null pointer");
5317 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
5318 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
5319 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
5320 Local<Value> result;
5321 has_pending_exception = !ToLocal<Value>(
5322 i::Execution::Call(isolate, self, recv_obj, argc, args), &result);
5323 RETURN_ON_FAILED_EXECUTION(Value);
5324 RETURN_ESCAPED(result);
5325 }
5326
SetName(v8::Local<v8::String> name)5327 void Function::SetName(v8::Local<v8::String> name) {
5328 auto self = Utils::OpenHandle(this);
5329 if (!self->IsJSFunction()) return;
5330 auto func = i::Handle<i::JSFunction>::cast(self);
5331 ASSERT_NO_SCRIPT_NO_EXCEPTION(func->GetIsolate());
5332 func->shared().SetName(*Utils::OpenHandle(*name));
5333 }
5334
GetName() const5335 Local<Value> Function::GetName() const {
5336 auto self = Utils::OpenHandle(this);
5337 i::Isolate* isolate = self->GetIsolate();
5338 if (self->IsJSBoundFunction()) {
5339 auto func = i::Handle<i::JSBoundFunction>::cast(self);
5340 i::Handle<i::Object> name;
5341 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, name,
5342 i::JSBoundFunction::GetName(isolate, func),
5343 Local<Value>());
5344 return Utils::ToLocal(name);
5345 }
5346 if (self->IsJSFunction()) {
5347 auto func = i::Handle<i::JSFunction>::cast(self);
5348 return Utils::ToLocal(handle(func->shared().Name(), isolate));
5349 }
5350 return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
5351 }
5352
GetInferredName() const5353 Local<Value> Function::GetInferredName() const {
5354 auto self = Utils::OpenHandle(this);
5355 if (!self->IsJSFunction()) {
5356 return ToApiHandle<Primitive>(
5357 self->GetIsolate()->factory()->undefined_value());
5358 }
5359 auto func = i::Handle<i::JSFunction>::cast(self);
5360 return Utils::ToLocal(
5361 i::Handle<i::Object>(func->shared().inferred_name(), func->GetIsolate()));
5362 }
5363
GetDebugName() const5364 Local<Value> Function::GetDebugName() const {
5365 auto self = Utils::OpenHandle(this);
5366 if (!self->IsJSFunction()) {
5367 return ToApiHandle<Primitive>(
5368 self->GetIsolate()->factory()->undefined_value());
5369 }
5370 auto func = i::Handle<i::JSFunction>::cast(self);
5371 i::Handle<i::String> name = i::JSFunction::GetDebugName(func);
5372 return Utils::ToLocal(i::Handle<i::Object>(*name, self->GetIsolate()));
5373 }
5374
GetScriptOrigin() const5375 ScriptOrigin Function::GetScriptOrigin() const {
5376 auto self = Utils::OpenHandle(this);
5377 auto isolate = reinterpret_cast<v8::Isolate*>(self->GetIsolate());
5378 if (!self->IsJSFunction()) return v8::ScriptOrigin(isolate, Local<Value>());
5379 auto func = i::Handle<i::JSFunction>::cast(self);
5380 if (func->shared().script().IsScript()) {
5381 i::Handle<i::Script> script(i::Script::cast(func->shared().script()),
5382 func->GetIsolate());
5383 return GetScriptOriginForScript(func->GetIsolate(), script);
5384 }
5385 return v8::ScriptOrigin(isolate, Local<Value>());
5386 }
5387
5388 const int Function::kLineOffsetNotFound = -1;
5389
GetScriptLineNumber() const5390 int Function::GetScriptLineNumber() const {
5391 auto self = Utils::OpenHandle(this);
5392 if (!self->IsJSFunction()) {
5393 return kLineOffsetNotFound;
5394 }
5395 auto func = i::Handle<i::JSFunction>::cast(self);
5396 if (func->shared().script().IsScript()) {
5397 i::Handle<i::Script> script(i::Script::cast(func->shared().script()),
5398 func->GetIsolate());
5399 return i::Script::GetLineNumber(script, func->shared().StartPosition());
5400 }
5401 return kLineOffsetNotFound;
5402 }
5403
GetScriptColumnNumber() const5404 int Function::GetScriptColumnNumber() const {
5405 auto self = Utils::OpenHandle(this);
5406 if (!self->IsJSFunction()) {
5407 return kLineOffsetNotFound;
5408 }
5409 auto func = i::Handle<i::JSFunction>::cast(self);
5410 if (func->shared().script().IsScript()) {
5411 i::Handle<i::Script> script(i::Script::cast(func->shared().script()),
5412 func->GetIsolate());
5413 return i::Script::GetColumnNumber(script, func->shared().StartPosition());
5414 }
5415 return kLineOffsetNotFound;
5416 }
5417
GetUnboundScript() const5418 MaybeLocal<UnboundScript> Function::GetUnboundScript() const {
5419 i::Handle<i::Object> self = Utils::OpenHandle(this);
5420 if (!self->IsJSFunction()) return MaybeLocal<UnboundScript>();
5421 i::SharedFunctionInfo sfi = i::JSFunction::cast(*self).shared();
5422 i::Isolate* isolate = sfi.GetIsolate();
5423 return ToApiHandle<UnboundScript>(i::handle(sfi, isolate));
5424 }
5425
ScriptId() const5426 int Function::ScriptId() const {
5427 i::JSReceiver self = *Utils::OpenHandle(this);
5428 if (!self.IsJSFunction()) return v8::UnboundScript::kNoScriptId;
5429 auto func = i::JSFunction::cast(self);
5430 if (!func.shared().script().IsScript()) return v8::UnboundScript::kNoScriptId;
5431 return i::Script::cast(func.shared().script()).id();
5432 }
5433
GetBoundFunction() const5434 Local<v8::Value> Function::GetBoundFunction() const {
5435 auto self = Utils::OpenHandle(this);
5436 if (self->IsJSBoundFunction()) {
5437 auto bound_function = i::Handle<i::JSBoundFunction>::cast(self);
5438 auto bound_target_function = i::handle(
5439 bound_function->bound_target_function(), bound_function->GetIsolate());
5440 return Utils::CallableToLocal(bound_target_function);
5441 }
5442 return v8::Undefined(reinterpret_cast<v8::Isolate*>(self->GetIsolate()));
5443 }
5444
FunctionProtoToString(Local<Context> context)5445 MaybeLocal<String> v8::Function::FunctionProtoToString(Local<Context> context) {
5446 PREPARE_FOR_EXECUTION(context, Function, FunctionProtoToString, String);
5447 auto self = Utils::OpenHandle(this);
5448 Local<Value> result;
5449 has_pending_exception = !ToLocal<Value>(
5450 i::Execution::CallBuiltin(isolate, isolate->function_to_string(), self, 0,
5451 nullptr),
5452 &result);
5453 RETURN_ON_FAILED_EXECUTION(String);
5454 RETURN_ESCAPED(Local<String>::Cast(result));
5455 }
5456
GetIdentityHash()5457 int Name::GetIdentityHash() {
5458 auto self = Utils::OpenHandle(this);
5459 return static_cast<int>(self->EnsureHash());
5460 }
5461
Length() const5462 int String::Length() const {
5463 i::Handle<i::String> str = Utils::OpenHandle(this);
5464 return str->length();
5465 }
5466
IsOneByte() const5467 bool String::IsOneByte() const {
5468 i::Handle<i::String> str = Utils::OpenHandle(this);
5469 return str->IsOneByteRepresentation();
5470 }
5471
5472 // Helpers for ContainsOnlyOneByteHelper
5473 template <size_t size>
5474 struct OneByteMask;
5475 template <>
5476 struct OneByteMask<4> {
5477 static const uint32_t value = 0xFF00FF00;
5478 };
5479 template <>
5480 struct OneByteMask<8> {
5481 static const uint64_t value = 0xFF00'FF00'FF00'FF00;
5482 };
5483 static const uintptr_t kOneByteMask = OneByteMask<sizeof(uintptr_t)>::value;
5484 static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1;
Unaligned(const uint16_t * chars)5485 static inline bool Unaligned(const uint16_t* chars) {
5486 return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask;
5487 }
5488
Align(const uint16_t * chars)5489 static inline const uint16_t* Align(const uint16_t* chars) {
5490 return reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(chars) &
5491 ~kAlignmentMask);
5492 }
5493
5494 class ContainsOnlyOneByteHelper {
5495 public:
ContainsOnlyOneByteHelper()5496 ContainsOnlyOneByteHelper() : is_one_byte_(true) {}
5497 ContainsOnlyOneByteHelper(const ContainsOnlyOneByteHelper&) = delete;
5498 ContainsOnlyOneByteHelper& operator=(const ContainsOnlyOneByteHelper&) =
5499 delete;
Check(i::String string)5500 bool Check(i::String string) {
5501 i::ConsString cons_string = i::String::VisitFlat(this, string, 0);
5502 if (cons_string.is_null()) return is_one_byte_;
5503 return CheckCons(cons_string);
5504 }
VisitOneByteString(const uint8_t * chars,int length)5505 void VisitOneByteString(const uint8_t* chars, int length) {
5506 // Nothing to do.
5507 }
VisitTwoByteString(const uint16_t * chars,int length)5508 void VisitTwoByteString(const uint16_t* chars, int length) {
5509 // Accumulated bits.
5510 uintptr_t acc = 0;
5511 // Align to uintptr_t.
5512 const uint16_t* end = chars + length;
5513 while (Unaligned(chars) && chars != end) {
5514 acc |= *chars++;
5515 }
5516 // Read word aligned in blocks,
5517 // checking the return value at the end of each block.
5518 const uint16_t* aligned_end = Align(end);
5519 const int increment = sizeof(uintptr_t) / sizeof(uint16_t);
5520 const int inner_loops = 16;
5521 while (chars + inner_loops * increment < aligned_end) {
5522 for (int i = 0; i < inner_loops; i++) {
5523 acc |= *reinterpret_cast<const uintptr_t*>(chars);
5524 chars += increment;
5525 }
5526 // Check for early return.
5527 if ((acc & kOneByteMask) != 0) {
5528 is_one_byte_ = false;
5529 return;
5530 }
5531 }
5532 // Read the rest.
5533 while (chars != end) {
5534 acc |= *chars++;
5535 }
5536 // Check result.
5537 if ((acc & kOneByteMask) != 0) is_one_byte_ = false;
5538 }
5539
5540 private:
CheckCons(i::ConsString cons_string)5541 bool CheckCons(i::ConsString cons_string) {
5542 while (true) {
5543 // Check left side if flat.
5544 i::String left = cons_string.first();
5545 i::ConsString left_as_cons = i::String::VisitFlat(this, left, 0);
5546 if (!is_one_byte_) return false;
5547 // Check right side if flat.
5548 i::String right = cons_string.second();
5549 i::ConsString right_as_cons = i::String::VisitFlat(this, right, 0);
5550 if (!is_one_byte_) return false;
5551 // Standard recurse/iterate trick.
5552 if (!left_as_cons.is_null() && !right_as_cons.is_null()) {
5553 if (left.length() < right.length()) {
5554 CheckCons(left_as_cons);
5555 cons_string = right_as_cons;
5556 } else {
5557 CheckCons(right_as_cons);
5558 cons_string = left_as_cons;
5559 }
5560 // Check fast return.
5561 if (!is_one_byte_) return false;
5562 continue;
5563 }
5564 // Descend left in place.
5565 if (!left_as_cons.is_null()) {
5566 cons_string = left_as_cons;
5567 continue;
5568 }
5569 // Descend right in place.
5570 if (!right_as_cons.is_null()) {
5571 cons_string = right_as_cons;
5572 continue;
5573 }
5574 // Terminate.
5575 break;
5576 }
5577 return is_one_byte_;
5578 }
5579 bool is_one_byte_;
5580 };
5581
ContainsOnlyOneByte() const5582 bool String::ContainsOnlyOneByte() const {
5583 i::Handle<i::String> str = Utils::OpenHandle(this);
5584 if (str->IsOneByteRepresentation()) return true;
5585 ContainsOnlyOneByteHelper helper;
5586 return helper.Check(*str);
5587 }
5588
Utf8Length(Isolate * isolate) const5589 int String::Utf8Length(Isolate* isolate) const {
5590 i::Handle<i::String> str = Utils::OpenHandle(this);
5591 str = i::String::Flatten(reinterpret_cast<i::Isolate*>(isolate), str);
5592 int length = str->length();
5593 if (length == 0) return 0;
5594 i::DisallowGarbageCollection no_gc;
5595 i::String::FlatContent flat = str->GetFlatContent(no_gc);
5596 DCHECK(flat.IsFlat());
5597 int utf8_length = 0;
5598 if (flat.IsOneByte()) {
5599 for (uint8_t c : flat.ToOneByteVector()) {
5600 utf8_length += c >> 7;
5601 }
5602 utf8_length += length;
5603 } else {
5604 int last_character = unibrow::Utf16::kNoPreviousCharacter;
5605 for (uint16_t c : flat.ToUC16Vector()) {
5606 utf8_length += unibrow::Utf8::Length(c, last_character);
5607 last_character = c;
5608 }
5609 }
5610 return utf8_length;
5611 }
5612
5613 namespace {
5614 // Writes the flat content of a string to a buffer. This is done in two phases.
5615 // The first phase calculates a pessimistic estimate (writable_length) on how
5616 // many code units can be safely written without exceeding the buffer capacity
5617 // and without leaving at a lone surrogate. The estimated number of code units
5618 // is then written out in one go, and the reported byte usage is used to
5619 // correct the estimate. This is repeated until the estimate becomes <= 0 or
5620 // all code units have been written out. The second phase writes out code
5621 // units until the buffer capacity is reached, would be exceeded by the next
5622 // unit, or all code units have been written out.
5623 template <typename Char>
WriteUtf8Impl(base::Vector<const Char> string,char * write_start,int write_capacity,int options,int * utf16_chars_read_out)5624 static int WriteUtf8Impl(base::Vector<const Char> string, char* write_start,
5625 int write_capacity, int options,
5626 int* utf16_chars_read_out) {
5627 bool write_null = !(options & v8::String::NO_NULL_TERMINATION);
5628 bool replace_invalid_utf8 = (options & v8::String::REPLACE_INVALID_UTF8);
5629 char* current_write = write_start;
5630 const Char* read_start = string.begin();
5631 int read_index = 0;
5632 int read_length = string.length();
5633 int prev_char = unibrow::Utf16::kNoPreviousCharacter;
5634 // Do a fast loop where there is no exit capacity check.
5635 // Need enough space to write everything but one character.
5636 STATIC_ASSERT(unibrow::Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 3);
5637 static const int kMaxSizePerChar = sizeof(Char) == 1 ? 2 : 3;
5638 while (read_index < read_length) {
5639 int up_to = read_length;
5640 if (write_capacity != -1) {
5641 int remaining_capacity =
5642 write_capacity - static_cast<int>(current_write - write_start);
5643 int writable_length =
5644 (remaining_capacity - kMaxSizePerChar) / kMaxSizePerChar;
5645 // Need to drop into slow loop.
5646 if (writable_length <= 0) break;
5647 up_to = std::min(up_to, read_index + writable_length);
5648 }
5649 // Write the characters to the stream.
5650 if (sizeof(Char) == 1) {
5651 // Simply memcpy if we only have ASCII characters.
5652 uint8_t char_mask = 0;
5653 for (int i = read_index; i < up_to; i++) char_mask |= read_start[i];
5654 if ((char_mask & 0x80) == 0) {
5655 int copy_length = up_to - read_index;
5656 memcpy(current_write, read_start + read_index, copy_length);
5657 current_write += copy_length;
5658 read_index = up_to;
5659 } else {
5660 for (; read_index < up_to; read_index++) {
5661 current_write += unibrow::Utf8::EncodeOneByte(
5662 current_write, static_cast<uint8_t>(read_start[read_index]));
5663 DCHECK(write_capacity == -1 ||
5664 (current_write - write_start) <= write_capacity);
5665 }
5666 }
5667 } else {
5668 for (; read_index < up_to; read_index++) {
5669 uint16_t character = read_start[read_index];
5670 current_write += unibrow::Utf8::Encode(current_write, character,
5671 prev_char, replace_invalid_utf8);
5672 prev_char = character;
5673 DCHECK(write_capacity == -1 ||
5674 (current_write - write_start) <= write_capacity);
5675 }
5676 }
5677 }
5678 if (read_index < read_length) {
5679 DCHECK_NE(-1, write_capacity);
5680 // Aborted due to limited capacity. Check capacity on each iteration.
5681 int remaining_capacity =
5682 write_capacity - static_cast<int>(current_write - write_start);
5683 DCHECK_GE(remaining_capacity, 0);
5684 for (; read_index < read_length && remaining_capacity > 0; read_index++) {
5685 uint32_t character = read_start[read_index];
5686 int written = 0;
5687 // We can't use a local buffer here because Encode needs to modify
5688 // previous characters in the stream. We know, however, that
5689 // exactly one character will be advanced.
5690 if (unibrow::Utf16::IsSurrogatePair(prev_char, character)) {
5691 written = unibrow::Utf8::Encode(current_write, character, prev_char,
5692 replace_invalid_utf8);
5693 DCHECK_EQ(written, 1);
5694 } else {
5695 // Use a scratch buffer to check the required characters.
5696 char temp_buffer[unibrow::Utf8::kMaxEncodedSize];
5697 // Encoding a surrogate pair to Utf8 always takes 4 bytes.
5698 static const int kSurrogatePairEncodedSize =
5699 static_cast<int>(unibrow::Utf8::kMaxEncodedSize);
5700 // For REPLACE_INVALID_UTF8, catch the case where we cut off in the
5701 // middle of a surrogate pair. Abort before encoding the pair instead.
5702 if (replace_invalid_utf8 &&
5703 remaining_capacity < kSurrogatePairEncodedSize &&
5704 unibrow::Utf16::IsLeadSurrogate(character) &&
5705 read_index + 1 < read_length &&
5706 unibrow::Utf16::IsTrailSurrogate(read_start[read_index + 1])) {
5707 write_null = false;
5708 break;
5709 }
5710 // Can't encode using prev_char as gcc has array bounds issues.
5711 written = unibrow::Utf8::Encode(temp_buffer, character,
5712 unibrow::Utf16::kNoPreviousCharacter,
5713 replace_invalid_utf8);
5714 if (written > remaining_capacity) {
5715 // Won't fit. Abort and do not null-terminate the result.
5716 write_null = false;
5717 break;
5718 }
5719 // Copy over the character from temp_buffer.
5720 for (int i = 0; i < written; i++) current_write[i] = temp_buffer[i];
5721 }
5722
5723 current_write += written;
5724 remaining_capacity -= written;
5725 prev_char = character;
5726 }
5727 }
5728
5729 // Write out number of utf16 characters written to the stream.
5730 if (utf16_chars_read_out != nullptr) *utf16_chars_read_out = read_index;
5731
5732 // Only null-terminate if there's space.
5733 if (write_null && (write_capacity == -1 ||
5734 (current_write - write_start) < write_capacity)) {
5735 *current_write++ = '\0';
5736 }
5737 return static_cast<int>(current_write - write_start);
5738 }
5739 } // anonymous namespace
5740
WriteUtf8(Isolate * v8_isolate,char * buffer,int capacity,int * nchars_ref,int options) const5741 int String::WriteUtf8(Isolate* v8_isolate, char* buffer, int capacity,
5742 int* nchars_ref, int options) const {
5743 i::Handle<i::String> str = Utils::OpenHandle(this);
5744 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
5745 API_RCS_SCOPE(isolate, String, WriteUtf8);
5746 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
5747 str = i::String::Flatten(isolate, str);
5748 i::DisallowGarbageCollection no_gc;
5749 i::String::FlatContent content = str->GetFlatContent(no_gc);
5750 if (content.IsOneByte()) {
5751 return WriteUtf8Impl<uint8_t>(content.ToOneByteVector(), buffer, capacity,
5752 options, nchars_ref);
5753 } else {
5754 return WriteUtf8Impl<uint16_t>(content.ToUC16Vector(), buffer, capacity,
5755 options, nchars_ref);
5756 }
5757 }
5758
5759 template <typename CharType>
WriteHelper(i::Isolate * isolate,const String * string,CharType * buffer,int start,int length,int options)5760 static inline int WriteHelper(i::Isolate* isolate, const String* string,
5761 CharType* buffer, int start, int length,
5762 int options) {
5763 API_RCS_SCOPE(isolate, String, Write);
5764 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
5765 DCHECK(start >= 0 && length >= -1);
5766 i::Handle<i::String> str = Utils::OpenHandle(string);
5767 str = i::String::Flatten(isolate, str);
5768 int end = start + length;
5769 if ((length == -1) || (length > str->length() - start)) end = str->length();
5770 if (end < 0) return 0;
5771 int write_length = end - start;
5772 if (start < end) i::String::WriteToFlat(*str, buffer, start, write_length);
5773 if (!(options & String::NO_NULL_TERMINATION) &&
5774 (length == -1 || write_length < length)) {
5775 buffer[write_length] = '\0';
5776 }
5777 return write_length;
5778 }
5779
WriteOneByte(Isolate * isolate,uint8_t * buffer,int start,int length,int options) const5780 int String::WriteOneByte(Isolate* isolate, uint8_t* buffer, int start,
5781 int length, int options) const {
5782 return WriteHelper(reinterpret_cast<i::Isolate*>(isolate), this, buffer,
5783 start, length, options);
5784 }
5785
Write(Isolate * isolate,uint16_t * buffer,int start,int length,int options) const5786 int String::Write(Isolate* isolate, uint16_t* buffer, int start, int length,
5787 int options) const {
5788 return WriteHelper(reinterpret_cast<i::Isolate*>(isolate), this, buffer,
5789 start, length, options);
5790 }
5791
IsExternal() const5792 bool v8::String::IsExternal() const {
5793 i::Handle<i::String> str = Utils::OpenHandle(this);
5794 return i::StringShape(*str).IsExternal();
5795 }
5796
IsExternalTwoByte() const5797 bool v8::String::IsExternalTwoByte() const {
5798 i::Handle<i::String> str = Utils::OpenHandle(this);
5799 return i::StringShape(*str).IsExternalTwoByte();
5800 }
5801
IsExternalOneByte() const5802 bool v8::String::IsExternalOneByte() const {
5803 i::Handle<i::String> str = Utils::OpenHandle(this);
5804 return i::StringShape(*str).IsExternalOneByte();
5805 }
5806
VerifyExternalStringResource(v8::String::ExternalStringResource * value) const5807 void v8::String::VerifyExternalStringResource(
5808 v8::String::ExternalStringResource* value) const {
5809 i::DisallowGarbageCollection no_gc;
5810 i::String str = *Utils::OpenHandle(this);
5811 const v8::String::ExternalStringResource* expected;
5812
5813 if (str.IsThinString()) {
5814 str = i::ThinString::cast(str).actual();
5815 }
5816
5817 if (i::StringShape(str).IsExternalTwoByte()) {
5818 const void* resource = i::ExternalTwoByteString::cast(str).resource();
5819 expected = reinterpret_cast<const ExternalStringResource*>(resource);
5820 } else {
5821 expected = nullptr;
5822 }
5823 CHECK_EQ(expected, value);
5824 }
5825
VerifyExternalStringResourceBase(v8::String::ExternalStringResourceBase * value,Encoding encoding) const5826 void v8::String::VerifyExternalStringResourceBase(
5827 v8::String::ExternalStringResourceBase* value, Encoding encoding) const {
5828 i::DisallowGarbageCollection no_gc;
5829 i::String str = *Utils::OpenHandle(this);
5830 const v8::String::ExternalStringResourceBase* expected;
5831 Encoding expectedEncoding;
5832
5833 if (str.IsThinString()) {
5834 str = i::ThinString::cast(str).actual();
5835 }
5836
5837 if (i::StringShape(str).IsExternalOneByte()) {
5838 const void* resource = i::ExternalOneByteString::cast(str).resource();
5839 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
5840 expectedEncoding = ONE_BYTE_ENCODING;
5841 } else if (i::StringShape(str).IsExternalTwoByte()) {
5842 const void* resource = i::ExternalTwoByteString::cast(str).resource();
5843 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
5844 expectedEncoding = TWO_BYTE_ENCODING;
5845 } else {
5846 expected = nullptr;
5847 expectedEncoding =
5848 str.IsOneByteRepresentation() ? ONE_BYTE_ENCODING : TWO_BYTE_ENCODING;
5849 }
5850 CHECK_EQ(expected, value);
5851 CHECK_EQ(expectedEncoding, encoding);
5852 }
5853
GetExternalStringResourceSlow() const5854 String::ExternalStringResource* String::GetExternalStringResourceSlow() const {
5855 i::DisallowGarbageCollection no_gc;
5856 using I = internal::Internals;
5857 i::String str = *Utils::OpenHandle(this);
5858
5859 if (str.IsThinString()) {
5860 str = i::ThinString::cast(str).actual();
5861 }
5862
5863 if (i::StringShape(str).IsExternalTwoByte()) {
5864 internal::Isolate* isolate = I::GetIsolateForSandbox(str.ptr());
5865 internal::Address value = I::ReadExternalPointerField(
5866 isolate, str.ptr(), I::kStringResourceOffset,
5867 internal::kExternalStringResourceTag);
5868 return reinterpret_cast<String::ExternalStringResource*>(value);
5869 }
5870 return nullptr;
5871 }
5872
UpdateDataCache()5873 void String::ExternalStringResource::UpdateDataCache() {
5874 DCHECK(IsCacheable());
5875 cached_data_ = data();
5876 }
5877
CheckCachedDataInvariants() const5878 void String::ExternalStringResource::CheckCachedDataInvariants() const {
5879 DCHECK(IsCacheable() && cached_data_ != nullptr);
5880 }
5881
UpdateDataCache()5882 void String::ExternalOneByteStringResource::UpdateDataCache() {
5883 DCHECK(IsCacheable());
5884 cached_data_ = data();
5885 }
5886
CheckCachedDataInvariants() const5887 void String::ExternalOneByteStringResource::CheckCachedDataInvariants() const {
5888 DCHECK(IsCacheable() && cached_data_ != nullptr);
5889 }
5890
GetExternalStringResourceBaseSlow(String::Encoding * encoding_out) const5891 String::ExternalStringResourceBase* String::GetExternalStringResourceBaseSlow(
5892 String::Encoding* encoding_out) const {
5893 i::DisallowGarbageCollection no_gc;
5894 using I = internal::Internals;
5895 ExternalStringResourceBase* resource = nullptr;
5896 i::String str = *Utils::OpenHandle(this);
5897
5898 if (str.IsThinString()) {
5899 str = i::ThinString::cast(str).actual();
5900 }
5901
5902 internal::Address string = str.ptr();
5903 int type =
5904 I::GetInstanceType(string) & I::kStringRepresentationAndEncodingMask;
5905 *encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask);
5906 if (i::StringShape(str).IsExternalOneByte() ||
5907 i::StringShape(str).IsExternalTwoByte()) {
5908 internal::Isolate* isolate = I::GetIsolateForSandbox(string);
5909 internal::Address value =
5910 I::ReadExternalPointerField(isolate, string, I::kStringResourceOffset,
5911 internal::kExternalStringResourceTag);
5912 resource = reinterpret_cast<ExternalStringResourceBase*>(value);
5913 }
5914 return resource;
5915 }
5916
5917 const v8::String::ExternalOneByteStringResource*
GetExternalOneByteStringResource() const5918 v8::String::GetExternalOneByteStringResource() const {
5919 i::DisallowGarbageCollection no_gc;
5920 i::String str = *Utils::OpenHandle(this);
5921 if (i::StringShape(str).IsExternalOneByte()) {
5922 return i::ExternalOneByteString::cast(str).resource();
5923 } else if (str.IsThinString()) {
5924 str = i::ThinString::cast(str).actual();
5925 if (i::StringShape(str).IsExternalOneByte()) {
5926 return i::ExternalOneByteString::cast(str).resource();
5927 }
5928 }
5929 return nullptr;
5930 }
5931
Description(Isolate * isolate) const5932 Local<Value> Symbol::Description(Isolate* isolate) const {
5933 i::Handle<i::Symbol> sym = Utils::OpenHandle(this);
5934 i::Handle<i::Object> description(sym->description(),
5935 reinterpret_cast<i::Isolate*>(isolate));
5936 return Utils::ToLocal(description);
5937 }
5938
Name() const5939 Local<Value> Private::Name() const {
5940 const Symbol* sym = reinterpret_cast<const Symbol*>(this);
5941 i::Handle<i::Symbol> i_sym = Utils::OpenHandle(sym);
5942 // v8::Private symbols are created by API and are therefore writable, so we
5943 // can always recover an Isolate.
5944 i::Isolate* isolate = i::GetIsolateFromWritableObject(*i_sym);
5945 return sym->Description(reinterpret_cast<Isolate*>(isolate));
5946 }
5947
Value() const5948 double Number::Value() const {
5949 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5950 return obj->Number();
5951 }
5952
Value() const5953 bool Boolean::Value() const {
5954 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5955 return obj->IsTrue();
5956 }
5957
Value() const5958 int64_t Integer::Value() const {
5959 i::Object obj = *Utils::OpenHandle(this);
5960 if (obj.IsSmi()) {
5961 return i::Smi::ToInt(obj);
5962 } else {
5963 return static_cast<int64_t>(obj.Number());
5964 }
5965 }
5966
Value() const5967 int32_t Int32::Value() const {
5968 i::Object obj = *Utils::OpenHandle(this);
5969 if (obj.IsSmi()) {
5970 return i::Smi::ToInt(obj);
5971 } else {
5972 return static_cast<int32_t>(obj.Number());
5973 }
5974 }
5975
Value() const5976 uint32_t Uint32::Value() const {
5977 i::Object obj = *Utils::OpenHandle(this);
5978 if (obj.IsSmi()) {
5979 return i::Smi::ToInt(obj);
5980 } else {
5981 return static_cast<uint32_t>(obj.Number());
5982 }
5983 }
5984
InternalFieldCount() const5985 int v8::Object::InternalFieldCount() const {
5986 i::JSReceiver self = *Utils::OpenHandle(this);
5987 if (!self.IsJSObject()) return 0;
5988 return i::JSObject::cast(self).GetEmbedderFieldCount();
5989 }
5990
InternalFieldOK(i::Handle<i::JSReceiver> obj,int index,const char * location)5991 static bool InternalFieldOK(i::Handle<i::JSReceiver> obj, int index,
5992 const char* location) {
5993 return Utils::ApiCheck(
5994 obj->IsJSObject() &&
5995 (index < i::Handle<i::JSObject>::cast(obj)->GetEmbedderFieldCount()),
5996 location, "Internal field out of bounds");
5997 }
5998
SlowGetInternalField(int index)5999 Local<Value> v8::Object::SlowGetInternalField(int index) {
6000 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
6001 const char* location = "v8::Object::GetInternalField()";
6002 if (!InternalFieldOK(obj, index, location)) return Local<Value>();
6003 i::Handle<i::Object> value(i::JSObject::cast(*obj).GetEmbedderField(index),
6004 obj->GetIsolate());
6005 return Utils::ToLocal(value);
6006 }
6007
6008 template<typename T>
SetInternalFieldImpl(v8::Object * receiver,int index,v8::Local<T> value)6009 void SetInternalFieldImpl(v8::Object* receiver, int index, v8::Local<T> value) {
6010 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(receiver);
6011 const char* location = "v8::Object::SetInternalField()";
6012 if (!InternalFieldOK(obj, index, location)) return;
6013 i::Handle<i::Object> val = Utils::OpenHandle(*value);
6014 i::Handle<i::JSObject>::cast(obj)->SetEmbedderField(index, *val);
6015 }
6016
SetInternalField(int index,v8::Local<Value> value)6017 void v8::Object::SetInternalField(int index, v8::Local<Value> value) {
6018 SetInternalFieldImpl(this, index, value);
6019 }
6020
6021 /**
6022 * These are Node.js-specific extentions used to avoid breaking changes in
6023 * Node.js v20.x.
6024 */
SetInternalFieldForNodeCore(int index,v8::Local<Module> value)6025 void v8::Object::SetInternalFieldForNodeCore(int index,
6026 v8::Local<Module> value) {
6027 SetInternalFieldImpl(this, index, value);
6028 }
6029
SetInternalFieldForNodeCore(int index,v8::Local<UnboundScript> value)6030 void v8::Object::SetInternalFieldForNodeCore(int index,
6031 v8::Local<UnboundScript> value) {
6032 SetInternalFieldImpl(this, index, value);
6033 }
6034
SlowGetAlignedPointerFromInternalField(int index)6035 void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) {
6036 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
6037 const char* location = "v8::Object::GetAlignedPointerFromInternalField()";
6038 if (!InternalFieldOK(obj, index, location)) return nullptr;
6039 void* result;
6040 Utils::ApiCheck(i::EmbedderDataSlot(i::JSObject::cast(*obj), index)
6041 .ToAlignedPointer(obj->GetIsolate(), &result),
6042 location, "Unaligned pointer");
6043 return result;
6044 }
6045
SetAlignedPointerInInternalField(int index,void * value)6046 void v8::Object::SetAlignedPointerInInternalField(int index, void* value) {
6047 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
6048 const char* location = "v8::Object::SetAlignedPointerInInternalField()";
6049 if (!InternalFieldOK(obj, index, location)) return;
6050
6051 i::DisallowGarbageCollection no_gc;
6052
6053 // There's no need to invalidate slots as embedder fields are always
6054 // tagged.
6055 obj->GetHeap()->NotifyObjectLayoutChange(*obj, no_gc,
6056 i::InvalidateRecordedSlots::kNo);
6057
6058 Utils::ApiCheck(i::EmbedderDataSlot(i::JSObject::cast(*obj), index)
6059 .store_aligned_pointer(obj->GetIsolate(), value),
6060 location, "Unaligned pointer");
6061 DCHECK_EQ(value, GetAlignedPointerFromInternalField(index));
6062 internal::WriteBarrier::MarkingFromInternalFields(i::JSObject::cast(*obj));
6063
6064 #ifdef VERIFY_HEAP
6065 obj->GetHeap()->VerifyObjectLayoutChange(*obj, obj->map());
6066 #endif // VERIFY_HEAP
6067 }
6068
SetAlignedPointerInInternalFields(int argc,int indices[],void * values[])6069 void v8::Object::SetAlignedPointerInInternalFields(int argc, int indices[],
6070 void* values[]) {
6071 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
6072
6073 i::DisallowGarbageCollection no_gc;
6074 // There's no need to invalidate slots as embedder fields are always
6075 // tagged.
6076 obj->GetHeap()->NotifyObjectLayoutChange(*obj, no_gc,
6077 i::InvalidateRecordedSlots::kNo);
6078
6079 const char* location = "v8::Object::SetAlignedPointerInInternalFields()";
6080 i::JSObject js_obj = i::JSObject::cast(*obj);
6081 int nof_embedder_fields = js_obj.GetEmbedderFieldCount();
6082 for (int i = 0; i < argc; i++) {
6083 int index = indices[i];
6084 if (!Utils::ApiCheck(index < nof_embedder_fields, location,
6085 "Internal field out of bounds")) {
6086 return;
6087 }
6088 void* value = values[i];
6089 Utils::ApiCheck(i::EmbedderDataSlot(js_obj, index)
6090 .store_aligned_pointer(obj->GetIsolate(), value),
6091 location, "Unaligned pointer");
6092 DCHECK_EQ(value, GetAlignedPointerFromInternalField(index));
6093 }
6094 internal::WriteBarrier::MarkingFromInternalFields(js_obj);
6095
6096 #ifdef VERIFY_HEAP
6097 obj->GetHeap()->VerifyObjectLayoutChange(*obj, obj->map());
6098 #endif // VERIFY_HEAP
6099 }
6100
6101 // --- E n v i r o n m e n t ---
6102
InitializePlatform(Platform * platform)6103 void v8::V8::InitializePlatform(Platform* platform) {
6104 i::V8::InitializePlatform(platform);
6105 }
6106
6107 #ifdef V8_SANDBOX
InitializeSandbox()6108 bool v8::V8::InitializeSandbox() { return i::V8::InitializeSandbox(); }
6109 #endif
6110
DisposePlatform()6111 void v8::V8::DisposePlatform() { i::V8::DisposePlatform(); }
6112
Initialize(const int build_config)6113 bool v8::V8::Initialize(const int build_config) {
6114 const bool kEmbedderPointerCompression =
6115 (build_config & kPointerCompression) != 0;
6116 if (kEmbedderPointerCompression != COMPRESS_POINTERS_BOOL) {
6117 FATAL(
6118 "Embedder-vs-V8 build configuration mismatch. On embedder side "
6119 "pointer compression is %s while on V8 side it's %s.",
6120 kEmbedderPointerCompression ? "ENABLED" : "DISABLED",
6121 COMPRESS_POINTERS_BOOL ? "ENABLED" : "DISABLED");
6122 }
6123
6124 const int kEmbedderSmiValueSize = (build_config & k31BitSmis) ? 31 : 32;
6125 if (kEmbedderSmiValueSize != internal::kSmiValueSize) {
6126 FATAL(
6127 "Embedder-vs-V8 build configuration mismatch. On embedder side "
6128 "Smi value size is %d while on V8 side it's %d.",
6129 kEmbedderSmiValueSize, internal::kSmiValueSize);
6130 }
6131
6132 const bool kEmbedderSandboxedExternalPointers =
6133 (build_config & kSandboxedExternalPointers) != 0;
6134 if (kEmbedderSandboxedExternalPointers !=
6135 V8_SANDBOXED_EXTERNAL_POINTERS_BOOL) {
6136 FATAL(
6137 "Embedder-vs-V8 build configuration mismatch. On embedder side "
6138 "sandboxed external pointers is %s while on V8 side it's %s.",
6139 kEmbedderSandboxedExternalPointers ? "ENABLED" : "DISABLED",
6140 V8_SANDBOXED_EXTERNAL_POINTERS_BOOL ? "ENABLED" : "DISABLED");
6141 }
6142
6143 const bool kEmbedderSandbox = (build_config & kSandbox) != 0;
6144 if (kEmbedderSandbox != V8_SANDBOX_BOOL) {
6145 FATAL(
6146 "Embedder-vs-V8 build configuration mismatch. On embedder side "
6147 "sandbox is %s while on V8 side it's %s.",
6148 kEmbedderSandbox ? "ENABLED" : "DISABLED",
6149 V8_SANDBOX_BOOL ? "ENABLED" : "DISABLED");
6150 }
6151
6152 i::V8::Initialize();
6153 return true;
6154 }
6155
6156 #if V8_OS_LINUX || V8_OS_DARWIN
TryHandleWebAssemblyTrapPosix(int sig_code,siginfo_t * info,void * context)6157 bool TryHandleWebAssemblyTrapPosix(int sig_code, siginfo_t* info,
6158 void* context) {
6159 #if V8_ENABLE_WEBASSEMBLY && V8_TRAP_HANDLER_SUPPORTED
6160 return i::trap_handler::TryHandleSignal(sig_code, info, context);
6161 #else
6162 return false;
6163 #endif
6164 }
6165 #endif
6166
6167 #if V8_OS_WIN
TryHandleWebAssemblyTrapWindows(EXCEPTION_POINTERS * exception)6168 bool TryHandleWebAssemblyTrapWindows(EXCEPTION_POINTERS* exception) {
6169 #if V8_ENABLE_WEBASSEMBLY && V8_TRAP_HANDLER_SUPPORTED
6170 return i::trap_handler::TryHandleWasmTrap(exception);
6171 #else
6172 return false;
6173 #endif
6174 }
6175 #endif
6176
EnableWebAssemblyTrapHandler(bool use_v8_signal_handler)6177 bool V8::EnableWebAssemblyTrapHandler(bool use_v8_signal_handler) {
6178 #if V8_ENABLE_WEBASSEMBLY
6179 return v8::internal::trap_handler::EnableTrapHandler(use_v8_signal_handler);
6180 #else
6181 return false;
6182 #endif
6183 }
6184
6185 #if defined(V8_OS_WIN)
SetUnhandledExceptionCallback(UnhandledExceptionCallback unhandled_exception_callback)6186 void V8::SetUnhandledExceptionCallback(
6187 UnhandledExceptionCallback unhandled_exception_callback) {
6188 #if defined(V8_OS_WIN64)
6189 v8::internal::win64_unwindinfo::SetUnhandledExceptionCallback(
6190 unhandled_exception_callback);
6191 #else
6192 // Not implemented, port needed.
6193 #endif // V8_OS_WIN64
6194 }
6195 #endif // V8_OS_WIN
6196
SetFatalMemoryErrorCallback(v8::OOMErrorCallback oom_error_callback)6197 void v8::V8::SetFatalMemoryErrorCallback(
6198 v8::OOMErrorCallback oom_error_callback) {
6199 g_oom_error_callback = oom_error_callback;
6200 }
6201
SetEntropySource(EntropySource entropy_source)6202 void v8::V8::SetEntropySource(EntropySource entropy_source) {
6203 base::RandomNumberGenerator::SetEntropySource(entropy_source);
6204 }
6205
SetReturnAddressLocationResolver(ReturnAddressLocationResolver return_address_resolver)6206 void v8::V8::SetReturnAddressLocationResolver(
6207 ReturnAddressLocationResolver return_address_resolver) {
6208 i::StackFrame::SetReturnAddressLocationResolver(return_address_resolver);
6209 }
6210
Dispose()6211 bool v8::V8::Dispose() {
6212 i::V8::Dispose();
6213 return true;
6214 }
6215
SharedMemoryStatistics()6216 SharedMemoryStatistics::SharedMemoryStatistics()
6217 : read_only_space_size_(0),
6218 read_only_space_used_size_(0),
6219 read_only_space_physical_size_(0) {}
6220
HeapStatistics()6221 HeapStatistics::HeapStatistics()
6222 : total_heap_size_(0),
6223 total_heap_size_executable_(0),
6224 total_physical_size_(0),
6225 total_available_size_(0),
6226 used_heap_size_(0),
6227 heap_size_limit_(0),
6228 malloced_memory_(0),
6229 external_memory_(0),
6230 peak_malloced_memory_(0),
6231 does_zap_garbage_(false),
6232 number_of_native_contexts_(0),
6233 number_of_detached_contexts_(0) {}
6234
HeapSpaceStatistics()6235 HeapSpaceStatistics::HeapSpaceStatistics()
6236 : space_name_(nullptr),
6237 space_size_(0),
6238 space_used_size_(0),
6239 space_available_size_(0),
6240 physical_space_size_(0) {}
6241
HeapObjectStatistics()6242 HeapObjectStatistics::HeapObjectStatistics()
6243 : object_type_(nullptr),
6244 object_sub_type_(nullptr),
6245 object_count_(0),
6246 object_size_(0) {}
6247
HeapCodeStatistics()6248 HeapCodeStatistics::HeapCodeStatistics()
6249 : code_and_metadata_size_(0),
6250 bytecode_and_metadata_size_(0),
6251 external_script_source_size_(0),
6252 cpu_profiler_metadata_size_(0) {}
6253
InitializeICU(const char * icu_data_file)6254 bool v8::V8::InitializeICU(const char* icu_data_file) {
6255 return i::InitializeICU(icu_data_file);
6256 }
6257
InitializeICUDefaultLocation(const char * exec_path,const char * icu_data_file)6258 bool v8::V8::InitializeICUDefaultLocation(const char* exec_path,
6259 const char* icu_data_file) {
6260 return i::InitializeICUDefaultLocation(exec_path, icu_data_file);
6261 }
6262
InitializeExternalStartupData(const char * directory_path)6263 void v8::V8::InitializeExternalStartupData(const char* directory_path) {
6264 i::InitializeExternalStartupData(directory_path);
6265 }
6266
6267 // static
InitializeExternalStartupDataFromFile(const char * snapshot_blob)6268 void v8::V8::InitializeExternalStartupDataFromFile(const char* snapshot_blob) {
6269 i::InitializeExternalStartupDataFromFile(snapshot_blob);
6270 }
6271
GetVersion()6272 const char* v8::V8::GetVersion() { return i::Version::GetVersion(); }
6273
6274 #ifdef V8_SANDBOX
GetSandboxAddressSpace()6275 VirtualAddressSpace* v8::V8::GetSandboxAddressSpace() {
6276 Utils::ApiCheck(i::GetProcessWideSandbox()->is_initialized(),
6277 "v8::V8::GetSandboxAddressSpace",
6278 "The sandbox must be initialized first.");
6279 return i::GetProcessWideSandbox()->address_space();
6280 }
6281
GetVirtualMemoryCagePageAllocator()6282 PageAllocator* v8::V8::GetVirtualMemoryCagePageAllocator() {
6283 Utils::ApiCheck(i::GetProcessWideSandbox()->is_initialized(),
6284 "v8::V8::GetVirtualMemoryCagePageAllocator",
6285 "The sandbox must be initialized first.");
6286 return i::GetProcessWideSandbox()->page_allocator();
6287 }
6288
GetSandboxSizeInBytes()6289 size_t v8::V8::GetSandboxSizeInBytes() {
6290 if (!i::GetProcessWideSandbox()->is_initialized()) {
6291 return 0;
6292 } else {
6293 return i::GetProcessWideSandbox()->size();
6294 }
6295 }
6296
IsSandboxConfiguredSecurely()6297 bool v8::V8::IsSandboxConfiguredSecurely() {
6298 Utils::ApiCheck(i::GetProcessWideSandbox()->is_initialized(),
6299 "v8::V8::IsSandoxConfiguredSecurely",
6300 "The sandbox must be initialized first.");
6301 // TODO(saelo) For now, we only treat a partially reserved sandbox as
6302 // insecure. Once we use sandboxed pointers, which assume that the sandbox
6303 // has a fixed size, we'll also treat sandboxes with a smaller size as
6304 // insecure because these pointers can then access memory outside of them.
6305 return !i::GetProcessWideSandbox()->is_partially_reserved();
6306 }
6307 #endif
6308
GetSharedMemoryStatistics(SharedMemoryStatistics * statistics)6309 void V8::GetSharedMemoryStatistics(SharedMemoryStatistics* statistics) {
6310 i::ReadOnlyHeap::PopulateReadOnlySpaceStatistics(statistics);
6311 }
6312
6313 template <typename ObjectType>
6314 struct InvokeBootstrapper;
6315
6316 template <>
6317 struct InvokeBootstrapper<i::Context> {
Invokev8::InvokeBootstrapper6318 i::Handle<i::Context> Invoke(
6319 i::Isolate* isolate, i::MaybeHandle<i::JSGlobalProxy> maybe_global_proxy,
6320 v8::Local<v8::ObjectTemplate> global_proxy_template,
6321 v8::ExtensionConfiguration* extensions, size_t context_snapshot_index,
6322 v8::DeserializeInternalFieldsCallback embedder_fields_deserializer,
6323 v8::MicrotaskQueue* microtask_queue) {
6324 return isolate->bootstrapper()->CreateEnvironment(
6325 maybe_global_proxy, global_proxy_template, extensions,
6326 context_snapshot_index, embedder_fields_deserializer, microtask_queue);
6327 }
6328 };
6329
6330 template <>
6331 struct InvokeBootstrapper<i::JSGlobalProxy> {
Invokev8::InvokeBootstrapper6332 i::Handle<i::JSGlobalProxy> Invoke(
6333 i::Isolate* isolate, i::MaybeHandle<i::JSGlobalProxy> maybe_global_proxy,
6334 v8::Local<v8::ObjectTemplate> global_proxy_template,
6335 v8::ExtensionConfiguration* extensions, size_t context_snapshot_index,
6336 v8::DeserializeInternalFieldsCallback embedder_fields_deserializer,
6337 v8::MicrotaskQueue* microtask_queue) {
6338 USE(extensions);
6339 USE(context_snapshot_index);
6340 return isolate->bootstrapper()->NewRemoteContext(maybe_global_proxy,
6341 global_proxy_template);
6342 }
6343 };
6344
6345 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 embedder_fields_deserializer,v8::MicrotaskQueue * microtask_queue)6346 static i::Handle<ObjectType> CreateEnvironment(
6347 i::Isolate* isolate, v8::ExtensionConfiguration* extensions,
6348 v8::MaybeLocal<ObjectTemplate> maybe_global_template,
6349 v8::MaybeLocal<Value> maybe_global_proxy, size_t context_snapshot_index,
6350 v8::DeserializeInternalFieldsCallback embedder_fields_deserializer,
6351 v8::MicrotaskQueue* microtask_queue) {
6352 i::Handle<ObjectType> result;
6353
6354 {
6355 ENTER_V8_FOR_NEW_CONTEXT(isolate);
6356 v8::Local<ObjectTemplate> proxy_template;
6357 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
6358 i::Handle<i::FunctionTemplateInfo> global_constructor;
6359 i::Handle<i::HeapObject> named_interceptor(
6360 isolate->factory()->undefined_value());
6361 i::Handle<i::HeapObject> indexed_interceptor(
6362 isolate->factory()->undefined_value());
6363
6364 if (!maybe_global_template.IsEmpty()) {
6365 v8::Local<v8::ObjectTemplate> global_template =
6366 maybe_global_template.ToLocalChecked();
6367 // Make sure that the global_template has a constructor.
6368 global_constructor = EnsureConstructor(isolate, *global_template);
6369
6370 // Create a fresh template for the global proxy object.
6371 proxy_template =
6372 ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate));
6373 proxy_constructor = EnsureConstructor(isolate, *proxy_template);
6374
6375 // Set the global template to be the prototype template of
6376 // global proxy template.
6377 i::FunctionTemplateInfo::SetPrototypeTemplate(
6378 isolate, proxy_constructor, Utils::OpenHandle(*global_template));
6379
6380 proxy_template->SetInternalFieldCount(
6381 global_template->InternalFieldCount());
6382
6383 // Migrate security handlers from global_template to
6384 // proxy_template. Temporarily removing access check
6385 // information from the global template.
6386 if (!global_constructor->GetAccessCheckInfo().IsUndefined(isolate)) {
6387 i::FunctionTemplateInfo::SetAccessCheckInfo(
6388 isolate, proxy_constructor,
6389 i::handle(global_constructor->GetAccessCheckInfo(), isolate));
6390 proxy_constructor->set_needs_access_check(
6391 global_constructor->needs_access_check());
6392 global_constructor->set_needs_access_check(false);
6393 i::FunctionTemplateInfo::SetAccessCheckInfo(
6394 isolate, global_constructor,
6395 i::ReadOnlyRoots(isolate).undefined_value_handle());
6396 }
6397
6398 // Same for other interceptors. If the global constructor has
6399 // interceptors, we need to replace them temporarily with noop
6400 // interceptors, so the map is correctly marked as having interceptors,
6401 // but we don't invoke any.
6402 if (!global_constructor->GetNamedPropertyHandler().IsUndefined(isolate)) {
6403 named_interceptor =
6404 handle(global_constructor->GetNamedPropertyHandler(), isolate);
6405 i::FunctionTemplateInfo::SetNamedPropertyHandler(
6406 isolate, global_constructor,
6407 i::ReadOnlyRoots(isolate).noop_interceptor_info_handle());
6408 }
6409 if (!global_constructor->GetIndexedPropertyHandler().IsUndefined(
6410 isolate)) {
6411 indexed_interceptor =
6412 handle(global_constructor->GetIndexedPropertyHandler(), isolate);
6413 i::FunctionTemplateInfo::SetIndexedPropertyHandler(
6414 isolate, global_constructor,
6415 i::ReadOnlyRoots(isolate).noop_interceptor_info_handle());
6416 }
6417 }
6418
6419 i::MaybeHandle<i::JSGlobalProxy> maybe_proxy;
6420 if (!maybe_global_proxy.IsEmpty()) {
6421 maybe_proxy = i::Handle<i::JSGlobalProxy>::cast(
6422 Utils::OpenHandle(*maybe_global_proxy.ToLocalChecked()));
6423 }
6424 // Create the environment.
6425 InvokeBootstrapper<ObjectType> invoke;
6426 result = invoke.Invoke(isolate, maybe_proxy, proxy_template, extensions,
6427 context_snapshot_index, embedder_fields_deserializer,
6428 microtask_queue);
6429
6430 // Restore the access check info and interceptors on the global template.
6431 if (!maybe_global_template.IsEmpty()) {
6432 DCHECK(!global_constructor.is_null());
6433 DCHECK(!proxy_constructor.is_null());
6434 i::FunctionTemplateInfo::SetAccessCheckInfo(
6435 isolate, global_constructor,
6436 i::handle(proxy_constructor->GetAccessCheckInfo(), isolate));
6437 global_constructor->set_needs_access_check(
6438 proxy_constructor->needs_access_check());
6439 i::FunctionTemplateInfo::SetNamedPropertyHandler(
6440 isolate, global_constructor, named_interceptor);
6441 i::FunctionTemplateInfo::SetIndexedPropertyHandler(
6442 isolate, global_constructor, indexed_interceptor);
6443 }
6444 }
6445 // Leave V8.
6446
6447 return result;
6448 }
6449
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 embedder_fields_deserializer,v8::MicrotaskQueue * microtask_queue)6450 Local<Context> NewContext(
6451 v8::Isolate* external_isolate, v8::ExtensionConfiguration* extensions,
6452 v8::MaybeLocal<ObjectTemplate> global_template,
6453 v8::MaybeLocal<Value> global_object, size_t context_snapshot_index,
6454 v8::DeserializeInternalFieldsCallback embedder_fields_deserializer,
6455 v8::MicrotaskQueue* microtask_queue) {
6456 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
6457 // TODO(jkummerow): This is for crbug.com/713699. Remove it if it doesn't
6458 // fail.
6459 // Sanity-check that the isolate is initialized and usable.
6460 CHECK(isolate->builtins()->code(i::Builtin::kIllegal).IsCodeT());
6461
6462 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.NewContext");
6463 API_RCS_SCOPE(isolate, Context, New);
6464 i::HandleScope scope(isolate);
6465 ExtensionConfiguration no_extensions;
6466 if (extensions == nullptr) extensions = &no_extensions;
6467 i::Handle<i::Context> env = CreateEnvironment<i::Context>(
6468 isolate, extensions, global_template, global_object,
6469 context_snapshot_index, embedder_fields_deserializer, microtask_queue);
6470 if (env.is_null()) {
6471 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
6472 return Local<Context>();
6473 }
6474 return Utils::ToLocal(scope.CloseAndEscape(env));
6475 }
6476
New(v8::Isolate * external_isolate,v8::ExtensionConfiguration * extensions,v8::MaybeLocal<ObjectTemplate> global_template,v8::MaybeLocal<Value> global_object,DeserializeInternalFieldsCallback internal_fields_deserializer,v8::MicrotaskQueue * microtask_queue)6477 Local<Context> v8::Context::New(
6478 v8::Isolate* external_isolate, v8::ExtensionConfiguration* extensions,
6479 v8::MaybeLocal<ObjectTemplate> global_template,
6480 v8::MaybeLocal<Value> global_object,
6481 DeserializeInternalFieldsCallback internal_fields_deserializer,
6482 v8::MicrotaskQueue* microtask_queue) {
6483 return NewContext(external_isolate, extensions, global_template,
6484 global_object, 0, internal_fields_deserializer,
6485 microtask_queue);
6486 }
6487
FromSnapshot(v8::Isolate * external_isolate,size_t context_snapshot_index,v8::DeserializeInternalFieldsCallback embedder_fields_deserializer,v8::ExtensionConfiguration * extensions,MaybeLocal<Value> global_object,v8::MicrotaskQueue * microtask_queue)6488 MaybeLocal<Context> v8::Context::FromSnapshot(
6489 v8::Isolate* external_isolate, size_t context_snapshot_index,
6490 v8::DeserializeInternalFieldsCallback embedder_fields_deserializer,
6491 v8::ExtensionConfiguration* extensions, MaybeLocal<Value> global_object,
6492 v8::MicrotaskQueue* microtask_queue) {
6493 size_t index_including_default_context = context_snapshot_index + 1;
6494 if (!i::Snapshot::HasContextSnapshot(
6495 reinterpret_cast<i::Isolate*>(external_isolate),
6496 index_including_default_context)) {
6497 return MaybeLocal<Context>();
6498 }
6499 return NewContext(external_isolate, extensions, MaybeLocal<ObjectTemplate>(),
6500 global_object, index_including_default_context,
6501 embedder_fields_deserializer, microtask_queue);
6502 }
6503
NewRemoteContext(v8::Isolate * external_isolate,v8::Local<ObjectTemplate> global_template,v8::MaybeLocal<v8::Value> global_object)6504 MaybeLocal<Object> v8::Context::NewRemoteContext(
6505 v8::Isolate* external_isolate, v8::Local<ObjectTemplate> global_template,
6506 v8::MaybeLocal<v8::Value> global_object) {
6507 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
6508 API_RCS_SCOPE(isolate, Context, NewRemoteContext);
6509 i::HandleScope scope(isolate);
6510 i::Handle<i::FunctionTemplateInfo> global_constructor =
6511 EnsureConstructor(isolate, *global_template);
6512 Utils::ApiCheck(global_constructor->needs_access_check(),
6513 "v8::Context::NewRemoteContext",
6514 "Global template needs to have access checks enabled.");
6515 i::Handle<i::AccessCheckInfo> access_check_info = i::handle(
6516 i::AccessCheckInfo::cast(global_constructor->GetAccessCheckInfo()),
6517 isolate);
6518 Utils::ApiCheck(access_check_info->named_interceptor() != i::Object(),
6519 "v8::Context::NewRemoteContext",
6520 "Global template needs to have access check handlers.");
6521 i::Handle<i::JSObject> global_proxy = CreateEnvironment<i::JSGlobalProxy>(
6522 isolate, nullptr, global_template, global_object, 0,
6523 DeserializeInternalFieldsCallback(), nullptr);
6524 if (global_proxy.is_null()) {
6525 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
6526 return MaybeLocal<Object>();
6527 }
6528 return Utils::ToLocal(scope.CloseAndEscape(global_proxy));
6529 }
6530
SetSecurityToken(Local<Value> token)6531 void v8::Context::SetSecurityToken(Local<Value> token) {
6532 i::Handle<i::Context> env = Utils::OpenHandle(this);
6533 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
6534 env->set_security_token(*token_handle);
6535 }
6536
UseDefaultSecurityToken()6537 void v8::Context::UseDefaultSecurityToken() {
6538 i::Handle<i::Context> env = Utils::OpenHandle(this);
6539 env->set_security_token(env->global_object());
6540 }
6541
GetSecurityToken()6542 Local<Value> v8::Context::GetSecurityToken() {
6543 i::Handle<i::Context> env = Utils::OpenHandle(this);
6544 i::Isolate* isolate = env->GetIsolate();
6545 i::Object security_token = env->security_token();
6546 i::Handle<i::Object> token_handle(security_token, isolate);
6547 return Utils::ToLocal(token_handle);
6548 }
6549
GetIsolate()6550 v8::Isolate* Context::GetIsolate() {
6551 i::Handle<i::Context> env = Utils::OpenHandle(this);
6552 return reinterpret_cast<Isolate*>(env->GetIsolate());
6553 }
6554
GetMicrotaskQueue()6555 v8::MicrotaskQueue* Context::GetMicrotaskQueue() {
6556 i::Handle<i::Context> env = Utils::OpenHandle(this);
6557 Utils::ApiCheck(env->IsNativeContext(), "v8::Context::GetMicrotaskQueue",
6558 "Must be calld on a native context");
6559 return i::Handle<i::NativeContext>::cast(env)->microtask_queue();
6560 }
6561
Global()6562 v8::Local<v8::Object> Context::Global() {
6563 i::Handle<i::Context> context = Utils::OpenHandle(this);
6564 i::Isolate* isolate = context->GetIsolate();
6565 i::Handle<i::Object> global(context->global_proxy(), isolate);
6566 // TODO(chromium:324812): This should always return the global proxy
6567 // but can't presently as calls to GetProtoype will return the wrong result.
6568 if (i::Handle<i::JSGlobalProxy>::cast(global)->IsDetachedFrom(
6569 context->global_object())) {
6570 global = i::Handle<i::Object>(context->global_object(), isolate);
6571 }
6572 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
6573 }
6574
DetachGlobal()6575 void Context::DetachGlobal() {
6576 i::Handle<i::Context> context = Utils::OpenHandle(this);
6577 i::Isolate* isolate = context->GetIsolate();
6578 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
6579 isolate->DetachGlobal(context);
6580 }
6581
GetExtrasBindingObject()6582 Local<v8::Object> Context::GetExtrasBindingObject() {
6583 i::Handle<i::Context> context = Utils::OpenHandle(this);
6584 i::Isolate* isolate = context->GetIsolate();
6585 i::Handle<i::JSObject> binding(context->extras_binding_object(), isolate);
6586 return Utils::ToLocal(binding);
6587 }
6588
AllowCodeGenerationFromStrings(bool allow)6589 void Context::AllowCodeGenerationFromStrings(bool allow) {
6590 i::Handle<i::Context> context = Utils::OpenHandle(this);
6591 i::Isolate* isolate = context->GetIsolate();
6592 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
6593 context->set_allow_code_gen_from_strings(
6594 allow ? i::ReadOnlyRoots(isolate).true_value()
6595 : i::ReadOnlyRoots(isolate).false_value());
6596 }
6597
IsCodeGenerationFromStringsAllowed() const6598 bool Context::IsCodeGenerationFromStringsAllowed() const {
6599 i::Context context = *Utils::OpenHandle(this);
6600 return !context.allow_code_gen_from_strings().IsFalse(context.GetIsolate());
6601 }
6602
SetErrorMessageForCodeGenerationFromStrings(Local<String> error)6603 void Context::SetErrorMessageForCodeGenerationFromStrings(Local<String> error) {
6604 i::Handle<i::Context> context = Utils::OpenHandle(this);
6605 i::Handle<i::String> error_handle = Utils::OpenHandle(*error);
6606 context->set_error_message_for_code_gen_from_strings(*error_handle);
6607 }
6608
SetAbortScriptExecution(Context::AbortScriptExecutionCallback callback)6609 void Context::SetAbortScriptExecution(
6610 Context::AbortScriptExecutionCallback callback) {
6611 i::Handle<i::Context> context = Utils::OpenHandle(this);
6612 i::Isolate* isolate = context->GetIsolate();
6613 if (callback == nullptr) {
6614 context->set_script_execution_callback(
6615 i::ReadOnlyRoots(isolate).undefined_value());
6616 } else {
6617 SET_FIELD_WRAPPED(isolate, context, set_script_execution_callback,
6618 callback);
6619 }
6620 }
6621
GetContinuationPreservedEmbedderData() const6622 Local<Value> Context::GetContinuationPreservedEmbedderData() const {
6623 i::Handle<i::Context> context = Utils::OpenHandle(this);
6624 i::Isolate* isolate = context->GetIsolate();
6625 i::Handle<i::Object> data(
6626 context->native_context().continuation_preserved_embedder_data(),
6627 isolate);
6628 return ToApiHandle<Object>(data);
6629 }
6630
SetContinuationPreservedEmbedderData(Local<Value> data)6631 void Context::SetContinuationPreservedEmbedderData(Local<Value> data) {
6632 i::Handle<i::Context> context = Utils::OpenHandle(this);
6633 i::Isolate* isolate = context->GetIsolate();
6634 if (data.IsEmpty())
6635 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
6636 context->native_context().set_continuation_preserved_embedder_data(
6637 *i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*data)));
6638 }
6639
SetPromiseHooks(Local<Function> init_hook,Local<Function> before_hook,Local<Function> after_hook,Local<Function> resolve_hook)6640 void v8::Context::SetPromiseHooks(Local<Function> init_hook,
6641 Local<Function> before_hook,
6642 Local<Function> after_hook,
6643 Local<Function> resolve_hook) {
6644 #ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
6645 i::Handle<i::Context> context = Utils::OpenHandle(this);
6646 i::Isolate* isolate = context->GetIsolate();
6647
6648 i::Handle<i::Object> init = isolate->factory()->undefined_value();
6649 i::Handle<i::Object> before = isolate->factory()->undefined_value();
6650 i::Handle<i::Object> after = isolate->factory()->undefined_value();
6651 i::Handle<i::Object> resolve = isolate->factory()->undefined_value();
6652
6653 bool has_hook = false;
6654
6655 if (!init_hook.IsEmpty()) {
6656 init = Utils::OpenHandle(*init_hook);
6657 has_hook = true;
6658 }
6659 if (!before_hook.IsEmpty()) {
6660 before = Utils::OpenHandle(*before_hook);
6661 has_hook = true;
6662 }
6663 if (!after_hook.IsEmpty()) {
6664 after = Utils::OpenHandle(*after_hook);
6665 has_hook = true;
6666 }
6667 if (!resolve_hook.IsEmpty()) {
6668 resolve = Utils::OpenHandle(*resolve_hook);
6669 has_hook = true;
6670 }
6671
6672 isolate->SetHasContextPromiseHooks(has_hook);
6673
6674 context->native_context().set_promise_hook_init_function(*init);
6675 context->native_context().set_promise_hook_before_function(*before);
6676 context->native_context().set_promise_hook_after_function(*after);
6677 context->native_context().set_promise_hook_resolve_function(*resolve);
6678 #else // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
6679 Utils::ApiCheck(false, "v8::Context::SetPromiseHook",
6680 "V8 was compiled without JavaScript Promise hooks");
6681 #endif // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
6682 }
6683
GetContext(Isolate * isolate,metrics::Recorder::ContextId id)6684 MaybeLocal<Context> metrics::Recorder::GetContext(
6685 Isolate* isolate, metrics::Recorder::ContextId id) {
6686 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6687 return i_isolate->GetContextFromRecorderContextId(id);
6688 }
6689
GetContextId(Local<Context> context)6690 metrics::Recorder::ContextId metrics::Recorder::GetContextId(
6691 Local<Context> context) {
6692 i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
6693 i::Isolate* isolate = i_context->GetIsolate();
6694 return isolate->GetOrRegisterRecorderContextId(
6695 handle(i_context->native_context(), isolate));
6696 }
6697
Get(v8::Isolate * isolate)6698 metrics::LongTaskStats metrics::LongTaskStats::Get(v8::Isolate* isolate) {
6699 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6700 return *i_isolate->GetCurrentLongTaskStats();
6701 }
6702
6703 namespace {
GetSerializedDataFromFixedArray(i::Isolate * isolate,i::FixedArray list,size_t index)6704 i::Address* GetSerializedDataFromFixedArray(i::Isolate* isolate,
6705 i::FixedArray list, size_t index) {
6706 if (index < static_cast<size_t>(list.length())) {
6707 int int_index = static_cast<int>(index);
6708 i::Object object = list.get(int_index);
6709 if (!object.IsTheHole(isolate)) {
6710 list.set_the_hole(isolate, int_index);
6711 // Shrink the list so that the last element is not the hole (unless it's
6712 // the first element, because we don't want to end up with a non-canonical
6713 // empty FixedArray).
6714 int last = list.length() - 1;
6715 while (last >= 0 && list.is_the_hole(isolate, last)) last--;
6716 if (last != -1) list.Shrink(isolate, last + 1);
6717 return i::Handle<i::Object>(object, isolate).location();
6718 }
6719 }
6720 return nullptr;
6721 }
6722 } // anonymous namespace
6723
GetDataFromSnapshotOnce(size_t index)6724 i::Address* Context::GetDataFromSnapshotOnce(size_t index) {
6725 auto context = Utils::OpenHandle(this);
6726 i::Isolate* i_isolate = context->GetIsolate();
6727 i::FixedArray list = context->serialized_objects();
6728 return GetSerializedDataFromFixedArray(i_isolate, list, index);
6729 }
6730
NewInstance(Local<Context> context)6731 MaybeLocal<v8::Object> ObjectTemplate::NewInstance(Local<Context> context) {
6732 PREPARE_FOR_EXECUTION(context, ObjectTemplate, NewInstance, Object);
6733 auto self = Utils::OpenHandle(this);
6734 Local<Object> result;
6735 has_pending_exception = !ToLocal<Object>(
6736 i::ApiNatives::InstantiateObject(isolate, self), &result);
6737 RETURN_ON_FAILED_EXECUTION(Object);
6738 RETURN_ESCAPED(result);
6739 }
6740
CheckCast(Data * that)6741 void v8::ObjectTemplate::CheckCast(Data* that) {
6742 i::Handle<i::Object> obj = Utils::OpenHandle(that);
6743 Utils::ApiCheck(obj->IsObjectTemplateInfo(), "v8::ObjectTemplate::Cast",
6744 "Value is not an ObjectTemplate");
6745 }
6746
CheckCast(Data * that)6747 void v8::FunctionTemplate::CheckCast(Data* that) {
6748 i::Handle<i::Object> obj = Utils::OpenHandle(that);
6749 Utils::ApiCheck(obj->IsFunctionTemplateInfo(), "v8::FunctionTemplate::Cast",
6750 "Value is not a FunctionTemplate");
6751 }
6752
CheckCast(Data * that)6753 void v8::Signature::CheckCast(Data* that) {
6754 i::Handle<i::Object> obj = Utils::OpenHandle(that);
6755 Utils::ApiCheck(obj->IsFunctionTemplateInfo(), "v8::Signature::Cast",
6756 "Value is not a Signature");
6757 }
6758
CheckCast(Data * that)6759 void v8::AccessorSignature::CheckCast(Data* that) {
6760 i::Handle<i::Object> obj = Utils::OpenHandle(that);
6761 Utils::ApiCheck(obj->IsFunctionTemplateInfo(), "v8::AccessorSignature::Cast",
6762 "Value is not an AccessorSignature");
6763 }
6764
GetFunction(Local<Context> context)6765 MaybeLocal<v8::Function> FunctionTemplate::GetFunction(Local<Context> context) {
6766 PREPARE_FOR_EXECUTION(context, FunctionTemplate, GetFunction, Function);
6767 auto self = Utils::OpenHandle(this);
6768 Local<Function> result;
6769 has_pending_exception =
6770 !ToLocal<Function>(i::ApiNatives::InstantiateFunction(self), &result);
6771 RETURN_ON_FAILED_EXECUTION(Function);
6772 RETURN_ESCAPED(result);
6773 }
6774
NewRemoteInstance()6775 MaybeLocal<v8::Object> FunctionTemplate::NewRemoteInstance() {
6776 auto self = Utils::OpenHandle(this);
6777 i::Isolate* isolate = self->GetIsolate();
6778 API_RCS_SCOPE(isolate, FunctionTemplate, NewRemoteInstance);
6779 i::HandleScope scope(isolate);
6780 i::Handle<i::FunctionTemplateInfo> constructor =
6781 EnsureConstructor(isolate, *InstanceTemplate());
6782 Utils::ApiCheck(constructor->needs_access_check(),
6783 "v8::FunctionTemplate::NewRemoteInstance",
6784 "InstanceTemplate needs to have access checks enabled.");
6785 i::Handle<i::AccessCheckInfo> access_check_info = i::handle(
6786 i::AccessCheckInfo::cast(constructor->GetAccessCheckInfo()), isolate);
6787 Utils::ApiCheck(access_check_info->named_interceptor() != i::Object(),
6788 "v8::FunctionTemplate::NewRemoteInstance",
6789 "InstanceTemplate needs to have access check handlers.");
6790 i::Handle<i::JSObject> object;
6791 if (!i::ApiNatives::InstantiateRemoteObject(
6792 Utils::OpenHandle(*InstanceTemplate()))
6793 .ToHandle(&object)) {
6794 if (isolate->has_pending_exception()) {
6795 isolate->OptionalRescheduleException(true);
6796 }
6797 return MaybeLocal<Object>();
6798 }
6799 return Utils::ToLocal(scope.CloseAndEscape(object));
6800 }
6801
HasInstance(v8::Local<v8::Value> value)6802 bool FunctionTemplate::HasInstance(v8::Local<v8::Value> value) {
6803 auto self = Utils::OpenHandle(this);
6804 auto obj = Utils::OpenHandle(*value);
6805 if (obj->IsJSObject() && self->IsTemplateFor(i::JSObject::cast(*obj))) {
6806 return true;
6807 }
6808 if (obj->IsJSGlobalProxy()) {
6809 // If it's a global proxy, then test with the global object. Note that the
6810 // inner global object may not necessarily be a JSGlobalObject.
6811 i::PrototypeIterator iter(self->GetIsolate(),
6812 i::JSObject::cast(*obj).map());
6813 // The global proxy should always have a prototype, as it is a bug to call
6814 // this on a detached JSGlobalProxy.
6815 DCHECK(!iter.IsAtEnd());
6816 return self->IsTemplateFor(iter.GetCurrent<i::JSObject>());
6817 }
6818 return false;
6819 }
6820
IsLeafTemplateForApiObject(v8::Local<v8::Value> value) const6821 bool FunctionTemplate::IsLeafTemplateForApiObject(
6822 v8::Local<v8::Value> value) const {
6823 i::DisallowGarbageCollection no_gc;
6824
6825 i::Object object = *Utils::OpenHandle(*value);
6826
6827 auto self = Utils::OpenHandle(this);
6828 return self->IsLeafTemplateForApiObject(object);
6829 }
6830
New(Isolate * isolate,void * value)6831 Local<External> v8::External::New(Isolate* isolate, void* value) {
6832 STATIC_ASSERT(sizeof(value) == sizeof(i::Address));
6833 // Nullptr is not allowed here because serialization/deserialization of
6834 // nullptr external api references is not possible as nullptr is used as an
6835 // external_references table terminator, see v8::SnapshotCreator()
6836 // constructors.
6837 DCHECK_NOT_NULL(value);
6838 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6839 API_RCS_SCOPE(i_isolate, External, New);
6840 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
6841 i::Handle<i::JSObject> external = i_isolate->factory()->NewExternal(value);
6842 return Utils::ExternalToLocal(external);
6843 }
6844
Value() const6845 void* External::Value() const {
6846 auto self = Utils::OpenHandle(this);
6847 return i::JSExternalObject::cast(*self).value();
6848 }
6849
6850 // anonymous namespace for string creation helper functions
6851 namespace {
6852
StringLength(const char * string)6853 inline int StringLength(const char* string) {
6854 size_t len = strlen(string);
6855 CHECK_GE(i::kMaxInt, len);
6856 return static_cast<int>(len);
6857 }
6858
StringLength(const uint8_t * string)6859 inline int StringLength(const uint8_t* string) {
6860 return StringLength(reinterpret_cast<const char*>(string));
6861 }
6862
StringLength(const uint16_t * string)6863 inline int StringLength(const uint16_t* string) {
6864 size_t length = 0;
6865 while (string[length] != '\0') length++;
6866 CHECK_GE(i::kMaxInt, length);
6867 return static_cast<int>(length);
6868 }
6869
6870 V8_WARN_UNUSED_RESULT
NewString(i::Factory * factory,NewStringType type,base::Vector<const char> string)6871 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
6872 NewStringType type,
6873 base::Vector<const char> string) {
6874 if (type == NewStringType::kInternalized) {
6875 return factory->InternalizeUtf8String(string);
6876 }
6877 return factory->NewStringFromUtf8(string);
6878 }
6879
6880 V8_WARN_UNUSED_RESULT
NewString(i::Factory * factory,NewStringType type,base::Vector<const uint8_t> string)6881 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
6882 NewStringType type,
6883 base::Vector<const uint8_t> string) {
6884 if (type == NewStringType::kInternalized) {
6885 return factory->InternalizeString(string);
6886 }
6887 return factory->NewStringFromOneByte(string);
6888 }
6889
6890 V8_WARN_UNUSED_RESULT
NewString(i::Factory * factory,NewStringType type,base::Vector<const uint16_t> string)6891 inline i::MaybeHandle<i::String> NewString(
6892 i::Factory* factory, NewStringType type,
6893 base::Vector<const uint16_t> string) {
6894 if (type == NewStringType::kInternalized) {
6895 return factory->InternalizeString(string);
6896 }
6897 return factory->NewStringFromTwoByte(string);
6898 }
6899
6900 STATIC_ASSERT(v8::String::kMaxLength == i::String::kMaxLength);
6901
6902 } // anonymous namespace
6903
6904 // TODO(dcarney): throw a context free exception.
6905 #define NEW_STRING(isolate, class_name, function_name, Char, data, type, \
6906 length) \
6907 MaybeLocal<String> result; \
6908 if (length == 0) { \
6909 result = String::Empty(isolate); \
6910 } else if (length > i::String::kMaxLength) { \
6911 result = MaybeLocal<String>(); \
6912 } else { \
6913 i::Isolate* i_isolate = reinterpret_cast<internal::Isolate*>(isolate); \
6914 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); \
6915 API_RCS_SCOPE(i_isolate, class_name, function_name); \
6916 if (length < 0) length = StringLength(data); \
6917 i::Handle<i::String> handle_result = \
6918 NewString(i_isolate->factory(), type, \
6919 base::Vector<const Char>(data, length)) \
6920 .ToHandleChecked(); \
6921 result = Utils::ToLocal(handle_result); \
6922 }
6923
NewFromUtf8Literal(Isolate * isolate,const char * literal,NewStringType type,int length)6924 Local<String> String::NewFromUtf8Literal(Isolate* isolate, const char* literal,
6925 NewStringType type, int length) {
6926 DCHECK_LE(length, i::String::kMaxLength);
6927 i::Isolate* i_isolate = reinterpret_cast<internal::Isolate*>(isolate);
6928 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
6929 API_RCS_SCOPE(i_isolate, String, NewFromUtf8Literal);
6930 i::Handle<i::String> handle_result =
6931 NewString(i_isolate->factory(), type,
6932 base::Vector<const char>(literal, length))
6933 .ToHandleChecked();
6934 return Utils::ToLocal(handle_result);
6935 }
6936
NewFromUtf8(Isolate * isolate,const char * data,NewStringType type,int length)6937 MaybeLocal<String> String::NewFromUtf8(Isolate* isolate, const char* data,
6938 NewStringType type, int length) {
6939 NEW_STRING(isolate, String, NewFromUtf8, char, data, type, length);
6940 return result;
6941 }
6942
NewFromOneByte(Isolate * isolate,const uint8_t * data,NewStringType type,int length)6943 MaybeLocal<String> String::NewFromOneByte(Isolate* isolate, const uint8_t* data,
6944 NewStringType type, int length) {
6945 NEW_STRING(isolate, String, NewFromOneByte, uint8_t, data, type, length);
6946 return result;
6947 }
6948
NewFromTwoByte(Isolate * isolate,const uint16_t * data,NewStringType type,int length)6949 MaybeLocal<String> String::NewFromTwoByte(Isolate* isolate,
6950 const uint16_t* data,
6951 NewStringType type, int length) {
6952 NEW_STRING(isolate, String, NewFromTwoByte, uint16_t, data, type, length);
6953 return result;
6954 }
6955
Concat(Isolate * v8_isolate,Local<String> left,Local<String> right)6956 Local<String> v8::String::Concat(Isolate* v8_isolate, Local<String> left,
6957 Local<String> right) {
6958 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
6959 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
6960 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
6961 API_RCS_SCOPE(isolate, String, Concat);
6962 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
6963 // If we are steering towards a range error, do not wait for the error to be
6964 // thrown, and return the null handle instead.
6965 if (left_string->length() + right_string->length() > i::String::kMaxLength) {
6966 return Local<String>();
6967 }
6968 i::Handle<i::String> result = isolate->factory()
6969 ->NewConsString(left_string, right_string)
6970 .ToHandleChecked();
6971 return Utils::ToLocal(result);
6972 }
6973
NewExternalTwoByte(Isolate * isolate,v8::String::ExternalStringResource * resource)6974 MaybeLocal<String> v8::String::NewExternalTwoByte(
6975 Isolate* isolate, v8::String::ExternalStringResource* resource) {
6976 CHECK(resource && resource->data());
6977 // TODO(dcarney): throw a context free exception.
6978 if (resource->length() > static_cast<size_t>(i::String::kMaxLength)) {
6979 return MaybeLocal<String>();
6980 }
6981 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6982 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
6983 API_RCS_SCOPE(i_isolate, String, NewExternalTwoByte);
6984 if (resource->length() > 0) {
6985 i::Handle<i::String> string = i_isolate->factory()
6986 ->NewExternalStringFromTwoByte(resource)
6987 .ToHandleChecked();
6988 return Utils::ToLocal(string);
6989 } else {
6990 // The resource isn't going to be used, free it immediately.
6991 resource->Dispose();
6992 return Utils::ToLocal(i_isolate->factory()->empty_string());
6993 }
6994 }
6995
NewExternalOneByte(Isolate * isolate,v8::String::ExternalOneByteStringResource * resource)6996 MaybeLocal<String> v8::String::NewExternalOneByte(
6997 Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
6998 CHECK_NOT_NULL(resource);
6999 // TODO(dcarney): throw a context free exception.
7000 if (resource->length() > static_cast<size_t>(i::String::kMaxLength)) {
7001 return MaybeLocal<String>();
7002 }
7003 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7004 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7005 API_RCS_SCOPE(i_isolate, String, NewExternalOneByte);
7006 if (resource->length() == 0) {
7007 // The resource isn't going to be used, free it immediately.
7008 resource->Dispose();
7009 return Utils::ToLocal(i_isolate->factory()->empty_string());
7010 }
7011 CHECK_NOT_NULL(resource->data());
7012 i::Handle<i::String> string = i_isolate->factory()
7013 ->NewExternalStringFromOneByte(resource)
7014 .ToHandleChecked();
7015 return Utils::ToLocal(string);
7016 }
7017
MakeExternal(v8::String::ExternalStringResource * resource)7018 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
7019 i::DisallowGarbageCollection no_gc;
7020
7021 i::String obj = *Utils::OpenHandle(this);
7022
7023 if (obj.IsThinString()) {
7024 obj = i::ThinString::cast(obj).actual();
7025 }
7026
7027 if (!obj.SupportsExternalization()) {
7028 return false;
7029 }
7030
7031 // It is safe to call GetIsolateFromWritableHeapObject because
7032 // SupportsExternalization already checked that the object is writable.
7033 i::Isolate* isolate = i::GetIsolateFromWritableObject(obj);
7034 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7035
7036 CHECK(resource && resource->data());
7037
7038 bool result = obj.MakeExternal(resource);
7039 DCHECK(result);
7040 DCHECK(obj.IsExternalString());
7041 return result;
7042 }
7043
MakeExternal(v8::String::ExternalOneByteStringResource * resource)7044 bool v8::String::MakeExternal(
7045 v8::String::ExternalOneByteStringResource* resource) {
7046 i::DisallowGarbageCollection no_gc;
7047
7048 i::String obj = *Utils::OpenHandle(this);
7049
7050 if (obj.IsThinString()) {
7051 obj = i::ThinString::cast(obj).actual();
7052 }
7053
7054 if (!obj.SupportsExternalization()) {
7055 return false;
7056 }
7057
7058 // It is safe to call GetIsolateFromWritableHeapObject because
7059 // SupportsExternalization already checked that the object is writable.
7060 i::Isolate* isolate = i::GetIsolateFromWritableObject(obj);
7061 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7062
7063 CHECK(resource && resource->data());
7064
7065 bool result = obj.MakeExternal(resource);
7066 DCHECK_IMPLIES(result, obj.IsExternalString());
7067 return result;
7068 }
7069
CanMakeExternal() const7070 bool v8::String::CanMakeExternal() const {
7071 i::String obj = *Utils::OpenHandle(this);
7072
7073 if (obj.IsThinString()) {
7074 obj = i::ThinString::cast(obj).actual();
7075 }
7076
7077 if (!obj.SupportsExternalization()) {
7078 return false;
7079 }
7080
7081 // Only old space strings should be externalized.
7082 return !i::Heap::InYoungGeneration(obj);
7083 }
7084
StringEquals(Local<String> that) const7085 bool v8::String::StringEquals(Local<String> that) const {
7086 auto self = Utils::OpenHandle(this);
7087 auto other = Utils::OpenHandle(*that);
7088 return self->Equals(*other);
7089 }
7090
GetIsolate()7091 Isolate* v8::Object::GetIsolate() {
7092 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
7093 return reinterpret_cast<Isolate*>(i_isolate);
7094 }
7095
New(Isolate * isolate)7096 Local<v8::Object> v8::Object::New(Isolate* isolate) {
7097 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7098 API_RCS_SCOPE(i_isolate, Object, New);
7099 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7100 i::Handle<i::JSObject> obj =
7101 i_isolate->factory()->NewJSObject(i_isolate->object_function());
7102 return Utils::ToLocal(obj);
7103 }
7104
7105 namespace {
7106
7107 // TODO(v8:7569): This is a workaround for the Handle vs MaybeHandle difference
7108 // in the return types of the different Add functions:
7109 // OrderedNameDictionary::Add returns MaybeHandle, NameDictionary::Add returns
7110 // Handle.
7111 template <typename T>
ToHandle(i::Handle<T> h)7112 i::Handle<T> ToHandle(i::Handle<T> h) {
7113 return h;
7114 }
7115 template <typename T>
ToHandle(i::MaybeHandle<T> h)7116 i::Handle<T> ToHandle(i::MaybeHandle<T> h) {
7117 return h.ToHandleChecked();
7118 }
7119
7120 template <typename Dictionary>
AddPropertiesAndElementsToObject(i::Isolate * i_isolate,i::Handle<Dictionary> & properties,i::Handle<i::FixedArrayBase> & elements,Local<Name> * names,Local<Value> * values,size_t length)7121 void AddPropertiesAndElementsToObject(i::Isolate* i_isolate,
7122 i::Handle<Dictionary>& properties,
7123 i::Handle<i::FixedArrayBase>& elements,
7124 Local<Name>* names, Local<Value>* values,
7125 size_t length) {
7126 for (size_t i = 0; i < length; ++i) {
7127 i::Handle<i::Name> name = Utils::OpenHandle(*names[i]);
7128 i::Handle<i::Object> value = Utils::OpenHandle(*values[i]);
7129
7130 // See if the {name} is a valid array index, in which case we need to
7131 // add the {name}/{value} pair to the {elements}, otherwise they end
7132 // up in the {properties} backing store.
7133 uint32_t index;
7134 if (name->AsArrayIndex(&index)) {
7135 // If this is the first element, allocate a proper
7136 // dictionary elements backing store for {elements}.
7137 if (!elements->IsNumberDictionary()) {
7138 elements =
7139 i::NumberDictionary::New(i_isolate, static_cast<int>(length));
7140 }
7141 elements = i::NumberDictionary::Set(
7142 i_isolate, i::Handle<i::NumberDictionary>::cast(elements), index,
7143 value);
7144 } else {
7145 // Internalize the {name} first.
7146 name = i_isolate->factory()->InternalizeName(name);
7147 i::InternalIndex const entry = properties->FindEntry(i_isolate, name);
7148 if (entry.is_not_found()) {
7149 // Add the {name}/{value} pair as a new entry.
7150 properties = ToHandle(Dictionary::Add(
7151 i_isolate, properties, name, value, i::PropertyDetails::Empty()));
7152 } else {
7153 // Overwrite the {entry} with the {value}.
7154 properties->ValueAtPut(entry, *value);
7155 }
7156 }
7157 }
7158 }
7159
7160 } // namespace
7161
New(Isolate * isolate,Local<Value> prototype_or_null,Local<Name> * names,Local<Value> * values,size_t length)7162 Local<v8::Object> v8::Object::New(Isolate* isolate,
7163 Local<Value> prototype_or_null,
7164 Local<Name>* names, Local<Value>* values,
7165 size_t length) {
7166 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7167 i::Handle<i::Object> proto = Utils::OpenHandle(*prototype_or_null);
7168 if (!Utils::ApiCheck(proto->IsNull() || proto->IsJSReceiver(),
7169 "v8::Object::New", "prototype must be null or object")) {
7170 return Local<v8::Object>();
7171 }
7172 API_RCS_SCOPE(i_isolate, Object, New);
7173 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7174
7175 i::Handle<i::FixedArrayBase> elements =
7176 i_isolate->factory()->empty_fixed_array();
7177
7178 // We assume that this API is mostly used to create objects with named
7179 // properties, and so we default to creating a properties backing store
7180 // large enough to hold all of them, while we start with no elements
7181 // (see http://bit.ly/v8-fast-object-create-cpp for the motivation).
7182 if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
7183 i::Handle<i::SwissNameDictionary> properties =
7184 i_isolate->factory()->NewSwissNameDictionary(static_cast<int>(length));
7185 AddPropertiesAndElementsToObject(i_isolate, properties, elements, names,
7186 values, length);
7187 i::Handle<i::JSObject> obj =
7188 i_isolate->factory()->NewSlowJSObjectWithPropertiesAndElements(
7189 i::Handle<i::HeapObject>::cast(proto), properties, elements);
7190 return Utils::ToLocal(obj);
7191 } else {
7192 i::Handle<i::NameDictionary> properties =
7193 i::NameDictionary::New(i_isolate, static_cast<int>(length));
7194 AddPropertiesAndElementsToObject(i_isolate, properties, elements, names,
7195 values, length);
7196 i::Handle<i::JSObject> obj =
7197 i_isolate->factory()->NewSlowJSObjectWithPropertiesAndElements(
7198 i::Handle<i::HeapObject>::cast(proto), properties, elements);
7199 return Utils::ToLocal(obj);
7200 }
7201 }
7202
New(Isolate * isolate,double value)7203 Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) {
7204 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7205 API_RCS_SCOPE(i_isolate, NumberObject, New);
7206 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7207 i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value);
7208 i::Handle<i::Object> obj =
7209 i::Object::ToObject(i_isolate, number).ToHandleChecked();
7210 return Utils::ToLocal(obj);
7211 }
7212
ValueOf() const7213 double v8::NumberObject::ValueOf() const {
7214 i::Handle<i::Object> obj = Utils::OpenHandle(this);
7215 i::Handle<i::JSPrimitiveWrapper> js_primitive_wrapper =
7216 i::Handle<i::JSPrimitiveWrapper>::cast(obj);
7217 API_RCS_SCOPE(js_primitive_wrapper->GetIsolate(), NumberObject, NumberValue);
7218 return js_primitive_wrapper->value().Number();
7219 }
7220
New(Isolate * isolate,int64_t value)7221 Local<v8::Value> v8::BigIntObject::New(Isolate* isolate, int64_t value) {
7222 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7223 API_RCS_SCOPE(i_isolate, BigIntObject, New);
7224 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7225 i::Handle<i::Object> bigint = i::BigInt::FromInt64(i_isolate, value);
7226 i::Handle<i::Object> obj =
7227 i::Object::ToObject(i_isolate, bigint).ToHandleChecked();
7228 return Utils::ToLocal(obj);
7229 }
7230
ValueOf() const7231 Local<v8::BigInt> v8::BigIntObject::ValueOf() const {
7232 i::Handle<i::Object> obj = Utils::OpenHandle(this);
7233 i::Handle<i::JSPrimitiveWrapper> js_primitive_wrapper =
7234 i::Handle<i::JSPrimitiveWrapper>::cast(obj);
7235 i::Isolate* isolate = js_primitive_wrapper->GetIsolate();
7236 API_RCS_SCOPE(isolate, BigIntObject, BigIntValue);
7237 return Utils::ToLocal(i::Handle<i::BigInt>(
7238 i::BigInt::cast(js_primitive_wrapper->value()), isolate));
7239 }
7240
New(Isolate * isolate,bool value)7241 Local<v8::Value> v8::BooleanObject::New(Isolate* isolate, bool value) {
7242 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7243 API_RCS_SCOPE(i_isolate, BooleanObject, New);
7244 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7245 i::Handle<i::Object> boolean(value
7246 ? i::ReadOnlyRoots(i_isolate).true_value()
7247 : i::ReadOnlyRoots(i_isolate).false_value(),
7248 i_isolate);
7249 i::Handle<i::Object> obj =
7250 i::Object::ToObject(i_isolate, boolean).ToHandleChecked();
7251 return Utils::ToLocal(obj);
7252 }
7253
ValueOf() const7254 bool v8::BooleanObject::ValueOf() const {
7255 i::Object obj = *Utils::OpenHandle(this);
7256 i::JSPrimitiveWrapper js_primitive_wrapper = i::JSPrimitiveWrapper::cast(obj);
7257 i::Isolate* isolate = js_primitive_wrapper.GetIsolate();
7258 API_RCS_SCOPE(isolate, BooleanObject, BooleanValue);
7259 return js_primitive_wrapper.value().IsTrue(isolate);
7260 }
7261
New(Isolate * v8_isolate,Local<String> value)7262 Local<v8::Value> v8::StringObject::New(Isolate* v8_isolate,
7263 Local<String> value) {
7264 i::Handle<i::String> string = Utils::OpenHandle(*value);
7265 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
7266 API_RCS_SCOPE(isolate, StringObject, New);
7267 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7268 i::Handle<i::Object> obj =
7269 i::Object::ToObject(isolate, string).ToHandleChecked();
7270 return Utils::ToLocal(obj);
7271 }
7272
ValueOf() const7273 Local<v8::String> v8::StringObject::ValueOf() const {
7274 i::Handle<i::Object> obj = Utils::OpenHandle(this);
7275 i::Handle<i::JSPrimitiveWrapper> js_primitive_wrapper =
7276 i::Handle<i::JSPrimitiveWrapper>::cast(obj);
7277 i::Isolate* isolate = js_primitive_wrapper->GetIsolate();
7278 API_RCS_SCOPE(isolate, StringObject, StringValue);
7279 return Utils::ToLocal(i::Handle<i::String>(
7280 i::String::cast(js_primitive_wrapper->value()), isolate));
7281 }
7282
New(Isolate * isolate,Local<Symbol> value)7283 Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Local<Symbol> value) {
7284 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7285 API_RCS_SCOPE(i_isolate, SymbolObject, New);
7286 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7287 i::Handle<i::Object> obj =
7288 i::Object::ToObject(i_isolate, Utils::OpenHandle(*value))
7289 .ToHandleChecked();
7290 return Utils::ToLocal(obj);
7291 }
7292
ValueOf() const7293 Local<v8::Symbol> v8::SymbolObject::ValueOf() const {
7294 i::Handle<i::Object> obj = Utils::OpenHandle(this);
7295 i::Handle<i::JSPrimitiveWrapper> js_primitive_wrapper =
7296 i::Handle<i::JSPrimitiveWrapper>::cast(obj);
7297 i::Isolate* isolate = js_primitive_wrapper->GetIsolate();
7298 API_RCS_SCOPE(isolate, SymbolObject, SymbolValue);
7299 return Utils::ToLocal(i::Handle<i::Symbol>(
7300 i::Symbol::cast(js_primitive_wrapper->value()), isolate));
7301 }
7302
New(Local<Context> context,double time)7303 MaybeLocal<v8::Value> v8::Date::New(Local<Context> context, double time) {
7304 if (std::isnan(time)) {
7305 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
7306 time = std::numeric_limits<double>::quiet_NaN();
7307 }
7308 PREPARE_FOR_EXECUTION(context, Date, New, Value);
7309 Local<Value> result;
7310 has_pending_exception = !ToLocal<Value>(
7311 i::JSDate::New(isolate->date_function(), isolate->date_function(), time),
7312 &result);
7313 RETURN_ON_FAILED_EXECUTION(Value);
7314 RETURN_ESCAPED(result);
7315 }
7316
ValueOf() const7317 double v8::Date::ValueOf() const {
7318 i::Handle<i::Object> obj = Utils::OpenHandle(this);
7319 i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj);
7320 API_RCS_SCOPE(jsdate->GetIsolate(), Date, NumberValue);
7321 return jsdate->value().Number();
7322 }
7323
7324 // Assert that the static TimeZoneDetection cast in
7325 // DateTimeConfigurationChangeNotification is valid.
7326 #define TIME_ZONE_DETECTION_ASSERT_EQ(value) \
7327 STATIC_ASSERT( \
7328 static_cast<int>(v8::Isolate::TimeZoneDetection::value) == \
7329 static_cast<int>(base::TimezoneCache::TimeZoneDetection::value));
7330 TIME_ZONE_DETECTION_ASSERT_EQ(kSkip)
TIME_ZONE_DETECTION_ASSERT_EQ(kRedetect)7331 TIME_ZONE_DETECTION_ASSERT_EQ(kRedetect)
7332 #undef TIME_ZONE_DETECTION_ASSERT_EQ
7333
7334 MaybeLocal<v8::RegExp> v8::RegExp::New(Local<Context> context,
7335 Local<String> pattern, Flags flags) {
7336 PREPARE_FOR_EXECUTION(context, RegExp, New, RegExp);
7337 Local<v8::RegExp> result;
7338 has_pending_exception =
7339 !ToLocal<RegExp>(i::JSRegExp::New(isolate, Utils::OpenHandle(*pattern),
7340 static_cast<i::JSRegExp::Flags>(flags)),
7341 &result);
7342 RETURN_ON_FAILED_EXECUTION(RegExp);
7343 RETURN_ESCAPED(result);
7344 }
7345
NewWithBacktrackLimit(Local<Context> context,Local<String> pattern,Flags flags,uint32_t backtrack_limit)7346 MaybeLocal<v8::RegExp> v8::RegExp::NewWithBacktrackLimit(
7347 Local<Context> context, Local<String> pattern, Flags flags,
7348 uint32_t backtrack_limit) {
7349 Utils::ApiCheck(i::Smi::IsValid(backtrack_limit),
7350 "v8::RegExp::NewWithBacktrackLimit",
7351 "backtrack_limit is too large or too small.");
7352 Utils::ApiCheck(backtrack_limit != i::JSRegExp::kNoBacktrackLimit,
7353 "v8::RegExp::NewWithBacktrackLimit",
7354 "Must set backtrack_limit");
7355 PREPARE_FOR_EXECUTION(context, RegExp, New, RegExp);
7356 Local<v8::RegExp> result;
7357 has_pending_exception = !ToLocal<RegExp>(
7358 i::JSRegExp::New(isolate, Utils::OpenHandle(*pattern),
7359 static_cast<i::JSRegExp::Flags>(flags), backtrack_limit),
7360 &result);
7361 RETURN_ON_FAILED_EXECUTION(RegExp);
7362 RETURN_ESCAPED(result);
7363 }
7364
GetSource() const7365 Local<v8::String> v8::RegExp::GetSource() const {
7366 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
7367 return Utils::ToLocal(
7368 i::Handle<i::String>(obj->EscapedPattern(), obj->GetIsolate()));
7369 }
7370
7371 // Assert that the static flags cast in GetFlags is valid.
7372 #define REGEXP_FLAG_ASSERT_EQ(flag) \
7373 STATIC_ASSERT(static_cast<int>(v8::RegExp::flag) == \
7374 static_cast<int>(i::JSRegExp::flag))
7375 REGEXP_FLAG_ASSERT_EQ(kNone);
7376 REGEXP_FLAG_ASSERT_EQ(kGlobal);
7377 REGEXP_FLAG_ASSERT_EQ(kIgnoreCase);
7378 REGEXP_FLAG_ASSERT_EQ(kMultiline);
7379 REGEXP_FLAG_ASSERT_EQ(kSticky);
7380 REGEXP_FLAG_ASSERT_EQ(kUnicode);
7381 REGEXP_FLAG_ASSERT_EQ(kHasIndices);
7382 REGEXP_FLAG_ASSERT_EQ(kLinear);
7383 #undef REGEXP_FLAG_ASSERT_EQ
7384
GetFlags() const7385 v8::RegExp::Flags v8::RegExp::GetFlags() const {
7386 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
7387 return RegExp::Flags(static_cast<int>(obj->flags()));
7388 }
7389
Exec(Local<Context> context,Local<v8::String> subject)7390 MaybeLocal<v8::Object> v8::RegExp::Exec(Local<Context> context,
7391 Local<v8::String> subject) {
7392 PREPARE_FOR_EXECUTION(context, RegExp, Exec, Object);
7393
7394 i::Handle<i::JSRegExp> regexp = Utils::OpenHandle(this);
7395 i::Handle<i::String> subject_string = Utils::OpenHandle(*subject);
7396
7397 // TODO(jgruber): RegExpUtils::RegExpExec was not written with efficiency in
7398 // mind. It fetches the 'exec' property and then calls it through JSEntry.
7399 // Unfortunately, this is currently the only full implementation of
7400 // RegExp.prototype.exec available in C++.
7401 Local<v8::Object> result;
7402 has_pending_exception = !ToLocal<Object>(
7403 i::RegExpUtils::RegExpExec(isolate, regexp, subject_string,
7404 isolate->factory()->undefined_value()),
7405 &result);
7406
7407 RETURN_ON_FAILED_EXECUTION(Object);
7408 RETURN_ESCAPED(result);
7409 }
7410
New(Isolate * isolate,int length)7411 Local<v8::Array> v8::Array::New(Isolate* isolate, int length) {
7412 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7413 API_RCS_SCOPE(i_isolate, Array, New);
7414 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7415 int real_length = length > 0 ? length : 0;
7416 i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length);
7417 i::Handle<i::Object> length_obj =
7418 i_isolate->factory()->NewNumberFromInt(real_length);
7419 obj->set_length(*length_obj);
7420 return Utils::ToLocal(obj);
7421 }
7422
New(Isolate * isolate,Local<Value> * elements,size_t length)7423 Local<v8::Array> v8::Array::New(Isolate* isolate, Local<Value>* elements,
7424 size_t length) {
7425 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7426 i::Factory* factory = i_isolate->factory();
7427 API_RCS_SCOPE(i_isolate, Array, New);
7428 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7429 int len = static_cast<int>(length);
7430
7431 i::Handle<i::FixedArray> result = factory->NewFixedArray(len);
7432 for (int i = 0; i < len; i++) {
7433 i::Handle<i::Object> element = Utils::OpenHandle(*elements[i]);
7434 result->set(i, *element);
7435 }
7436
7437 return Utils::ToLocal(
7438 factory->NewJSArrayWithElements(result, i::PACKED_ELEMENTS, len));
7439 }
7440
Length() const7441 uint32_t v8::Array::Length() const {
7442 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
7443 i::Object length = obj->length();
7444 if (length.IsSmi()) {
7445 return i::Smi::ToInt(length);
7446 } else {
7447 return static_cast<uint32_t>(length.Number());
7448 }
7449 }
7450
New(Isolate * isolate)7451 Local<v8::Map> v8::Map::New(Isolate* isolate) {
7452 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7453 API_RCS_SCOPE(i_isolate, Map, New);
7454 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7455 i::Handle<i::JSMap> obj = i_isolate->factory()->NewJSMap();
7456 return Utils::ToLocal(obj);
7457 }
7458
Size() const7459 size_t v8::Map::Size() const {
7460 i::Handle<i::JSMap> obj = Utils::OpenHandle(this);
7461 return i::OrderedHashMap::cast(obj->table()).NumberOfElements();
7462 }
7463
Clear()7464 void Map::Clear() {
7465 auto self = Utils::OpenHandle(this);
7466 i::Isolate* isolate = self->GetIsolate();
7467 API_RCS_SCOPE(isolate, Map, Clear);
7468 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7469 i::JSMap::Clear(isolate, self);
7470 }
7471
Get(Local<Context> context,Local<Value> key)7472 MaybeLocal<Value> Map::Get(Local<Context> context, Local<Value> key) {
7473 PREPARE_FOR_EXECUTION(context, Map, Get, Value);
7474 auto self = Utils::OpenHandle(this);
7475 Local<Value> result;
7476 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7477 has_pending_exception =
7478 !ToLocal<Value>(i::Execution::CallBuiltin(isolate, isolate->map_get(),
7479 self, arraysize(argv), argv),
7480 &result);
7481 RETURN_ON_FAILED_EXECUTION(Value);
7482 RETURN_ESCAPED(result);
7483 }
7484
Set(Local<Context> context,Local<Value> key,Local<Value> value)7485 MaybeLocal<Map> Map::Set(Local<Context> context, Local<Value> key,
7486 Local<Value> value) {
7487 PREPARE_FOR_EXECUTION(context, Map, Set, Map);
7488 auto self = Utils::OpenHandle(this);
7489 i::Handle<i::Object> result;
7490 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key),
7491 Utils::OpenHandle(*value)};
7492 has_pending_exception =
7493 !i::Execution::CallBuiltin(isolate, isolate->map_set(), self,
7494 arraysize(argv), argv)
7495 .ToHandle(&result);
7496 RETURN_ON_FAILED_EXECUTION(Map);
7497 RETURN_ESCAPED(Local<Map>::Cast(Utils::ToLocal(result)));
7498 }
7499
Has(Local<Context> context,Local<Value> key)7500 Maybe<bool> Map::Has(Local<Context> context, Local<Value> key) {
7501 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7502 ENTER_V8(isolate, context, Map, Has, Nothing<bool>(), i::HandleScope);
7503 auto self = Utils::OpenHandle(this);
7504 i::Handle<i::Object> result;
7505 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7506 has_pending_exception =
7507 !i::Execution::CallBuiltin(isolate, isolate->map_has(), self,
7508 arraysize(argv), argv)
7509 .ToHandle(&result);
7510 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7511 return Just(result->IsTrue(isolate));
7512 }
7513
Delete(Local<Context> context,Local<Value> key)7514 Maybe<bool> Map::Delete(Local<Context> context, Local<Value> key) {
7515 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7516 ENTER_V8(isolate, context, Map, Delete, Nothing<bool>(), i::HandleScope);
7517 auto self = Utils::OpenHandle(this);
7518 i::Handle<i::Object> result;
7519 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7520 has_pending_exception =
7521 !i::Execution::CallBuiltin(isolate, isolate->map_delete(), self,
7522 arraysize(argv), argv)
7523 .ToHandle(&result);
7524 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7525 return Just(result->IsTrue(isolate));
7526 }
7527
7528 namespace {
7529
7530 enum class MapAsArrayKind {
7531 kEntries = i::JS_MAP_KEY_VALUE_ITERATOR_TYPE,
7532 kKeys = i::JS_MAP_KEY_ITERATOR_TYPE,
7533 kValues = i::JS_MAP_VALUE_ITERATOR_TYPE
7534 };
7535
7536 enum class SetAsArrayKind {
7537 kEntries = i::JS_SET_KEY_VALUE_ITERATOR_TYPE,
7538 kValues = i::JS_SET_VALUE_ITERATOR_TYPE
7539 };
7540
MapAsArray(i::Isolate * isolate,i::Object table_obj,int offset,MapAsArrayKind kind)7541 i::Handle<i::JSArray> MapAsArray(i::Isolate* isolate, i::Object table_obj,
7542 int offset, MapAsArrayKind kind) {
7543 i::Factory* factory = isolate->factory();
7544 i::Handle<i::OrderedHashMap> table(i::OrderedHashMap::cast(table_obj),
7545 isolate);
7546 const bool collect_keys =
7547 kind == MapAsArrayKind::kEntries || kind == MapAsArrayKind::kKeys;
7548 const bool collect_values =
7549 kind == MapAsArrayKind::kEntries || kind == MapAsArrayKind::kValues;
7550 int capacity = table->UsedCapacity();
7551 int max_length =
7552 (capacity - offset) * ((collect_keys && collect_values) ? 2 : 1);
7553 i::Handle<i::FixedArray> result = factory->NewFixedArray(max_length);
7554 int result_index = 0;
7555 {
7556 i::DisallowGarbageCollection no_gc;
7557 i::Oddball the_hole = i::ReadOnlyRoots(isolate).the_hole_value();
7558 for (int i = offset; i < capacity; ++i) {
7559 i::InternalIndex entry(i);
7560 i::Object key = table->KeyAt(entry);
7561 if (key == the_hole) continue;
7562 if (collect_keys) result->set(result_index++, key);
7563 if (collect_values) result->set(result_index++, table->ValueAt(entry));
7564 }
7565 }
7566 DCHECK_GE(max_length, result_index);
7567 if (result_index == 0) return factory->NewJSArray(0);
7568 result->Shrink(isolate, result_index);
7569 return factory->NewJSArrayWithElements(result, i::PACKED_ELEMENTS,
7570 result_index);
7571 }
7572
7573 } // namespace
7574
AsArray() const7575 Local<Array> Map::AsArray() const {
7576 i::Handle<i::JSMap> obj = Utils::OpenHandle(this);
7577 i::Isolate* isolate = obj->GetIsolate();
7578 API_RCS_SCOPE(isolate, Map, AsArray);
7579 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7580 return Utils::ToLocal(
7581 MapAsArray(isolate, obj->table(), 0, MapAsArrayKind::kEntries));
7582 }
7583
New(Isolate * isolate)7584 Local<v8::Set> v8::Set::New(Isolate* isolate) {
7585 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7586 API_RCS_SCOPE(i_isolate, Set, New);
7587 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7588 i::Handle<i::JSSet> obj = i_isolate->factory()->NewJSSet();
7589 return Utils::ToLocal(obj);
7590 }
7591
Size() const7592 size_t v8::Set::Size() const {
7593 i::Handle<i::JSSet> obj = Utils::OpenHandle(this);
7594 return i::OrderedHashSet::cast(obj->table()).NumberOfElements();
7595 }
7596
Clear()7597 void Set::Clear() {
7598 auto self = Utils::OpenHandle(this);
7599 i::Isolate* isolate = self->GetIsolate();
7600 API_RCS_SCOPE(isolate, Set, Clear);
7601 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7602 i::JSSet::Clear(isolate, self);
7603 }
7604
Add(Local<Context> context,Local<Value> key)7605 MaybeLocal<Set> Set::Add(Local<Context> context, Local<Value> key) {
7606 PREPARE_FOR_EXECUTION(context, Set, Add, Set);
7607 auto self = Utils::OpenHandle(this);
7608 i::Handle<i::Object> result;
7609 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7610 has_pending_exception =
7611 !i::Execution::CallBuiltin(isolate, isolate->set_add(), self,
7612 arraysize(argv), argv)
7613 .ToHandle(&result);
7614 RETURN_ON_FAILED_EXECUTION(Set);
7615 RETURN_ESCAPED(Local<Set>::Cast(Utils::ToLocal(result)));
7616 }
7617
Has(Local<Context> context,Local<Value> key)7618 Maybe<bool> Set::Has(Local<Context> context, Local<Value> key) {
7619 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7620 ENTER_V8(isolate, context, Set, Has, Nothing<bool>(), i::HandleScope);
7621 auto self = Utils::OpenHandle(this);
7622 i::Handle<i::Object> result;
7623 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7624 has_pending_exception =
7625 !i::Execution::CallBuiltin(isolate, isolate->set_has(), self,
7626 arraysize(argv), argv)
7627 .ToHandle(&result);
7628 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7629 return Just(result->IsTrue(isolate));
7630 }
7631
Delete(Local<Context> context,Local<Value> key)7632 Maybe<bool> Set::Delete(Local<Context> context, Local<Value> key) {
7633 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7634 ENTER_V8(isolate, context, Set, Delete, Nothing<bool>(), i::HandleScope);
7635 auto self = Utils::OpenHandle(this);
7636 i::Handle<i::Object> result;
7637 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7638 has_pending_exception =
7639 !i::Execution::CallBuiltin(isolate, isolate->set_delete(), self,
7640 arraysize(argv), argv)
7641 .ToHandle(&result);
7642 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7643 return Just(result->IsTrue(isolate));
7644 }
7645
7646 namespace {
SetAsArray(i::Isolate * isolate,i::Object table_obj,int offset,SetAsArrayKind kind)7647 i::Handle<i::JSArray> SetAsArray(i::Isolate* isolate, i::Object table_obj,
7648 int offset, SetAsArrayKind kind) {
7649 i::Factory* factory = isolate->factory();
7650 i::Handle<i::OrderedHashSet> table(i::OrderedHashSet::cast(table_obj),
7651 isolate);
7652 // Elements skipped by |offset| may already be deleted.
7653 int capacity = table->UsedCapacity();
7654 const bool collect_key_values = kind == SetAsArrayKind::kEntries;
7655 int max_length = (capacity - offset) * (collect_key_values ? 2 : 1);
7656 if (max_length == 0) return factory->NewJSArray(0);
7657 i::Handle<i::FixedArray> result = factory->NewFixedArray(max_length);
7658 int result_index = 0;
7659 {
7660 i::DisallowGarbageCollection no_gc;
7661 i::Oddball the_hole = i::ReadOnlyRoots(isolate).the_hole_value();
7662 for (int i = offset; i < capacity; ++i) {
7663 i::InternalIndex entry(i);
7664 i::Object key = table->KeyAt(entry);
7665 if (key == the_hole) continue;
7666 result->set(result_index++, key);
7667 if (collect_key_values) result->set(result_index++, key);
7668 }
7669 }
7670 DCHECK_GE(max_length, result_index);
7671 if (result_index == 0) return factory->NewJSArray(0);
7672 result->Shrink(isolate, result_index);
7673 return factory->NewJSArrayWithElements(result, i::PACKED_ELEMENTS,
7674 result_index);
7675 }
7676 } // namespace
7677
AsArray() const7678 Local<Array> Set::AsArray() const {
7679 i::Handle<i::JSSet> obj = Utils::OpenHandle(this);
7680 i::Isolate* isolate = obj->GetIsolate();
7681 API_RCS_SCOPE(isolate, Set, AsArray);
7682 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7683 return Utils::ToLocal(
7684 SetAsArray(isolate, obj->table(), 0, SetAsArrayKind::kValues));
7685 }
7686
New(Local<Context> context)7687 MaybeLocal<Promise::Resolver> Promise::Resolver::New(Local<Context> context) {
7688 PREPARE_FOR_EXECUTION(context, Promise_Resolver, New, Resolver);
7689 Local<Promise::Resolver> result;
7690 has_pending_exception =
7691 !ToLocal<Promise::Resolver>(isolate->factory()->NewJSPromise(), &result);
7692 RETURN_ON_FAILED_EXECUTION(Promise::Resolver);
7693 RETURN_ESCAPED(result);
7694 }
7695
GetPromise()7696 Local<Promise> Promise::Resolver::GetPromise() {
7697 i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
7698 return Local<Promise>::Cast(Utils::ToLocal(promise));
7699 }
7700
Resolve(Local<Context> context,Local<Value> value)7701 Maybe<bool> Promise::Resolver::Resolve(Local<Context> context,
7702 Local<Value> value) {
7703 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7704 ENTER_V8(isolate, context, Promise_Resolver, Resolve, Nothing<bool>(),
7705 i::HandleScope);
7706 auto self = Utils::OpenHandle(this);
7707 auto promise = i::Handle<i::JSPromise>::cast(self);
7708
7709 if (promise->status() != Promise::kPending) {
7710 return Just(true);
7711 }
7712
7713 has_pending_exception =
7714 i::JSPromise::Resolve(promise, Utils::OpenHandle(*value)).is_null();
7715 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7716 return Just(true);
7717 }
7718
Reject(Local<Context> context,Local<Value> value)7719 Maybe<bool> Promise::Resolver::Reject(Local<Context> context,
7720 Local<Value> value) {
7721 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7722 ENTER_V8(isolate, context, Promise_Resolver, Reject, Nothing<bool>(),
7723 i::HandleScope);
7724 auto self = Utils::OpenHandle(this);
7725 auto promise = i::Handle<i::JSPromise>::cast(self);
7726
7727 if (promise->status() != Promise::kPending) {
7728 return Just(true);
7729 }
7730
7731 has_pending_exception =
7732 i::JSPromise::Reject(promise, Utils::OpenHandle(*value)).is_null();
7733 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7734 return Just(true);
7735 }
7736
Catch(Local<Context> context,Local<Function> handler)7737 MaybeLocal<Promise> Promise::Catch(Local<Context> context,
7738 Local<Function> handler) {
7739 PREPARE_FOR_EXECUTION(context, Promise, Catch, Promise);
7740 auto self = Utils::OpenHandle(this);
7741 i::Handle<i::Object> argv[] = {isolate->factory()->undefined_value(),
7742 Utils::OpenHandle(*handler)};
7743 i::Handle<i::Object> result;
7744 // Do not call the built-in Promise.prototype.catch!
7745 // v8::Promise should not call out to a monkeypatched Promise.prototype.then
7746 // as the implementation of Promise.prototype.catch does.
7747 has_pending_exception =
7748 !i::Execution::CallBuiltin(isolate, isolate->promise_then(), self,
7749 arraysize(argv), argv)
7750 .ToHandle(&result);
7751 RETURN_ON_FAILED_EXECUTION(Promise);
7752 RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
7753 }
7754
Then(Local<Context> context,Local<Function> handler)7755 MaybeLocal<Promise> Promise::Then(Local<Context> context,
7756 Local<Function> handler) {
7757 PREPARE_FOR_EXECUTION(context, Promise, Then, Promise);
7758 auto self = Utils::OpenHandle(this);
7759 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*handler)};
7760 i::Handle<i::Object> result;
7761 has_pending_exception =
7762 !i::Execution::CallBuiltin(isolate, isolate->promise_then(), self,
7763 arraysize(argv), argv)
7764 .ToHandle(&result);
7765 RETURN_ON_FAILED_EXECUTION(Promise);
7766 RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
7767 }
7768
Then(Local<Context> context,Local<Function> on_fulfilled,Local<Function> on_rejected)7769 MaybeLocal<Promise> Promise::Then(Local<Context> context,
7770 Local<Function> on_fulfilled,
7771 Local<Function> on_rejected) {
7772 PREPARE_FOR_EXECUTION(context, Promise, Then, Promise);
7773 auto self = Utils::OpenHandle(this);
7774 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*on_fulfilled),
7775 Utils::OpenHandle(*on_rejected)};
7776 i::Handle<i::Object> result;
7777 has_pending_exception =
7778 !i::Execution::CallBuiltin(isolate, isolate->promise_then(), self,
7779 arraysize(argv), argv)
7780 .ToHandle(&result);
7781 RETURN_ON_FAILED_EXECUTION(Promise);
7782 RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
7783 }
7784
HasHandler() const7785 bool Promise::HasHandler() const {
7786 i::JSReceiver promise = *Utils::OpenHandle(this);
7787 i::Isolate* isolate = promise.GetIsolate();
7788 API_RCS_SCOPE(isolate, Promise, HasRejectHandler);
7789 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7790 if (!promise.IsJSPromise()) return false;
7791 return i::JSPromise::cast(promise).has_handler();
7792 }
7793
Result()7794 Local<Value> Promise::Result() {
7795 i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
7796 i::Isolate* isolate = promise->GetIsolate();
7797 API_RCS_SCOPE(isolate, Promise, Result);
7798 i::Handle<i::JSPromise> js_promise = i::Handle<i::JSPromise>::cast(promise);
7799 Utils::ApiCheck(js_promise->status() != kPending, "v8_Promise_Result",
7800 "Promise is still pending");
7801 i::Handle<i::Object> result(js_promise->result(), isolate);
7802 return Utils::ToLocal(result);
7803 }
7804
State()7805 Promise::PromiseState Promise::State() {
7806 i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
7807 API_RCS_SCOPE(promise->GetIsolate(), Promise, Status);
7808 i::Handle<i::JSPromise> js_promise = i::Handle<i::JSPromise>::cast(promise);
7809 return static_cast<PromiseState>(js_promise->status());
7810 }
7811
MarkAsHandled()7812 void Promise::MarkAsHandled() {
7813 i::Handle<i::JSPromise> js_promise = Utils::OpenHandle(this);
7814 js_promise->set_has_handler(true);
7815 }
7816
MarkAsSilent()7817 void Promise::MarkAsSilent() {
7818 i::Handle<i::JSPromise> js_promise = Utils::OpenHandle(this);
7819 js_promise->set_is_silent(true);
7820 }
7821
GetTarget()7822 Local<Value> Proxy::GetTarget() {
7823 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7824 i::Handle<i::Object> target(self->target(), self->GetIsolate());
7825 return Utils::ToLocal(target);
7826 }
7827
GetHandler()7828 Local<Value> Proxy::GetHandler() {
7829 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7830 i::Handle<i::Object> handler(self->handler(), self->GetIsolate());
7831 return Utils::ToLocal(handler);
7832 }
7833
IsRevoked() const7834 bool Proxy::IsRevoked() const {
7835 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7836 return self->IsRevoked();
7837 }
7838
Revoke()7839 void Proxy::Revoke() {
7840 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7841 i::JSProxy::Revoke(self);
7842 }
7843
New(Local<Context> context,Local<Object> local_target,Local<Object> local_handler)7844 MaybeLocal<Proxy> Proxy::New(Local<Context> context, Local<Object> local_target,
7845 Local<Object> local_handler) {
7846 PREPARE_FOR_EXECUTION(context, Proxy, New, Proxy);
7847 i::Handle<i::JSReceiver> target = Utils::OpenHandle(*local_target);
7848 i::Handle<i::JSReceiver> handler = Utils::OpenHandle(*local_handler);
7849 Local<Proxy> result;
7850 has_pending_exception =
7851 !ToLocal<Proxy>(i::JSProxy::New(isolate, target, handler), &result);
7852 RETURN_ON_FAILED_EXECUTION(Proxy);
7853 RETURN_ESCAPED(result);
7854 }
7855
CompiledWasmModule(std::shared_ptr<internal::wasm::NativeModule> native_module,const char * source_url,size_t url_length)7856 CompiledWasmModule::CompiledWasmModule(
7857 std::shared_ptr<internal::wasm::NativeModule> native_module,
7858 const char* source_url, size_t url_length)
7859 : native_module_(std::move(native_module)),
7860 source_url_(source_url, url_length) {
7861 CHECK_NOT_NULL(native_module_);
7862 }
7863
Serialize()7864 OwnedBuffer CompiledWasmModule::Serialize() {
7865 #if V8_ENABLE_WEBASSEMBLY
7866 TRACE_EVENT0("v8.wasm", "wasm.SerializeModule");
7867 i::wasm::WasmSerializer wasm_serializer(native_module_.get());
7868 size_t buffer_size = wasm_serializer.GetSerializedNativeModuleSize();
7869 std::unique_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]);
7870 if (!wasm_serializer.SerializeNativeModule({buffer.get(), buffer_size}))
7871 return {};
7872 return {std::move(buffer), buffer_size};
7873 #else
7874 UNREACHABLE();
7875 #endif // V8_ENABLE_WEBASSEMBLY
7876 }
7877
GetWireBytesRef()7878 MemorySpan<const uint8_t> CompiledWasmModule::GetWireBytesRef() {
7879 #if V8_ENABLE_WEBASSEMBLY
7880 base::Vector<const uint8_t> bytes_vec = native_module_->wire_bytes();
7881 return {bytes_vec.begin(), bytes_vec.size()};
7882 #else
7883 UNREACHABLE();
7884 #endif // V8_ENABLE_WEBASSEMBLY
7885 }
7886
Buffer()7887 Local<ArrayBuffer> v8::WasmMemoryObject::Buffer() {
7888 #if V8_ENABLE_WEBASSEMBLY
7889 i::Handle<i::WasmMemoryObject> obj = Utils::OpenHandle(this);
7890 i::Handle<i::JSArrayBuffer> buffer(obj->array_buffer(), obj->GetIsolate());
7891 return Utils::ToLocal(buffer);
7892 #else
7893 UNREACHABLE();
7894 #endif // V8_ENABLE_WEBASSEMBLY
7895 }
7896
GetCompiledModule()7897 CompiledWasmModule WasmModuleObject::GetCompiledModule() {
7898 #if V8_ENABLE_WEBASSEMBLY
7899 auto obj = i::Handle<i::WasmModuleObject>::cast(Utils::OpenHandle(this));
7900 auto url =
7901 i::handle(i::String::cast(obj->script().name()), obj->GetIsolate());
7902 int length;
7903 std::unique_ptr<char[]> cstring =
7904 url->ToCString(i::DISALLOW_NULLS, i::FAST_STRING_TRAVERSAL, &length);
7905 return CompiledWasmModule(std::move(obj->shared_native_module()),
7906 cstring.get(), length);
7907 #else
7908 UNREACHABLE();
7909 #endif // V8_ENABLE_WEBASSEMBLY
7910 }
7911
FromCompiledModule(Isolate * isolate,const CompiledWasmModule & compiled_module)7912 MaybeLocal<WasmModuleObject> WasmModuleObject::FromCompiledModule(
7913 Isolate* isolate, const CompiledWasmModule& compiled_module) {
7914 #if V8_ENABLE_WEBASSEMBLY
7915 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7916 i::Handle<i::WasmModuleObject> module_object =
7917 i::wasm::GetWasmEngine()->ImportNativeModule(
7918 i_isolate, compiled_module.native_module_,
7919 base::VectorOf(compiled_module.source_url()));
7920 return Local<WasmModuleObject>::Cast(
7921 Utils::ToLocal(i::Handle<i::JSObject>::cast(module_object)));
7922 #else
7923 UNREACHABLE();
7924 #endif // V8_ENABLE_WEBASSEMBLY
7925 }
7926
Compile(Isolate * isolate,MemorySpan<const uint8_t> wire_bytes)7927 MaybeLocal<WasmModuleObject> WasmModuleObject::Compile(
7928 Isolate* isolate, MemorySpan<const uint8_t> wire_bytes) {
7929 #if V8_ENABLE_WEBASSEMBLY
7930 const uint8_t* start = wire_bytes.data();
7931 size_t length = wire_bytes.size();
7932 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7933 if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
7934 return MaybeLocal<WasmModuleObject>();
7935 }
7936 i::MaybeHandle<i::JSObject> maybe_compiled;
7937 {
7938 i::wasm::ErrorThrower thrower(i_isolate, "WasmModuleObject::Compile()");
7939 auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
7940 maybe_compiled = i::wasm::GetWasmEngine()->SyncCompile(
7941 i_isolate, enabled_features, &thrower,
7942 i::wasm::ModuleWireBytes(start, start + length));
7943 }
7944 CHECK_EQ(maybe_compiled.is_null(), i_isolate->has_pending_exception());
7945 if (maybe_compiled.is_null()) {
7946 i_isolate->OptionalRescheduleException(false);
7947 return MaybeLocal<WasmModuleObject>();
7948 }
7949 return Local<WasmModuleObject>::Cast(
7950 Utils::ToLocal(maybe_compiled.ToHandleChecked()));
7951 #else
7952 Utils::ApiCheck(false, "WasmModuleObject::Compile",
7953 "WebAssembly support is not enabled.");
7954 UNREACHABLE();
7955 #endif // V8_ENABLE_WEBASSEMBLY
7956 }
7957
WasmModuleObjectBuilderStreaming(Isolate * isolate)7958 WasmModuleObjectBuilderStreaming::WasmModuleObjectBuilderStreaming(
7959 Isolate* isolate) {
7960 USE(isolate_);
7961 }
7962
GetPromise()7963 Local<Promise> WasmModuleObjectBuilderStreaming::GetPromise() { return {}; }
7964
OnBytesReceived(const uint8_t * bytes,size_t size)7965 void WasmModuleObjectBuilderStreaming::OnBytesReceived(const uint8_t* bytes,
7966 size_t size) {}
7967
Finish()7968 void WasmModuleObjectBuilderStreaming::Finish() {}
7969
Abort(MaybeLocal<Value> exception)7970 void WasmModuleObjectBuilderStreaming::Abort(MaybeLocal<Value> exception) {}
7971
Reallocate(void * data,size_t old_length,size_t new_length)7972 void* v8::ArrayBuffer::Allocator::Reallocate(void* data, size_t old_length,
7973 size_t new_length) {
7974 if (old_length == new_length) return data;
7975 uint8_t* new_data =
7976 reinterpret_cast<uint8_t*>(AllocateUninitialized(new_length));
7977 if (new_data == nullptr) return nullptr;
7978 size_t bytes_to_copy = std::min(old_length, new_length);
7979 memcpy(new_data, data, bytes_to_copy);
7980 if (new_length > bytes_to_copy) {
7981 memset(new_data + bytes_to_copy, 0, new_length - bytes_to_copy);
7982 }
7983 Free(data, old_length);
7984 return new_data;
7985 }
7986
7987 // static
NewDefaultAllocator()7988 v8::ArrayBuffer::Allocator* v8::ArrayBuffer::Allocator::NewDefaultAllocator() {
7989 return new ArrayBufferAllocator();
7990 }
7991
IsDetachable() const7992 bool v8::ArrayBuffer::IsDetachable() const {
7993 return Utils::OpenHandle(this)->is_detachable();
7994 }
7995
WasDetached() const7996 bool v8::ArrayBuffer::WasDetached() const {
7997 return Utils::OpenHandle(this)->was_detached();
7998 }
7999
8000 namespace {
ToInternal(std::shared_ptr<i::BackingStoreBase> backing_store)8001 std::shared_ptr<i::BackingStore> ToInternal(
8002 std::shared_ptr<i::BackingStoreBase> backing_store) {
8003 return std::static_pointer_cast<i::BackingStore>(backing_store);
8004 }
8005 } // namespace
8006
Detach()8007 void v8::ArrayBuffer::Detach() {
8008 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
8009 i::Isolate* isolate = obj->GetIsolate();
8010 Utils::ApiCheck(obj->is_detachable(), "v8::ArrayBuffer::Detach",
8011 "Only detachable ArrayBuffers can be detached");
8012 API_RCS_SCOPE(isolate, ArrayBuffer, Detach);
8013 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
8014 obj->Detach();
8015 }
8016
ByteLength() const8017 size_t v8::ArrayBuffer::ByteLength() const {
8018 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
8019 return obj->byte_length();
8020 }
8021
New(Isolate * isolate,size_t byte_length)8022 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) {
8023 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8024 API_RCS_SCOPE(i_isolate, ArrayBuffer, New);
8025 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8026 i::MaybeHandle<i::JSArrayBuffer> result =
8027 i_isolate->factory()->NewJSArrayBufferAndBackingStore(
8028 byte_length, i::InitializedFlag::kZeroInitialized);
8029
8030 i::Handle<i::JSArrayBuffer> array_buffer;
8031 if (!result.ToHandle(&array_buffer)) {
8032 // TODO(jbroman): It may be useful in the future to provide a MaybeLocal
8033 // version that throws an exception or otherwise does not crash.
8034 i::FatalProcessOutOfMemory(i_isolate, "v8::ArrayBuffer::New");
8035 }
8036
8037 return Utils::ToLocal(array_buffer);
8038 }
8039
New(Isolate * isolate,std::shared_ptr<BackingStore> backing_store)8040 Local<ArrayBuffer> v8::ArrayBuffer::New(
8041 Isolate* isolate, std::shared_ptr<BackingStore> backing_store) {
8042 CHECK_IMPLIES(backing_store->ByteLength() != 0,
8043 backing_store->Data() != nullptr);
8044 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8045 API_RCS_SCOPE(i_isolate, ArrayBuffer, New);
8046 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8047 std::shared_ptr<i::BackingStore> i_backing_store(
8048 ToInternal(std::move(backing_store)));
8049 Utils::ApiCheck(
8050 !i_backing_store->is_shared(), "v8_ArrayBuffer_New",
8051 "Cannot construct ArrayBuffer with a BackingStore of SharedArrayBuffer");
8052 i::Handle<i::JSArrayBuffer> obj =
8053 i_isolate->factory()->NewJSArrayBuffer(std::move(i_backing_store));
8054 return Utils::ToLocal(obj);
8055 }
8056
NewBackingStore(Isolate * isolate,size_t byte_length)8057 std::unique_ptr<v8::BackingStore> v8::ArrayBuffer::NewBackingStore(
8058 Isolate* isolate, size_t byte_length) {
8059 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8060 API_RCS_SCOPE(i_isolate, ArrayBuffer, NewBackingStore);
8061 CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength);
8062 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8063 std::unique_ptr<i::BackingStoreBase> backing_store =
8064 i::BackingStore::Allocate(i_isolate, byte_length,
8065 i::SharedFlag::kNotShared,
8066 i::InitializedFlag::kZeroInitialized);
8067 if (!backing_store) {
8068 i::FatalProcessOutOfMemory(i_isolate, "v8::ArrayBuffer::NewBackingStore");
8069 }
8070 return std::unique_ptr<v8::BackingStore>(
8071 static_cast<v8::BackingStore*>(backing_store.release()));
8072 }
8073
NewBackingStore(void * data,size_t byte_length,v8::BackingStore::DeleterCallback deleter,void * deleter_data)8074 std::unique_ptr<v8::BackingStore> v8::ArrayBuffer::NewBackingStore(
8075 void* data, size_t byte_length, v8::BackingStore::DeleterCallback deleter,
8076 void* deleter_data) {
8077 CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength);
8078 std::unique_ptr<i::BackingStoreBase> backing_store =
8079 i::BackingStore::WrapAllocation(data, byte_length, deleter, deleter_data,
8080 i::SharedFlag::kNotShared);
8081 return std::unique_ptr<v8::BackingStore>(
8082 static_cast<v8::BackingStore*>(backing_store.release()));
8083 }
8084
Buffer()8085 Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
8086 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
8087 i::Handle<i::JSArrayBuffer> buffer;
8088 if (obj->IsJSDataView()) {
8089 i::Handle<i::JSDataView> data_view(i::JSDataView::cast(*obj),
8090 obj->GetIsolate());
8091 DCHECK(data_view->buffer().IsJSArrayBuffer());
8092 buffer = i::handle(i::JSArrayBuffer::cast(data_view->buffer()),
8093 data_view->GetIsolate());
8094 } else {
8095 DCHECK(obj->IsJSTypedArray());
8096 buffer = i::JSTypedArray::cast(*obj).GetBuffer();
8097 }
8098 return Utils::ToLocal(buffer);
8099 }
8100
CopyContents(void * dest,size_t byte_length)8101 size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) {
8102 i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this);
8103 size_t bytes_to_copy = std::min(byte_length, self->byte_length());
8104 if (bytes_to_copy) {
8105 i::DisallowGarbageCollection no_gc;
8106 i::Isolate* isolate = self->GetIsolate();
8107 const char* source;
8108 if (self->IsJSTypedArray()) {
8109 i::Handle<i::JSTypedArray> array(i::JSTypedArray::cast(*self), isolate);
8110 source = reinterpret_cast<char*>(array->DataPtr());
8111 } else {
8112 DCHECK(self->IsJSDataView());
8113 i::Handle<i::JSDataView> data_view(i::JSDataView::cast(*self), isolate);
8114 source = reinterpret_cast<char*>(data_view->data_pointer());
8115 }
8116 memcpy(dest, source, bytes_to_copy);
8117 }
8118 return bytes_to_copy;
8119 }
8120
HasBuffer() const8121 bool v8::ArrayBufferView::HasBuffer() const {
8122 i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this);
8123 if (!self->IsJSTypedArray()) return true;
8124 auto typed_array = i::Handle<i::JSTypedArray>::cast(self);
8125 return !typed_array->is_on_heap();
8126 }
8127
ByteOffset()8128 size_t v8::ArrayBufferView::ByteOffset() {
8129 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
8130 return obj->WasDetached() ? 0 : obj->byte_offset();
8131 }
8132
ByteLength()8133 size_t v8::ArrayBufferView::ByteLength() {
8134 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
8135 return obj->WasDetached() ? 0 : obj->byte_length();
8136 }
8137
Length()8138 size_t v8::TypedArray::Length() {
8139 i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
8140 return obj->WasDetached() ? 0 : obj->length();
8141 }
8142
8143 static_assert(
8144 v8::TypedArray::kMaxLength == i::JSTypedArray::kMaxLength,
8145 "v8::TypedArray::kMaxLength must match i::JSTypedArray::kMaxLength");
8146
8147 #define TYPED_ARRAY_NEW(Type, type, TYPE, ctype) \
8148 Local<Type##Array> Type##Array::New(Local<ArrayBuffer> array_buffer, \
8149 size_t byte_offset, size_t length) { \
8150 i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate(); \
8151 API_RCS_SCOPE(isolate, Type##Array, New); \
8152 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \
8153 if (!Utils::ApiCheck(length <= kMaxLength, \
8154 "v8::" #Type \
8155 "Array::New(Local<ArrayBuffer>, size_t, size_t)", \
8156 "length exceeds max allowed value")) { \
8157 return Local<Type##Array>(); \
8158 } \
8159 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer); \
8160 i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray( \
8161 i::kExternal##Type##Array, buffer, byte_offset, length); \
8162 return Utils::ToLocal##Type##Array(obj); \
8163 } \
8164 Local<Type##Array> Type##Array::New( \
8165 Local<SharedArrayBuffer> shared_array_buffer, size_t byte_offset, \
8166 size_t length) { \
8167 CHECK(i::FLAG_harmony_sharedarraybuffer); \
8168 i::Isolate* isolate = \
8169 Utils::OpenHandle(*shared_array_buffer)->GetIsolate(); \
8170 API_RCS_SCOPE(isolate, Type##Array, New); \
8171 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \
8172 if (!Utils::ApiCheck( \
8173 length <= kMaxLength, \
8174 "v8::" #Type \
8175 "Array::New(Local<SharedArrayBuffer>, size_t, size_t)", \
8176 "length exceeds max allowed value")) { \
8177 return Local<Type##Array>(); \
8178 } \
8179 i::Handle<i::JSArrayBuffer> buffer = \
8180 Utils::OpenHandle(*shared_array_buffer); \
8181 i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray( \
8182 i::kExternal##Type##Array, buffer, byte_offset, length); \
8183 return Utils::ToLocal##Type##Array(obj); \
8184 }
8185
TYPED_ARRAYS(TYPED_ARRAY_NEW)8186 TYPED_ARRAYS(TYPED_ARRAY_NEW)
8187 #undef TYPED_ARRAY_NEW
8188
8189 Local<DataView> DataView::New(Local<ArrayBuffer> array_buffer,
8190 size_t byte_offset, size_t byte_length) {
8191 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
8192 i::Isolate* isolate = buffer->GetIsolate();
8193 API_RCS_SCOPE(isolate, DataView, New);
8194 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
8195 i::Handle<i::JSDataView> obj =
8196 isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length);
8197 return Utils::ToLocal(obj);
8198 }
8199
New(Local<SharedArrayBuffer> shared_array_buffer,size_t byte_offset,size_t byte_length)8200 Local<DataView> DataView::New(Local<SharedArrayBuffer> shared_array_buffer,
8201 size_t byte_offset, size_t byte_length) {
8202 CHECK(i::FLAG_harmony_sharedarraybuffer);
8203 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*shared_array_buffer);
8204 i::Isolate* isolate = buffer->GetIsolate();
8205 API_RCS_SCOPE(isolate, DataView, New);
8206 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
8207 i::Handle<i::JSDataView> obj =
8208 isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length);
8209 return Utils::ToLocal(obj);
8210 }
8211
ByteLength() const8212 size_t v8::SharedArrayBuffer::ByteLength() const {
8213 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
8214 return obj->byte_length();
8215 }
8216
New(Isolate * isolate,size_t byte_length)8217 Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(Isolate* isolate,
8218 size_t byte_length) {
8219 CHECK(i::FLAG_harmony_sharedarraybuffer);
8220 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8221 API_RCS_SCOPE(i_isolate, SharedArrayBuffer, New);
8222 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8223
8224 std::unique_ptr<i::BackingStore> backing_store =
8225 i::BackingStore::Allocate(i_isolate, byte_length, i::SharedFlag::kShared,
8226 i::InitializedFlag::kZeroInitialized);
8227
8228 if (!backing_store) {
8229 // TODO(jbroman): It may be useful in the future to provide a MaybeLocal
8230 // version that throws an exception or otherwise does not crash.
8231 i::FatalProcessOutOfMemory(i_isolate, "v8::SharedArrayBuffer::New");
8232 }
8233
8234 i::Handle<i::JSArrayBuffer> obj =
8235 i_isolate->factory()->NewJSSharedArrayBuffer(std::move(backing_store));
8236 return Utils::ToLocalShared(obj);
8237 }
8238
New(Isolate * isolate,std::shared_ptr<BackingStore> backing_store)8239 Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(
8240 Isolate* isolate, std::shared_ptr<BackingStore> backing_store) {
8241 CHECK(i::FLAG_harmony_sharedarraybuffer);
8242 CHECK_IMPLIES(backing_store->ByteLength() != 0,
8243 backing_store->Data() != nullptr);
8244 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8245 API_RCS_SCOPE(i_isolate, SharedArrayBuffer, New);
8246 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8247 std::shared_ptr<i::BackingStore> i_backing_store(ToInternal(backing_store));
8248 Utils::ApiCheck(
8249 i_backing_store->is_shared(), "v8_SharedArrayBuffer_New",
8250 "Cannot construct SharedArrayBuffer with BackingStore of ArrayBuffer");
8251 i::Handle<i::JSArrayBuffer> obj =
8252 i_isolate->factory()->NewJSSharedArrayBuffer(std::move(i_backing_store));
8253 return Utils::ToLocalShared(obj);
8254 }
8255
NewBackingStore(Isolate * isolate,size_t byte_length)8256 std::unique_ptr<v8::BackingStore> v8::SharedArrayBuffer::NewBackingStore(
8257 Isolate* isolate, size_t byte_length) {
8258 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8259 API_RCS_SCOPE(i_isolate, SharedArrayBuffer, NewBackingStore);
8260 CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength);
8261 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8262 std::unique_ptr<i::BackingStoreBase> backing_store =
8263 i::BackingStore::Allocate(i_isolate, byte_length, i::SharedFlag::kShared,
8264 i::InitializedFlag::kZeroInitialized);
8265 if (!backing_store) {
8266 i::FatalProcessOutOfMemory(i_isolate,
8267 "v8::SharedArrayBuffer::NewBackingStore");
8268 }
8269 return std::unique_ptr<v8::BackingStore>(
8270 static_cast<v8::BackingStore*>(backing_store.release()));
8271 }
8272
NewBackingStore(void * data,size_t byte_length,v8::BackingStore::DeleterCallback deleter,void * deleter_data)8273 std::unique_ptr<v8::BackingStore> v8::SharedArrayBuffer::NewBackingStore(
8274 void* data, size_t byte_length, v8::BackingStore::DeleterCallback deleter,
8275 void* deleter_data) {
8276 CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength);
8277 std::unique_ptr<i::BackingStoreBase> backing_store =
8278 i::BackingStore::WrapAllocation(data, byte_length, deleter, deleter_data,
8279 i::SharedFlag::kShared);
8280 return std::unique_ptr<v8::BackingStore>(
8281 static_cast<v8::BackingStore*>(backing_store.release()));
8282 }
8283
New(Isolate * isolate,Local<String> name)8284 Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
8285 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8286 API_RCS_SCOPE(i_isolate, Symbol, New);
8287 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8288 i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol();
8289 if (!name.IsEmpty()) result->set_description(*Utils::OpenHandle(*name));
8290 return Utils::ToLocal(result);
8291 }
8292
For(Isolate * isolate,Local<String> name)8293 Local<Symbol> v8::Symbol::For(Isolate* isolate, Local<String> name) {
8294 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8295 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
8296 return Utils::ToLocal(
8297 i_isolate->SymbolFor(i::RootIndex::kPublicSymbolTable, i_name, false));
8298 }
8299
ForApi(Isolate * isolate,Local<String> name)8300 Local<Symbol> v8::Symbol::ForApi(Isolate* isolate, Local<String> name) {
8301 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8302 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
8303 return Utils::ToLocal(
8304 i_isolate->SymbolFor(i::RootIndex::kApiSymbolTable, i_name, false));
8305 }
8306
8307 #define WELL_KNOWN_SYMBOLS(V) \
8308 V(AsyncIterator, async_iterator) \
8309 V(HasInstance, has_instance) \
8310 V(IsConcatSpreadable, is_concat_spreadable) \
8311 V(Iterator, iterator) \
8312 V(Match, match) \
8313 V(Replace, replace) \
8314 V(Search, search) \
8315 V(Split, split) \
8316 V(ToPrimitive, to_primitive) \
8317 V(ToStringTag, to_string_tag) \
8318 V(Unscopables, unscopables)
8319
8320 #define SYMBOL_GETTER(Name, name) \
8321 Local<Symbol> v8::Symbol::Get##Name(Isolate* isolate) { \
8322 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); \
8323 return Utils::ToLocal(i_isolate->factory()->name##_symbol()); \
8324 }
8325
WELL_KNOWN_SYMBOLS(SYMBOL_GETTER)8326 WELL_KNOWN_SYMBOLS(SYMBOL_GETTER)
8327
8328 #undef SYMBOL_GETTER
8329 #undef WELL_KNOWN_SYMBOLS
8330
8331 Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) {
8332 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8333 API_RCS_SCOPE(i_isolate, Private, New);
8334 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8335 i::Handle<i::Symbol> symbol = i_isolate->factory()->NewPrivateSymbol();
8336 if (!name.IsEmpty()) symbol->set_description(*Utils::OpenHandle(*name));
8337 Local<Symbol> result = Utils::ToLocal(symbol);
8338 return v8::Local<Private>(reinterpret_cast<Private*>(*result));
8339 }
8340
ForApi(Isolate * isolate,Local<String> name)8341 Local<Private> v8::Private::ForApi(Isolate* isolate, Local<String> name) {
8342 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8343 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
8344 Local<Symbol> result = Utils::ToLocal(
8345 i_isolate->SymbolFor(i::RootIndex::kApiPrivateSymbolTable, i_name, true));
8346 return v8::Local<Private>(reinterpret_cast<Private*>(*result));
8347 }
8348
New(Isolate * isolate,double value)8349 Local<Number> v8::Number::New(Isolate* isolate, double value) {
8350 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8351 if (std::isnan(value)) {
8352 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
8353 value = std::numeric_limits<double>::quiet_NaN();
8354 }
8355 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
8356 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
8357 return Utils::NumberToLocal(result);
8358 }
8359
New(Isolate * isolate,int32_t value)8360 Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) {
8361 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8362 if (i::Smi::IsValid(value)) {
8363 return Utils::IntegerToLocal(
8364 i::Handle<i::Object>(i::Smi::FromInt(value), internal_isolate));
8365 }
8366 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
8367 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
8368 return Utils::IntegerToLocal(result);
8369 }
8370
NewFromUnsigned(Isolate * isolate,uint32_t value)8371 Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) {
8372 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8373 bool fits_into_int32_t = (value & (1 << 31)) == 0;
8374 if (fits_into_int32_t) {
8375 return Integer::New(isolate, static_cast<int32_t>(value));
8376 }
8377 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
8378 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
8379 return Utils::IntegerToLocal(result);
8380 }
8381
New(Isolate * isolate,int64_t value)8382 Local<BigInt> v8::BigInt::New(Isolate* isolate, int64_t value) {
8383 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8384 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
8385 i::Handle<i::BigInt> result = i::BigInt::FromInt64(internal_isolate, value);
8386 return Utils::ToLocal(result);
8387 }
8388
NewFromUnsigned(Isolate * isolate,uint64_t value)8389 Local<BigInt> v8::BigInt::NewFromUnsigned(Isolate* isolate, uint64_t value) {
8390 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8391 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
8392 i::Handle<i::BigInt> result = i::BigInt::FromUint64(internal_isolate, value);
8393 return Utils::ToLocal(result);
8394 }
8395
NewFromWords(Local<Context> context,int sign_bit,int word_count,const uint64_t * words)8396 MaybeLocal<BigInt> v8::BigInt::NewFromWords(Local<Context> context,
8397 int sign_bit, int word_count,
8398 const uint64_t* words) {
8399 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
8400 ENTER_V8_NO_SCRIPT(isolate, context, BigInt, NewFromWords,
8401 MaybeLocal<BigInt>(), InternalEscapableScope);
8402 i::MaybeHandle<i::BigInt> result =
8403 i::BigInt::FromWords64(isolate, sign_bit, word_count, words);
8404 has_pending_exception = result.is_null();
8405 RETURN_ON_FAILED_EXECUTION(BigInt);
8406 RETURN_ESCAPED(Utils::ToLocal(result.ToHandleChecked()));
8407 }
8408
Uint64Value(bool * lossless) const8409 uint64_t v8::BigInt::Uint64Value(bool* lossless) const {
8410 i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8411 return handle->AsUint64(lossless);
8412 }
8413
Int64Value(bool * lossless) const8414 int64_t v8::BigInt::Int64Value(bool* lossless) const {
8415 i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8416 return handle->AsInt64(lossless);
8417 }
8418
WordCount() const8419 int BigInt::WordCount() const {
8420 i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8421 return handle->Words64Count();
8422 }
8423
ToWordsArray(int * sign_bit,int * word_count,uint64_t * words) const8424 void BigInt::ToWordsArray(int* sign_bit, int* word_count,
8425 uint64_t* words) const {
8426 i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8427 return handle->ToWordsArray64(sign_bit, word_count, words);
8428 }
8429
ReportExternalAllocationLimitReached()8430 void Isolate::ReportExternalAllocationLimitReached() {
8431 i::Heap* heap = reinterpret_cast<i::Isolate*>(this)->heap();
8432 if (heap->gc_state() != i::Heap::NOT_IN_GC) return;
8433 heap->ReportExternalMemoryPressure();
8434 }
8435
GetHeapProfiler()8436 HeapProfiler* Isolate::GetHeapProfiler() {
8437 i::HeapProfiler* heap_profiler =
8438 reinterpret_cast<i::Isolate*>(this)->heap_profiler();
8439 return reinterpret_cast<HeapProfiler*>(heap_profiler);
8440 }
8441
SetIdle(bool is_idle)8442 void Isolate::SetIdle(bool is_idle) {
8443 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8444 isolate->SetIdle(is_idle);
8445 }
8446
GetArrayBufferAllocator()8447 ArrayBuffer::Allocator* Isolate::GetArrayBufferAllocator() {
8448 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8449 return isolate->array_buffer_allocator();
8450 }
8451
InContext()8452 bool Isolate::InContext() {
8453 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8454 return !isolate->context().is_null();
8455 }
8456
ClearKeptObjects()8457 void Isolate::ClearKeptObjects() {
8458 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8459 isolate->ClearKeptObjects();
8460 }
8461
GetCurrentContext()8462 v8::Local<v8::Context> Isolate::GetCurrentContext() {
8463 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8464 i::Context context = isolate->context();
8465 if (context.is_null()) return Local<Context>();
8466 i::Context native_context = context.native_context();
8467 if (native_context.is_null()) return Local<Context>();
8468 return Utils::ToLocal(i::Handle<i::Context>(native_context, isolate));
8469 }
8470
GetEnteredOrMicrotaskContext()8471 v8::Local<v8::Context> Isolate::GetEnteredOrMicrotaskContext() {
8472 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8473 i::Handle<i::Object> last =
8474 isolate->handle_scope_implementer()->LastEnteredOrMicrotaskContext();
8475 if (last.is_null()) return Local<Context>();
8476 DCHECK(last->IsNativeContext());
8477 return Utils::ToLocal(i::Handle<i::Context>::cast(last));
8478 }
8479
GetIncumbentContext()8480 v8::Local<v8::Context> Isolate::GetIncumbentContext() {
8481 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8482 i::Handle<i::Context> context = isolate->GetIncumbentContext();
8483 return Utils::ToLocal(context);
8484 }
8485
ThrowError(v8::Local<v8::String> message)8486 v8::Local<Value> Isolate::ThrowError(v8::Local<v8::String> message) {
8487 return ThrowException(v8::Exception::Error(message));
8488 }
8489
ThrowException(v8::Local<v8::Value> value)8490 v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
8491 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8492 ENTER_V8_DO_NOT_USE(isolate);
8493 // If we're passed an empty handle, we throw an undefined exception
8494 // to deal more gracefully with out of memory situations.
8495 if (value.IsEmpty()) {
8496 isolate->ScheduleThrow(i::ReadOnlyRoots(isolate).undefined_value());
8497 } else {
8498 isolate->ScheduleThrow(*Utils::OpenHandle(*value));
8499 }
8500 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
8501 }
8502
AddGCPrologueCallback(GCCallbackWithData callback,void * data,GCType gc_type)8503 void Isolate::AddGCPrologueCallback(GCCallbackWithData callback, void* data,
8504 GCType gc_type) {
8505 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8506 isolate->heap()->AddGCPrologueCallback(callback, gc_type, data);
8507 }
8508
RemoveGCPrologueCallback(GCCallbackWithData callback,void * data)8509 void Isolate::RemoveGCPrologueCallback(GCCallbackWithData callback,
8510 void* data) {
8511 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8512 isolate->heap()->RemoveGCPrologueCallback(callback, data);
8513 }
8514
AddGCEpilogueCallback(GCCallbackWithData callback,void * data,GCType gc_type)8515 void Isolate::AddGCEpilogueCallback(GCCallbackWithData callback, void* data,
8516 GCType gc_type) {
8517 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8518 isolate->heap()->AddGCEpilogueCallback(callback, gc_type, data);
8519 }
8520
RemoveGCEpilogueCallback(GCCallbackWithData callback,void * data)8521 void Isolate::RemoveGCEpilogueCallback(GCCallbackWithData callback,
8522 void* data) {
8523 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8524 isolate->heap()->RemoveGCEpilogueCallback(callback, data);
8525 }
8526
CallGCCallbackWithoutData(Isolate * isolate,GCType type,GCCallbackFlags flags,void * data)8527 static void CallGCCallbackWithoutData(Isolate* isolate, GCType type,
8528 GCCallbackFlags flags, void* data) {
8529 reinterpret_cast<Isolate::GCCallback>(data)(isolate, type, flags);
8530 }
8531
AddGCPrologueCallback(GCCallback callback,GCType gc_type)8532 void Isolate::AddGCPrologueCallback(GCCallback callback, GCType gc_type) {
8533 void* data = reinterpret_cast<void*>(callback);
8534 AddGCPrologueCallback(CallGCCallbackWithoutData, data, gc_type);
8535 }
8536
RemoveGCPrologueCallback(GCCallback callback)8537 void Isolate::RemoveGCPrologueCallback(GCCallback callback) {
8538 void* data = reinterpret_cast<void*>(callback);
8539 RemoveGCPrologueCallback(CallGCCallbackWithoutData, data);
8540 }
8541
AddGCEpilogueCallback(GCCallback callback,GCType gc_type)8542 void Isolate::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) {
8543 void* data = reinterpret_cast<void*>(callback);
8544 AddGCEpilogueCallback(CallGCCallbackWithoutData, data, gc_type);
8545 }
8546
RemoveGCEpilogueCallback(GCCallback callback)8547 void Isolate::RemoveGCEpilogueCallback(GCCallback callback) {
8548 void* data = reinterpret_cast<void*>(callback);
8549 RemoveGCEpilogueCallback(CallGCCallbackWithoutData, data);
8550 }
8551
SetEmbedderHeapTracer(EmbedderHeapTracer * tracer)8552 void Isolate::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) {
8553 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8554 CHECK_NULL(isolate->heap()->cpp_heap());
8555 isolate->heap()->SetEmbedderHeapTracer(tracer);
8556 }
8557
GetEmbedderHeapTracer()8558 EmbedderHeapTracer* Isolate::GetEmbedderHeapTracer() {
8559 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8560 return isolate->heap()->GetEmbedderHeapTracer();
8561 }
8562
SetEmbedderRootsHandler(EmbedderRootsHandler * handler)8563 void Isolate::SetEmbedderRootsHandler(EmbedderRootsHandler* handler) {
8564 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8565 isolate->heap()->SetEmbedderRootsHandler(handler);
8566 }
8567
AttachCppHeap(CppHeap * cpp_heap)8568 void Isolate::AttachCppHeap(CppHeap* cpp_heap) {
8569 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8570 CHECK_NULL(GetEmbedderHeapTracer());
8571 isolate->heap()->AttachCppHeap(cpp_heap);
8572 }
8573
DetachCppHeap()8574 void Isolate::DetachCppHeap() {
8575 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8576 isolate->heap()->DetachCppHeap();
8577 }
8578
GetCppHeap() const8579 CppHeap* Isolate::GetCppHeap() const {
8580 const i::Isolate* isolate = reinterpret_cast<const i::Isolate*>(this);
8581 return isolate->heap()->cpp_heap();
8582 }
8583
SetGetExternallyAllocatedMemoryInBytesCallback(GetExternallyAllocatedMemoryInBytesCallback callback)8584 void Isolate::SetGetExternallyAllocatedMemoryInBytesCallback(
8585 GetExternallyAllocatedMemoryInBytesCallback callback) {
8586 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8587 isolate->heap()->SetGetExternallyAllocatedMemoryInBytesCallback(callback);
8588 }
8589
TerminateExecution()8590 void Isolate::TerminateExecution() {
8591 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8592 isolate->stack_guard()->RequestTerminateExecution();
8593 }
8594
IsExecutionTerminating()8595 bool Isolate::IsExecutionTerminating() {
8596 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8597 return IsExecutionTerminatingCheck(isolate);
8598 }
8599
CancelTerminateExecution()8600 void Isolate::CancelTerminateExecution() {
8601 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8602 isolate->stack_guard()->ClearTerminateExecution();
8603 isolate->CancelTerminateExecution();
8604 }
8605
RequestInterrupt(InterruptCallback callback,void * data)8606 void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
8607 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8608 isolate->RequestInterrupt(callback, data);
8609 }
8610
HasPendingBackgroundTasks()8611 bool Isolate::HasPendingBackgroundTasks() {
8612 #if V8_ENABLE_WEBASSEMBLY
8613 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8614 return i::wasm::GetWasmEngine()->HasRunningCompileJob(isolate);
8615 #else
8616 return false;
8617 #endif // V8_ENABLE_WEBASSEMBLY
8618 }
8619
RequestGarbageCollectionForTesting(GarbageCollectionType type)8620 void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) {
8621 Utils::ApiCheck(i::FLAG_expose_gc,
8622 "v8::Isolate::RequestGarbageCollectionForTesting",
8623 "Must use --expose-gc");
8624 if (type == kMinorGarbageCollection) {
8625 reinterpret_cast<i::Isolate*>(this)->heap()->CollectGarbage(
8626 i::NEW_SPACE, i::GarbageCollectionReason::kTesting,
8627 kGCCallbackFlagForced);
8628 } else {
8629 DCHECK_EQ(kFullGarbageCollection, type);
8630 reinterpret_cast<i::Isolate*>(this)->heap()->PreciseCollectAllGarbage(
8631 i::Heap::kNoGCFlags, i::GarbageCollectionReason::kTesting,
8632 kGCCallbackFlagForced);
8633 }
8634 }
8635
RequestGarbageCollectionForTesting(GarbageCollectionType type,EmbedderHeapTracer::EmbedderStackState stack_state)8636 void Isolate::RequestGarbageCollectionForTesting(
8637 GarbageCollectionType type,
8638 EmbedderHeapTracer::EmbedderStackState stack_state) {
8639 base::Optional<i::EmbedderStackStateScope> stack_scope;
8640 if (type == kFullGarbageCollection) {
8641 stack_scope.emplace(reinterpret_cast<i::Isolate*>(this)->heap(),
8642 i::EmbedderStackStateScope::kExplicitInvocation,
8643 stack_state);
8644 }
8645 RequestGarbageCollectionForTesting(type);
8646 }
8647
GetCurrent()8648 Isolate* Isolate::GetCurrent() {
8649 i::Isolate* isolate = i::Isolate::Current();
8650 return reinterpret_cast<Isolate*>(isolate);
8651 }
8652
TryGetCurrent()8653 Isolate* Isolate::TryGetCurrent() {
8654 i::Isolate* isolate = i::Isolate::TryGetCurrent();
8655 return reinterpret_cast<Isolate*>(isolate);
8656 }
8657
IsCurrent() const8658 bool Isolate::IsCurrent() const {
8659 return reinterpret_cast<const i::Isolate*>(this)->IsCurrent();
8660 }
8661
8662 // static
Allocate()8663 Isolate* Isolate::Allocate() {
8664 return reinterpret_cast<Isolate*>(i::Isolate::New());
8665 }
8666
8667 Isolate::CreateParams::CreateParams() = default;
8668
8669 Isolate::CreateParams::~CreateParams() = default;
8670
8671 // static
8672 // This is separate so that tests can provide a different |isolate|.
Initialize(Isolate * isolate,const v8::Isolate::CreateParams & params)8673 void Isolate::Initialize(Isolate* isolate,
8674 const v8::Isolate::CreateParams& params) {
8675 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8676 TRACE_EVENT_CALL_STATS_SCOPED(i_isolate, "v8", "V8.IsolateInitialize");
8677 if (auto allocator = params.array_buffer_allocator_shared) {
8678 CHECK(params.array_buffer_allocator == nullptr ||
8679 params.array_buffer_allocator == allocator.get());
8680 i_isolate->set_array_buffer_allocator(allocator.get());
8681 i_isolate->set_array_buffer_allocator_shared(std::move(allocator));
8682 } else {
8683 CHECK_NOT_NULL(params.array_buffer_allocator);
8684 i_isolate->set_array_buffer_allocator(params.array_buffer_allocator);
8685 }
8686 if (params.snapshot_blob != nullptr) {
8687 i_isolate->set_snapshot_blob(params.snapshot_blob);
8688 } else {
8689 i_isolate->set_snapshot_blob(i::Snapshot::DefaultSnapshotBlob());
8690 }
8691
8692 if (params.fatal_error_callback) {
8693 isolate->SetFatalErrorHandler(params.fatal_error_callback);
8694 }
8695
8696 if (params.oom_error_callback) {
8697 isolate->SetOOMErrorHandler(params.oom_error_callback);
8698 }
8699
8700 if (params.counter_lookup_callback) {
8701 isolate->SetCounterFunction(params.counter_lookup_callback);
8702 }
8703
8704 if (params.create_histogram_callback) {
8705 isolate->SetCreateHistogramFunction(params.create_histogram_callback);
8706 }
8707
8708 if (params.add_histogram_sample_callback) {
8709 isolate->SetAddHistogramSampleFunction(
8710 params.add_histogram_sample_callback);
8711 }
8712
8713 i_isolate->set_api_external_references(params.external_references);
8714 i_isolate->set_allow_atomics_wait(params.allow_atomics_wait);
8715
8716 i_isolate->heap()->ConfigureHeap(params.constraints);
8717 if (params.constraints.stack_limit() != nullptr) {
8718 uintptr_t limit =
8719 reinterpret_cast<uintptr_t>(params.constraints.stack_limit());
8720 i_isolate->stack_guard()->SetStackLimit(limit);
8721 }
8722
8723 if (params.experimental_attach_to_shared_isolate != nullptr) {
8724 i_isolate->set_shared_isolate(reinterpret_cast<i::Isolate*>(
8725 params.experimental_attach_to_shared_isolate));
8726 }
8727
8728 // TODO(v8:2487): Once we got rid of Isolate::Current(), we can remove this.
8729 Isolate::Scope isolate_scope(isolate);
8730 if (i_isolate->snapshot_blob() == nullptr) {
8731 FATAL(
8732 "V8 snapshot blob was not set during initialization. This can mean "
8733 "that the snapshot blob file is corrupted or missing.");
8734 }
8735 if (!i::Snapshot::Initialize(i_isolate)) {
8736 // If snapshot data was provided and we failed to deserialize it must
8737 // have been corrupted.
8738 FATAL(
8739 "Failed to deserialize the V8 snapshot blob. This can mean that the "
8740 "snapshot blob file is corrupted or missing.");
8741 }
8742
8743 {
8744 // Set up code event handlers. Needs to be after i::Snapshot::Initialize
8745 // because that is where we add the isolate to WasmEngine.
8746 auto code_event_handler = params.code_event_handler;
8747 if (code_event_handler) {
8748 isolate->SetJitCodeEventHandler(kJitCodeEventEnumExisting,
8749 code_event_handler);
8750 }
8751 }
8752
8753 i_isolate->set_only_terminate_in_safe_scope(
8754 params.only_terminate_in_safe_scope);
8755 i_isolate->set_embedder_wrapper_type_index(
8756 params.embedder_wrapper_type_index);
8757 i_isolate->set_embedder_wrapper_object_index(
8758 params.embedder_wrapper_object_index);
8759
8760 if (!i::V8::GetCurrentPlatform()
8761 ->GetForegroundTaskRunner(isolate)
8762 ->NonNestableTasksEnabled()) {
8763 FATAL(
8764 "The current platform's foreground task runner does not have "
8765 "non-nestable tasks enabled. The embedder must provide one.");
8766 }
8767 }
8768
New(const Isolate::CreateParams & params)8769 Isolate* Isolate::New(const Isolate::CreateParams& params) {
8770 Isolate* isolate = Allocate();
8771 Initialize(isolate, params);
8772 return isolate;
8773 }
8774
Dispose()8775 void Isolate::Dispose() {
8776 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8777 if (!Utils::ApiCheck(!isolate->IsInUse(), "v8::Isolate::Dispose()",
8778 "Disposing the isolate that is entered by a thread.")) {
8779 return;
8780 }
8781 i::Isolate::Delete(isolate);
8782 }
8783
DumpAndResetStats()8784 void Isolate::DumpAndResetStats() {
8785 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8786 isolate->DumpAndResetStats();
8787 }
8788
DiscardThreadSpecificMetadata()8789 void Isolate::DiscardThreadSpecificMetadata() {
8790 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8791 isolate->DiscardPerThreadDataForThisThread();
8792 }
8793
Enter()8794 void Isolate::Enter() {
8795 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8796 isolate->Enter();
8797 }
8798
Exit()8799 void Isolate::Exit() {
8800 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8801 isolate->Exit();
8802 }
8803
SetAbortOnUncaughtExceptionCallback(AbortOnUncaughtExceptionCallback callback)8804 void Isolate::SetAbortOnUncaughtExceptionCallback(
8805 AbortOnUncaughtExceptionCallback callback) {
8806 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8807 isolate->SetAbortOnUncaughtExceptionCallback(callback);
8808 }
8809
SetHostImportModuleDynamicallyCallback(HostImportModuleDynamicallyWithImportAssertionsCallback callback)8810 void Isolate::SetHostImportModuleDynamicallyCallback(
8811 HostImportModuleDynamicallyWithImportAssertionsCallback callback) {
8812 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8813 isolate->SetHostImportModuleDynamicallyCallback(callback);
8814 }
8815
SetHostImportModuleDynamicallyCallback(HostImportModuleDynamicallyCallback callback)8816 void Isolate::SetHostImportModuleDynamicallyCallback(
8817 HostImportModuleDynamicallyCallback callback) {
8818 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8819 isolate->SetHostImportModuleDynamicallyCallback(callback);
8820 }
8821
SetHostInitializeImportMetaObjectCallback(HostInitializeImportMetaObjectCallback callback)8822 void Isolate::SetHostInitializeImportMetaObjectCallback(
8823 HostInitializeImportMetaObjectCallback callback) {
8824 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8825 isolate->SetHostInitializeImportMetaObjectCallback(callback);
8826 }
8827
SetHostCreateShadowRealmContextCallback(HostCreateShadowRealmContextCallback callback)8828 void Isolate::SetHostCreateShadowRealmContextCallback(
8829 HostCreateShadowRealmContextCallback callback) {
8830 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8831 isolate->SetHostCreateShadowRealmContextCallback(callback);
8832 }
8833
SetPrepareStackTraceCallback(PrepareStackTraceCallback callback)8834 void Isolate::SetPrepareStackTraceCallback(PrepareStackTraceCallback callback) {
8835 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8836 isolate->SetPrepareStackTraceCallback(callback);
8837 }
8838
DisallowJavascriptExecutionScope(Isolate * isolate,Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)8839 Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope(
8840 Isolate* isolate,
8841 Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)
8842 : on_failure_(on_failure), isolate_(isolate) {
8843 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8844 switch (on_failure_) {
8845 case CRASH_ON_FAILURE:
8846 i::DisallowJavascriptExecution::Open(i_isolate,
8847 &was_execution_allowed_assert_);
8848 break;
8849 case THROW_ON_FAILURE:
8850 i::ThrowOnJavascriptExecution::Open(i_isolate,
8851 &was_execution_allowed_throws_);
8852 break;
8853 case DUMP_ON_FAILURE:
8854 i::DumpOnJavascriptExecution::Open(i_isolate,
8855 &was_execution_allowed_dump_);
8856 break;
8857 default:
8858 UNREACHABLE();
8859 }
8860 }
8861
~DisallowJavascriptExecutionScope()8862 Isolate::DisallowJavascriptExecutionScope::~DisallowJavascriptExecutionScope() {
8863 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
8864 switch (on_failure_) {
8865 case CRASH_ON_FAILURE:
8866 i::DisallowJavascriptExecution::Close(i_isolate,
8867 was_execution_allowed_assert_);
8868 break;
8869 case THROW_ON_FAILURE:
8870 i::ThrowOnJavascriptExecution::Close(i_isolate,
8871 was_execution_allowed_throws_);
8872 break;
8873 case DUMP_ON_FAILURE:
8874 i::DumpOnJavascriptExecution::Close(i_isolate,
8875 was_execution_allowed_dump_);
8876 break;
8877 default:
8878 UNREACHABLE();
8879 }
8880 }
8881
AllowJavascriptExecutionScope(Isolate * isolate)8882 Isolate::AllowJavascriptExecutionScope::AllowJavascriptExecutionScope(
8883 Isolate* isolate)
8884 : isolate_(isolate) {
8885 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8886 i::AllowJavascriptExecution::Open(i_isolate, &was_execution_allowed_assert_);
8887 i::NoThrowOnJavascriptExecution::Open(i_isolate,
8888 &was_execution_allowed_throws_);
8889 i::NoDumpOnJavascriptExecution::Open(i_isolate, &was_execution_allowed_dump_);
8890 }
8891
~AllowJavascriptExecutionScope()8892 Isolate::AllowJavascriptExecutionScope::~AllowJavascriptExecutionScope() {
8893 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
8894 i::AllowJavascriptExecution::Close(i_isolate, was_execution_allowed_assert_);
8895 i::NoThrowOnJavascriptExecution::Close(i_isolate,
8896 was_execution_allowed_throws_);
8897 i::NoDumpOnJavascriptExecution::Close(i_isolate, was_execution_allowed_dump_);
8898 }
8899
SuppressMicrotaskExecutionScope(Isolate * isolate,MicrotaskQueue * microtask_queue)8900 Isolate::SuppressMicrotaskExecutionScope::SuppressMicrotaskExecutionScope(
8901 Isolate* isolate, MicrotaskQueue* microtask_queue)
8902 : isolate_(reinterpret_cast<i::Isolate*>(isolate)),
8903 microtask_queue_(microtask_queue
8904 ? static_cast<i::MicrotaskQueue*>(microtask_queue)
8905 : isolate_->default_microtask_queue()) {
8906 isolate_->thread_local_top()->IncrementCallDepth(this);
8907 microtask_queue_->IncrementMicrotasksSuppressions();
8908 }
8909
~SuppressMicrotaskExecutionScope()8910 Isolate::SuppressMicrotaskExecutionScope::~SuppressMicrotaskExecutionScope() {
8911 microtask_queue_->DecrementMicrotasksSuppressions();
8912 isolate_->thread_local_top()->DecrementCallDepth(this);
8913 }
8914
SafeForTerminationScope(v8::Isolate * isolate)8915 Isolate::SafeForTerminationScope::SafeForTerminationScope(v8::Isolate* isolate)
8916 : isolate_(reinterpret_cast<i::Isolate*>(isolate)),
8917 prev_value_(isolate_->next_v8_call_is_safe_for_termination()) {
8918 isolate_->set_next_v8_call_is_safe_for_termination(true);
8919 }
8920
~SafeForTerminationScope()8921 Isolate::SafeForTerminationScope::~SafeForTerminationScope() {
8922 isolate_->set_next_v8_call_is_safe_for_termination(prev_value_);
8923 }
8924
GetDataFromSnapshotOnce(size_t index)8925 i::Address* Isolate::GetDataFromSnapshotOnce(size_t index) {
8926 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
8927 i::FixedArray list = i_isolate->heap()->serialized_objects();
8928 return GetSerializedDataFromFixedArray(i_isolate, list, index);
8929 }
8930
GetHeapStatistics(HeapStatistics * heap_statistics)8931 void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) {
8932 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8933 i::Heap* heap = isolate->heap();
8934
8935 // The order of acquiring memory statistics is important here. We query in
8936 // this order because of concurrent allocation: 1) used memory 2) comitted
8937 // physical memory 3) committed memory. Therefore the condition used <=
8938 // committed physical <= committed should hold.
8939 heap_statistics->used_global_handles_size_ = heap->UsedGlobalHandlesSize();
8940 heap_statistics->total_global_handles_size_ = heap->TotalGlobalHandlesSize();
8941 DCHECK_LE(heap_statistics->used_global_handles_size_,
8942 heap_statistics->total_global_handles_size_);
8943
8944 heap_statistics->used_heap_size_ = heap->SizeOfObjects();
8945 heap_statistics->total_physical_size_ = heap->CommittedPhysicalMemory();
8946 heap_statistics->total_heap_size_ = heap->CommittedMemory();
8947
8948 heap_statistics->total_available_size_ = heap->Available();
8949
8950 if (!i::ReadOnlyHeap::IsReadOnlySpaceShared()) {
8951 i::ReadOnlySpace* ro_space = heap->read_only_space();
8952 heap_statistics->used_heap_size_ += ro_space->Size();
8953 heap_statistics->total_physical_size_ +=
8954 ro_space->CommittedPhysicalMemory();
8955 heap_statistics->total_heap_size_ += ro_space->CommittedMemory();
8956 }
8957
8958 // TODO(dinfuehr): Right now used <= committed physical does not hold. Fix
8959 // this and add DCHECK.
8960 DCHECK_LE(heap_statistics->used_heap_size_,
8961 heap_statistics->total_heap_size_);
8962
8963 heap_statistics->total_heap_size_executable_ =
8964 heap->CommittedMemoryExecutable();
8965 heap_statistics->heap_size_limit_ = heap->MaxReserved();
8966 // TODO(7424): There is no public API for the {WasmEngine} yet. Once such an
8967 // API becomes available we should report the malloced memory separately. For
8968 // now we just add the values, thereby over-approximating the peak slightly.
8969 heap_statistics->malloced_memory_ =
8970 isolate->allocator()->GetCurrentMemoryUsage() +
8971 isolate->string_table()->GetCurrentMemoryUsage();
8972 // On 32-bit systems backing_store_bytes() might overflow size_t temporarily
8973 // due to concurrent array buffer sweeping.
8974 heap_statistics->external_memory_ =
8975 isolate->heap()->backing_store_bytes() < SIZE_MAX
8976 ? static_cast<size_t>(isolate->heap()->backing_store_bytes())
8977 : SIZE_MAX;
8978 heap_statistics->peak_malloced_memory_ =
8979 isolate->allocator()->GetMaxMemoryUsage();
8980 heap_statistics->number_of_native_contexts_ = heap->NumberOfNativeContexts();
8981 heap_statistics->number_of_detached_contexts_ =
8982 heap->NumberOfDetachedContexts();
8983 heap_statistics->does_zap_garbage_ = heap->ShouldZapGarbage();
8984
8985 #if V8_ENABLE_WEBASSEMBLY
8986 heap_statistics->malloced_memory_ +=
8987 i::wasm::GetWasmEngine()->allocator()->GetCurrentMemoryUsage();
8988 heap_statistics->peak_malloced_memory_ +=
8989 i::wasm::GetWasmEngine()->allocator()->GetMaxMemoryUsage();
8990 #endif // V8_ENABLE_WEBASSEMBLY
8991 }
8992
DeserializeOrCompile(Isolate * v8_isolate,MemorySpan<const uint8_t> wire_bytes,MemorySpan<const uint8_t> wasm_cache_data,bool & cacheRejected)8993 MaybeLocal<WasmModuleObject> WasmModuleObject::DeserializeOrCompile(
8994 Isolate* v8_isolate, MemorySpan<const uint8_t> wire_bytes,
8995 MemorySpan<const uint8_t> wasm_cache_data, bool& cacheRejected) {
8996 #if V8_ENABLE_WEBASSEMBLY
8997 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
8998 i::MaybeHandle<i::WasmModuleObject> maybe_mdoule =
8999 i::wasm::DeserializeNativeModule(
9000 i_isolate,
9001 base::Vector<const uint8_t>(wasm_cache_data.data(),
9002 wasm_cache_data.size()),
9003 base::Vector<const uint8_t>(wire_bytes.data(), wire_bytes.size()),
9004 {});
9005 cacheRejected = maybe_mdoule.is_null();
9006 if (!cacheRejected) {
9007 // Deserialize successfully
9008 return Local<WasmModuleObject>::Cast(Utils::ToLocal(
9009 i::Handle<i::JSObject>::cast(maybe_mdoule.ToHandleChecked())));
9010 }
9011 return Compile(v8_isolate, wire_bytes);
9012 #else
9013 Utils::ApiCheck(false, "WasmModuleObject::DeserializeOrCompile",
9014 "WebAssembly support is not enabled");
9015 UNREACHABLE();
9016 #endif // V8_ENABLE_WEBASSEMBLY
9017 }
9018
CompileFunction(Isolate * v8_isolate,uint32_t function_index,WasmExecutionTier tier)9019 bool WasmModuleObject::CompileFunction(Isolate* v8_isolate,
9020 uint32_t function_index,
9021 WasmExecutionTier tier) {
9022 #if V8_ENABLE_WEBASSEMBLY
9023 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9024 auto module = i::Handle<i::WasmModuleObject>::cast(Utils::OpenHandle(this));
9025 auto* native_module = module->native_module();
9026 uint32_t num_imported_functions = native_module->num_imported_functions();
9027 uint32_t num_functions = native_module->num_functions();
9028 // Check function index out of range.
9029 if (function_index < num_imported_functions || function_index >= num_functions) {
9030 return false;
9031 }
9032
9033 // Update the static_assert once i::wasm::ExecutionTier changed.
9034 static_assert(static_cast<uint8_t>(v8::WasmExecutionTier::kNone) ==
9035 static_cast<uint8_t>(i::wasm::ExecutionTier::kNone));
9036 static_assert(static_cast<uint8_t>(v8::WasmExecutionTier::kLiftoff) ==
9037 static_cast<uint8_t>(i::wasm::ExecutionTier::kLiftoff));
9038 static_assert(static_cast<uint8_t>(v8::WasmExecutionTier::kTurbofan) ==
9039 static_cast<uint8_t>(i::wasm::ExecutionTier::kTurbofan));
9040 auto executionTier =
9041 static_cast<i::wasm::ExecutionTier>(static_cast<uint8_t>(tier));
9042 i::wasm::GetWasmEngine()->CompileFunction(i_isolate,
9043 module->native_module(),
9044 function_index, executionTier);
9045 if (native_module->compilation_state()->failed()) {
9046 return false;
9047 }
9048 return true;
9049 #else
9050 Utils::ApiCheck(false, "WasmModuleObject::CompileFunction",
9051 "WebAssembly support is not enabled");
9052 UNREACHABLE();
9053 #endif // V8_ENABLE_WEBASSEMBLY
9054 }
9055
NumberOfHeapSpaces()9056 size_t Isolate::NumberOfHeapSpaces() {
9057 return i::LAST_SPACE - i::FIRST_SPACE + 1;
9058 }
9059
GetHeapSpaceStatistics(HeapSpaceStatistics * space_statistics,size_t index)9060 bool Isolate::GetHeapSpaceStatistics(HeapSpaceStatistics* space_statistics,
9061 size_t index) {
9062 if (!space_statistics) return false;
9063 if (!i::Heap::IsValidAllocationSpace(static_cast<i::AllocationSpace>(index)))
9064 return false;
9065
9066 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9067 i::Heap* heap = isolate->heap();
9068
9069 i::AllocationSpace allocation_space = static_cast<i::AllocationSpace>(index);
9070 space_statistics->space_name_ = i::BaseSpace::GetSpaceName(allocation_space);
9071
9072 if (allocation_space == i::RO_SPACE) {
9073 if (i::ReadOnlyHeap::IsReadOnlySpaceShared()) {
9074 // RO_SPACE memory is accounted for elsewhere when ReadOnlyHeap is shared.
9075 space_statistics->space_size_ = 0;
9076 space_statistics->space_used_size_ = 0;
9077 space_statistics->space_available_size_ = 0;
9078 space_statistics->physical_space_size_ = 0;
9079 } else {
9080 i::ReadOnlySpace* space = heap->read_only_space();
9081 space_statistics->space_size_ = space->CommittedMemory();
9082 space_statistics->space_used_size_ = space->Size();
9083 space_statistics->space_available_size_ = 0;
9084 space_statistics->physical_space_size_ = space->CommittedPhysicalMemory();
9085 }
9086 } else {
9087 i::Space* space = heap->space(static_cast<int>(index));
9088 space_statistics->space_size_ = space ? space->CommittedMemory() : 0;
9089 space_statistics->space_used_size_ = space ? space->SizeOfObjects() : 0;
9090 space_statistics->space_available_size_ = space ? space->Available() : 0;
9091 space_statistics->physical_space_size_ =
9092 space ? space->CommittedPhysicalMemory() : 0;
9093 }
9094 return true;
9095 }
9096
NumberOfTrackedHeapObjectTypes()9097 size_t Isolate::NumberOfTrackedHeapObjectTypes() {
9098 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9099 i::Heap* heap = isolate->heap();
9100 return heap->NumberOfTrackedHeapObjectTypes();
9101 }
9102
GetHeapObjectStatisticsAtLastGC(HeapObjectStatistics * object_statistics,size_t type_index)9103 bool Isolate::GetHeapObjectStatisticsAtLastGC(
9104 HeapObjectStatistics* object_statistics, size_t type_index) {
9105 if (!object_statistics) return false;
9106 if (V8_LIKELY(!i::TracingFlags::is_gc_stats_enabled())) return false;
9107
9108 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9109 i::Heap* heap = isolate->heap();
9110 if (type_index >= heap->NumberOfTrackedHeapObjectTypes()) return false;
9111
9112 const char* object_type;
9113 const char* object_sub_type;
9114 size_t object_count = heap->ObjectCountAtLastGC(type_index);
9115 size_t object_size = heap->ObjectSizeAtLastGC(type_index);
9116 if (!heap->GetObjectTypeName(type_index, &object_type, &object_sub_type)) {
9117 // There should be no objects counted when the type is unknown.
9118 DCHECK_EQ(object_count, 0U);
9119 DCHECK_EQ(object_size, 0U);
9120 return false;
9121 }
9122
9123 object_statistics->object_type_ = object_type;
9124 object_statistics->object_sub_type_ = object_sub_type;
9125 object_statistics->object_count_ = object_count;
9126 object_statistics->object_size_ = object_size;
9127 return true;
9128 }
9129
GetHeapCodeAndMetadataStatistics(HeapCodeStatistics * code_statistics)9130 bool Isolate::GetHeapCodeAndMetadataStatistics(
9131 HeapCodeStatistics* code_statistics) {
9132 if (!code_statistics) return false;
9133
9134 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9135 isolate->heap()->CollectCodeStatistics();
9136
9137 code_statistics->code_and_metadata_size_ = isolate->code_and_metadata_size();
9138 code_statistics->bytecode_and_metadata_size_ =
9139 isolate->bytecode_and_metadata_size();
9140 code_statistics->external_script_source_size_ =
9141 isolate->external_script_source_size();
9142 code_statistics->cpu_profiler_metadata_size_ =
9143 i::CpuProfiler::GetAllProfilersMemorySize(
9144 reinterpret_cast<i::Isolate*>(isolate));
9145
9146 return true;
9147 }
9148
MeasureMemory(std::unique_ptr<MeasureMemoryDelegate> delegate,MeasureMemoryExecution execution)9149 bool Isolate::MeasureMemory(std::unique_ptr<MeasureMemoryDelegate> delegate,
9150 MeasureMemoryExecution execution) {
9151 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9152 return isolate->heap()->MeasureMemory(std::move(delegate), execution);
9153 }
9154
Default(Isolate * isolate,Local<Context> context,Local<Promise::Resolver> promise_resolver,MeasureMemoryMode mode)9155 std::unique_ptr<MeasureMemoryDelegate> MeasureMemoryDelegate::Default(
9156 Isolate* isolate, Local<Context> context,
9157 Local<Promise::Resolver> promise_resolver, MeasureMemoryMode mode) {
9158 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9159 i::Handle<i::NativeContext> native_context =
9160 handle(Utils::OpenHandle(*context)->native_context(), i_isolate);
9161 i::Handle<i::JSPromise> js_promise =
9162 i::Handle<i::JSPromise>::cast(Utils::OpenHandle(*promise_resolver));
9163 return i_isolate->heap()->MeasureMemoryDelegate(native_context, js_promise,
9164 mode);
9165 }
9166
GetStackSample(const RegisterState & state,void ** frames,size_t frames_limit,SampleInfo * sample_info)9167 void Isolate::GetStackSample(const RegisterState& state, void** frames,
9168 size_t frames_limit, SampleInfo* sample_info) {
9169 RegisterState regs = state;
9170 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9171 if (i::TickSample::GetStackSample(isolate, ®s,
9172 i::TickSample::kSkipCEntryFrame, frames,
9173 frames_limit, sample_info)) {
9174 return;
9175 }
9176 sample_info->frames_count = 0;
9177 sample_info->vm_state = OTHER;
9178 sample_info->external_callback_entry = nullptr;
9179 }
9180
NumberOfPhantomHandleResetsSinceLastCall()9181 size_t Isolate::NumberOfPhantomHandleResetsSinceLastCall() {
9182 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9183 return isolate->global_handles()->GetAndResetGlobalHandleResetCount();
9184 }
9185
AdjustAmountOfExternalAllocatedMemory(int64_t change_in_bytes)9186 int64_t Isolate::AdjustAmountOfExternalAllocatedMemory(
9187 int64_t change_in_bytes) {
9188 // Try to check for unreasonably large or small values from the embedder.
9189 const int64_t kMaxReasonableBytes = int64_t(1) << 60;
9190 const int64_t kMinReasonableBytes = -kMaxReasonableBytes;
9191 STATIC_ASSERT(kMaxReasonableBytes >= i::JSArrayBuffer::kMaxByteLength);
9192
9193 CHECK(kMinReasonableBytes <= change_in_bytes &&
9194 change_in_bytes < kMaxReasonableBytes);
9195
9196 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
9197 int64_t amount = i_isolate->heap()->update_external_memory(change_in_bytes);
9198
9199 if (change_in_bytes <= 0) return amount;
9200
9201 if (amount > i_isolate->heap()->external_memory_limit()) {
9202 ReportExternalAllocationLimitReached();
9203 }
9204 return amount;
9205 }
9206
SetEventLogger(LogEventCallback that)9207 void Isolate::SetEventLogger(LogEventCallback that) {
9208 // Do not overwrite the event logger if we want to log explicitly.
9209 if (i::FLAG_log_internal_timer_events) return;
9210 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9211 isolate->set_event_logger(that);
9212 }
9213
AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback)9214 void Isolate::AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback) {
9215 if (callback == nullptr) return;
9216 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9217 isolate->AddBeforeCallEnteredCallback(callback);
9218 }
9219
RemoveBeforeCallEnteredCallback(BeforeCallEnteredCallback callback)9220 void Isolate::RemoveBeforeCallEnteredCallback(
9221 BeforeCallEnteredCallback callback) {
9222 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9223 isolate->RemoveBeforeCallEnteredCallback(callback);
9224 }
9225
AddCallCompletedCallback(CallCompletedCallback callback)9226 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
9227 if (callback == nullptr) return;
9228 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9229 isolate->AddCallCompletedCallback(callback);
9230 }
9231
RemoveCallCompletedCallback(CallCompletedCallback callback)9232 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
9233 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9234 isolate->RemoveCallCompletedCallback(callback);
9235 }
9236
Wake()9237 void Isolate::AtomicsWaitWakeHandle::Wake() {
9238 reinterpret_cast<i::AtomicsWaitWakeHandle*>(this)->Wake();
9239 }
9240
SetAtomicsWaitCallback(AtomicsWaitCallback callback,void * data)9241 void Isolate::SetAtomicsWaitCallback(AtomicsWaitCallback callback, void* data) {
9242 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9243 isolate->SetAtomicsWaitCallback(callback, data);
9244 }
9245
SetPromiseHook(PromiseHook hook)9246 void Isolate::SetPromiseHook(PromiseHook hook) {
9247 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9248 isolate->SetPromiseHook(hook);
9249 }
9250
SetPromiseRejectCallback(PromiseRejectCallback callback)9251 void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
9252 if (callback == nullptr) return;
9253 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9254 isolate->SetPromiseRejectCallback(callback);
9255 }
9256
PerformMicrotaskCheckpoint()9257 void Isolate::PerformMicrotaskCheckpoint() {
9258 DCHECK_NE(MicrotasksPolicy::kScoped, GetMicrotasksPolicy());
9259 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9260 isolate->default_microtask_queue()->PerformCheckpoint(this);
9261 }
9262
EnqueueMicrotask(Local<Function> v8_function)9263 void Isolate::EnqueueMicrotask(Local<Function> v8_function) {
9264 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9265 i::Handle<i::JSReceiver> function = Utils::OpenHandle(*v8_function);
9266 i::Handle<i::NativeContext> handler_context;
9267 if (!i::JSReceiver::GetContextForMicrotask(function).ToHandle(
9268 &handler_context))
9269 handler_context = isolate->native_context();
9270 MicrotaskQueue* microtask_queue = handler_context->microtask_queue();
9271 if (microtask_queue) microtask_queue->EnqueueMicrotask(this, v8_function);
9272 }
9273
EnqueueMicrotask(MicrotaskCallback callback,void * data)9274 void Isolate::EnqueueMicrotask(MicrotaskCallback callback, void* data) {
9275 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9276 isolate->default_microtask_queue()->EnqueueMicrotask(this, callback, data);
9277 }
9278
SetMicrotasksPolicy(MicrotasksPolicy policy)9279 void Isolate::SetMicrotasksPolicy(MicrotasksPolicy policy) {
9280 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9281 isolate->default_microtask_queue()->set_microtasks_policy(policy);
9282 }
9283
GetMicrotasksPolicy() const9284 MicrotasksPolicy Isolate::GetMicrotasksPolicy() const {
9285 i::Isolate* isolate =
9286 reinterpret_cast<i::Isolate*>(const_cast<Isolate*>(this));
9287 return isolate->default_microtask_queue()->microtasks_policy();
9288 }
9289
AddMicrotasksCompletedCallback(MicrotasksCompletedCallbackWithData callback,void * data)9290 void Isolate::AddMicrotasksCompletedCallback(
9291 MicrotasksCompletedCallbackWithData callback, void* data) {
9292 DCHECK(callback);
9293 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9294 isolate->default_microtask_queue()->AddMicrotasksCompletedCallback(callback,
9295 data);
9296 }
9297
RemoveMicrotasksCompletedCallback(MicrotasksCompletedCallbackWithData callback,void * data)9298 void Isolate::RemoveMicrotasksCompletedCallback(
9299 MicrotasksCompletedCallbackWithData callback, void* data) {
9300 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9301 isolate->default_microtask_queue()->RemoveMicrotasksCompletedCallback(
9302 callback, data);
9303 }
9304
SetUseCounterCallback(UseCounterCallback callback)9305 void Isolate::SetUseCounterCallback(UseCounterCallback callback) {
9306 reinterpret_cast<i::Isolate*>(this)->SetUseCounterCallback(callback);
9307 }
9308
SetCounterFunction(CounterLookupCallback callback)9309 void Isolate::SetCounterFunction(CounterLookupCallback callback) {
9310 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9311 isolate->counters()->ResetCounterFunction(callback);
9312 }
9313
SetCreateHistogramFunction(CreateHistogramCallback callback)9314 void Isolate::SetCreateHistogramFunction(CreateHistogramCallback callback) {
9315 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9316 isolate->counters()->ResetCreateHistogramFunction(callback);
9317 }
9318
SetAddHistogramSampleFunction(AddHistogramSampleCallback callback)9319 void Isolate::SetAddHistogramSampleFunction(
9320 AddHistogramSampleCallback callback) {
9321 reinterpret_cast<i::Isolate*>(this)
9322 ->counters()
9323 ->SetAddHistogramSampleFunction(callback);
9324 }
9325
SetMetricsRecorder(const std::shared_ptr<metrics::Recorder> & metrics_recorder)9326 void Isolate::SetMetricsRecorder(
9327 const std::shared_ptr<metrics::Recorder>& metrics_recorder) {
9328 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9329 isolate->metrics_recorder()->SetEmbedderRecorder(isolate, metrics_recorder);
9330 }
9331
SetAddCrashKeyCallback(AddCrashKeyCallback callback)9332 void Isolate::SetAddCrashKeyCallback(AddCrashKeyCallback callback) {
9333 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9334 isolate->SetAddCrashKeyCallback(callback);
9335 }
9336
IdleNotificationDeadline(double deadline_in_seconds)9337 bool Isolate::IdleNotificationDeadline(double deadline_in_seconds) {
9338 // Returning true tells the caller that it need not
9339 // continue to call IdleNotification.
9340 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9341 if (!i::FLAG_use_idle_notification) return true;
9342 return isolate->heap()->IdleNotification(deadline_in_seconds);
9343 }
9344
LowMemoryNotification()9345 void Isolate::LowMemoryNotification() {
9346 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9347 {
9348 i::NestedTimedHistogramScope idle_notification_scope(
9349 isolate->counters()->gc_low_memory_notification());
9350 TRACE_EVENT0("v8", "V8.GCLowMemoryNotification");
9351 isolate->heap()->CollectAllAvailableGarbage(
9352 i::GarbageCollectionReason::kLowMemoryNotification);
9353 }
9354 }
9355
ContextDisposedNotification(bool dependant_context)9356 int Isolate::ContextDisposedNotification(bool dependant_context) {
9357 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9358 #if V8_ENABLE_WEBASSEMBLY
9359 if (!dependant_context) {
9360 if (!isolate->context().is_null()) {
9361 // We left the current context, we can abort all WebAssembly compilations
9362 // of that context.
9363 // A handle scope for the native context.
9364 i::HandleScope handle_scope(isolate);
9365 i::wasm::GetWasmEngine()->DeleteCompileJobsOnContext(
9366 isolate->native_context());
9367 }
9368 }
9369 #endif // V8_ENABLE_WEBASSEMBLY
9370 // TODO(ahaas): move other non-heap activity out of the heap call.
9371 return isolate->heap()->NotifyContextDisposed(dependant_context);
9372 }
9373
IsolateInForegroundNotification()9374 void Isolate::IsolateInForegroundNotification() {
9375 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9376 return isolate->IsolateInForegroundNotification();
9377 }
9378
IsolateInBackgroundNotification()9379 void Isolate::IsolateInBackgroundNotification() {
9380 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9381 return isolate->IsolateInBackgroundNotification();
9382 }
9383
MemoryPressureNotification(MemoryPressureLevel level)9384 void Isolate::MemoryPressureNotification(MemoryPressureLevel level) {
9385 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9386 bool on_isolate_thread =
9387 isolate->was_locker_ever_used()
9388 ? isolate->thread_manager()->IsLockedByCurrentThread()
9389 : i::ThreadId::Current() == isolate->thread_id();
9390 isolate->heap()->MemoryPressureNotification(level, on_isolate_thread);
9391 }
9392
ClearCachesForTesting()9393 void Isolate::ClearCachesForTesting() {
9394 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9395 isolate->AbortConcurrentOptimization(i::BlockingBehavior::kBlock);
9396 isolate->ClearSerializerData();
9397 }
9398
EnableMemorySavingsMode()9399 void Isolate::EnableMemorySavingsMode() {
9400 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9401 isolate->EnableMemorySavingsMode();
9402 }
9403
DisableMemorySavingsMode()9404 void Isolate::DisableMemorySavingsMode() {
9405 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9406 isolate->DisableMemorySavingsMode();
9407 }
9408
SetRAILMode(RAILMode rail_mode)9409 void Isolate::SetRAILMode(RAILMode rail_mode) {
9410 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9411 return isolate->SetRAILMode(rail_mode);
9412 }
9413
UpdateLoadStartTime()9414 void Isolate::UpdateLoadStartTime() {
9415 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9416 isolate->UpdateLoadStartTime();
9417 }
9418
IncreaseHeapLimitForDebugging()9419 void Isolate::IncreaseHeapLimitForDebugging() {
9420 // No-op.
9421 }
9422
RestoreOriginalHeapLimit()9423 void Isolate::RestoreOriginalHeapLimit() {
9424 // No-op.
9425 }
9426
IsHeapLimitIncreasedForDebugging()9427 bool Isolate::IsHeapLimitIncreasedForDebugging() { return false; }
9428
SetJitCodeEventHandler(JitCodeEventOptions options,JitCodeEventHandler event_handler)9429 void Isolate::SetJitCodeEventHandler(JitCodeEventOptions options,
9430 JitCodeEventHandler event_handler) {
9431 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9432 // Ensure that logging is initialized for our isolate.
9433 isolate->InitializeLoggingAndCounters();
9434 isolate->logger()->SetCodeEventHandler(options, event_handler);
9435 }
9436
SetStackLimit(uintptr_t stack_limit)9437 void Isolate::SetStackLimit(uintptr_t stack_limit) {
9438 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9439 CHECK(stack_limit);
9440 isolate->stack_guard()->SetStackLimit(stack_limit);
9441 }
9442
GetCodeRange(void ** start,size_t * length_in_bytes)9443 void Isolate::GetCodeRange(void** start, size_t* length_in_bytes) {
9444 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9445 const base::AddressRegion& code_region = isolate->heap()->code_region();
9446 *start = reinterpret_cast<void*>(code_region.begin());
9447 *length_in_bytes = code_region.size();
9448 }
9449
GetEmbeddedCodeRange(const void ** start,size_t * length_in_bytes)9450 void Isolate::GetEmbeddedCodeRange(const void** start,
9451 size_t* length_in_bytes) {
9452 // Note, we should return the embedded code rande from the .text section here.
9453 i::EmbeddedData d = i::EmbeddedData::FromBlob();
9454 *start = reinterpret_cast<const void*>(d.code());
9455 *length_in_bytes = d.code_size();
9456 }
9457
GetJSEntryStubs()9458 JSEntryStubs Isolate::GetJSEntryStubs() {
9459 JSEntryStubs entry_stubs;
9460
9461 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9462 std::array<std::pair<i::Builtin, JSEntryStub*>, 3> stubs = {
9463 {{i::Builtin::kJSEntry, &entry_stubs.js_entry_stub},
9464 {i::Builtin::kJSConstructEntry, &entry_stubs.js_construct_entry_stub},
9465 {i::Builtin::kJSRunMicrotasksEntry,
9466 &entry_stubs.js_run_microtasks_entry_stub}}};
9467 for (auto& pair : stubs) {
9468 i::Code js_entry = FromCodeT(isolate->builtins()->code(pair.first));
9469 pair.second->code.start =
9470 reinterpret_cast<const void*>(js_entry.InstructionStart());
9471 pair.second->code.length_in_bytes = js_entry.InstructionSize();
9472 }
9473
9474 return entry_stubs;
9475 }
9476
CopyCodePages(size_t capacity,MemoryRange * code_pages_out)9477 size_t Isolate::CopyCodePages(size_t capacity, MemoryRange* code_pages_out) {
9478 #if !defined(V8_TARGET_ARCH_64_BIT) && !defined(V8_TARGET_ARCH_ARM)
9479 // Not implemented on other platforms.
9480 UNREACHABLE();
9481 #else
9482
9483 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9484 std::vector<MemoryRange>* code_pages = isolate->GetCodePages();
9485
9486 DCHECK_NOT_NULL(code_pages);
9487
9488 // Copy as many elements into the output vector as we can. If the
9489 // caller-provided buffer is not big enough, we fill it, and the caller can
9490 // provide a bigger one next time. We do it this way because allocation is not
9491 // allowed in signal handlers.
9492 size_t limit = std::min(capacity, code_pages->size());
9493 for (size_t i = 0; i < limit; i++) {
9494 code_pages_out[i] = code_pages->at(i);
9495 }
9496 return code_pages->size();
9497 #endif
9498 }
9499
9500 #define CALLBACK_SETTER(ExternalName, Type, InternalName) \
9501 void Isolate::Set##ExternalName(Type callback) { \
9502 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); \
9503 isolate->set_##InternalName(callback); \
9504 }
9505
CALLBACK_SETTER(FatalErrorHandler,FatalErrorCallback,exception_behavior)9506 CALLBACK_SETTER(FatalErrorHandler, FatalErrorCallback, exception_behavior)
9507 CALLBACK_SETTER(OOMErrorHandler, OOMErrorCallback, oom_behavior)
9508 CALLBACK_SETTER(ModifyCodeGenerationFromStringsCallback,
9509 ModifyCodeGenerationFromStringsCallback2,
9510 modify_code_gen_callback2)
9511 CALLBACK_SETTER(AllowWasmCodeGenerationCallback,
9512 AllowWasmCodeGenerationCallback, allow_wasm_code_gen_callback)
9513
9514 CALLBACK_SETTER(WasmModuleCallback, ExtensionCallback, wasm_module_callback)
9515 CALLBACK_SETTER(WasmInstanceCallback, ExtensionCallback, wasm_instance_callback)
9516
9517 CALLBACK_SETTER(WasmStreamingCallback, WasmStreamingCallback,
9518 wasm_streaming_callback)
9519
9520 CALLBACK_SETTER(WasmLoadSourceMapCallback, WasmLoadSourceMapCallback,
9521 wasm_load_source_map_callback)
9522
9523 CALLBACK_SETTER(WasmSimdEnabledCallback, WasmSimdEnabledCallback,
9524 wasm_simd_enabled_callback)
9525
9526 CALLBACK_SETTER(WasmExceptionsEnabledCallback, WasmExceptionsEnabledCallback,
9527 wasm_exceptions_enabled_callback)
9528
9529 CALLBACK_SETTER(WasmDynamicTieringEnabledCallback,
9530 WasmDynamicTieringEnabledCallback,
9531 wasm_dynamic_tiering_enabled_callback)
9532
9533 CALLBACK_SETTER(SharedArrayBufferConstructorEnabledCallback,
9534 SharedArrayBufferConstructorEnabledCallback,
9535 sharedarraybuffer_constructor_enabled_callback)
9536
9537 void Isolate::InstallConditionalFeatures(Local<Context> context) {
9538 v8::HandleScope handle_scope(this);
9539 v8::Context::Scope context_scope(context);
9540 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9541 isolate->InstallConditionalFeatures(Utils::OpenHandle(*context));
9542 #if V8_ENABLE_WEBASSEMBLY
9543 if (i::FLAG_expose_wasm) {
9544 i::WasmJs::InstallConditionalFeatures(isolate, Utils::OpenHandle(*context));
9545 }
9546 #endif // V8_ENABLE_WEBASSEMBLY
9547 }
9548
AddNearHeapLimitCallback(v8::NearHeapLimitCallback callback,void * data)9549 void Isolate::AddNearHeapLimitCallback(v8::NearHeapLimitCallback callback,
9550 void* data) {
9551 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9552 isolate->heap()->AddNearHeapLimitCallback(callback, data);
9553 }
9554
RemoveNearHeapLimitCallback(v8::NearHeapLimitCallback callback,size_t heap_limit)9555 void Isolate::RemoveNearHeapLimitCallback(v8::NearHeapLimitCallback callback,
9556 size_t heap_limit) {
9557 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9558 isolate->heap()->RemoveNearHeapLimitCallback(callback, heap_limit);
9559 }
9560
AutomaticallyRestoreInitialHeapLimit(double threshold_percent)9561 void Isolate::AutomaticallyRestoreInitialHeapLimit(double threshold_percent) {
9562 DCHECK_GT(threshold_percent, 0.0);
9563 DCHECK_LT(threshold_percent, 1.0);
9564 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9565 isolate->heap()->AutomaticallyRestoreInitialHeapLimit(threshold_percent);
9566 }
9567
IsDead()9568 bool Isolate::IsDead() {
9569 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9570 return isolate->IsDead();
9571 }
9572
AddMessageListener(MessageCallback that,Local<Value> data)9573 bool Isolate::AddMessageListener(MessageCallback that, Local<Value> data) {
9574 return AddMessageListenerWithErrorLevel(that, kMessageError, data);
9575 }
9576
AddMessageListenerWithErrorLevel(MessageCallback that,int message_levels,Local<Value> data)9577 bool Isolate::AddMessageListenerWithErrorLevel(MessageCallback that,
9578 int message_levels,
9579 Local<Value> data) {
9580 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9581 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
9582 i::HandleScope scope(isolate);
9583 i::Handle<i::TemplateList> list = isolate->factory()->message_listeners();
9584 i::Handle<i::FixedArray> listener = isolate->factory()->NewFixedArray(3);
9585 i::Handle<i::Foreign> foreign =
9586 isolate->factory()->NewForeign(FUNCTION_ADDR(that));
9587 listener->set(0, *foreign);
9588 listener->set(1, data.IsEmpty() ? i::ReadOnlyRoots(isolate).undefined_value()
9589 : *Utils::OpenHandle(*data));
9590 listener->set(2, i::Smi::FromInt(message_levels));
9591 list = i::TemplateList::Add(isolate, list, listener);
9592 isolate->heap()->SetMessageListeners(*list);
9593 return true;
9594 }
9595
RemoveMessageListeners(MessageCallback that)9596 void Isolate::RemoveMessageListeners(MessageCallback that) {
9597 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9598 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
9599 i::HandleScope scope(isolate);
9600 i::DisallowGarbageCollection no_gc;
9601 i::TemplateList listeners = isolate->heap()->message_listeners();
9602 for (int i = 0; i < listeners.length(); i++) {
9603 if (listeners.get(i).IsUndefined(isolate)) continue; // skip deleted ones
9604 i::FixedArray listener = i::FixedArray::cast(listeners.get(i));
9605 i::Foreign callback_obj = i::Foreign::cast(listener.get(0));
9606 if (callback_obj.foreign_address() == FUNCTION_ADDR(that)) {
9607 listeners.set(i, i::ReadOnlyRoots(isolate).undefined_value());
9608 }
9609 }
9610 }
9611
SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback callback)9612 void Isolate::SetFailedAccessCheckCallbackFunction(
9613 FailedAccessCheckCallback callback) {
9614 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9615 isolate->SetFailedAccessCheckCallback(callback);
9616 }
9617
SetCaptureStackTraceForUncaughtExceptions(bool capture,int frame_limit,StackTrace::StackTraceOptions options)9618 void Isolate::SetCaptureStackTraceForUncaughtExceptions(
9619 bool capture, int frame_limit, StackTrace::StackTraceOptions options) {
9620 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9621 isolate->SetCaptureStackTraceForUncaughtExceptions(capture, frame_limit,
9622 options);
9623 }
9624
VisitExternalResources(ExternalResourceVisitor * visitor)9625 void Isolate::VisitExternalResources(ExternalResourceVisitor* visitor) {
9626 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9627 isolate->heap()->VisitExternalResources(visitor);
9628 }
9629
IsInUse()9630 bool Isolate::IsInUse() {
9631 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9632 return isolate->IsInUse();
9633 }
9634
VisitHandlesWithClassIds(PersistentHandleVisitor * visitor)9635 void Isolate::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) {
9636 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9637 i::DisallowGarbageCollection no_gc;
9638 isolate->global_handles()->IterateAllRootsWithClassIds(visitor);
9639 }
9640
VisitWeakHandles(PersistentHandleVisitor * visitor)9641 void Isolate::VisitWeakHandles(PersistentHandleVisitor* visitor) {
9642 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9643 i::DisallowGarbageCollection no_gc;
9644 isolate->global_handles()->IterateYoungWeakRootsWithClassIds(visitor);
9645 }
9646
SetAllowAtomicsWait(bool allow)9647 void Isolate::SetAllowAtomicsWait(bool allow) {
9648 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9649 isolate->set_allow_atomics_wait(allow);
9650 }
9651
DateTimeConfigurationChangeNotification(TimeZoneDetection time_zone_detection)9652 void v8::Isolate::DateTimeConfigurationChangeNotification(
9653 TimeZoneDetection time_zone_detection) {
9654 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
9655 API_RCS_SCOPE(i_isolate, Isolate, DateTimeConfigurationChangeNotification);
9656 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
9657 i_isolate->date_cache()->ResetDateCache(
9658 static_cast<base::TimezoneCache::TimeZoneDetection>(time_zone_detection));
9659 #ifdef V8_INTL_SUPPORT
9660 i_isolate->clear_cached_icu_object(
9661 i::Isolate::ICUObjectCacheType::kDefaultSimpleDateFormat);
9662 i_isolate->clear_cached_icu_object(
9663 i::Isolate::ICUObjectCacheType::kDefaultSimpleDateFormatForTime);
9664 i_isolate->clear_cached_icu_object(
9665 i::Isolate::ICUObjectCacheType::kDefaultSimpleDateFormatForDate);
9666 #endif // V8_INTL_SUPPORT
9667 }
9668
LocaleConfigurationChangeNotification()9669 void v8::Isolate::LocaleConfigurationChangeNotification() {
9670 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
9671 API_RCS_SCOPE(i_isolate, Isolate, LocaleConfigurationChangeNotification);
9672 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
9673
9674 #ifdef V8_INTL_SUPPORT
9675 i_isolate->ResetDefaultLocale();
9676 #endif // V8_INTL_SUPPORT
9677 }
9678
IsCodeLike(v8::Isolate * isolate) const9679 bool v8::Object::IsCodeLike(v8::Isolate* isolate) const {
9680 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9681 API_RCS_SCOPE(i_isolate, Object, IsCodeLike);
9682 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
9683 i::HandleScope scope(i_isolate);
9684 return Utils::OpenHandle(this)->IsCodeLike(i_isolate);
9685 }
9686
9687 // static
New(Isolate * isolate,MicrotasksPolicy policy)9688 std::unique_ptr<MicrotaskQueue> MicrotaskQueue::New(Isolate* isolate,
9689 MicrotasksPolicy policy) {
9690 auto microtask_queue =
9691 i::MicrotaskQueue::New(reinterpret_cast<i::Isolate*>(isolate));
9692 microtask_queue->set_microtasks_policy(policy);
9693 std::unique_ptr<MicrotaskQueue> ret(std::move(microtask_queue));
9694 return ret;
9695 }
9696
MicrotasksScope(Isolate * isolate,MicrotasksScope::Type type)9697 MicrotasksScope::MicrotasksScope(Isolate* isolate, MicrotasksScope::Type type)
9698 : MicrotasksScope(isolate, nullptr, type) {}
9699
MicrotasksScope(Isolate * isolate,MicrotaskQueue * microtask_queue,MicrotasksScope::Type type)9700 MicrotasksScope::MicrotasksScope(Isolate* isolate,
9701 MicrotaskQueue* microtask_queue,
9702 MicrotasksScope::Type type)
9703 : isolate_(reinterpret_cast<i::Isolate*>(isolate)),
9704 microtask_queue_(microtask_queue
9705 ? static_cast<i::MicrotaskQueue*>(microtask_queue)
9706 : isolate_->default_microtask_queue()),
9707 run_(type == MicrotasksScope::kRunMicrotasks) {
9708 if (run_) microtask_queue_->IncrementMicrotasksScopeDepth();
9709 #ifdef DEBUG
9710 if (!run_) microtask_queue_->IncrementDebugMicrotasksScopeDepth();
9711 #endif
9712 }
9713
~MicrotasksScope()9714 MicrotasksScope::~MicrotasksScope() {
9715 if (run_) {
9716 microtask_queue_->DecrementMicrotasksScopeDepth();
9717 if (MicrotasksPolicy::kScoped == microtask_queue_->microtasks_policy() &&
9718 !isolate_->has_scheduled_exception()) {
9719 DCHECK_IMPLIES(isolate_->has_scheduled_exception(),
9720 isolate_->scheduled_exception() ==
9721 i::ReadOnlyRoots(isolate_).termination_exception());
9722 microtask_queue_->PerformCheckpoint(reinterpret_cast<Isolate*>(isolate_));
9723 }
9724 }
9725 #ifdef DEBUG
9726 if (!run_) microtask_queue_->DecrementDebugMicrotasksScopeDepth();
9727 #endif
9728 }
9729
9730 // static
PerformCheckpoint(Isolate * v8_isolate)9731 void MicrotasksScope::PerformCheckpoint(Isolate* v8_isolate) {
9732 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9733 auto* microtask_queue = isolate->default_microtask_queue();
9734 microtask_queue->PerformCheckpoint(v8_isolate);
9735 }
9736
9737 // static
GetCurrentDepth(Isolate * v8_isolate)9738 int MicrotasksScope::GetCurrentDepth(Isolate* v8_isolate) {
9739 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9740 auto* microtask_queue = isolate->default_microtask_queue();
9741 return microtask_queue->GetMicrotasksScopeDepth();
9742 }
9743
9744 // static
IsRunningMicrotasks(Isolate * v8_isolate)9745 bool MicrotasksScope::IsRunningMicrotasks(Isolate* v8_isolate) {
9746 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9747 auto* microtask_queue = isolate->default_microtask_queue();
9748 return microtask_queue->IsRunningMicrotasks();
9749 }
9750
Utf8Value(v8::Isolate * isolate,v8::Local<v8::Value> obj)9751 String::Utf8Value::Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> obj)
9752 : str_(nullptr), length_(0) {
9753 if (obj.IsEmpty()) return;
9754 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9755 ENTER_V8_DO_NOT_USE(i_isolate);
9756 i::HandleScope scope(i_isolate);
9757 Local<Context> context = isolate->GetCurrentContext();
9758 TryCatch try_catch(isolate);
9759 Local<String> str;
9760 if (!obj->ToString(context).ToLocal(&str)) return;
9761 length_ = str->Utf8Length(isolate);
9762 str_ = i::NewArray<char>(length_ + 1);
9763 str->WriteUtf8(isolate, str_);
9764 }
9765
~Utf8Value()9766 String::Utf8Value::~Utf8Value() { i::DeleteArray(str_); }
9767
Value(v8::Isolate * isolate,v8::Local<v8::Value> obj)9768 String::Value::Value(v8::Isolate* isolate, v8::Local<v8::Value> obj)
9769 : str_(nullptr), length_(0) {
9770 if (obj.IsEmpty()) return;
9771 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9772 ENTER_V8_DO_NOT_USE(i_isolate);
9773 i::HandleScope scope(i_isolate);
9774 Local<Context> context = isolate->GetCurrentContext();
9775 TryCatch try_catch(isolate);
9776 Local<String> str;
9777 if (!obj->ToString(context).ToLocal(&str)) return;
9778 length_ = str->Length();
9779 str_ = i::NewArray<uint16_t>(length_ + 1);
9780 str->Write(isolate, str_);
9781 }
9782
~Value()9783 String::Value::~Value() { i::DeleteArray(str_); }
9784
9785 #define DEFINE_ERROR(NAME, name) \
9786 Local<Value> Exception::NAME(v8::Local<v8::String> raw_message) { \
9787 i::Isolate* isolate = i::Isolate::Current(); \
9788 API_RCS_SCOPE(isolate, NAME, New); \
9789 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \
9790 i::Object error; \
9791 { \
9792 i::HandleScope scope(isolate); \
9793 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); \
9794 i::Handle<i::JSFunction> constructor = isolate->name##_function(); \
9795 error = *isolate->factory()->NewError(constructor, message); \
9796 } \
9797 i::Handle<i::Object> result(error, isolate); \
9798 return Utils::ToLocal(result); \
9799 }
9800
DEFINE_ERROR(RangeError,range_error)9801 DEFINE_ERROR(RangeError, range_error)
9802 DEFINE_ERROR(ReferenceError, reference_error)
9803 DEFINE_ERROR(SyntaxError, syntax_error)
9804 DEFINE_ERROR(TypeError, type_error)
9805 DEFINE_ERROR(WasmCompileError, wasm_compile_error)
9806 DEFINE_ERROR(WasmLinkError, wasm_link_error)
9807 DEFINE_ERROR(WasmRuntimeError, wasm_runtime_error)
9808 DEFINE_ERROR(Error, error)
9809
9810 #undef DEFINE_ERROR
9811
9812 Local<Message> Exception::CreateMessage(Isolate* isolate,
9813 Local<Value> exception) {
9814 i::Handle<i::Object> obj = Utils::OpenHandle(*exception);
9815 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9816 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
9817 i::HandleScope scope(i_isolate);
9818 return Utils::MessageToLocal(
9819 scope.CloseAndEscape(i_isolate->CreateMessage(obj, nullptr)));
9820 }
9821
GetStackTrace(Local<Value> exception)9822 Local<StackTrace> Exception::GetStackTrace(Local<Value> exception) {
9823 i::Handle<i::Object> obj = Utils::OpenHandle(*exception);
9824 if (!obj->IsJSObject()) return Local<StackTrace>();
9825 i::Handle<i::JSObject> js_obj = i::Handle<i::JSObject>::cast(obj);
9826 i::Isolate* isolate = js_obj->GetIsolate();
9827 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
9828 return Utils::StackTraceToLocal(isolate->GetDetailedStackTrace(js_obj));
9829 }
9830
PreviewEntries(bool * is_key_value)9831 v8::MaybeLocal<v8::Array> v8::Object::PreviewEntries(bool* is_key_value) {
9832 if (IsMap()) {
9833 *is_key_value = true;
9834 return Map::Cast(this)->AsArray();
9835 }
9836 if (IsSet()) {
9837 *is_key_value = false;
9838 return Set::Cast(this)->AsArray();
9839 }
9840
9841 i::Handle<i::JSReceiver> object = Utils::OpenHandle(this);
9842 i::Isolate* isolate = object->GetIsolate();
9843 Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
9844 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
9845 if (object->IsJSWeakCollection()) {
9846 *is_key_value = object->IsJSWeakMap();
9847 return Utils::ToLocal(i::JSWeakCollection::GetEntries(
9848 i::Handle<i::JSWeakCollection>::cast(object), 0));
9849 }
9850 if (object->IsJSMapIterator()) {
9851 i::Handle<i::JSMapIterator> it = i::Handle<i::JSMapIterator>::cast(object);
9852 MapAsArrayKind const kind =
9853 static_cast<MapAsArrayKind>(it->map().instance_type());
9854 *is_key_value = kind == MapAsArrayKind::kEntries;
9855 if (!it->HasMore()) return v8::Array::New(v8_isolate);
9856 return Utils::ToLocal(
9857 MapAsArray(isolate, it->table(), i::Smi::ToInt(it->index()), kind));
9858 }
9859 if (object->IsJSSetIterator()) {
9860 i::Handle<i::JSSetIterator> it = i::Handle<i::JSSetIterator>::cast(object);
9861 SetAsArrayKind const kind =
9862 static_cast<SetAsArrayKind>(it->map().instance_type());
9863 *is_key_value = kind == SetAsArrayKind::kEntries;
9864 if (!it->HasMore()) return v8::Array::New(v8_isolate);
9865 return Utils::ToLocal(
9866 SetAsArray(isolate, it->table(), i::Smi::ToInt(it->index()), kind));
9867 }
9868 return v8::MaybeLocal<v8::Array>();
9869 }
9870
GetFunctionName() const9871 Local<String> CpuProfileNode::GetFunctionName() const {
9872 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9873 i::Isolate* isolate = node->isolate();
9874 const i::CodeEntry* entry = node->entry();
9875 i::Handle<i::String> name =
9876 isolate->factory()->InternalizeUtf8String(entry->name());
9877 return ToApiHandle<String>(name);
9878 }
9879
GetFunctionNameStr() const9880 const char* CpuProfileNode::GetFunctionNameStr() const {
9881 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9882 return node->entry()->name();
9883 }
9884
GetScriptId() const9885 int CpuProfileNode::GetScriptId() const {
9886 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9887 const i::CodeEntry* entry = node->entry();
9888 return entry->script_id();
9889 }
9890
GetScriptResourceName() const9891 Local<String> CpuProfileNode::GetScriptResourceName() const {
9892 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9893 i::Isolate* isolate = node->isolate();
9894 return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
9895 node->entry()->resource_name()));
9896 }
9897
GetScriptResourceNameStr() const9898 const char* CpuProfileNode::GetScriptResourceNameStr() const {
9899 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9900 return node->entry()->resource_name();
9901 }
9902
IsScriptSharedCrossOrigin() const9903 bool CpuProfileNode::IsScriptSharedCrossOrigin() const {
9904 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9905 return node->entry()->is_shared_cross_origin();
9906 }
9907
GetLineNumber() const9908 int CpuProfileNode::GetLineNumber() const {
9909 return reinterpret_cast<const i::ProfileNode*>(this)->line_number();
9910 }
9911
GetColumnNumber() const9912 int CpuProfileNode::GetColumnNumber() const {
9913 return reinterpret_cast<const i::ProfileNode*>(this)
9914 ->entry()
9915 ->column_number();
9916 }
9917
GetHitLineCount() const9918 unsigned int CpuProfileNode::GetHitLineCount() const {
9919 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9920 return node->GetHitLineCount();
9921 }
9922
GetLineTicks(LineTick * entries,unsigned int length) const9923 bool CpuProfileNode::GetLineTicks(LineTick* entries,
9924 unsigned int length) const {
9925 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9926 return node->GetLineTicks(entries, length);
9927 }
9928
GetBailoutReason() const9929 const char* CpuProfileNode::GetBailoutReason() const {
9930 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9931 return node->entry()->bailout_reason();
9932 }
9933
GetHitCount() const9934 unsigned CpuProfileNode::GetHitCount() const {
9935 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
9936 }
9937
GetNodeId() const9938 unsigned CpuProfileNode::GetNodeId() const {
9939 return reinterpret_cast<const i::ProfileNode*>(this)->id();
9940 }
9941
GetSourceType() const9942 CpuProfileNode::SourceType CpuProfileNode::GetSourceType() const {
9943 return reinterpret_cast<const i::ProfileNode*>(this)->source_type();
9944 }
9945
GetChildrenCount() const9946 int CpuProfileNode::GetChildrenCount() const {
9947 return static_cast<int>(
9948 reinterpret_cast<const i::ProfileNode*>(this)->children()->size());
9949 }
9950
GetChild(int index) const9951 const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
9952 const i::ProfileNode* child =
9953 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
9954 return reinterpret_cast<const CpuProfileNode*>(child);
9955 }
9956
GetParent() const9957 const CpuProfileNode* CpuProfileNode::GetParent() const {
9958 const i::ProfileNode* parent =
9959 reinterpret_cast<const i::ProfileNode*>(this)->parent();
9960 return reinterpret_cast<const CpuProfileNode*>(parent);
9961 }
9962
GetDeoptInfos() const9963 const std::vector<CpuProfileDeoptInfo>& CpuProfileNode::GetDeoptInfos() const {
9964 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9965 return node->deopt_infos();
9966 }
9967
Delete()9968 void CpuProfile::Delete() {
9969 i::CpuProfile* profile = reinterpret_cast<i::CpuProfile*>(this);
9970 i::CpuProfiler* profiler = profile->cpu_profiler();
9971 DCHECK_NOT_NULL(profiler);
9972 profiler->DeleteProfile(profile);
9973 }
9974
GetTitle() const9975 Local<String> CpuProfile::GetTitle() const {
9976 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9977 i::Isolate* isolate = profile->top_down()->isolate();
9978 return ToApiHandle<String>(
9979 isolate->factory()->InternalizeUtf8String(profile->title()));
9980 }
9981
GetTopDownRoot() const9982 const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
9983 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9984 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
9985 }
9986
GetSample(int index) const9987 const CpuProfileNode* CpuProfile::GetSample(int index) const {
9988 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9989 return reinterpret_cast<const CpuProfileNode*>(profile->sample(index).node);
9990 }
9991
9992 const int CpuProfileNode::kNoLineNumberInfo;
9993 const int CpuProfileNode::kNoColumnNumberInfo;
9994
GetSampleTimestamp(int index) const9995 int64_t CpuProfile::GetSampleTimestamp(int index) const {
9996 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9997 return profile->sample(index).timestamp.since_origin().InMicroseconds();
9998 }
9999
GetSampleState(int index) const10000 StateTag CpuProfile::GetSampleState(int index) const {
10001 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
10002 return profile->sample(index).state_tag;
10003 }
10004
GetSampleEmbedderState(int index) const10005 EmbedderStateTag CpuProfile::GetSampleEmbedderState(int index) const {
10006 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
10007 return profile->sample(index).embedder_state_tag;
10008 }
10009
GetStartTime() const10010 int64_t CpuProfile::GetStartTime() const {
10011 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
10012 return profile->start_time().since_origin().InMicroseconds();
10013 }
10014
GetEndTime() const10015 int64_t CpuProfile::GetEndTime() const {
10016 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
10017 return profile->end_time().since_origin().InMicroseconds();
10018 }
10019
ToInternal(const CpuProfile * profile)10020 static i::CpuProfile* ToInternal(const CpuProfile* profile) {
10021 return const_cast<i::CpuProfile*>(
10022 reinterpret_cast<const i::CpuProfile*>(profile));
10023 }
10024
Serialize(OutputStream * stream,CpuProfile::SerializationFormat format) const10025 void CpuProfile::Serialize(OutputStream* stream,
10026 CpuProfile::SerializationFormat format) const {
10027 Utils::ApiCheck(format == kJSON, "v8::CpuProfile::Serialize",
10028 "Unknown serialization format");
10029 Utils::ApiCheck(stream->GetChunkSize() > 0, "v8::CpuProfile::Serialize",
10030 "Invalid stream chunk size");
10031 i::CpuProfileJSONSerializer serializer(ToInternal(this));
10032 serializer.Serialize(stream);
10033 }
10034
GetSamplesCount() const10035 int CpuProfile::GetSamplesCount() const {
10036 return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
10037 }
10038
New(Isolate * isolate,CpuProfilingNamingMode naming_mode,CpuProfilingLoggingMode logging_mode)10039 CpuProfiler* CpuProfiler::New(Isolate* isolate,
10040 CpuProfilingNamingMode naming_mode,
10041 CpuProfilingLoggingMode logging_mode) {
10042 return reinterpret_cast<CpuProfiler*>(new i::CpuProfiler(
10043 reinterpret_cast<i::Isolate*>(isolate), naming_mode, logging_mode));
10044 }
10045
CpuProfilingOptions(CpuProfilingMode mode,unsigned max_samples,int sampling_interval_us,MaybeLocal<Context> filter_context)10046 CpuProfilingOptions::CpuProfilingOptions(CpuProfilingMode mode,
10047 unsigned max_samples,
10048 int sampling_interval_us,
10049 MaybeLocal<Context> filter_context)
10050 : mode_(mode),
10051 max_samples_(max_samples),
10052 sampling_interval_us_(sampling_interval_us) {
10053 if (!filter_context.IsEmpty()) {
10054 Local<Context> local_filter_context = filter_context.ToLocalChecked();
10055 filter_context_.Reset(local_filter_context->GetIsolate(),
10056 local_filter_context);
10057 filter_context_.SetWeak();
10058 }
10059 }
10060
raw_filter_context() const10061 void* CpuProfilingOptions::raw_filter_context() const {
10062 return reinterpret_cast<void*>(
10063 i::Context::cast(*Utils::OpenPersistent(filter_context_))
10064 .native_context()
10065 .address());
10066 }
10067
Dispose()10068 void CpuProfiler::Dispose() { delete reinterpret_cast<i::CpuProfiler*>(this); }
10069
10070 // static
CollectSample(Isolate * isolate)10071 void CpuProfiler::CollectSample(Isolate* isolate) {
10072 i::CpuProfiler::CollectSample(reinterpret_cast<i::Isolate*>(isolate));
10073 }
10074
SetSamplingInterval(int us)10075 void CpuProfiler::SetSamplingInterval(int us) {
10076 DCHECK_GE(us, 0);
10077 return reinterpret_cast<i::CpuProfiler*>(this)->set_sampling_interval(
10078 base::TimeDelta::FromMicroseconds(us));
10079 }
10080
SetUsePreciseSampling(bool use_precise_sampling)10081 void CpuProfiler::SetUsePreciseSampling(bool use_precise_sampling) {
10082 reinterpret_cast<i::CpuProfiler*>(this)->set_use_precise_sampling(
10083 use_precise_sampling);
10084 }
10085
Start(CpuProfilingOptions options,std::unique_ptr<DiscardedSamplesDelegate> delegate)10086 CpuProfilingResult CpuProfiler::Start(
10087 CpuProfilingOptions options,
10088 std::unique_ptr<DiscardedSamplesDelegate> delegate) {
10089 return reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
10090 options, std::move(delegate));
10091 }
10092
Start(Local<String> title,CpuProfilingOptions options,std::unique_ptr<DiscardedSamplesDelegate> delegate)10093 CpuProfilingResult CpuProfiler::Start(
10094 Local<String> title, CpuProfilingOptions options,
10095 std::unique_ptr<DiscardedSamplesDelegate> delegate) {
10096 return reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
10097 *Utils::OpenHandle(*title), options, std::move(delegate));
10098 }
10099
Start(Local<String> title,bool record_samples)10100 CpuProfilingResult CpuProfiler::Start(Local<String> title,
10101 bool record_samples) {
10102 CpuProfilingOptions options(
10103 kLeafNodeLineNumbers,
10104 record_samples ? CpuProfilingOptions::kNoSampleLimit : 0);
10105 return reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
10106 *Utils::OpenHandle(*title), options);
10107 }
10108
Start(Local<String> title,CpuProfilingMode mode,bool record_samples,unsigned max_samples)10109 CpuProfilingResult CpuProfiler::Start(Local<String> title,
10110 CpuProfilingMode mode,
10111 bool record_samples,
10112 unsigned max_samples) {
10113 CpuProfilingOptions options(mode, record_samples ? max_samples : 0);
10114 return reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
10115 *Utils::OpenHandle(*title), options);
10116 }
10117
StartProfiling(Local<String> title,CpuProfilingOptions options,std::unique_ptr<DiscardedSamplesDelegate> delegate)10118 CpuProfilingStatus CpuProfiler::StartProfiling(
10119 Local<String> title, CpuProfilingOptions options,
10120 std::unique_ptr<DiscardedSamplesDelegate> delegate) {
10121 return Start(title, options, std::move(delegate)).status;
10122 }
10123
StartProfiling(Local<String> title,bool record_samples)10124 CpuProfilingStatus CpuProfiler::StartProfiling(Local<String> title,
10125 bool record_samples) {
10126 return Start(title, record_samples).status;
10127 }
10128
StartProfiling(Local<String> title,CpuProfilingMode mode,bool record_samples,unsigned max_samples)10129 CpuProfilingStatus CpuProfiler::StartProfiling(Local<String> title,
10130 CpuProfilingMode mode,
10131 bool record_samples,
10132 unsigned max_samples) {
10133 return Start(title, mode, record_samples, max_samples).status;
10134 }
10135
StopProfiling(Local<String> title)10136 CpuProfile* CpuProfiler::StopProfiling(Local<String> title) {
10137 return reinterpret_cast<CpuProfile*>(
10138 reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
10139 *Utils::OpenHandle(*title)));
10140 }
10141
Stop(ProfilerId id)10142 CpuProfile* CpuProfiler::Stop(ProfilerId id) {
10143 return reinterpret_cast<CpuProfile*>(
10144 reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(id));
10145 }
10146
UseDetailedSourcePositionsForProfiling(Isolate * isolate)10147 void CpuProfiler::UseDetailedSourcePositionsForProfiling(Isolate* isolate) {
10148 reinterpret_cast<i::Isolate*>(isolate)
10149 ->SetDetailedSourcePositionsForProfiling(true);
10150 }
10151
GetCodeStartAddress()10152 uintptr_t CodeEvent::GetCodeStartAddress() {
10153 return reinterpret_cast<i::CodeEvent*>(this)->code_start_address;
10154 }
10155
GetCodeSize()10156 size_t CodeEvent::GetCodeSize() {
10157 return reinterpret_cast<i::CodeEvent*>(this)->code_size;
10158 }
10159
GetFunctionName()10160 Local<String> CodeEvent::GetFunctionName() {
10161 return ToApiHandle<String>(
10162 reinterpret_cast<i::CodeEvent*>(this)->function_name);
10163 }
10164
GetScriptName()10165 Local<String> CodeEvent::GetScriptName() {
10166 return ToApiHandle<String>(
10167 reinterpret_cast<i::CodeEvent*>(this)->script_name);
10168 }
10169
GetScriptLine()10170 int CodeEvent::GetScriptLine() {
10171 return reinterpret_cast<i::CodeEvent*>(this)->script_line;
10172 }
10173
GetScriptColumn()10174 int CodeEvent::GetScriptColumn() {
10175 return reinterpret_cast<i::CodeEvent*>(this)->script_column;
10176 }
10177
GetCodeType()10178 CodeEventType CodeEvent::GetCodeType() {
10179 return reinterpret_cast<i::CodeEvent*>(this)->code_type;
10180 }
10181
GetComment()10182 const char* CodeEvent::GetComment() {
10183 return reinterpret_cast<i::CodeEvent*>(this)->comment;
10184 }
10185
GetPreviousCodeStartAddress()10186 uintptr_t CodeEvent::GetPreviousCodeStartAddress() {
10187 return reinterpret_cast<i::CodeEvent*>(this)->previous_code_start_address;
10188 }
10189
GetCodeEventTypeName(CodeEventType code_event_type)10190 const char* CodeEvent::GetCodeEventTypeName(CodeEventType code_event_type) {
10191 switch (code_event_type) {
10192 case kUnknownType:
10193 return "Unknown";
10194 #define V(Name) \
10195 case k##Name##Type: \
10196 return #Name;
10197 CODE_EVENTS_LIST(V)
10198 #undef V
10199 }
10200 // The execution should never pass here
10201 UNREACHABLE();
10202 }
10203
CodeEventHandler(Isolate * isolate)10204 CodeEventHandler::CodeEventHandler(Isolate* isolate) {
10205 internal_listener_ =
10206 new i::ExternalCodeEventListener(reinterpret_cast<i::Isolate*>(isolate));
10207 }
10208
~CodeEventHandler()10209 CodeEventHandler::~CodeEventHandler() {
10210 delete reinterpret_cast<i::ExternalCodeEventListener*>(internal_listener_);
10211 }
10212
Enable()10213 void CodeEventHandler::Enable() {
10214 reinterpret_cast<i::ExternalCodeEventListener*>(internal_listener_)
10215 ->StartListening(this);
10216 }
10217
Disable()10218 void CodeEventHandler::Disable() {
10219 reinterpret_cast<i::ExternalCodeEventListener*>(internal_listener_)
10220 ->StopListening();
10221 }
10222
ToInternal(const HeapGraphEdge * edge)10223 static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
10224 return const_cast<i::HeapGraphEdge*>(
10225 reinterpret_cast<const i::HeapGraphEdge*>(edge));
10226 }
10227
GetType() const10228 HeapGraphEdge::Type HeapGraphEdge::GetType() const {
10229 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
10230 }
10231
GetName() const10232 Local<Value> HeapGraphEdge::GetName() const {
10233 i::HeapGraphEdge* edge = ToInternal(this);
10234 i::Isolate* isolate = edge->isolate();
10235 switch (edge->type()) {
10236 case i::HeapGraphEdge::kContextVariable:
10237 case i::HeapGraphEdge::kInternal:
10238 case i::HeapGraphEdge::kProperty:
10239 case i::HeapGraphEdge::kShortcut:
10240 case i::HeapGraphEdge::kWeak:
10241 return ToApiHandle<String>(
10242 isolate->factory()->InternalizeUtf8String(edge->name()));
10243 case i::HeapGraphEdge::kElement:
10244 case i::HeapGraphEdge::kHidden:
10245 return ToApiHandle<Number>(
10246 isolate->factory()->NewNumberFromInt(edge->index()));
10247 default:
10248 UNREACHABLE();
10249 }
10250 }
10251
GetFromNode() const10252 const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
10253 const i::HeapEntry* from = ToInternal(this)->from();
10254 return reinterpret_cast<const HeapGraphNode*>(from);
10255 }
10256
GetToNode() const10257 const HeapGraphNode* HeapGraphEdge::GetToNode() const {
10258 const i::HeapEntry* to = ToInternal(this)->to();
10259 return reinterpret_cast<const HeapGraphNode*>(to);
10260 }
10261
ToInternal(const HeapGraphNode * entry)10262 static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
10263 return const_cast<i::HeapEntry*>(
10264 reinterpret_cast<const i::HeapEntry*>(entry));
10265 }
10266
GetType() const10267 HeapGraphNode::Type HeapGraphNode::GetType() const {
10268 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
10269 }
10270
GetName() const10271 Local<String> HeapGraphNode::GetName() const {
10272 i::Isolate* isolate = ToInternal(this)->isolate();
10273 return ToApiHandle<String>(
10274 isolate->factory()->InternalizeUtf8String(ToInternal(this)->name()));
10275 }
10276
GetId() const10277 SnapshotObjectId HeapGraphNode::GetId() const { return ToInternal(this)->id(); }
10278
GetShallowSize() const10279 size_t HeapGraphNode::GetShallowSize() const {
10280 return ToInternal(this)->self_size();
10281 }
10282
GetChildrenCount() const10283 int HeapGraphNode::GetChildrenCount() const {
10284 return ToInternal(this)->children_count();
10285 }
10286
GetChild(int index) const10287 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
10288 return reinterpret_cast<const HeapGraphEdge*>(ToInternal(this)->child(index));
10289 }
10290
ToInternal(const HeapSnapshot * snapshot)10291 static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
10292 return const_cast<i::HeapSnapshot*>(
10293 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
10294 }
10295
Delete()10296 void HeapSnapshot::Delete() {
10297 i::Isolate* isolate = ToInternal(this)->profiler()->isolate();
10298 if (isolate->heap_profiler()->GetSnapshotsCount() > 1 ||
10299 isolate->heap_profiler()->IsTakingSnapshot()) {
10300 ToInternal(this)->Delete();
10301 } else {
10302 // If this is the last snapshot, clean up all accessory data as well.
10303 isolate->heap_profiler()->DeleteAllSnapshots();
10304 }
10305 }
10306
GetRoot() const10307 const HeapGraphNode* HeapSnapshot::GetRoot() const {
10308 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
10309 }
10310
GetNodeById(SnapshotObjectId id) const10311 const HeapGraphNode* HeapSnapshot::GetNodeById(SnapshotObjectId id) const {
10312 return reinterpret_cast<const HeapGraphNode*>(
10313 ToInternal(this)->GetEntryById(id));
10314 }
10315
GetNodesCount() const10316 int HeapSnapshot::GetNodesCount() const {
10317 return static_cast<int>(ToInternal(this)->entries().size());
10318 }
10319
GetNode(int index) const10320 const HeapGraphNode* HeapSnapshot::GetNode(int index) const {
10321 return reinterpret_cast<const HeapGraphNode*>(
10322 &ToInternal(this)->entries().at(index));
10323 }
10324
GetMaxSnapshotJSObjectId() const10325 SnapshotObjectId HeapSnapshot::GetMaxSnapshotJSObjectId() const {
10326 return ToInternal(this)->max_snapshot_js_object_id();
10327 }
10328
Serialize(OutputStream * stream,HeapSnapshot::SerializationFormat format) const10329 void HeapSnapshot::Serialize(OutputStream* stream,
10330 HeapSnapshot::SerializationFormat format) const {
10331 Utils::ApiCheck(format == kJSON, "v8::HeapSnapshot::Serialize",
10332 "Unknown serialization format");
10333 Utils::ApiCheck(stream->GetChunkSize() > 0, "v8::HeapSnapshot::Serialize",
10334 "Invalid stream chunk size");
10335 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
10336 serializer.Serialize(stream);
10337 }
10338
10339 // static
10340 STATIC_CONST_MEMBER_DEFINITION const SnapshotObjectId
10341 HeapProfiler::kUnknownObjectId;
10342
GetSnapshotCount()10343 int HeapProfiler::GetSnapshotCount() {
10344 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotsCount();
10345 }
10346
GetHeapSnapshot(int index)10347 const HeapSnapshot* HeapProfiler::GetHeapSnapshot(int index) {
10348 return reinterpret_cast<const HeapSnapshot*>(
10349 reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshot(index));
10350 }
10351
GetObjectId(Local<Value> value)10352 SnapshotObjectId HeapProfiler::GetObjectId(Local<Value> value) {
10353 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
10354 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj);
10355 }
10356
GetObjectId(NativeObject value)10357 SnapshotObjectId HeapProfiler::GetObjectId(NativeObject value) {
10358 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(value);
10359 }
10360
FindObjectById(SnapshotObjectId id)10361 Local<Value> HeapProfiler::FindObjectById(SnapshotObjectId id) {
10362 i::Handle<i::Object> obj =
10363 reinterpret_cast<i::HeapProfiler*>(this)->FindHeapObjectById(id);
10364 if (obj.is_null()) return Local<Value>();
10365 return Utils::ToLocal(obj);
10366 }
10367
ClearObjectIds()10368 void HeapProfiler::ClearObjectIds() {
10369 reinterpret_cast<i::HeapProfiler*>(this)->ClearHeapObjectMap();
10370 }
10371
TakeHeapSnapshot(ActivityControl * control,ObjectNameResolver * resolver,bool treat_global_objects_as_roots,bool capture_numeric_value)10372 const HeapSnapshot* HeapProfiler::TakeHeapSnapshot(
10373 ActivityControl* control, ObjectNameResolver* resolver,
10374 bool treat_global_objects_as_roots, bool capture_numeric_value) {
10375 return reinterpret_cast<const HeapSnapshot*>(
10376 reinterpret_cast<i::HeapProfiler*>(this)->TakeSnapshot(
10377 control, resolver, treat_global_objects_as_roots,
10378 capture_numeric_value));
10379 }
10380
StartTrackingHeapObjects(bool track_allocations)10381 void HeapProfiler::StartTrackingHeapObjects(bool track_allocations) {
10382 reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTracking(
10383 track_allocations);
10384 }
10385
StopTrackingHeapObjects()10386 void HeapProfiler::StopTrackingHeapObjects() {
10387 reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTracking();
10388 }
10389
GetHeapStats(OutputStream * stream,int64_t * timestamp_us)10390 SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream,
10391 int64_t* timestamp_us) {
10392 i::HeapProfiler* heap_profiler = reinterpret_cast<i::HeapProfiler*>(this);
10393 return heap_profiler->PushHeapObjectsStats(stream, timestamp_us);
10394 }
10395
StartSamplingHeapProfiler(uint64_t sample_interval,int stack_depth,SamplingFlags flags)10396 bool HeapProfiler::StartSamplingHeapProfiler(uint64_t sample_interval,
10397 int stack_depth,
10398 SamplingFlags flags) {
10399 return reinterpret_cast<i::HeapProfiler*>(this)->StartSamplingHeapProfiler(
10400 sample_interval, stack_depth, flags);
10401 }
10402
StopSamplingHeapProfiler()10403 void HeapProfiler::StopSamplingHeapProfiler() {
10404 reinterpret_cast<i::HeapProfiler*>(this)->StopSamplingHeapProfiler();
10405 }
10406
GetAllocationProfile()10407 AllocationProfile* HeapProfiler::GetAllocationProfile() {
10408 return reinterpret_cast<i::HeapProfiler*>(this)->GetAllocationProfile();
10409 }
10410
DeleteAllHeapSnapshots()10411 void HeapProfiler::DeleteAllHeapSnapshots() {
10412 reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots();
10413 }
10414
AddBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback,void * data)10415 void HeapProfiler::AddBuildEmbedderGraphCallback(
10416 BuildEmbedderGraphCallback callback, void* data) {
10417 reinterpret_cast<i::HeapProfiler*>(this)->AddBuildEmbedderGraphCallback(
10418 callback, data);
10419 }
10420
RemoveBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback,void * data)10421 void HeapProfiler::RemoveBuildEmbedderGraphCallback(
10422 BuildEmbedderGraphCallback callback, void* data) {
10423 reinterpret_cast<i::HeapProfiler*>(this)->RemoveBuildEmbedderGraphCallback(
10424 callback, data);
10425 }
10426
SetGetDetachednessCallback(GetDetachednessCallback callback,void * data)10427 void HeapProfiler::SetGetDetachednessCallback(GetDetachednessCallback callback,
10428 void* data) {
10429 reinterpret_cast<i::HeapProfiler*>(this)->SetGetDetachednessCallback(callback,
10430 data);
10431 }
10432
SetStackStart(void * stack_start)10433 void EmbedderHeapTracer::SetStackStart(void* stack_start) {
10434 CHECK(isolate_);
10435 reinterpret_cast<i::Isolate*>(isolate_)->global_handles()->SetStackStart(
10436 stack_start);
10437 }
10438
FinalizeTracing()10439 void EmbedderHeapTracer::FinalizeTracing() {
10440 if (isolate_) {
10441 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(isolate_);
10442 if (isolate->heap()->incremental_marking()->IsMarking()) {
10443 isolate->heap()->FinalizeIncrementalMarkingAtomically(
10444 i::GarbageCollectionReason::kExternalFinalize);
10445 }
10446 }
10447 }
10448
IncreaseAllocatedSize(size_t bytes)10449 void EmbedderHeapTracer::IncreaseAllocatedSize(size_t bytes) {
10450 if (isolate_) {
10451 i::LocalEmbedderHeapTracer* const tracer =
10452 reinterpret_cast<i::Isolate*>(isolate_)
10453 ->heap()
10454 ->local_embedder_heap_tracer();
10455 DCHECK_NOT_NULL(tracer);
10456 tracer->IncreaseAllocatedSize(bytes);
10457 }
10458 }
10459
DecreaseAllocatedSize(size_t bytes)10460 void EmbedderHeapTracer::DecreaseAllocatedSize(size_t bytes) {
10461 if (isolate_) {
10462 i::LocalEmbedderHeapTracer* const tracer =
10463 reinterpret_cast<i::Isolate*>(isolate_)
10464 ->heap()
10465 ->local_embedder_heap_tracer();
10466 DCHECK_NOT_NULL(tracer);
10467 tracer->DecreaseAllocatedSize(bytes);
10468 }
10469 }
10470
RegisterEmbedderReference(const BasicTracedReference<v8::Data> & ref)10471 void EmbedderHeapTracer::RegisterEmbedderReference(
10472 const BasicTracedReference<v8::Data>& ref) {
10473 if (ref.IsEmpty()) return;
10474
10475 i::Heap* const heap = reinterpret_cast<i::Isolate*>(isolate_)->heap();
10476 heap->RegisterExternallyReferencedObject(
10477 reinterpret_cast<i::Address*>(ref.val_));
10478 }
10479
IterateTracedGlobalHandles(TracedGlobalHandleVisitor * visitor)10480 void EmbedderHeapTracer::IterateTracedGlobalHandles(
10481 TracedGlobalHandleVisitor* visitor) {
10482 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(isolate_);
10483 i::DisallowGarbageCollection no_gc;
10484 isolate->global_handles()->IterateTracedNodes(visitor);
10485 }
10486
IsRootForNonTracingGC(const v8::TracedReference<v8::Value> & handle)10487 bool EmbedderHeapTracer::IsRootForNonTracingGC(
10488 const v8::TracedReference<v8::Value>& handle) {
10489 return true;
10490 }
10491
ResetHandleInNonTracingGC(const v8::TracedReference<v8::Value> & handle)10492 void EmbedderHeapTracer::ResetHandleInNonTracingGC(
10493 const v8::TracedReference<v8::Value>& handle) {
10494 UNREACHABLE();
10495 }
10496
EmbedderStateScope(Isolate * isolate,Local<v8::Context> context,EmbedderStateTag tag)10497 EmbedderStateScope::EmbedderStateScope(Isolate* isolate,
10498 Local<v8::Context> context,
10499 EmbedderStateTag tag)
10500 : embedder_state_(new internal::EmbedderState(isolate, context, tag)) {}
10501
10502 // std::unique_ptr's destructor is not compatible with Forward declared
10503 // EmbedderState class.
10504 // Default destructor must be defined in implementation file.
10505 EmbedderStateScope::~EmbedderStateScope() = default;
10506
CheckValue() const10507 void TracedReferenceBase::CheckValue() const {
10508 #ifdef V8_HOST_ARCH_64_BIT
10509 if (!val_) return;
10510
10511 CHECK_NE(internal::kGlobalHandleZapValue, *reinterpret_cast<uint64_t*>(val_));
10512 #endif // V8_HOST_ARCH_64_BIT
10513 }
10514
CFunction(const void * address,const CFunctionInfo * type_info)10515 CFunction::CFunction(const void* address, const CFunctionInfo* type_info)
10516 : address_(address), type_info_(type_info) {
10517 CHECK_NOT_NULL(address_);
10518 CHECK_NOT_NULL(type_info_);
10519 }
10520
CFunctionInfo(const CTypeInfo & return_info,unsigned int arg_count,const CTypeInfo * arg_info)10521 CFunctionInfo::CFunctionInfo(const CTypeInfo& return_info,
10522 unsigned int arg_count, const CTypeInfo* arg_info)
10523 : return_info_(return_info), arg_count_(arg_count), arg_info_(arg_info) {
10524 if (arg_count_ > 0) {
10525 for (unsigned int i = 0; i < arg_count_ - 1; ++i) {
10526 DCHECK(arg_info_[i].GetType() != CTypeInfo::kCallbackOptionsType);
10527 }
10528 }
10529 }
10530
ArgumentInfo(unsigned int index) const10531 const CTypeInfo& CFunctionInfo::ArgumentInfo(unsigned int index) const {
10532 DCHECK_LT(index, ArgumentCount());
10533 return arg_info_[index];
10534 }
10535
ValidateIndex(size_t index) const10536 void FastApiTypedArrayBase::ValidateIndex(size_t index) const {
10537 DCHECK_LT(index, length_);
10538 }
10539
RegisterState()10540 RegisterState::RegisterState()
10541 : pc(nullptr), sp(nullptr), fp(nullptr), lr(nullptr) {}
10542 RegisterState::~RegisterState() = default;
10543
RegisterState(const RegisterState & other)10544 RegisterState::RegisterState(const RegisterState& other) { *this = other; }
10545
operator =(const RegisterState & other)10546 RegisterState& RegisterState::operator=(const RegisterState& other) {
10547 if (&other != this) {
10548 pc = other.pc;
10549 sp = other.sp;
10550 fp = other.fp;
10551 lr = other.lr;
10552 if (other.callee_saved) {
10553 // Make a deep copy if {other.callee_saved} is non-null.
10554 callee_saved =
10555 std::make_unique<CalleeSavedRegisters>(*(other.callee_saved));
10556 } else {
10557 // Otherwise, set {callee_saved} to null to match {other}.
10558 callee_saved.reset();
10559 }
10560 }
10561 return *this;
10562 }
10563
10564 #if !V8_ENABLE_WEBASSEMBLY
10565 // If WebAssembly is disabled, we still need to provide an implementation of the
10566 // WasmStreaming API. Since {WasmStreaming::Unpack} will always fail, all
10567 // methods are unreachable.
10568
10569 class WasmStreaming::WasmStreamingImpl {};
10570
WasmStreaming(std::unique_ptr<WasmStreamingImpl>)10571 WasmStreaming::WasmStreaming(std::unique_ptr<WasmStreamingImpl>) {
10572 UNREACHABLE();
10573 }
10574
10575 WasmStreaming::~WasmStreaming() = default;
10576
OnBytesReceived(const uint8_t * bytes,size_t size)10577 void WasmStreaming::OnBytesReceived(const uint8_t* bytes, size_t size) {
10578 UNREACHABLE();
10579 }
10580
Finish(bool can_use_compiled_module)10581 void WasmStreaming::Finish(bool can_use_compiled_module) { UNREACHABLE(); }
10582
Abort(MaybeLocal<Value> exception)10583 void WasmStreaming::Abort(MaybeLocal<Value> exception) { UNREACHABLE(); }
10584
SetCompiledModuleBytes(const uint8_t * bytes,size_t size)10585 bool WasmStreaming::SetCompiledModuleBytes(const uint8_t* bytes, size_t size) {
10586 UNREACHABLE();
10587 }
10588
SetClient(std::shared_ptr<Client> client)10589 void WasmStreaming::SetClient(std::shared_ptr<Client> client) { UNREACHABLE(); }
10590
SetUrl(const char * url,size_t length)10591 void WasmStreaming::SetUrl(const char* url, size_t length) { UNREACHABLE(); }
10592
10593 // static
Unpack(Isolate * isolate,Local<Value> value)10594 std::shared_ptr<WasmStreaming> WasmStreaming::Unpack(Isolate* isolate,
10595 Local<Value> value) {
10596 FATAL("WebAssembly is disabled");
10597 }
10598 #endif // !V8_ENABLE_WEBASSEMBLY
10599
10600 namespace internal {
10601
10602 const size_t HandleScopeImplementer::kEnteredContextsOffset =
10603 offsetof(HandleScopeImplementer, entered_contexts_);
10604 const size_t HandleScopeImplementer::kIsMicrotaskContextOffset =
10605 offsetof(HandleScopeImplementer, is_microtask_context_);
10606
FreeThreadResources()10607 void HandleScopeImplementer::FreeThreadResources() { Free(); }
10608
ArchiveThread(char * storage)10609 char* HandleScopeImplementer::ArchiveThread(char* storage) {
10610 HandleScopeData* current = isolate_->handle_scope_data();
10611 handle_scope_data_ = *current;
10612 MemCopy(storage, this, sizeof(*this));
10613
10614 ResetAfterArchive();
10615 current->Initialize();
10616
10617 return storage + ArchiveSpacePerThread();
10618 }
10619
ArchiveSpacePerThread()10620 int HandleScopeImplementer::ArchiveSpacePerThread() {
10621 return sizeof(HandleScopeImplementer);
10622 }
10623
RestoreThread(char * storage)10624 char* HandleScopeImplementer::RestoreThread(char* storage) {
10625 MemCopy(this, storage, sizeof(*this));
10626 *isolate_->handle_scope_data() = handle_scope_data_;
10627 return storage + ArchiveSpacePerThread();
10628 }
10629
IterateThis(RootVisitor * v)10630 void HandleScopeImplementer::IterateThis(RootVisitor* v) {
10631 #ifdef DEBUG
10632 bool found_block_before_deferred = false;
10633 #endif
10634 // Iterate over all handles in the blocks except for the last.
10635 for (int i = static_cast<int>(blocks()->size()) - 2; i >= 0; --i) {
10636 Address* block = blocks()->at(i);
10637 // Cast possibly-unrelated pointers to plain Address before comparing them
10638 // to avoid undefined behavior.
10639 if (last_handle_before_deferred_block_ != nullptr &&
10640 (reinterpret_cast<Address>(last_handle_before_deferred_block_) <=
10641 reinterpret_cast<Address>(&block[kHandleBlockSize])) &&
10642 (reinterpret_cast<Address>(last_handle_before_deferred_block_) >=
10643 reinterpret_cast<Address>(block))) {
10644 v->VisitRootPointers(Root::kHandleScope, nullptr, FullObjectSlot(block),
10645 FullObjectSlot(last_handle_before_deferred_block_));
10646 DCHECK(!found_block_before_deferred);
10647 #ifdef DEBUG
10648 found_block_before_deferred = true;
10649 #endif
10650 } else {
10651 v->VisitRootPointers(Root::kHandleScope, nullptr, FullObjectSlot(block),
10652 FullObjectSlot(&block[kHandleBlockSize]));
10653 }
10654 }
10655
10656 DCHECK(last_handle_before_deferred_block_ == nullptr ||
10657 found_block_before_deferred);
10658
10659 // Iterate over live handles in the last block (if any).
10660 if (!blocks()->empty()) {
10661 v->VisitRootPointers(Root::kHandleScope, nullptr,
10662 FullObjectSlot(blocks()->back()),
10663 FullObjectSlot(handle_scope_data_.next));
10664 }
10665
10666 DetachableVector<Context>* context_lists[2] = {&saved_contexts_,
10667 &entered_contexts_};
10668 for (unsigned i = 0; i < arraysize(context_lists); i++) {
10669 context_lists[i]->shrink_to_fit();
10670 if (context_lists[i]->empty()) continue;
10671 FullObjectSlot start(&context_lists[i]->front());
10672 v->VisitRootPointers(Root::kHandleScope, nullptr, start,
10673 start + static_cast<int>(context_lists[i]->size()));
10674 }
10675 // The shape of |entered_contexts_| and |is_microtask_context_| stacks must
10676 // be in sync.
10677 is_microtask_context_.shrink_to_fit();
10678 DCHECK_EQ(entered_contexts_.capacity(), is_microtask_context_.capacity());
10679 DCHECK_EQ(entered_contexts_.size(), is_microtask_context_.size());
10680 }
10681
Iterate(RootVisitor * v)10682 void HandleScopeImplementer::Iterate(RootVisitor* v) {
10683 HandleScopeData* current = isolate_->handle_scope_data();
10684 handle_scope_data_ = *current;
10685 IterateThis(v);
10686 }
10687
Iterate(RootVisitor * v,char * storage)10688 char* HandleScopeImplementer::Iterate(RootVisitor* v, char* storage) {
10689 HandleScopeImplementer* scope_implementer =
10690 reinterpret_cast<HandleScopeImplementer*>(storage);
10691 scope_implementer->IterateThis(v);
10692 return storage + ArchiveSpacePerThread();
10693 }
10694
DetachPersistent(Address * prev_limit)10695 std::unique_ptr<PersistentHandles> HandleScopeImplementer::DetachPersistent(
10696 Address* prev_limit) {
10697 std::unique_ptr<PersistentHandles> ph(new PersistentHandles(isolate()));
10698 DCHECK_NOT_NULL(prev_limit);
10699
10700 while (!blocks_.empty()) {
10701 Address* block_start = blocks_.back();
10702 Address* block_limit = &block_start[kHandleBlockSize];
10703 // We should not need to check for SealHandleScope here. Assert this.
10704 DCHECK_IMPLIES(block_start <= prev_limit && prev_limit <= block_limit,
10705 prev_limit == block_limit);
10706 if (prev_limit == block_limit) break;
10707 ph->blocks_.push_back(blocks_.back());
10708 #if DEBUG
10709 ph->ordered_blocks_.insert(blocks_.back());
10710 #endif
10711 blocks_.pop_back();
10712 }
10713
10714 // ph->blocks_ now contains the blocks installed on the
10715 // HandleScope stack since BeginDeferredScope was called, but in
10716 // reverse order.
10717
10718 // Switch first and last blocks, such that the last block is the one
10719 // that is potentially half full.
10720 DCHECK(!blocks_.empty() && !ph->blocks_.empty());
10721 std::swap(ph->blocks_.front(), ph->blocks_.back());
10722
10723 ph->block_next_ = isolate()->handle_scope_data()->next;
10724 Address* block_start = ph->blocks_.back();
10725 ph->block_limit_ = block_start + kHandleBlockSize;
10726
10727 DCHECK_NOT_NULL(last_handle_before_deferred_block_);
10728 last_handle_before_deferred_block_ = nullptr;
10729 return ph;
10730 }
10731
BeginDeferredScope()10732 void HandleScopeImplementer::BeginDeferredScope() {
10733 DCHECK_NULL(last_handle_before_deferred_block_);
10734 last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next;
10735 }
10736
InvokeAccessorGetterCallback(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Value> & info,v8::AccessorNameGetterCallback getter)10737 void InvokeAccessorGetterCallback(
10738 v8::Local<v8::Name> property,
10739 const v8::PropertyCallbackInfo<v8::Value>& info,
10740 v8::AccessorNameGetterCallback getter) {
10741 // Leaving JavaScript.
10742 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
10743 RCS_SCOPE(isolate, RuntimeCallCounterId::kAccessorGetterCallback);
10744 Address getter_address = reinterpret_cast<Address>(getter);
10745 ExternalCallbackScope call_scope(isolate, getter_address);
10746 getter(property, info);
10747 }
10748
InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value> & info,v8::FunctionCallback callback)10749 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
10750 v8::FunctionCallback callback) {
10751 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
10752 RCS_SCOPE(isolate, RuntimeCallCounterId::kFunctionCallback);
10753 Address callback_address = reinterpret_cast<Address>(callback);
10754 ExternalCallbackScope call_scope(isolate, callback_address);
10755 callback(info);
10756 }
10757
InvokeFinalizationRegistryCleanupFromTask(Handle<Context> context,Handle<JSFinalizationRegistry> finalization_registry,Handle<Object> callback)10758 void InvokeFinalizationRegistryCleanupFromTask(
10759 Handle<Context> context,
10760 Handle<JSFinalizationRegistry> finalization_registry,
10761 Handle<Object> callback) {
10762 Isolate* isolate = finalization_registry->native_context().GetIsolate();
10763 RCS_SCOPE(isolate,
10764 RuntimeCallCounterId::kFinalizationRegistryCleanupFromTask);
10765 // Do not use ENTER_V8 because this is always called from a running
10766 // FinalizationRegistryCleanupTask within V8 and we should not log it as an
10767 // API call. This method is implemented here to avoid duplication of the
10768 // exception handling and microtask running logic in CallDepthScope.
10769 if (IsExecutionTerminatingCheck(isolate)) return;
10770 Local<v8::Context> api_context = Utils::ToLocal(context);
10771 CallDepthScope<true> call_depth_scope(isolate, api_context);
10772 VMState<OTHER> state(isolate);
10773 Handle<Object> argv[] = {callback};
10774 if (Execution::CallBuiltin(isolate,
10775 isolate->finalization_registry_cleanup_some(),
10776 finalization_registry, arraysize(argv), argv)
10777 .is_null()) {
10778 call_depth_scope.Escape();
10779 }
10780 }
10781
10782 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10783 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10784 int32_t ConvertDouble(double d) {
10785 return internal::DoubleToInt32(d);
10786 }
10787
10788 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10789 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10790 uint32_t ConvertDouble(double d) {
10791 return internal::DoubleToUint32(d);
10792 }
10793
10794 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10795 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10796 float ConvertDouble(double d) {
10797 return internal::DoubleToFloat32(d);
10798 }
10799
10800 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10801 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10802 double ConvertDouble(double d) {
10803 return d;
10804 }
10805
10806 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10807 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10808 int64_t ConvertDouble(double d) {
10809 return internal::DoubleToWebIDLInt64(d);
10810 }
10811
10812 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10813 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10814 uint64_t ConvertDouble(double d) {
10815 return internal::DoubleToWebIDLUint64(d);
10816 }
10817
10818 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10819 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10820 bool ConvertDouble(double d) {
10821 // Implements https://tc39.es/ecma262/#sec-toboolean.
10822 return !std::isnan(d) && d != 0;
10823 }
10824
10825 // Undefine macros for jumbo build.
10826 #undef SET_FIELD_WRAPPED
10827 #undef NEW_STRING
10828 #undef CALLBACK_SETTER
10829
10830 } // namespace internal
10831
10832 template <>
10833 bool V8_EXPORT V8_WARN_UNUSED_RESULT
TryToCopyAndConvertArrayToCppBuffer(Local<Array> src,int32_t * dst,uint32_t max_length)10834 TryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<int32_t>::Build().GetId(),
10835 int32_t>(Local<Array> src, int32_t* dst,
10836 uint32_t max_length) {
10837 return CopyAndConvertArrayToCppBuffer<
10838 CTypeInfo(CTypeInfo::Type::kInt32, CTypeInfo::SequenceType::kIsSequence)
10839 .GetId(),
10840 int32_t>(src, dst, max_length);
10841 }
10842
10843 template <>
10844 bool V8_EXPORT V8_WARN_UNUSED_RESULT
TryToCopyAndConvertArrayToCppBuffer(Local<Array> src,uint32_t * dst,uint32_t max_length)10845 TryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<uint32_t>::Build().GetId(),
10846 uint32_t>(Local<Array> src, uint32_t* dst,
10847 uint32_t max_length) {
10848 return CopyAndConvertArrayToCppBuffer<
10849 CTypeInfo(CTypeInfo::Type::kUint32, CTypeInfo::SequenceType::kIsSequence)
10850 .GetId(),
10851 uint32_t>(src, dst, max_length);
10852 }
10853
10854 template <>
10855 bool V8_EXPORT V8_WARN_UNUSED_RESULT
TryToCopyAndConvertArrayToCppBuffer(Local<Array> src,float * dst,uint32_t max_length)10856 TryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<float>::Build().GetId(),
10857 float>(Local<Array> src, float* dst,
10858 uint32_t max_length) {
10859 return CopyAndConvertArrayToCppBuffer<
10860 CTypeInfo(CTypeInfo::Type::kFloat32, CTypeInfo::SequenceType::kIsSequence)
10861 .GetId(),
10862 float>(src, dst, max_length);
10863 }
10864
10865 template <>
10866 bool V8_EXPORT V8_WARN_UNUSED_RESULT
TryToCopyAndConvertArrayToCppBuffer(Local<Array> src,double * dst,uint32_t max_length)10867 TryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<double>::Build().GetId(),
10868 double>(Local<Array> src, double* dst,
10869 uint32_t max_length) {
10870 return CopyAndConvertArrayToCppBuffer<
10871 CTypeInfo(CTypeInfo::Type::kFloat64, CTypeInfo::SequenceType::kIsSequence)
10872 .GetId(),
10873 double>(src, dst, max_length);
10874 }
10875
10876 } // namespace v8
10877
10878 #undef TRACE_BS
10879 #include "src/api/api-macros-undef.h"
10880