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-extension.h"
19 #include "include/v8-fast-api-calls.h"
20 #include "include/v8-function.h"
21 #include "include/v8-json.h"
22 #include "include/v8-locker.h"
23 #include "include/v8-primitive-object.h"
24 #include "include/v8-profiler.h"
25 #include "include/v8-unwinder-state.h"
26 #include "include/v8-util.h"
27 #include "include/v8-wasm.h"
28 #include "src/api/api-inl.h"
29 #include "src/api/api-natives.h"
30 #include "src/base/functional.h"
31 #include "src/base/logging.h"
32 #include "src/base/platform/platform.h"
33 #include "src/base/platform/time.h"
34 #include "src/base/safe_conversions.h"
35 #include "src/base/utils/random-number-generator.h"
36 #include "src/baseline/baseline-batch-compiler.h"
37 #include "src/builtins/accessors.h"
38 #include "src/builtins/builtins-utils.h"
39 #include "src/codegen/compiler.h"
40 #include "src/codegen/cpu-features.h"
41 #include "src/codegen/script-details.h"
42 #include "src/common/assert-scope.h"
43 #include "src/common/external-pointer.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/debug/liveedit.h"
48 #include "src/deoptimizer/deoptimizer.h"
49 #include "src/diagnostics/gdb-jit.h"
50 #include "src/execution/execution.h"
51 #include "src/execution/frames-inl.h"
52 #include "src/execution/isolate-inl.h"
53 #include "src/execution/messages.h"
54 #include "src/execution/microtask-queue.h"
55 #include "src/execution/runtime-profiler.h"
56 #include "src/execution/simulator.h"
57 #include "src/execution/v8threads.h"
58 #include "src/execution/vm-state-inl.h"
59 #include "src/handles/global-handles.h"
60 #include "src/handles/persistent-handles.h"
61 #include "src/heap/embedder-tracing.h"
62 #include "src/heap/heap-inl.h"
63 #include "src/init/bootstrapper.h"
64 #include "src/init/icu_util.h"
65 #include "src/init/startup-data-util.h"
66 #include "src/init/v8.h"
67 #include "src/init/vm-cage.h"
68 #include "src/json/json-parser.h"
69 #include "src/json/json-stringifier.h"
70 #include "src/logging/counters-scopes.h"
71 #include "src/logging/metrics.h"
72 #include "src/logging/runtime-call-stats-scope.h"
73 #include "src/logging/tracing-flags.h"
74 #include "src/numbers/conversions-inl.h"
75 #include "src/objects/api-callbacks.h"
76 #include "src/objects/contexts.h"
77 #include "src/objects/embedder-data-array-inl.h"
78 #include "src/objects/embedder-data-slot-inl.h"
79 #include "src/objects/hash-table-inl.h"
80 #include "src/objects/heap-object.h"
81 #include "src/objects/js-array-buffer-inl.h"
82 #include "src/objects/js-array-inl.h"
83 #include "src/objects/js-collection-inl.h"
84 #include "src/objects/js-promise-inl.h"
85 #include "src/objects/js-regexp-inl.h"
86 #include "src/objects/js-weak-refs-inl.h"
87 #include "src/objects/module-inl.h"
88 #include "src/objects/objects-inl.h"
89 #include "src/objects/oddball.h"
90 #include "src/objects/ordered-hash-table-inl.h"
91 #include "src/objects/property-descriptor.h"
92 #include "src/objects/property-details.h"
93 #include "src/objects/property.h"
94 #include "src/objects/prototype.h"
95 #include "src/objects/shared-function-info.h"
96 #include "src/objects/slots.h"
97 #include "src/objects/smi.h"
98 #include "src/objects/stack-frame-info-inl.h"
99 #include "src/objects/synthetic-module-inl.h"
100 #include "src/objects/templates.h"
101 #include "src/objects/value-serializer.h"
102 #include "src/parsing/parse-info.h"
103 #include "src/parsing/parser.h"
104 #include "src/parsing/pending-compilation-error-handler.h"
105 #include "src/parsing/scanner-character-streams.h"
106 #include "src/profiler/cpu-profiler.h"
107 #include "src/profiler/heap-profiler.h"
108 #include "src/profiler/heap-snapshot-generator-inl.h"
109 #include "src/profiler/profile-generator-inl.h"
110 #include "src/profiler/tick-sample.h"
111 #include "src/regexp/regexp-utils.h"
112 #include "src/runtime/runtime.h"
113 #include "src/snapshot/code-serializer.h"
114 #include "src/snapshot/embedded/embedded-data.h"
115 #include "src/snapshot/snapshot.h"
116 #include "src/snapshot/startup-serializer.h" // For SerializedHandleChecker.
117 #include "src/strings/char-predicates-inl.h"
118 #include "src/strings/string-hasher.h"
119 #include "src/strings/unicode-inl.h"
120 #include "src/tracing/trace-event.h"
121 #include "src/utils/detachable-vector.h"
122 #include "src/utils/version.h"
123
124 #if V8_ENABLE_WEBASSEMBLY
125 #include "src/trap-handler/trap-handler.h"
126 #include "src/wasm/streaming-decoder.h"
127 #include "src/wasm/value-type.h"
128 #include "src/wasm/wasm-engine.h"
129 #include "src/wasm/wasm-js.h"
130 #include "src/wasm/wasm-objects-inl.h"
131 #include "src/wasm/wasm-result.h"
132 #include "src/wasm/wasm-serialization.h"
133 #endif // V8_ENABLE_WEBASSEMBLY
134
135 #if V8_OS_LINUX || V8_OS_MACOSX || V8_OS_FREEBSD
136 #include <signal.h>
137 #include "include/v8-wasm-trap-handler-posix.h"
138 #include "src/trap-handler/handler-inside-posix.h"
139 #endif
140
141 #if V8_OS_WIN
142 #include <windows.h>
143
144 // This has to come after windows.h.
145 #include <versionhelpers.h>
146
147 #include "include/v8-wasm-trap-handler-win.h"
148 #include "src/trap-handler/handler-inside-win.h"
149 #if defined(V8_OS_WIN64)
150 #include "src/base/platform/wrappers.h"
151 #include "src/diagnostics/unwinding-info-win64.h"
152 #endif // V8_OS_WIN64
153 #if defined(V8_ENABLE_SYSTEM_INSTRUMENTATION)
154 #include "src/diagnostics/system-jit-win.h"
155 #endif
156 #endif // V8_OS_WIN
157
158 // Has to be the last include (doesn't have include guards):
159 #include "src/api/api-macros.h"
160
161 #define TRACE_BS(...) \
162 do { \
163 if (i::FLAG_trace_backing_store) PrintF(__VA_ARGS__); \
164 } while (false)
165
166 namespace v8 {
167
GetScriptOriginForScript(i::Isolate * isolate,i::Handle<i::Script> script)168 static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate,
169 i::Handle<i::Script> script) {
170 i::Handle<i::Object> scriptName(script->GetNameOrSourceURL(), isolate);
171 i::Handle<i::Object> source_map_url(script->source_mapping_url(), isolate);
172 i::Handle<i::FixedArray> host_defined_options(script->host_defined_options(),
173 isolate);
174 ScriptOriginOptions options(script->origin_options());
175 bool is_wasm = false;
176 #if V8_ENABLE_WEBASSEMBLY
177 is_wasm = script->type() == i::Script::TYPE_WASM;
178 #endif // V8_ENABLE_WEBASSEMBLY
179 v8::ScriptOrigin origin(
180 reinterpret_cast<v8::Isolate*>(isolate), Utils::ToLocal(scriptName),
181 script->line_offset(), script->column_offset(),
182 options.IsSharedCrossOrigin(), script->id(),
183 Utils::ToLocal(source_map_url), options.IsOpaque(), is_wasm,
184 options.IsModule(), Utils::PrimitiveArrayToLocal(host_defined_options));
185 return origin;
186 }
187
ScriptOrigin(Local<Value> resource_name,Local<Integer> line_offset,Local<Integer> column_offset,Local<Boolean> is_shared_cross_origin,Local<Integer> script_id,Local<Value> source_map_url,Local<Boolean> is_opaque,Local<Boolean> is_wasm,Local<Boolean> is_module,Local<PrimitiveArray> host_defined_options)188 ScriptOrigin::ScriptOrigin(
189 Local<Value> resource_name, Local<Integer> line_offset,
190 Local<Integer> column_offset, Local<Boolean> is_shared_cross_origin,
191 Local<Integer> script_id, Local<Value> source_map_url,
192 Local<Boolean> is_opaque, Local<Boolean> is_wasm, Local<Boolean> is_module,
193 Local<PrimitiveArray> host_defined_options)
194 : ScriptOrigin(
195 Isolate::GetCurrent(), resource_name,
196 line_offset.IsEmpty() ? 0 : static_cast<int>(line_offset->Value()),
197 column_offset.IsEmpty() ? 0
198 : static_cast<int>(column_offset->Value()),
199 !is_shared_cross_origin.IsEmpty() && is_shared_cross_origin->IsTrue(),
200 static_cast<int>(script_id.IsEmpty() ? -1 : script_id->Value()),
201 source_map_url, !is_opaque.IsEmpty() && is_opaque->IsTrue(),
202 !is_wasm.IsEmpty() && is_wasm->IsTrue(),
203 !is_module.IsEmpty() && is_module->IsTrue(), host_defined_options) {}
204
ScriptOrigin(Local<Value> resource_name,int line_offset,int column_offset,bool is_shared_cross_origin,int script_id,Local<Value> source_map_url,bool is_opaque,bool is_wasm,bool is_module,Local<PrimitiveArray> host_defined_options)205 ScriptOrigin::ScriptOrigin(Local<Value> resource_name, int line_offset,
206 int column_offset, bool is_shared_cross_origin,
207 int script_id, Local<Value> source_map_url,
208 bool is_opaque, bool is_wasm, bool is_module,
209 Local<PrimitiveArray> host_defined_options)
210 : isolate_(Isolate::GetCurrent()),
211 resource_name_(resource_name),
212 resource_line_offset_(line_offset),
213 resource_column_offset_(column_offset),
214 options_(is_shared_cross_origin, is_opaque, is_wasm, is_module),
215 script_id_(script_id),
216 source_map_url_(source_map_url),
217 host_defined_options_(host_defined_options) {}
218
ResourceLineOffset() const219 Local<Integer> ScriptOrigin::ResourceLineOffset() const {
220 return v8::Integer::New(isolate_, resource_line_offset_);
221 }
222
ResourceColumnOffset() const223 Local<Integer> ScriptOrigin::ResourceColumnOffset() const {
224 return v8::Integer::New(isolate_, resource_column_offset_);
225 }
226
ScriptID() const227 Local<Integer> ScriptOrigin::ScriptID() const {
228 return v8::Integer::New(isolate_, script_id_);
229 }
230
231 // --- E x c e p t i o n B e h a v i o r ---
232
FatalProcessOutOfMemory(i::Isolate * isolate,const char * location)233 void i::FatalProcessOutOfMemory(i::Isolate* isolate, const char* location) {
234 i::V8::FatalProcessOutOfMemory(isolate, location, false);
235 }
236
237 // When V8 cannot allocate memory FatalProcessOutOfMemory is called. The default
238 // OOM error handler is called and execution is stopped.
FatalProcessOutOfMemory(i::Isolate * isolate,const char * location,bool is_heap_oom)239 void i::V8::FatalProcessOutOfMemory(i::Isolate* isolate, const char* location,
240 bool is_heap_oom) {
241 char last_few_messages[Heap::kTraceRingBufferSize + 1];
242 char js_stacktrace[Heap::kStacktraceBufferSize + 1];
243 i::HeapStats heap_stats;
244
245 if (isolate == nullptr) {
246 isolate = Isolate::TryGetCurrent();
247 }
248
249 if (isolate == nullptr) {
250 // If the Isolate is not available for the current thread we cannot retrieve
251 // memory information from the Isolate. Write easy-to-recognize values on
252 // the stack.
253 memset(last_few_messages, 0x0BADC0DE, Heap::kTraceRingBufferSize + 1);
254 memset(js_stacktrace, 0x0BADC0DE, Heap::kStacktraceBufferSize + 1);
255 memset(&heap_stats, 0xBADC0DE, sizeof(heap_stats));
256 // Note that the embedder's oom handler is also not available and therefore
257 // won't be called in this case. We just crash.
258 FATAL("Fatal process out of memory: %s", location);
259 UNREACHABLE();
260 }
261
262 memset(last_few_messages, 0, Heap::kTraceRingBufferSize + 1);
263 memset(js_stacktrace, 0, Heap::kStacktraceBufferSize + 1);
264
265 intptr_t start_marker;
266 heap_stats.start_marker = &start_marker;
267 size_t ro_space_size;
268 heap_stats.ro_space_size = &ro_space_size;
269 size_t ro_space_capacity;
270 heap_stats.ro_space_capacity = &ro_space_capacity;
271 size_t new_space_size;
272 heap_stats.new_space_size = &new_space_size;
273 size_t new_space_capacity;
274 heap_stats.new_space_capacity = &new_space_capacity;
275 size_t old_space_size;
276 heap_stats.old_space_size = &old_space_size;
277 size_t old_space_capacity;
278 heap_stats.old_space_capacity = &old_space_capacity;
279 size_t code_space_size;
280 heap_stats.code_space_size = &code_space_size;
281 size_t code_space_capacity;
282 heap_stats.code_space_capacity = &code_space_capacity;
283 size_t map_space_size;
284 heap_stats.map_space_size = &map_space_size;
285 size_t map_space_capacity;
286 heap_stats.map_space_capacity = &map_space_capacity;
287 size_t lo_space_size;
288 heap_stats.lo_space_size = &lo_space_size;
289 size_t code_lo_space_size;
290 heap_stats.code_lo_space_size = &code_lo_space_size;
291 size_t global_handle_count;
292 heap_stats.global_handle_count = &global_handle_count;
293 size_t weak_global_handle_count;
294 heap_stats.weak_global_handle_count = &weak_global_handle_count;
295 size_t pending_global_handle_count;
296 heap_stats.pending_global_handle_count = &pending_global_handle_count;
297 size_t near_death_global_handle_count;
298 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
299 size_t free_global_handle_count;
300 heap_stats.free_global_handle_count = &free_global_handle_count;
301 size_t memory_allocator_size;
302 heap_stats.memory_allocator_size = &memory_allocator_size;
303 size_t memory_allocator_capacity;
304 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
305 size_t malloced_memory;
306 heap_stats.malloced_memory = &malloced_memory;
307 size_t malloced_peak_memory;
308 heap_stats.malloced_peak_memory = &malloced_peak_memory;
309 size_t objects_per_type[LAST_TYPE + 1] = {0};
310 heap_stats.objects_per_type = objects_per_type;
311 size_t size_per_type[LAST_TYPE + 1] = {0};
312 heap_stats.size_per_type = size_per_type;
313 int os_error;
314 heap_stats.os_error = &os_error;
315 heap_stats.last_few_messages = last_few_messages;
316 heap_stats.js_stacktrace = js_stacktrace;
317 intptr_t end_marker;
318 heap_stats.end_marker = &end_marker;
319 if (isolate->heap()->HasBeenSetUp()) {
320 // BUG(1718): Don't use the take_snapshot since we don't support
321 // HeapObjectIterator here without doing a special GC.
322 isolate->heap()->RecordStats(&heap_stats, false);
323 if (!FLAG_correctness_fuzzer_suppressions) {
324 char* first_newline = strchr(last_few_messages, '\n');
325 if (first_newline == nullptr || first_newline[1] == '\0')
326 first_newline = last_few_messages;
327 base::OS::PrintError("\n<--- Last few GCs --->\n%s\n", first_newline);
328 base::OS::PrintError("\n<--- JS stacktrace --->\n%s\n", js_stacktrace);
329 }
330 }
331 Utils::ReportOOMFailure(isolate, location, is_heap_oom);
332 // If the fatal error handler returns, we stop execution.
333 FATAL("API fatal error handler returned after process out of memory");
334 }
335
ReportApiFailure(const char * location,const char * message)336 void Utils::ReportApiFailure(const char* location, const char* message) {
337 i::Isolate* isolate = i::Isolate::TryGetCurrent();
338 FatalErrorCallback callback = nullptr;
339 if (isolate != nullptr) {
340 callback = isolate->exception_behavior();
341 }
342 if (callback == nullptr) {
343 base::OS::PrintError("\n#\n# Fatal error in %s\n# %s\n#\n\n", location,
344 message);
345 base::OS::Abort();
346 } else {
347 callback(location, message);
348 }
349 isolate->SignalFatalError();
350 }
351
ReportOOMFailure(i::Isolate * isolate,const char * location,bool is_heap_oom)352 void Utils::ReportOOMFailure(i::Isolate* isolate, const char* location,
353 bool is_heap_oom) {
354 OOMErrorCallback oom_callback = isolate->oom_behavior();
355 if (oom_callback == nullptr) {
356 // TODO(wfh): Remove this fallback once Blink is setting OOM handler. See
357 // crbug.com/614440.
358 FatalErrorCallback fatal_callback = isolate->exception_behavior();
359 if (fatal_callback == nullptr) {
360 base::OS::PrintError("\n#\n# Fatal %s OOM in %s\n#\n\n",
361 is_heap_oom ? "javascript" : "process", location);
362 #ifdef V8_FUZZILLI
363 exit(0);
364 #else
365 base::OS::Abort();
366 #endif // V8_FUZZILLI
367 } else {
368 fatal_callback(location,
369 is_heap_oom
370 ? "Allocation failed - JavaScript heap out of memory"
371 : "Allocation failed - process out of memory");
372 }
373 } else {
374 oom_callback(location, is_heap_oom);
375 }
376 isolate->SignalFatalError();
377 }
378
SetSnapshotDataBlob(StartupData * snapshot_blob)379 void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
380 i::V8::SetSnapshotBlob(snapshot_blob);
381 }
382
383 namespace {
384
385 #ifdef V8_VIRTUAL_MEMORY_CAGE
386 // ArrayBufferAllocator to use when the virtual memory cage is enabled, in which
387 // case all ArrayBuffer backing stores need to be allocated inside the data
388 // cage. Note, the current implementation is extremely inefficient as it uses
389 // the BoundedPageAllocator. In the future, we'll need a proper allocator
390 // implementation.
391 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
392 public:
ArrayBufferAllocator()393 ArrayBufferAllocator() { CHECK(page_allocator_); }
394
Allocate(size_t length)395 void* Allocate(size_t length) override {
396 return page_allocator_->AllocatePages(nullptr, RoundUp(length, page_size_),
397 page_size_,
398 PageAllocator::kReadWrite);
399 }
400
AllocateUninitialized(size_t length)401 void* AllocateUninitialized(size_t length) override {
402 return Allocate(length);
403 }
404
Free(void * data,size_t length)405 void Free(void* data, size_t length) override {
406 page_allocator_->FreePages(data, RoundUp(length, page_size_));
407 }
408
409 private:
410 PageAllocator* page_allocator_ = internal::GetArrayBufferPageAllocator();
411 const size_t page_size_ = page_allocator_->AllocatePageSize();
412 };
413
414 #else
415
416 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
417 public:
418 void* Allocate(size_t length) override {
419 #if V8_OS_AIX && _LINUX_SOURCE_COMPAT
420 // Work around for GCC bug on AIX
421 // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
422 void* data = __linux_calloc(length, 1);
423 #else
424 void* data = base::Calloc(length, 1);
425 #endif
426 return data;
427 }
428
429 void* AllocateUninitialized(size_t length) override {
430 #if V8_OS_AIX && _LINUX_SOURCE_COMPAT
431 // Work around for GCC bug on AIX
432 // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
433 void* data = __linux_malloc(length);
434 #else
435 void* data = base::Malloc(length);
436 #endif
437 return data;
438 }
439
440 void Free(void* data, size_t) override { base::Free(data); }
441
442 void* Reallocate(void* data, size_t old_length, size_t new_length) override {
443 #if V8_OS_AIX && _LINUX_SOURCE_COMPAT
444 // Work around for GCC bug on AIX
445 // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
446 void* new_data = __linux_realloc(data, new_length);
447 #else
448 void* new_data = base::Realloc(data, new_length);
449 #endif
450 if (new_length > old_length) {
451 memset(reinterpret_cast<uint8_t*>(new_data) + old_length, 0,
452 new_length - old_length);
453 }
454 return new_data;
455 }
456 };
457 #endif // V8_VIRTUAL_MEMORY_CAGE
458
459 struct SnapshotCreatorData {
SnapshotCreatorDatav8::__anon68be8ea50111::SnapshotCreatorData460 explicit SnapshotCreatorData(Isolate* isolate)
461 : isolate_(isolate),
462 default_context_(),
463 contexts_(isolate),
464 created_(false) {}
465
castv8::__anon68be8ea50111::SnapshotCreatorData466 static SnapshotCreatorData* cast(void* data) {
467 return reinterpret_cast<SnapshotCreatorData*>(data);
468 }
469
470 ArrayBufferAllocator allocator_;
471 Isolate* isolate_;
472 Persistent<Context> default_context_;
473 SerializeInternalFieldsCallback default_embedder_fields_serializer_;
474 PersistentValueVector<Context> contexts_;
475 std::vector<SerializeInternalFieldsCallback> embedder_fields_serializers_;
476 bool created_;
477 };
478
479 } // namespace
480
SnapshotCreator(Isolate * isolate,const intptr_t * external_references,StartupData * existing_snapshot)481 SnapshotCreator::SnapshotCreator(Isolate* isolate,
482 const intptr_t* external_references,
483 StartupData* existing_snapshot) {
484 SnapshotCreatorData* data = new SnapshotCreatorData(isolate);
485 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
486 internal_isolate->set_array_buffer_allocator(&data->allocator_);
487 internal_isolate->set_api_external_references(external_references);
488 internal_isolate->enable_serializer();
489 isolate->Enter();
490 const StartupData* blob = existing_snapshot
491 ? existing_snapshot
492 : i::Snapshot::DefaultSnapshotBlob();
493 if (blob && blob->raw_size > 0) {
494 internal_isolate->set_snapshot_blob(blob);
495 i::Snapshot::Initialize(internal_isolate);
496 } else {
497 internal_isolate->InitWithoutSnapshot();
498 }
499 data_ = data;
500 // Disable batch compilation during snapshot creation.
501 internal_isolate->baseline_batch_compiler()->set_enabled(false);
502 }
503
SnapshotCreator(const intptr_t * external_references,StartupData * existing_snapshot)504 SnapshotCreator::SnapshotCreator(const intptr_t* external_references,
505 StartupData* existing_snapshot)
506 : SnapshotCreator(Isolate::Allocate(), external_references,
507 existing_snapshot) {}
508
~SnapshotCreator()509 SnapshotCreator::~SnapshotCreator() {
510 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
511 DCHECK(data->created_);
512 Isolate* isolate = data->isolate_;
513 isolate->Exit();
514 isolate->Dispose();
515 delete data;
516 }
517
GetIsolate()518 Isolate* SnapshotCreator::GetIsolate() {
519 return SnapshotCreatorData::cast(data_)->isolate_;
520 }
521
SetDefaultContext(Local<Context> context,SerializeInternalFieldsCallback callback)522 void SnapshotCreator::SetDefaultContext(
523 Local<Context> context, SerializeInternalFieldsCallback callback) {
524 DCHECK(!context.IsEmpty());
525 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
526 DCHECK(!data->created_);
527 DCHECK(data->default_context_.IsEmpty());
528 Isolate* isolate = data->isolate_;
529 CHECK_EQ(isolate, context->GetIsolate());
530 data->default_context_.Reset(isolate, context);
531 data->default_embedder_fields_serializer_ = callback;
532 }
533
AddContext(Local<Context> context,SerializeInternalFieldsCallback callback)534 size_t SnapshotCreator::AddContext(Local<Context> context,
535 SerializeInternalFieldsCallback callback) {
536 DCHECK(!context.IsEmpty());
537 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
538 DCHECK(!data->created_);
539 Isolate* isolate = data->isolate_;
540 CHECK_EQ(isolate, context->GetIsolate());
541 size_t index = data->contexts_.Size();
542 data->contexts_.Append(context);
543 data->embedder_fields_serializers_.push_back(callback);
544 return index;
545 }
546
AddData(i::Address object)547 size_t SnapshotCreator::AddData(i::Address object) {
548 DCHECK_NE(object, i::kNullAddress);
549 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
550 DCHECK(!data->created_);
551 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_);
552 i::HandleScope scope(isolate);
553 i::Handle<i::Object> obj(i::Object(object), isolate);
554 i::Handle<i::ArrayList> list;
555 if (!isolate->heap()->serialized_objects().IsArrayList()) {
556 list = i::ArrayList::New(isolate, 1);
557 } else {
558 list = i::Handle<i::ArrayList>(
559 i::ArrayList::cast(isolate->heap()->serialized_objects()), isolate);
560 }
561 size_t index = static_cast<size_t>(list->Length());
562 list = i::ArrayList::Add(isolate, list, obj);
563 isolate->heap()->SetSerializedObjects(*list);
564 return index;
565 }
566
AddData(Local<Context> context,i::Address object)567 size_t SnapshotCreator::AddData(Local<Context> context, i::Address object) {
568 DCHECK_NE(object, i::kNullAddress);
569 DCHECK(!SnapshotCreatorData::cast(data_)->created_);
570 i::Handle<i::Context> ctx = Utils::OpenHandle(*context);
571 i::Isolate* isolate = ctx->GetIsolate();
572 i::HandleScope scope(isolate);
573 i::Handle<i::Object> obj(i::Object(object), isolate);
574 i::Handle<i::ArrayList> list;
575 if (!ctx->serialized_objects().IsArrayList()) {
576 list = i::ArrayList::New(isolate, 1);
577 } else {
578 list = i::Handle<i::ArrayList>(
579 i::ArrayList::cast(ctx->serialized_objects()), isolate);
580 }
581 size_t index = static_cast<size_t>(list->Length());
582 list = i::ArrayList::Add(isolate, list, obj);
583 ctx->set_serialized_objects(*list);
584 return index;
585 }
586
587 namespace {
ConvertSerializedObjectsToFixedArray(Local<Context> context)588 void ConvertSerializedObjectsToFixedArray(Local<Context> context) {
589 i::Handle<i::Context> ctx = Utils::OpenHandle(*context);
590 i::Isolate* isolate = ctx->GetIsolate();
591 if (!ctx->serialized_objects().IsArrayList()) {
592 ctx->set_serialized_objects(i::ReadOnlyRoots(isolate).empty_fixed_array());
593 } else {
594 i::Handle<i::ArrayList> list(i::ArrayList::cast(ctx->serialized_objects()),
595 isolate);
596 i::Handle<i::FixedArray> elements = i::ArrayList::Elements(isolate, list);
597 ctx->set_serialized_objects(*elements);
598 }
599 }
600
ConvertSerializedObjectsToFixedArray(i::Isolate * isolate)601 void ConvertSerializedObjectsToFixedArray(i::Isolate* isolate) {
602 if (!isolate->heap()->serialized_objects().IsArrayList()) {
603 isolate->heap()->SetSerializedObjects(
604 i::ReadOnlyRoots(isolate).empty_fixed_array());
605 } else {
606 i::Handle<i::ArrayList> list(
607 i::ArrayList::cast(isolate->heap()->serialized_objects()), isolate);
608 i::Handle<i::FixedArray> elements = i::ArrayList::Elements(isolate, list);
609 isolate->heap()->SetSerializedObjects(*elements);
610 }
611 }
612 } // anonymous namespace
613
CreateBlob(SnapshotCreator::FunctionCodeHandling function_code_handling)614 StartupData SnapshotCreator::CreateBlob(
615 SnapshotCreator::FunctionCodeHandling function_code_handling) {
616 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
617 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_);
618 DCHECK(!data->created_);
619 DCHECK(!data->default_context_.IsEmpty());
620
621 const int num_additional_contexts = static_cast<int>(data->contexts_.Size());
622 const int num_contexts = num_additional_contexts + 1; // The default context.
623
624 // Create and store lists of embedder-provided data needed during
625 // serialization.
626 {
627 i::HandleScope scope(isolate);
628 // Convert list of context-independent data to FixedArray.
629 ConvertSerializedObjectsToFixedArray(isolate);
630
631 // Convert lists of context-dependent data to FixedArray.
632 ConvertSerializedObjectsToFixedArray(
633 data->default_context_.Get(data->isolate_));
634 for (int i = 0; i < num_additional_contexts; i++) {
635 ConvertSerializedObjectsToFixedArray(data->contexts_.Get(i));
636 }
637
638 // We need to store the global proxy size upfront in case we need the
639 // bootstrapper to create a global proxy before we deserialize the context.
640 i::Handle<i::FixedArray> global_proxy_sizes =
641 isolate->factory()->NewFixedArray(num_additional_contexts,
642 i::AllocationType::kOld);
643 for (int i = 0; i < num_additional_contexts; i++) {
644 i::Handle<i::Context> context =
645 v8::Utils::OpenHandle(*data->contexts_.Get(i));
646 global_proxy_sizes->set(i,
647 i::Smi::FromInt(context->global_proxy().Size()));
648 }
649 isolate->heap()->SetSerializedGlobalProxySizes(*global_proxy_sizes);
650 }
651
652 // We might rehash strings and re-sort descriptors. Clear the lookup cache.
653 isolate->descriptor_lookup_cache()->Clear();
654
655 // If we don't do this then we end up with a stray root pointing at the
656 // context even after we have disposed of the context.
657 isolate->heap()->CollectAllAvailableGarbage(
658 i::GarbageCollectionReason::kSnapshotCreator);
659 {
660 i::HandleScope scope(isolate);
661 isolate->heap()->CompactWeakArrayLists();
662 }
663
664 i::Snapshot::ClearReconstructableDataForSerialization(
665 isolate, function_code_handling == FunctionCodeHandling::kClear);
666
667 i::DisallowGarbageCollection no_gc_from_here_on;
668
669 // Create a vector with all contexts and clear associated Persistent fields.
670 // Note these contexts may be dead after calling Clear(), but will not be
671 // collected until serialization completes and the DisallowGarbageCollection
672 // scope above goes out of scope.
673 std::vector<i::Context> contexts;
674 contexts.reserve(num_contexts);
675 {
676 i::HandleScope scope(isolate);
677 contexts.push_back(
678 *v8::Utils::OpenHandle(*data->default_context_.Get(data->isolate_)));
679 data->default_context_.Reset();
680 for (int i = 0; i < num_additional_contexts; i++) {
681 i::Handle<i::Context> context =
682 v8::Utils::OpenHandle(*data->contexts_.Get(i));
683 contexts.push_back(*context);
684 }
685 data->contexts_.Clear();
686 }
687
688 // Check that values referenced by global/eternal handles are accounted for.
689 i::SerializedHandleChecker handle_checker(isolate, &contexts);
690 CHECK(handle_checker.CheckGlobalAndEternalHandles());
691
692 // Create a vector with all embedder fields serializers.
693 std::vector<SerializeInternalFieldsCallback> embedder_fields_serializers;
694 embedder_fields_serializers.reserve(num_contexts);
695 embedder_fields_serializers.push_back(
696 data->default_embedder_fields_serializer_);
697 for (int i = 0; i < num_additional_contexts; i++) {
698 embedder_fields_serializers.push_back(
699 data->embedder_fields_serializers_[i]);
700 }
701
702 data->created_ = true;
703 return i::Snapshot::Create(isolate, &contexts, embedder_fields_serializers,
704 no_gc_from_here_on);
705 }
706
CanBeRehashed() const707 bool StartupData::CanBeRehashed() const {
708 DCHECK(i::Snapshot::VerifyChecksum(this));
709 return i::Snapshot::ExtractRehashability(this);
710 }
711
IsValid() const712 bool StartupData::IsValid() const { return i::Snapshot::VersionIsValid(this); }
713
SetDcheckErrorHandler(DcheckErrorCallback that)714 void V8::SetDcheckErrorHandler(DcheckErrorCallback that) {
715 v8::base::SetDcheckFunction(that);
716 }
717
SetFlagsFromString(const char * str)718 void V8::SetFlagsFromString(const char* str) {
719 SetFlagsFromString(str, strlen(str));
720 }
721
SetFlagsFromString(const char * str,size_t length)722 void V8::SetFlagsFromString(const char* str, size_t length) {
723 i::FlagList::SetFlagsFromString(str, length);
724 i::FlagList::EnforceFlagImplications();
725 }
726
SetFlagsFromCommandLine(int * argc,char ** argv,bool remove_flags)727 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
728 using HelpOptions = i::FlagList::HelpOptions;
729 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags,
730 HelpOptions(HelpOptions::kDontExit));
731 }
732
733 RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
734
RegisteredExtension(std::unique_ptr<Extension> extension)735 RegisteredExtension::RegisteredExtension(std::unique_ptr<Extension> extension)
736 : extension_(std::move(extension)) {}
737
738 // static
Register(std::unique_ptr<Extension> extension)739 void RegisteredExtension::Register(std::unique_ptr<Extension> extension) {
740 RegisteredExtension* new_extension =
741 new RegisteredExtension(std::move(extension));
742 new_extension->next_ = first_extension_;
743 first_extension_ = new_extension;
744 }
745
746 // static
UnregisterAll()747 void RegisteredExtension::UnregisterAll() {
748 RegisteredExtension* re = first_extension_;
749 while (re != nullptr) {
750 RegisteredExtension* next = re->next();
751 delete re;
752 re = next;
753 }
754 first_extension_ = nullptr;
755 }
756
757 namespace {
758 class ExtensionResource : public String::ExternalOneByteStringResource {
759 public:
ExtensionResource()760 ExtensionResource() : data_(nullptr), length_(0) {}
ExtensionResource(const char * data,size_t length)761 ExtensionResource(const char* data, size_t length)
762 : data_(data), length_(length) {}
data() const763 const char* data() const override { return data_; }
length() const764 size_t length() const override { return length_; }
Dispose()765 void Dispose() override {}
766
767 private:
768 const char* data_;
769 size_t length_;
770 };
771 } // anonymous namespace
772
RegisterExtension(std::unique_ptr<Extension> extension)773 void RegisterExtension(std::unique_ptr<Extension> extension) {
774 RegisteredExtension::Register(std::move(extension));
775 }
776
Extension(const char * name,const char * source,int dep_count,const char ** deps,int source_length)777 Extension::Extension(const char* name, const char* source, int dep_count,
778 const char** deps, int source_length)
779 : name_(name),
780 source_length_(source_length >= 0
781 ? source_length
782 : (source ? static_cast<int>(strlen(source)) : 0)),
783 dep_count_(dep_count),
784 deps_(deps),
785 auto_enable_(false) {
786 source_ = new ExtensionResource(source, source_length_);
787 CHECK(source != nullptr || source_length_ == 0);
788 }
789
ConfigureDefaultsFromHeapSize(size_t initial_heap_size_in_bytes,size_t maximum_heap_size_in_bytes)790 void ResourceConstraints::ConfigureDefaultsFromHeapSize(
791 size_t initial_heap_size_in_bytes, size_t maximum_heap_size_in_bytes) {
792 CHECK_LE(initial_heap_size_in_bytes, maximum_heap_size_in_bytes);
793 if (maximum_heap_size_in_bytes == 0) {
794 return;
795 }
796 size_t young_generation, old_generation;
797 i::Heap::GenerationSizesFromHeapSize(maximum_heap_size_in_bytes,
798 &young_generation, &old_generation);
799 set_max_young_generation_size_in_bytes(
800 std::max(young_generation, i::Heap::MinYoungGenerationSize()));
801 set_max_old_generation_size_in_bytes(
802 std::max(old_generation, i::Heap::MinOldGenerationSize()));
803 if (initial_heap_size_in_bytes > 0) {
804 i::Heap::GenerationSizesFromHeapSize(initial_heap_size_in_bytes,
805 &young_generation, &old_generation);
806 // We do not set lower bounds for the initial sizes.
807 set_initial_young_generation_size_in_bytes(young_generation);
808 set_initial_old_generation_size_in_bytes(old_generation);
809 }
810 if (i::kPlatformRequiresCodeRange) {
811 set_code_range_size_in_bytes(
812 std::min(i::kMaximalCodeRangeSize, maximum_heap_size_in_bytes));
813 }
814 }
815
ConfigureDefaults(uint64_t physical_memory,uint64_t virtual_memory_limit)816 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
817 uint64_t virtual_memory_limit) {
818 size_t heap_size = i::Heap::HeapSizeFromPhysicalMemory(physical_memory);
819 size_t young_generation, old_generation;
820 i::Heap::GenerationSizesFromHeapSize(heap_size, &young_generation,
821 &old_generation);
822 set_max_young_generation_size_in_bytes(young_generation);
823 set_max_old_generation_size_in_bytes(old_generation);
824
825 if (virtual_memory_limit > 0 && i::kPlatformRequiresCodeRange) {
826 set_code_range_size_in_bytes(
827 std::min(i::kMaximalCodeRangeSize,
828 static_cast<size_t>(virtual_memory_limit / 8)));
829 }
830 }
831
832 namespace api_internal {
GlobalizeTracedReference(i::Isolate * isolate,i::Address * obj,internal::Address * slot,bool has_destructor)833 i::Address* GlobalizeTracedReference(i::Isolate* isolate, i::Address* obj,
834 internal::Address* slot,
835 bool has_destructor) {
836 LOG_API(isolate, TracedGlobal, New);
837 #ifdef DEBUG
838 Utils::ApiCheck((slot != nullptr), "v8::GlobalizeTracedReference",
839 "the address slot must be not null");
840 #endif
841 i::Handle<i::Object> result =
842 isolate->global_handles()->CreateTraced(*obj, slot, has_destructor);
843 #ifdef VERIFY_HEAP
844 if (i::FLAG_verify_heap) {
845 i::Object(*obj).ObjectVerify(isolate);
846 }
847 #endif // VERIFY_HEAP
848 return result.location();
849 }
850
GlobalizeReference(i::Isolate * isolate,i::Address * obj)851 i::Address* GlobalizeReference(i::Isolate* isolate, i::Address* obj) {
852 LOG_API(isolate, Persistent, New);
853 i::Handle<i::Object> result = isolate->global_handles()->Create(*obj);
854 #ifdef VERIFY_HEAP
855 if (i::FLAG_verify_heap) {
856 i::Object(*obj).ObjectVerify(isolate);
857 }
858 #endif // VERIFY_HEAP
859 return result.location();
860 }
861
CopyGlobalReference(i::Address * from)862 i::Address* CopyGlobalReference(i::Address* from) {
863 i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(from);
864 return result.location();
865 }
866
MoveGlobalReference(internal::Address ** from,internal::Address ** to)867 void MoveGlobalReference(internal::Address** from, internal::Address** to) {
868 i::GlobalHandles::MoveGlobal(from, to);
869 }
870
MakeWeak(i::Address * location,void * parameter,WeakCallbackInfo<void>::Callback weak_callback,WeakCallbackType type)871 void MakeWeak(i::Address* location, void* parameter,
872 WeakCallbackInfo<void>::Callback weak_callback,
873 WeakCallbackType type) {
874 i::GlobalHandles::MakeWeak(location, parameter, weak_callback, type);
875 }
876
MakeWeak(i::Address ** location_addr)877 void MakeWeak(i::Address** location_addr) {
878 i::GlobalHandles::MakeWeak(location_addr);
879 }
880
ClearWeak(i::Address * location)881 void* ClearWeak(i::Address* location) {
882 return i::GlobalHandles::ClearWeakness(location);
883 }
884
AnnotateStrongRetainer(i::Address * location,const char * label)885 void AnnotateStrongRetainer(i::Address* location, const char* label) {
886 i::GlobalHandles::AnnotateStrongRetainer(location, label);
887 }
888
DisposeGlobal(i::Address * location)889 void DisposeGlobal(i::Address* location) {
890 i::GlobalHandles::Destroy(location);
891 }
892
Eternalize(Isolate * v8_isolate,Value * value)893 Value* Eternalize(Isolate* v8_isolate, Value* value) {
894 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
895 i::Object object = *Utils::OpenHandle(value);
896 int index = -1;
897 isolate->eternal_handles()->Create(isolate, object, &index);
898 return reinterpret_cast<Value*>(
899 isolate->eternal_handles()->Get(index).location());
900 }
901
MoveTracedGlobalReference(internal::Address ** from,internal::Address ** to)902 void MoveTracedGlobalReference(internal::Address** from,
903 internal::Address** to) {
904 i::GlobalHandles::MoveTracedGlobal(from, to);
905 }
906
CopyTracedGlobalReference(const internal::Address * const * from,internal::Address ** to)907 void CopyTracedGlobalReference(const internal::Address* const* from,
908 internal::Address** to) {
909 i::GlobalHandles::CopyTracedGlobal(from, to);
910 }
911
DisposeTracedGlobal(internal::Address * location)912 void DisposeTracedGlobal(internal::Address* location) {
913 i::GlobalHandles::DestroyTraced(location);
914 }
915
SetFinalizationCallbackTraced(internal::Address * location,void * parameter,WeakCallbackInfo<void>::Callback callback)916 void SetFinalizationCallbackTraced(internal::Address* location, void* parameter,
917 WeakCallbackInfo<void>::Callback callback) {
918 i::GlobalHandles::SetFinalizationCallbackForTraced(location, parameter,
919 callback);
920 }
921
FromJustIsNothing()922 void FromJustIsNothing() {
923 Utils::ApiCheck(false, "v8::FromJust", "Maybe value is Nothing.");
924 }
925
ToLocalEmpty()926 void ToLocalEmpty() {
927 Utils::ApiCheck(false, "v8::ToLocalChecked", "Empty MaybeLocal.");
928 }
929
InternalFieldOutOfBounds(int index)930 void InternalFieldOutOfBounds(int index) {
931 Utils::ApiCheck(0 <= index && index < kInternalFieldsInWeakCallback,
932 "WeakCallbackInfo::GetInternalField",
933 "Internal field out of bounds.");
934 }
935
936 } // namespace api_internal
937
938 // --- H a n d l e s ---
939
HandleScope(Isolate * isolate)940 HandleScope::HandleScope(Isolate* isolate) { Initialize(isolate); }
941
Initialize(Isolate * isolate)942 void HandleScope::Initialize(Isolate* isolate) {
943 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
944 // We do not want to check the correct usage of the Locker class all over the
945 // place, so we do it only here: Without a HandleScope, an embedder can do
946 // almost nothing, so it is enough to check in this central place.
947 // We make an exception if the serializer is enabled, which means that the
948 // Isolate is exclusively used to create a snapshot.
949 Utils::ApiCheck(
950 !v8::Locker::WasEverUsed() ||
951 internal_isolate->thread_manager()->IsLockedByCurrentThread() ||
952 internal_isolate->serializer_enabled(),
953 "HandleScope::HandleScope",
954 "Entering the V8 API without proper locking in place");
955 i::HandleScopeData* current = internal_isolate->handle_scope_data();
956 isolate_ = internal_isolate;
957 prev_next_ = current->next;
958 prev_limit_ = current->limit;
959 current->level++;
960 }
961
~HandleScope()962 HandleScope::~HandleScope() {
963 i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_);
964 }
965
operator new(size_t)966 void* HandleScope::operator new(size_t) { base::OS::Abort(); }
operator new[](size_t)967 void* HandleScope::operator new[](size_t) { base::OS::Abort(); }
operator delete(void *,size_t)968 void HandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
operator delete[](void *,size_t)969 void HandleScope::operator delete[](void*, size_t) { base::OS::Abort(); }
970
NumberOfHandles(Isolate * isolate)971 int HandleScope::NumberOfHandles(Isolate* isolate) {
972 return i::HandleScope::NumberOfHandles(
973 reinterpret_cast<i::Isolate*>(isolate));
974 }
975
CreateHandle(i::Isolate * isolate,i::Address value)976 i::Address* HandleScope::CreateHandle(i::Isolate* isolate, i::Address value) {
977 return i::HandleScope::CreateHandle(isolate, value);
978 }
979
EscapableHandleScope(Isolate * v8_isolate)980 EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) {
981 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
982 escape_slot_ =
983 CreateHandle(isolate, i::ReadOnlyRoots(isolate).the_hole_value().ptr());
984 Initialize(v8_isolate);
985 }
986
Escape(i::Address * escape_value)987 i::Address* EscapableHandleScope::Escape(i::Address* escape_value) {
988 i::Heap* heap = reinterpret_cast<i::Isolate*>(GetIsolate())->heap();
989 Utils::ApiCheck(i::Object(*escape_slot_).IsTheHole(heap->isolate()),
990 "EscapableHandleScope::Escape", "Escape value set twice");
991 if (escape_value == nullptr) {
992 *escape_slot_ = i::ReadOnlyRoots(heap).undefined_value().ptr();
993 return nullptr;
994 }
995 *escape_slot_ = *escape_value;
996 return escape_slot_;
997 }
998
operator new(size_t)999 void* EscapableHandleScope::operator new(size_t) { base::OS::Abort(); }
operator new[](size_t)1000 void* EscapableHandleScope::operator new[](size_t) { base::OS::Abort(); }
operator delete(void *,size_t)1001 void EscapableHandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
operator delete[](void *,size_t)1002 void EscapableHandleScope::operator delete[](void*, size_t) {
1003 base::OS::Abort();
1004 }
1005
SealHandleScope(Isolate * isolate)1006 SealHandleScope::SealHandleScope(Isolate* isolate)
1007 : isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
1008 i::HandleScopeData* current = isolate_->handle_scope_data();
1009 prev_limit_ = current->limit;
1010 current->limit = current->next;
1011 prev_sealed_level_ = current->sealed_level;
1012 current->sealed_level = current->level;
1013 }
1014
~SealHandleScope()1015 SealHandleScope::~SealHandleScope() {
1016 i::HandleScopeData* current = isolate_->handle_scope_data();
1017 DCHECK_EQ(current->next, current->limit);
1018 current->limit = prev_limit_;
1019 DCHECK_EQ(current->level, current->sealed_level);
1020 current->sealed_level = prev_sealed_level_;
1021 }
1022
operator new(size_t)1023 void* SealHandleScope::operator new(size_t) { base::OS::Abort(); }
operator new[](size_t)1024 void* SealHandleScope::operator new[](size_t) { base::OS::Abort(); }
operator delete(void *,size_t)1025 void SealHandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
operator delete[](void *,size_t)1026 void SealHandleScope::operator delete[](void*, size_t) { base::OS::Abort(); }
1027
IsModule() const1028 bool Data::IsModule() const { return Utils::OpenHandle(this)->IsModule(); }
1029
IsValue() const1030 bool Data::IsValue() const {
1031 i::DisallowGarbageCollection no_gc;
1032 i::Object self = *Utils::OpenHandle(this);
1033 if (self.IsSmi()) return true;
1034 i::HeapObject heap_object = i::HeapObject::cast(self);
1035 DCHECK(!heap_object.IsTheHole());
1036 if (heap_object.IsSymbol()) {
1037 return !i::Symbol::cast(heap_object).is_private();
1038 }
1039 return heap_object.IsPrimitiveHeapObject() || heap_object.IsJSReceiver();
1040 }
1041
IsPrivate() const1042 bool Data::IsPrivate() const {
1043 return Utils::OpenHandle(this)->IsPrivateSymbol();
1044 }
1045
IsObjectTemplate() const1046 bool Data::IsObjectTemplate() const {
1047 return Utils::OpenHandle(this)->IsObjectTemplateInfo();
1048 }
1049
IsFunctionTemplate() const1050 bool Data::IsFunctionTemplate() const {
1051 return Utils::OpenHandle(this)->IsFunctionTemplateInfo();
1052 }
1053
IsContext() const1054 bool Data::IsContext() const { return Utils::OpenHandle(this)->IsContext(); }
1055
Enter()1056 void Context::Enter() {
1057 i::Handle<i::Context> env = Utils::OpenHandle(this);
1058 i::Isolate* isolate = env->GetIsolate();
1059 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1060 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
1061 impl->EnterContext(*env);
1062 impl->SaveContext(isolate->context());
1063 isolate->set_context(*env);
1064 }
1065
Exit()1066 void Context::Exit() {
1067 i::Handle<i::Context> env = Utils::OpenHandle(this);
1068 i::Isolate* isolate = env->GetIsolate();
1069 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1070 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
1071 if (!Utils::ApiCheck(impl->LastEnteredContextWas(*env), "v8::Context::Exit()",
1072 "Cannot exit non-entered context")) {
1073 return;
1074 }
1075 impl->LeaveContext();
1076 isolate->set_context(impl->RestoreContext());
1077 }
1078
BackupIncumbentScope(Local<Context> backup_incumbent_context)1079 Context::BackupIncumbentScope::BackupIncumbentScope(
1080 Local<Context> backup_incumbent_context)
1081 : backup_incumbent_context_(backup_incumbent_context) {
1082 DCHECK(!backup_incumbent_context_.IsEmpty());
1083
1084 i::Handle<i::Context> env = Utils::OpenHandle(*backup_incumbent_context_);
1085 i::Isolate* isolate = env->GetIsolate();
1086
1087 js_stack_comparable_address_ =
1088 i::SimulatorStack::RegisterJSStackComparableAddress(isolate);
1089
1090 prev_ = isolate->top_backup_incumbent_scope();
1091 isolate->set_top_backup_incumbent_scope(this);
1092 }
1093
~BackupIncumbentScope()1094 Context::BackupIncumbentScope::~BackupIncumbentScope() {
1095 i::Handle<i::Context> env = Utils::OpenHandle(*backup_incumbent_context_);
1096 i::Isolate* isolate = env->GetIsolate();
1097
1098 i::SimulatorStack::UnregisterJSStackComparableAddress(isolate);
1099
1100 isolate->set_top_backup_incumbent_scope(prev_);
1101 }
1102
1103 STATIC_ASSERT(i::Internals::kEmbedderDataSlotSize == i::kEmbedderDataSlotSize);
1104
EmbedderDataFor(Context * context,int index,bool can_grow,const char * location)1105 static i::Handle<i::EmbedderDataArray> EmbedderDataFor(Context* context,
1106 int index, bool can_grow,
1107 const char* location) {
1108 i::Handle<i::Context> env = Utils::OpenHandle(context);
1109 i::Isolate* isolate = env->GetIsolate();
1110 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
1111 bool ok = Utils::ApiCheck(env->IsNativeContext(), location,
1112 "Not a native context") &&
1113 Utils::ApiCheck(index >= 0, location, "Negative index");
1114 if (!ok) return i::Handle<i::EmbedderDataArray>();
1115 // TODO(ishell): remove cast once embedder_data slot has a proper type.
1116 i::Handle<i::EmbedderDataArray> data(
1117 i::EmbedderDataArray::cast(env->embedder_data()), isolate);
1118 if (index < data->length()) return data;
1119 if (!Utils::ApiCheck(can_grow && index < i::EmbedderDataArray::kMaxLength,
1120 location, "Index too large")) {
1121 return i::Handle<i::EmbedderDataArray>();
1122 }
1123 data = i::EmbedderDataArray::EnsureCapacity(isolate, data, index);
1124 env->set_embedder_data(*data);
1125 return data;
1126 }
1127
GetNumberOfEmbedderDataFields()1128 uint32_t Context::GetNumberOfEmbedderDataFields() {
1129 i::Handle<i::Context> context = Utils::OpenHandle(this);
1130 ASSERT_NO_SCRIPT_NO_EXCEPTION(context->GetIsolate());
1131 Utils::ApiCheck(context->IsNativeContext(),
1132 "Context::GetNumberOfEmbedderDataFields",
1133 "Not a native context");
1134 // TODO(ishell): remove cast once embedder_data slot has a proper type.
1135 return static_cast<uint32_t>(
1136 i::EmbedderDataArray::cast(context->embedder_data()).length());
1137 }
1138
SlowGetEmbedderData(int index)1139 v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) {
1140 const char* location = "v8::Context::GetEmbedderData()";
1141 i::Handle<i::EmbedderDataArray> data =
1142 EmbedderDataFor(this, index, false, location);
1143 if (data.is_null()) return Local<Value>();
1144 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1145 i::Handle<i::Object> result(i::EmbedderDataSlot(*data, index).load_tagged(),
1146 isolate);
1147 return Utils::ToLocal(result);
1148 }
1149
SetEmbedderData(int index,v8::Local<Value> value)1150 void Context::SetEmbedderData(int index, v8::Local<Value> value) {
1151 const char* location = "v8::Context::SetEmbedderData()";
1152 i::Handle<i::EmbedderDataArray> data =
1153 EmbedderDataFor(this, index, true, location);
1154 if (data.is_null()) return;
1155 i::Handle<i::Object> val = Utils::OpenHandle(*value);
1156 i::EmbedderDataSlot::store_tagged(*data, index, *val);
1157 DCHECK_EQ(*Utils::OpenHandle(*value),
1158 *Utils::OpenHandle(*GetEmbedderData(index)));
1159 }
1160
SlowGetAlignedPointerFromEmbedderData(int index)1161 void* Context::SlowGetAlignedPointerFromEmbedderData(int index) {
1162 const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()";
1163 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1164 i::HandleScope handle_scope(isolate);
1165 i::Handle<i::EmbedderDataArray> data =
1166 EmbedderDataFor(this, index, false, location);
1167 if (data.is_null()) return nullptr;
1168 void* result;
1169 Utils::ApiCheck(
1170 i::EmbedderDataSlot(*data, index).ToAlignedPointer(isolate, &result),
1171 location, "Pointer is not aligned");
1172 return result;
1173 }
1174
SetAlignedPointerInEmbedderData(int index,void * value)1175 void Context::SetAlignedPointerInEmbedderData(int index, void* value) {
1176 const char* location = "v8::Context::SetAlignedPointerInEmbedderData()";
1177 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1178 i::Handle<i::EmbedderDataArray> data =
1179 EmbedderDataFor(this, index, true, location);
1180 bool ok =
1181 i::EmbedderDataSlot(*data, index).store_aligned_pointer(isolate, value);
1182 Utils::ApiCheck(ok, location, "Pointer is not aligned");
1183 DCHECK_EQ(value, GetAlignedPointerFromEmbedderData(index));
1184 }
1185
1186 // --- T e m p l a t e ---
1187
InitializeTemplate(i::TemplateInfo that,int type,bool do_not_cache)1188 static void InitializeTemplate(i::TemplateInfo that, int type,
1189 bool do_not_cache) {
1190 that.set_number_of_properties(0);
1191 that.set_tag(type);
1192 int serial_number =
1193 do_not_cache ? i::TemplateInfo::kDoNotCache : i::TemplateInfo::kUncached;
1194 that.set_serial_number(serial_number);
1195 }
1196
Set(v8::Local<Name> name,v8::Local<Data> value,v8::PropertyAttribute attribute)1197 void Template::Set(v8::Local<Name> name, v8::Local<Data> value,
1198 v8::PropertyAttribute attribute) {
1199 auto templ = Utils::OpenHandle(this);
1200 i::Isolate* isolate = templ->GetIsolate();
1201 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1202 i::HandleScope scope(isolate);
1203 auto value_obj = Utils::OpenHandle(*value);
1204
1205 Utils::ApiCheck(!value_obj->IsJSReceiver() || value_obj->IsTemplateInfo(),
1206 "v8::Template::Set",
1207 "Invalid value, must be a primitive or a Template");
1208
1209 // The template cache only performs shallow clones, if we set an
1210 // ObjectTemplate as a property value then we can not cache the receiver
1211 // template.
1212 if (value_obj->IsObjectTemplateInfo()) {
1213 templ->set_serial_number(i::TemplateInfo::kDoNotCache);
1214 }
1215
1216 i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name),
1217 value_obj,
1218 static_cast<i::PropertyAttributes>(attribute));
1219 }
1220
SetPrivate(v8::Local<Private> name,v8::Local<Data> value,v8::PropertyAttribute attribute)1221 void Template::SetPrivate(v8::Local<Private> name, v8::Local<Data> value,
1222 v8::PropertyAttribute attribute) {
1223 Set(Utils::ToLocal(Utils::OpenHandle(reinterpret_cast<Name*>(*name))), value,
1224 attribute);
1225 }
1226
SetAccessorProperty(v8::Local<v8::Name> name,v8::Local<FunctionTemplate> getter,v8::Local<FunctionTemplate> setter,v8::PropertyAttribute attribute,v8::AccessControl access_control)1227 void Template::SetAccessorProperty(v8::Local<v8::Name> name,
1228 v8::Local<FunctionTemplate> getter,
1229 v8::Local<FunctionTemplate> setter,
1230 v8::PropertyAttribute attribute,
1231 v8::AccessControl access_control) {
1232 // TODO(verwaest): Remove |access_control|.
1233 DCHECK_EQ(v8::DEFAULT, access_control);
1234 auto templ = Utils::OpenHandle(this);
1235 auto isolate = templ->GetIsolate();
1236 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1237 DCHECK(!name.IsEmpty());
1238 DCHECK(!getter.IsEmpty() || !setter.IsEmpty());
1239 i::HandleScope scope(isolate);
1240 i::ApiNatives::AddAccessorProperty(
1241 isolate, templ, Utils::OpenHandle(*name),
1242 Utils::OpenHandle(*getter, true), Utils::OpenHandle(*setter, true),
1243 static_cast<i::PropertyAttributes>(attribute));
1244 }
1245
1246 // --- F u n c t i o n T e m p l a t e ---
InitializeFunctionTemplate(i::FunctionTemplateInfo info,bool do_not_cache)1247 static void InitializeFunctionTemplate(i::FunctionTemplateInfo info,
1248 bool do_not_cache) {
1249 InitializeTemplate(info, Consts::FUNCTION_TEMPLATE, do_not_cache);
1250 info.set_flag(0);
1251 }
1252
1253 static Local<ObjectTemplate> ObjectTemplateNew(
1254 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor,
1255 bool do_not_cache);
1256
PrototypeTemplate()1257 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
1258 auto self = Utils::OpenHandle(this);
1259 i::Isolate* i_isolate = self->GetIsolate();
1260 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1261 i::Handle<i::HeapObject> result(self->GetPrototypeTemplate(), i_isolate);
1262 if (result->IsUndefined(i_isolate)) {
1263 // Do not cache prototype objects.
1264 result = Utils::OpenHandle(
1265 *ObjectTemplateNew(i_isolate, Local<FunctionTemplate>(), true));
1266 i::FunctionTemplateInfo::SetPrototypeTemplate(i_isolate, self, result);
1267 }
1268 return ToApiHandle<ObjectTemplate>(result);
1269 }
1270
SetPrototypeProviderTemplate(Local<FunctionTemplate> prototype_provider)1271 void FunctionTemplate::SetPrototypeProviderTemplate(
1272 Local<FunctionTemplate> prototype_provider) {
1273 auto self = Utils::OpenHandle(this);
1274 i::Isolate* i_isolate = self->GetIsolate();
1275 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1276 i::Handle<i::FunctionTemplateInfo> result =
1277 Utils::OpenHandle(*prototype_provider);
1278 Utils::ApiCheck(self->GetPrototypeTemplate().IsUndefined(i_isolate),
1279 "v8::FunctionTemplate::SetPrototypeProviderTemplate",
1280 "Protoype must be undefined");
1281 Utils::ApiCheck(self->GetParentTemplate().IsUndefined(i_isolate),
1282 "v8::FunctionTemplate::SetPrototypeProviderTemplate",
1283 "Prototype provider must be empty");
1284 i::FunctionTemplateInfo::SetPrototypeProviderTemplate(i_isolate, self,
1285 result);
1286 }
1287
EnsureNotPublished(i::Handle<i::FunctionTemplateInfo> info,const char * func)1288 static void EnsureNotPublished(i::Handle<i::FunctionTemplateInfo> info,
1289 const char* func) {
1290 DCHECK_IMPLIES(info->instantiated(), info->published());
1291 Utils::ApiCheck(!info->published(), func,
1292 "FunctionTemplate already instantiated");
1293 }
1294
Inherit(v8::Local<FunctionTemplate> value)1295 void FunctionTemplate::Inherit(v8::Local<FunctionTemplate> value) {
1296 auto info = Utils::OpenHandle(this);
1297 EnsureNotPublished(info, "v8::FunctionTemplate::Inherit");
1298 i::Isolate* i_isolate = info->GetIsolate();
1299 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1300 Utils::ApiCheck(info->GetPrototypeProviderTemplate().IsUndefined(i_isolate),
1301 "v8::FunctionTemplate::Inherit",
1302 "Protoype provider must be empty");
1303 i::FunctionTemplateInfo::SetParentTemplate(i_isolate, info,
1304 Utils::OpenHandle(*value));
1305 }
1306
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)1307 static Local<FunctionTemplate> FunctionTemplateNew(
1308 i::Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
1309 v8::Local<Signature> signature, int length, ConstructorBehavior behavior,
1310 bool do_not_cache,
1311 v8::Local<Private> cached_property_name = v8::Local<Private>(),
1312 SideEffectType side_effect_type = SideEffectType::kHasSideEffect,
1313 const MemorySpan<const CFunction>& c_function_overloads = {},
1314 uint8_t instance_type = 0,
1315 uint8_t allowed_receiver_instance_type_range_start = 0,
1316 uint8_t allowed_receiver_instance_type_range_end = 0) {
1317 i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct(
1318 i::FUNCTION_TEMPLATE_INFO_TYPE, i::AllocationType::kOld);
1319 i::Handle<i::FunctionTemplateInfo> obj =
1320 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
1321 {
1322 // Disallow GC until all fields of obj have acceptable types.
1323 i::DisallowGarbageCollection no_gc;
1324 i::FunctionTemplateInfo raw = *obj;
1325 InitializeFunctionTemplate(raw, do_not_cache);
1326 raw.set_length(length);
1327 raw.set_undetectable(false);
1328 raw.set_needs_access_check(false);
1329 raw.set_accept_any_receiver(true);
1330 if (!signature.IsEmpty()) {
1331 raw.set_signature(*Utils::OpenHandle(*signature));
1332 }
1333 raw.set_cached_property_name(
1334 cached_property_name.IsEmpty()
1335 ? i::ReadOnlyRoots(isolate).the_hole_value()
1336 : *Utils::OpenHandle(*cached_property_name));
1337 if (behavior == ConstructorBehavior::kThrow) raw.set_remove_prototype(true);
1338 raw.SetInstanceType(instance_type);
1339 raw.set_allowed_receiver_instance_type_range_start(
1340 allowed_receiver_instance_type_range_start);
1341 raw.set_allowed_receiver_instance_type_range_end(
1342 allowed_receiver_instance_type_range_end);
1343 }
1344 if (callback != nullptr) {
1345 Utils::ToLocal(obj)->SetCallHandler(callback, data, side_effect_type,
1346 c_function_overloads);
1347 }
1348 return Utils::ToLocal(obj);
1349 }
1350
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)1351 Local<FunctionTemplate> FunctionTemplate::New(
1352 Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
1353 v8::Local<Signature> signature, int length, ConstructorBehavior behavior,
1354 SideEffectType side_effect_type, const CFunction* c_function,
1355 uint16_t instance_type, uint16_t allowed_receiver_instance_type_range_start,
1356 uint16_t allowed_receiver_instance_type_range_end) {
1357 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1358 // Changes to the environment cannot be captured in the snapshot. Expect no
1359 // function templates when the isolate is created for serialization.
1360 LOG_API(i_isolate, FunctionTemplate, New);
1361 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1362 return FunctionTemplateNew(
1363 i_isolate, callback, data, signature, length, behavior, false,
1364 Local<Private>(), side_effect_type,
1365 c_function ? MemorySpan<const CFunction>{c_function, 1}
1366 : MemorySpan<const CFunction>{},
1367 instance_type, allowed_receiver_instance_type_range_start,
1368 allowed_receiver_instance_type_range_end);
1369 }
1370
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)1371 Local<FunctionTemplate> FunctionTemplate::NewWithCFunctionOverloads(
1372 Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
1373 v8::Local<Signature> signature, int length, ConstructorBehavior behavior,
1374 SideEffectType side_effect_type,
1375 const MemorySpan<const CFunction>& c_function_overloads) {
1376 // TODO(mslekova): Once runtime overload resolution between sequences is
1377 // supported, check that if (c_function_overloads.size() == 2), then
1378 // c_function_overloads.data()[0].
1379 // CanResolveOverload(c_function_overloads.data()[1]). We won't support
1380 // the case where the size is greater than 2 for runtime resolution, until
1381 // we've added support for ArrayBuffers and ArrayBufferViews. OTOH the
1382 // overloads list might contain more than 2 functions with different arity,
1383 // the resolution between which is available at compile time.
1384
1385 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1386 LOG_API(i_isolate, FunctionTemplate, New);
1387 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1388 return FunctionTemplateNew(i_isolate, callback, data, signature, length,
1389 behavior, false, Local<Private>(),
1390 side_effect_type, c_function_overloads);
1391 }
1392
NewWithCache(Isolate * isolate,FunctionCallback callback,Local<Private> cache_property,Local<Value> data,Local<Signature> signature,int length,SideEffectType side_effect_type)1393 Local<FunctionTemplate> FunctionTemplate::NewWithCache(
1394 Isolate* isolate, FunctionCallback callback, Local<Private> cache_property,
1395 Local<Value> data, Local<Signature> signature, int length,
1396 SideEffectType side_effect_type) {
1397 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1398 LOG_API(i_isolate, FunctionTemplate, NewWithCache);
1399 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1400 return FunctionTemplateNew(i_isolate, callback, data, signature, length,
1401 ConstructorBehavior::kAllow, false, cache_property,
1402 side_effect_type);
1403 }
1404
New(Isolate * isolate,Local<FunctionTemplate> receiver)1405 Local<Signature> Signature::New(Isolate* isolate,
1406 Local<FunctionTemplate> receiver) {
1407 return Utils::SignatureToLocal(Utils::OpenHandle(*receiver));
1408 }
1409
New(Isolate * isolate,Local<FunctionTemplate> receiver)1410 Local<AccessorSignature> AccessorSignature::New(
1411 Isolate* isolate, Local<FunctionTemplate> receiver) {
1412 return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
1413 }
1414
1415 #define SET_FIELD_WRAPPED(isolate, obj, setter, cdata) \
1416 do { \
1417 i::Handle<i::Object> foreign = FromCData(isolate, cdata); \
1418 (obj)->setter(*foreign); \
1419 } while (false)
1420
SetCallHandler(FunctionCallback callback,v8::Local<Value> data,SideEffectType side_effect_type,const MemorySpan<const CFunction> & c_function_overloads)1421 void FunctionTemplate::SetCallHandler(
1422 FunctionCallback callback, v8::Local<Value> data,
1423 SideEffectType side_effect_type,
1424 const MemorySpan<const CFunction>& c_function_overloads) {
1425 auto info = Utils::OpenHandle(this);
1426 EnsureNotPublished(info, "v8::FunctionTemplate::SetCallHandler");
1427 i::Isolate* isolate = info->GetIsolate();
1428 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1429 i::HandleScope scope(isolate);
1430 i::Handle<i::CallHandlerInfo> obj = isolate->factory()->NewCallHandlerInfo(
1431 side_effect_type == SideEffectType::kHasNoSideEffect);
1432 SET_FIELD_WRAPPED(isolate, obj, set_callback, callback);
1433 SET_FIELD_WRAPPED(isolate, obj, set_js_callback, obj->redirected_callback());
1434 if (data.IsEmpty()) {
1435 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1436 }
1437 obj->set_data(*Utils::OpenHandle(*data));
1438 if (c_function_overloads.size() > 0) {
1439 // Stores the data for a sequence of CFunction overloads into a single
1440 // FixedArray, as [address_0, signature_0, ... address_n-1, signature_n-1].
1441 i::Handle<i::FixedArray> function_overloads =
1442 isolate->factory()->NewFixedArray(static_cast<int>(
1443 c_function_overloads.size() *
1444 i::FunctionTemplateInfo::kFunctionOverloadEntrySize));
1445 int function_count = static_cast<int>(c_function_overloads.size());
1446 for (int i = 0; i < function_count; i++) {
1447 const CFunction& c_function = c_function_overloads.data()[i];
1448 i::Handle<i::Object> address =
1449 FromCData(isolate, c_function.GetAddress());
1450 function_overloads->set(
1451 i::FunctionTemplateInfo::kFunctionOverloadEntrySize * i, *address);
1452 i::Handle<i::Object> signature =
1453 FromCData(isolate, c_function.GetTypeInfo());
1454 function_overloads->set(
1455 i::FunctionTemplateInfo::kFunctionOverloadEntrySize * i + 1,
1456 *signature);
1457 }
1458 i::FunctionTemplateInfo::SetCFunctionOverloads(isolate, info,
1459 function_overloads);
1460 }
1461 info->set_call_code(*obj, kReleaseStore);
1462 }
1463
1464 namespace {
1465
1466 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)1467 i::Handle<i::AccessorInfo> MakeAccessorInfo(
1468 i::Isolate* isolate, v8::Local<Name> name, Getter getter, Setter setter,
1469 v8::Local<Value> data, v8::AccessControl settings,
1470 v8::Local<AccessorSignature> signature, bool is_special_data_property,
1471 bool replace_on_access) {
1472 i::Handle<i::AccessorInfo> obj = isolate->factory()->NewAccessorInfo();
1473 SET_FIELD_WRAPPED(isolate, obj, set_getter, getter);
1474 DCHECK_IMPLIES(replace_on_access,
1475 is_special_data_property && setter == nullptr);
1476 if (is_special_data_property && setter == nullptr) {
1477 setter = reinterpret_cast<Setter>(&i::Accessors::ReconfigureToDataProperty);
1478 }
1479 SET_FIELD_WRAPPED(isolate, obj, set_setter, setter);
1480 i::Address redirected = obj->redirected_getter();
1481 if (redirected != i::kNullAddress) {
1482 SET_FIELD_WRAPPED(isolate, obj, set_js_getter, redirected);
1483 }
1484 if (data.IsEmpty()) {
1485 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1486 }
1487 obj->set_data(*Utils::OpenHandle(*data));
1488 obj->set_is_special_data_property(is_special_data_property);
1489 obj->set_replace_on_access(replace_on_access);
1490 i::Handle<i::Name> accessor_name = Utils::OpenHandle(*name);
1491 if (!accessor_name->IsUniqueName()) {
1492 accessor_name = isolate->factory()->InternalizeString(
1493 i::Handle<i::String>::cast(accessor_name));
1494 }
1495 obj->set_name(*accessor_name);
1496 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
1497 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
1498 obj->set_initial_property_attributes(i::NONE);
1499 if (!signature.IsEmpty()) {
1500 obj->set_expected_receiver_type(*Utils::OpenHandle(*signature));
1501 }
1502 return obj;
1503 }
1504
1505 } // namespace
1506
InstanceTemplate()1507 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
1508 i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this, true);
1509 if (!Utils::ApiCheck(!handle.is_null(),
1510 "v8::FunctionTemplate::InstanceTemplate()",
1511 "Reading from empty handle")) {
1512 return Local<ObjectTemplate>();
1513 }
1514 i::Isolate* isolate = handle->GetIsolate();
1515 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1516 if (handle->GetInstanceTemplate().IsUndefined(isolate)) {
1517 Local<ObjectTemplate> templ =
1518 ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle));
1519 i::FunctionTemplateInfo::SetInstanceTemplate(isolate, handle,
1520 Utils::OpenHandle(*templ));
1521 }
1522 i::Handle<i::ObjectTemplateInfo> result(
1523 i::ObjectTemplateInfo::cast(handle->GetInstanceTemplate()), isolate);
1524 return Utils::ToLocal(result);
1525 }
1526
SetLength(int length)1527 void FunctionTemplate::SetLength(int length) {
1528 auto info = Utils::OpenHandle(this);
1529 EnsureNotPublished(info, "v8::FunctionTemplate::SetLength");
1530 auto isolate = info->GetIsolate();
1531 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1532 info->set_length(length);
1533 }
1534
SetClassName(Local<String> name)1535 void FunctionTemplate::SetClassName(Local<String> name) {
1536 auto info = Utils::OpenHandle(this);
1537 EnsureNotPublished(info, "v8::FunctionTemplate::SetClassName");
1538 auto isolate = info->GetIsolate();
1539 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1540 info->set_class_name(*Utils::OpenHandle(*name));
1541 }
1542
SetAcceptAnyReceiver(bool value)1543 void FunctionTemplate::SetAcceptAnyReceiver(bool value) {
1544 auto info = Utils::OpenHandle(this);
1545 EnsureNotPublished(info, "v8::FunctionTemplate::SetAcceptAnyReceiver");
1546 auto isolate = info->GetIsolate();
1547 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1548 info->set_accept_any_receiver(value);
1549 }
1550
ReadOnlyPrototype()1551 void FunctionTemplate::ReadOnlyPrototype() {
1552 auto info = Utils::OpenHandle(this);
1553 EnsureNotPublished(info, "v8::FunctionTemplate::ReadOnlyPrototype");
1554 auto isolate = info->GetIsolate();
1555 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1556 info->set_read_only_prototype(true);
1557 }
1558
RemovePrototype()1559 void FunctionTemplate::RemovePrototype() {
1560 auto info = Utils::OpenHandle(this);
1561 EnsureNotPublished(info, "v8::FunctionTemplate::RemovePrototype");
1562 auto isolate = info->GetIsolate();
1563 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1564 info->set_remove_prototype(true);
1565 }
1566
1567 // --- O b j e c t T e m p l a t e ---
1568
New(Isolate * isolate,v8::Local<FunctionTemplate> constructor)1569 Local<ObjectTemplate> ObjectTemplate::New(
1570 Isolate* isolate, v8::Local<FunctionTemplate> constructor) {
1571 return New(reinterpret_cast<i::Isolate*>(isolate), constructor);
1572 }
1573
ObjectTemplateNew(i::Isolate * isolate,v8::Local<FunctionTemplate> constructor,bool do_not_cache)1574 static Local<ObjectTemplate> ObjectTemplateNew(
1575 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor,
1576 bool do_not_cache) {
1577 LOG_API(isolate, ObjectTemplate, New);
1578 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1579 i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct(
1580 i::OBJECT_TEMPLATE_INFO_TYPE, i::AllocationType::kOld);
1581 i::Handle<i::ObjectTemplateInfo> obj =
1582 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
1583 {
1584 // Disallow GC until all fields of obj have acceptable types.
1585 i::DisallowGarbageCollection no_gc;
1586 i::ObjectTemplateInfo raw = *obj;
1587 InitializeTemplate(raw, Consts::OBJECT_TEMPLATE, do_not_cache);
1588 raw.set_data(0);
1589 if (!constructor.IsEmpty()) {
1590 raw.set_constructor(*Utils::OpenHandle(*constructor));
1591 }
1592 }
1593 return Utils::ToLocal(obj);
1594 }
1595
New(i::Isolate * isolate,v8::Local<FunctionTemplate> constructor)1596 Local<ObjectTemplate> ObjectTemplate::New(
1597 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor) {
1598 return ObjectTemplateNew(isolate, constructor, false);
1599 }
1600
1601 // Ensure that the object template has a constructor. If no
1602 // constructor is available we create one.
EnsureConstructor(i::Isolate * isolate,ObjectTemplate * object_template)1603 static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
1604 i::Isolate* isolate, ObjectTemplate* object_template) {
1605 i::Object obj = Utils::OpenHandle(object_template)->constructor();
1606 if (!obj.IsUndefined(isolate)) {
1607 i::FunctionTemplateInfo info = i::FunctionTemplateInfo::cast(obj);
1608 return i::Handle<i::FunctionTemplateInfo>(info, isolate);
1609 }
1610 Local<FunctionTemplate> templ =
1611 FunctionTemplate::New(reinterpret_cast<Isolate*>(isolate));
1612 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
1613 i::FunctionTemplateInfo::SetInstanceTemplate(
1614 isolate, constructor, Utils::OpenHandle(object_template));
1615 Utils::OpenHandle(object_template)->set_constructor(*constructor);
1616 return constructor;
1617 }
1618
1619 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)1620 static void TemplateSetAccessor(
1621 Template* template_obj, v8::Local<Name> name, Getter getter, Setter setter,
1622 Data data, AccessControl settings, PropertyAttribute attribute,
1623 v8::Local<AccessorSignature> signature, bool is_special_data_property,
1624 bool replace_on_access, SideEffectType getter_side_effect_type,
1625 SideEffectType setter_side_effect_type) {
1626 auto info = Utils::OpenHandle(template_obj);
1627 auto isolate = info->GetIsolate();
1628 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1629 i::HandleScope scope(isolate);
1630 i::Handle<i::AccessorInfo> accessor_info =
1631 MakeAccessorInfo(isolate, name, getter, setter, data, settings, signature,
1632 is_special_data_property, replace_on_access);
1633 accessor_info->set_initial_property_attributes(
1634 static_cast<i::PropertyAttributes>(attribute));
1635 accessor_info->set_getter_side_effect_type(getter_side_effect_type);
1636 accessor_info->set_setter_side_effect_type(setter_side_effect_type);
1637 i::ApiNatives::AddNativeDataProperty(isolate, info, accessor_info);
1638 }
1639
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)1640 void Template::SetNativeDataProperty(
1641 v8::Local<String> name, AccessorGetterCallback getter,
1642 AccessorSetterCallback setter, v8::Local<Value> data,
1643 PropertyAttribute attribute, v8::Local<AccessorSignature> signature,
1644 AccessControl settings, SideEffectType getter_side_effect_type,
1645 SideEffectType setter_side_effect_type) {
1646 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1647 signature, true, false, getter_side_effect_type,
1648 setter_side_effect_type);
1649 }
1650
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)1651 void Template::SetNativeDataProperty(
1652 v8::Local<Name> name, AccessorNameGetterCallback getter,
1653 AccessorNameSetterCallback setter, v8::Local<Value> data,
1654 PropertyAttribute attribute, v8::Local<AccessorSignature> signature,
1655 AccessControl settings, SideEffectType getter_side_effect_type,
1656 SideEffectType setter_side_effect_type) {
1657 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1658 signature, true, false, getter_side_effect_type,
1659 setter_side_effect_type);
1660 }
1661
SetLazyDataProperty(v8::Local<Name> name,AccessorNameGetterCallback getter,v8::Local<Value> data,PropertyAttribute attribute,SideEffectType getter_side_effect_type,SideEffectType setter_side_effect_type)1662 void Template::SetLazyDataProperty(v8::Local<Name> name,
1663 AccessorNameGetterCallback getter,
1664 v8::Local<Value> data,
1665 PropertyAttribute attribute,
1666 SideEffectType getter_side_effect_type,
1667 SideEffectType setter_side_effect_type) {
1668 TemplateSetAccessor(this, name, getter,
1669 static_cast<AccessorNameSetterCallback>(nullptr), data,
1670 DEFAULT, attribute, Local<AccessorSignature>(), true,
1671 true, getter_side_effect_type, setter_side_effect_type);
1672 }
1673
SetIntrinsicDataProperty(Local<Name> name,Intrinsic intrinsic,PropertyAttribute attribute)1674 void Template::SetIntrinsicDataProperty(Local<Name> name, Intrinsic intrinsic,
1675 PropertyAttribute attribute) {
1676 auto templ = Utils::OpenHandle(this);
1677 i::Isolate* isolate = templ->GetIsolate();
1678 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1679 i::HandleScope scope(isolate);
1680 i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name),
1681 intrinsic,
1682 static_cast<i::PropertyAttributes>(attribute));
1683 }
1684
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)1685 void ObjectTemplate::SetAccessor(v8::Local<String> name,
1686 AccessorGetterCallback getter,
1687 AccessorSetterCallback setter,
1688 v8::Local<Value> data, AccessControl settings,
1689 PropertyAttribute attribute,
1690 v8::Local<AccessorSignature> signature,
1691 SideEffectType getter_side_effect_type,
1692 SideEffectType setter_side_effect_type) {
1693 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1694 signature, i::FLAG_disable_old_api_accessors, false,
1695 getter_side_effect_type, setter_side_effect_type);
1696 }
1697
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)1698 void ObjectTemplate::SetAccessor(v8::Local<Name> name,
1699 AccessorNameGetterCallback getter,
1700 AccessorNameSetterCallback setter,
1701 v8::Local<Value> data, AccessControl settings,
1702 PropertyAttribute attribute,
1703 v8::Local<AccessorSignature> signature,
1704 SideEffectType getter_side_effect_type,
1705 SideEffectType setter_side_effect_type) {
1706 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1707 signature, i::FLAG_disable_old_api_accessors, false,
1708 getter_side_effect_type, setter_side_effect_type);
1709 }
1710
1711 template <typename Getter, typename Setter, typename Query, typename Descriptor,
1712 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)1713 static i::Handle<i::InterceptorInfo> CreateInterceptorInfo(
1714 i::Isolate* isolate, Getter getter, Setter setter, Query query,
1715 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1716 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1717 auto obj = i::Handle<i::InterceptorInfo>::cast(isolate->factory()->NewStruct(
1718 i::INTERCEPTOR_INFO_TYPE, i::AllocationType::kOld));
1719 obj->set_flags(0);
1720
1721 if (getter != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_getter, getter);
1722 if (setter != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_setter, setter);
1723 if (query != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_query, query);
1724 if (descriptor != nullptr)
1725 SET_FIELD_WRAPPED(isolate, obj, set_descriptor, descriptor);
1726 if (remover != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_deleter, remover);
1727 if (enumerator != nullptr)
1728 SET_FIELD_WRAPPED(isolate, obj, set_enumerator, enumerator);
1729 if (definer != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_definer, definer);
1730 obj->set_can_intercept_symbols(
1731 !(static_cast<int>(flags) &
1732 static_cast<int>(PropertyHandlerFlags::kOnlyInterceptStrings)));
1733 obj->set_all_can_read(static_cast<int>(flags) &
1734 static_cast<int>(PropertyHandlerFlags::kAllCanRead));
1735 obj->set_non_masking(static_cast<int>(flags) &
1736 static_cast<int>(PropertyHandlerFlags::kNonMasking));
1737 obj->set_has_no_side_effect(
1738 static_cast<int>(flags) &
1739 static_cast<int>(PropertyHandlerFlags::kHasNoSideEffect));
1740
1741 if (data.IsEmpty()) {
1742 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1743 }
1744 obj->set_data(*Utils::OpenHandle(*data));
1745 return obj;
1746 }
1747
1748 template <typename Getter, typename Setter, typename Query, typename Descriptor,
1749 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)1750 static i::Handle<i::InterceptorInfo> CreateNamedInterceptorInfo(
1751 i::Isolate* isolate, Getter getter, Setter setter, Query query,
1752 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1753 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1754 auto interceptor =
1755 CreateInterceptorInfo(isolate, getter, setter, query, descriptor, remover,
1756 enumerator, definer, data, flags);
1757 interceptor->set_is_named(true);
1758 return interceptor;
1759 }
1760
1761 template <typename Getter, typename Setter, typename Query, typename Descriptor,
1762 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)1763 static i::Handle<i::InterceptorInfo> CreateIndexedInterceptorInfo(
1764 i::Isolate* isolate, Getter getter, Setter setter, Query query,
1765 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1766 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1767 auto interceptor =
1768 CreateInterceptorInfo(isolate, getter, setter, query, descriptor, remover,
1769 enumerator, definer, data, flags);
1770 interceptor->set_is_named(false);
1771 return interceptor;
1772 }
1773
1774 template <typename Getter, typename Setter, typename Query, typename Descriptor,
1775 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)1776 static void ObjectTemplateSetNamedPropertyHandler(
1777 ObjectTemplate* templ, Getter getter, Setter setter, Query query,
1778 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1779 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1780 i::Isolate* isolate = Utils::OpenHandle(templ)->GetIsolate();
1781 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1782 i::HandleScope scope(isolate);
1783 auto cons = EnsureConstructor(isolate, templ);
1784 EnsureNotPublished(cons, "ObjectTemplateSetNamedPropertyHandler");
1785 auto obj =
1786 CreateNamedInterceptorInfo(isolate, getter, setter, query, descriptor,
1787 remover, enumerator, definer, data, flags);
1788 i::FunctionTemplateInfo::SetNamedPropertyHandler(isolate, cons, obj);
1789 }
1790
SetHandler(const NamedPropertyHandlerConfiguration & config)1791 void ObjectTemplate::SetHandler(
1792 const NamedPropertyHandlerConfiguration& config) {
1793 ObjectTemplateSetNamedPropertyHandler(
1794 this, config.getter, config.setter, config.query, config.descriptor,
1795 config.deleter, config.enumerator, config.definer, config.data,
1796 config.flags);
1797 }
1798
MarkAsUndetectable()1799 void ObjectTemplate::MarkAsUndetectable() {
1800 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1801 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1802 i::HandleScope scope(isolate);
1803 auto cons = EnsureConstructor(isolate, this);
1804 EnsureNotPublished(cons, "v8::ObjectTemplate::MarkAsUndetectable");
1805 cons->set_undetectable(true);
1806 }
1807
SetAccessCheckCallback(AccessCheckCallback callback,Local<Value> data)1808 void ObjectTemplate::SetAccessCheckCallback(AccessCheckCallback callback,
1809 Local<Value> data) {
1810 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1811 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1812 i::HandleScope scope(isolate);
1813 auto cons = EnsureConstructor(isolate, this);
1814 EnsureNotPublished(cons, "v8::ObjectTemplate::SetAccessCheckCallback");
1815
1816 i::Handle<i::Struct> struct_info = isolate->factory()->NewStruct(
1817 i::ACCESS_CHECK_INFO_TYPE, i::AllocationType::kOld);
1818 i::Handle<i::AccessCheckInfo> info =
1819 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1820
1821 SET_FIELD_WRAPPED(isolate, info, set_callback, callback);
1822 info->set_named_interceptor(i::Object());
1823 info->set_indexed_interceptor(i::Object());
1824
1825 if (data.IsEmpty()) {
1826 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1827 }
1828 info->set_data(*Utils::OpenHandle(*data));
1829
1830 i::FunctionTemplateInfo::SetAccessCheckInfo(isolate, cons, info);
1831 cons->set_needs_access_check(true);
1832 }
1833
SetAccessCheckCallbackAndHandler(AccessCheckCallback callback,const NamedPropertyHandlerConfiguration & named_handler,const IndexedPropertyHandlerConfiguration & indexed_handler,Local<Value> data)1834 void ObjectTemplate::SetAccessCheckCallbackAndHandler(
1835 AccessCheckCallback callback,
1836 const NamedPropertyHandlerConfiguration& named_handler,
1837 const IndexedPropertyHandlerConfiguration& indexed_handler,
1838 Local<Value> data) {
1839 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1840 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1841 i::HandleScope scope(isolate);
1842 auto cons = EnsureConstructor(isolate, this);
1843 EnsureNotPublished(cons,
1844 "v8::ObjectTemplate::SetAccessCheckCallbackWithHandler");
1845
1846 i::Handle<i::Struct> struct_info = isolate->factory()->NewStruct(
1847 i::ACCESS_CHECK_INFO_TYPE, i::AllocationType::kOld);
1848 i::Handle<i::AccessCheckInfo> info =
1849 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1850
1851 SET_FIELD_WRAPPED(isolate, info, set_callback, callback);
1852 auto named_interceptor = CreateNamedInterceptorInfo(
1853 isolate, named_handler.getter, named_handler.setter, named_handler.query,
1854 named_handler.descriptor, named_handler.deleter, named_handler.enumerator,
1855 named_handler.definer, named_handler.data, named_handler.flags);
1856 info->set_named_interceptor(*named_interceptor);
1857 auto indexed_interceptor = CreateIndexedInterceptorInfo(
1858 isolate, indexed_handler.getter, indexed_handler.setter,
1859 indexed_handler.query, indexed_handler.descriptor,
1860 indexed_handler.deleter, indexed_handler.enumerator,
1861 indexed_handler.definer, indexed_handler.data, indexed_handler.flags);
1862 info->set_indexed_interceptor(*indexed_interceptor);
1863
1864 if (data.IsEmpty()) {
1865 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1866 }
1867 info->set_data(*Utils::OpenHandle(*data));
1868
1869 i::FunctionTemplateInfo::SetAccessCheckInfo(isolate, cons, info);
1870 cons->set_needs_access_check(true);
1871 }
1872
SetHandler(const IndexedPropertyHandlerConfiguration & config)1873 void ObjectTemplate::SetHandler(
1874 const IndexedPropertyHandlerConfiguration& config) {
1875 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1876 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1877 i::HandleScope scope(isolate);
1878 auto cons = EnsureConstructor(isolate, this);
1879 EnsureNotPublished(cons, "v8::ObjectTemplate::SetHandler");
1880 auto obj = CreateIndexedInterceptorInfo(
1881 isolate, config.getter, config.setter, config.query, config.descriptor,
1882 config.deleter, config.enumerator, config.definer, config.data,
1883 config.flags);
1884 i::FunctionTemplateInfo::SetIndexedPropertyHandler(isolate, cons, obj);
1885 }
1886
SetCallAsFunctionHandler(FunctionCallback callback,Local<Value> data)1887 void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback,
1888 Local<Value> data) {
1889 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1890 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1891 i::HandleScope scope(isolate);
1892 auto cons = EnsureConstructor(isolate, this);
1893 EnsureNotPublished(cons, "v8::ObjectTemplate::SetCallAsFunctionHandler");
1894 i::Handle<i::CallHandlerInfo> obj = isolate->factory()->NewCallHandlerInfo();
1895 SET_FIELD_WRAPPED(isolate, obj, set_callback, callback);
1896 SET_FIELD_WRAPPED(isolate, obj, set_js_callback, obj->redirected_callback());
1897 if (data.IsEmpty()) {
1898 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1899 }
1900 obj->set_data(*Utils::OpenHandle(*data));
1901 i::FunctionTemplateInfo::SetInstanceCallHandler(isolate, cons, obj);
1902 }
1903
InternalFieldCount() const1904 int ObjectTemplate::InternalFieldCount() const {
1905 return Utils::OpenHandle(this)->embedder_field_count();
1906 }
1907
SetInternalFieldCount(int value)1908 void ObjectTemplate::SetInternalFieldCount(int value) {
1909 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1910 if (!Utils::ApiCheck(i::Smi::IsValid(value),
1911 "v8::ObjectTemplate::SetInternalFieldCount()",
1912 "Invalid embedder field count")) {
1913 return;
1914 }
1915 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1916 if (value > 0) {
1917 // The embedder field count is set by the constructor function's
1918 // construct code, so we ensure that there is a constructor
1919 // function to do the setting.
1920 EnsureConstructor(isolate, this);
1921 }
1922 Utils::OpenHandle(this)->set_embedder_field_count(value);
1923 }
1924
IsImmutableProto() const1925 bool ObjectTemplate::IsImmutableProto() const {
1926 return Utils::OpenHandle(this)->immutable_proto();
1927 }
1928
SetImmutableProto()1929 void ObjectTemplate::SetImmutableProto() {
1930 auto self = Utils::OpenHandle(this);
1931 i::Isolate* isolate = self->GetIsolate();
1932 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1933 self->set_immutable_proto(true);
1934 }
1935
IsCodeLike() const1936 bool ObjectTemplate::IsCodeLike() const {
1937 return Utils::OpenHandle(this)->code_like();
1938 }
1939
SetCodeLike()1940 void ObjectTemplate::SetCodeLike() {
1941 auto self = Utils::OpenHandle(this);
1942 i::Isolate* isolate = self->GetIsolate();
1943 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1944 self->set_code_like(true);
1945 }
1946
1947 // --- S c r i p t s ---
1948
1949 // Internally, UnboundScript is a SharedFunctionInfo, and Script is a
1950 // JSFunction.
1951
CachedData(const uint8_t * data_,int length_,BufferPolicy buffer_policy_)1952 ScriptCompiler::CachedData::CachedData(const uint8_t* data_, int length_,
1953 BufferPolicy buffer_policy_)
1954 : data(data_),
1955 length(length_),
1956 rejected(false),
1957 buffer_policy(buffer_policy_) {}
1958
~CachedData()1959 ScriptCompiler::CachedData::~CachedData() {
1960 if (buffer_policy == BufferOwned) {
1961 delete[] data;
1962 }
1963 }
1964
SetBookmark()1965 bool ScriptCompiler::ExternalSourceStream::SetBookmark() { return false; }
1966
ResetToBookmark()1967 void ScriptCompiler::ExternalSourceStream::ResetToBookmark() { UNREACHABLE(); }
1968
StreamedSource(std::unique_ptr<ExternalSourceStream> stream,Encoding encoding)1969 ScriptCompiler::StreamedSource::StreamedSource(
1970 std::unique_ptr<ExternalSourceStream> stream, Encoding encoding)
1971 : impl_(new i::ScriptStreamingData(std::move(stream), encoding)) {}
1972
1973 ScriptCompiler::StreamedSource::~StreamedSource() = default;
1974
BindToCurrentContext()1975 Local<Script> UnboundScript::BindToCurrentContext() {
1976 auto function_info =
1977 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1978 i::Isolate* isolate = function_info->GetIsolate();
1979 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1980 i::Handle<i::JSFunction> function =
1981 i::Factory::JSFunctionBuilder{isolate, function_info,
1982 isolate->native_context()}
1983 .Build();
1984 return ToApiHandle<Script>(function);
1985 }
1986
GetId() const1987 int UnboundScript::GetId() const {
1988 auto function_info = i::SharedFunctionInfo::cast(*Utils::OpenHandle(this));
1989 i::Isolate* isolate = function_info.GetIsolate();
1990 LOG_API(isolate, UnboundScript, GetId);
1991 return i::Script::cast(function_info.script()).id();
1992 }
1993
GetLineNumber(int code_pos)1994 int UnboundScript::GetLineNumber(int code_pos) {
1995 i::Handle<i::SharedFunctionInfo> obj =
1996 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1997 i::Isolate* isolate = obj->GetIsolate();
1998 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1999 LOG_API(isolate, UnboundScript, GetLineNumber);
2000 if (obj->script().IsScript()) {
2001 i::Handle<i::Script> script(i::Script::cast(obj->script()), isolate);
2002 return i::Script::GetLineNumber(script, code_pos);
2003 } else {
2004 return -1;
2005 }
2006 }
2007
GetScriptName()2008 Local<Value> UnboundScript::GetScriptName() {
2009 i::Handle<i::SharedFunctionInfo> obj =
2010 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
2011 i::Isolate* isolate = obj->GetIsolate();
2012 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2013 LOG_API(isolate, UnboundScript, GetName);
2014 if (obj->script().IsScript()) {
2015 i::Object name = i::Script::cast(obj->script()).name();
2016 return Utils::ToLocal(i::Handle<i::Object>(name, isolate));
2017 } else {
2018 return Local<String>();
2019 }
2020 }
2021
GetSourceURL()2022 Local<Value> UnboundScript::GetSourceURL() {
2023 i::Handle<i::SharedFunctionInfo> obj =
2024 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
2025 i::Isolate* isolate = obj->GetIsolate();
2026 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2027 LOG_API(isolate, UnboundScript, GetSourceURL);
2028 if (obj->script().IsScript()) {
2029 i::Object url = i::Script::cast(obj->script()).source_url();
2030 return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
2031 } else {
2032 return Local<String>();
2033 }
2034 }
2035
GetSourceMappingURL()2036 Local<Value> UnboundScript::GetSourceMappingURL() {
2037 i::Handle<i::SharedFunctionInfo> obj =
2038 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
2039 i::Isolate* isolate = obj->GetIsolate();
2040 LOG_API(isolate, UnboundScript, GetSourceMappingURL);
2041 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2042 if (obj->script().IsScript()) {
2043 i::Object url = i::Script::cast(obj->script()).source_mapping_url();
2044 return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
2045 } else {
2046 return Local<String>();
2047 }
2048 }
2049
Run(Local<Context> context)2050 MaybeLocal<Value> Script::Run(Local<Context> context) {
2051 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
2052 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
2053 ENTER_V8(isolate, context, Script, Run, MaybeLocal<Value>(),
2054 InternalEscapableScope);
2055 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
2056 i::NestedTimedHistogramScope execute_timer(
2057 isolate->counters()->execute_precise());
2058 i::AggregatingHistogramTimerScope histogram_timer(
2059 isolate->counters()->compile_lazy());
2060 auto fun = i::Handle<i::JSFunction>::cast(Utils::OpenHandle(this));
2061
2062 // TODO(crbug.com/1193459): remove once ablation study is completed
2063 base::ElapsedTimer timer;
2064 base::TimeDelta delta;
2065 if (i::FLAG_script_delay > 0) {
2066 delta = v8::base::TimeDelta::FromMillisecondsD(i::FLAG_script_delay);
2067 }
2068 if (i::FLAG_script_delay_once > 0 && !isolate->did_run_script_delay()) {
2069 delta = v8::base::TimeDelta::FromMillisecondsD(i::FLAG_script_delay_once);
2070 isolate->set_did_run_script_delay(true);
2071 }
2072 if (i::FLAG_script_delay_fraction > 0.0) {
2073 timer.Start();
2074 } else if (delta.InMicroseconds() > 0) {
2075 timer.Start();
2076 while (timer.Elapsed() < delta) {
2077 // Busy wait.
2078 }
2079 }
2080
2081 i::Handle<i::Object> receiver = isolate->global_proxy();
2082 Local<Value> result;
2083 has_pending_exception = !ToLocal<Value>(
2084 i::Execution::Call(isolate, fun, receiver, 0, nullptr), &result);
2085
2086 if (i::FLAG_script_delay_fraction > 0.0) {
2087 delta = v8::base::TimeDelta::FromMillisecondsD(
2088 timer.Elapsed().InMillisecondsF() * i::FLAG_script_delay_fraction);
2089 timer.Restart();
2090 while (timer.Elapsed() < delta) {
2091 // Busy wait.
2092 }
2093 }
2094
2095 RETURN_ON_FAILED_EXECUTION(Value);
2096 RETURN_ESCAPED(result);
2097 }
2098
GetResourceName()2099 Local<Value> ScriptOrModule::GetResourceName() {
2100 i::Handle<i::Script> obj = Utils::OpenHandle(this);
2101 i::Isolate* isolate = obj->GetIsolate();
2102 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2103 i::Handle<i::Object> val(obj->name(), isolate);
2104 return ToApiHandle<Value>(val);
2105 }
2106
GetHostDefinedOptions()2107 Local<PrimitiveArray> ScriptOrModule::GetHostDefinedOptions() {
2108 i::Handle<i::Script> obj = Utils::OpenHandle(this);
2109 i::Isolate* isolate = obj->GetIsolate();
2110 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2111 i::Handle<i::FixedArray> val(obj->host_defined_options(), isolate);
2112 return ToApiHandle<PrimitiveArray>(val);
2113 }
2114
GetUnboundScript()2115 Local<UnboundScript> Script::GetUnboundScript() {
2116 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2117 i::SharedFunctionInfo sfi = i::JSFunction::cast(*obj).shared();
2118 i::Isolate* isolate = sfi.GetIsolate();
2119 return ToApiHandle<UnboundScript>(i::handle(sfi, isolate));
2120 }
2121
2122 // static
New(Isolate * v8_isolate,int length)2123 Local<PrimitiveArray> PrimitiveArray::New(Isolate* v8_isolate, int length) {
2124 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2125 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2126 Utils::ApiCheck(length >= 0, "v8::PrimitiveArray::New",
2127 "length must be equal or greater than zero");
2128 i::Handle<i::FixedArray> array = isolate->factory()->NewFixedArray(length);
2129 return ToApiHandle<PrimitiveArray>(array);
2130 }
2131
Length() const2132 int PrimitiveArray::Length() const {
2133 i::Handle<i::FixedArray> array = Utils::OpenHandle(this);
2134 return array->length();
2135 }
2136
Set(Isolate * v8_isolate,int index,Local<Primitive> item)2137 void PrimitiveArray::Set(Isolate* v8_isolate, int index,
2138 Local<Primitive> item) {
2139 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2140 i::Handle<i::FixedArray> array = Utils::OpenHandle(this);
2141 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2142 Utils::ApiCheck(index >= 0 && index < array->length(),
2143 "v8::PrimitiveArray::Set",
2144 "index must be greater than or equal to 0 and less than the "
2145 "array length");
2146 i::Handle<i::Object> i_item = Utils::OpenHandle(*item);
2147 array->set(index, *i_item);
2148 }
2149
Get(Isolate * v8_isolate,int index)2150 Local<Primitive> PrimitiveArray::Get(Isolate* v8_isolate, int index) {
2151 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2152 i::Handle<i::FixedArray> array = Utils::OpenHandle(this);
2153 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2154 Utils::ApiCheck(index >= 0 && index < array->length(),
2155 "v8::PrimitiveArray::Get",
2156 "index must be greater than or equal to 0 and less than the "
2157 "array length");
2158 i::Handle<i::Object> i_item(array->get(index), isolate);
2159 return ToApiHandle<Primitive>(i_item);
2160 }
2161
Length() const2162 int FixedArray::Length() const {
2163 i::Handle<i::FixedArray> self = Utils::OpenHandle(this);
2164 return self->length();
2165 }
2166
Get(Local<Context> context,int i) const2167 Local<Data> FixedArray::Get(Local<Context> context, int i) const {
2168 i::Handle<i::FixedArray> self = Utils::OpenHandle(this);
2169 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
2170 CHECK_LT(i, self->length());
2171 i::Handle<i::Object> entry(self->get(i), isolate);
2172 return ToApiHandle<Data>(entry);
2173 }
2174
GetSpecifier() const2175 Local<String> ModuleRequest::GetSpecifier() const {
2176 i::Handle<i::ModuleRequest> self = Utils::OpenHandle(this);
2177 i::Isolate* isolate = self->GetIsolate();
2178 return ToApiHandle<String>(i::handle(self->specifier(), isolate));
2179 }
2180
GetSourceOffset() const2181 int ModuleRequest::GetSourceOffset() const {
2182 return Utils::OpenHandle(this)->position();
2183 }
2184
GetImportAssertions() const2185 Local<FixedArray> ModuleRequest::GetImportAssertions() const {
2186 i::Handle<i::ModuleRequest> self = Utils::OpenHandle(this);
2187 i::Isolate* isolate = self->GetIsolate();
2188 return ToApiHandle<FixedArray>(i::handle(self->import_assertions(), isolate));
2189 }
2190
GetStatus() const2191 Module::Status Module::GetStatus() const {
2192 i::Handle<i::Module> self = Utils::OpenHandle(this);
2193 switch (self->status()) {
2194 case i::Module::kUnlinked:
2195 case i::Module::kPreLinking:
2196 return kUninstantiated;
2197 case i::Module::kLinking:
2198 return kInstantiating;
2199 case i::Module::kLinked:
2200 return kInstantiated;
2201 case i::Module::kEvaluating:
2202 case i::Module::kEvaluatingAsync:
2203 return kEvaluating;
2204 case i::Module::kEvaluated:
2205 return kEvaluated;
2206 case i::Module::kErrored:
2207 return kErrored;
2208 }
2209 UNREACHABLE();
2210 }
2211
GetException() const2212 Local<Value> Module::GetException() const {
2213 Utils::ApiCheck(GetStatus() == kErrored, "v8::Module::GetException",
2214 "Module status must be kErrored");
2215 i::Handle<i::Module> self = Utils::OpenHandle(this);
2216 i::Isolate* isolate = self->GetIsolate();
2217 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2218 return ToApiHandle<Value>(i::handle(self->GetException(), isolate));
2219 }
2220
GetModuleRequestsLength() const2221 int Module::GetModuleRequestsLength() const {
2222 i::Module self = *Utils::OpenHandle(this);
2223 if (self.IsSyntheticModule()) return 0;
2224 ASSERT_NO_SCRIPT_NO_EXCEPTION(self.GetIsolate());
2225 return i::SourceTextModule::cast(self).info().module_requests().length();
2226 }
2227
GetModuleRequest(int i) const2228 Local<String> Module::GetModuleRequest(int i) const {
2229 Utils::ApiCheck(i >= 0, "v8::Module::GetModuleRequest",
2230 "index must be positive");
2231 i::Handle<i::Module> self = Utils::OpenHandle(this);
2232 Utils::ApiCheck(self->IsSourceTextModule(), "v8::Module::GetModuleRequest",
2233 "Expected SourceTextModule");
2234 i::Isolate* isolate = self->GetIsolate();
2235 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2236 i::Handle<i::FixedArray> module_requests(
2237 i::Handle<i::SourceTextModule>::cast(self)->info().module_requests(),
2238 isolate);
2239 Utils::ApiCheck(i < module_requests->length(), "v8::Module::GetModuleRequest",
2240 "index is out of bounds");
2241 i::Handle<i::ModuleRequest> module_request(
2242 i::ModuleRequest::cast(module_requests->get(i)), isolate);
2243 return ToApiHandle<String>(i::handle(module_request->specifier(), isolate));
2244 }
2245
GetModuleRequestLocation(int i) const2246 Location Module::GetModuleRequestLocation(int i) const {
2247 Utils::ApiCheck(i >= 0, "v8::Module::GetModuleRequest",
2248 "index must be positive");
2249 i::Handle<i::Module> self = Utils::OpenHandle(this);
2250 i::Isolate* isolate = self->GetIsolate();
2251 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2252 i::HandleScope scope(isolate);
2253 Utils::ApiCheck(self->IsSourceTextModule(),
2254 "Module::GetModuleRequestLocation",
2255 "Expected SourceTextModule");
2256 i::Handle<i::FixedArray> module_requests(
2257 i::Handle<i::SourceTextModule>::cast(self)->info().module_requests(),
2258 isolate);
2259 Utils::ApiCheck(i < module_requests->length(), "v8::Module::GetModuleRequest",
2260 "index is out of bounds");
2261 i::Handle<i::ModuleRequest> module_request(
2262 i::ModuleRequest::cast(module_requests->get(i)), isolate);
2263 int position = module_request->position();
2264 i::Handle<i::Script> script(
2265 i::Handle<i::SourceTextModule>::cast(self)->GetScript(), isolate);
2266 i::Script::PositionInfo info;
2267 i::Script::GetPositionInfo(script, position, &info, i::Script::WITH_OFFSET);
2268 return v8::Location(info.line, info.column);
2269 }
2270
GetModuleRequests() const2271 Local<FixedArray> Module::GetModuleRequests() const {
2272 i::Handle<i::Module> self = Utils::OpenHandle(this);
2273 if (self->IsSyntheticModule()) {
2274 // Synthetic modules are leaf nodes in the module graph. They have no
2275 // ModuleRequests.
2276 return ToApiHandle<FixedArray>(
2277 self->GetReadOnlyRoots().empty_fixed_array_handle());
2278 } else {
2279 i::Isolate* isolate = self->GetIsolate();
2280 i::Handle<i::FixedArray> module_requests(
2281 i::Handle<i::SourceTextModule>::cast(self)->info().module_requests(),
2282 isolate);
2283 return ToApiHandle<FixedArray>(module_requests);
2284 }
2285 }
2286
SourceOffsetToLocation(int offset) const2287 Location Module::SourceOffsetToLocation(int offset) const {
2288 i::Handle<i::Module> self = Utils::OpenHandle(this);
2289 i::Isolate* isolate = self->GetIsolate();
2290 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2291 i::HandleScope scope(isolate);
2292 Utils::ApiCheck(
2293 self->IsSourceTextModule(), "v8::Module::SourceOffsetToLocation",
2294 "v8::Module::SourceOffsetToLocation must be used on an SourceTextModule");
2295 i::Handle<i::Script> script(
2296 i::Handle<i::SourceTextModule>::cast(self)->GetScript(), isolate);
2297 i::Script::PositionInfo info;
2298 i::Script::GetPositionInfo(script, offset, &info, i::Script::WITH_OFFSET);
2299 return v8::Location(info.line, info.column);
2300 }
2301
GetModuleNamespace()2302 Local<Value> Module::GetModuleNamespace() {
2303 Utils::ApiCheck(
2304 GetStatus() >= kInstantiated, "v8::Module::GetModuleNamespace",
2305 "v8::Module::GetModuleNamespace must be used on an instantiated module");
2306 i::Handle<i::Module> self = Utils::OpenHandle(this);
2307 auto isolate = self->GetIsolate();
2308 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2309 i::Handle<i::JSModuleNamespace> module_namespace =
2310 i::Module::GetModuleNamespace(isolate, self);
2311 return ToApiHandle<Value>(module_namespace);
2312 }
2313
GetUnboundModuleScript()2314 Local<UnboundModuleScript> Module::GetUnboundModuleScript() {
2315 i::Handle<i::Module> self = Utils::OpenHandle(this);
2316 Utils::ApiCheck(
2317 self->IsSourceTextModule(), "v8::Module::GetUnboundModuleScript",
2318 "v8::Module::GetUnboundModuleScript must be used on an SourceTextModule");
2319 auto isolate = self->GetIsolate();
2320 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2321 return ToApiHandle<UnboundModuleScript>(i::handle(
2322 i::Handle<i::SourceTextModule>::cast(self)->GetSharedFunctionInfo(),
2323 isolate));
2324 }
2325
ScriptId() const2326 int Module::ScriptId() const {
2327 i::Module self = *Utils::OpenHandle(this);
2328 Utils::ApiCheck(self.IsSourceTextModule(), "v8::Module::ScriptId",
2329 "v8::Module::ScriptId must be used on an SourceTextModule");
2330 ASSERT_NO_SCRIPT_NO_EXCEPTION(self.GetIsolate());
2331 return i::SourceTextModule::cast(self).GetScript().id();
2332 }
2333
IsGraphAsync() const2334 bool Module::IsGraphAsync() const {
2335 Utils::ApiCheck(
2336 GetStatus() >= kInstantiated, "v8::Module::IsGraphAsync",
2337 "v8::Module::IsGraphAsync must be used on an instantiated module");
2338 i::Module self = *Utils::OpenHandle(this);
2339 auto isolate = self.GetIsolate();
2340 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2341 return self.IsGraphAsync(isolate);
2342 }
2343
IsSourceTextModule() const2344 bool Module::IsSourceTextModule() const {
2345 return Utils::OpenHandle(this)->IsSourceTextModule();
2346 }
2347
IsSyntheticModule() const2348 bool Module::IsSyntheticModule() const {
2349 return Utils::OpenHandle(this)->IsSyntheticModule();
2350 }
2351
GetIdentityHash() const2352 int Module::GetIdentityHash() const { return Utils::OpenHandle(this)->hash(); }
2353
InstantiateModule(Local<Context> context,Module::ResolveCallback callback)2354 Maybe<bool> Module::InstantiateModule(Local<Context> context,
2355 Module::ResolveCallback callback) {
2356 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
2357 ENTER_V8(isolate, context, Module, InstantiateModule, Nothing<bool>(),
2358 i::HandleScope);
2359 ResolveModuleCallback callback_with_import_assertions = nullptr;
2360 has_pending_exception =
2361 !i::Module::Instantiate(isolate, Utils::OpenHandle(this), context,
2362 callback_with_import_assertions, callback);
2363 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
2364 return Just(true);
2365 }
2366
InstantiateModule(Local<Context> context,Module::ResolveModuleCallback callback)2367 Maybe<bool> Module::InstantiateModule(Local<Context> context,
2368 Module::ResolveModuleCallback callback) {
2369 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
2370 ENTER_V8(isolate, context, Module, InstantiateModule, Nothing<bool>(),
2371 i::HandleScope);
2372 has_pending_exception = !i::Module::Instantiate(
2373 isolate, Utils::OpenHandle(this), context, callback, nullptr);
2374 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
2375 return Just(true);
2376 }
2377
Evaluate(Local<Context> context)2378 MaybeLocal<Value> Module::Evaluate(Local<Context> context) {
2379 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
2380 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
2381 ENTER_V8(isolate, context, Module, Evaluate, MaybeLocal<Value>(),
2382 InternalEscapableScope);
2383 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
2384 i::NestedTimedHistogramScope execute_timer(
2385 isolate->counters()->execute_precise());
2386 i::AggregatingHistogramTimerScope timer(isolate->counters()->compile_lazy());
2387
2388 i::Handle<i::Module> self = Utils::OpenHandle(this);
2389 Utils::ApiCheck(self->status() >= i::Module::kLinked, "Module::Evaluate",
2390 "Expected instantiated module");
2391
2392 Local<Value> result;
2393 has_pending_exception = !ToLocal(i::Module::Evaluate(isolate, self), &result);
2394 RETURN_ON_FAILED_EXECUTION(Value);
2395 RETURN_ESCAPED(result);
2396 }
2397
CreateSyntheticModule(Isolate * isolate,Local<String> module_name,const std::vector<Local<v8::String>> & export_names,v8::Module::SyntheticModuleEvaluationSteps evaluation_steps)2398 Local<Module> Module::CreateSyntheticModule(
2399 Isolate* isolate, Local<String> module_name,
2400 const std::vector<Local<v8::String>>& export_names,
2401 v8::Module::SyntheticModuleEvaluationSteps evaluation_steps) {
2402 auto i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2403 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
2404 i::Handle<i::String> i_module_name = Utils::OpenHandle(*module_name);
2405 i::Handle<i::FixedArray> i_export_names = i_isolate->factory()->NewFixedArray(
2406 static_cast<int>(export_names.size()));
2407 for (int i = 0; i < i_export_names->length(); ++i) {
2408 i::Handle<i::String> str = i_isolate->factory()->InternalizeString(
2409 Utils::OpenHandle(*export_names[i]));
2410 i_export_names->set(i, *str);
2411 }
2412 return v8::Utils::ToLocal(
2413 i::Handle<i::Module>(i_isolate->factory()->NewSyntheticModule(
2414 i_module_name, i_export_names, evaluation_steps)));
2415 }
2416
SetSyntheticModuleExport(Isolate * isolate,Local<String> export_name,Local<v8::Value> export_value)2417 Maybe<bool> Module::SetSyntheticModuleExport(Isolate* isolate,
2418 Local<String> export_name,
2419 Local<v8::Value> export_value) {
2420 auto i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2421 i::Handle<i::String> i_export_name = Utils::OpenHandle(*export_name);
2422 i::Handle<i::Object> i_export_value = Utils::OpenHandle(*export_value);
2423 i::Handle<i::Module> self = Utils::OpenHandle(this);
2424 Utils::ApiCheck(self->IsSyntheticModule(),
2425 "v8::Module::SyntheticModuleSetExport",
2426 "v8::Module::SyntheticModuleSetExport must only be called on "
2427 "a SyntheticModule");
2428 ENTER_V8_NO_SCRIPT(i_isolate, isolate->GetCurrentContext(), Module,
2429 SetSyntheticModuleExport, Nothing<bool>(), i::HandleScope);
2430 has_pending_exception =
2431 i::SyntheticModule::SetExport(i_isolate,
2432 i::Handle<i::SyntheticModule>::cast(self),
2433 i_export_name, i_export_value)
2434 .IsNothing();
2435 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
2436 return Just(true);
2437 }
2438
2439 namespace {
2440
GetScriptDetails(i::Isolate * isolate,Local<Value> resource_name,int resource_line_offset,int resource_column_offset,Local<Value> source_map_url,Local<PrimitiveArray> host_defined_options,ScriptOriginOptions origin_options)2441 i::ScriptDetails GetScriptDetails(i::Isolate* isolate,
2442 Local<Value> resource_name,
2443 int resource_line_offset,
2444 int resource_column_offset,
2445 Local<Value> source_map_url,
2446 Local<PrimitiveArray> host_defined_options,
2447 ScriptOriginOptions origin_options) {
2448 i::ScriptDetails script_details(Utils::OpenHandle(*(resource_name), true),
2449 origin_options);
2450 script_details.line_offset = resource_line_offset;
2451 script_details.column_offset = resource_column_offset;
2452 script_details.host_defined_options =
2453 host_defined_options.IsEmpty()
2454 ? isolate->factory()->empty_fixed_array()
2455 : Utils::OpenHandle(*(host_defined_options));
2456 if (!source_map_url.IsEmpty()) {
2457 script_details.source_map_url = Utils::OpenHandle(*(source_map_url));
2458 }
2459 return script_details;
2460 }
2461
2462 } // namespace
2463
CompileUnboundInternal(Isolate * v8_isolate,Source * source,CompileOptions options,NoCacheReason no_cache_reason)2464 MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundInternal(
2465 Isolate* v8_isolate, Source* source, CompileOptions options,
2466 NoCacheReason no_cache_reason) {
2467 auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2468 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
2469 ENTER_V8_NO_SCRIPT(isolate, v8_isolate->GetCurrentContext(), ScriptCompiler,
2470 CompileUnbound, MaybeLocal<UnboundScript>(),
2471 InternalEscapableScope);
2472
2473 i::Handle<i::String> str = Utils::OpenHandle(*(source->source_string));
2474
2475 i::Handle<i::SharedFunctionInfo> result;
2476 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileScript");
2477 i::ScriptDetails script_details = GetScriptDetails(
2478 isolate, source->resource_name, source->resource_line_offset,
2479 source->resource_column_offset, source->source_map_url,
2480 source->host_defined_options, source->resource_options);
2481
2482 i::MaybeHandle<i::SharedFunctionInfo> maybe_function_info;
2483 if (options == kConsumeCodeCache) {
2484 if (source->consume_cache_task) {
2485 // Take ownership of the internal deserialization task and clear it off
2486 // the consume task on the source.
2487 DCHECK_NOT_NULL(source->consume_cache_task->impl_);
2488 std::unique_ptr<i::BackgroundDeserializeTask> deserialize_task =
2489 std::move(source->consume_cache_task->impl_);
2490 maybe_function_info =
2491 i::Compiler::GetSharedFunctionInfoForScriptWithDeserializeTask(
2492 isolate, str, script_details, deserialize_task.get(), options,
2493 no_cache_reason, i::NOT_NATIVES_CODE);
2494 source->cached_data->rejected = deserialize_task->rejected();
2495 } else {
2496 DCHECK(source->cached_data);
2497 // AlignedCachedData takes care of pointer-aligning the data.
2498 auto cached_data = std::make_unique<i::AlignedCachedData>(
2499 source->cached_data->data, source->cached_data->length);
2500 maybe_function_info =
2501 i::Compiler::GetSharedFunctionInfoForScriptWithCachedData(
2502 isolate, str, script_details, cached_data.get(), options,
2503 no_cache_reason, i::NOT_NATIVES_CODE);
2504 source->cached_data->rejected = cached_data->rejected();
2505 }
2506 } else {
2507 // Compile without any cache.
2508 maybe_function_info = i::Compiler::GetSharedFunctionInfoForScript(
2509 isolate, str, script_details, options, no_cache_reason,
2510 i::NOT_NATIVES_CODE);
2511 }
2512
2513 has_pending_exception = !maybe_function_info.ToHandle(&result);
2514 RETURN_ON_FAILED_EXECUTION(UnboundScript);
2515 RETURN_ESCAPED(ToApiHandle<UnboundScript>(result));
2516 }
2517
CompileUnboundScript(Isolate * v8_isolate,Source * source,CompileOptions options,NoCacheReason no_cache_reason)2518 MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundScript(
2519 Isolate* v8_isolate, Source* source, CompileOptions options,
2520 NoCacheReason no_cache_reason) {
2521 Utils::ApiCheck(
2522 !source->GetResourceOptions().IsModule(),
2523 "v8::ScriptCompiler::CompileUnboundScript",
2524 "v8::ScriptCompiler::CompileModule must be used to compile modules");
2525 return CompileUnboundInternal(v8_isolate, source, options, no_cache_reason);
2526 }
2527
Compile(Local<Context> context,Source * source,CompileOptions options,NoCacheReason no_cache_reason)2528 MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,
2529 Source* source,
2530 CompileOptions options,
2531 NoCacheReason no_cache_reason) {
2532 Utils::ApiCheck(
2533 !source->GetResourceOptions().IsModule(), "v8::ScriptCompiler::Compile",
2534 "v8::ScriptCompiler::CompileModule must be used to compile modules");
2535 auto isolate = context->GetIsolate();
2536 MaybeLocal<UnboundScript> maybe =
2537 CompileUnboundInternal(isolate, source, options, no_cache_reason);
2538 Local<UnboundScript> result;
2539 if (!maybe.ToLocal(&result)) return MaybeLocal<Script>();
2540 v8::Context::Scope scope(context);
2541 return result->BindToCurrentContext();
2542 }
2543
CompileModule(Isolate * isolate,Source * source,CompileOptions options,NoCacheReason no_cache_reason)2544 MaybeLocal<Module> ScriptCompiler::CompileModule(
2545 Isolate* isolate, Source* source, CompileOptions options,
2546 NoCacheReason no_cache_reason) {
2547 Utils::ApiCheck(options == kNoCompileOptions || options == kConsumeCodeCache,
2548 "v8::ScriptCompiler::CompileModule",
2549 "Invalid CompileOptions");
2550 Utils::ApiCheck(source->GetResourceOptions().IsModule(),
2551 "v8::ScriptCompiler::CompileModule",
2552 "Invalid ScriptOrigin: is_module must be true");
2553 MaybeLocal<UnboundScript> maybe =
2554 CompileUnboundInternal(isolate, source, options, no_cache_reason);
2555 Local<UnboundScript> unbound;
2556 if (!maybe.ToLocal(&unbound)) return MaybeLocal<Module>();
2557 i::Handle<i::SharedFunctionInfo> shared = Utils::OpenHandle(*unbound);
2558 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2559 return ToApiHandle<Module>(i_isolate->factory()->NewSourceTextModule(shared));
2560 }
2561
2562 namespace {
IsIdentifier(i::Isolate * isolate,i::Handle<i::String> string)2563 bool IsIdentifier(i::Isolate* isolate, i::Handle<i::String> string) {
2564 string = i::String::Flatten(isolate, string);
2565 const int length = string->length();
2566 if (length == 0) return false;
2567 if (!i::IsIdentifierStart(string->Get(0))) return false;
2568 i::DisallowGarbageCollection no_gc;
2569 i::String::FlatContent flat = string->GetFlatContent(no_gc);
2570 if (flat.IsOneByte()) {
2571 auto vector = flat.ToOneByteVector();
2572 for (int i = 1; i < length; i++) {
2573 if (!i::IsIdentifierPart(vector[i])) return false;
2574 }
2575 } else {
2576 auto vector = flat.ToUC16Vector();
2577 for (int i = 1; i < length; i++) {
2578 if (!i::IsIdentifierPart(vector[i])) return false;
2579 }
2580 }
2581 return true;
2582 }
2583 } // anonymous namespace
2584
CompileFunctionInContext(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)2585 MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext(
2586 Local<Context> v8_context, Source* source, size_t arguments_count,
2587 Local<String> arguments[], size_t context_extension_count,
2588 Local<Object> context_extensions[], CompileOptions options,
2589 NoCacheReason no_cache_reason,
2590 Local<ScriptOrModule>* script_or_module_out) {
2591 Local<Function> result;
2592
2593 {
2594 PREPARE_FOR_EXECUTION(v8_context, ScriptCompiler, CompileFunctionInContext,
2595 Function);
2596 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
2597
2598 DCHECK(options == CompileOptions::kConsumeCodeCache ||
2599 options == CompileOptions::kEagerCompile ||
2600 options == CompileOptions::kNoCompileOptions);
2601
2602 i::Handle<i::Context> context = Utils::OpenHandle(*v8_context);
2603
2604 DCHECK(context->IsNativeContext());
2605
2606 i::Handle<i::FixedArray> arguments_list =
2607 isolate->factory()->NewFixedArray(static_cast<int>(arguments_count));
2608 for (int i = 0; i < static_cast<int>(arguments_count); i++) {
2609 i::Handle<i::String> argument = Utils::OpenHandle(*arguments[i]);
2610 if (!IsIdentifier(isolate, argument)) return Local<Function>();
2611 arguments_list->set(i, *argument);
2612 }
2613
2614 for (size_t i = 0; i < context_extension_count; ++i) {
2615 i::Handle<i::JSReceiver> extension =
2616 Utils::OpenHandle(*context_extensions[i]);
2617 if (!extension->IsJSObject()) return Local<Function>();
2618 context = isolate->factory()->NewWithContext(
2619 context,
2620 i::ScopeInfo::CreateForWithScope(
2621 isolate,
2622 context->IsNativeContext()
2623 ? i::Handle<i::ScopeInfo>::null()
2624 : i::Handle<i::ScopeInfo>(context->scope_info(), isolate)),
2625 extension);
2626 }
2627
2628 i::ScriptDetails script_details = GetScriptDetails(
2629 isolate, source->resource_name, source->resource_line_offset,
2630 source->resource_column_offset, source->source_map_url,
2631 source->host_defined_options, source->resource_options);
2632
2633 std::unique_ptr<i::AlignedCachedData> cached_data;
2634 if (options == kConsumeCodeCache) {
2635 DCHECK(source->cached_data);
2636 // ScriptData takes care of pointer-aligning the data.
2637 cached_data.reset(new i::AlignedCachedData(source->cached_data->data,
2638 source->cached_data->length));
2639 }
2640
2641 i::Handle<i::JSFunction> scoped_result;
2642 has_pending_exception =
2643 !i::Compiler::GetWrappedFunction(
2644 Utils::OpenHandle(*source->source_string), arguments_list, context,
2645 script_details, cached_data.get(), options, no_cache_reason)
2646 .ToHandle(&scoped_result);
2647 if (options == kConsumeCodeCache) {
2648 source->cached_data->rejected = cached_data->rejected();
2649 }
2650 RETURN_ON_FAILED_EXECUTION(Function);
2651 result = handle_scope.Escape(Utils::CallableToLocal(scoped_result));
2652 }
2653
2654 if (script_or_module_out != nullptr) {
2655 i::Handle<i::JSFunction> function =
2656 i::Handle<i::JSFunction>::cast(Utils::OpenHandle(*result));
2657 i::Isolate* isolate = function->GetIsolate();
2658 i::Handle<i::SharedFunctionInfo> shared(function->shared(), isolate);
2659 i::Handle<i::Script> script(i::Script::cast(shared->script()), isolate);
2660 *script_or_module_out = v8::Utils::ScriptOrModuleToLocal(script);
2661 }
2662
2663 return result;
2664 }
2665
Run()2666 void ScriptCompiler::ScriptStreamingTask::Run() { data_->task->Run(); }
2667
StartStreaming(Isolate * v8_isolate,StreamedSource * source,v8::ScriptType type)2668 ScriptCompiler::ScriptStreamingTask* ScriptCompiler::StartStreaming(
2669 Isolate* v8_isolate, StreamedSource* source, v8::ScriptType type) {
2670 if (!i::FLAG_script_streaming) return nullptr;
2671 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2672 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2673 i::ScriptStreamingData* data = source->impl();
2674 std::unique_ptr<i::BackgroundCompileTask> task =
2675 std::make_unique<i::BackgroundCompileTask>(data, isolate, type);
2676 data->task = std::move(task);
2677 return new ScriptCompiler::ScriptStreamingTask(data);
2678 }
2679
ConsumeCodeCacheTask(std::unique_ptr<i::BackgroundDeserializeTask> impl)2680 ScriptCompiler::ConsumeCodeCacheTask::ConsumeCodeCacheTask(
2681 std::unique_ptr<i::BackgroundDeserializeTask> impl)
2682 : impl_(std::move(impl)) {}
2683
2684 ScriptCompiler::ConsumeCodeCacheTask::~ConsumeCodeCacheTask() = default;
2685
Run()2686 void ScriptCompiler::ConsumeCodeCacheTask::Run() { impl_->Run(); }
2687
StartConsumingCodeCache(Isolate * v8_isolate,std::unique_ptr<CachedData> cached_data)2688 ScriptCompiler::ConsumeCodeCacheTask* ScriptCompiler::StartConsumingCodeCache(
2689 Isolate* v8_isolate, std::unique_ptr<CachedData> cached_data) {
2690 if (!i::FLAG_concurrent_cache_deserialization) return nullptr;
2691 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
2692 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
2693 return new ScriptCompiler::ConsumeCodeCacheTask(
2694 std::make_unique<i::BackgroundDeserializeTask>(isolate,
2695 std::move(cached_data)));
2696 }
2697
2698 namespace {
CompileStreamedSource(i::Isolate * isolate,ScriptCompiler::StreamedSource * v8_source,Local<String> full_source_string,const ScriptOrigin & origin)2699 i::MaybeHandle<i::SharedFunctionInfo> CompileStreamedSource(
2700 i::Isolate* isolate, ScriptCompiler::StreamedSource* v8_source,
2701 Local<String> full_source_string, const ScriptOrigin& origin) {
2702 i::Handle<i::String> str = Utils::OpenHandle(*(full_source_string));
2703 i::ScriptDetails script_details =
2704 GetScriptDetails(isolate, origin.ResourceName(), origin.LineOffset(),
2705 origin.ColumnOffset(), origin.SourceMapUrl(),
2706 origin.HostDefinedOptions(), origin.Options());
2707 i::ScriptStreamingData* data = v8_source->impl();
2708 return i::Compiler::GetSharedFunctionInfoForStreamedScript(
2709 isolate, str, script_details, data);
2710 }
2711
2712 } // namespace
2713
Compile(Local<Context> context,StreamedSource * v8_source,Local<String> full_source_string,const ScriptOrigin & origin)2714 MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,
2715 StreamedSource* v8_source,
2716 Local<String> full_source_string,
2717 const ScriptOrigin& origin) {
2718 PREPARE_FOR_EXECUTION(context, ScriptCompiler, Compile, Script);
2719 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
2720 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
2721 "V8.CompileStreamedScript");
2722 i::Handle<i::SharedFunctionInfo> sfi;
2723 i::MaybeHandle<i::SharedFunctionInfo> maybe_sfi =
2724 CompileStreamedSource(isolate, v8_source, full_source_string, origin);
2725 has_pending_exception = !maybe_sfi.ToHandle(&sfi);
2726 if (has_pending_exception) isolate->ReportPendingMessages();
2727 RETURN_ON_FAILED_EXECUTION(Script);
2728 Local<UnboundScript> generic = ToApiHandle<UnboundScript>(sfi);
2729 if (generic.IsEmpty()) return Local<Script>();
2730 Local<Script> bound = generic->BindToCurrentContext();
2731 if (bound.IsEmpty()) return Local<Script>();
2732 RETURN_ESCAPED(bound);
2733 }
2734
CompileModule(Local<Context> context,StreamedSource * v8_source,Local<String> full_source_string,const ScriptOrigin & origin)2735 MaybeLocal<Module> ScriptCompiler::CompileModule(
2736 Local<Context> context, StreamedSource* v8_source,
2737 Local<String> full_source_string, const ScriptOrigin& origin) {
2738 PREPARE_FOR_EXECUTION(context, ScriptCompiler, Compile, Module);
2739 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
2740 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
2741 "V8.CompileStreamedModule");
2742 i::Handle<i::SharedFunctionInfo> sfi;
2743 i::MaybeHandle<i::SharedFunctionInfo> maybe_sfi =
2744 CompileStreamedSource(isolate, v8_source, full_source_string, origin);
2745 has_pending_exception = !maybe_sfi.ToHandle(&sfi);
2746 if (has_pending_exception) isolate->ReportPendingMessages();
2747 RETURN_ON_FAILED_EXECUTION(Module);
2748 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2749 RETURN_ESCAPED(
2750 ToApiHandle<Module>(i_isolate->factory()->NewSourceTextModule(sfi)));
2751 }
2752
CachedDataVersionTag()2753 uint32_t ScriptCompiler::CachedDataVersionTag() {
2754 return static_cast<uint32_t>(base::hash_combine(
2755 internal::Version::Hash(), internal::FlagList::Hash(),
2756 static_cast<uint32_t>(internal::CpuFeatures::SupportedFeatures())));
2757 }
2758
CreateCodeCache(Local<UnboundScript> unbound_script)2759 ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache(
2760 Local<UnboundScript> unbound_script) {
2761 i::Handle<i::SharedFunctionInfo> shared =
2762 i::Handle<i::SharedFunctionInfo>::cast(
2763 Utils::OpenHandle(*unbound_script));
2764 ASSERT_NO_SCRIPT_NO_EXCEPTION(shared->GetIsolate());
2765 DCHECK(shared->is_toplevel());
2766 return i::CodeSerializer::Serialize(shared);
2767 }
2768
2769 // static
CreateCodeCache(Local<UnboundModuleScript> unbound_module_script)2770 ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache(
2771 Local<UnboundModuleScript> unbound_module_script) {
2772 i::Handle<i::SharedFunctionInfo> shared =
2773 i::Handle<i::SharedFunctionInfo>::cast(
2774 Utils::OpenHandle(*unbound_module_script));
2775 ASSERT_NO_SCRIPT_NO_EXCEPTION(shared->GetIsolate());
2776 DCHECK(shared->is_toplevel());
2777 return i::CodeSerializer::Serialize(shared);
2778 }
2779
CreateCodeCacheForFunction(Local<Function> function)2780 ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCacheForFunction(
2781 Local<Function> function) {
2782 auto js_function =
2783 i::Handle<i::JSFunction>::cast(Utils::OpenHandle(*function));
2784 i::Handle<i::SharedFunctionInfo> shared(js_function->shared(),
2785 js_function->GetIsolate());
2786 ASSERT_NO_SCRIPT_NO_EXCEPTION(shared->GetIsolate());
2787 Utils::ApiCheck(shared->is_wrapped(),
2788 "v8::ScriptCompiler::CreateCodeCacheForFunction",
2789 "Expected SharedFunctionInfo with wrapped source code.");
2790 return i::CodeSerializer::Serialize(shared);
2791 }
2792
Compile(Local<Context> context,Local<String> source,ScriptOrigin * origin)2793 MaybeLocal<Script> Script::Compile(Local<Context> context, Local<String> source,
2794 ScriptOrigin* origin) {
2795 if (origin) {
2796 ScriptCompiler::Source script_source(source, *origin);
2797 return ScriptCompiler::Compile(context, &script_source);
2798 }
2799 ScriptCompiler::Source script_source(source);
2800 return ScriptCompiler::Compile(context, &script_source);
2801 }
2802
2803 // --- E x c e p t i o n s ---
2804
TryCatch(v8::Isolate * isolate)2805 v8::TryCatch::TryCatch(v8::Isolate* isolate)
2806 : isolate_(reinterpret_cast<i::Isolate*>(isolate)),
2807 next_(isolate_->try_catch_handler()),
2808 is_verbose_(false),
2809 can_continue_(true),
2810 capture_message_(true),
2811 rethrow_(false),
2812 has_terminated_(false) {
2813 ResetInternal();
2814 // Special handling for simulators which have a separate JS stack.
2815 js_stack_comparable_address_ = static_cast<internal::Address>(
2816 i::SimulatorStack::RegisterJSStackComparableAddress(isolate_));
2817 isolate_->RegisterTryCatchHandler(this);
2818 }
2819
~TryCatch()2820 v8::TryCatch::~TryCatch() {
2821 if (rethrow_) {
2822 v8::Isolate* isolate = reinterpret_cast<Isolate*>(isolate_);
2823 v8::HandleScope scope(isolate);
2824 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(isolate, Exception());
2825 if (HasCaught() && capture_message_) {
2826 // If an exception was caught and rethrow_ is indicated, the saved
2827 // message, script, and location need to be restored to Isolate TLS
2828 // for reuse. capture_message_ needs to be disabled so that Throw()
2829 // does not create a new message.
2830 isolate_->thread_local_top()->rethrowing_message_ = true;
2831 isolate_->RestorePendingMessageFromTryCatch(this);
2832 }
2833 isolate_->UnregisterTryCatchHandler(this);
2834 i::SimulatorStack::UnregisterJSStackComparableAddress(isolate_);
2835 reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc);
2836 DCHECK(!isolate_->thread_local_top()->rethrowing_message_);
2837 } else {
2838 if (HasCaught() && isolate_->has_scheduled_exception()) {
2839 // If an exception was caught but is still scheduled because no API call
2840 // promoted it, then it is canceled to prevent it from being propagated.
2841 // Note that this will not cancel termination exceptions.
2842 isolate_->CancelScheduledExceptionFromTryCatch(this);
2843 }
2844 isolate_->UnregisterTryCatchHandler(this);
2845 i::SimulatorStack::UnregisterJSStackComparableAddress(isolate_);
2846 }
2847 }
2848
operator new(size_t)2849 void* v8::TryCatch::operator new(size_t) { base::OS::Abort(); }
operator new[](size_t)2850 void* v8::TryCatch::operator new[](size_t) { base::OS::Abort(); }
operator delete(void *,size_t)2851 void v8::TryCatch::operator delete(void*, size_t) { base::OS::Abort(); }
operator delete[](void *,size_t)2852 void v8::TryCatch::operator delete[](void*, size_t) { base::OS::Abort(); }
2853
HasCaught() const2854 bool v8::TryCatch::HasCaught() const {
2855 return !i::Object(reinterpret_cast<i::Address>(exception_))
2856 .IsTheHole(isolate_);
2857 }
2858
CanContinue() const2859 bool v8::TryCatch::CanContinue() const { return can_continue_; }
2860
HasTerminated() const2861 bool v8::TryCatch::HasTerminated() const { return has_terminated_; }
2862
ReThrow()2863 v8::Local<v8::Value> v8::TryCatch::ReThrow() {
2864 if (!HasCaught()) return v8::Local<v8::Value>();
2865 rethrow_ = true;
2866 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_));
2867 }
2868
Exception() const2869 v8::Local<Value> v8::TryCatch::Exception() const {
2870 if (HasCaught()) {
2871 // Check for out of memory exception.
2872 i::Object exception(reinterpret_cast<i::Address>(exception_));
2873 return v8::Utils::ToLocal(i::Handle<i::Object>(exception, isolate_));
2874 } else {
2875 return v8::Local<Value>();
2876 }
2877 }
2878
StackTrace(Local<Context> context,Local<Value> exception)2879 MaybeLocal<Value> v8::TryCatch::StackTrace(Local<Context> context,
2880 Local<Value> exception) {
2881 i::Handle<i::Object> i_exception = Utils::OpenHandle(*exception);
2882 if (!i_exception->IsJSObject()) return v8::Local<Value>();
2883 PREPARE_FOR_EXECUTION(context, TryCatch, StackTrace, Value);
2884 auto obj = i::Handle<i::JSObject>::cast(i_exception);
2885 i::Handle<i::String> name = isolate->factory()->stack_string();
2886 Maybe<bool> maybe = i::JSReceiver::HasProperty(obj, name);
2887 has_pending_exception = maybe.IsNothing();
2888 RETURN_ON_FAILED_EXECUTION(Value);
2889 if (!maybe.FromJust()) return v8::Local<Value>();
2890 Local<Value> result;
2891 has_pending_exception =
2892 !ToLocal<Value>(i::JSReceiver::GetProperty(isolate, obj, name), &result);
2893 RETURN_ON_FAILED_EXECUTION(Value);
2894 RETURN_ESCAPED(result);
2895 }
2896
StackTrace(Local<Context> context) const2897 MaybeLocal<Value> v8::TryCatch::StackTrace(Local<Context> context) const {
2898 if (!HasCaught()) return v8::Local<Value>();
2899 return StackTrace(context, Exception());
2900 }
2901
Message() const2902 v8::Local<v8::Message> v8::TryCatch::Message() const {
2903 i::Object message(reinterpret_cast<i::Address>(message_obj_));
2904 DCHECK(message.IsJSMessageObject() || message.IsTheHole(isolate_));
2905 if (HasCaught() && !message.IsTheHole(isolate_)) {
2906 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_));
2907 } else {
2908 return v8::Local<v8::Message>();
2909 }
2910 }
2911
Reset()2912 void v8::TryCatch::Reset() {
2913 if (!rethrow_ && HasCaught() && isolate_->has_scheduled_exception()) {
2914 // If an exception was caught but is still scheduled because no API call
2915 // promoted it, then it is canceled to prevent it from being propagated.
2916 // Note that this will not cancel termination exceptions.
2917 isolate_->CancelScheduledExceptionFromTryCatch(this);
2918 }
2919 ResetInternal();
2920 }
2921
ResetInternal()2922 void v8::TryCatch::ResetInternal() {
2923 i::Object the_hole = i::ReadOnlyRoots(isolate_).the_hole_value();
2924 exception_ = reinterpret_cast<void*>(the_hole.ptr());
2925 message_obj_ = reinterpret_cast<void*>(the_hole.ptr());
2926 }
2927
SetVerbose(bool value)2928 void v8::TryCatch::SetVerbose(bool value) { is_verbose_ = value; }
2929
IsVerbose() const2930 bool v8::TryCatch::IsVerbose() const { return is_verbose_; }
2931
SetCaptureMessage(bool value)2932 void v8::TryCatch::SetCaptureMessage(bool value) { capture_message_ = value; }
2933
2934 // --- M e s s a g e ---
2935
Get() const2936 Local<String> Message::Get() const {
2937 auto self = Utils::OpenHandle(this);
2938 i::Isolate* isolate = self->GetIsolate();
2939 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2940 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2941 i::Handle<i::String> raw_result =
2942 i::MessageHandler::GetMessage(isolate, self);
2943 Local<String> result = Utils::ToLocal(raw_result);
2944 return scope.Escape(result);
2945 }
2946
GetIsolate() const2947 v8::Isolate* Message::GetIsolate() const {
2948 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2949 return reinterpret_cast<Isolate*>(isolate);
2950 }
2951
GetScriptOrigin() const2952 ScriptOrigin Message::GetScriptOrigin() const {
2953 auto self = Utils::OpenHandle(this);
2954 i::Isolate* isolate = self->GetIsolate();
2955 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2956 i::Handle<i::Script> script(self->script(), isolate);
2957 return GetScriptOriginForScript(isolate, script);
2958 }
2959
GetScriptResourceName() const2960 v8::Local<Value> Message::GetScriptResourceName() const {
2961 ASSERT_NO_SCRIPT_NO_EXCEPTION(Utils::OpenHandle(this)->GetIsolate());
2962 return GetScriptOrigin().ResourceName();
2963 }
2964
GetStackTrace() const2965 v8::Local<v8::StackTrace> Message::GetStackTrace() const {
2966 auto self = Utils::OpenHandle(this);
2967 i::Isolate* isolate = self->GetIsolate();
2968 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2969 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2970 i::Handle<i::Object> stackFramesObj(self->stack_frames(), isolate);
2971 if (!stackFramesObj->IsFixedArray()) return v8::Local<v8::StackTrace>();
2972 auto stackTrace = i::Handle<i::FixedArray>::cast(stackFramesObj);
2973 return scope.Escape(Utils::StackTraceToLocal(stackTrace));
2974 }
2975
GetLineNumber(Local<Context> context) const2976 Maybe<int> Message::GetLineNumber(Local<Context> context) const {
2977 auto self = Utils::OpenHandle(this);
2978 i::Isolate* isolate = self->GetIsolate();
2979 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2980 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
2981 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
2982 return Just(self->GetLineNumber());
2983 }
2984
GetStartPosition() const2985 int Message::GetStartPosition() const {
2986 auto self = Utils::OpenHandle(this);
2987 i::Isolate* isolate = self->GetIsolate();
2988 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2989 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
2990 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
2991 return self->GetStartPosition();
2992 }
2993
GetEndPosition() const2994 int Message::GetEndPosition() const {
2995 auto self = Utils::OpenHandle(this);
2996 i::Isolate* isolate = self->GetIsolate();
2997 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
2998 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
2999 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3000 return self->GetEndPosition();
3001 }
3002
ErrorLevel() const3003 int Message::ErrorLevel() const {
3004 auto self = Utils::OpenHandle(this);
3005 ASSERT_NO_SCRIPT_NO_EXCEPTION(self->GetIsolate());
3006 return self->error_level();
3007 }
3008
GetStartColumn() const3009 int Message::GetStartColumn() const {
3010 auto self = Utils::OpenHandle(this);
3011 i::Isolate* isolate = self->GetIsolate();
3012 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3013 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3014 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3015 return self->GetColumnNumber();
3016 }
3017
GetWasmFunctionIndex() const3018 int Message::GetWasmFunctionIndex() const {
3019 #if V8_ENABLE_WEBASSEMBLY
3020 auto self = Utils::OpenHandle(this);
3021 i::Isolate* isolate = self->GetIsolate();
3022 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3023 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3024 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3025 int start_position = self->GetColumnNumber();
3026 if (start_position == -1) return Message::kNoWasmFunctionIndexInfo;
3027
3028 i::Handle<i::Script> script(self->script(), isolate);
3029
3030 if (script->type() != i::Script::TYPE_WASM) {
3031 return Message::kNoWasmFunctionIndexInfo;
3032 }
3033
3034 auto debug_script = ToApiHandle<debug::Script>(script);
3035 return Local<debug::WasmScript>::Cast(debug_script)
3036 ->GetContainingFunction(start_position);
3037 #else
3038 return Message::kNoWasmFunctionIndexInfo;
3039 #endif // V8_ENABLE_WEBASSEMBLY
3040 }
3041
GetStartColumn(Local<Context> context) const3042 Maybe<int> Message::GetStartColumn(Local<Context> context) const {
3043 return Just(GetStartColumn());
3044 }
3045
GetEndColumn() const3046 int Message::GetEndColumn() const {
3047 auto self = Utils::OpenHandle(this);
3048 i::Isolate* isolate = self->GetIsolate();
3049 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3050 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3051 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3052 const int column_number = self->GetColumnNumber();
3053 if (column_number == -1) return -1;
3054 const int start = self->GetStartPosition();
3055 const int end = self->GetEndPosition();
3056 return column_number + (end - start);
3057 }
3058
GetEndColumn(Local<Context> context) const3059 Maybe<int> Message::GetEndColumn(Local<Context> context) const {
3060 return Just(GetEndColumn());
3061 }
3062
IsSharedCrossOrigin() const3063 bool Message::IsSharedCrossOrigin() const {
3064 auto self = Utils::OpenHandle(this);
3065 i::Isolate* isolate = self->GetIsolate();
3066 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3067 return self->script().origin_options().IsSharedCrossOrigin();
3068 }
3069
IsOpaque() const3070 bool Message::IsOpaque() const {
3071 auto self = Utils::OpenHandle(this);
3072 i::Isolate* isolate = self->GetIsolate();
3073 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3074 return self->script().origin_options().IsOpaque();
3075 }
3076
GetSource(Local<Context> context) const3077 MaybeLocal<String> Message::GetSource(Local<Context> context) const {
3078 auto self = Utils::OpenHandle(this);
3079 i::Isolate* isolate = self->GetIsolate();
3080 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3081 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3082 i::Handle<i::String> source(self->GetSource(), isolate);
3083 RETURN_ESCAPED(Utils::ToLocal(source));
3084 }
3085
GetSourceLine(Local<Context> context) const3086 MaybeLocal<String> Message::GetSourceLine(Local<Context> context) const {
3087 auto self = Utils::OpenHandle(this);
3088 i::Isolate* isolate = self->GetIsolate();
3089 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
3090 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
3091 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
3092 RETURN_ESCAPED(Utils::ToLocal(self->GetSourceLine()));
3093 }
3094
PrintCurrentStackTrace(Isolate * isolate,FILE * out)3095 void Message::PrintCurrentStackTrace(Isolate* isolate, FILE* out) {
3096 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
3097 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
3098 std::ostringstream stack_trace_stream;
3099 i_isolate->PrintCurrentStackTrace(stack_trace_stream);
3100 i::PrintF(out, "%s", stack_trace_stream.str().c_str());
3101 }
3102
PrintCurrentStackTrace(Isolate * isolate,std::ostream & out)3103 void Message::PrintCurrentStackTrace(Isolate* isolate, std::ostream& out) {
3104 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
3105 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
3106 i_isolate->PrintCurrentStackTrace(out);
3107 }
3108
3109 // --- S t a c k T r a c e ---
3110
GetFrame(Isolate * v8_isolate,uint32_t index) const3111 Local<StackFrame> StackTrace::GetFrame(Isolate* v8_isolate,
3112 uint32_t index) const {
3113 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3114 i::Handle<i::StackFrameInfo> frame(
3115 i::StackFrameInfo::cast(Utils::OpenHandle(this)->get(index)), isolate);
3116 return Utils::StackFrameToLocal(frame);
3117 }
3118
GetFrameCount() const3119 int StackTrace::GetFrameCount() const {
3120 return Utils::OpenHandle(this)->length();
3121 }
3122
CurrentStackTrace(Isolate * isolate,int frame_limit,StackTraceOptions options)3123 Local<StackTrace> StackTrace::CurrentStackTrace(Isolate* isolate,
3124 int frame_limit,
3125 StackTraceOptions options) {
3126 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
3127 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
3128 i::Handle<i::FixedArray> stackTrace =
3129 i_isolate->CaptureCurrentStackTrace(frame_limit, options);
3130 return Utils::StackTraceToLocal(stackTrace);
3131 }
3132
3133 // --- S t a c k F r a m e ---
3134
GetLineNumber() const3135 int StackFrame::GetLineNumber() const {
3136 return i::StackFrameInfo::GetLineNumber(Utils::OpenHandle(this));
3137 }
3138
GetColumn() const3139 int StackFrame::GetColumn() const {
3140 return i::StackFrameInfo::GetColumnNumber(Utils::OpenHandle(this));
3141 }
3142
GetScriptId() const3143 int StackFrame::GetScriptId() const {
3144 return Utils::OpenHandle(this)->GetScriptId();
3145 }
3146
GetScriptName() const3147 Local<String> StackFrame::GetScriptName() const {
3148 auto self = Utils::OpenHandle(this);
3149 auto isolate = self->GetIsolate();
3150 i::Handle<i::Object> name(self->GetScriptName(), isolate);
3151 if (!name->IsString()) return {};
3152 return Local<String>::Cast(Utils::ToLocal(name));
3153 }
3154
GetScriptNameOrSourceURL() const3155 Local<String> StackFrame::GetScriptNameOrSourceURL() const {
3156 auto self = Utils::OpenHandle(this);
3157 auto isolate = self->GetIsolate();
3158 i::Handle<i::Object> name_or_url(self->GetScriptNameOrSourceURL(), isolate);
3159 if (!name_or_url->IsString()) return {};
3160 return Local<String>::Cast(Utils::ToLocal(name_or_url));
3161 }
3162
GetScriptSource() const3163 Local<String> StackFrame::GetScriptSource() const {
3164 auto self = Utils::OpenHandle(this);
3165 auto isolate = self->GetIsolate();
3166 i::Handle<i::Object> source(self->GetScriptSource(), isolate);
3167 if (!source->IsString()) return {};
3168 return Local<String>::Cast(Utils::ToLocal(source));
3169 }
3170
GetScriptSourceMappingURL() const3171 Local<String> StackFrame::GetScriptSourceMappingURL() const {
3172 auto self = Utils::OpenHandle(this);
3173 auto isolate = self->GetIsolate();
3174 i::Handle<i::Object> sourceMappingURL(self->GetScriptSourceMappingURL(),
3175 isolate);
3176 if (!sourceMappingURL->IsString()) return {};
3177 return Local<String>::Cast(Utils::ToLocal(sourceMappingURL));
3178 }
3179
GetFunctionName() const3180 Local<String> StackFrame::GetFunctionName() const {
3181 auto self = Utils::OpenHandle(this);
3182 auto name = i::StackFrameInfo::GetFunctionName(self);
3183 if (!name->IsString()) return {};
3184 return Local<String>::Cast(Utils::ToLocal(name));
3185 }
3186
IsEval() const3187 bool StackFrame::IsEval() const { return Utils::OpenHandle(this)->IsEval(); }
3188
IsConstructor() const3189 bool StackFrame::IsConstructor() const {
3190 return Utils::OpenHandle(this)->IsConstructor();
3191 }
3192
IsWasm() const3193 bool StackFrame::IsWasm() const {
3194 #if V8_ENABLE_WEBASSEMBLY
3195 return Utils::OpenHandle(this)->IsWasm();
3196 #else
3197 return false;
3198 #endif // V8_ENABLE_WEBASSEMBLY
3199 }
3200
IsUserJavaScript() const3201 bool StackFrame::IsUserJavaScript() const {
3202 return Utils::OpenHandle(this)->IsUserJavaScript();
3203 }
3204
3205 // --- J S O N ---
3206
Parse(Local<Context> context,Local<String> json_string)3207 MaybeLocal<Value> JSON::Parse(Local<Context> context,
3208 Local<String> json_string) {
3209 PREPARE_FOR_EXECUTION(context, JSON, Parse, Value);
3210 i::Handle<i::String> string = Utils::OpenHandle(*json_string);
3211 i::Handle<i::String> source = i::String::Flatten(isolate, string);
3212 i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
3213 auto maybe = source->IsOneByteRepresentation()
3214 ? i::JsonParser<uint8_t>::Parse(isolate, source, undefined)
3215 : i::JsonParser<uint16_t>::Parse(isolate, source, undefined);
3216 Local<Value> result;
3217 has_pending_exception = !ToLocal<Value>(maybe, &result);
3218 RETURN_ON_FAILED_EXECUTION(Value);
3219 RETURN_ESCAPED(result);
3220 }
3221
Stringify(Local<Context> context,Local<Value> json_object,Local<String> gap)3222 MaybeLocal<String> JSON::Stringify(Local<Context> context,
3223 Local<Value> json_object,
3224 Local<String> gap) {
3225 PREPARE_FOR_EXECUTION(context, JSON, Stringify, String);
3226 i::Handle<i::Object> object = Utils::OpenHandle(*json_object);
3227 i::Handle<i::Object> replacer = isolate->factory()->undefined_value();
3228 i::Handle<i::String> gap_string = gap.IsEmpty()
3229 ? isolate->factory()->empty_string()
3230 : Utils::OpenHandle(*gap);
3231 i::Handle<i::Object> maybe;
3232 has_pending_exception =
3233 !i::JsonStringify(isolate, object, replacer, gap_string).ToHandle(&maybe);
3234 RETURN_ON_FAILED_EXECUTION(String);
3235 Local<String> result;
3236 has_pending_exception =
3237 !ToLocal<String>(i::Object::ToString(isolate, maybe), &result);
3238 RETURN_ON_FAILED_EXECUTION(String);
3239 RETURN_ESCAPED(result);
3240 }
3241
3242 // --- V a l u e S e r i a l i z a t i o n ---
3243
WriteHostObject(Isolate * v8_isolate,Local<Object> object)3244 Maybe<bool> ValueSerializer::Delegate::WriteHostObject(Isolate* v8_isolate,
3245 Local<Object> object) {
3246 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3247 isolate->ScheduleThrow(*isolate->factory()->NewError(
3248 isolate->error_function(), i::MessageTemplate::kDataCloneError,
3249 Utils::OpenHandle(*object)));
3250 return Nothing<bool>();
3251 }
3252
GetSharedArrayBufferId(Isolate * v8_isolate,Local<SharedArrayBuffer> shared_array_buffer)3253 Maybe<uint32_t> ValueSerializer::Delegate::GetSharedArrayBufferId(
3254 Isolate* v8_isolate, Local<SharedArrayBuffer> shared_array_buffer) {
3255 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3256 isolate->ScheduleThrow(*isolate->factory()->NewError(
3257 isolate->error_function(), i::MessageTemplate::kDataCloneError,
3258 Utils::OpenHandle(*shared_array_buffer)));
3259 return Nothing<uint32_t>();
3260 }
3261
GetWasmModuleTransferId(Isolate * v8_isolate,Local<WasmModuleObject> module)3262 Maybe<uint32_t> ValueSerializer::Delegate::GetWasmModuleTransferId(
3263 Isolate* v8_isolate, Local<WasmModuleObject> module) {
3264 return Nothing<uint32_t>();
3265 }
3266
ReallocateBufferMemory(void * old_buffer,size_t size,size_t * actual_size)3267 void* ValueSerializer::Delegate::ReallocateBufferMemory(void* old_buffer,
3268 size_t size,
3269 size_t* actual_size) {
3270 *actual_size = size;
3271 return base::Realloc(old_buffer, size);
3272 }
3273
FreeBufferMemory(void * buffer)3274 void ValueSerializer::Delegate::FreeBufferMemory(void* buffer) {
3275 return base::Free(buffer);
3276 }
3277
3278 struct ValueSerializer::PrivateData {
PrivateDatav8::ValueSerializer::PrivateData3279 explicit PrivateData(i::Isolate* i, ValueSerializer::Delegate* delegate)
3280 : isolate(i), serializer(i, delegate) {}
3281 i::Isolate* isolate;
3282 i::ValueSerializer serializer;
3283 };
3284
ValueSerializer(Isolate * isolate)3285 ValueSerializer::ValueSerializer(Isolate* isolate)
3286 : ValueSerializer(isolate, nullptr) {}
3287
ValueSerializer(Isolate * isolate,Delegate * delegate)3288 ValueSerializer::ValueSerializer(Isolate* isolate, Delegate* delegate)
3289 : private_(
3290 new PrivateData(reinterpret_cast<i::Isolate*>(isolate), delegate)) {}
3291
~ValueSerializer()3292 ValueSerializer::~ValueSerializer() { delete private_; }
3293
WriteHeader()3294 void ValueSerializer::WriteHeader() { private_->serializer.WriteHeader(); }
3295
SetTreatArrayBufferViewsAsHostObjects(bool mode)3296 void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) {
3297 private_->serializer.SetTreatArrayBufferViewsAsHostObjects(mode);
3298 }
3299
WriteValue(Local<Context> context,Local<Value> value)3300 Maybe<bool> ValueSerializer::WriteValue(Local<Context> context,
3301 Local<Value> value) {
3302 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
3303 ENTER_V8(isolate, context, ValueSerializer, WriteValue, Nothing<bool>(),
3304 i::HandleScope);
3305 i::Handle<i::Object> object = Utils::OpenHandle(*value);
3306 Maybe<bool> result = private_->serializer.WriteObject(object);
3307 has_pending_exception = result.IsNothing();
3308 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
3309 return result;
3310 }
3311
Release()3312 std::pair<uint8_t*, size_t> ValueSerializer::Release() {
3313 return private_->serializer.Release();
3314 }
3315
TransferArrayBuffer(uint32_t transfer_id,Local<ArrayBuffer> array_buffer)3316 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id,
3317 Local<ArrayBuffer> array_buffer) {
3318 private_->serializer.TransferArrayBuffer(transfer_id,
3319 Utils::OpenHandle(*array_buffer));
3320 }
3321
WriteUint32(uint32_t value)3322 void ValueSerializer::WriteUint32(uint32_t value) {
3323 private_->serializer.WriteUint32(value);
3324 }
3325
WriteUint64(uint64_t value)3326 void ValueSerializer::WriteUint64(uint64_t value) {
3327 private_->serializer.WriteUint64(value);
3328 }
3329
WriteDouble(double value)3330 void ValueSerializer::WriteDouble(double value) {
3331 private_->serializer.WriteDouble(value);
3332 }
3333
WriteRawBytes(const void * source,size_t length)3334 void ValueSerializer::WriteRawBytes(const void* source, size_t length) {
3335 private_->serializer.WriteRawBytes(source, length);
3336 }
3337
ReadHostObject(Isolate * v8_isolate)3338 MaybeLocal<Object> ValueDeserializer::Delegate::ReadHostObject(
3339 Isolate* v8_isolate) {
3340 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3341 isolate->ScheduleThrow(*isolate->factory()->NewError(
3342 isolate->error_function(),
3343 i::MessageTemplate::kDataCloneDeserializationError));
3344 return MaybeLocal<Object>();
3345 }
3346
GetWasmModuleFromId(Isolate * v8_isolate,uint32_t id)3347 MaybeLocal<WasmModuleObject> ValueDeserializer::Delegate::GetWasmModuleFromId(
3348 Isolate* v8_isolate, uint32_t id) {
3349 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3350 isolate->ScheduleThrow(*isolate->factory()->NewError(
3351 isolate->error_function(),
3352 i::MessageTemplate::kDataCloneDeserializationError));
3353 return MaybeLocal<WasmModuleObject>();
3354 }
3355
3356 MaybeLocal<SharedArrayBuffer>
GetSharedArrayBufferFromId(Isolate * v8_isolate,uint32_t id)3357 ValueDeserializer::Delegate::GetSharedArrayBufferFromId(Isolate* v8_isolate,
3358 uint32_t id) {
3359 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3360 isolate->ScheduleThrow(*isolate->factory()->NewError(
3361 isolate->error_function(),
3362 i::MessageTemplate::kDataCloneDeserializationError));
3363 return MaybeLocal<SharedArrayBuffer>();
3364 }
3365
3366 struct ValueDeserializer::PrivateData {
PrivateDatav8::ValueDeserializer::PrivateData3367 PrivateData(i::Isolate* i, base::Vector<const uint8_t> data,
3368 Delegate* delegate)
3369 : isolate(i), deserializer(i, data, delegate) {}
3370 i::Isolate* isolate;
3371 i::ValueDeserializer deserializer;
3372 bool supports_legacy_wire_format = false;
3373 };
3374
ValueDeserializer(Isolate * isolate,const uint8_t * data,size_t size)3375 ValueDeserializer::ValueDeserializer(Isolate* isolate, const uint8_t* data,
3376 size_t size)
3377 : ValueDeserializer(isolate, data, size, nullptr) {}
3378
ValueDeserializer(Isolate * isolate,const uint8_t * data,size_t size,Delegate * delegate)3379 ValueDeserializer::ValueDeserializer(Isolate* isolate, const uint8_t* data,
3380 size_t size, Delegate* delegate) {
3381 private_ = new PrivateData(reinterpret_cast<i::Isolate*>(isolate),
3382 base::Vector<const uint8_t>(data, size), delegate);
3383 }
3384
~ValueDeserializer()3385 ValueDeserializer::~ValueDeserializer() { delete private_; }
3386
ReadHeader(Local<Context> context)3387 Maybe<bool> ValueDeserializer::ReadHeader(Local<Context> context) {
3388 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
3389 ENTER_V8_NO_SCRIPT(isolate, context, ValueDeserializer, ReadHeader,
3390 Nothing<bool>(), i::HandleScope);
3391
3392 bool read_header = false;
3393 has_pending_exception = !private_->deserializer.ReadHeader().To(&read_header);
3394 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
3395 DCHECK(read_header);
3396
3397 static const uint32_t kMinimumNonLegacyVersion = 13;
3398 if (GetWireFormatVersion() < kMinimumNonLegacyVersion &&
3399 !private_->supports_legacy_wire_format) {
3400 isolate->Throw(*isolate->factory()->NewError(
3401 i::MessageTemplate::kDataCloneDeserializationVersionError));
3402 has_pending_exception = true;
3403 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
3404 }
3405
3406 return Just(true);
3407 }
3408
SetSupportsLegacyWireFormat(bool supports_legacy_wire_format)3409 void ValueDeserializer::SetSupportsLegacyWireFormat(
3410 bool supports_legacy_wire_format) {
3411 private_->supports_legacy_wire_format = supports_legacy_wire_format;
3412 }
3413
GetWireFormatVersion() const3414 uint32_t ValueDeserializer::GetWireFormatVersion() const {
3415 return private_->deserializer.GetWireFormatVersion();
3416 }
3417
ReadValue(Local<Context> context)3418 MaybeLocal<Value> ValueDeserializer::ReadValue(Local<Context> context) {
3419 PREPARE_FOR_EXECUTION(context, ValueDeserializer, ReadValue, Value);
3420 i::MaybeHandle<i::Object> result;
3421 if (GetWireFormatVersion() > 0) {
3422 result = private_->deserializer.ReadObject();
3423 } else {
3424 result =
3425 private_->deserializer.ReadObjectUsingEntireBufferForLegacyFormat();
3426 }
3427 Local<Value> value;
3428 has_pending_exception = !ToLocal(result, &value);
3429 RETURN_ON_FAILED_EXECUTION(Value);
3430 RETURN_ESCAPED(value);
3431 }
3432
TransferArrayBuffer(uint32_t transfer_id,Local<ArrayBuffer> array_buffer)3433 void ValueDeserializer::TransferArrayBuffer(uint32_t transfer_id,
3434 Local<ArrayBuffer> array_buffer) {
3435 private_->deserializer.TransferArrayBuffer(transfer_id,
3436 Utils::OpenHandle(*array_buffer));
3437 }
3438
TransferSharedArrayBuffer(uint32_t transfer_id,Local<SharedArrayBuffer> shared_array_buffer)3439 void ValueDeserializer::TransferSharedArrayBuffer(
3440 uint32_t transfer_id, Local<SharedArrayBuffer> shared_array_buffer) {
3441 private_->deserializer.TransferArrayBuffer(
3442 transfer_id, Utils::OpenHandle(*shared_array_buffer));
3443 }
3444
ReadUint32(uint32_t * value)3445 bool ValueDeserializer::ReadUint32(uint32_t* value) {
3446 return private_->deserializer.ReadUint32(value);
3447 }
3448
ReadUint64(uint64_t * value)3449 bool ValueDeserializer::ReadUint64(uint64_t* value) {
3450 return private_->deserializer.ReadUint64(value);
3451 }
3452
ReadDouble(double * value)3453 bool ValueDeserializer::ReadDouble(double* value) {
3454 return private_->deserializer.ReadDouble(value);
3455 }
3456
ReadRawBytes(size_t length,const void ** data)3457 bool ValueDeserializer::ReadRawBytes(size_t length, const void** data) {
3458 return private_->deserializer.ReadRawBytes(length, data);
3459 }
3460
3461 // --- D a t a ---
3462
FullIsUndefined() const3463 bool Value::FullIsUndefined() const {
3464 i::Handle<i::Object> object = Utils::OpenHandle(this);
3465 bool result = object->IsUndefined();
3466 DCHECK_EQ(result, QuickIsUndefined());
3467 return result;
3468 }
3469
FullIsNull() const3470 bool Value::FullIsNull() const {
3471 i::Handle<i::Object> object = Utils::OpenHandle(this);
3472 bool result = object->IsNull();
3473 DCHECK_EQ(result, QuickIsNull());
3474 return result;
3475 }
3476
IsTrue() const3477 bool Value::IsTrue() const {
3478 i::Object object = *Utils::OpenHandle(this);
3479 if (object.IsSmi()) return false;
3480 return object.IsTrue();
3481 }
3482
IsFalse() const3483 bool Value::IsFalse() const {
3484 i::Object object = *Utils::OpenHandle(this);
3485 if (object.IsSmi()) return false;
3486 return object.IsFalse();
3487 }
3488
IsFunction() const3489 bool Value::IsFunction() const { return Utils::OpenHandle(this)->IsCallable(); }
3490
IsName() const3491 bool Value::IsName() const { return Utils::OpenHandle(this)->IsName(); }
3492
FullIsString() const3493 bool Value::FullIsString() const {
3494 bool result = Utils::OpenHandle(this)->IsString();
3495 DCHECK_EQ(result, QuickIsString());
3496 return result;
3497 }
3498
IsSymbol() const3499 bool Value::IsSymbol() const {
3500 return Utils::OpenHandle(this)->IsPublicSymbol();
3501 }
3502
IsArray() const3503 bool Value::IsArray() const { return Utils::OpenHandle(this)->IsJSArray(); }
3504
IsArrayBuffer() const3505 bool Value::IsArrayBuffer() const {
3506 i::Object obj = *Utils::OpenHandle(this);
3507 if (!obj.IsJSArrayBuffer()) return false;
3508 return !i::JSArrayBuffer::cast(obj).is_shared();
3509 }
3510
IsArrayBufferView() const3511 bool Value::IsArrayBufferView() const {
3512 return Utils::OpenHandle(this)->IsJSArrayBufferView();
3513 }
3514
IsTypedArray() const3515 bool Value::IsTypedArray() const {
3516 return Utils::OpenHandle(this)->IsJSTypedArray();
3517 }
3518
3519 #define VALUE_IS_TYPED_ARRAY(Type, typeName, TYPE, ctype) \
3520 bool Value::Is##Type##Array() const { \
3521 i::Handle<i::Object> obj = Utils::OpenHandle(this); \
3522 return obj->IsJSTypedArray() && \
3523 i::JSTypedArray::cast(*obj).type() == i::kExternal##Type##Array; \
3524 }
3525
TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)3526 TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)
3527
3528 #undef VALUE_IS_TYPED_ARRAY
3529
3530 bool Value::IsDataView() const {
3531 return Utils::OpenHandle(this)->IsJSDataView();
3532 }
3533
IsSharedArrayBuffer() const3534 bool Value::IsSharedArrayBuffer() const {
3535 i::Object obj = *Utils::OpenHandle(this);
3536 if (!obj.IsJSArrayBuffer()) return false;
3537 return i::JSArrayBuffer::cast(obj).is_shared();
3538 }
3539
IsObject() const3540 bool Value::IsObject() const { return Utils::OpenHandle(this)->IsJSReceiver(); }
3541
IsNumber() const3542 bool Value::IsNumber() const { return Utils::OpenHandle(this)->IsNumber(); }
3543
IsBigInt() const3544 bool Value::IsBigInt() const { return Utils::OpenHandle(this)->IsBigInt(); }
3545
IsProxy() const3546 bool Value::IsProxy() const { return Utils::OpenHandle(this)->IsJSProxy(); }
3547
3548 #define VALUE_IS_SPECIFIC_TYPE(Type, Check) \
3549 bool Value::Is##Type() const { \
3550 i::Handle<i::Object> obj = Utils::OpenHandle(this); \
3551 return obj->Is##Check(); \
3552 }
3553
VALUE_IS_SPECIFIC_TYPE(ArgumentsObject,JSArgumentsObject)3554 VALUE_IS_SPECIFIC_TYPE(ArgumentsObject, JSArgumentsObject)
3555 VALUE_IS_SPECIFIC_TYPE(BigIntObject, BigIntWrapper)
3556 VALUE_IS_SPECIFIC_TYPE(BooleanObject, BooleanWrapper)
3557 VALUE_IS_SPECIFIC_TYPE(NumberObject, NumberWrapper)
3558 VALUE_IS_SPECIFIC_TYPE(StringObject, StringWrapper)
3559 VALUE_IS_SPECIFIC_TYPE(SymbolObject, SymbolWrapper)
3560 VALUE_IS_SPECIFIC_TYPE(Date, JSDate)
3561 VALUE_IS_SPECIFIC_TYPE(Map, JSMap)
3562 VALUE_IS_SPECIFIC_TYPE(Set, JSSet)
3563 #if V8_ENABLE_WEBASSEMBLY
3564 VALUE_IS_SPECIFIC_TYPE(WasmMemoryObject, WasmMemoryObject)
3565 VALUE_IS_SPECIFIC_TYPE(WasmModuleObject, WasmModuleObject)
3566 #else
3567 bool Value::IsWasmMemoryObject() const { return false; }
3568 bool Value::IsWasmModuleObject() const { return false; }
3569 #endif // V8_ENABLE_WEBASSEMBLY
3570 VALUE_IS_SPECIFIC_TYPE(WeakMap, JSWeakMap)
3571 VALUE_IS_SPECIFIC_TYPE(WeakSet, JSWeakSet)
3572
3573 #undef VALUE_IS_SPECIFIC_TYPE
3574
3575 bool Value::IsBoolean() const { return Utils::OpenHandle(this)->IsBoolean(); }
3576
IsExternal() const3577 bool Value::IsExternal() const {
3578 i::Object obj = *Utils::OpenHandle(this);
3579 if (!obj.IsHeapObject()) return false;
3580 i::HeapObject heap_obj = i::HeapObject::cast(obj);
3581 // Check the instance type is JS_OBJECT (instance type of Externals) before
3582 // attempting to get the Isolate since that guarantees the object is writable
3583 // and GetIsolate will work.
3584 if (heap_obj.map().instance_type() != i::JS_OBJECT_TYPE) return false;
3585 i::Isolate* isolate = i::JSObject::cast(heap_obj).GetIsolate();
3586 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
3587 return heap_obj.IsExternal(isolate);
3588 }
3589
IsInt32() const3590 bool Value::IsInt32() const {
3591 i::Object obj = *Utils::OpenHandle(this);
3592 if (obj.IsSmi()) return true;
3593 if (obj.IsNumber()) {
3594 return i::IsInt32Double(obj.Number());
3595 }
3596 return false;
3597 }
3598
IsUint32() const3599 bool Value::IsUint32() const {
3600 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3601 if (obj->IsSmi()) return i::Smi::ToInt(*obj) >= 0;
3602 if (obj->IsNumber()) {
3603 double value = obj->Number();
3604 return !i::IsMinusZero(value) && value >= 0 && value <= i::kMaxUInt32 &&
3605 value == i::FastUI2D(i::FastD2UI(value));
3606 }
3607 return false;
3608 }
3609
IsNativeError() const3610 bool Value::IsNativeError() const {
3611 return Utils::OpenHandle(this)->IsJSError();
3612 }
3613
IsRegExp() const3614 bool Value::IsRegExp() const {
3615 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3616 return obj->IsJSRegExp();
3617 }
3618
IsAsyncFunction() const3619 bool Value::IsAsyncFunction() const {
3620 i::Object obj = *Utils::OpenHandle(this);
3621 if (!obj.IsJSFunction()) return false;
3622 i::JSFunction func = i::JSFunction::cast(obj);
3623 return i::IsAsyncFunction(func.shared().kind());
3624 }
3625
IsGeneratorFunction() const3626 bool Value::IsGeneratorFunction() const {
3627 i::Object obj = *Utils::OpenHandle(this);
3628 if (!obj.IsJSFunction()) return false;
3629 i::JSFunction func = i::JSFunction::cast(obj);
3630 ASSERT_NO_SCRIPT_NO_EXCEPTION(func.GetIsolate());
3631 return i::IsGeneratorFunction(func.shared().kind());
3632 }
3633
IsGeneratorObject() const3634 bool Value::IsGeneratorObject() const {
3635 return Utils::OpenHandle(this)->IsJSGeneratorObject();
3636 }
3637
IsMapIterator() const3638 bool Value::IsMapIterator() const {
3639 return Utils::OpenHandle(this)->IsJSMapIterator();
3640 }
3641
IsSetIterator() const3642 bool Value::IsSetIterator() const {
3643 return Utils::OpenHandle(this)->IsJSSetIterator();
3644 }
3645
IsPromise() const3646 bool Value::IsPromise() const { return Utils::OpenHandle(this)->IsJSPromise(); }
3647
IsModuleNamespaceObject() const3648 bool Value::IsModuleNamespaceObject() const {
3649 return Utils::OpenHandle(this)->IsJSModuleNamespace();
3650 }
3651
ToString(Local<Context> context) const3652 MaybeLocal<String> Value::ToString(Local<Context> context) const {
3653 auto obj = Utils::OpenHandle(this);
3654 if (obj->IsString()) return ToApiHandle<String>(obj);
3655 PREPARE_FOR_EXECUTION(context, Object, ToString, String);
3656 Local<String> result;
3657 has_pending_exception =
3658 !ToLocal<String>(i::Object::ToString(isolate, obj), &result);
3659 RETURN_ON_FAILED_EXECUTION(String);
3660 RETURN_ESCAPED(result);
3661 }
3662
ToDetailString(Local<Context> context) const3663 MaybeLocal<String> Value::ToDetailString(Local<Context> context) const {
3664 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3665 if (obj->IsString()) return ToApiHandle<String>(obj);
3666 PREPARE_FOR_EXECUTION(context, Object, ToDetailString, String);
3667 Local<String> result =
3668 Utils::ToLocal(i::Object::NoSideEffectsToString(isolate, obj));
3669 RETURN_ON_FAILED_EXECUTION(String);
3670 RETURN_ESCAPED(result);
3671 }
3672
ToObject(Local<Context> context) const3673 MaybeLocal<Object> Value::ToObject(Local<Context> context) const {
3674 auto obj = Utils::OpenHandle(this);
3675 if (obj->IsJSReceiver()) return ToApiHandle<Object>(obj);
3676 PREPARE_FOR_EXECUTION(context, Object, ToObject, Object);
3677 Local<Object> result;
3678 has_pending_exception =
3679 !ToLocal<Object>(i::Object::ToObject(isolate, obj), &result);
3680 RETURN_ON_FAILED_EXECUTION(Object);
3681 RETURN_ESCAPED(result);
3682 }
3683
ToBigInt(Local<Context> context) const3684 MaybeLocal<BigInt> Value::ToBigInt(Local<Context> context) const {
3685 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3686 if (obj->IsBigInt()) return ToApiHandle<BigInt>(obj);
3687 PREPARE_FOR_EXECUTION(context, Object, ToBigInt, BigInt);
3688 Local<BigInt> result;
3689 has_pending_exception =
3690 !ToLocal<BigInt>(i::BigInt::FromObject(isolate, obj), &result);
3691 RETURN_ON_FAILED_EXECUTION(BigInt);
3692 RETURN_ESCAPED(result);
3693 }
3694
BooleanValue(Isolate * v8_isolate) const3695 bool Value::BooleanValue(Isolate* v8_isolate) const {
3696 return Utils::OpenHandle(this)->BooleanValue(
3697 reinterpret_cast<i::Isolate*>(v8_isolate));
3698 }
3699
ToBoolean(Isolate * v8_isolate) const3700 Local<Boolean> Value::ToBoolean(Isolate* v8_isolate) const {
3701 auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3702 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
3703 return ToApiHandle<Boolean>(
3704 isolate->factory()->ToBoolean(BooleanValue(v8_isolate)));
3705 }
3706
ToNumber(Local<Context> context) const3707 MaybeLocal<Number> Value::ToNumber(Local<Context> context) const {
3708 auto obj = Utils::OpenHandle(this);
3709 if (obj->IsNumber()) return ToApiHandle<Number>(obj);
3710 PREPARE_FOR_EXECUTION(context, Object, ToNumber, Number);
3711 Local<Number> result;
3712 has_pending_exception =
3713 !ToLocal<Number>(i::Object::ToNumber(isolate, obj), &result);
3714 RETURN_ON_FAILED_EXECUTION(Number);
3715 RETURN_ESCAPED(result);
3716 }
3717
ToInteger(Local<Context> context) const3718 MaybeLocal<Integer> Value::ToInteger(Local<Context> context) const {
3719 auto obj = Utils::OpenHandle(this);
3720 if (obj->IsSmi()) return ToApiHandle<Integer>(obj);
3721 PREPARE_FOR_EXECUTION(context, Object, ToInteger, Integer);
3722 Local<Integer> result;
3723 has_pending_exception =
3724 !ToLocal<Integer>(i::Object::ToInteger(isolate, obj), &result);
3725 RETURN_ON_FAILED_EXECUTION(Integer);
3726 RETURN_ESCAPED(result);
3727 }
3728
ToInt32(Local<Context> context) const3729 MaybeLocal<Int32> Value::ToInt32(Local<Context> context) const {
3730 auto obj = Utils::OpenHandle(this);
3731 if (obj->IsSmi()) return ToApiHandle<Int32>(obj);
3732 Local<Int32> result;
3733 PREPARE_FOR_EXECUTION(context, Object, ToInt32, Int32);
3734 has_pending_exception =
3735 !ToLocal<Int32>(i::Object::ToInt32(isolate, obj), &result);
3736 RETURN_ON_FAILED_EXECUTION(Int32);
3737 RETURN_ESCAPED(result);
3738 }
3739
ToUint32(Local<Context> context) const3740 MaybeLocal<Uint32> Value::ToUint32(Local<Context> context) const {
3741 auto obj = Utils::OpenHandle(this);
3742 if (obj->IsSmi()) return ToApiHandle<Uint32>(obj);
3743 Local<Uint32> result;
3744 PREPARE_FOR_EXECUTION(context, Object, ToUint32, Uint32);
3745 has_pending_exception =
3746 !ToLocal<Uint32>(i::Object::ToUint32(isolate, obj), &result);
3747 RETURN_ON_FAILED_EXECUTION(Uint32);
3748 RETURN_ESCAPED(result);
3749 }
3750
DecodeExternalPointerImpl(const i::Isolate * isolate,i::ExternalPointer_t encoded_pointer,ExternalPointerTag tag)3751 i::Address i::DecodeExternalPointerImpl(const i::Isolate* isolate,
3752 i::ExternalPointer_t encoded_pointer,
3753 ExternalPointerTag tag) {
3754 return i::DecodeExternalPointer(isolate, encoded_pointer, tag);
3755 }
3756
IsolateFromNeverReadOnlySpaceObject(i::Address obj)3757 i::Isolate* i::IsolateFromNeverReadOnlySpaceObject(i::Address obj) {
3758 return i::GetIsolateFromWritableObject(i::HeapObject::cast(i::Object(obj)));
3759 }
3760
ShouldThrowOnError(i::Isolate * isolate)3761 bool i::ShouldThrowOnError(i::Isolate* isolate) {
3762 return i::GetShouldThrow(isolate, Nothing<i::ShouldThrow>()) ==
3763 i::ShouldThrow::kThrowOnError;
3764 }
3765
CanHaveInternalField(int instance_type)3766 bool i::CanHaveInternalField(int instance_type) {
3767 return instance_type == i::Internals::kJSObjectType ||
3768 instance_type == i::Internals::kJSSpecialApiObjectType ||
3769 v8::internal::InstanceTypeChecker::IsJSApiObject(
3770 static_cast<v8::internal::InstanceType>(instance_type));
3771 }
3772
CheckInitializedImpl(v8::Isolate * external_isolate)3773 void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
3774 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
3775 Utils::ApiCheck(isolate != nullptr && !isolate->IsDead(),
3776 "v8::internal::Internals::CheckInitialized",
3777 "Isolate is not initialized or V8 has died");
3778 }
3779
CheckCast(Data * that)3780 void v8::Value::CheckCast(Data* that) {
3781 Utils::ApiCheck(that->IsValue(), "v8::Value::Cast", "Data is not a Value");
3782 }
3783
CheckCast(v8::Value * that)3784 void External::CheckCast(v8::Value* that) {
3785 Utils::ApiCheck(that->IsExternal(), "v8::External::Cast",
3786 "Value is not an External");
3787 }
3788
CheckCast(Value * that)3789 void v8::Object::CheckCast(Value* that) {
3790 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3791 Utils::ApiCheck(obj->IsJSReceiver(), "v8::Object::Cast",
3792 "Value is not an Object");
3793 }
3794
CheckCast(Value * that)3795 void v8::Function::CheckCast(Value* that) {
3796 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3797 Utils::ApiCheck(obj->IsCallable(), "v8::Function::Cast",
3798 "Value is not a Function");
3799 }
3800
CheckCast(v8::Data * that)3801 void v8::Boolean::CheckCast(v8::Data* that) {
3802 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3803 Utils::ApiCheck(obj->IsBoolean(), "v8::Boolean::Cast",
3804 "Value is not a Boolean");
3805 }
3806
CheckCast(v8::Data * that)3807 void v8::Name::CheckCast(v8::Data* that) {
3808 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3809 Utils::ApiCheck(obj->IsName(), "v8::Name::Cast", "Value is not a Name");
3810 }
3811
CheckCast(v8::Data * that)3812 void v8::String::CheckCast(v8::Data* that) {
3813 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3814 Utils::ApiCheck(obj->IsString(), "v8::String::Cast", "Value is not a String");
3815 }
3816
CheckCast(v8::Data * that)3817 void v8::Symbol::CheckCast(v8::Data* that) {
3818 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3819 Utils::ApiCheck(obj->IsSymbol(), "v8::Symbol::Cast", "Value is not a Symbol");
3820 }
3821
CheckCast(v8::Data * that)3822 void v8::Private::CheckCast(v8::Data* that) {
3823 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3824 Utils::ApiCheck(
3825 obj->IsSymbol() && i::Handle<i::Symbol>::cast(obj)->is_private(),
3826 "v8::Private::Cast", "Value is not a Private");
3827 }
3828
CheckCast(v8::Data * that)3829 void v8::ModuleRequest::CheckCast(v8::Data* that) {
3830 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3831 Utils::ApiCheck(obj->IsModuleRequest(), "v8::ModuleRequest::Cast",
3832 "Value is not a ModuleRequest");
3833 }
3834
CheckCast(v8::Data * that)3835 void v8::Module::CheckCast(v8::Data* that) {
3836 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3837 Utils::ApiCheck(obj->IsModule(), "v8::Module::Cast", "Value is not a Module");
3838 }
3839
CheckCast(v8::Data * that)3840 void v8::Number::CheckCast(v8::Data* that) {
3841 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3842 Utils::ApiCheck(obj->IsNumber(), "v8::Number::Cast()",
3843 "Value is not a Number");
3844 }
3845
CheckCast(v8::Data * that)3846 void v8::Integer::CheckCast(v8::Data* that) {
3847 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3848 Utils::ApiCheck(obj->IsNumber(), "v8::Integer::Cast",
3849 "Value is not an Integer");
3850 }
3851
CheckCast(v8::Data * that)3852 void v8::Int32::CheckCast(v8::Data* that) {
3853 Utils::ApiCheck(Value::Cast(that)->IsInt32(), "v8::Int32::Cast",
3854 "Value is not a 32-bit signed integer");
3855 }
3856
CheckCast(v8::Data * that)3857 void v8::Uint32::CheckCast(v8::Data* that) {
3858 Utils::ApiCheck(Value::Cast(that)->IsUint32(), "v8::Uint32::Cast",
3859 "Value is not a 32-bit unsigned integer");
3860 }
3861
CheckCast(v8::Data * that)3862 void v8::BigInt::CheckCast(v8::Data* that) {
3863 Utils::ApiCheck(Value::Cast(that)->IsBigInt(), "v8::BigInt::Cast",
3864 "Value is not a BigInt");
3865 }
3866
CheckCast(v8::Data * that)3867 void v8::Context::CheckCast(v8::Data* that) {
3868 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3869 Utils::ApiCheck(obj->IsContext(), "v8::Context::Cast",
3870 "Value is not a Context");
3871 }
3872
CheckCast(Value * that)3873 void v8::Array::CheckCast(Value* that) {
3874 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3875 Utils::ApiCheck(obj->IsJSArray(), "v8::Array::Cast", "Value is not an Array");
3876 }
3877
CheckCast(Value * that)3878 void v8::Map::CheckCast(Value* that) {
3879 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3880 Utils::ApiCheck(obj->IsJSMap(), "v8::Map::Cast", "Value is not a Map");
3881 }
3882
CheckCast(Value * that)3883 void v8::Set::CheckCast(Value* that) {
3884 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3885 Utils::ApiCheck(obj->IsJSSet(), "v8_Set_Cast", "Value is not a Set");
3886 }
3887
CheckCast(Value * that)3888 void v8::Promise::CheckCast(Value* that) {
3889 Utils::ApiCheck(that->IsPromise(), "v8::Promise::Cast",
3890 "Value is not a Promise");
3891 }
3892
CheckCast(Value * that)3893 void v8::Promise::Resolver::CheckCast(Value* that) {
3894 Utils::ApiCheck(that->IsPromise(), "v8::Promise::Resolver::Cast",
3895 "Value is not a Promise::Resolver");
3896 }
3897
CheckCast(Value * that)3898 void v8::Proxy::CheckCast(Value* that) {
3899 Utils::ApiCheck(that->IsProxy(), "v8::Proxy::Cast", "Value is not a Proxy");
3900 }
3901
CheckCast(Value * that)3902 void v8::WasmMemoryObject::CheckCast(Value* that) {
3903 Utils::ApiCheck(that->IsWasmMemoryObject(), "v8::WasmMemoryObject::Cast",
3904 "Value is not a WasmMemoryObject");
3905 }
3906
CheckCast(Value * that)3907 void v8::WasmModuleObject::CheckCast(Value* that) {
3908 Utils::ApiCheck(that->IsWasmModuleObject(), "v8::WasmModuleObject::Cast",
3909 "Value is not a WasmModuleObject");
3910 }
3911
~BackingStore()3912 v8::BackingStore::~BackingStore() {
3913 auto i_this = reinterpret_cast<const i::BackingStore*>(this);
3914 i_this->~BackingStore(); // manually call internal destructor
3915 }
3916
Data() const3917 void* v8::BackingStore::Data() const {
3918 return reinterpret_cast<const i::BackingStore*>(this)->buffer_start();
3919 }
3920
ByteLength() const3921 size_t v8::BackingStore::ByteLength() const {
3922 return reinterpret_cast<const i::BackingStore*>(this)->byte_length();
3923 }
3924
IsShared() const3925 bool v8::BackingStore::IsShared() const {
3926 return reinterpret_cast<const i::BackingStore*>(this)->is_shared();
3927 }
3928
3929 // static
Reallocate(v8::Isolate * isolate,std::unique_ptr<v8::BackingStore> backing_store,size_t byte_length)3930 std::unique_ptr<v8::BackingStore> v8::BackingStore::Reallocate(
3931 v8::Isolate* isolate, std::unique_ptr<v8::BackingStore> backing_store,
3932 size_t byte_length) {
3933 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
3934 LOG_API(i_isolate, ArrayBuffer, BackingStore_Reallocate);
3935 Utils::ApiCheck(byte_length <= i::JSArrayBuffer::kMaxByteLength,
3936 "v8::BackingStore::Reallocate", "byte_lenght is too large");
3937 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
3938 i::BackingStore* i_backing_store =
3939 reinterpret_cast<i::BackingStore*>(backing_store.get());
3940 if (!i_backing_store->Reallocate(i_isolate, byte_length)) {
3941 i::FatalProcessOutOfMemory(i_isolate, "v8::BackingStore::Reallocate");
3942 }
3943 return backing_store;
3944 }
3945
3946 // static
EmptyDeleter(void * data,size_t length,void * deleter_data)3947 void v8::BackingStore::EmptyDeleter(void* data, size_t length,
3948 void* deleter_data) {
3949 DCHECK_NULL(deleter_data);
3950 }
3951
GetBackingStore()3952 std::shared_ptr<v8::BackingStore> v8::ArrayBuffer::GetBackingStore() {
3953 i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
3954 std::shared_ptr<i::BackingStore> backing_store = self->GetBackingStore();
3955 if (!backing_store) {
3956 backing_store =
3957 i::BackingStore::EmptyBackingStore(i::SharedFlag::kNotShared);
3958 }
3959 std::shared_ptr<i::BackingStoreBase> bs_base = backing_store;
3960 return std::static_pointer_cast<v8::BackingStore>(bs_base);
3961 }
3962
GetBackingStore()3963 std::shared_ptr<v8::BackingStore> v8::SharedArrayBuffer::GetBackingStore() {
3964 i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
3965 std::shared_ptr<i::BackingStore> backing_store = self->GetBackingStore();
3966 if (!backing_store) {
3967 backing_store = i::BackingStore::EmptyBackingStore(i::SharedFlag::kShared);
3968 }
3969 std::shared_ptr<i::BackingStoreBase> bs_base = backing_store;
3970 return std::static_pointer_cast<v8::BackingStore>(bs_base);
3971 }
3972
CheckCast(Value * that)3973 void v8::ArrayBuffer::CheckCast(Value* that) {
3974 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3975 Utils::ApiCheck(
3976 obj->IsJSArrayBuffer() && !i::JSArrayBuffer::cast(*obj).is_shared(),
3977 "v8::ArrayBuffer::Cast()", "Value is not an ArrayBuffer");
3978 }
3979
CheckCast(Value * that)3980 void v8::ArrayBufferView::CheckCast(Value* that) {
3981 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3982 Utils::ApiCheck(obj->IsJSArrayBufferView(), "v8::ArrayBufferView::Cast()",
3983 "Value is not an ArrayBufferView");
3984 }
3985
3986 constexpr size_t v8::TypedArray::kMaxLength;
3987
CheckCast(Value * that)3988 void v8::TypedArray::CheckCast(Value* that) {
3989 i::Handle<i::Object> obj = Utils::OpenHandle(that);
3990 Utils::ApiCheck(obj->IsJSTypedArray(), "v8::TypedArray::Cast()",
3991 "Value is not a TypedArray");
3992 }
3993
3994 #define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype) \
3995 void v8::Type##Array::CheckCast(Value* that) { \
3996 i::Handle<i::Object> obj = Utils::OpenHandle(that); \
3997 Utils::ApiCheck( \
3998 obj->IsJSTypedArray() && \
3999 i::JSTypedArray::cast(*obj).type() == i::kExternal##Type##Array, \
4000 "v8::" #Type "Array::Cast()", "Value is not a " #Type "Array"); \
4001 }
4002
TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST)4003 TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST)
4004
4005 #undef CHECK_TYPED_ARRAY_CAST
4006
4007 void v8::DataView::CheckCast(Value* that) {
4008 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4009 Utils::ApiCheck(obj->IsJSDataView(), "v8::DataView::Cast()",
4010 "Value is not a DataView");
4011 }
4012
CheckCast(Value * that)4013 void v8::SharedArrayBuffer::CheckCast(Value* that) {
4014 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4015 Utils::ApiCheck(
4016 obj->IsJSArrayBuffer() && i::JSArrayBuffer::cast(*obj).is_shared(),
4017 "v8::SharedArrayBuffer::Cast()", "Value is not a SharedArrayBuffer");
4018 }
4019
CheckCast(v8::Value * that)4020 void v8::Date::CheckCast(v8::Value* that) {
4021 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4022 Utils::ApiCheck(obj->IsJSDate(), "v8::Date::Cast()", "Value is not a Date");
4023 }
4024
CheckCast(v8::Value * that)4025 void v8::StringObject::CheckCast(v8::Value* that) {
4026 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4027 Utils::ApiCheck(obj->IsStringWrapper(), "v8::StringObject::Cast()",
4028 "Value is not a StringObject");
4029 }
4030
CheckCast(v8::Value * that)4031 void v8::SymbolObject::CheckCast(v8::Value* that) {
4032 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4033 Utils::ApiCheck(obj->IsSymbolWrapper(), "v8::SymbolObject::Cast()",
4034 "Value is not a SymbolObject");
4035 }
4036
CheckCast(v8::Value * that)4037 void v8::NumberObject::CheckCast(v8::Value* that) {
4038 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4039 Utils::ApiCheck(obj->IsNumberWrapper(), "v8::NumberObject::Cast()",
4040 "Value is not a NumberObject");
4041 }
4042
CheckCast(v8::Value * that)4043 void v8::BigIntObject::CheckCast(v8::Value* that) {
4044 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4045 Utils::ApiCheck(obj->IsBigIntWrapper(), "v8::BigIntObject::Cast()",
4046 "Value is not a BigIntObject");
4047 }
4048
CheckCast(v8::Value * that)4049 void v8::BooleanObject::CheckCast(v8::Value* that) {
4050 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4051 Utils::ApiCheck(obj->IsBooleanWrapper(), "v8::BooleanObject::Cast()",
4052 "Value is not a BooleanObject");
4053 }
4054
CheckCast(v8::Value * that)4055 void v8::RegExp::CheckCast(v8::Value* that) {
4056 i::Handle<i::Object> obj = Utils::OpenHandle(that);
4057 Utils::ApiCheck(obj->IsJSRegExp(), "v8::RegExp::Cast()",
4058 "Value is not a RegExp");
4059 }
4060
NumberValue(Local<Context> context) const4061 Maybe<double> Value::NumberValue(Local<Context> context) const {
4062 auto obj = Utils::OpenHandle(this);
4063 if (obj->IsNumber()) return Just(obj->Number());
4064 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4065 ENTER_V8(isolate, context, Value, NumberValue, Nothing<double>(),
4066 i::HandleScope);
4067 i::Handle<i::Object> num;
4068 has_pending_exception = !i::Object::ToNumber(isolate, obj).ToHandle(&num);
4069 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(double);
4070 return Just(num->Number());
4071 }
4072
IntegerValue(Local<Context> context) const4073 Maybe<int64_t> Value::IntegerValue(Local<Context> context) const {
4074 auto obj = Utils::OpenHandle(this);
4075 if (obj->IsNumber()) {
4076 return Just(NumberToInt64(*obj));
4077 }
4078 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4079 ENTER_V8(isolate, context, Value, IntegerValue, Nothing<int64_t>(),
4080 i::HandleScope);
4081 i::Handle<i::Object> num;
4082 has_pending_exception = !i::Object::ToInteger(isolate, obj).ToHandle(&num);
4083 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int64_t);
4084 return Just(NumberToInt64(*num));
4085 }
4086
Int32Value(Local<Context> context) const4087 Maybe<int32_t> Value::Int32Value(Local<Context> context) const {
4088 auto obj = Utils::OpenHandle(this);
4089 if (obj->IsNumber()) return Just(NumberToInt32(*obj));
4090 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4091 ENTER_V8(isolate, context, Value, Int32Value, Nothing<int32_t>(),
4092 i::HandleScope);
4093 i::Handle<i::Object> num;
4094 has_pending_exception = !i::Object::ToInt32(isolate, obj).ToHandle(&num);
4095 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int32_t);
4096 return Just(num->IsSmi() ? i::Smi::ToInt(*num)
4097 : static_cast<int32_t>(num->Number()));
4098 }
4099
Uint32Value(Local<Context> context) const4100 Maybe<uint32_t> Value::Uint32Value(Local<Context> context) const {
4101 auto obj = Utils::OpenHandle(this);
4102 if (obj->IsNumber()) return Just(NumberToUint32(*obj));
4103 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4104 ENTER_V8(isolate, context, Value, Uint32Value, Nothing<uint32_t>(),
4105 i::HandleScope);
4106 i::Handle<i::Object> num;
4107 has_pending_exception = !i::Object::ToUint32(isolate, obj).ToHandle(&num);
4108 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(uint32_t);
4109 return Just(num->IsSmi() ? static_cast<uint32_t>(i::Smi::ToInt(*num))
4110 : static_cast<uint32_t>(num->Number()));
4111 }
4112
ToArrayIndex(Local<Context> context) const4113 MaybeLocal<Uint32> Value::ToArrayIndex(Local<Context> context) const {
4114 auto self = Utils::OpenHandle(this);
4115 if (self->IsSmi()) {
4116 if (i::Smi::ToInt(*self) >= 0) return Utils::Uint32ToLocal(self);
4117 return Local<Uint32>();
4118 }
4119 PREPARE_FOR_EXECUTION(context, Object, ToArrayIndex, Uint32);
4120 i::Handle<i::Object> string_obj;
4121 has_pending_exception =
4122 !i::Object::ToString(isolate, self).ToHandle(&string_obj);
4123 RETURN_ON_FAILED_EXECUTION(Uint32);
4124 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
4125 uint32_t index;
4126 if (str->AsArrayIndex(&index)) {
4127 i::Handle<i::Object> value;
4128 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
4129 value = i::Handle<i::Object>(i::Smi::FromInt(index), isolate);
4130 } else {
4131 value = isolate->factory()->NewNumber(index);
4132 }
4133 RETURN_ESCAPED(Utils::Uint32ToLocal(value));
4134 }
4135 return Local<Uint32>();
4136 }
4137
Equals(Local<Context> context,Local<Value> that) const4138 Maybe<bool> Value::Equals(Local<Context> context, Local<Value> that) const {
4139 i::Isolate* isolate = Utils::OpenHandle(*context)->GetIsolate();
4140 ENTER_V8(isolate, context, Value, Equals, Nothing<bool>(), i::HandleScope);
4141 auto self = Utils::OpenHandle(this);
4142 auto other = Utils::OpenHandle(*that);
4143 Maybe<bool> result = i::Object::Equals(isolate, self, other);
4144 has_pending_exception = result.IsNothing();
4145 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4146 return result;
4147 }
4148
StrictEquals(Local<Value> that) const4149 bool Value::StrictEquals(Local<Value> that) const {
4150 auto self = Utils::OpenHandle(this);
4151 auto other = Utils::OpenHandle(*that);
4152 return self->StrictEquals(*other);
4153 }
4154
SameValue(Local<Value> that) const4155 bool Value::SameValue(Local<Value> that) const {
4156 auto self = Utils::OpenHandle(this);
4157 auto other = Utils::OpenHandle(*that);
4158 return self->SameValue(*other);
4159 }
4160
TypeOf(v8::Isolate * external_isolate)4161 Local<String> Value::TypeOf(v8::Isolate* external_isolate) {
4162 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
4163 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
4164 LOG_API(isolate, Value, TypeOf);
4165 return Utils::ToLocal(i::Object::TypeOf(isolate, Utils::OpenHandle(this)));
4166 }
4167
InstanceOf(v8::Local<v8::Context> context,v8::Local<v8::Object> object)4168 Maybe<bool> Value::InstanceOf(v8::Local<v8::Context> context,
4169 v8::Local<v8::Object> object) {
4170 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4171 ENTER_V8(isolate, context, Value, InstanceOf, Nothing<bool>(),
4172 i::HandleScope);
4173 auto left = Utils::OpenHandle(this);
4174 auto right = Utils::OpenHandle(*object);
4175 i::Handle<i::Object> result;
4176 has_pending_exception =
4177 !i::Object::InstanceOf(isolate, left, right).ToHandle(&result);
4178 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4179 return Just(result->IsTrue(isolate));
4180 }
4181
Set(v8::Local<v8::Context> context,v8::Local<Value> key,v8::Local<Value> value)4182 Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context,
4183 v8::Local<Value> key, v8::Local<Value> value) {
4184 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4185 ENTER_V8(isolate, context, Object, Set, Nothing<bool>(), i::HandleScope);
4186 auto self = Utils::OpenHandle(this);
4187 auto key_obj = Utils::OpenHandle(*key);
4188 auto value_obj = Utils::OpenHandle(*value);
4189 has_pending_exception =
4190 i::Runtime::SetObjectProperty(isolate, self, key_obj, value_obj,
4191 i::StoreOrigin::kMaybeKeyed,
4192 Just(i::ShouldThrow::kDontThrow))
4193 .is_null();
4194 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4195 return Just(true);
4196 }
4197
Set(v8::Local<v8::Context> context,uint32_t index,v8::Local<Value> value)4198 Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context, uint32_t index,
4199 v8::Local<Value> value) {
4200 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4201 ENTER_V8(isolate, context, Object, Set, Nothing<bool>(), i::HandleScope);
4202 auto self = Utils::OpenHandle(this);
4203 auto value_obj = Utils::OpenHandle(*value);
4204 has_pending_exception = i::Object::SetElement(isolate, self, index, value_obj,
4205 i::ShouldThrow::kDontThrow)
4206 .is_null();
4207 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4208 return Just(true);
4209 }
4210
CreateDataProperty(v8::Local<v8::Context> context,v8::Local<Name> key,v8::Local<Value> value)4211 Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context,
4212 v8::Local<Name> key,
4213 v8::Local<Value> value) {
4214 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4215 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4216 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
4217 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
4218
4219 i::PropertyKey lookup_key(isolate, key_obj);
4220 i::LookupIterator it(isolate, self, lookup_key, i::LookupIterator::OWN);
4221 if (self->IsJSProxy()) {
4222 ENTER_V8(isolate, context, Object, CreateDataProperty, Nothing<bool>(),
4223 i::HandleScope);
4224 Maybe<bool> result =
4225 i::JSReceiver::CreateDataProperty(&it, value_obj, Just(i::kDontThrow));
4226 has_pending_exception = result.IsNothing();
4227 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4228 return result;
4229 } else {
4230 ENTER_V8_NO_SCRIPT(isolate, context, Object, CreateDataProperty,
4231 Nothing<bool>(), i::HandleScope);
4232 Maybe<bool> result =
4233 i::JSObject::CreateDataProperty(&it, value_obj, Just(i::kDontThrow));
4234 has_pending_exception = result.IsNothing();
4235 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4236 return result;
4237 }
4238 }
4239
CreateDataProperty(v8::Local<v8::Context> context,uint32_t index,v8::Local<Value> value)4240 Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context,
4241 uint32_t index,
4242 v8::Local<Value> value) {
4243 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4244 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4245 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
4246
4247 i::LookupIterator it(isolate, self, index, self, i::LookupIterator::OWN);
4248 if (self->IsJSProxy()) {
4249 ENTER_V8(isolate, context, Object, CreateDataProperty, Nothing<bool>(),
4250 i::HandleScope);
4251 Maybe<bool> result =
4252 i::JSReceiver::CreateDataProperty(&it, value_obj, Just(i::kDontThrow));
4253 has_pending_exception = result.IsNothing();
4254 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4255 return result;
4256 } else {
4257 ENTER_V8_NO_SCRIPT(isolate, context, Object, CreateDataProperty,
4258 Nothing<bool>(), i::HandleScope);
4259 Maybe<bool> result =
4260 i::JSObject::CreateDataProperty(&it, value_obj, Just(i::kDontThrow));
4261 has_pending_exception = result.IsNothing();
4262 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4263 return result;
4264 }
4265 }
4266
4267 struct v8::PropertyDescriptor::PrivateData {
PrivateDatav8::v8::PropertyDescriptor::PrivateData4268 PrivateData() : desc() {}
4269 i::PropertyDescriptor desc;
4270 };
4271
PropertyDescriptor()4272 v8::PropertyDescriptor::PropertyDescriptor() : private_(new PrivateData()) {}
4273
4274 // DataDescriptor
PropertyDescriptor(v8::Local<v8::Value> value)4275 v8::PropertyDescriptor::PropertyDescriptor(v8::Local<v8::Value> value)
4276 : private_(new PrivateData()) {
4277 private_->desc.set_value(Utils::OpenHandle(*value, true));
4278 }
4279
4280 // DataDescriptor with writable field
PropertyDescriptor(v8::Local<v8::Value> value,bool writable)4281 v8::PropertyDescriptor::PropertyDescriptor(v8::Local<v8::Value> value,
4282 bool writable)
4283 : private_(new PrivateData()) {
4284 private_->desc.set_value(Utils::OpenHandle(*value, true));
4285 private_->desc.set_writable(writable);
4286 }
4287
4288 // AccessorDescriptor
PropertyDescriptor(v8::Local<v8::Value> get,v8::Local<v8::Value> set)4289 v8::PropertyDescriptor::PropertyDescriptor(v8::Local<v8::Value> get,
4290 v8::Local<v8::Value> set)
4291 : private_(new PrivateData()) {
4292 DCHECK(get.IsEmpty() || get->IsUndefined() || get->IsFunction());
4293 DCHECK(set.IsEmpty() || set->IsUndefined() || set->IsFunction());
4294 private_->desc.set_get(Utils::OpenHandle(*get, true));
4295 private_->desc.set_set(Utils::OpenHandle(*set, true));
4296 }
4297
~PropertyDescriptor()4298 v8::PropertyDescriptor::~PropertyDescriptor() { delete private_; }
4299
value() const4300 v8::Local<Value> v8::PropertyDescriptor::value() const {
4301 DCHECK(private_->desc.has_value());
4302 return Utils::ToLocal(private_->desc.value());
4303 }
4304
get() const4305 v8::Local<Value> v8::PropertyDescriptor::get() const {
4306 DCHECK(private_->desc.has_get());
4307 return Utils::ToLocal(private_->desc.get());
4308 }
4309
set() const4310 v8::Local<Value> v8::PropertyDescriptor::set() const {
4311 DCHECK(private_->desc.has_set());
4312 return Utils::ToLocal(private_->desc.set());
4313 }
4314
has_value() const4315 bool v8::PropertyDescriptor::has_value() const {
4316 return private_->desc.has_value();
4317 }
has_get() const4318 bool v8::PropertyDescriptor::has_get() const {
4319 return private_->desc.has_get();
4320 }
has_set() const4321 bool v8::PropertyDescriptor::has_set() const {
4322 return private_->desc.has_set();
4323 }
4324
writable() const4325 bool v8::PropertyDescriptor::writable() const {
4326 DCHECK(private_->desc.has_writable());
4327 return private_->desc.writable();
4328 }
4329
has_writable() const4330 bool v8::PropertyDescriptor::has_writable() const {
4331 return private_->desc.has_writable();
4332 }
4333
set_enumerable(bool enumerable)4334 void v8::PropertyDescriptor::set_enumerable(bool enumerable) {
4335 private_->desc.set_enumerable(enumerable);
4336 }
4337
enumerable() const4338 bool v8::PropertyDescriptor::enumerable() const {
4339 DCHECK(private_->desc.has_enumerable());
4340 return private_->desc.enumerable();
4341 }
4342
has_enumerable() const4343 bool v8::PropertyDescriptor::has_enumerable() const {
4344 return private_->desc.has_enumerable();
4345 }
4346
set_configurable(bool configurable)4347 void v8::PropertyDescriptor::set_configurable(bool configurable) {
4348 private_->desc.set_configurable(configurable);
4349 }
4350
configurable() const4351 bool v8::PropertyDescriptor::configurable() const {
4352 DCHECK(private_->desc.has_configurable());
4353 return private_->desc.configurable();
4354 }
4355
has_configurable() const4356 bool v8::PropertyDescriptor::has_configurable() const {
4357 return private_->desc.has_configurable();
4358 }
4359
DefineOwnProperty(v8::Local<v8::Context> context,v8::Local<Name> key,v8::Local<Value> value,v8::PropertyAttribute attributes)4360 Maybe<bool> v8::Object::DefineOwnProperty(v8::Local<v8::Context> context,
4361 v8::Local<Name> key,
4362 v8::Local<Value> value,
4363 v8::PropertyAttribute attributes) {
4364 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4365 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4366 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
4367 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
4368
4369 i::PropertyDescriptor desc;
4370 desc.set_writable(!(attributes & v8::ReadOnly));
4371 desc.set_enumerable(!(attributes & v8::DontEnum));
4372 desc.set_configurable(!(attributes & v8::DontDelete));
4373 desc.set_value(value_obj);
4374
4375 if (self->IsJSProxy()) {
4376 ENTER_V8(isolate, context, Object, DefineOwnProperty, Nothing<bool>(),
4377 i::HandleScope);
4378 Maybe<bool> success = i::JSReceiver::DefineOwnProperty(
4379 isolate, self, key_obj, &desc, Just(i::kDontThrow));
4380 // Even though we said kDontThrow, there might be accessors that do throw.
4381 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4382 return success;
4383 } else {
4384 // If it's not a JSProxy, i::JSReceiver::DefineOwnProperty should never run
4385 // a script.
4386 ENTER_V8_NO_SCRIPT(isolate, context, Object, DefineOwnProperty,
4387 Nothing<bool>(), i::HandleScope);
4388 Maybe<bool> success = i::JSReceiver::DefineOwnProperty(
4389 isolate, self, key_obj, &desc, Just(i::kDontThrow));
4390 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4391 return success;
4392 }
4393 }
4394
DefineProperty(v8::Local<v8::Context> context,v8::Local<Name> key,PropertyDescriptor & descriptor)4395 Maybe<bool> v8::Object::DefineProperty(v8::Local<v8::Context> context,
4396 v8::Local<Name> key,
4397 PropertyDescriptor& descriptor) {
4398 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4399 ENTER_V8(isolate, context, Object, DefineOwnProperty, Nothing<bool>(),
4400 i::HandleScope);
4401 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4402 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
4403
4404 Maybe<bool> success = i::JSReceiver::DefineOwnProperty(
4405 isolate, self, key_obj, &descriptor.get_private()->desc,
4406 Just(i::kDontThrow));
4407 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4408 return success;
4409 }
4410
SetPrivate(Local<Context> context,Local<Private> key,Local<Value> value)4411 Maybe<bool> v8::Object::SetPrivate(Local<Context> context, Local<Private> key,
4412 Local<Value> value) {
4413 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4414 ENTER_V8_NO_SCRIPT(isolate, context, Object, SetPrivate, Nothing<bool>(),
4415 i::HandleScope);
4416 auto self = Utils::OpenHandle(this);
4417 auto key_obj = Utils::OpenHandle(reinterpret_cast<Name*>(*key));
4418 auto value_obj = Utils::OpenHandle(*value);
4419 if (self->IsJSProxy()) {
4420 i::PropertyDescriptor desc;
4421 desc.set_writable(true);
4422 desc.set_enumerable(false);
4423 desc.set_configurable(true);
4424 desc.set_value(value_obj);
4425 return i::JSProxy::SetPrivateSymbol(
4426 isolate, i::Handle<i::JSProxy>::cast(self),
4427 i::Handle<i::Symbol>::cast(key_obj), &desc, Just(i::kDontThrow));
4428 }
4429 auto js_object = i::Handle<i::JSObject>::cast(self);
4430 i::LookupIterator it(isolate, js_object, key_obj, js_object);
4431 has_pending_exception = i::JSObject::DefineOwnPropertyIgnoreAttributes(
4432 &it, value_obj, i::DONT_ENUM)
4433 .is_null();
4434 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4435 return Just(true);
4436 }
4437
Get(Local<v8::Context> context,Local<Value> key)4438 MaybeLocal<Value> v8::Object::Get(Local<v8::Context> context,
4439 Local<Value> key) {
4440 PREPARE_FOR_EXECUTION(context, Object, Get, Value);
4441 auto self = Utils::OpenHandle(this);
4442 auto key_obj = Utils::OpenHandle(*key);
4443 i::Handle<i::Object> result;
4444 has_pending_exception =
4445 !i::Runtime::GetObjectProperty(isolate, self, key_obj).ToHandle(&result);
4446 RETURN_ON_FAILED_EXECUTION(Value);
4447 RETURN_ESCAPED(Utils::ToLocal(result));
4448 }
4449
Get(Local<Context> context,uint32_t index)4450 MaybeLocal<Value> v8::Object::Get(Local<Context> context, uint32_t index) {
4451 PREPARE_FOR_EXECUTION(context, Object, Get, Value);
4452 auto self = Utils::OpenHandle(this);
4453 i::Handle<i::Object> result;
4454 has_pending_exception =
4455 !i::JSReceiver::GetElement(isolate, self, index).ToHandle(&result);
4456 RETURN_ON_FAILED_EXECUTION(Value);
4457 RETURN_ESCAPED(Utils::ToLocal(result));
4458 }
4459
GetPrivate(Local<Context> context,Local<Private> key)4460 MaybeLocal<Value> v8::Object::GetPrivate(Local<Context> context,
4461 Local<Private> key) {
4462 return Get(context, Local<Value>(reinterpret_cast<Value*>(*key)));
4463 }
4464
GetPropertyAttributes(Local<Context> context,Local<Value> key)4465 Maybe<PropertyAttribute> v8::Object::GetPropertyAttributes(
4466 Local<Context> context, Local<Value> key) {
4467 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4468 ENTER_V8(isolate, context, Object, GetPropertyAttributes,
4469 Nothing<PropertyAttribute>(), i::HandleScope);
4470 auto self = Utils::OpenHandle(this);
4471 auto key_obj = Utils::OpenHandle(*key);
4472 if (!key_obj->IsName()) {
4473 has_pending_exception =
4474 !i::Object::ToString(isolate, key_obj).ToHandle(&key_obj);
4475 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
4476 }
4477 auto key_name = i::Handle<i::Name>::cast(key_obj);
4478 auto result = i::JSReceiver::GetPropertyAttributes(self, key_name);
4479 has_pending_exception = result.IsNothing();
4480 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
4481 if (result.FromJust() == i::ABSENT) {
4482 return Just(static_cast<PropertyAttribute>(i::NONE));
4483 }
4484 return Just(static_cast<PropertyAttribute>(result.FromJust()));
4485 }
4486
GetOwnPropertyDescriptor(Local<Context> context,Local<Name> key)4487 MaybeLocal<Value> v8::Object::GetOwnPropertyDescriptor(Local<Context> context,
4488 Local<Name> key) {
4489 PREPARE_FOR_EXECUTION(context, Object, GetOwnPropertyDescriptor, Value);
4490 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
4491 i::Handle<i::Name> key_name = Utils::OpenHandle(*key);
4492
4493 i::PropertyDescriptor desc;
4494 Maybe<bool> found =
4495 i::JSReceiver::GetOwnPropertyDescriptor(isolate, obj, key_name, &desc);
4496 has_pending_exception = found.IsNothing();
4497 RETURN_ON_FAILED_EXECUTION(Value);
4498 if (!found.FromJust()) {
4499 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
4500 }
4501 RETURN_ESCAPED(Utils::ToLocal(desc.ToObject(isolate)));
4502 }
4503
GetPrototype()4504 Local<Value> v8::Object::GetPrototype() {
4505 auto self = Utils::OpenHandle(this);
4506 auto isolate = self->GetIsolate();
4507 i::PrototypeIterator iter(isolate, self);
4508 return Utils::ToLocal(i::PrototypeIterator::GetCurrent(iter));
4509 }
4510
SetPrototype(Local<Context> context,Local<Value> value)4511 Maybe<bool> v8::Object::SetPrototype(Local<Context> context,
4512 Local<Value> value) {
4513 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4514 auto self = Utils::OpenHandle(this);
4515 auto value_obj = Utils::OpenHandle(*value);
4516 if (self->IsJSProxy()) {
4517 ENTER_V8(isolate, context, Object, SetPrototype, Nothing<bool>(),
4518 i::HandleScope);
4519 // We do not allow exceptions thrown while setting the prototype
4520 // to propagate outside.
4521 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
4522 auto result = i::JSProxy::SetPrototype(i::Handle<i::JSProxy>::cast(self),
4523 value_obj, false, i::kThrowOnError);
4524 has_pending_exception = result.IsNothing();
4525 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4526 } else {
4527 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
4528 auto result = i::JSObject::SetPrototype(i::Handle<i::JSObject>::cast(self),
4529 value_obj, false, i::kThrowOnError);
4530 if (result.IsNothing()) {
4531 isolate->clear_pending_exception();
4532 return Nothing<bool>();
4533 }
4534 }
4535 return Just(true);
4536 }
4537
FindInstanceInPrototypeChain(v8::Local<FunctionTemplate> tmpl)4538 Local<Object> v8::Object::FindInstanceInPrototypeChain(
4539 v8::Local<FunctionTemplate> tmpl) {
4540 auto self = Utils::OpenHandle(this);
4541 auto isolate = self->GetIsolate();
4542 i::PrototypeIterator iter(isolate, *self, i::kStartAtReceiver);
4543 auto tmpl_info = *Utils::OpenHandle(*tmpl);
4544 while (!tmpl_info.IsTemplateFor(iter.GetCurrent<i::JSObject>())) {
4545 iter.Advance();
4546 if (iter.IsAtEnd()) return Local<Object>();
4547 if (!iter.GetCurrent().IsJSObject()) return Local<Object>();
4548 }
4549 // IsTemplateFor() ensures that iter.GetCurrent() can't be a Proxy here.
4550 return Utils::ToLocal(i::handle(iter.GetCurrent<i::JSObject>(), isolate));
4551 }
4552
GetPropertyNames(Local<Context> context)4553 MaybeLocal<Array> v8::Object::GetPropertyNames(Local<Context> context) {
4554 return GetPropertyNames(
4555 context, v8::KeyCollectionMode::kIncludePrototypes,
4556 static_cast<v8::PropertyFilter>(ONLY_ENUMERABLE | SKIP_SYMBOLS),
4557 v8::IndexFilter::kIncludeIndices);
4558 }
4559
GetPropertyNames(Local<Context> context,KeyCollectionMode mode,PropertyFilter property_filter,IndexFilter index_filter,KeyConversionMode key_conversion)4560 MaybeLocal<Array> v8::Object::GetPropertyNames(
4561 Local<Context> context, KeyCollectionMode mode,
4562 PropertyFilter property_filter, IndexFilter index_filter,
4563 KeyConversionMode key_conversion) {
4564 PREPARE_FOR_EXECUTION(context, Object, GetPropertyNames, Array);
4565 auto self = Utils::OpenHandle(this);
4566 i::Handle<i::FixedArray> value;
4567 i::KeyAccumulator accumulator(
4568 isolate, static_cast<i::KeyCollectionMode>(mode),
4569 static_cast<i::PropertyFilter>(property_filter));
4570 accumulator.set_skip_indices(index_filter == IndexFilter::kSkipIndices);
4571 has_pending_exception = accumulator.CollectKeys(self, self).IsNothing();
4572 RETURN_ON_FAILED_EXECUTION(Array);
4573 value =
4574 accumulator.GetKeys(static_cast<i::GetKeysConversion>(key_conversion));
4575 DCHECK(self->map().EnumLength() == i::kInvalidEnumCacheSentinel ||
4576 self->map().EnumLength() == 0 ||
4577 self->map().instance_descriptors(isolate).enum_cache().keys() !=
4578 *value);
4579 auto result = isolate->factory()->NewJSArrayWithElements(value);
4580 RETURN_ESCAPED(Utils::ToLocal(result));
4581 }
4582
GetOwnPropertyNames(Local<Context> context)4583 MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context) {
4584 return GetOwnPropertyNames(
4585 context, static_cast<v8::PropertyFilter>(ONLY_ENUMERABLE | SKIP_SYMBOLS));
4586 }
4587
GetOwnPropertyNames(Local<Context> context,PropertyFilter filter,KeyConversionMode key_conversion)4588 MaybeLocal<Array> v8::Object::GetOwnPropertyNames(
4589 Local<Context> context, PropertyFilter filter,
4590 KeyConversionMode key_conversion) {
4591 return GetPropertyNames(context, KeyCollectionMode::kOwnOnly, filter,
4592 v8::IndexFilter::kIncludeIndices, key_conversion);
4593 }
4594
ObjectProtoToString(Local<Context> context)4595 MaybeLocal<String> v8::Object::ObjectProtoToString(Local<Context> context) {
4596 PREPARE_FOR_EXECUTION(context, Object, ObjectProtoToString, String);
4597 auto self = Utils::OpenHandle(this);
4598 Local<Value> result;
4599 has_pending_exception = !ToLocal<Value>(
4600 i::Execution::CallBuiltin(isolate, isolate->object_to_string(), self, 0,
4601 nullptr),
4602 &result);
4603 RETURN_ON_FAILED_EXECUTION(String);
4604 RETURN_ESCAPED(Local<String>::Cast(result));
4605 }
4606
GetConstructorName()4607 Local<String> v8::Object::GetConstructorName() {
4608 auto self = Utils::OpenHandle(this);
4609 i::Handle<i::String> name = i::JSReceiver::GetConstructorName(self);
4610 return Utils::ToLocal(name);
4611 }
4612
SetIntegrityLevel(Local<Context> context,IntegrityLevel level)4613 Maybe<bool> v8::Object::SetIntegrityLevel(Local<Context> context,
4614 IntegrityLevel level) {
4615 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4616 ENTER_V8(isolate, context, Object, SetIntegrityLevel, Nothing<bool>(),
4617 i::HandleScope);
4618 auto self = Utils::OpenHandle(this);
4619 i::JSReceiver::IntegrityLevel i_level =
4620 level == IntegrityLevel::kFrozen ? i::FROZEN : i::SEALED;
4621 Maybe<bool> result =
4622 i::JSReceiver::SetIntegrityLevel(self, i_level, i::kThrowOnError);
4623 has_pending_exception = result.IsNothing();
4624 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4625 return result;
4626 }
4627
Delete(Local<Context> context,Local<Value> key)4628 Maybe<bool> v8::Object::Delete(Local<Context> context, Local<Value> key) {
4629 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4630 auto self = Utils::OpenHandle(this);
4631 auto key_obj = Utils::OpenHandle(*key);
4632 if (self->IsJSProxy()) {
4633 ENTER_V8(isolate, context, Object, Delete, Nothing<bool>(), i::HandleScope);
4634 Maybe<bool> result = i::Runtime::DeleteObjectProperty(
4635 isolate, self, key_obj, i::LanguageMode::kSloppy);
4636 has_pending_exception = result.IsNothing();
4637 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4638 return result;
4639 } else {
4640 // If it's not a JSProxy, i::Runtime::DeleteObjectProperty should never run
4641 // a script.
4642 ENTER_V8_NO_SCRIPT(isolate, context, Object, Delete, Nothing<bool>(),
4643 i::HandleScope);
4644 Maybe<bool> result = i::Runtime::DeleteObjectProperty(
4645 isolate, self, key_obj, i::LanguageMode::kSloppy);
4646 has_pending_exception = result.IsNothing();
4647 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4648 return result;
4649 }
4650 }
4651
DeletePrivate(Local<Context> context,Local<Private> key)4652 Maybe<bool> v8::Object::DeletePrivate(Local<Context> context,
4653 Local<Private> key) {
4654 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4655 // In case of private symbols, i::Runtime::DeleteObjectProperty does not run
4656 // any author script.
4657 ENTER_V8_NO_SCRIPT(isolate, context, Object, Delete, Nothing<bool>(),
4658 i::HandleScope);
4659 auto self = Utils::OpenHandle(this);
4660 auto key_obj = Utils::OpenHandle(*key);
4661 Maybe<bool> result = i::Runtime::DeleteObjectProperty(
4662 isolate, self, key_obj, i::LanguageMode::kSloppy);
4663 has_pending_exception = result.IsNothing();
4664 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4665 return result;
4666 }
4667
Has(Local<Context> context,Local<Value> key)4668 Maybe<bool> v8::Object::Has(Local<Context> context, Local<Value> key) {
4669 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4670 ENTER_V8(isolate, context, Object, Has, Nothing<bool>(), i::HandleScope);
4671 auto self = Utils::OpenHandle(this);
4672 auto key_obj = Utils::OpenHandle(*key);
4673 Maybe<bool> maybe = Nothing<bool>();
4674 // Check if the given key is an array index.
4675 uint32_t index = 0;
4676 if (key_obj->ToArrayIndex(&index)) {
4677 maybe = i::JSReceiver::HasElement(self, index);
4678 } else {
4679 // Convert the key to a name - possibly by calling back into JavaScript.
4680 i::Handle<i::Name> name;
4681 if (i::Object::ToName(isolate, key_obj).ToHandle(&name)) {
4682 maybe = i::JSReceiver::HasProperty(self, name);
4683 }
4684 }
4685 has_pending_exception = maybe.IsNothing();
4686 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4687 return maybe;
4688 }
4689
HasPrivate(Local<Context> context,Local<Private> key)4690 Maybe<bool> v8::Object::HasPrivate(Local<Context> context, Local<Private> key) {
4691 return HasOwnProperty(context, Local<Name>(reinterpret_cast<Name*>(*key)));
4692 }
4693
Delete(Local<Context> context,uint32_t index)4694 Maybe<bool> v8::Object::Delete(Local<Context> context, uint32_t index) {
4695 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4696 ENTER_V8(isolate, context, Object, Delete, Nothing<bool>(), i::HandleScope);
4697 auto self = Utils::OpenHandle(this);
4698 Maybe<bool> result = i::JSReceiver::DeleteElement(self, index);
4699 has_pending_exception = result.IsNothing();
4700 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4701 return result;
4702 }
4703
Has(Local<Context> context,uint32_t index)4704 Maybe<bool> v8::Object::Has(Local<Context> context, uint32_t index) {
4705 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4706 ENTER_V8(isolate, context, Object, Has, Nothing<bool>(), i::HandleScope);
4707 auto self = Utils::OpenHandle(this);
4708 auto maybe = i::JSReceiver::HasElement(self, index);
4709 has_pending_exception = maybe.IsNothing();
4710 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4711 return maybe;
4712 }
4713
4714 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)4715 static Maybe<bool> ObjectSetAccessor(
4716 Local<Context> context, Object* self, Local<Name> name, Getter getter,
4717 Setter setter, Data data, AccessControl settings,
4718 PropertyAttribute attributes, bool is_special_data_property,
4719 bool replace_on_access, SideEffectType getter_side_effect_type,
4720 SideEffectType setter_side_effect_type) {
4721 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4722 ENTER_V8_NO_SCRIPT(isolate, context, Object, SetAccessor, Nothing<bool>(),
4723 i::HandleScope);
4724 if (!Utils::OpenHandle(self)->IsJSObject()) return Just(false);
4725 i::Handle<i::JSObject> obj =
4726 i::Handle<i::JSObject>::cast(Utils::OpenHandle(self));
4727 v8::Local<AccessorSignature> signature;
4728 i::Handle<i::AccessorInfo> info =
4729 MakeAccessorInfo(isolate, name, getter, setter, data, settings, signature,
4730 is_special_data_property, replace_on_access);
4731 info->set_getter_side_effect_type(getter_side_effect_type);
4732 info->set_setter_side_effect_type(setter_side_effect_type);
4733 if (info.is_null()) return Nothing<bool>();
4734 bool fast = obj->HasFastProperties();
4735 i::Handle<i::Object> result;
4736
4737 i::Handle<i::Name> accessor_name(info->name(), isolate);
4738 i::PropertyAttributes attrs = static_cast<i::PropertyAttributes>(attributes);
4739 has_pending_exception =
4740 !i::JSObject::SetAccessor(obj, accessor_name, info, attrs)
4741 .ToHandle(&result);
4742 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4743 if (result->IsUndefined(isolate)) return Just(false);
4744 if (fast) {
4745 i::JSObject::MigrateSlowToFast(obj, 0, "APISetAccessor");
4746 }
4747 return Just(true);
4748 }
4749
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)4750 Maybe<bool> Object::SetAccessor(Local<Context> context, Local<Name> name,
4751 AccessorNameGetterCallback getter,
4752 AccessorNameSetterCallback setter,
4753 MaybeLocal<Value> data, AccessControl settings,
4754 PropertyAttribute attribute,
4755 SideEffectType getter_side_effect_type,
4756 SideEffectType setter_side_effect_type) {
4757 return ObjectSetAccessor(context, this, name, getter, setter,
4758 data.FromMaybe(Local<Value>()), settings, attribute,
4759 i::FLAG_disable_old_api_accessors, false,
4760 getter_side_effect_type, setter_side_effect_type);
4761 }
4762
SetAccessorProperty(Local<Name> name,Local<Function> getter,Local<Function> setter,PropertyAttribute attribute,AccessControl settings)4763 void Object::SetAccessorProperty(Local<Name> name, Local<Function> getter,
4764 Local<Function> setter,
4765 PropertyAttribute attribute,
4766 AccessControl settings) {
4767 // TODO(verwaest): Remove |settings|.
4768 DCHECK_EQ(v8::DEFAULT, settings);
4769 auto self = Utils::OpenHandle(this);
4770 i::Isolate* isolate = self->GetIsolate();
4771 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
4772 i::HandleScope scope(isolate);
4773 if (!self->IsJSObject()) return;
4774 i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter);
4775 i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true);
4776 if (setter_i.is_null()) setter_i = isolate->factory()->null_value();
4777 i::JSObject::DefineAccessor(i::Handle<i::JSObject>::cast(self),
4778 v8::Utils::OpenHandle(*name), getter_i, setter_i,
4779 static_cast<i::PropertyAttributes>(attribute));
4780 }
4781
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)4782 Maybe<bool> Object::SetNativeDataProperty(
4783 v8::Local<v8::Context> context, v8::Local<Name> name,
4784 AccessorNameGetterCallback getter, AccessorNameSetterCallback setter,
4785 v8::Local<Value> data, PropertyAttribute attributes,
4786 SideEffectType getter_side_effect_type,
4787 SideEffectType setter_side_effect_type) {
4788 return ObjectSetAccessor(context, this, name, getter, setter, data, DEFAULT,
4789 attributes, true, false, getter_side_effect_type,
4790 setter_side_effect_type);
4791 }
4792
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)4793 Maybe<bool> Object::SetLazyDataProperty(
4794 v8::Local<v8::Context> context, v8::Local<Name> name,
4795 AccessorNameGetterCallback getter, v8::Local<Value> data,
4796 PropertyAttribute attributes, SideEffectType getter_side_effect_type,
4797 SideEffectType setter_side_effect_type) {
4798 return ObjectSetAccessor(context, this, name, getter,
4799 static_cast<AccessorNameSetterCallback>(nullptr),
4800 data, DEFAULT, attributes, true, true,
4801 getter_side_effect_type, setter_side_effect_type);
4802 }
4803
HasOwnProperty(Local<Context> context,Local<Name> key)4804 Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context,
4805 Local<Name> key) {
4806 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4807 ENTER_V8(isolate, context, Object, HasOwnProperty, Nothing<bool>(),
4808 i::HandleScope);
4809 auto self = Utils::OpenHandle(this);
4810 auto key_val = Utils::OpenHandle(*key);
4811 auto result = i::JSReceiver::HasOwnProperty(self, key_val);
4812 has_pending_exception = result.IsNothing();
4813 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4814 return result;
4815 }
4816
HasOwnProperty(Local<Context> context,uint32_t index)4817 Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context, uint32_t index) {
4818 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4819 ENTER_V8(isolate, context, Object, HasOwnProperty, Nothing<bool>(),
4820 i::HandleScope);
4821 auto self = Utils::OpenHandle(this);
4822 auto result = i::JSReceiver::HasOwnProperty(self, index);
4823 has_pending_exception = result.IsNothing();
4824 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4825 return result;
4826 }
4827
HasRealNamedProperty(Local<Context> context,Local<Name> key)4828 Maybe<bool> v8::Object::HasRealNamedProperty(Local<Context> context,
4829 Local<Name> key) {
4830 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4831 ENTER_V8_NO_SCRIPT(isolate, context, Object, HasRealNamedProperty,
4832 Nothing<bool>(), i::HandleScope);
4833 auto self = Utils::OpenHandle(this);
4834 if (!self->IsJSObject()) return Just(false);
4835 auto key_val = Utils::OpenHandle(*key);
4836 auto result = i::JSObject::HasRealNamedProperty(
4837 i::Handle<i::JSObject>::cast(self), key_val);
4838 has_pending_exception = result.IsNothing();
4839 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4840 return result;
4841 }
4842
HasRealIndexedProperty(Local<Context> context,uint32_t index)4843 Maybe<bool> v8::Object::HasRealIndexedProperty(Local<Context> context,
4844 uint32_t index) {
4845 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4846 ENTER_V8_NO_SCRIPT(isolate, context, Object, HasRealIndexedProperty,
4847 Nothing<bool>(), i::HandleScope);
4848 auto self = Utils::OpenHandle(this);
4849 if (!self->IsJSObject()) return Just(false);
4850 auto result = i::JSObject::HasRealElementProperty(
4851 i::Handle<i::JSObject>::cast(self), index);
4852 has_pending_exception = result.IsNothing();
4853 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4854 return result;
4855 }
4856
HasRealNamedCallbackProperty(Local<Context> context,Local<Name> key)4857 Maybe<bool> v8::Object::HasRealNamedCallbackProperty(Local<Context> context,
4858 Local<Name> key) {
4859 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4860 ENTER_V8_NO_SCRIPT(isolate, context, Object, HasRealNamedCallbackProperty,
4861 Nothing<bool>(), i::HandleScope);
4862 auto self = Utils::OpenHandle(this);
4863 if (!self->IsJSObject()) return Just(false);
4864 auto key_val = Utils::OpenHandle(*key);
4865 auto result = i::JSObject::HasRealNamedCallbackProperty(
4866 i::Handle<i::JSObject>::cast(self), key_val);
4867 has_pending_exception = result.IsNothing();
4868 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
4869 return result;
4870 }
4871
HasNamedLookupInterceptor() const4872 bool v8::Object::HasNamedLookupInterceptor() const {
4873 auto self = *Utils::OpenHandle(this);
4874 if (self.IsJSObject()) return false;
4875 return i::JSObject::cast(self).HasNamedInterceptor();
4876 }
4877
HasIndexedLookupInterceptor() const4878 bool v8::Object::HasIndexedLookupInterceptor() const {
4879 auto self = *Utils::OpenHandle(this);
4880 if (self.IsJSObject()) return false;
4881 return i::JSObject::cast(self).HasIndexedInterceptor();
4882 }
4883
GetRealNamedPropertyInPrototypeChain(Local<Context> context,Local<Name> key)4884 MaybeLocal<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
4885 Local<Context> context, Local<Name> key) {
4886 PREPARE_FOR_EXECUTION(context, Object, GetRealNamedPropertyInPrototypeChain,
4887 Value);
4888 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4889 if (!self->IsJSObject()) return MaybeLocal<Value>();
4890 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
4891 i::PrototypeIterator iter(isolate, self);
4892 if (iter.IsAtEnd()) return MaybeLocal<Value>();
4893 i::Handle<i::JSReceiver> proto =
4894 i::PrototypeIterator::GetCurrent<i::JSReceiver>(iter);
4895 i::PropertyKey lookup_key(isolate, key_obj);
4896 i::LookupIterator it(isolate, self, lookup_key, proto,
4897 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
4898 Local<Value> result;
4899 has_pending_exception = !ToLocal<Value>(i::Object::GetProperty(&it), &result);
4900 RETURN_ON_FAILED_EXECUTION(Value);
4901 if (!it.IsFound()) return MaybeLocal<Value>();
4902 RETURN_ESCAPED(result);
4903 }
4904
4905 Maybe<PropertyAttribute>
GetRealNamedPropertyAttributesInPrototypeChain(Local<Context> context,Local<Name> key)4906 v8::Object::GetRealNamedPropertyAttributesInPrototypeChain(
4907 Local<Context> context, Local<Name> key) {
4908 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4909 ENTER_V8(isolate, context, Object,
4910 GetRealNamedPropertyAttributesInPrototypeChain,
4911 Nothing<PropertyAttribute>(), i::HandleScope);
4912 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4913 if (!self->IsJSObject()) return Nothing<PropertyAttribute>();
4914 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
4915 i::PrototypeIterator iter(isolate, self);
4916 if (iter.IsAtEnd()) return Nothing<PropertyAttribute>();
4917 i::Handle<i::JSReceiver> proto =
4918 i::PrototypeIterator::GetCurrent<i::JSReceiver>(iter);
4919 i::PropertyKey lookup_key(isolate, key_obj);
4920 i::LookupIterator it(isolate, self, lookup_key, proto,
4921 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
4922 Maybe<i::PropertyAttributes> result =
4923 i::JSReceiver::GetPropertyAttributes(&it);
4924 has_pending_exception = result.IsNothing();
4925 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
4926 if (!it.IsFound()) return Nothing<PropertyAttribute>();
4927 if (result.FromJust() == i::ABSENT) return Just(None);
4928 return Just(static_cast<PropertyAttribute>(result.FromJust()));
4929 }
4930
GetRealNamedProperty(Local<Context> context,Local<Name> key)4931 MaybeLocal<Value> v8::Object::GetRealNamedProperty(Local<Context> context,
4932 Local<Name> key) {
4933 PREPARE_FOR_EXECUTION(context, Object, GetRealNamedProperty, Value);
4934 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4935 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
4936 i::PropertyKey lookup_key(isolate, key_obj);
4937 i::LookupIterator it(isolate, self, lookup_key, self,
4938 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
4939 Local<Value> result;
4940 has_pending_exception = !ToLocal<Value>(i::Object::GetProperty(&it), &result);
4941 RETURN_ON_FAILED_EXECUTION(Value);
4942 if (!it.IsFound()) return MaybeLocal<Value>();
4943 RETURN_ESCAPED(result);
4944 }
4945
GetRealNamedPropertyAttributes(Local<Context> context,Local<Name> key)4946 Maybe<PropertyAttribute> v8::Object::GetRealNamedPropertyAttributes(
4947 Local<Context> context, Local<Name> key) {
4948 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
4949 ENTER_V8(isolate, context, Object, GetRealNamedPropertyAttributes,
4950 Nothing<PropertyAttribute>(), i::HandleScope);
4951 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
4952 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
4953 i::PropertyKey lookup_key(isolate, key_obj);
4954 i::LookupIterator it(isolate, self, lookup_key, self,
4955 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
4956 auto result = i::JSReceiver::GetPropertyAttributes(&it);
4957 has_pending_exception = result.IsNothing();
4958 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
4959 if (!it.IsFound()) return Nothing<PropertyAttribute>();
4960 if (result.FromJust() == i::ABSENT) {
4961 return Just(static_cast<PropertyAttribute>(i::NONE));
4962 }
4963 return Just<PropertyAttribute>(
4964 static_cast<PropertyAttribute>(result.FromJust()));
4965 }
4966
Clone()4967 Local<v8::Object> v8::Object::Clone() {
4968 auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
4969 auto isolate = self->GetIsolate();
4970 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
4971 i::Handle<i::JSObject> result = isolate->factory()->CopyJSObject(self);
4972 return Utils::ToLocal(result);
4973 }
4974
4975 namespace {
CreationContextImpl(i::Handle<i::JSReceiver> self)4976 Local<v8::Context> CreationContextImpl(i::Handle<i::JSReceiver> self) {
4977 i::Handle<i::Context> context;
4978 if (self->GetCreationContext().ToHandle(&context)) {
4979 return Utils::ToLocal(context);
4980 }
4981
4982 return Local<v8::Context>();
4983 }
4984 } // namespace
4985
CreationContext()4986 Local<v8::Context> v8::Object::CreationContext() {
4987 auto self = Utils::OpenHandle(this);
4988 return CreationContextImpl(self);
4989 }
4990
CreationContext(const PersistentBase<Object> & object)4991 Local<v8::Context> v8::Object::CreationContext(
4992 const PersistentBase<Object>& object) {
4993 auto self = Utils::OpenHandle(object.val_);
4994 return CreationContextImpl(self);
4995 }
4996
GetCreationContext()4997 MaybeLocal<v8::Context> v8::Object::GetCreationContext() {
4998 auto self = Utils::OpenHandle(this);
4999 i::Handle<i::Context> context;
5000 if (self->GetCreationContext().ToHandle(&context)) {
5001 return Utils::ToLocal(context);
5002 }
5003
5004 return MaybeLocal<v8::Context>();
5005 }
5006
GetIdentityHash()5007 int v8::Object::GetIdentityHash() {
5008 i::DisallowGarbageCollection no_gc;
5009 auto self = Utils::OpenHandle(this);
5010 auto isolate = self->GetIsolate();
5011 ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
5012 i::HandleScope scope(isolate);
5013 return self->GetOrCreateIdentityHash(isolate).value();
5014 }
5015
IsCallable() const5016 bool v8::Object::IsCallable() const {
5017 auto self = Utils::OpenHandle(this);
5018 return self->IsCallable();
5019 }
5020
IsConstructor() const5021 bool v8::Object::IsConstructor() const {
5022 auto self = Utils::OpenHandle(this);
5023 return self->IsConstructor();
5024 }
5025
IsApiWrapper() const5026 bool v8::Object::IsApiWrapper() const {
5027 auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
5028 return self->IsApiWrapper();
5029 }
5030
IsUndetectable() const5031 bool v8::Object::IsUndetectable() const {
5032 auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
5033 return self->IsUndetectable();
5034 }
5035
CallAsFunction(Local<Context> context,Local<Value> recv,int argc,Local<Value> argv[])5036 MaybeLocal<Value> Object::CallAsFunction(Local<Context> context,
5037 Local<Value> recv, int argc,
5038 Local<Value> argv[]) {
5039 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
5040 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
5041 ENTER_V8(isolate, context, Object, CallAsFunction, MaybeLocal<Value>(),
5042 InternalEscapableScope);
5043 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
5044 i::NestedTimedHistogramScope execute_timer(
5045 isolate->counters()->execute_precise());
5046 auto self = Utils::OpenHandle(this);
5047 auto recv_obj = Utils::OpenHandle(*recv);
5048 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
5049 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
5050 Local<Value> result;
5051 has_pending_exception = !ToLocal<Value>(
5052 i::Execution::Call(isolate, self, recv_obj, argc, args), &result);
5053 RETURN_ON_FAILED_EXECUTION(Value);
5054 RETURN_ESCAPED(result);
5055 }
5056
CallAsConstructor(Local<Context> context,int argc,Local<Value> argv[])5057 MaybeLocal<Value> Object::CallAsConstructor(Local<Context> context, int argc,
5058 Local<Value> argv[]) {
5059 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
5060 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
5061 ENTER_V8(isolate, context, Object, CallAsConstructor, MaybeLocal<Value>(),
5062 InternalEscapableScope);
5063 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
5064 i::NestedTimedHistogramScope execute_timer(
5065 isolate->counters()->execute_precise());
5066 auto self = Utils::OpenHandle(this);
5067 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
5068 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
5069 Local<Value> result;
5070 has_pending_exception = !ToLocal<Value>(
5071 i::Execution::New(isolate, self, self, argc, args), &result);
5072 RETURN_ON_FAILED_EXECUTION(Value);
5073 RETURN_ESCAPED(result);
5074 }
5075
New(Local<Context> context,FunctionCallback callback,Local<Value> data,int length,ConstructorBehavior behavior,SideEffectType side_effect_type)5076 MaybeLocal<Function> Function::New(Local<Context> context,
5077 FunctionCallback callback, Local<Value> data,
5078 int length, ConstructorBehavior behavior,
5079 SideEffectType side_effect_type) {
5080 i::Isolate* isolate = Utils::OpenHandle(*context)->GetIsolate();
5081 LOG_API(isolate, Function, New);
5082 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
5083 auto templ =
5084 FunctionTemplateNew(isolate, callback, data, Local<Signature>(), length,
5085 behavior, true, Local<Private>(), side_effect_type);
5086 return templ->GetFunction(context);
5087 }
5088
NewInstance(Local<Context> context,int argc,v8::Local<v8::Value> argv[]) const5089 MaybeLocal<Object> Function::NewInstance(Local<Context> context, int argc,
5090 v8::Local<v8::Value> argv[]) const {
5091 return NewInstanceWithSideEffectType(context, argc, argv,
5092 SideEffectType::kHasSideEffect);
5093 }
5094
NewInstanceWithSideEffectType(Local<Context> context,int argc,v8::Local<v8::Value> argv[],SideEffectType side_effect_type) const5095 MaybeLocal<Object> Function::NewInstanceWithSideEffectType(
5096 Local<Context> context, int argc, v8::Local<v8::Value> argv[],
5097 SideEffectType side_effect_type) const {
5098 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
5099 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
5100 ENTER_V8(isolate, context, Function, NewInstance, MaybeLocal<Object>(),
5101 InternalEscapableScope);
5102 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
5103 i::NestedTimedHistogramScope execute_timer(
5104 isolate->counters()->execute_precise());
5105 auto self = Utils::OpenHandle(this);
5106 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
5107 bool should_set_has_no_side_effect =
5108 side_effect_type == SideEffectType::kHasNoSideEffect &&
5109 isolate->debug_execution_mode() == i::DebugInfo::kSideEffects;
5110 if (should_set_has_no_side_effect) {
5111 CHECK(self->IsJSFunction() &&
5112 i::JSFunction::cast(*self).shared().IsApiFunction());
5113 i::Object obj =
5114 i::JSFunction::cast(*self).shared().get_api_func_data().call_code(
5115 kAcquireLoad);
5116 if (obj.IsCallHandlerInfo()) {
5117 i::CallHandlerInfo handler_info = i::CallHandlerInfo::cast(obj);
5118 if (!handler_info.IsSideEffectFreeCallHandlerInfo()) {
5119 handler_info.SetNextCallHasNoSideEffect();
5120 }
5121 }
5122 }
5123 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
5124 Local<Object> result;
5125 has_pending_exception = !ToLocal<Object>(
5126 i::Execution::New(isolate, self, self, argc, args), &result);
5127 if (should_set_has_no_side_effect) {
5128 i::Object obj =
5129 i::JSFunction::cast(*self).shared().get_api_func_data().call_code(
5130 kAcquireLoad);
5131 if (obj.IsCallHandlerInfo()) {
5132 i::CallHandlerInfo handler_info = i::CallHandlerInfo::cast(obj);
5133 if (has_pending_exception) {
5134 // Restore the map if an exception prevented restoration.
5135 handler_info.NextCallHasNoSideEffect();
5136 } else {
5137 DCHECK(handler_info.IsSideEffectCallHandlerInfo() ||
5138 handler_info.IsSideEffectFreeCallHandlerInfo());
5139 }
5140 }
5141 }
5142 RETURN_ON_FAILED_EXECUTION(Object);
5143 RETURN_ESCAPED(result);
5144 }
5145
Call(Local<Context> context,v8::Local<v8::Value> recv,int argc,v8::Local<v8::Value> argv[])5146 MaybeLocal<v8::Value> Function::Call(Local<Context> context,
5147 v8::Local<v8::Value> recv, int argc,
5148 v8::Local<v8::Value> argv[]) {
5149 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
5150 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
5151 ENTER_V8(isolate, context, Function, Call, MaybeLocal<Value>(),
5152 InternalEscapableScope);
5153 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
5154 i::NestedTimedHistogramScope execute_timer(
5155 isolate->counters()->execute_precise());
5156 auto self = Utils::OpenHandle(this);
5157 Utils::ApiCheck(!self.is_null(), "v8::Function::Call",
5158 "Function to be called is a null pointer");
5159 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
5160 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
5161 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
5162 Local<Value> result;
5163 has_pending_exception = !ToLocal<Value>(
5164 i::Execution::Call(isolate, self, recv_obj, argc, args), &result);
5165 RETURN_ON_FAILED_EXECUTION(Value);
5166 RETURN_ESCAPED(result);
5167 }
5168
SetName(v8::Local<v8::String> name)5169 void Function::SetName(v8::Local<v8::String> name) {
5170 auto self = Utils::OpenHandle(this);
5171 if (!self->IsJSFunction()) return;
5172 auto func = i::Handle<i::JSFunction>::cast(self);
5173 ASSERT_NO_SCRIPT_NO_EXCEPTION(func->GetIsolate());
5174 func->shared().SetName(*Utils::OpenHandle(*name));
5175 }
5176
GetName() const5177 Local<Value> Function::GetName() const {
5178 auto self = Utils::OpenHandle(this);
5179 i::Isolate* isolate = self->GetIsolate();
5180 if (self->IsJSBoundFunction()) {
5181 auto func = i::Handle<i::JSBoundFunction>::cast(self);
5182 i::Handle<i::Object> name;
5183 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, name,
5184 i::JSBoundFunction::GetName(isolate, func),
5185 Local<Value>());
5186 return Utils::ToLocal(name);
5187 }
5188 if (self->IsJSFunction()) {
5189 auto func = i::Handle<i::JSFunction>::cast(self);
5190 return Utils::ToLocal(handle(func->shared().Name(), isolate));
5191 }
5192 return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
5193 }
5194
GetInferredName() const5195 Local<Value> Function::GetInferredName() const {
5196 auto self = Utils::OpenHandle(this);
5197 if (!self->IsJSFunction()) {
5198 return ToApiHandle<Primitive>(
5199 self->GetIsolate()->factory()->undefined_value());
5200 }
5201 auto func = i::Handle<i::JSFunction>::cast(self);
5202 return Utils::ToLocal(
5203 i::Handle<i::Object>(func->shared().inferred_name(), func->GetIsolate()));
5204 }
5205
GetDebugName() const5206 Local<Value> Function::GetDebugName() const {
5207 auto self = Utils::OpenHandle(this);
5208 if (!self->IsJSFunction()) {
5209 return ToApiHandle<Primitive>(
5210 self->GetIsolate()->factory()->undefined_value());
5211 }
5212 auto func = i::Handle<i::JSFunction>::cast(self);
5213 i::Handle<i::String> name = i::JSFunction::GetDebugName(func);
5214 return Utils::ToLocal(i::Handle<i::Object>(*name, self->GetIsolate()));
5215 }
5216
GetScriptOrigin() const5217 ScriptOrigin Function::GetScriptOrigin() const {
5218 auto self = Utils::OpenHandle(this);
5219 auto isolate = reinterpret_cast<v8::Isolate*>(self->GetIsolate());
5220 if (!self->IsJSFunction()) return v8::ScriptOrigin(isolate, Local<Value>());
5221 auto func = i::Handle<i::JSFunction>::cast(self);
5222 if (func->shared().script().IsScript()) {
5223 i::Handle<i::Script> script(i::Script::cast(func->shared().script()),
5224 func->GetIsolate());
5225 return GetScriptOriginForScript(func->GetIsolate(), script);
5226 }
5227 return v8::ScriptOrigin(isolate, Local<Value>());
5228 }
5229
5230 const int Function::kLineOffsetNotFound = -1;
5231
GetScriptLineNumber() const5232 int Function::GetScriptLineNumber() const {
5233 auto self = Utils::OpenHandle(this);
5234 if (!self->IsJSFunction()) {
5235 return kLineOffsetNotFound;
5236 }
5237 auto func = i::Handle<i::JSFunction>::cast(self);
5238 if (func->shared().script().IsScript()) {
5239 i::Handle<i::Script> script(i::Script::cast(func->shared().script()),
5240 func->GetIsolate());
5241 return i::Script::GetLineNumber(script, func->shared().StartPosition());
5242 }
5243 return kLineOffsetNotFound;
5244 }
5245
GetScriptColumnNumber() const5246 int Function::GetScriptColumnNumber() const {
5247 auto self = Utils::OpenHandle(this);
5248 if (!self->IsJSFunction()) {
5249 return kLineOffsetNotFound;
5250 }
5251 auto func = i::Handle<i::JSFunction>::cast(self);
5252 if (func->shared().script().IsScript()) {
5253 i::Handle<i::Script> script(i::Script::cast(func->shared().script()),
5254 func->GetIsolate());
5255 return i::Script::GetColumnNumber(script, func->shared().StartPosition());
5256 }
5257 return kLineOffsetNotFound;
5258 }
5259
ScriptId() const5260 int Function::ScriptId() const {
5261 i::JSReceiver self = *Utils::OpenHandle(this);
5262 if (!self.IsJSFunction()) return v8::UnboundScript::kNoScriptId;
5263 auto func = i::JSFunction::cast(self);
5264 if (!func.shared().script().IsScript()) return v8::UnboundScript::kNoScriptId;
5265 return i::Script::cast(func.shared().script()).id();
5266 }
5267
GetBoundFunction() const5268 Local<v8::Value> Function::GetBoundFunction() const {
5269 auto self = Utils::OpenHandle(this);
5270 if (self->IsJSBoundFunction()) {
5271 auto bound_function = i::Handle<i::JSBoundFunction>::cast(self);
5272 auto bound_target_function = i::handle(
5273 bound_function->bound_target_function(), bound_function->GetIsolate());
5274 return Utils::CallableToLocal(bound_target_function);
5275 }
5276 return v8::Undefined(reinterpret_cast<v8::Isolate*>(self->GetIsolate()));
5277 }
5278
FunctionProtoToString(Local<Context> context)5279 MaybeLocal<String> v8::Function::FunctionProtoToString(Local<Context> context) {
5280 PREPARE_FOR_EXECUTION(context, Function, FunctionProtoToString, String);
5281 auto self = Utils::OpenHandle(this);
5282 Local<Value> result;
5283 has_pending_exception = !ToLocal<Value>(
5284 i::Execution::CallBuiltin(isolate, isolate->function_to_string(), self, 0,
5285 nullptr),
5286 &result);
5287 RETURN_ON_FAILED_EXECUTION(String);
5288 RETURN_ESCAPED(Local<String>::Cast(result));
5289 }
5290
GetIdentityHash()5291 int Name::GetIdentityHash() {
5292 auto self = Utils::OpenHandle(this);
5293 return static_cast<int>(self->EnsureHash());
5294 }
5295
Length() const5296 int String::Length() const {
5297 i::Handle<i::String> str = Utils::OpenHandle(this);
5298 return str->length();
5299 }
5300
IsOneByte() const5301 bool String::IsOneByte() const {
5302 i::Handle<i::String> str = Utils::OpenHandle(this);
5303 return str->IsOneByteRepresentation();
5304 }
5305
5306 // Helpers for ContainsOnlyOneByteHelper
5307 template <size_t size>
5308 struct OneByteMask;
5309 template <>
5310 struct OneByteMask<4> {
5311 static const uint32_t value = 0xFF00FF00;
5312 };
5313 template <>
5314 struct OneByteMask<8> {
5315 static const uint64_t value = 0xFF00'FF00'FF00'FF00;
5316 };
5317 static const uintptr_t kOneByteMask = OneByteMask<sizeof(uintptr_t)>::value;
5318 static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1;
Unaligned(const uint16_t * chars)5319 static inline bool Unaligned(const uint16_t* chars) {
5320 return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask;
5321 }
5322
Align(const uint16_t * chars)5323 static inline const uint16_t* Align(const uint16_t* chars) {
5324 return reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(chars) &
5325 ~kAlignmentMask);
5326 }
5327
5328 class ContainsOnlyOneByteHelper {
5329 public:
ContainsOnlyOneByteHelper()5330 ContainsOnlyOneByteHelper() : is_one_byte_(true) {}
5331 ContainsOnlyOneByteHelper(const ContainsOnlyOneByteHelper&) = delete;
5332 ContainsOnlyOneByteHelper& operator=(const ContainsOnlyOneByteHelper&) =
5333 delete;
Check(i::String string)5334 bool Check(i::String string) {
5335 i::ConsString cons_string = i::String::VisitFlat(this, string, 0);
5336 if (cons_string.is_null()) return is_one_byte_;
5337 return CheckCons(cons_string);
5338 }
VisitOneByteString(const uint8_t * chars,int length)5339 void VisitOneByteString(const uint8_t* chars, int length) {
5340 // Nothing to do.
5341 }
VisitTwoByteString(const uint16_t * chars,int length)5342 void VisitTwoByteString(const uint16_t* chars, int length) {
5343 // Accumulated bits.
5344 uintptr_t acc = 0;
5345 // Align to uintptr_t.
5346 const uint16_t* end = chars + length;
5347 while (Unaligned(chars) && chars != end) {
5348 acc |= *chars++;
5349 }
5350 // Read word aligned in blocks,
5351 // checking the return value at the end of each block.
5352 const uint16_t* aligned_end = Align(end);
5353 const int increment = sizeof(uintptr_t) / sizeof(uint16_t);
5354 const int inner_loops = 16;
5355 while (chars + inner_loops * increment < aligned_end) {
5356 for (int i = 0; i < inner_loops; i++) {
5357 acc |= *reinterpret_cast<const uintptr_t*>(chars);
5358 chars += increment;
5359 }
5360 // Check for early return.
5361 if ((acc & kOneByteMask) != 0) {
5362 is_one_byte_ = false;
5363 return;
5364 }
5365 }
5366 // Read the rest.
5367 while (chars != end) {
5368 acc |= *chars++;
5369 }
5370 // Check result.
5371 if ((acc & kOneByteMask) != 0) is_one_byte_ = false;
5372 }
5373
5374 private:
CheckCons(i::ConsString cons_string)5375 bool CheckCons(i::ConsString cons_string) {
5376 while (true) {
5377 // Check left side if flat.
5378 i::String left = cons_string.first();
5379 i::ConsString left_as_cons = i::String::VisitFlat(this, left, 0);
5380 if (!is_one_byte_) return false;
5381 // Check right side if flat.
5382 i::String right = cons_string.second();
5383 i::ConsString right_as_cons = i::String::VisitFlat(this, right, 0);
5384 if (!is_one_byte_) return false;
5385 // Standard recurse/iterate trick.
5386 if (!left_as_cons.is_null() && !right_as_cons.is_null()) {
5387 if (left.length() < right.length()) {
5388 CheckCons(left_as_cons);
5389 cons_string = right_as_cons;
5390 } else {
5391 CheckCons(right_as_cons);
5392 cons_string = left_as_cons;
5393 }
5394 // Check fast return.
5395 if (!is_one_byte_) return false;
5396 continue;
5397 }
5398 // Descend left in place.
5399 if (!left_as_cons.is_null()) {
5400 cons_string = left_as_cons;
5401 continue;
5402 }
5403 // Descend right in place.
5404 if (!right_as_cons.is_null()) {
5405 cons_string = right_as_cons;
5406 continue;
5407 }
5408 // Terminate.
5409 break;
5410 }
5411 return is_one_byte_;
5412 }
5413 bool is_one_byte_;
5414 };
5415
ContainsOnlyOneByte() const5416 bool String::ContainsOnlyOneByte() const {
5417 i::Handle<i::String> str = Utils::OpenHandle(this);
5418 if (str->IsOneByteRepresentation()) return true;
5419 ContainsOnlyOneByteHelper helper;
5420 return helper.Check(*str);
5421 }
5422
Utf8Length(Isolate * isolate) const5423 int String::Utf8Length(Isolate* isolate) const {
5424 i::Handle<i::String> str = Utils::OpenHandle(this);
5425 str = i::String::Flatten(reinterpret_cast<i::Isolate*>(isolate), str);
5426 int length = str->length();
5427 if (length == 0) return 0;
5428 i::DisallowGarbageCollection no_gc;
5429 i::String::FlatContent flat = str->GetFlatContent(no_gc);
5430 DCHECK(flat.IsFlat());
5431 int utf8_length = 0;
5432 if (flat.IsOneByte()) {
5433 for (uint8_t c : flat.ToOneByteVector()) {
5434 utf8_length += c >> 7;
5435 }
5436 utf8_length += length;
5437 } else {
5438 int last_character = unibrow::Utf16::kNoPreviousCharacter;
5439 for (uint16_t c : flat.ToUC16Vector()) {
5440 utf8_length += unibrow::Utf8::Length(c, last_character);
5441 last_character = c;
5442 }
5443 }
5444 return utf8_length;
5445 }
5446
5447 namespace {
5448 // Writes the flat content of a string to a buffer. This is done in two phases.
5449 // The first phase calculates a pessimistic estimate (writable_length) on how
5450 // many code units can be safely written without exceeding the buffer capacity
5451 // and without leaving at a lone surrogate. The estimated number of code units
5452 // is then written out in one go, and the reported byte usage is used to
5453 // correct the estimate. This is repeated until the estimate becomes <= 0 or
5454 // all code units have been written out. The second phase writes out code
5455 // units until the buffer capacity is reached, would be exceeded by the next
5456 // unit, or all code units have been written out.
5457 template <typename Char>
WriteUtf8Impl(base::Vector<const Char> string,char * write_start,int write_capacity,int options,int * utf16_chars_read_out)5458 static int WriteUtf8Impl(base::Vector<const Char> string, char* write_start,
5459 int write_capacity, int options,
5460 int* utf16_chars_read_out) {
5461 bool write_null = !(options & v8::String::NO_NULL_TERMINATION);
5462 bool replace_invalid_utf8 = (options & v8::String::REPLACE_INVALID_UTF8);
5463 char* current_write = write_start;
5464 const Char* read_start = string.begin();
5465 int read_index = 0;
5466 int read_length = string.length();
5467 int prev_char = unibrow::Utf16::kNoPreviousCharacter;
5468 // Do a fast loop where there is no exit capacity check.
5469 // Need enough space to write everything but one character.
5470 STATIC_ASSERT(unibrow::Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 3);
5471 static const int kMaxSizePerChar = sizeof(Char) == 1 ? 2 : 3;
5472 while (read_index < read_length) {
5473 int up_to = read_length;
5474 if (write_capacity != -1) {
5475 int remaining_capacity =
5476 write_capacity - static_cast<int>(current_write - write_start);
5477 int writable_length =
5478 (remaining_capacity - kMaxSizePerChar) / kMaxSizePerChar;
5479 // Need to drop into slow loop.
5480 if (writable_length <= 0) break;
5481 up_to = std::min(up_to, read_index + writable_length);
5482 }
5483 // Write the characters to the stream.
5484 if (sizeof(Char) == 1) {
5485 // Simply memcpy if we only have ASCII characters.
5486 uint8_t char_mask = 0;
5487 for (int i = read_index; i < up_to; i++) char_mask |= read_start[i];
5488 if ((char_mask & 0x80) == 0) {
5489 int copy_length = up_to - read_index;
5490 memcpy(current_write, read_start + read_index, copy_length);
5491 current_write += copy_length;
5492 read_index = up_to;
5493 } else {
5494 for (; read_index < up_to; read_index++) {
5495 current_write += unibrow::Utf8::EncodeOneByte(
5496 current_write, static_cast<uint8_t>(read_start[read_index]));
5497 DCHECK(write_capacity == -1 ||
5498 (current_write - write_start) <= write_capacity);
5499 }
5500 }
5501 } else {
5502 for (; read_index < up_to; read_index++) {
5503 uint16_t character = read_start[read_index];
5504 current_write += unibrow::Utf8::Encode(current_write, character,
5505 prev_char, replace_invalid_utf8);
5506 prev_char = character;
5507 DCHECK(write_capacity == -1 ||
5508 (current_write - write_start) <= write_capacity);
5509 }
5510 }
5511 }
5512 if (read_index < read_length) {
5513 DCHECK_NE(-1, write_capacity);
5514 // Aborted due to limited capacity. Check capacity on each iteration.
5515 int remaining_capacity =
5516 write_capacity - static_cast<int>(current_write - write_start);
5517 DCHECK_GE(remaining_capacity, 0);
5518 for (; read_index < read_length && remaining_capacity > 0; read_index++) {
5519 uint32_t character = read_start[read_index];
5520 int written = 0;
5521 // We can't use a local buffer here because Encode needs to modify
5522 // previous characters in the stream. We know, however, that
5523 // exactly one character will be advanced.
5524 if (unibrow::Utf16::IsSurrogatePair(prev_char, character)) {
5525 written = unibrow::Utf8::Encode(current_write, character, prev_char,
5526 replace_invalid_utf8);
5527 DCHECK_EQ(written, 1);
5528 } else {
5529 // Use a scratch buffer to check the required characters.
5530 char temp_buffer[unibrow::Utf8::kMaxEncodedSize];
5531 // Encoding a surrogate pair to Utf8 always takes 4 bytes.
5532 static const int kSurrogatePairEncodedSize =
5533 static_cast<int>(unibrow::Utf8::kMaxEncodedSize);
5534 // For REPLACE_INVALID_UTF8, catch the case where we cut off in the
5535 // middle of a surrogate pair. Abort before encoding the pair instead.
5536 if (replace_invalid_utf8 &&
5537 remaining_capacity < kSurrogatePairEncodedSize &&
5538 unibrow::Utf16::IsLeadSurrogate(character) &&
5539 read_index + 1 < read_length &&
5540 unibrow::Utf16::IsTrailSurrogate(read_start[read_index + 1])) {
5541 write_null = false;
5542 break;
5543 }
5544 // Can't encode using prev_char as gcc has array bounds issues.
5545 written = unibrow::Utf8::Encode(temp_buffer, character,
5546 unibrow::Utf16::kNoPreviousCharacter,
5547 replace_invalid_utf8);
5548 if (written > remaining_capacity) {
5549 // Won't fit. Abort and do not null-terminate the result.
5550 write_null = false;
5551 break;
5552 }
5553 // Copy over the character from temp_buffer.
5554 for (int i = 0; i < written; i++) current_write[i] = temp_buffer[i];
5555 }
5556
5557 current_write += written;
5558 remaining_capacity -= written;
5559 prev_char = character;
5560 }
5561 }
5562
5563 // Write out number of utf16 characters written to the stream.
5564 if (utf16_chars_read_out != nullptr) *utf16_chars_read_out = read_index;
5565
5566 // Only null-terminate if there's space.
5567 if (write_null && (write_capacity == -1 ||
5568 (current_write - write_start) < write_capacity)) {
5569 *current_write++ = '\0';
5570 }
5571 return static_cast<int>(current_write - write_start);
5572 }
5573 } // anonymous namespace
5574
WriteUtf8(Isolate * v8_isolate,char * buffer,int capacity,int * nchars_ref,int options) const5575 int String::WriteUtf8(Isolate* v8_isolate, char* buffer, int capacity,
5576 int* nchars_ref, int options) const {
5577 i::Handle<i::String> str = Utils::OpenHandle(this);
5578 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
5579 LOG_API(isolate, String, WriteUtf8);
5580 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
5581 str = i::String::Flatten(isolate, str);
5582 i::DisallowGarbageCollection no_gc;
5583 i::String::FlatContent content = str->GetFlatContent(no_gc);
5584 if (content.IsOneByte()) {
5585 return WriteUtf8Impl<uint8_t>(content.ToOneByteVector(), buffer, capacity,
5586 options, nchars_ref);
5587 } else {
5588 return WriteUtf8Impl<uint16_t>(content.ToUC16Vector(), buffer, capacity,
5589 options, nchars_ref);
5590 }
5591 }
5592
5593 template <typename CharType>
WriteHelper(i::Isolate * isolate,const String * string,CharType * buffer,int start,int length,int options)5594 static inline int WriteHelper(i::Isolate* isolate, const String* string,
5595 CharType* buffer, int start, int length,
5596 int options) {
5597 LOG_API(isolate, String, Write);
5598 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
5599 DCHECK(start >= 0 && length >= -1);
5600 i::Handle<i::String> str = Utils::OpenHandle(string);
5601 str = i::String::Flatten(isolate, str);
5602 int end = start + length;
5603 if ((length == -1) || (length > str->length() - start)) end = str->length();
5604 if (end < 0) return 0;
5605 int write_length = end - start;
5606 if (start < end) i::String::WriteToFlat(*str, buffer, start, write_length);
5607 if (!(options & String::NO_NULL_TERMINATION) &&
5608 (length == -1 || write_length < length)) {
5609 buffer[write_length] = '\0';
5610 }
5611 return write_length;
5612 }
5613
WriteOneByte(Isolate * isolate,uint8_t * buffer,int start,int length,int options) const5614 int String::WriteOneByte(Isolate* isolate, uint8_t* buffer, int start,
5615 int length, int options) const {
5616 return WriteHelper(reinterpret_cast<i::Isolate*>(isolate), this, buffer,
5617 start, length, options);
5618 }
5619
Write(Isolate * isolate,uint16_t * buffer,int start,int length,int options) const5620 int String::Write(Isolate* isolate, uint16_t* buffer, int start, int length,
5621 int options) const {
5622 return WriteHelper(reinterpret_cast<i::Isolate*>(isolate), this, buffer,
5623 start, length, options);
5624 }
5625
IsExternal() const5626 bool v8::String::IsExternal() const {
5627 i::Handle<i::String> str = Utils::OpenHandle(this);
5628 return i::StringShape(*str).IsExternal();
5629 }
5630
IsExternalTwoByte() const5631 bool v8::String::IsExternalTwoByte() const {
5632 i::Handle<i::String> str = Utils::OpenHandle(this);
5633 return i::StringShape(*str).IsExternalTwoByte();
5634 }
5635
IsExternalOneByte() const5636 bool v8::String::IsExternalOneByte() const {
5637 i::Handle<i::String> str = Utils::OpenHandle(this);
5638 return i::StringShape(*str).IsExternalOneByte();
5639 }
5640
VerifyExternalStringResource(v8::String::ExternalStringResource * value) const5641 void v8::String::VerifyExternalStringResource(
5642 v8::String::ExternalStringResource* value) const {
5643 i::DisallowGarbageCollection no_gc;
5644 i::String str = *Utils::OpenHandle(this);
5645 const v8::String::ExternalStringResource* expected;
5646
5647 if (str.IsThinString()) {
5648 str = i::ThinString::cast(str).actual();
5649 }
5650
5651 if (i::StringShape(str).IsExternalTwoByte()) {
5652 const void* resource = i::ExternalTwoByteString::cast(str).resource();
5653 expected = reinterpret_cast<const ExternalStringResource*>(resource);
5654 } else {
5655 expected = nullptr;
5656 }
5657 CHECK_EQ(expected, value);
5658 }
5659
VerifyExternalStringResourceBase(v8::String::ExternalStringResourceBase * value,Encoding encoding) const5660 void v8::String::VerifyExternalStringResourceBase(
5661 v8::String::ExternalStringResourceBase* value, Encoding encoding) const {
5662 i::DisallowGarbageCollection no_gc;
5663 i::String str = *Utils::OpenHandle(this);
5664 const v8::String::ExternalStringResourceBase* expected;
5665 Encoding expectedEncoding;
5666
5667 if (str.IsThinString()) {
5668 str = i::ThinString::cast(str).actual();
5669 }
5670
5671 if (i::StringShape(str).IsExternalOneByte()) {
5672 const void* resource = i::ExternalOneByteString::cast(str).resource();
5673 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
5674 expectedEncoding = ONE_BYTE_ENCODING;
5675 } else if (i::StringShape(str).IsExternalTwoByte()) {
5676 const void* resource = i::ExternalTwoByteString::cast(str).resource();
5677 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
5678 expectedEncoding = TWO_BYTE_ENCODING;
5679 } else {
5680 expected = nullptr;
5681 expectedEncoding =
5682 str.IsOneByteRepresentation() ? ONE_BYTE_ENCODING : TWO_BYTE_ENCODING;
5683 }
5684 CHECK_EQ(expected, value);
5685 CHECK_EQ(expectedEncoding, encoding);
5686 }
5687
GetExternalStringResourceSlow() const5688 String::ExternalStringResource* String::GetExternalStringResourceSlow() const {
5689 i::DisallowGarbageCollection no_gc;
5690 using I = internal::Internals;
5691 i::String str = *Utils::OpenHandle(this);
5692
5693 if (str.IsThinString()) {
5694 str = i::ThinString::cast(str).actual();
5695 }
5696
5697 if (i::StringShape(str).IsExternalTwoByte()) {
5698 internal::Isolate* isolate = I::GetIsolateForHeapSandbox(str.ptr());
5699 internal::Address value = I::ReadExternalPointerField(
5700 isolate, str.ptr(), I::kStringResourceOffset,
5701 internal::kExternalStringResourceTag);
5702 return reinterpret_cast<String::ExternalStringResource*>(value);
5703 }
5704 return nullptr;
5705 }
5706
UpdateDataCache()5707 void String::ExternalStringResource::UpdateDataCache() {
5708 DCHECK(IsCacheable());
5709 cached_data_ = data();
5710 }
5711
CheckCachedDataInvariants() const5712 void String::ExternalStringResource::CheckCachedDataInvariants() const {
5713 DCHECK(IsCacheable() && cached_data_ != nullptr);
5714 }
5715
UpdateDataCache()5716 void String::ExternalOneByteStringResource::UpdateDataCache() {
5717 DCHECK(IsCacheable());
5718 cached_data_ = data();
5719 }
5720
CheckCachedDataInvariants() const5721 void String::ExternalOneByteStringResource::CheckCachedDataInvariants() const {
5722 DCHECK(IsCacheable() && cached_data_ != nullptr);
5723 }
5724
GetExternalStringResourceBaseSlow(String::Encoding * encoding_out) const5725 String::ExternalStringResourceBase* String::GetExternalStringResourceBaseSlow(
5726 String::Encoding* encoding_out) const {
5727 i::DisallowGarbageCollection no_gc;
5728 using I = internal::Internals;
5729 ExternalStringResourceBase* resource = nullptr;
5730 i::String str = *Utils::OpenHandle(this);
5731
5732 if (str.IsThinString()) {
5733 str = i::ThinString::cast(str).actual();
5734 }
5735
5736 internal::Address string = str.ptr();
5737 int type = I::GetInstanceType(string) & I::kFullStringRepresentationMask;
5738 *encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask);
5739 if (i::StringShape(str).IsExternalOneByte() ||
5740 i::StringShape(str).IsExternalTwoByte()) {
5741 internal::Isolate* isolate = I::GetIsolateForHeapSandbox(string);
5742 internal::Address value =
5743 I::ReadExternalPointerField(isolate, string, I::kStringResourceOffset,
5744 internal::kExternalStringResourceTag);
5745 resource = reinterpret_cast<ExternalStringResourceBase*>(value);
5746 }
5747 return resource;
5748 }
5749
5750 const v8::String::ExternalOneByteStringResource*
GetExternalOneByteStringResource() const5751 v8::String::GetExternalOneByteStringResource() const {
5752 i::DisallowGarbageCollection no_gc;
5753 i::String str = *Utils::OpenHandle(this);
5754 if (i::StringShape(str).IsExternalOneByte()) {
5755 return i::ExternalOneByteString::cast(str).resource();
5756 } else if (str.IsThinString()) {
5757 str = i::ThinString::cast(str).actual();
5758 if (i::StringShape(str).IsExternalOneByte()) {
5759 return i::ExternalOneByteString::cast(str).resource();
5760 }
5761 }
5762 return nullptr;
5763 }
5764
Description() const5765 Local<Value> Symbol::Description() const {
5766 i::Handle<i::Symbol> sym = Utils::OpenHandle(this);
5767
5768 i::Isolate* isolate;
5769 if (!i::GetIsolateFromHeapObject(*sym, &isolate)) {
5770 // Symbol is in RO_SPACE, which means that its description is also in
5771 // RO_SPACE. Since RO_SPACE objects are immovable we can use the
5772 // Handle(Address*) constructor with the address of the description
5773 // field in the Symbol object without needing an isolate.
5774 DCHECK(!COMPRESS_POINTERS_IN_ISOLATE_CAGE_BOOL);
5775 #ifndef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
5776 i::Handle<i::HeapObject> ro_description(reinterpret_cast<i::Address*>(
5777 sym->GetFieldAddress(i::Symbol::kDescriptionOffset)));
5778 return Utils::ToLocal(ro_description);
5779 #else
5780 isolate = reinterpret_cast<i::Isolate*>(Isolate::GetCurrent());
5781 #endif
5782 }
5783
5784 return Description(reinterpret_cast<Isolate*>(isolate));
5785 }
5786
Description(Isolate * isolate) const5787 Local<Value> Symbol::Description(Isolate* isolate) const {
5788 i::Handle<i::Symbol> sym = Utils::OpenHandle(this);
5789 i::Handle<i::Object> description(sym->description(),
5790 reinterpret_cast<i::Isolate*>(isolate));
5791 return Utils::ToLocal(description);
5792 }
5793
Name() const5794 Local<Value> Private::Name() const {
5795 const Symbol* sym = reinterpret_cast<const Symbol*>(this);
5796 i::Handle<i::Symbol> i_sym = Utils::OpenHandle(sym);
5797 // v8::Private symbols are created by API and are therefore writable, so we
5798 // can always recover an Isolate.
5799 i::Isolate* isolate = i::GetIsolateFromWritableObject(*i_sym);
5800 return sym->Description(reinterpret_cast<Isolate*>(isolate));
5801 }
5802
Value() const5803 double Number::Value() const {
5804 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5805 return obj->Number();
5806 }
5807
Value() const5808 bool Boolean::Value() const {
5809 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5810 return obj->IsTrue();
5811 }
5812
Value() const5813 int64_t Integer::Value() const {
5814 i::Object obj = *Utils::OpenHandle(this);
5815 if (obj.IsSmi()) {
5816 return i::Smi::ToInt(obj);
5817 } else {
5818 return static_cast<int64_t>(obj.Number());
5819 }
5820 }
5821
Value() const5822 int32_t Int32::Value() const {
5823 i::Object obj = *Utils::OpenHandle(this);
5824 if (obj.IsSmi()) {
5825 return i::Smi::ToInt(obj);
5826 } else {
5827 return static_cast<int32_t>(obj.Number());
5828 }
5829 }
5830
Value() const5831 uint32_t Uint32::Value() const {
5832 i::Object obj = *Utils::OpenHandle(this);
5833 if (obj.IsSmi()) {
5834 return i::Smi::ToInt(obj);
5835 } else {
5836 return static_cast<uint32_t>(obj.Number());
5837 }
5838 }
5839
InternalFieldCount() const5840 int v8::Object::InternalFieldCount() const {
5841 i::JSReceiver self = *Utils::OpenHandle(this);
5842 if (!self.IsJSObject()) return 0;
5843 return i::JSObject::cast(self).GetEmbedderFieldCount();
5844 }
5845
InternalFieldOK(i::Handle<i::JSReceiver> obj,int index,const char * location)5846 static bool InternalFieldOK(i::Handle<i::JSReceiver> obj, int index,
5847 const char* location) {
5848 return Utils::ApiCheck(
5849 obj->IsJSObject() &&
5850 (index < i::Handle<i::JSObject>::cast(obj)->GetEmbedderFieldCount()),
5851 location, "Internal field out of bounds");
5852 }
5853
SlowGetInternalField(int index)5854 Local<Value> v8::Object::SlowGetInternalField(int index) {
5855 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
5856 const char* location = "v8::Object::GetInternalField()";
5857 if (!InternalFieldOK(obj, index, location)) return Local<Value>();
5858 i::Handle<i::Object> value(i::JSObject::cast(*obj).GetEmbedderField(index),
5859 obj->GetIsolate());
5860 return Utils::ToLocal(value);
5861 }
5862
SetInternalField(int index,v8::Local<Value> value)5863 void v8::Object::SetInternalField(int index, v8::Local<Value> value) {
5864 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
5865 const char* location = "v8::Object::SetInternalField()";
5866 if (!InternalFieldOK(obj, index, location)) return;
5867 i::Handle<i::Object> val = Utils::OpenHandle(*value);
5868 i::Handle<i::JSObject>::cast(obj)->SetEmbedderField(index, *val);
5869 }
5870
SlowGetAlignedPointerFromInternalField(int index)5871 void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) {
5872 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
5873 const char* location = "v8::Object::GetAlignedPointerFromInternalField()";
5874 if (!InternalFieldOK(obj, index, location)) return nullptr;
5875 void* result;
5876 Utils::ApiCheck(i::EmbedderDataSlot(i::JSObject::cast(*obj), index)
5877 .ToAlignedPointer(obj->GetIsolate(), &result),
5878 location, "Unaligned pointer");
5879 return result;
5880 }
5881
SetAlignedPointerInInternalField(int index,void * value)5882 void v8::Object::SetAlignedPointerInInternalField(int index, void* value) {
5883 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
5884 const char* location = "v8::Object::SetAlignedPointerInInternalField()";
5885 if (!InternalFieldOK(obj, index, location)) return;
5886 Utils::ApiCheck(i::EmbedderDataSlot(i::JSObject::cast(*obj), index)
5887 .store_aligned_pointer(obj->GetIsolate(), value),
5888 location, "Unaligned pointer");
5889 DCHECK_EQ(value, GetAlignedPointerFromInternalField(index));
5890 }
5891
SetAlignedPointerInInternalFields(int argc,int indices[],void * values[])5892 void v8::Object::SetAlignedPointerInInternalFields(int argc, int indices[],
5893 void* values[]) {
5894 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
5895 const char* location = "v8::Object::SetAlignedPointerInInternalFields()";
5896 i::DisallowGarbageCollection no_gc;
5897 i::JSObject js_obj = i::JSObject::cast(*obj);
5898 int nof_embedder_fields = js_obj.GetEmbedderFieldCount();
5899 for (int i = 0; i < argc; i++) {
5900 int index = indices[i];
5901 if (!Utils::ApiCheck(index < nof_embedder_fields, location,
5902 "Internal field out of bounds")) {
5903 return;
5904 }
5905 void* value = values[i];
5906 Utils::ApiCheck(i::EmbedderDataSlot(js_obj, index)
5907 .store_aligned_pointer(obj->GetIsolate(), value),
5908 location, "Unaligned pointer");
5909 DCHECK_EQ(value, GetAlignedPointerFromInternalField(index));
5910 }
5911 }
5912
ExternalValue(i::Object obj)5913 static void* ExternalValue(i::Object obj) {
5914 // Obscure semantics for undefined, but somehow checked in our unit tests...
5915 if (obj.IsUndefined()) {
5916 return nullptr;
5917 }
5918 i::Object foreign = i::JSObject::cast(obj).GetEmbedderField(0);
5919 return reinterpret_cast<void*>(i::Foreign::cast(foreign).foreign_address());
5920 }
5921
5922 // --- E n v i r o n m e n t ---
5923
InitializePlatform(Platform * platform)5924 void v8::V8::InitializePlatform(Platform* platform) {
5925 i::V8::InitializePlatform(platform);
5926 }
5927
5928 #ifdef V8_VIRTUAL_MEMORY_CAGE
InitializeVirtualMemoryCage()5929 bool v8::V8::InitializeVirtualMemoryCage() {
5930 return i::V8::InitializeVirtualMemoryCage();
5931 }
5932 #endif
5933
ShutdownPlatform()5934 void v8::V8::ShutdownPlatform() { i::V8::ShutdownPlatform(); }
5935
Initialize(const int build_config)5936 bool v8::V8::Initialize(const int build_config) {
5937 const bool kEmbedderPointerCompression =
5938 (build_config & kPointerCompression) != 0;
5939 if (kEmbedderPointerCompression != COMPRESS_POINTERS_BOOL) {
5940 FATAL(
5941 "Embedder-vs-V8 build configuration mismatch. On embedder side "
5942 "pointer compression is %s while on V8 side it's %s.",
5943 kEmbedderPointerCompression ? "ENABLED" : "DISABLED",
5944 COMPRESS_POINTERS_BOOL ? "ENABLED" : "DISABLED");
5945 }
5946
5947 const int kEmbedderSmiValueSize = (build_config & k31BitSmis) ? 31 : 32;
5948 if (kEmbedderSmiValueSize != internal::kSmiValueSize) {
5949 FATAL(
5950 "Embedder-vs-V8 build configuration mismatch. On embedder side "
5951 "Smi value size is %d while on V8 side it's %d.",
5952 kEmbedderSmiValueSize, internal::kSmiValueSize);
5953 }
5954
5955 const bool kEmbedderHeapSandbox = (build_config & kHeapSandbox) != 0;
5956 if (kEmbedderHeapSandbox != V8_HEAP_SANDBOX_BOOL) {
5957 FATAL(
5958 "Embedder-vs-V8 build configuration mismatch. On embedder side "
5959 "heap sandbox is %s while on V8 side it's %s.",
5960 kEmbedderHeapSandbox ? "ENABLED" : "DISABLED",
5961 V8_HEAP_SANDBOX_BOOL ? "ENABLED" : "DISABLED");
5962 }
5963
5964 const bool kEmbedderVirtualMemoryCage =
5965 (build_config & kVirtualMemoryCage) != 0;
5966 if (kEmbedderVirtualMemoryCage != V8_VIRTUAL_MEMORY_CAGE_BOOL) {
5967 FATAL(
5968 "Embedder-vs-V8 build configuration mismatch. On embedder side "
5969 "virtual memory cage is %s while on V8 side it's %s.",
5970 kEmbedderVirtualMemoryCage ? "ENABLED" : "DISABLED",
5971 V8_VIRTUAL_MEMORY_CAGE_BOOL ? "ENABLED" : "DISABLED");
5972 }
5973
5974 i::V8::Initialize();
5975 return true;
5976 }
5977
5978 #if V8_OS_LINUX || V8_OS_MACOSX || V8_OS_OPENBSD || V8_OS_FREEBSD
TryHandleWebAssemblyTrapPosix(int sig_code,siginfo_t * info,void * context)5979 bool TryHandleWebAssemblyTrapPosix(int sig_code, siginfo_t* info,
5980 void* context) {
5981 #if V8_ENABLE_WEBASSEMBLY && V8_TRAP_HANDLER_SUPPORTED
5982 return i::trap_handler::TryHandleSignal(sig_code, info, context);
5983 #else
5984 return false;
5985 #endif
5986 }
5987 #endif
5988
5989 #if V8_OS_WIN
TryHandleWebAssemblyTrapWindows(EXCEPTION_POINTERS * exception)5990 bool TryHandleWebAssemblyTrapWindows(EXCEPTION_POINTERS* exception) {
5991 #if V8_ENABLE_WEBASSEMBLY && V8_TRAP_HANDLER_SUPPORTED
5992 return i::trap_handler::TryHandleWasmTrap(exception);
5993 #else
5994 return false;
5995 #endif
5996 }
5997 #endif
5998
EnableWebAssemblyTrapHandler(bool use_v8_signal_handler)5999 bool V8::EnableWebAssemblyTrapHandler(bool use_v8_signal_handler) {
6000 #if V8_ENABLE_WEBASSEMBLY
6001 return v8::internal::trap_handler::EnableTrapHandler(use_v8_signal_handler);
6002 #else
6003 return false;
6004 #endif
6005 }
6006
6007 #if defined(V8_OS_WIN)
SetUnhandledExceptionCallback(UnhandledExceptionCallback unhandled_exception_callback)6008 void V8::SetUnhandledExceptionCallback(
6009 UnhandledExceptionCallback unhandled_exception_callback) {
6010 #if defined(V8_OS_WIN64)
6011 v8::internal::win64_unwindinfo::SetUnhandledExceptionCallback(
6012 unhandled_exception_callback);
6013 #else
6014 // Not implemented, port needed.
6015 #endif // V8_OS_WIN64
6016 }
6017 #endif // V8_OS_WIN
6018
SetEntropySource(EntropySource entropy_source)6019 void v8::V8::SetEntropySource(EntropySource entropy_source) {
6020 base::RandomNumberGenerator::SetEntropySource(entropy_source);
6021 }
6022
SetReturnAddressLocationResolver(ReturnAddressLocationResolver return_address_resolver)6023 void v8::V8::SetReturnAddressLocationResolver(
6024 ReturnAddressLocationResolver return_address_resolver) {
6025 i::StackFrame::SetReturnAddressLocationResolver(return_address_resolver);
6026 }
6027
Dispose()6028 bool v8::V8::Dispose() {
6029 i::V8::TearDown();
6030 return true;
6031 }
6032
SharedMemoryStatistics()6033 SharedMemoryStatistics::SharedMemoryStatistics()
6034 : read_only_space_size_(0),
6035 read_only_space_used_size_(0),
6036 read_only_space_physical_size_(0) {}
6037
HeapStatistics()6038 HeapStatistics::HeapStatistics()
6039 : total_heap_size_(0),
6040 total_heap_size_executable_(0),
6041 total_physical_size_(0),
6042 total_available_size_(0),
6043 used_heap_size_(0),
6044 heap_size_limit_(0),
6045 malloced_memory_(0),
6046 external_memory_(0),
6047 peak_malloced_memory_(0),
6048 does_zap_garbage_(false),
6049 number_of_native_contexts_(0),
6050 number_of_detached_contexts_(0) {}
6051
HeapSpaceStatistics()6052 HeapSpaceStatistics::HeapSpaceStatistics()
6053 : space_name_(nullptr),
6054 space_size_(0),
6055 space_used_size_(0),
6056 space_available_size_(0),
6057 physical_space_size_(0) {}
6058
HeapObjectStatistics()6059 HeapObjectStatistics::HeapObjectStatistics()
6060 : object_type_(nullptr),
6061 object_sub_type_(nullptr),
6062 object_count_(0),
6063 object_size_(0) {}
6064
HeapCodeStatistics()6065 HeapCodeStatistics::HeapCodeStatistics()
6066 : code_and_metadata_size_(0),
6067 bytecode_and_metadata_size_(0),
6068 external_script_source_size_(0) {}
6069
InitializeICU(const char * icu_data_file)6070 bool v8::V8::InitializeICU(const char* icu_data_file) {
6071 return i::InitializeICU(icu_data_file);
6072 }
6073
InitializeICUDefaultLocation(const char * exec_path,const char * icu_data_file)6074 bool v8::V8::InitializeICUDefaultLocation(const char* exec_path,
6075 const char* icu_data_file) {
6076 return i::InitializeICUDefaultLocation(exec_path, icu_data_file);
6077 }
6078
InitializeExternalStartupData(const char * directory_path)6079 void v8::V8::InitializeExternalStartupData(const char* directory_path) {
6080 i::InitializeExternalStartupData(directory_path);
6081 }
6082
6083 // static
InitializeExternalStartupDataFromFile(const char * snapshot_blob)6084 void v8::V8::InitializeExternalStartupDataFromFile(const char* snapshot_blob) {
6085 i::InitializeExternalStartupDataFromFile(snapshot_blob);
6086 }
6087
GetVersion()6088 const char* v8::V8::GetVersion() { return i::Version::GetVersion(); }
6089
6090 #ifdef V8_VIRTUAL_MEMORY_CAGE
GetVirtualMemoryCagePageAllocator()6091 PageAllocator* v8::V8::GetVirtualMemoryCagePageAllocator() {
6092 CHECK(i::GetProcessWideVirtualMemoryCage()->is_initialized());
6093 return i::GetProcessWideVirtualMemoryCage()->page_allocator();
6094 }
6095
GetVirtualMemoryCageSizeInBytes()6096 size_t v8::V8::GetVirtualMemoryCageSizeInBytes() {
6097 if (!i::GetProcessWideVirtualMemoryCage()->is_initialized()) {
6098 return 0;
6099 } else {
6100 return i::GetProcessWideVirtualMemoryCage()->size();
6101 }
6102 }
6103 #endif
6104
GetSharedMemoryStatistics(SharedMemoryStatistics * statistics)6105 void V8::GetSharedMemoryStatistics(SharedMemoryStatistics* statistics) {
6106 i::ReadOnlyHeap::PopulateReadOnlySpaceStatistics(statistics);
6107 }
6108
6109 template <typename ObjectType>
6110 struct InvokeBootstrapper;
6111
6112 template <>
6113 struct InvokeBootstrapper<i::Context> {
Invokev8::InvokeBootstrapper6114 i::Handle<i::Context> Invoke(
6115 i::Isolate* isolate, i::MaybeHandle<i::JSGlobalProxy> maybe_global_proxy,
6116 v8::Local<v8::ObjectTemplate> global_proxy_template,
6117 v8::ExtensionConfiguration* extensions, size_t context_snapshot_index,
6118 v8::DeserializeInternalFieldsCallback embedder_fields_deserializer,
6119 v8::MicrotaskQueue* microtask_queue) {
6120 return isolate->bootstrapper()->CreateEnvironment(
6121 maybe_global_proxy, global_proxy_template, extensions,
6122 context_snapshot_index, embedder_fields_deserializer, microtask_queue);
6123 }
6124 };
6125
6126 template <>
6127 struct InvokeBootstrapper<i::JSGlobalProxy> {
Invokev8::InvokeBootstrapper6128 i::Handle<i::JSGlobalProxy> Invoke(
6129 i::Isolate* isolate, i::MaybeHandle<i::JSGlobalProxy> maybe_global_proxy,
6130 v8::Local<v8::ObjectTemplate> global_proxy_template,
6131 v8::ExtensionConfiguration* extensions, size_t context_snapshot_index,
6132 v8::DeserializeInternalFieldsCallback embedder_fields_deserializer,
6133 v8::MicrotaskQueue* microtask_queue) {
6134 USE(extensions);
6135 USE(context_snapshot_index);
6136 return isolate->bootstrapper()->NewRemoteContext(maybe_global_proxy,
6137 global_proxy_template);
6138 }
6139 };
6140
6141 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)6142 static i::Handle<ObjectType> CreateEnvironment(
6143 i::Isolate* isolate, v8::ExtensionConfiguration* extensions,
6144 v8::MaybeLocal<ObjectTemplate> maybe_global_template,
6145 v8::MaybeLocal<Value> maybe_global_proxy, size_t context_snapshot_index,
6146 v8::DeserializeInternalFieldsCallback embedder_fields_deserializer,
6147 v8::MicrotaskQueue* microtask_queue) {
6148 i::Handle<ObjectType> result;
6149
6150 {
6151 ENTER_V8_FOR_NEW_CONTEXT(isolate);
6152 v8::Local<ObjectTemplate> proxy_template;
6153 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
6154 i::Handle<i::FunctionTemplateInfo> global_constructor;
6155 i::Handle<i::HeapObject> named_interceptor(
6156 isolate->factory()->undefined_value());
6157 i::Handle<i::HeapObject> indexed_interceptor(
6158 isolate->factory()->undefined_value());
6159
6160 if (!maybe_global_template.IsEmpty()) {
6161 v8::Local<v8::ObjectTemplate> global_template =
6162 maybe_global_template.ToLocalChecked();
6163 // Make sure that the global_template has a constructor.
6164 global_constructor = EnsureConstructor(isolate, *global_template);
6165
6166 // Create a fresh template for the global proxy object.
6167 proxy_template =
6168 ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate));
6169 proxy_constructor = EnsureConstructor(isolate, *proxy_template);
6170
6171 // Set the global template to be the prototype template of
6172 // global proxy template.
6173 i::FunctionTemplateInfo::SetPrototypeTemplate(
6174 isolate, proxy_constructor, Utils::OpenHandle(*global_template));
6175
6176 proxy_template->SetInternalFieldCount(
6177 global_template->InternalFieldCount());
6178
6179 // Migrate security handlers from global_template to
6180 // proxy_template. Temporarily removing access check
6181 // information from the global template.
6182 if (!global_constructor->GetAccessCheckInfo().IsUndefined(isolate)) {
6183 i::FunctionTemplateInfo::SetAccessCheckInfo(
6184 isolate, proxy_constructor,
6185 i::handle(global_constructor->GetAccessCheckInfo(), isolate));
6186 proxy_constructor->set_needs_access_check(
6187 global_constructor->needs_access_check());
6188 global_constructor->set_needs_access_check(false);
6189 i::FunctionTemplateInfo::SetAccessCheckInfo(
6190 isolate, global_constructor,
6191 i::ReadOnlyRoots(isolate).undefined_value_handle());
6192 }
6193
6194 // Same for other interceptors. If the global constructor has
6195 // interceptors, we need to replace them temporarily with noop
6196 // interceptors, so the map is correctly marked as having interceptors,
6197 // but we don't invoke any.
6198 if (!global_constructor->GetNamedPropertyHandler().IsUndefined(isolate)) {
6199 named_interceptor =
6200 handle(global_constructor->GetNamedPropertyHandler(), isolate);
6201 i::FunctionTemplateInfo::SetNamedPropertyHandler(
6202 isolate, global_constructor,
6203 i::ReadOnlyRoots(isolate).noop_interceptor_info_handle());
6204 }
6205 if (!global_constructor->GetIndexedPropertyHandler().IsUndefined(
6206 isolate)) {
6207 indexed_interceptor =
6208 handle(global_constructor->GetIndexedPropertyHandler(), isolate);
6209 i::FunctionTemplateInfo::SetIndexedPropertyHandler(
6210 isolate, global_constructor,
6211 i::ReadOnlyRoots(isolate).noop_interceptor_info_handle());
6212 }
6213 }
6214
6215 i::MaybeHandle<i::JSGlobalProxy> maybe_proxy;
6216 if (!maybe_global_proxy.IsEmpty()) {
6217 maybe_proxy = i::Handle<i::JSGlobalProxy>::cast(
6218 Utils::OpenHandle(*maybe_global_proxy.ToLocalChecked()));
6219 }
6220 // Create the environment.
6221 InvokeBootstrapper<ObjectType> invoke;
6222 result = invoke.Invoke(isolate, maybe_proxy, proxy_template, extensions,
6223 context_snapshot_index, embedder_fields_deserializer,
6224 microtask_queue);
6225
6226 // Restore the access check info and interceptors on the global template.
6227 if (!maybe_global_template.IsEmpty()) {
6228 DCHECK(!global_constructor.is_null());
6229 DCHECK(!proxy_constructor.is_null());
6230 i::FunctionTemplateInfo::SetAccessCheckInfo(
6231 isolate, global_constructor,
6232 i::handle(proxy_constructor->GetAccessCheckInfo(), isolate));
6233 global_constructor->set_needs_access_check(
6234 proxy_constructor->needs_access_check());
6235 i::FunctionTemplateInfo::SetNamedPropertyHandler(
6236 isolate, global_constructor, named_interceptor);
6237 i::FunctionTemplateInfo::SetIndexedPropertyHandler(
6238 isolate, global_constructor, indexed_interceptor);
6239 }
6240 }
6241 // Leave V8.
6242
6243 return result;
6244 }
6245
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)6246 Local<Context> NewContext(
6247 v8::Isolate* external_isolate, v8::ExtensionConfiguration* extensions,
6248 v8::MaybeLocal<ObjectTemplate> global_template,
6249 v8::MaybeLocal<Value> global_object, size_t context_snapshot_index,
6250 v8::DeserializeInternalFieldsCallback embedder_fields_deserializer,
6251 v8::MicrotaskQueue* microtask_queue) {
6252 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
6253 // TODO(jkummerow): This is for crbug.com/713699. Remove it if it doesn't
6254 // fail.
6255 // Sanity-check that the isolate is initialized and usable.
6256 CHECK(isolate->builtins()->code(i::Builtin::kIllegal).IsCode());
6257
6258 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.NewContext");
6259 LOG_API(isolate, Context, New);
6260 i::HandleScope scope(isolate);
6261 ExtensionConfiguration no_extensions;
6262 if (extensions == nullptr) extensions = &no_extensions;
6263 i::Handle<i::Context> env = CreateEnvironment<i::Context>(
6264 isolate, extensions, global_template, global_object,
6265 context_snapshot_index, embedder_fields_deserializer, microtask_queue);
6266 if (env.is_null()) {
6267 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
6268 return Local<Context>();
6269 }
6270 return Utils::ToLocal(scope.CloseAndEscape(env));
6271 }
6272
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)6273 Local<Context> v8::Context::New(
6274 v8::Isolate* external_isolate, v8::ExtensionConfiguration* extensions,
6275 v8::MaybeLocal<ObjectTemplate> global_template,
6276 v8::MaybeLocal<Value> global_object,
6277 DeserializeInternalFieldsCallback internal_fields_deserializer,
6278 v8::MicrotaskQueue* microtask_queue) {
6279 return NewContext(external_isolate, extensions, global_template,
6280 global_object, 0, internal_fields_deserializer,
6281 microtask_queue);
6282 }
6283
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)6284 MaybeLocal<Context> v8::Context::FromSnapshot(
6285 v8::Isolate* external_isolate, size_t context_snapshot_index,
6286 v8::DeserializeInternalFieldsCallback embedder_fields_deserializer,
6287 v8::ExtensionConfiguration* extensions, MaybeLocal<Value> global_object,
6288 v8::MicrotaskQueue* microtask_queue) {
6289 size_t index_including_default_context = context_snapshot_index + 1;
6290 if (!i::Snapshot::HasContextSnapshot(
6291 reinterpret_cast<i::Isolate*>(external_isolate),
6292 index_including_default_context)) {
6293 return MaybeLocal<Context>();
6294 }
6295 return NewContext(external_isolate, extensions, MaybeLocal<ObjectTemplate>(),
6296 global_object, index_including_default_context,
6297 embedder_fields_deserializer, microtask_queue);
6298 }
6299
NewRemoteContext(v8::Isolate * external_isolate,v8::Local<ObjectTemplate> global_template,v8::MaybeLocal<v8::Value> global_object)6300 MaybeLocal<Object> v8::Context::NewRemoteContext(
6301 v8::Isolate* external_isolate, v8::Local<ObjectTemplate> global_template,
6302 v8::MaybeLocal<v8::Value> global_object) {
6303 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
6304 LOG_API(isolate, Context, NewRemoteContext);
6305 i::HandleScope scope(isolate);
6306 i::Handle<i::FunctionTemplateInfo> global_constructor =
6307 EnsureConstructor(isolate, *global_template);
6308 Utils::ApiCheck(global_constructor->needs_access_check(),
6309 "v8::Context::NewRemoteContext",
6310 "Global template needs to have access checks enabled.");
6311 i::Handle<i::AccessCheckInfo> access_check_info = i::handle(
6312 i::AccessCheckInfo::cast(global_constructor->GetAccessCheckInfo()),
6313 isolate);
6314 Utils::ApiCheck(access_check_info->named_interceptor() != i::Object(),
6315 "v8::Context::NewRemoteContext",
6316 "Global template needs to have access check handlers.");
6317 i::Handle<i::JSObject> global_proxy = CreateEnvironment<i::JSGlobalProxy>(
6318 isolate, nullptr, global_template, global_object, 0,
6319 DeserializeInternalFieldsCallback(), nullptr);
6320 if (global_proxy.is_null()) {
6321 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
6322 return MaybeLocal<Object>();
6323 }
6324 return Utils::ToLocal(scope.CloseAndEscape(global_proxy));
6325 }
6326
SetSecurityToken(Local<Value> token)6327 void v8::Context::SetSecurityToken(Local<Value> token) {
6328 i::Handle<i::Context> env = Utils::OpenHandle(this);
6329 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
6330 env->set_security_token(*token_handle);
6331 }
6332
UseDefaultSecurityToken()6333 void v8::Context::UseDefaultSecurityToken() {
6334 i::Handle<i::Context> env = Utils::OpenHandle(this);
6335 env->set_security_token(env->global_object());
6336 }
6337
GetSecurityToken()6338 Local<Value> v8::Context::GetSecurityToken() {
6339 i::Handle<i::Context> env = Utils::OpenHandle(this);
6340 i::Isolate* isolate = env->GetIsolate();
6341 i::Object security_token = env->security_token();
6342 i::Handle<i::Object> token_handle(security_token, isolate);
6343 return Utils::ToLocal(token_handle);
6344 }
6345
GetIsolate()6346 v8::Isolate* Context::GetIsolate() {
6347 i::Handle<i::Context> env = Utils::OpenHandle(this);
6348 return reinterpret_cast<Isolate*>(env->GetIsolate());
6349 }
6350
GetMicrotaskQueue()6351 v8::MicrotaskQueue* Context::GetMicrotaskQueue() {
6352 i::Handle<i::Context> env = Utils::OpenHandle(this);
6353 Utils::ApiCheck(env->IsNativeContext(), "v8::Context::GetMicrotaskQueue",
6354 "Must be calld on a native context");
6355 return i::Handle<i::NativeContext>::cast(env)->microtask_queue();
6356 }
6357
Global()6358 v8::Local<v8::Object> Context::Global() {
6359 i::Handle<i::Context> context = Utils::OpenHandle(this);
6360 i::Isolate* isolate = context->GetIsolate();
6361 i::Handle<i::Object> global(context->global_proxy(), isolate);
6362 // TODO(chromium:324812): This should always return the global proxy
6363 // but can't presently as calls to GetProtoype will return the wrong result.
6364 if (i::Handle<i::JSGlobalProxy>::cast(global)->IsDetachedFrom(
6365 context->global_object())) {
6366 global = i::Handle<i::Object>(context->global_object(), isolate);
6367 }
6368 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
6369 }
6370
DetachGlobal()6371 void Context::DetachGlobal() {
6372 i::Handle<i::Context> context = Utils::OpenHandle(this);
6373 i::Isolate* isolate = context->GetIsolate();
6374 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
6375 isolate->DetachGlobal(context);
6376 }
6377
GetExtrasBindingObject()6378 Local<v8::Object> Context::GetExtrasBindingObject() {
6379 i::Handle<i::Context> context = Utils::OpenHandle(this);
6380 i::Isolate* isolate = context->GetIsolate();
6381 i::Handle<i::JSObject> binding(context->extras_binding_object(), isolate);
6382 return Utils::ToLocal(binding);
6383 }
6384
AllowCodeGenerationFromStrings(bool allow)6385 void Context::AllowCodeGenerationFromStrings(bool allow) {
6386 i::Handle<i::Context> context = Utils::OpenHandle(this);
6387 i::Isolate* isolate = context->GetIsolate();
6388 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
6389 context->set_allow_code_gen_from_strings(
6390 allow ? i::ReadOnlyRoots(isolate).true_value()
6391 : i::ReadOnlyRoots(isolate).false_value());
6392 }
6393
IsCodeGenerationFromStringsAllowed() const6394 bool Context::IsCodeGenerationFromStringsAllowed() const {
6395 i::Context context = *Utils::OpenHandle(this);
6396 return !context.allow_code_gen_from_strings().IsFalse(context.GetIsolate());
6397 }
6398
SetErrorMessageForCodeGenerationFromStrings(Local<String> error)6399 void Context::SetErrorMessageForCodeGenerationFromStrings(Local<String> error) {
6400 i::Handle<i::Context> context = Utils::OpenHandle(this);
6401 i::Handle<i::String> error_handle = Utils::OpenHandle(*error);
6402 context->set_error_message_for_code_gen_from_strings(*error_handle);
6403 }
6404
SetAbortScriptExecution(Context::AbortScriptExecutionCallback callback)6405 void Context::SetAbortScriptExecution(
6406 Context::AbortScriptExecutionCallback callback) {
6407 i::Handle<i::Context> context = Utils::OpenHandle(this);
6408 i::Isolate* isolate = context->GetIsolate();
6409 if (callback == nullptr) {
6410 context->set_script_execution_callback(
6411 i::ReadOnlyRoots(isolate).undefined_value());
6412 } else {
6413 SET_FIELD_WRAPPED(isolate, context, set_script_execution_callback,
6414 callback);
6415 }
6416 }
6417
GetContinuationPreservedEmbedderData() const6418 Local<Value> Context::GetContinuationPreservedEmbedderData() const {
6419 i::Handle<i::Context> context = Utils::OpenHandle(this);
6420 i::Isolate* isolate = context->GetIsolate();
6421 i::Handle<i::Object> data(
6422 context->native_context().continuation_preserved_embedder_data(),
6423 isolate);
6424 return ToApiHandle<Object>(data);
6425 }
6426
SetContinuationPreservedEmbedderData(Local<Value> data)6427 void Context::SetContinuationPreservedEmbedderData(Local<Value> data) {
6428 i::Handle<i::Context> context = Utils::OpenHandle(this);
6429 i::Isolate* isolate = context->GetIsolate();
6430 if (data.IsEmpty())
6431 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
6432 context->native_context().set_continuation_preserved_embedder_data(
6433 *i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*data)));
6434 }
6435
SetPromiseHooks(Local<Function> init_hook,Local<Function> before_hook,Local<Function> after_hook,Local<Function> resolve_hook)6436 void v8::Context::SetPromiseHooks(Local<Function> init_hook,
6437 Local<Function> before_hook,
6438 Local<Function> after_hook,
6439 Local<Function> resolve_hook) {
6440 i::Handle<i::Context> context = Utils::OpenHandle(this);
6441 i::Isolate* isolate = context->GetIsolate();
6442
6443 i::Handle<i::Object> init = isolate->factory()->undefined_value();
6444 i::Handle<i::Object> before = isolate->factory()->undefined_value();
6445 i::Handle<i::Object> after = isolate->factory()->undefined_value();
6446 i::Handle<i::Object> resolve = isolate->factory()->undefined_value();
6447
6448 bool has_hook = false;
6449
6450 if (!init_hook.IsEmpty()) {
6451 init = Utils::OpenHandle(*init_hook);
6452 has_hook = true;
6453 }
6454 if (!before_hook.IsEmpty()) {
6455 before = Utils::OpenHandle(*before_hook);
6456 has_hook = true;
6457 }
6458 if (!after_hook.IsEmpty()) {
6459 after = Utils::OpenHandle(*after_hook);
6460 has_hook = true;
6461 }
6462 if (!resolve_hook.IsEmpty()) {
6463 resolve = Utils::OpenHandle(*resolve_hook);
6464 has_hook = true;
6465 }
6466
6467 isolate->SetHasContextPromiseHooks(has_hook);
6468
6469 context->native_context().set_promise_hook_init_function(*init);
6470 context->native_context().set_promise_hook_before_function(*before);
6471 context->native_context().set_promise_hook_after_function(*after);
6472 context->native_context().set_promise_hook_resolve_function(*resolve);
6473 }
6474
GetContext(Isolate * isolate,metrics::Recorder::ContextId id)6475 MaybeLocal<Context> metrics::Recorder::GetContext(
6476 Isolate* isolate, metrics::Recorder::ContextId id) {
6477 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6478 return i_isolate->GetContextFromRecorderContextId(id);
6479 }
6480
GetContextId(Local<Context> context)6481 metrics::Recorder::ContextId metrics::Recorder::GetContextId(
6482 Local<Context> context) {
6483 i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
6484 i::Isolate* isolate = i_context->GetIsolate();
6485 return isolate->GetOrRegisterRecorderContextId(
6486 handle(i_context->native_context(), isolate));
6487 }
6488
Get(v8::Isolate * isolate)6489 metrics::LongTaskStats metrics::LongTaskStats::Get(v8::Isolate* isolate) {
6490 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6491 return *i_isolate->GetCurrentLongTaskStats();
6492 }
6493
6494 namespace {
GetSerializedDataFromFixedArray(i::Isolate * isolate,i::FixedArray list,size_t index)6495 i::Address* GetSerializedDataFromFixedArray(i::Isolate* isolate,
6496 i::FixedArray list, size_t index) {
6497 if (index < static_cast<size_t>(list.length())) {
6498 int int_index = static_cast<int>(index);
6499 i::Object object = list.get(int_index);
6500 if (!object.IsTheHole(isolate)) {
6501 list.set_the_hole(isolate, int_index);
6502 // Shrink the list so that the last element is not the hole (unless it's
6503 // the first element, because we don't want to end up with a non-canonical
6504 // empty FixedArray).
6505 int last = list.length() - 1;
6506 while (last >= 0 && list.is_the_hole(isolate, last)) last--;
6507 if (last != -1) list.Shrink(isolate, last + 1);
6508 return i::Handle<i::Object>(object, isolate).location();
6509 }
6510 }
6511 return nullptr;
6512 }
6513 } // anonymous namespace
6514
GetDataFromSnapshotOnce(size_t index)6515 i::Address* Context::GetDataFromSnapshotOnce(size_t index) {
6516 auto context = Utils::OpenHandle(this);
6517 i::Isolate* i_isolate = context->GetIsolate();
6518 i::FixedArray list = context->serialized_objects();
6519 return GetSerializedDataFromFixedArray(i_isolate, list, index);
6520 }
6521
NewInstance(Local<Context> context)6522 MaybeLocal<v8::Object> ObjectTemplate::NewInstance(Local<Context> context) {
6523 PREPARE_FOR_EXECUTION(context, ObjectTemplate, NewInstance, Object);
6524 auto self = Utils::OpenHandle(this);
6525 Local<Object> result;
6526 has_pending_exception = !ToLocal<Object>(
6527 i::ApiNatives::InstantiateObject(isolate, self), &result);
6528 RETURN_ON_FAILED_EXECUTION(Object);
6529 RETURN_ESCAPED(result);
6530 }
6531
CheckCast(Data * that)6532 void v8::ObjectTemplate::CheckCast(Data* that) {
6533 i::Handle<i::Object> obj = Utils::OpenHandle(that);
6534 Utils::ApiCheck(obj->IsObjectTemplateInfo(), "v8::ObjectTemplate::Cast",
6535 "Value is not an ObjectTemplate");
6536 }
6537
CheckCast(Data * that)6538 void v8::FunctionTemplate::CheckCast(Data* that) {
6539 i::Handle<i::Object> obj = Utils::OpenHandle(that);
6540 Utils::ApiCheck(obj->IsFunctionTemplateInfo(), "v8::FunctionTemplate::Cast",
6541 "Value is not a FunctionTemplate");
6542 }
6543
CheckCast(Data * that)6544 void v8::Signature::CheckCast(Data* that) {
6545 i::Handle<i::Object> obj = Utils::OpenHandle(that);
6546 Utils::ApiCheck(obj->IsFunctionTemplateInfo(), "v8::Signature::Cast",
6547 "Value is not a Signature");
6548 }
6549
CheckCast(Data * that)6550 void v8::AccessorSignature::CheckCast(Data* that) {
6551 i::Handle<i::Object> obj = Utils::OpenHandle(that);
6552 Utils::ApiCheck(obj->IsFunctionTemplateInfo(), "v8::AccessorSignature::Cast",
6553 "Value is not an AccessorSignature");
6554 }
6555
GetFunction(Local<Context> context)6556 MaybeLocal<v8::Function> FunctionTemplate::GetFunction(Local<Context> context) {
6557 PREPARE_FOR_EXECUTION(context, FunctionTemplate, GetFunction, Function);
6558 auto self = Utils::OpenHandle(this);
6559 Local<Function> result;
6560 has_pending_exception =
6561 !ToLocal<Function>(i::ApiNatives::InstantiateFunction(self), &result);
6562 RETURN_ON_FAILED_EXECUTION(Function);
6563 RETURN_ESCAPED(result);
6564 }
6565
NewRemoteInstance()6566 MaybeLocal<v8::Object> FunctionTemplate::NewRemoteInstance() {
6567 auto self = Utils::OpenHandle(this);
6568 i::Isolate* isolate = self->GetIsolate();
6569 LOG_API(isolate, FunctionTemplate, NewRemoteInstance);
6570 i::HandleScope scope(isolate);
6571 i::Handle<i::FunctionTemplateInfo> constructor =
6572 EnsureConstructor(isolate, *InstanceTemplate());
6573 Utils::ApiCheck(constructor->needs_access_check(),
6574 "v8::FunctionTemplate::NewRemoteInstance",
6575 "InstanceTemplate needs to have access checks enabled.");
6576 i::Handle<i::AccessCheckInfo> access_check_info = i::handle(
6577 i::AccessCheckInfo::cast(constructor->GetAccessCheckInfo()), isolate);
6578 Utils::ApiCheck(access_check_info->named_interceptor() != i::Object(),
6579 "v8::FunctionTemplate::NewRemoteInstance",
6580 "InstanceTemplate needs to have access check handlers.");
6581 i::Handle<i::JSObject> object;
6582 if (!i::ApiNatives::InstantiateRemoteObject(
6583 Utils::OpenHandle(*InstanceTemplate()))
6584 .ToHandle(&object)) {
6585 if (isolate->has_pending_exception()) {
6586 isolate->OptionalRescheduleException(true);
6587 }
6588 return MaybeLocal<Object>();
6589 }
6590 return Utils::ToLocal(scope.CloseAndEscape(object));
6591 }
6592
HasInstance(v8::Local<v8::Value> value)6593 bool FunctionTemplate::HasInstance(v8::Local<v8::Value> value) {
6594 auto self = Utils::OpenHandle(this);
6595 auto obj = Utils::OpenHandle(*value);
6596 if (obj->IsJSObject() && self->IsTemplateFor(i::JSObject::cast(*obj))) {
6597 return true;
6598 }
6599 if (obj->IsJSGlobalProxy()) {
6600 // If it's a global proxy, then test with the global object. Note that the
6601 // inner global object may not necessarily be a JSGlobalObject.
6602 i::PrototypeIterator iter(self->GetIsolate(),
6603 i::JSObject::cast(*obj).map());
6604 // The global proxy should always have a prototype, as it is a bug to call
6605 // this on a detached JSGlobalProxy.
6606 DCHECK(!iter.IsAtEnd());
6607 return self->IsTemplateFor(iter.GetCurrent<i::JSObject>());
6608 }
6609 return false;
6610 }
6611
IsLeafTemplateForApiObject(v8::Local<v8::Value> value) const6612 bool FunctionTemplate::IsLeafTemplateForApiObject(
6613 v8::Local<v8::Value> value) const {
6614 i::DisallowGarbageCollection no_gc;
6615
6616 i::Object object = *Utils::OpenHandle(*value);
6617
6618 auto self = Utils::OpenHandle(this);
6619 return self->IsLeafTemplateForApiObject(object);
6620 }
6621
New(Isolate * isolate,void * value)6622 Local<External> v8::External::New(Isolate* isolate, void* value) {
6623 STATIC_ASSERT(sizeof(value) == sizeof(i::Address));
6624 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6625 LOG_API(i_isolate, External, New);
6626 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
6627 i::Handle<i::JSObject> external = i_isolate->factory()->NewExternal(value);
6628 return Utils::ExternalToLocal(external);
6629 }
6630
Value() const6631 void* External::Value() const {
6632 return ExternalValue(*Utils::OpenHandle(this));
6633 }
6634
6635 // anonymous namespace for string creation helper functions
6636 namespace {
6637
StringLength(const char * string)6638 inline int StringLength(const char* string) {
6639 size_t len = strlen(string);
6640 CHECK_GE(i::kMaxInt, len);
6641 return static_cast<int>(len);
6642 }
6643
StringLength(const uint8_t * string)6644 inline int StringLength(const uint8_t* string) {
6645 return StringLength(reinterpret_cast<const char*>(string));
6646 }
6647
StringLength(const uint16_t * string)6648 inline int StringLength(const uint16_t* string) {
6649 size_t length = 0;
6650 while (string[length] != '\0') length++;
6651 CHECK_GE(i::kMaxInt, length);
6652 return static_cast<int>(length);
6653 }
6654
6655 V8_WARN_UNUSED_RESULT
NewString(i::Factory * factory,NewStringType type,base::Vector<const char> string)6656 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
6657 NewStringType type,
6658 base::Vector<const char> string) {
6659 if (type == NewStringType::kInternalized) {
6660 return factory->InternalizeUtf8String(string);
6661 }
6662 return factory->NewStringFromUtf8(string);
6663 }
6664
6665 V8_WARN_UNUSED_RESULT
NewString(i::Factory * factory,NewStringType type,base::Vector<const uint8_t> string)6666 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
6667 NewStringType type,
6668 base::Vector<const uint8_t> string) {
6669 if (type == NewStringType::kInternalized) {
6670 return factory->InternalizeString(string);
6671 }
6672 return factory->NewStringFromOneByte(string);
6673 }
6674
6675 V8_WARN_UNUSED_RESULT
NewString(i::Factory * factory,NewStringType type,base::Vector<const uint16_t> string)6676 inline i::MaybeHandle<i::String> NewString(
6677 i::Factory* factory, NewStringType type,
6678 base::Vector<const uint16_t> string) {
6679 if (type == NewStringType::kInternalized) {
6680 return factory->InternalizeString(string);
6681 }
6682 return factory->NewStringFromTwoByte(string);
6683 }
6684
6685 STATIC_ASSERT(v8::String::kMaxLength == i::String::kMaxLength);
6686
6687 } // anonymous namespace
6688
6689 // TODO(dcarney): throw a context free exception.
6690 #define NEW_STRING(isolate, class_name, function_name, Char, data, type, \
6691 length) \
6692 MaybeLocal<String> result; \
6693 if (length == 0) { \
6694 result = String::Empty(isolate); \
6695 } else if (length > i::String::kMaxLength) { \
6696 result = MaybeLocal<String>(); \
6697 } else { \
6698 i::Isolate* i_isolate = reinterpret_cast<internal::Isolate*>(isolate); \
6699 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); \
6700 LOG_API(i_isolate, class_name, function_name); \
6701 if (length < 0) length = StringLength(data); \
6702 i::Handle<i::String> handle_result = \
6703 NewString(i_isolate->factory(), type, \
6704 base::Vector<const Char>(data, length)) \
6705 .ToHandleChecked(); \
6706 result = Utils::ToLocal(handle_result); \
6707 }
6708
NewFromUtf8Literal(Isolate * isolate,const char * literal,NewStringType type,int length)6709 Local<String> String::NewFromUtf8Literal(Isolate* isolate, const char* literal,
6710 NewStringType type, int length) {
6711 DCHECK_LE(length, i::String::kMaxLength);
6712 i::Isolate* i_isolate = reinterpret_cast<internal::Isolate*>(isolate);
6713 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
6714 LOG_API(i_isolate, String, NewFromUtf8Literal);
6715 i::Handle<i::String> handle_result =
6716 NewString(i_isolate->factory(), type,
6717 base::Vector<const char>(literal, length))
6718 .ToHandleChecked();
6719 return Utils::ToLocal(handle_result);
6720 }
6721
NewFromUtf8(Isolate * isolate,const char * data,NewStringType type,int length)6722 MaybeLocal<String> String::NewFromUtf8(Isolate* isolate, const char* data,
6723 NewStringType type, int length) {
6724 NEW_STRING(isolate, String, NewFromUtf8, char, data, type, length);
6725 return result;
6726 }
6727
NewFromOneByte(Isolate * isolate,const uint8_t * data,NewStringType type,int length)6728 MaybeLocal<String> String::NewFromOneByte(Isolate* isolate, const uint8_t* data,
6729 NewStringType type, int length) {
6730 NEW_STRING(isolate, String, NewFromOneByte, uint8_t, data, type, length);
6731 return result;
6732 }
6733
NewFromTwoByte(Isolate * isolate,const uint16_t * data,NewStringType type,int length)6734 MaybeLocal<String> String::NewFromTwoByte(Isolate* isolate,
6735 const uint16_t* data,
6736 NewStringType type, int length) {
6737 NEW_STRING(isolate, String, NewFromTwoByte, uint16_t, data, type, length);
6738 return result;
6739 }
6740
Concat(Isolate * v8_isolate,Local<String> left,Local<String> right)6741 Local<String> v8::String::Concat(Isolate* v8_isolate, Local<String> left,
6742 Local<String> right) {
6743 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
6744 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
6745 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
6746 LOG_API(isolate, String, Concat);
6747 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
6748 // If we are steering towards a range error, do not wait for the error to be
6749 // thrown, and return the null handle instead.
6750 if (left_string->length() + right_string->length() > i::String::kMaxLength) {
6751 return Local<String>();
6752 }
6753 i::Handle<i::String> result = isolate->factory()
6754 ->NewConsString(left_string, right_string)
6755 .ToHandleChecked();
6756 return Utils::ToLocal(result);
6757 }
6758
NewExternalTwoByte(Isolate * isolate,v8::String::ExternalStringResource * resource)6759 MaybeLocal<String> v8::String::NewExternalTwoByte(
6760 Isolate* isolate, v8::String::ExternalStringResource* resource) {
6761 CHECK(resource && resource->data());
6762 // TODO(dcarney): throw a context free exception.
6763 if (resource->length() > static_cast<size_t>(i::String::kMaxLength)) {
6764 return MaybeLocal<String>();
6765 }
6766 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6767 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
6768 LOG_API(i_isolate, String, NewExternalTwoByte);
6769 if (resource->length() > 0) {
6770 i::Handle<i::String> string = i_isolate->factory()
6771 ->NewExternalStringFromTwoByte(resource)
6772 .ToHandleChecked();
6773 return Utils::ToLocal(string);
6774 } else {
6775 // The resource isn't going to be used, free it immediately.
6776 resource->Dispose();
6777 return Utils::ToLocal(i_isolate->factory()->empty_string());
6778 }
6779 }
6780
NewExternalOneByte(Isolate * isolate,v8::String::ExternalOneByteStringResource * resource)6781 MaybeLocal<String> v8::String::NewExternalOneByte(
6782 Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
6783 CHECK_NOT_NULL(resource);
6784 // TODO(dcarney): throw a context free exception.
6785 if (resource->length() > static_cast<size_t>(i::String::kMaxLength)) {
6786 return MaybeLocal<String>();
6787 }
6788 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6789 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
6790 LOG_API(i_isolate, String, NewExternalOneByte);
6791 if (resource->length() == 0) {
6792 // The resource isn't going to be used, free it immediately.
6793 resource->Dispose();
6794 return Utils::ToLocal(i_isolate->factory()->empty_string());
6795 }
6796 CHECK_NOT_NULL(resource->data());
6797 i::Handle<i::String> string = i_isolate->factory()
6798 ->NewExternalStringFromOneByte(resource)
6799 .ToHandleChecked();
6800 return Utils::ToLocal(string);
6801 }
6802
MakeExternal(v8::String::ExternalStringResource * resource)6803 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
6804 i::DisallowGarbageCollection no_gc;
6805
6806 i::String obj = *Utils::OpenHandle(this);
6807
6808 if (obj.IsThinString()) {
6809 obj = i::ThinString::cast(obj).actual();
6810 }
6811
6812 if (!obj.SupportsExternalization()) {
6813 return false;
6814 }
6815
6816 // It is safe to call GetIsolateFromWritableHeapObject because
6817 // SupportsExternalization already checked that the object is writable.
6818 i::Isolate* isolate = i::GetIsolateFromWritableObject(obj);
6819 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
6820
6821 CHECK(resource && resource->data());
6822
6823 bool result = obj.MakeExternal(resource);
6824 DCHECK(result);
6825 DCHECK(obj.IsExternalString());
6826 return result;
6827 }
6828
MakeExternal(v8::String::ExternalOneByteStringResource * resource)6829 bool v8::String::MakeExternal(
6830 v8::String::ExternalOneByteStringResource* resource) {
6831 i::DisallowGarbageCollection no_gc;
6832
6833 i::String obj = *Utils::OpenHandle(this);
6834
6835 if (obj.IsThinString()) {
6836 obj = i::ThinString::cast(obj).actual();
6837 }
6838
6839 if (!obj.SupportsExternalization()) {
6840 return false;
6841 }
6842
6843 // It is safe to call GetIsolateFromWritableHeapObject because
6844 // SupportsExternalization already checked that the object is writable.
6845 i::Isolate* isolate = i::GetIsolateFromWritableObject(obj);
6846 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
6847
6848 CHECK(resource && resource->data());
6849
6850 bool result = obj.MakeExternal(resource);
6851 DCHECK_IMPLIES(result, obj.IsExternalString());
6852 return result;
6853 }
6854
CanMakeExternal() const6855 bool v8::String::CanMakeExternal() const {
6856 i::String obj = *Utils::OpenHandle(this);
6857
6858 if (obj.IsThinString()) {
6859 obj = i::ThinString::cast(obj).actual();
6860 }
6861
6862 if (!obj.SupportsExternalization()) {
6863 return false;
6864 }
6865
6866 // Only old space strings should be externalized.
6867 return !i::Heap::InYoungGeneration(obj);
6868 }
6869
StringEquals(Local<String> that) const6870 bool v8::String::StringEquals(Local<String> that) const {
6871 auto self = Utils::OpenHandle(this);
6872 auto other = Utils::OpenHandle(*that);
6873 return self->Equals(*other);
6874 }
6875
GetIsolate()6876 Isolate* v8::Object::GetIsolate() {
6877 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
6878 return reinterpret_cast<Isolate*>(i_isolate);
6879 }
6880
New(Isolate * isolate)6881 Local<v8::Object> v8::Object::New(Isolate* isolate) {
6882 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6883 LOG_API(i_isolate, Object, New);
6884 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
6885 i::Handle<i::JSObject> obj =
6886 i_isolate->factory()->NewJSObject(i_isolate->object_function());
6887 return Utils::ToLocal(obj);
6888 }
6889
6890 namespace {
6891
6892 // TODO(v8:7569): This is a workaround for the Handle vs MaybeHandle difference
6893 // in the return types of the different Add functions:
6894 // OrderedNameDictionary::Add returns MaybeHandle, NameDictionary::Add returns
6895 // Handle.
6896 template <typename T>
ToHandle(i::Handle<T> h)6897 i::Handle<T> ToHandle(i::Handle<T> h) {
6898 return h;
6899 }
6900 template <typename T>
ToHandle(i::MaybeHandle<T> h)6901 i::Handle<T> ToHandle(i::MaybeHandle<T> h) {
6902 return h.ToHandleChecked();
6903 }
6904
6905 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)6906 void AddPropertiesAndElementsToObject(i::Isolate* i_isolate,
6907 i::Handle<Dictionary>& properties,
6908 i::Handle<i::FixedArrayBase>& elements,
6909 Local<Name>* names, Local<Value>* values,
6910 size_t length) {
6911 for (size_t i = 0; i < length; ++i) {
6912 i::Handle<i::Name> name = Utils::OpenHandle(*names[i]);
6913 i::Handle<i::Object> value = Utils::OpenHandle(*values[i]);
6914
6915 // See if the {name} is a valid array index, in which case we need to
6916 // add the {name}/{value} pair to the {elements}, otherwise they end
6917 // up in the {properties} backing store.
6918 uint32_t index;
6919 if (name->AsArrayIndex(&index)) {
6920 // If this is the first element, allocate a proper
6921 // dictionary elements backing store for {elements}.
6922 if (!elements->IsNumberDictionary()) {
6923 elements =
6924 i::NumberDictionary::New(i_isolate, static_cast<int>(length));
6925 }
6926 elements = i::NumberDictionary::Set(
6927 i_isolate, i::Handle<i::NumberDictionary>::cast(elements), index,
6928 value);
6929 } else {
6930 // Internalize the {name} first.
6931 name = i_isolate->factory()->InternalizeName(name);
6932 i::InternalIndex const entry = properties->FindEntry(i_isolate, name);
6933 if (entry.is_not_found()) {
6934 // Add the {name}/{value} pair as a new entry.
6935 properties = ToHandle(Dictionary::Add(
6936 i_isolate, properties, name, value, i::PropertyDetails::Empty()));
6937 } else {
6938 // Overwrite the {entry} with the {value}.
6939 properties->ValueAtPut(entry, *value);
6940 }
6941 }
6942 }
6943 }
6944
6945 } // namespace
6946
New(Isolate * isolate,Local<Value> prototype_or_null,Local<Name> * names,Local<Value> * values,size_t length)6947 Local<v8::Object> v8::Object::New(Isolate* isolate,
6948 Local<Value> prototype_or_null,
6949 Local<Name>* names, Local<Value>* values,
6950 size_t length) {
6951 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6952 i::Handle<i::Object> proto = Utils::OpenHandle(*prototype_or_null);
6953 if (!Utils::ApiCheck(proto->IsNull() || proto->IsJSReceiver(),
6954 "v8::Object::New", "prototype must be null or object")) {
6955 return Local<v8::Object>();
6956 }
6957 LOG_API(i_isolate, Object, New);
6958 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
6959
6960 i::Handle<i::FixedArrayBase> elements =
6961 i_isolate->factory()->empty_fixed_array();
6962
6963 // We assume that this API is mostly used to create objects with named
6964 // properties, and so we default to creating a properties backing store
6965 // large enough to hold all of them, while we start with no elements
6966 // (see http://bit.ly/v8-fast-object-create-cpp for the motivation).
6967 if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
6968 i::Handle<i::SwissNameDictionary> properties =
6969 i_isolate->factory()->NewSwissNameDictionary(static_cast<int>(length));
6970 AddPropertiesAndElementsToObject(i_isolate, properties, elements, names,
6971 values, length);
6972 i::Handle<i::JSObject> obj =
6973 i_isolate->factory()->NewSlowJSObjectWithPropertiesAndElements(
6974 i::Handle<i::HeapObject>::cast(proto), properties, elements);
6975 return Utils::ToLocal(obj);
6976 } else {
6977 i::Handle<i::NameDictionary> properties =
6978 i::NameDictionary::New(i_isolate, static_cast<int>(length));
6979 AddPropertiesAndElementsToObject(i_isolate, properties, elements, names,
6980 values, length);
6981 i::Handle<i::JSObject> obj =
6982 i_isolate->factory()->NewSlowJSObjectWithPropertiesAndElements(
6983 i::Handle<i::HeapObject>::cast(proto), properties, elements);
6984 return Utils::ToLocal(obj);
6985 }
6986 }
6987
New(Isolate * isolate,double value)6988 Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) {
6989 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6990 LOG_API(i_isolate, NumberObject, New);
6991 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
6992 i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value);
6993 i::Handle<i::Object> obj =
6994 i::Object::ToObject(i_isolate, number).ToHandleChecked();
6995 return Utils::ToLocal(obj);
6996 }
6997
ValueOf() const6998 double v8::NumberObject::ValueOf() const {
6999 i::Handle<i::Object> obj = Utils::OpenHandle(this);
7000 i::Handle<i::JSPrimitiveWrapper> js_primitive_wrapper =
7001 i::Handle<i::JSPrimitiveWrapper>::cast(obj);
7002 i::Isolate* isolate = js_primitive_wrapper->GetIsolate();
7003 LOG_API(isolate, NumberObject, NumberValue);
7004 return js_primitive_wrapper->value().Number();
7005 }
7006
New(Isolate * isolate,int64_t value)7007 Local<v8::Value> v8::BigIntObject::New(Isolate* isolate, int64_t value) {
7008 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7009 LOG_API(i_isolate, BigIntObject, New);
7010 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7011 i::Handle<i::Object> bigint = i::BigInt::FromInt64(i_isolate, value);
7012 i::Handle<i::Object> obj =
7013 i::Object::ToObject(i_isolate, bigint).ToHandleChecked();
7014 return Utils::ToLocal(obj);
7015 }
7016
ValueOf() const7017 Local<v8::BigInt> v8::BigIntObject::ValueOf() const {
7018 i::Handle<i::Object> obj = Utils::OpenHandle(this);
7019 i::Handle<i::JSPrimitiveWrapper> js_primitive_wrapper =
7020 i::Handle<i::JSPrimitiveWrapper>::cast(obj);
7021 i::Isolate* isolate = js_primitive_wrapper->GetIsolate();
7022 LOG_API(isolate, BigIntObject, BigIntValue);
7023 return Utils::ToLocal(i::Handle<i::BigInt>(
7024 i::BigInt::cast(js_primitive_wrapper->value()), isolate));
7025 }
7026
New(Isolate * isolate,bool value)7027 Local<v8::Value> v8::BooleanObject::New(Isolate* isolate, bool value) {
7028 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7029 LOG_API(i_isolate, BooleanObject, New);
7030 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7031 i::Handle<i::Object> boolean(value
7032 ? i::ReadOnlyRoots(i_isolate).true_value()
7033 : i::ReadOnlyRoots(i_isolate).false_value(),
7034 i_isolate);
7035 i::Handle<i::Object> obj =
7036 i::Object::ToObject(i_isolate, boolean).ToHandleChecked();
7037 return Utils::ToLocal(obj);
7038 }
7039
ValueOf() const7040 bool v8::BooleanObject::ValueOf() const {
7041 i::Object obj = *Utils::OpenHandle(this);
7042 i::JSPrimitiveWrapper js_primitive_wrapper = i::JSPrimitiveWrapper::cast(obj);
7043 i::Isolate* isolate = js_primitive_wrapper.GetIsolate();
7044 LOG_API(isolate, BooleanObject, BooleanValue);
7045 return js_primitive_wrapper.value().IsTrue(isolate);
7046 }
7047
New(Isolate * v8_isolate,Local<String> value)7048 Local<v8::Value> v8::StringObject::New(Isolate* v8_isolate,
7049 Local<String> value) {
7050 i::Handle<i::String> string = Utils::OpenHandle(*value);
7051 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
7052 LOG_API(isolate, StringObject, New);
7053 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7054 i::Handle<i::Object> obj =
7055 i::Object::ToObject(isolate, string).ToHandleChecked();
7056 return Utils::ToLocal(obj);
7057 }
7058
ValueOf() const7059 Local<v8::String> v8::StringObject::ValueOf() const {
7060 i::Handle<i::Object> obj = Utils::OpenHandle(this);
7061 i::Handle<i::JSPrimitiveWrapper> js_primitive_wrapper =
7062 i::Handle<i::JSPrimitiveWrapper>::cast(obj);
7063 i::Isolate* isolate = js_primitive_wrapper->GetIsolate();
7064 LOG_API(isolate, StringObject, StringValue);
7065 return Utils::ToLocal(i::Handle<i::String>(
7066 i::String::cast(js_primitive_wrapper->value()), isolate));
7067 }
7068
New(Isolate * isolate,Local<Symbol> value)7069 Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Local<Symbol> value) {
7070 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7071 LOG_API(i_isolate, SymbolObject, New);
7072 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7073 i::Handle<i::Object> obj =
7074 i::Object::ToObject(i_isolate, Utils::OpenHandle(*value))
7075 .ToHandleChecked();
7076 return Utils::ToLocal(obj);
7077 }
7078
ValueOf() const7079 Local<v8::Symbol> v8::SymbolObject::ValueOf() const {
7080 i::Handle<i::Object> obj = Utils::OpenHandle(this);
7081 i::Handle<i::JSPrimitiveWrapper> js_primitive_wrapper =
7082 i::Handle<i::JSPrimitiveWrapper>::cast(obj);
7083 i::Isolate* isolate = js_primitive_wrapper->GetIsolate();
7084 LOG_API(isolate, SymbolObject, SymbolValue);
7085 return Utils::ToLocal(i::Handle<i::Symbol>(
7086 i::Symbol::cast(js_primitive_wrapper->value()), isolate));
7087 }
7088
New(Local<Context> context,double time)7089 MaybeLocal<v8::Value> v8::Date::New(Local<Context> context, double time) {
7090 if (std::isnan(time)) {
7091 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
7092 time = std::numeric_limits<double>::quiet_NaN();
7093 }
7094 PREPARE_FOR_EXECUTION(context, Date, New, Value);
7095 Local<Value> result;
7096 has_pending_exception = !ToLocal<Value>(
7097 i::JSDate::New(isolate->date_function(), isolate->date_function(), time),
7098 &result);
7099 RETURN_ON_FAILED_EXECUTION(Value);
7100 RETURN_ESCAPED(result);
7101 }
7102
ValueOf() const7103 double v8::Date::ValueOf() const {
7104 i::Handle<i::Object> obj = Utils::OpenHandle(this);
7105 i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj);
7106 i::Isolate* isolate = jsdate->GetIsolate();
7107 LOG_API(isolate, Date, NumberValue);
7108 return jsdate->value().Number();
7109 }
7110
7111 // Assert that the static TimeZoneDetection cast in
7112 // DateTimeConfigurationChangeNotification is valid.
7113 #define TIME_ZONE_DETECTION_ASSERT_EQ(value) \
7114 STATIC_ASSERT( \
7115 static_cast<int>(v8::Isolate::TimeZoneDetection::value) == \
7116 static_cast<int>(base::TimezoneCache::TimeZoneDetection::value));
7117 TIME_ZONE_DETECTION_ASSERT_EQ(kSkip)
TIME_ZONE_DETECTION_ASSERT_EQ(kRedetect)7118 TIME_ZONE_DETECTION_ASSERT_EQ(kRedetect)
7119 #undef TIME_ZONE_DETECTION_ASSERT_EQ
7120
7121 MaybeLocal<v8::RegExp> v8::RegExp::New(Local<Context> context,
7122 Local<String> pattern, Flags flags) {
7123 PREPARE_FOR_EXECUTION(context, RegExp, New, RegExp);
7124 Local<v8::RegExp> result;
7125 has_pending_exception =
7126 !ToLocal<RegExp>(i::JSRegExp::New(isolate, Utils::OpenHandle(*pattern),
7127 static_cast<i::JSRegExp::Flags>(flags)),
7128 &result);
7129 RETURN_ON_FAILED_EXECUTION(RegExp);
7130 RETURN_ESCAPED(result);
7131 }
7132
NewWithBacktrackLimit(Local<Context> context,Local<String> pattern,Flags flags,uint32_t backtrack_limit)7133 MaybeLocal<v8::RegExp> v8::RegExp::NewWithBacktrackLimit(
7134 Local<Context> context, Local<String> pattern, Flags flags,
7135 uint32_t backtrack_limit) {
7136 Utils::ApiCheck(i::Smi::IsValid(backtrack_limit),
7137 "v8::RegExp::NewWithBacktrackLimit",
7138 "backtrack_limit is too large or too small.");
7139 Utils::ApiCheck(backtrack_limit != i::JSRegExp::kNoBacktrackLimit,
7140 "v8::RegExp::NewWithBacktrackLimit",
7141 "Must set backtrack_limit");
7142 PREPARE_FOR_EXECUTION(context, RegExp, New, RegExp);
7143 Local<v8::RegExp> result;
7144 has_pending_exception = !ToLocal<RegExp>(
7145 i::JSRegExp::New(isolate, Utils::OpenHandle(*pattern),
7146 static_cast<i::JSRegExp::Flags>(flags), backtrack_limit),
7147 &result);
7148 RETURN_ON_FAILED_EXECUTION(RegExp);
7149 RETURN_ESCAPED(result);
7150 }
7151
GetSource() const7152 Local<v8::String> v8::RegExp::GetSource() const {
7153 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
7154 return Utils::ToLocal(
7155 i::Handle<i::String>(obj->EscapedPattern(), obj->GetIsolate()));
7156 }
7157
7158 // Assert that the static flags cast in GetFlags is valid.
7159 #define REGEXP_FLAG_ASSERT_EQ(flag) \
7160 STATIC_ASSERT(static_cast<int>(v8::RegExp::flag) == \
7161 static_cast<int>(i::JSRegExp::flag))
7162 REGEXP_FLAG_ASSERT_EQ(kNone);
7163 REGEXP_FLAG_ASSERT_EQ(kGlobal);
7164 REGEXP_FLAG_ASSERT_EQ(kIgnoreCase);
7165 REGEXP_FLAG_ASSERT_EQ(kMultiline);
7166 REGEXP_FLAG_ASSERT_EQ(kSticky);
7167 REGEXP_FLAG_ASSERT_EQ(kUnicode);
7168 REGEXP_FLAG_ASSERT_EQ(kHasIndices);
7169 REGEXP_FLAG_ASSERT_EQ(kLinear);
7170 #undef REGEXP_FLAG_ASSERT_EQ
7171
GetFlags() const7172 v8::RegExp::Flags v8::RegExp::GetFlags() const {
7173 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
7174 return RegExp::Flags(static_cast<int>(obj->flags()));
7175 }
7176
Exec(Local<Context> context,Local<v8::String> subject)7177 MaybeLocal<v8::Object> v8::RegExp::Exec(Local<Context> context,
7178 Local<v8::String> subject) {
7179 PREPARE_FOR_EXECUTION(context, RegExp, Exec, Object);
7180
7181 i::Handle<i::JSRegExp> regexp = Utils::OpenHandle(this);
7182 i::Handle<i::String> subject_string = Utils::OpenHandle(*subject);
7183
7184 // TODO(jgruber): RegExpUtils::RegExpExec was not written with efficiency in
7185 // mind. It fetches the 'exec' property and then calls it through JSEntry.
7186 // Unfortunately, this is currently the only full implementation of
7187 // RegExp.prototype.exec available in C++.
7188 Local<v8::Object> result;
7189 has_pending_exception = !ToLocal<Object>(
7190 i::RegExpUtils::RegExpExec(isolate, regexp, subject_string,
7191 isolate->factory()->undefined_value()),
7192 &result);
7193
7194 RETURN_ON_FAILED_EXECUTION(Object);
7195 RETURN_ESCAPED(result);
7196 }
7197
New(Isolate * isolate,int length)7198 Local<v8::Array> v8::Array::New(Isolate* isolate, int length) {
7199 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7200 LOG_API(i_isolate, Array, New);
7201 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7202 int real_length = length > 0 ? length : 0;
7203 i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length);
7204 i::Handle<i::Object> length_obj =
7205 i_isolate->factory()->NewNumberFromInt(real_length);
7206 obj->set_length(*length_obj);
7207 return Utils::ToLocal(obj);
7208 }
7209
New(Isolate * isolate,Local<Value> * elements,size_t length)7210 Local<v8::Array> v8::Array::New(Isolate* isolate, Local<Value>* elements,
7211 size_t length) {
7212 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7213 i::Factory* factory = i_isolate->factory();
7214 LOG_API(i_isolate, Array, New);
7215 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7216 int len = static_cast<int>(length);
7217
7218 i::Handle<i::FixedArray> result = factory->NewFixedArray(len);
7219 for (int i = 0; i < len; i++) {
7220 i::Handle<i::Object> element = Utils::OpenHandle(*elements[i]);
7221 result->set(i, *element);
7222 }
7223
7224 return Utils::ToLocal(
7225 factory->NewJSArrayWithElements(result, i::PACKED_ELEMENTS, len));
7226 }
7227
Length() const7228 uint32_t v8::Array::Length() const {
7229 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
7230 i::Object length = obj->length();
7231 if (length.IsSmi()) {
7232 return i::Smi::ToInt(length);
7233 } else {
7234 return static_cast<uint32_t>(length.Number());
7235 }
7236 }
7237
New(Isolate * isolate)7238 Local<v8::Map> v8::Map::New(Isolate* isolate) {
7239 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7240 LOG_API(i_isolate, Map, New);
7241 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7242 i::Handle<i::JSMap> obj = i_isolate->factory()->NewJSMap();
7243 return Utils::ToLocal(obj);
7244 }
7245
Size() const7246 size_t v8::Map::Size() const {
7247 i::Handle<i::JSMap> obj = Utils::OpenHandle(this);
7248 return i::OrderedHashMap::cast(obj->table()).NumberOfElements();
7249 }
7250
Clear()7251 void Map::Clear() {
7252 auto self = Utils::OpenHandle(this);
7253 i::Isolate* isolate = self->GetIsolate();
7254 LOG_API(isolate, Map, Clear);
7255 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7256 i::JSMap::Clear(isolate, self);
7257 }
7258
Get(Local<Context> context,Local<Value> key)7259 MaybeLocal<Value> Map::Get(Local<Context> context, Local<Value> key) {
7260 PREPARE_FOR_EXECUTION(context, Map, Get, Value);
7261 auto self = Utils::OpenHandle(this);
7262 Local<Value> result;
7263 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7264 has_pending_exception =
7265 !ToLocal<Value>(i::Execution::CallBuiltin(isolate, isolate->map_get(),
7266 self, arraysize(argv), argv),
7267 &result);
7268 RETURN_ON_FAILED_EXECUTION(Value);
7269 RETURN_ESCAPED(result);
7270 }
7271
Set(Local<Context> context,Local<Value> key,Local<Value> value)7272 MaybeLocal<Map> Map::Set(Local<Context> context, Local<Value> key,
7273 Local<Value> value) {
7274 PREPARE_FOR_EXECUTION(context, Map, Set, Map);
7275 auto self = Utils::OpenHandle(this);
7276 i::Handle<i::Object> result;
7277 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key),
7278 Utils::OpenHandle(*value)};
7279 has_pending_exception =
7280 !i::Execution::CallBuiltin(isolate, isolate->map_set(), self,
7281 arraysize(argv), argv)
7282 .ToHandle(&result);
7283 RETURN_ON_FAILED_EXECUTION(Map);
7284 RETURN_ESCAPED(Local<Map>::Cast(Utils::ToLocal(result)));
7285 }
7286
Has(Local<Context> context,Local<Value> key)7287 Maybe<bool> Map::Has(Local<Context> context, Local<Value> key) {
7288 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7289 ENTER_V8(isolate, context, Map, Has, Nothing<bool>(), i::HandleScope);
7290 auto self = Utils::OpenHandle(this);
7291 i::Handle<i::Object> result;
7292 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7293 has_pending_exception =
7294 !i::Execution::CallBuiltin(isolate, isolate->map_has(), self,
7295 arraysize(argv), argv)
7296 .ToHandle(&result);
7297 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7298 return Just(result->IsTrue(isolate));
7299 }
7300
Delete(Local<Context> context,Local<Value> key)7301 Maybe<bool> Map::Delete(Local<Context> context, Local<Value> key) {
7302 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7303 ENTER_V8(isolate, context, Map, Delete, Nothing<bool>(), i::HandleScope);
7304 auto self = Utils::OpenHandle(this);
7305 i::Handle<i::Object> result;
7306 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7307 has_pending_exception =
7308 !i::Execution::CallBuiltin(isolate, isolate->map_delete(), self,
7309 arraysize(argv), argv)
7310 .ToHandle(&result);
7311 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7312 return Just(result->IsTrue(isolate));
7313 }
7314
7315 namespace {
7316
7317 enum class MapAsArrayKind {
7318 kEntries = i::JS_MAP_KEY_VALUE_ITERATOR_TYPE,
7319 kKeys = i::JS_MAP_KEY_ITERATOR_TYPE,
7320 kValues = i::JS_MAP_VALUE_ITERATOR_TYPE
7321 };
7322
7323 enum class SetAsArrayKind {
7324 kEntries = i::JS_SET_KEY_VALUE_ITERATOR_TYPE,
7325 kValues = i::JS_SET_VALUE_ITERATOR_TYPE
7326 };
7327
MapAsArray(i::Isolate * isolate,i::Object table_obj,int offset,MapAsArrayKind kind)7328 i::Handle<i::JSArray> MapAsArray(i::Isolate* isolate, i::Object table_obj,
7329 int offset, MapAsArrayKind kind) {
7330 i::Factory* factory = isolate->factory();
7331 i::Handle<i::OrderedHashMap> table(i::OrderedHashMap::cast(table_obj),
7332 isolate);
7333 const bool collect_keys =
7334 kind == MapAsArrayKind::kEntries || kind == MapAsArrayKind::kKeys;
7335 const bool collect_values =
7336 kind == MapAsArrayKind::kEntries || kind == MapAsArrayKind::kValues;
7337 int capacity = table->UsedCapacity();
7338 int max_length =
7339 (capacity - offset) * ((collect_keys && collect_values) ? 2 : 1);
7340 i::Handle<i::FixedArray> result = factory->NewFixedArray(max_length);
7341 int result_index = 0;
7342 {
7343 i::DisallowGarbageCollection no_gc;
7344 i::Oddball the_hole = i::ReadOnlyRoots(isolate).the_hole_value();
7345 for (int i = offset; i < capacity; ++i) {
7346 i::InternalIndex entry(i);
7347 i::Object key = table->KeyAt(entry);
7348 if (key == the_hole) continue;
7349 if (collect_keys) result->set(result_index++, key);
7350 if (collect_values) result->set(result_index++, table->ValueAt(entry));
7351 }
7352 }
7353 DCHECK_GE(max_length, result_index);
7354 if (result_index == 0) return factory->NewJSArray(0);
7355 result->Shrink(isolate, result_index);
7356 return factory->NewJSArrayWithElements(result, i::PACKED_ELEMENTS,
7357 result_index);
7358 }
7359
7360 } // namespace
7361
AsArray() const7362 Local<Array> Map::AsArray() const {
7363 i::Handle<i::JSMap> obj = Utils::OpenHandle(this);
7364 i::Isolate* isolate = obj->GetIsolate();
7365 LOG_API(isolate, Map, AsArray);
7366 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7367 return Utils::ToLocal(
7368 MapAsArray(isolate, obj->table(), 0, MapAsArrayKind::kEntries));
7369 }
7370
New(Isolate * isolate)7371 Local<v8::Set> v8::Set::New(Isolate* isolate) {
7372 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7373 LOG_API(i_isolate, Set, New);
7374 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7375 i::Handle<i::JSSet> obj = i_isolate->factory()->NewJSSet();
7376 return Utils::ToLocal(obj);
7377 }
7378
Size() const7379 size_t v8::Set::Size() const {
7380 i::Handle<i::JSSet> obj = Utils::OpenHandle(this);
7381 return i::OrderedHashSet::cast(obj->table()).NumberOfElements();
7382 }
7383
Clear()7384 void Set::Clear() {
7385 auto self = Utils::OpenHandle(this);
7386 i::Isolate* isolate = self->GetIsolate();
7387 LOG_API(isolate, Set, Clear);
7388 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7389 i::JSSet::Clear(isolate, self);
7390 }
7391
Add(Local<Context> context,Local<Value> key)7392 MaybeLocal<Set> Set::Add(Local<Context> context, Local<Value> key) {
7393 PREPARE_FOR_EXECUTION(context, Set, Add, Set);
7394 auto self = Utils::OpenHandle(this);
7395 i::Handle<i::Object> result;
7396 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7397 has_pending_exception =
7398 !i::Execution::CallBuiltin(isolate, isolate->set_add(), self,
7399 arraysize(argv), argv)
7400 .ToHandle(&result);
7401 RETURN_ON_FAILED_EXECUTION(Set);
7402 RETURN_ESCAPED(Local<Set>::Cast(Utils::ToLocal(result)));
7403 }
7404
Has(Local<Context> context,Local<Value> key)7405 Maybe<bool> Set::Has(Local<Context> context, Local<Value> key) {
7406 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7407 ENTER_V8(isolate, context, Set, Has, Nothing<bool>(), i::HandleScope);
7408 auto self = Utils::OpenHandle(this);
7409 i::Handle<i::Object> result;
7410 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7411 has_pending_exception =
7412 !i::Execution::CallBuiltin(isolate, isolate->set_has(), self,
7413 arraysize(argv), argv)
7414 .ToHandle(&result);
7415 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7416 return Just(result->IsTrue(isolate));
7417 }
7418
Delete(Local<Context> context,Local<Value> key)7419 Maybe<bool> Set::Delete(Local<Context> context, Local<Value> key) {
7420 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7421 ENTER_V8(isolate, context, Set, Delete, Nothing<bool>(), i::HandleScope);
7422 auto self = Utils::OpenHandle(this);
7423 i::Handle<i::Object> result;
7424 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7425 has_pending_exception =
7426 !i::Execution::CallBuiltin(isolate, isolate->set_delete(), self,
7427 arraysize(argv), argv)
7428 .ToHandle(&result);
7429 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7430 return Just(result->IsTrue(isolate));
7431 }
7432
7433 namespace {
SetAsArray(i::Isolate * isolate,i::Object table_obj,int offset,SetAsArrayKind kind)7434 i::Handle<i::JSArray> SetAsArray(i::Isolate* isolate, i::Object table_obj,
7435 int offset, SetAsArrayKind kind) {
7436 i::Factory* factory = isolate->factory();
7437 i::Handle<i::OrderedHashSet> table(i::OrderedHashSet::cast(table_obj),
7438 isolate);
7439 // Elements skipped by |offset| may already be deleted.
7440 int capacity = table->UsedCapacity();
7441 const bool collect_key_values = kind == SetAsArrayKind::kEntries;
7442 int max_length = (capacity - offset) * (collect_key_values ? 2 : 1);
7443 if (max_length == 0) return factory->NewJSArray(0);
7444 i::Handle<i::FixedArray> result = factory->NewFixedArray(max_length);
7445 int result_index = 0;
7446 {
7447 i::DisallowGarbageCollection no_gc;
7448 i::Oddball the_hole = i::ReadOnlyRoots(isolate).the_hole_value();
7449 for (int i = offset; i < capacity; ++i) {
7450 i::InternalIndex entry(i);
7451 i::Object key = table->KeyAt(entry);
7452 if (key == the_hole) continue;
7453 result->set(result_index++, key);
7454 if (collect_key_values) result->set(result_index++, key);
7455 }
7456 }
7457 DCHECK_GE(max_length, result_index);
7458 if (result_index == 0) return factory->NewJSArray(0);
7459 result->Shrink(isolate, result_index);
7460 return factory->NewJSArrayWithElements(result, i::PACKED_ELEMENTS,
7461 result_index);
7462 }
7463 } // namespace
7464
AsArray() const7465 Local<Array> Set::AsArray() const {
7466 i::Handle<i::JSSet> obj = Utils::OpenHandle(this);
7467 i::Isolate* isolate = obj->GetIsolate();
7468 LOG_API(isolate, Set, AsArray);
7469 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7470 return Utils::ToLocal(
7471 SetAsArray(isolate, obj->table(), 0, SetAsArrayKind::kValues));
7472 }
7473
New(Local<Context> context)7474 MaybeLocal<Promise::Resolver> Promise::Resolver::New(Local<Context> context) {
7475 PREPARE_FOR_EXECUTION(context, Promise_Resolver, New, Resolver);
7476 Local<Promise::Resolver> result;
7477 has_pending_exception =
7478 !ToLocal<Promise::Resolver>(isolate->factory()->NewJSPromise(), &result);
7479 RETURN_ON_FAILED_EXECUTION(Promise::Resolver);
7480 RETURN_ESCAPED(result);
7481 }
7482
GetPromise()7483 Local<Promise> Promise::Resolver::GetPromise() {
7484 i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
7485 return Local<Promise>::Cast(Utils::ToLocal(promise));
7486 }
7487
Resolve(Local<Context> context,Local<Value> value)7488 Maybe<bool> Promise::Resolver::Resolve(Local<Context> context,
7489 Local<Value> value) {
7490 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7491 ENTER_V8(isolate, context, Promise_Resolver, Resolve, Nothing<bool>(),
7492 i::HandleScope);
7493 auto self = Utils::OpenHandle(this);
7494 auto promise = i::Handle<i::JSPromise>::cast(self);
7495
7496 if (promise->status() != Promise::kPending) {
7497 return Just(true);
7498 }
7499
7500 has_pending_exception =
7501 i::JSPromise::Resolve(promise, Utils::OpenHandle(*value)).is_null();
7502 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7503 return Just(true);
7504 }
7505
Reject(Local<Context> context,Local<Value> value)7506 Maybe<bool> Promise::Resolver::Reject(Local<Context> context,
7507 Local<Value> value) {
7508 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
7509 ENTER_V8(isolate, context, Promise_Resolver, Reject, Nothing<bool>(),
7510 i::HandleScope);
7511 auto self = Utils::OpenHandle(this);
7512 auto promise = i::Handle<i::JSPromise>::cast(self);
7513
7514 if (promise->status() != Promise::kPending) {
7515 return Just(true);
7516 }
7517
7518 has_pending_exception =
7519 i::JSPromise::Reject(promise, Utils::OpenHandle(*value)).is_null();
7520 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7521 return Just(true);
7522 }
7523
Catch(Local<Context> context,Local<Function> handler)7524 MaybeLocal<Promise> Promise::Catch(Local<Context> context,
7525 Local<Function> handler) {
7526 PREPARE_FOR_EXECUTION(context, Promise, Catch, Promise);
7527 auto self = Utils::OpenHandle(this);
7528 i::Handle<i::Object> argv[] = {isolate->factory()->undefined_value(),
7529 Utils::OpenHandle(*handler)};
7530 i::Handle<i::Object> result;
7531 // Do not call the built-in Promise.prototype.catch!
7532 // v8::Promise should not call out to a monkeypatched Promise.prototype.then
7533 // as the implementation of Promise.prototype.catch does.
7534 has_pending_exception =
7535 !i::Execution::CallBuiltin(isolate, isolate->promise_then(), self,
7536 arraysize(argv), argv)
7537 .ToHandle(&result);
7538 RETURN_ON_FAILED_EXECUTION(Promise);
7539 RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
7540 }
7541
Then(Local<Context> context,Local<Function> handler)7542 MaybeLocal<Promise> Promise::Then(Local<Context> context,
7543 Local<Function> handler) {
7544 PREPARE_FOR_EXECUTION(context, Promise, Then, Promise);
7545 auto self = Utils::OpenHandle(this);
7546 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*handler)};
7547 i::Handle<i::Object> result;
7548 has_pending_exception =
7549 !i::Execution::CallBuiltin(isolate, isolate->promise_then(), self,
7550 arraysize(argv), argv)
7551 .ToHandle(&result);
7552 RETURN_ON_FAILED_EXECUTION(Promise);
7553 RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
7554 }
7555
Then(Local<Context> context,Local<Function> on_fulfilled,Local<Function> on_rejected)7556 MaybeLocal<Promise> Promise::Then(Local<Context> context,
7557 Local<Function> on_fulfilled,
7558 Local<Function> on_rejected) {
7559 PREPARE_FOR_EXECUTION(context, Promise, Then, Promise);
7560 auto self = Utils::OpenHandle(this);
7561 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*on_fulfilled),
7562 Utils::OpenHandle(*on_rejected)};
7563 i::Handle<i::Object> result;
7564 has_pending_exception =
7565 !i::Execution::CallBuiltin(isolate, isolate->promise_then(), self,
7566 arraysize(argv), argv)
7567 .ToHandle(&result);
7568 RETURN_ON_FAILED_EXECUTION(Promise);
7569 RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
7570 }
7571
HasHandler() const7572 bool Promise::HasHandler() const {
7573 i::JSReceiver promise = *Utils::OpenHandle(this);
7574 i::Isolate* isolate = promise.GetIsolate();
7575 LOG_API(isolate, Promise, HasRejectHandler);
7576 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7577 if (!promise.IsJSPromise()) return false;
7578 return i::JSPromise::cast(promise).has_handler();
7579 }
7580
Result()7581 Local<Value> Promise::Result() {
7582 i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
7583 i::Isolate* isolate = promise->GetIsolate();
7584 LOG_API(isolate, Promise, Result);
7585 i::Handle<i::JSPromise> js_promise = i::Handle<i::JSPromise>::cast(promise);
7586 Utils::ApiCheck(js_promise->status() != kPending, "v8_Promise_Result",
7587 "Promise is still pending");
7588 i::Handle<i::Object> result(js_promise->result(), isolate);
7589 return Utils::ToLocal(result);
7590 }
7591
State()7592 Promise::PromiseState Promise::State() {
7593 i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
7594 i::Isolate* isolate = promise->GetIsolate();
7595 LOG_API(isolate, Promise, Status);
7596 i::Handle<i::JSPromise> js_promise = i::Handle<i::JSPromise>::cast(promise);
7597 return static_cast<PromiseState>(js_promise->status());
7598 }
7599
MarkAsHandled()7600 void Promise::MarkAsHandled() {
7601 i::Handle<i::JSPromise> js_promise = Utils::OpenHandle(this);
7602 js_promise->set_has_handler(true);
7603 }
7604
MarkAsSilent()7605 void Promise::MarkAsSilent() {
7606 i::Handle<i::JSPromise> js_promise = Utils::OpenHandle(this);
7607 js_promise->set_is_silent(true);
7608 }
7609
GetTarget()7610 Local<Value> Proxy::GetTarget() {
7611 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7612 i::Handle<i::Object> target(self->target(), self->GetIsolate());
7613 return Utils::ToLocal(target);
7614 }
7615
GetHandler()7616 Local<Value> Proxy::GetHandler() {
7617 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7618 i::Handle<i::Object> handler(self->handler(), self->GetIsolate());
7619 return Utils::ToLocal(handler);
7620 }
7621
IsRevoked() const7622 bool Proxy::IsRevoked() const {
7623 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7624 return self->IsRevoked();
7625 }
7626
Revoke()7627 void Proxy::Revoke() {
7628 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7629 i::JSProxy::Revoke(self);
7630 }
7631
New(Local<Context> context,Local<Object> local_target,Local<Object> local_handler)7632 MaybeLocal<Proxy> Proxy::New(Local<Context> context, Local<Object> local_target,
7633 Local<Object> local_handler) {
7634 PREPARE_FOR_EXECUTION(context, Proxy, New, Proxy);
7635 i::Handle<i::JSReceiver> target = Utils::OpenHandle(*local_target);
7636 i::Handle<i::JSReceiver> handler = Utils::OpenHandle(*local_handler);
7637 Local<Proxy> result;
7638 has_pending_exception =
7639 !ToLocal<Proxy>(i::JSProxy::New(isolate, target, handler), &result);
7640 RETURN_ON_FAILED_EXECUTION(Proxy);
7641 RETURN_ESCAPED(result);
7642 }
7643
CompiledWasmModule(std::shared_ptr<internal::wasm::NativeModule> native_module,const char * source_url,size_t url_length)7644 CompiledWasmModule::CompiledWasmModule(
7645 std::shared_ptr<internal::wasm::NativeModule> native_module,
7646 const char* source_url, size_t url_length)
7647 : native_module_(std::move(native_module)),
7648 source_url_(source_url, url_length) {
7649 CHECK_NOT_NULL(native_module_);
7650 }
7651
Serialize()7652 OwnedBuffer CompiledWasmModule::Serialize() {
7653 #if V8_ENABLE_WEBASSEMBLY
7654 TRACE_EVENT0("v8.wasm", "wasm.SerializeModule");
7655 i::wasm::WasmSerializer wasm_serializer(native_module_.get());
7656 size_t buffer_size = wasm_serializer.GetSerializedNativeModuleSize();
7657 std::unique_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]);
7658 if (!wasm_serializer.SerializeNativeModule({buffer.get(), buffer_size}))
7659 return {};
7660 return {std::move(buffer), buffer_size};
7661 #else
7662 UNREACHABLE();
7663 #endif // V8_ENABLE_WEBASSEMBLY
7664 }
7665
GetWireBytesRef()7666 MemorySpan<const uint8_t> CompiledWasmModule::GetWireBytesRef() {
7667 #if V8_ENABLE_WEBASSEMBLY
7668 base::Vector<const uint8_t> bytes_vec = native_module_->wire_bytes();
7669 return {bytes_vec.begin(), bytes_vec.size()};
7670 #else
7671 UNREACHABLE();
7672 #endif // V8_ENABLE_WEBASSEMBLY
7673 }
7674
Buffer()7675 Local<ArrayBuffer> v8::WasmMemoryObject::Buffer() {
7676 #if V8_ENABLE_WEBASSEMBLY
7677 i::Handle<i::WasmMemoryObject> obj = Utils::OpenHandle(this);
7678 i::Handle<i::JSArrayBuffer> buffer(obj->array_buffer(), obj->GetIsolate());
7679 return Utils::ToLocal(buffer);
7680 #else
7681 UNREACHABLE();
7682 #endif // V8_ENABLE_WEBASSEMBLY
7683 }
7684
GetCompiledModule()7685 CompiledWasmModule WasmModuleObject::GetCompiledModule() {
7686 #if V8_ENABLE_WEBASSEMBLY
7687 auto obj = i::Handle<i::WasmModuleObject>::cast(Utils::OpenHandle(this));
7688 auto url =
7689 i::handle(i::String::cast(obj->script().name()), obj->GetIsolate());
7690 int length;
7691 std::unique_ptr<char[]> cstring =
7692 url->ToCString(i::DISALLOW_NULLS, i::FAST_STRING_TRAVERSAL, &length);
7693 return CompiledWasmModule(std::move(obj->shared_native_module()),
7694 cstring.get(), length);
7695 #else
7696 UNREACHABLE();
7697 #endif // V8_ENABLE_WEBASSEMBLY
7698 }
7699
FromCompiledModule(Isolate * isolate,const CompiledWasmModule & compiled_module)7700 MaybeLocal<WasmModuleObject> WasmModuleObject::FromCompiledModule(
7701 Isolate* isolate, const CompiledWasmModule& compiled_module) {
7702 #if V8_ENABLE_WEBASSEMBLY
7703 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7704 i::Handle<i::WasmModuleObject> module_object =
7705 i::wasm::GetWasmEngine()->ImportNativeModule(
7706 i_isolate, compiled_module.native_module_,
7707 base::VectorOf(compiled_module.source_url()));
7708 return Local<WasmModuleObject>::Cast(
7709 Utils::ToLocal(i::Handle<i::JSObject>::cast(module_object)));
7710 #else
7711 UNREACHABLE();
7712 #endif // V8_ENABLE_WEBASSEMBLY
7713 }
7714
WasmModuleObjectBuilderStreaming(Isolate * isolate)7715 WasmModuleObjectBuilderStreaming::WasmModuleObjectBuilderStreaming(
7716 Isolate* isolate) {
7717 USE(isolate_);
7718 }
7719
GetPromise()7720 Local<Promise> WasmModuleObjectBuilderStreaming::GetPromise() { return {}; }
7721
OnBytesReceived(const uint8_t * bytes,size_t size)7722 void WasmModuleObjectBuilderStreaming::OnBytesReceived(const uint8_t* bytes,
7723 size_t size) {}
7724
Finish()7725 void WasmModuleObjectBuilderStreaming::Finish() {}
7726
Abort(MaybeLocal<Value> exception)7727 void WasmModuleObjectBuilderStreaming::Abort(MaybeLocal<Value> exception) {}
7728
Reallocate(void * data,size_t old_length,size_t new_length)7729 void* v8::ArrayBuffer::Allocator::Reallocate(void* data, size_t old_length,
7730 size_t new_length) {
7731 if (old_length == new_length) return data;
7732 uint8_t* new_data =
7733 reinterpret_cast<uint8_t*>(AllocateUninitialized(new_length));
7734 if (new_data == nullptr) return nullptr;
7735 size_t bytes_to_copy = std::min(old_length, new_length);
7736 memcpy(new_data, data, bytes_to_copy);
7737 if (new_length > bytes_to_copy) {
7738 memset(new_data + bytes_to_copy, 0, new_length - bytes_to_copy);
7739 }
7740 Free(data, old_length);
7741 return new_data;
7742 }
7743
7744 // static
NewDefaultAllocator()7745 v8::ArrayBuffer::Allocator* v8::ArrayBuffer::Allocator::NewDefaultAllocator() {
7746 return new ArrayBufferAllocator();
7747 }
7748
IsDetachable() const7749 bool v8::ArrayBuffer::IsDetachable() const {
7750 return Utils::OpenHandle(this)->is_detachable();
7751 }
7752
7753 namespace {
ToInternal(std::shared_ptr<i::BackingStoreBase> backing_store)7754 std::shared_ptr<i::BackingStore> ToInternal(
7755 std::shared_ptr<i::BackingStoreBase> backing_store) {
7756 return std::static_pointer_cast<i::BackingStore>(backing_store);
7757 }
7758 } // namespace
7759
Detach()7760 void v8::ArrayBuffer::Detach() {
7761 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
7762 i::Isolate* isolate = obj->GetIsolate();
7763 Utils::ApiCheck(obj->is_detachable(), "v8::ArrayBuffer::Detach",
7764 "Only detachable ArrayBuffers can be detached");
7765 LOG_API(isolate, ArrayBuffer, Detach);
7766 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7767 obj->Detach();
7768 }
7769
ByteLength() const7770 size_t v8::ArrayBuffer::ByteLength() const {
7771 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
7772 return obj->byte_length();
7773 }
7774
New(Isolate * isolate,size_t byte_length)7775 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) {
7776 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7777 LOG_API(i_isolate, ArrayBuffer, New);
7778 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7779 i::MaybeHandle<i::JSArrayBuffer> result =
7780 i_isolate->factory()->NewJSArrayBufferAndBackingStore(
7781 byte_length, i::InitializedFlag::kZeroInitialized);
7782
7783 i::Handle<i::JSArrayBuffer> array_buffer;
7784 if (!result.ToHandle(&array_buffer)) {
7785 // TODO(jbroman): It may be useful in the future to provide a MaybeLocal
7786 // version that throws an exception or otherwise does not crash.
7787 i::FatalProcessOutOfMemory(i_isolate, "v8::ArrayBuffer::New");
7788 }
7789
7790 return Utils::ToLocal(array_buffer);
7791 }
7792
New(Isolate * isolate,std::shared_ptr<BackingStore> backing_store)7793 Local<ArrayBuffer> v8::ArrayBuffer::New(
7794 Isolate* isolate, std::shared_ptr<BackingStore> backing_store) {
7795 CHECK_IMPLIES(backing_store->ByteLength() != 0,
7796 backing_store->Data() != nullptr);
7797 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7798 LOG_API(i_isolate, ArrayBuffer, New);
7799 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7800 std::shared_ptr<i::BackingStore> i_backing_store(
7801 ToInternal(std::move(backing_store)));
7802 Utils::ApiCheck(
7803 !i_backing_store->is_shared(), "v8_ArrayBuffer_New",
7804 "Cannot construct ArrayBuffer with a BackingStore of SharedArrayBuffer");
7805 i::Handle<i::JSArrayBuffer> obj =
7806 i_isolate->factory()->NewJSArrayBuffer(std::move(i_backing_store));
7807 return Utils::ToLocal(obj);
7808 }
7809
NewBackingStore(Isolate * isolate,size_t byte_length)7810 std::unique_ptr<v8::BackingStore> v8::ArrayBuffer::NewBackingStore(
7811 Isolate* isolate, size_t byte_length) {
7812 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7813 LOG_API(i_isolate, ArrayBuffer, NewBackingStore);
7814 CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength);
7815 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7816 std::unique_ptr<i::BackingStoreBase> backing_store =
7817 i::BackingStore::Allocate(i_isolate, byte_length,
7818 i::SharedFlag::kNotShared,
7819 i::InitializedFlag::kZeroInitialized);
7820 if (!backing_store) {
7821 i::FatalProcessOutOfMemory(i_isolate, "v8::ArrayBuffer::NewBackingStore");
7822 }
7823 return std::unique_ptr<v8::BackingStore>(
7824 static_cast<v8::BackingStore*>(backing_store.release()));
7825 }
7826
NewBackingStore(void * data,size_t byte_length,v8::BackingStore::DeleterCallback deleter,void * deleter_data)7827 std::unique_ptr<v8::BackingStore> v8::ArrayBuffer::NewBackingStore(
7828 void* data, size_t byte_length, v8::BackingStore::DeleterCallback deleter,
7829 void* deleter_data) {
7830 CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength);
7831 std::unique_ptr<i::BackingStoreBase> backing_store =
7832 i::BackingStore::WrapAllocation(data, byte_length, deleter, deleter_data,
7833 i::SharedFlag::kNotShared);
7834 return std::unique_ptr<v8::BackingStore>(
7835 static_cast<v8::BackingStore*>(backing_store.release()));
7836 }
7837
Buffer()7838 Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
7839 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
7840 i::Handle<i::JSArrayBuffer> buffer;
7841 if (obj->IsJSDataView()) {
7842 i::Handle<i::JSDataView> data_view(i::JSDataView::cast(*obj),
7843 obj->GetIsolate());
7844 DCHECK(data_view->buffer().IsJSArrayBuffer());
7845 buffer = i::handle(i::JSArrayBuffer::cast(data_view->buffer()),
7846 data_view->GetIsolate());
7847 } else {
7848 DCHECK(obj->IsJSTypedArray());
7849 buffer = i::JSTypedArray::cast(*obj).GetBuffer();
7850 }
7851 return Utils::ToLocal(buffer);
7852 }
7853
CopyContents(void * dest,size_t byte_length)7854 size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) {
7855 i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this);
7856 size_t byte_offset = self->byte_offset();
7857 size_t bytes_to_copy = std::min(byte_length, self->byte_length());
7858 if (bytes_to_copy) {
7859 i::DisallowGarbageCollection no_gc;
7860 i::Isolate* isolate = self->GetIsolate();
7861 i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(self->buffer()),
7862 isolate);
7863 const char* source = reinterpret_cast<char*>(buffer->backing_store());
7864 if (source == nullptr) {
7865 DCHECK(self->IsJSTypedArray());
7866 i::Handle<i::JSTypedArray> typed_array(i::JSTypedArray::cast(*self),
7867 isolate);
7868 source = reinterpret_cast<char*>(typed_array->DataPtr());
7869 }
7870 memcpy(dest, source + byte_offset, bytes_to_copy);
7871 }
7872 return bytes_to_copy;
7873 }
7874
HasBuffer() const7875 bool v8::ArrayBufferView::HasBuffer() const {
7876 i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this);
7877 if (!self->IsJSTypedArray()) return true;
7878 auto typed_array = i::Handle<i::JSTypedArray>::cast(self);
7879 return !typed_array->is_on_heap();
7880 }
7881
ByteOffset()7882 size_t v8::ArrayBufferView::ByteOffset() {
7883 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
7884 return obj->WasDetached() ? 0 : obj->byte_offset();
7885 }
7886
ByteLength()7887 size_t v8::ArrayBufferView::ByteLength() {
7888 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
7889 return obj->WasDetached() ? 0 : obj->byte_length();
7890 }
7891
Length()7892 size_t v8::TypedArray::Length() {
7893 i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
7894 return obj->WasDetached() ? 0 : obj->length();
7895 }
7896
7897 static_assert(
7898 v8::TypedArray::kMaxLength == i::JSTypedArray::kMaxLength,
7899 "v8::TypedArray::kMaxLength must match i::JSTypedArray::kMaxLength");
7900
7901 #define TYPED_ARRAY_NEW(Type, type, TYPE, ctype) \
7902 Local<Type##Array> Type##Array::New(Local<ArrayBuffer> array_buffer, \
7903 size_t byte_offset, size_t length) { \
7904 i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate(); \
7905 LOG_API(isolate, Type##Array, New); \
7906 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \
7907 if (!Utils::ApiCheck(length <= kMaxLength, \
7908 "v8::" #Type \
7909 "Array::New(Local<ArrayBuffer>, size_t, size_t)", \
7910 "length exceeds max allowed value")) { \
7911 return Local<Type##Array>(); \
7912 } \
7913 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer); \
7914 i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray( \
7915 i::kExternal##Type##Array, buffer, byte_offset, length); \
7916 return Utils::ToLocal##Type##Array(obj); \
7917 } \
7918 Local<Type##Array> Type##Array::New( \
7919 Local<SharedArrayBuffer> shared_array_buffer, size_t byte_offset, \
7920 size_t length) { \
7921 CHECK(i::FLAG_harmony_sharedarraybuffer); \
7922 i::Isolate* isolate = \
7923 Utils::OpenHandle(*shared_array_buffer)->GetIsolate(); \
7924 LOG_API(isolate, Type##Array, New); \
7925 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \
7926 if (!Utils::ApiCheck( \
7927 length <= kMaxLength, \
7928 "v8::" #Type \
7929 "Array::New(Local<SharedArrayBuffer>, size_t, size_t)", \
7930 "length exceeds max allowed value")) { \
7931 return Local<Type##Array>(); \
7932 } \
7933 i::Handle<i::JSArrayBuffer> buffer = \
7934 Utils::OpenHandle(*shared_array_buffer); \
7935 i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray( \
7936 i::kExternal##Type##Array, buffer, byte_offset, length); \
7937 return Utils::ToLocal##Type##Array(obj); \
7938 }
7939
TYPED_ARRAYS(TYPED_ARRAY_NEW)7940 TYPED_ARRAYS(TYPED_ARRAY_NEW)
7941 #undef TYPED_ARRAY_NEW
7942
7943 Local<DataView> DataView::New(Local<ArrayBuffer> array_buffer,
7944 size_t byte_offset, size_t byte_length) {
7945 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
7946 i::Isolate* isolate = buffer->GetIsolate();
7947 LOG_API(isolate, DataView, New);
7948 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7949 i::Handle<i::JSDataView> obj =
7950 isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length);
7951 return Utils::ToLocal(obj);
7952 }
7953
New(Local<SharedArrayBuffer> shared_array_buffer,size_t byte_offset,size_t byte_length)7954 Local<DataView> DataView::New(Local<SharedArrayBuffer> shared_array_buffer,
7955 size_t byte_offset, size_t byte_length) {
7956 CHECK(i::FLAG_harmony_sharedarraybuffer);
7957 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*shared_array_buffer);
7958 i::Isolate* isolate = buffer->GetIsolate();
7959 LOG_API(isolate, DataView, New);
7960 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7961 i::Handle<i::JSDataView> obj =
7962 isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length);
7963 return Utils::ToLocal(obj);
7964 }
7965
ByteLength() const7966 size_t v8::SharedArrayBuffer::ByteLength() const {
7967 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
7968 return obj->byte_length();
7969 }
7970
New(Isolate * isolate,size_t byte_length)7971 Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(Isolate* isolate,
7972 size_t byte_length) {
7973 CHECK(i::FLAG_harmony_sharedarraybuffer);
7974 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7975 LOG_API(i_isolate, SharedArrayBuffer, New);
7976 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7977
7978 std::unique_ptr<i::BackingStore> backing_store =
7979 i::BackingStore::Allocate(i_isolate, byte_length, i::SharedFlag::kShared,
7980 i::InitializedFlag::kZeroInitialized);
7981
7982 if (!backing_store) {
7983 // TODO(jbroman): It may be useful in the future to provide a MaybeLocal
7984 // version that throws an exception or otherwise does not crash.
7985 i::FatalProcessOutOfMemory(i_isolate, "v8::SharedArrayBuffer::New");
7986 }
7987
7988 i::Handle<i::JSArrayBuffer> obj =
7989 i_isolate->factory()->NewJSSharedArrayBuffer(std::move(backing_store));
7990 return Utils::ToLocalShared(obj);
7991 }
7992
New(Isolate * isolate,std::shared_ptr<BackingStore> backing_store)7993 Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(
7994 Isolate* isolate, std::shared_ptr<BackingStore> backing_store) {
7995 CHECK(i::FLAG_harmony_sharedarraybuffer);
7996 CHECK_IMPLIES(backing_store->ByteLength() != 0,
7997 backing_store->Data() != nullptr);
7998 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7999 LOG_API(i_isolate, SharedArrayBuffer, New);
8000 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8001 std::shared_ptr<i::BackingStore> i_backing_store(ToInternal(backing_store));
8002 Utils::ApiCheck(
8003 i_backing_store->is_shared(), "v8_SharedArrayBuffer_New",
8004 "Cannot construct SharedArrayBuffer with BackingStore of ArrayBuffer");
8005 i::Handle<i::JSArrayBuffer> obj =
8006 i_isolate->factory()->NewJSSharedArrayBuffer(std::move(i_backing_store));
8007 return Utils::ToLocalShared(obj);
8008 }
8009
NewBackingStore(Isolate * isolate,size_t byte_length)8010 std::unique_ptr<v8::BackingStore> v8::SharedArrayBuffer::NewBackingStore(
8011 Isolate* isolate, size_t byte_length) {
8012 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8013 LOG_API(i_isolate, SharedArrayBuffer, NewBackingStore);
8014 CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength);
8015 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8016 std::unique_ptr<i::BackingStoreBase> backing_store =
8017 i::BackingStore::Allocate(i_isolate, byte_length, i::SharedFlag::kShared,
8018 i::InitializedFlag::kZeroInitialized);
8019 if (!backing_store) {
8020 i::FatalProcessOutOfMemory(i_isolate,
8021 "v8::SharedArrayBuffer::NewBackingStore");
8022 }
8023 return std::unique_ptr<v8::BackingStore>(
8024 static_cast<v8::BackingStore*>(backing_store.release()));
8025 }
8026
NewBackingStore(void * data,size_t byte_length,v8::BackingStore::DeleterCallback deleter,void * deleter_data)8027 std::unique_ptr<v8::BackingStore> v8::SharedArrayBuffer::NewBackingStore(
8028 void* data, size_t byte_length, v8::BackingStore::DeleterCallback deleter,
8029 void* deleter_data) {
8030 CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength);
8031 std::unique_ptr<i::BackingStoreBase> backing_store =
8032 i::BackingStore::WrapAllocation(data, byte_length, deleter, deleter_data,
8033 i::SharedFlag::kShared);
8034 return std::unique_ptr<v8::BackingStore>(
8035 static_cast<v8::BackingStore*>(backing_store.release()));
8036 }
8037
New(Isolate * isolate,Local<String> name)8038 Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
8039 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8040 LOG_API(i_isolate, Symbol, New);
8041 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8042 i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol();
8043 if (!name.IsEmpty()) result->set_description(*Utils::OpenHandle(*name));
8044 return Utils::ToLocal(result);
8045 }
8046
For(Isolate * isolate,Local<String> name)8047 Local<Symbol> v8::Symbol::For(Isolate* isolate, Local<String> name) {
8048 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8049 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
8050 return Utils::ToLocal(
8051 i_isolate->SymbolFor(i::RootIndex::kPublicSymbolTable, i_name, false));
8052 }
8053
ForApi(Isolate * isolate,Local<String> name)8054 Local<Symbol> v8::Symbol::ForApi(Isolate* isolate, Local<String> name) {
8055 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8056 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
8057 return Utils::ToLocal(
8058 i_isolate->SymbolFor(i::RootIndex::kApiSymbolTable, i_name, false));
8059 }
8060
8061 #define WELL_KNOWN_SYMBOLS(V) \
8062 V(AsyncIterator, async_iterator) \
8063 V(HasInstance, has_instance) \
8064 V(IsConcatSpreadable, is_concat_spreadable) \
8065 V(Iterator, iterator) \
8066 V(Match, match) \
8067 V(Replace, replace) \
8068 V(Search, search) \
8069 V(Split, split) \
8070 V(ToPrimitive, to_primitive) \
8071 V(ToStringTag, to_string_tag) \
8072 V(Unscopables, unscopables)
8073
8074 #define SYMBOL_GETTER(Name, name) \
8075 Local<Symbol> v8::Symbol::Get##Name(Isolate* isolate) { \
8076 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); \
8077 return Utils::ToLocal(i_isolate->factory()->name##_symbol()); \
8078 }
8079
WELL_KNOWN_SYMBOLS(SYMBOL_GETTER)8080 WELL_KNOWN_SYMBOLS(SYMBOL_GETTER)
8081
8082 #undef SYMBOL_GETTER
8083 #undef WELL_KNOWN_SYMBOLS
8084
8085 Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) {
8086 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8087 LOG_API(i_isolate, Private, New);
8088 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
8089 i::Handle<i::Symbol> symbol = i_isolate->factory()->NewPrivateSymbol();
8090 if (!name.IsEmpty()) symbol->set_description(*Utils::OpenHandle(*name));
8091 Local<Symbol> result = Utils::ToLocal(symbol);
8092 return v8::Local<Private>(reinterpret_cast<Private*>(*result));
8093 }
8094
ForApi(Isolate * isolate,Local<String> name)8095 Local<Private> v8::Private::ForApi(Isolate* isolate, Local<String> name) {
8096 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8097 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
8098 Local<Symbol> result = Utils::ToLocal(
8099 i_isolate->SymbolFor(i::RootIndex::kApiPrivateSymbolTable, i_name, true));
8100 return v8::Local<Private>(reinterpret_cast<Private*>(*result));
8101 }
8102
New(Isolate * isolate,double value)8103 Local<Number> v8::Number::New(Isolate* isolate, double value) {
8104 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8105 if (std::isnan(value)) {
8106 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
8107 value = std::numeric_limits<double>::quiet_NaN();
8108 }
8109 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
8110 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
8111 return Utils::NumberToLocal(result);
8112 }
8113
New(Isolate * isolate,int32_t value)8114 Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) {
8115 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8116 if (i::Smi::IsValid(value)) {
8117 return Utils::IntegerToLocal(
8118 i::Handle<i::Object>(i::Smi::FromInt(value), internal_isolate));
8119 }
8120 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
8121 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
8122 return Utils::IntegerToLocal(result);
8123 }
8124
NewFromUnsigned(Isolate * isolate,uint32_t value)8125 Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) {
8126 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8127 bool fits_into_int32_t = (value & (1 << 31)) == 0;
8128 if (fits_into_int32_t) {
8129 return Integer::New(isolate, static_cast<int32_t>(value));
8130 }
8131 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
8132 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
8133 return Utils::IntegerToLocal(result);
8134 }
8135
New(Isolate * isolate,int64_t value)8136 Local<BigInt> v8::BigInt::New(Isolate* isolate, int64_t value) {
8137 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8138 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
8139 i::Handle<i::BigInt> result = i::BigInt::FromInt64(internal_isolate, value);
8140 return Utils::ToLocal(result);
8141 }
8142
NewFromUnsigned(Isolate * isolate,uint64_t value)8143 Local<BigInt> v8::BigInt::NewFromUnsigned(Isolate* isolate, uint64_t value) {
8144 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8145 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
8146 i::Handle<i::BigInt> result = i::BigInt::FromUint64(internal_isolate, value);
8147 return Utils::ToLocal(result);
8148 }
8149
NewFromWords(Local<Context> context,int sign_bit,int word_count,const uint64_t * words)8150 MaybeLocal<BigInt> v8::BigInt::NewFromWords(Local<Context> context,
8151 int sign_bit, int word_count,
8152 const uint64_t* words) {
8153 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
8154 ENTER_V8_NO_SCRIPT(isolate, context, BigInt, NewFromWords,
8155 MaybeLocal<BigInt>(), InternalEscapableScope);
8156 i::MaybeHandle<i::BigInt> result =
8157 i::BigInt::FromWords64(isolate, sign_bit, word_count, words);
8158 has_pending_exception = result.is_null();
8159 RETURN_ON_FAILED_EXECUTION(BigInt);
8160 RETURN_ESCAPED(Utils::ToLocal(result.ToHandleChecked()));
8161 }
8162
Uint64Value(bool * lossless) const8163 uint64_t v8::BigInt::Uint64Value(bool* lossless) const {
8164 i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8165 return handle->AsUint64(lossless);
8166 }
8167
Int64Value(bool * lossless) const8168 int64_t v8::BigInt::Int64Value(bool* lossless) const {
8169 i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8170 return handle->AsInt64(lossless);
8171 }
8172
WordCount() const8173 int BigInt::WordCount() const {
8174 i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8175 return handle->Words64Count();
8176 }
8177
ToWordsArray(int * sign_bit,int * word_count,uint64_t * words) const8178 void BigInt::ToWordsArray(int* sign_bit, int* word_count,
8179 uint64_t* words) const {
8180 i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8181 return handle->ToWordsArray64(sign_bit, word_count, words);
8182 }
8183
ReportExternalAllocationLimitReached()8184 void Isolate::ReportExternalAllocationLimitReached() {
8185 i::Heap* heap = reinterpret_cast<i::Isolate*>(this)->heap();
8186 if (heap->gc_state() != i::Heap::NOT_IN_GC) return;
8187 heap->ReportExternalMemoryPressure();
8188 }
8189
GetHeapProfiler()8190 HeapProfiler* Isolate::GetHeapProfiler() {
8191 i::HeapProfiler* heap_profiler =
8192 reinterpret_cast<i::Isolate*>(this)->heap_profiler();
8193 return reinterpret_cast<HeapProfiler*>(heap_profiler);
8194 }
8195
SetIdle(bool is_idle)8196 void Isolate::SetIdle(bool is_idle) {
8197 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8198 isolate->SetIdle(is_idle);
8199 }
8200
GetArrayBufferAllocator()8201 ArrayBuffer::Allocator* Isolate::GetArrayBufferAllocator() {
8202 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8203 return isolate->array_buffer_allocator();
8204 }
8205
InContext()8206 bool Isolate::InContext() {
8207 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8208 return !isolate->context().is_null();
8209 }
8210
ClearKeptObjects()8211 void Isolate::ClearKeptObjects() {
8212 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8213 isolate->ClearKeptObjects();
8214 }
8215
GetCurrentContext()8216 v8::Local<v8::Context> Isolate::GetCurrentContext() {
8217 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8218 i::Context context = isolate->context();
8219 if (context.is_null()) return Local<Context>();
8220 i::Context native_context = context.native_context();
8221 if (native_context.is_null()) return Local<Context>();
8222 return Utils::ToLocal(i::Handle<i::Context>(native_context, isolate));
8223 }
8224
GetEnteredOrMicrotaskContext()8225 v8::Local<v8::Context> Isolate::GetEnteredOrMicrotaskContext() {
8226 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8227 i::Handle<i::Object> last =
8228 isolate->handle_scope_implementer()->LastEnteredOrMicrotaskContext();
8229 if (last.is_null()) return Local<Context>();
8230 DCHECK(last->IsNativeContext());
8231 return Utils::ToLocal(i::Handle<i::Context>::cast(last));
8232 }
8233
GetIncumbentContext()8234 v8::Local<v8::Context> Isolate::GetIncumbentContext() {
8235 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8236 i::Handle<i::Context> context = isolate->GetIncumbentContext();
8237 return Utils::ToLocal(context);
8238 }
8239
ThrowError(v8::Local<v8::String> message)8240 v8::Local<Value> Isolate::ThrowError(v8::Local<v8::String> message) {
8241 return ThrowException(v8::Exception::Error(message));
8242 }
8243
ThrowException(v8::Local<v8::Value> value)8244 v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
8245 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8246 ENTER_V8_DO_NOT_USE(isolate);
8247 // If we're passed an empty handle, we throw an undefined exception
8248 // to deal more gracefully with out of memory situations.
8249 if (value.IsEmpty()) {
8250 isolate->ScheduleThrow(i::ReadOnlyRoots(isolate).undefined_value());
8251 } else {
8252 isolate->ScheduleThrow(*Utils::OpenHandle(*value));
8253 }
8254 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
8255 }
8256
AddGCPrologueCallback(GCCallbackWithData callback,void * data,GCType gc_type)8257 void Isolate::AddGCPrologueCallback(GCCallbackWithData callback, void* data,
8258 GCType gc_type) {
8259 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8260 isolate->heap()->AddGCPrologueCallback(callback, gc_type, data);
8261 }
8262
RemoveGCPrologueCallback(GCCallbackWithData callback,void * data)8263 void Isolate::RemoveGCPrologueCallback(GCCallbackWithData callback,
8264 void* data) {
8265 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8266 isolate->heap()->RemoveGCPrologueCallback(callback, data);
8267 }
8268
AddGCEpilogueCallback(GCCallbackWithData callback,void * data,GCType gc_type)8269 void Isolate::AddGCEpilogueCallback(GCCallbackWithData callback, void* data,
8270 GCType gc_type) {
8271 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8272 isolate->heap()->AddGCEpilogueCallback(callback, gc_type, data);
8273 }
8274
RemoveGCEpilogueCallback(GCCallbackWithData callback,void * data)8275 void Isolate::RemoveGCEpilogueCallback(GCCallbackWithData callback,
8276 void* data) {
8277 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8278 isolate->heap()->RemoveGCEpilogueCallback(callback, data);
8279 }
8280
CallGCCallbackWithoutData(Isolate * isolate,GCType type,GCCallbackFlags flags,void * data)8281 static void CallGCCallbackWithoutData(Isolate* isolate, GCType type,
8282 GCCallbackFlags flags, void* data) {
8283 reinterpret_cast<Isolate::GCCallback>(data)(isolate, type, flags);
8284 }
8285
AddGCPrologueCallback(GCCallback callback,GCType gc_type)8286 void Isolate::AddGCPrologueCallback(GCCallback callback, GCType gc_type) {
8287 void* data = reinterpret_cast<void*>(callback);
8288 AddGCPrologueCallback(CallGCCallbackWithoutData, data, gc_type);
8289 }
8290
RemoveGCPrologueCallback(GCCallback callback)8291 void Isolate::RemoveGCPrologueCallback(GCCallback callback) {
8292 void* data = reinterpret_cast<void*>(callback);
8293 RemoveGCPrologueCallback(CallGCCallbackWithoutData, data);
8294 }
8295
AddGCEpilogueCallback(GCCallback callback,GCType gc_type)8296 void Isolate::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) {
8297 void* data = reinterpret_cast<void*>(callback);
8298 AddGCEpilogueCallback(CallGCCallbackWithoutData, data, gc_type);
8299 }
8300
RemoveGCEpilogueCallback(GCCallback callback)8301 void Isolate::RemoveGCEpilogueCallback(GCCallback callback) {
8302 void* data = reinterpret_cast<void*>(callback);
8303 RemoveGCEpilogueCallback(CallGCCallbackWithoutData, data);
8304 }
8305
SetEmbedderHeapTracer(EmbedderHeapTracer * tracer)8306 void Isolate::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) {
8307 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8308 isolate->heap()->SetEmbedderHeapTracer(tracer);
8309 }
8310
GetEmbedderHeapTracer()8311 EmbedderHeapTracer* Isolate::GetEmbedderHeapTracer() {
8312 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8313 return isolate->heap()->GetEmbedderHeapTracer();
8314 }
8315
SetEmbedderRootsHandler(EmbedderRootsHandler * handler)8316 void Isolate::SetEmbedderRootsHandler(EmbedderRootsHandler* handler) {
8317 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8318 isolate->heap()->SetEmbedderRootsHandler(handler);
8319 }
8320
AttachCppHeap(CppHeap * cpp_heap)8321 void Isolate::AttachCppHeap(CppHeap* cpp_heap) {
8322 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8323 isolate->heap()->AttachCppHeap(cpp_heap);
8324 }
8325
DetachCppHeap()8326 void Isolate::DetachCppHeap() {
8327 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8328 isolate->heap()->DetachCppHeap();
8329 }
8330
GetCppHeap() const8331 CppHeap* Isolate::GetCppHeap() const {
8332 const i::Isolate* isolate = reinterpret_cast<const i::Isolate*>(this);
8333 return isolate->heap()->cpp_heap();
8334 }
8335
SetGetExternallyAllocatedMemoryInBytesCallback(GetExternallyAllocatedMemoryInBytesCallback callback)8336 void Isolate::SetGetExternallyAllocatedMemoryInBytesCallback(
8337 GetExternallyAllocatedMemoryInBytesCallback callback) {
8338 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8339 isolate->heap()->SetGetExternallyAllocatedMemoryInBytesCallback(callback);
8340 }
8341
TerminateExecution()8342 void Isolate::TerminateExecution() {
8343 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8344 isolate->stack_guard()->RequestTerminateExecution();
8345 }
8346
IsExecutionTerminating()8347 bool Isolate::IsExecutionTerminating() {
8348 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8349 return IsExecutionTerminatingCheck(isolate);
8350 }
8351
CancelTerminateExecution()8352 void Isolate::CancelTerminateExecution() {
8353 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8354 isolate->stack_guard()->ClearTerminateExecution();
8355 isolate->CancelTerminateExecution();
8356 }
8357
RequestInterrupt(InterruptCallback callback,void * data)8358 void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
8359 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8360 isolate->RequestInterrupt(callback, data);
8361 }
8362
HasPendingBackgroundTasks()8363 bool Isolate::HasPendingBackgroundTasks() {
8364 #if V8_ENABLE_WEBASSEMBLY
8365 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8366 return i::wasm::GetWasmEngine()->HasRunningCompileJob(isolate);
8367 #else
8368 return false;
8369 #endif // V8_ENABLE_WEBASSEMBLY
8370 }
8371
RequestGarbageCollectionForTesting(GarbageCollectionType type)8372 void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) {
8373 Utils::ApiCheck(i::FLAG_expose_gc,
8374 "v8::Isolate::RequestGarbageCollectionForTesting",
8375 "Must use --expose-gc");
8376 if (type == kMinorGarbageCollection) {
8377 reinterpret_cast<i::Isolate*>(this)->heap()->CollectGarbage(
8378 i::NEW_SPACE, i::GarbageCollectionReason::kTesting,
8379 kGCCallbackFlagForced);
8380 } else {
8381 DCHECK_EQ(kFullGarbageCollection, type);
8382 reinterpret_cast<i::Isolate*>(this)->heap()->PreciseCollectAllGarbage(
8383 i::Heap::kNoGCFlags, i::GarbageCollectionReason::kTesting,
8384 kGCCallbackFlagForced);
8385 }
8386 }
8387
GetCurrent()8388 Isolate* Isolate::GetCurrent() {
8389 i::Isolate* isolate = i::Isolate::Current();
8390 return reinterpret_cast<Isolate*>(isolate);
8391 }
8392
TryGetCurrent()8393 Isolate* Isolate::TryGetCurrent() {
8394 i::Isolate* isolate = i::Isolate::TryGetCurrent();
8395 return reinterpret_cast<Isolate*>(isolate);
8396 }
8397
8398 // static
Allocate()8399 Isolate* Isolate::Allocate() {
8400 return reinterpret_cast<Isolate*>(i::Isolate::New());
8401 }
8402
8403 Isolate::CreateParams::CreateParams() = default;
8404
8405 Isolate::CreateParams::~CreateParams() = default;
8406
8407 // static
8408 // This is separate so that tests can provide a different |isolate|.
Initialize(Isolate * isolate,const v8::Isolate::CreateParams & params)8409 void Isolate::Initialize(Isolate* isolate,
8410 const v8::Isolate::CreateParams& params) {
8411 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8412 if (auto allocator = params.array_buffer_allocator_shared) {
8413 CHECK(params.array_buffer_allocator == nullptr ||
8414 params.array_buffer_allocator == allocator.get());
8415 i_isolate->set_array_buffer_allocator(allocator.get());
8416 i_isolate->set_array_buffer_allocator_shared(std::move(allocator));
8417 } else {
8418 CHECK_NOT_NULL(params.array_buffer_allocator);
8419 i_isolate->set_array_buffer_allocator(params.array_buffer_allocator);
8420 }
8421 if (params.snapshot_blob != nullptr) {
8422 i_isolate->set_snapshot_blob(params.snapshot_blob);
8423 } else {
8424 i_isolate->set_snapshot_blob(i::Snapshot::DefaultSnapshotBlob());
8425 }
8426 if (params.counter_lookup_callback) {
8427 isolate->SetCounterFunction(params.counter_lookup_callback);
8428 }
8429
8430 if (params.create_histogram_callback) {
8431 isolate->SetCreateHistogramFunction(params.create_histogram_callback);
8432 }
8433
8434 if (params.add_histogram_sample_callback) {
8435 isolate->SetAddHistogramSampleFunction(
8436 params.add_histogram_sample_callback);
8437 }
8438
8439 i_isolate->set_api_external_references(params.external_references);
8440 i_isolate->set_allow_atomics_wait(params.allow_atomics_wait);
8441
8442 i_isolate->heap()->ConfigureHeap(params.constraints);
8443 if (params.constraints.stack_limit() != nullptr) {
8444 uintptr_t limit =
8445 reinterpret_cast<uintptr_t>(params.constraints.stack_limit());
8446 i_isolate->stack_guard()->SetStackLimit(limit);
8447 }
8448 // TODO(jochen): Once we got rid of Isolate::Current(), we can remove this.
8449 Isolate::Scope isolate_scope(isolate);
8450 if (i_isolate->snapshot_blob() == nullptr) {
8451 FATAL(
8452 "V8 snapshot blob was not set during initialization. This can mean "
8453 "that the snapshot blob file is corrupted or missing.");
8454 }
8455 if (!i::Snapshot::Initialize(i_isolate)) {
8456 // If snapshot data was provided and we failed to deserialize it must
8457 // have been corrupted.
8458 FATAL(
8459 "Failed to deserialize the V8 snapshot blob. This can mean that the "
8460 "snapshot blob file is corrupted or missing.");
8461 }
8462
8463 {
8464 // Set up code event handlers. Needs to be after i::Snapshot::Initialize
8465 // because that is where we add the isolate to WasmEngine.
8466 auto code_event_handler = params.code_event_handler;
8467 #ifdef ENABLE_GDB_JIT_INTERFACE
8468 if (code_event_handler == nullptr && i::FLAG_gdbjit) {
8469 code_event_handler = i::GDBJITInterface::EventHandler;
8470 }
8471 #endif // ENABLE_GDB_JIT_INTERFACE
8472 #if defined(V8_OS_WIN) && defined(V8_ENABLE_SYSTEM_INSTRUMENTATION)
8473 if (code_event_handler == nullptr &&
8474 i::FLAG_enable_system_instrumentation) {
8475 code_event_handler = i::ETWJITInterface::EventHandler;
8476 }
8477 #endif // defined(V8_OS_WIN)
8478
8479 if (code_event_handler) {
8480 isolate->SetJitCodeEventHandler(kJitCodeEventDefault, code_event_handler);
8481 }
8482 }
8483
8484 i_isolate->set_only_terminate_in_safe_scope(
8485 params.only_terminate_in_safe_scope);
8486 i_isolate->set_embedder_wrapper_type_index(
8487 params.embedder_wrapper_type_index);
8488 i_isolate->set_embedder_wrapper_object_index(
8489 params.embedder_wrapper_object_index);
8490
8491 if (!i::V8::GetCurrentPlatform()
8492 ->GetForegroundTaskRunner(isolate)
8493 ->NonNestableTasksEnabled()) {
8494 FATAL(
8495 "The current platform's foreground task runner does not have "
8496 "non-nestable tasks enabled. The embedder must provide one.");
8497 }
8498 }
8499
New(const Isolate::CreateParams & params)8500 Isolate* Isolate::New(const Isolate::CreateParams& params) {
8501 Isolate* isolate = Allocate();
8502 Initialize(isolate, params);
8503 return isolate;
8504 }
8505
Dispose()8506 void Isolate::Dispose() {
8507 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8508 if (!Utils::ApiCheck(!isolate->IsInUse(), "v8::Isolate::Dispose()",
8509 "Disposing the isolate that is entered by a thread.")) {
8510 return;
8511 }
8512 i::Isolate::Delete(isolate);
8513 }
8514
DumpAndResetStats()8515 void Isolate::DumpAndResetStats() {
8516 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8517 isolate->DumpAndResetStats();
8518 }
8519
DiscardThreadSpecificMetadata()8520 void Isolate::DiscardThreadSpecificMetadata() {
8521 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8522 isolate->DiscardPerThreadDataForThisThread();
8523 }
8524
Enter()8525 void Isolate::Enter() {
8526 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8527 isolate->Enter();
8528 }
8529
Exit()8530 void Isolate::Exit() {
8531 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8532 isolate->Exit();
8533 }
8534
SetAbortOnUncaughtExceptionCallback(AbortOnUncaughtExceptionCallback callback)8535 void Isolate::SetAbortOnUncaughtExceptionCallback(
8536 AbortOnUncaughtExceptionCallback callback) {
8537 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8538 isolate->SetAbortOnUncaughtExceptionCallback(callback);
8539 }
8540
SetHostImportModuleDynamicallyCallback(HostImportModuleDynamicallyWithImportAssertionsCallback callback)8541 void Isolate::SetHostImportModuleDynamicallyCallback(
8542 HostImportModuleDynamicallyWithImportAssertionsCallback callback) {
8543 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8544 isolate->SetHostImportModuleDynamicallyCallback(callback);
8545 }
8546
SetHostInitializeImportMetaObjectCallback(HostInitializeImportMetaObjectCallback callback)8547 void Isolate::SetHostInitializeImportMetaObjectCallback(
8548 HostInitializeImportMetaObjectCallback callback) {
8549 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8550 isolate->SetHostInitializeImportMetaObjectCallback(callback);
8551 }
8552
SetPrepareStackTraceCallback(PrepareStackTraceCallback callback)8553 void Isolate::SetPrepareStackTraceCallback(PrepareStackTraceCallback callback) {
8554 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8555 isolate->SetPrepareStackTraceCallback(callback);
8556 }
8557
DisallowJavascriptExecutionScope(Isolate * isolate,Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)8558 Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope(
8559 Isolate* isolate,
8560 Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)
8561 : on_failure_(on_failure), isolate_(isolate) {
8562 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8563 switch (on_failure_) {
8564 case CRASH_ON_FAILURE:
8565 i::DisallowJavascriptExecution::Open(i_isolate,
8566 &was_execution_allowed_assert_);
8567 break;
8568 case THROW_ON_FAILURE:
8569 i::ThrowOnJavascriptExecution::Open(i_isolate,
8570 &was_execution_allowed_throws_);
8571 break;
8572 case DUMP_ON_FAILURE:
8573 i::DumpOnJavascriptExecution::Open(i_isolate,
8574 &was_execution_allowed_dump_);
8575 break;
8576 default:
8577 UNREACHABLE();
8578 }
8579 }
8580
~DisallowJavascriptExecutionScope()8581 Isolate::DisallowJavascriptExecutionScope::~DisallowJavascriptExecutionScope() {
8582 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
8583 switch (on_failure_) {
8584 case CRASH_ON_FAILURE:
8585 i::DisallowJavascriptExecution::Close(i_isolate,
8586 was_execution_allowed_assert_);
8587 break;
8588 case THROW_ON_FAILURE:
8589 i::ThrowOnJavascriptExecution::Close(i_isolate,
8590 was_execution_allowed_throws_);
8591 break;
8592 case DUMP_ON_FAILURE:
8593 i::DumpOnJavascriptExecution::Close(i_isolate,
8594 was_execution_allowed_dump_);
8595 break;
8596 default:
8597 UNREACHABLE();
8598 }
8599 }
8600
AllowJavascriptExecutionScope(Isolate * isolate)8601 Isolate::AllowJavascriptExecutionScope::AllowJavascriptExecutionScope(
8602 Isolate* isolate)
8603 : isolate_(isolate) {
8604 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8605 i::AllowJavascriptExecution::Open(i_isolate, &was_execution_allowed_assert_);
8606 i::NoThrowOnJavascriptExecution::Open(i_isolate,
8607 &was_execution_allowed_throws_);
8608 i::NoDumpOnJavascriptExecution::Open(i_isolate, &was_execution_allowed_dump_);
8609 }
8610
~AllowJavascriptExecutionScope()8611 Isolate::AllowJavascriptExecutionScope::~AllowJavascriptExecutionScope() {
8612 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
8613 i::AllowJavascriptExecution::Close(i_isolate, was_execution_allowed_assert_);
8614 i::NoThrowOnJavascriptExecution::Close(i_isolate,
8615 was_execution_allowed_throws_);
8616 i::NoDumpOnJavascriptExecution::Close(i_isolate, was_execution_allowed_dump_);
8617 }
8618
SuppressMicrotaskExecutionScope(Isolate * isolate,MicrotaskQueue * microtask_queue)8619 Isolate::SuppressMicrotaskExecutionScope::SuppressMicrotaskExecutionScope(
8620 Isolate* isolate, MicrotaskQueue* microtask_queue)
8621 : isolate_(reinterpret_cast<i::Isolate*>(isolate)),
8622 microtask_queue_(microtask_queue
8623 ? static_cast<i::MicrotaskQueue*>(microtask_queue)
8624 : isolate_->default_microtask_queue()) {
8625 isolate_->thread_local_top()->IncrementCallDepth(this);
8626 microtask_queue_->IncrementMicrotasksSuppressions();
8627 }
8628
~SuppressMicrotaskExecutionScope()8629 Isolate::SuppressMicrotaskExecutionScope::~SuppressMicrotaskExecutionScope() {
8630 microtask_queue_->DecrementMicrotasksSuppressions();
8631 isolate_->thread_local_top()->DecrementCallDepth(this);
8632 }
8633
SafeForTerminationScope(v8::Isolate * isolate)8634 Isolate::SafeForTerminationScope::SafeForTerminationScope(v8::Isolate* isolate)
8635 : isolate_(reinterpret_cast<i::Isolate*>(isolate)),
8636 prev_value_(isolate_->next_v8_call_is_safe_for_termination()) {
8637 isolate_->set_next_v8_call_is_safe_for_termination(true);
8638 }
8639
~SafeForTerminationScope()8640 Isolate::SafeForTerminationScope::~SafeForTerminationScope() {
8641 isolate_->set_next_v8_call_is_safe_for_termination(prev_value_);
8642 }
8643
GetDataFromSnapshotOnce(size_t index)8644 i::Address* Isolate::GetDataFromSnapshotOnce(size_t index) {
8645 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
8646 i::FixedArray list = i_isolate->heap()->serialized_objects();
8647 return GetSerializedDataFromFixedArray(i_isolate, list, index);
8648 }
8649
GetHeapStatistics(HeapStatistics * heap_statistics)8650 void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) {
8651 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8652 i::Heap* heap = isolate->heap();
8653
8654 // The order of acquiring memory statistics is important here. We query in
8655 // this order because of concurrent allocation: 1) used memory 2) comitted
8656 // physical memory 3) committed memory. Therefore the condition used <=
8657 // committed physical <= committed should hold.
8658 heap_statistics->used_global_handles_size_ = heap->UsedGlobalHandlesSize();
8659 heap_statistics->total_global_handles_size_ = heap->TotalGlobalHandlesSize();
8660 DCHECK_LE(heap_statistics->used_global_handles_size_,
8661 heap_statistics->total_global_handles_size_);
8662
8663 heap_statistics->used_heap_size_ = heap->SizeOfObjects();
8664 heap_statistics->total_physical_size_ = heap->CommittedPhysicalMemory();
8665 heap_statistics->total_heap_size_ = heap->CommittedMemory();
8666
8667 heap_statistics->total_available_size_ = heap->Available();
8668
8669 if (!i::ReadOnlyHeap::IsReadOnlySpaceShared()) {
8670 i::ReadOnlySpace* ro_space = heap->read_only_space();
8671 heap_statistics->used_heap_size_ += ro_space->Size();
8672 heap_statistics->total_physical_size_ +=
8673 ro_space->CommittedPhysicalMemory();
8674 heap_statistics->total_heap_size_ += ro_space->CommittedMemory();
8675 }
8676
8677 // TODO(dinfuehr): Right now used <= committed physical does not hold. Fix
8678 // this and add DCHECK.
8679 DCHECK_LE(heap_statistics->used_heap_size_,
8680 heap_statistics->total_heap_size_);
8681
8682 heap_statistics->total_heap_size_executable_ =
8683 heap->CommittedMemoryExecutable();
8684 heap_statistics->heap_size_limit_ = heap->MaxReserved();
8685 // TODO(7424): There is no public API for the {WasmEngine} yet. Once such an
8686 // API becomes available we should report the malloced memory separately. For
8687 // now we just add the values, thereby over-approximating the peak slightly.
8688 heap_statistics->malloced_memory_ =
8689 isolate->allocator()->GetCurrentMemoryUsage() +
8690 isolate->string_table()->GetCurrentMemoryUsage();
8691 // On 32-bit systems backing_store_bytes() might overflow size_t temporarily
8692 // due to concurrent array buffer sweeping.
8693 heap_statistics->external_memory_ =
8694 isolate->heap()->backing_store_bytes() < SIZE_MAX
8695 ? static_cast<size_t>(isolate->heap()->backing_store_bytes())
8696 : SIZE_MAX;
8697 heap_statistics->peak_malloced_memory_ =
8698 isolate->allocator()->GetMaxMemoryUsage();
8699 heap_statistics->number_of_native_contexts_ = heap->NumberOfNativeContexts();
8700 heap_statistics->number_of_detached_contexts_ =
8701 heap->NumberOfDetachedContexts();
8702 heap_statistics->does_zap_garbage_ = heap->ShouldZapGarbage();
8703
8704 #if V8_ENABLE_WEBASSEMBLY
8705 heap_statistics->malloced_memory_ +=
8706 i::wasm::GetWasmEngine()->allocator()->GetCurrentMemoryUsage();
8707 heap_statistics->peak_malloced_memory_ +=
8708 i::wasm::GetWasmEngine()->allocator()->GetMaxMemoryUsage();
8709 #endif // V8_ENABLE_WEBASSEMBLY
8710 }
8711
NumberOfHeapSpaces()8712 size_t Isolate::NumberOfHeapSpaces() {
8713 return i::LAST_SPACE - i::FIRST_SPACE + 1;
8714 }
8715
GetHeapSpaceStatistics(HeapSpaceStatistics * space_statistics,size_t index)8716 bool Isolate::GetHeapSpaceStatistics(HeapSpaceStatistics* space_statistics,
8717 size_t index) {
8718 if (!space_statistics) return false;
8719 if (!i::Heap::IsValidAllocationSpace(static_cast<i::AllocationSpace>(index)))
8720 return false;
8721
8722 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8723 i::Heap* heap = isolate->heap();
8724
8725 i::AllocationSpace allocation_space = static_cast<i::AllocationSpace>(index);
8726 space_statistics->space_name_ = i::BaseSpace::GetSpaceName(allocation_space);
8727
8728 if (allocation_space == i::RO_SPACE) {
8729 if (i::ReadOnlyHeap::IsReadOnlySpaceShared()) {
8730 // RO_SPACE memory is accounted for elsewhere when ReadOnlyHeap is shared.
8731 space_statistics->space_size_ = 0;
8732 space_statistics->space_used_size_ = 0;
8733 space_statistics->space_available_size_ = 0;
8734 space_statistics->physical_space_size_ = 0;
8735 } else {
8736 i::ReadOnlySpace* space = heap->read_only_space();
8737 space_statistics->space_size_ = space->CommittedMemory();
8738 space_statistics->space_used_size_ = space->Size();
8739 space_statistics->space_available_size_ = 0;
8740 space_statistics->physical_space_size_ = space->CommittedPhysicalMemory();
8741 }
8742 } else {
8743 i::Space* space = heap->space(static_cast<int>(index));
8744 space_statistics->space_size_ = space ? space->CommittedMemory() : 0;
8745 space_statistics->space_used_size_ = space ? space->SizeOfObjects() : 0;
8746 space_statistics->space_available_size_ = space ? space->Available() : 0;
8747 space_statistics->physical_space_size_ =
8748 space ? space->CommittedPhysicalMemory() : 0;
8749 }
8750 return true;
8751 }
8752
NumberOfTrackedHeapObjectTypes()8753 size_t Isolate::NumberOfTrackedHeapObjectTypes() {
8754 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8755 i::Heap* heap = isolate->heap();
8756 return heap->NumberOfTrackedHeapObjectTypes();
8757 }
8758
GetHeapObjectStatisticsAtLastGC(HeapObjectStatistics * object_statistics,size_t type_index)8759 bool Isolate::GetHeapObjectStatisticsAtLastGC(
8760 HeapObjectStatistics* object_statistics, size_t type_index) {
8761 if (!object_statistics) return false;
8762 if (V8_LIKELY(!i::TracingFlags::is_gc_stats_enabled())) return false;
8763
8764 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8765 i::Heap* heap = isolate->heap();
8766 if (type_index >= heap->NumberOfTrackedHeapObjectTypes()) return false;
8767
8768 const char* object_type;
8769 const char* object_sub_type;
8770 size_t object_count = heap->ObjectCountAtLastGC(type_index);
8771 size_t object_size = heap->ObjectSizeAtLastGC(type_index);
8772 if (!heap->GetObjectTypeName(type_index, &object_type, &object_sub_type)) {
8773 // There should be no objects counted when the type is unknown.
8774 DCHECK_EQ(object_count, 0U);
8775 DCHECK_EQ(object_size, 0U);
8776 return false;
8777 }
8778
8779 object_statistics->object_type_ = object_type;
8780 object_statistics->object_sub_type_ = object_sub_type;
8781 object_statistics->object_count_ = object_count;
8782 object_statistics->object_size_ = object_size;
8783 return true;
8784 }
8785
GetHeapCodeAndMetadataStatistics(HeapCodeStatistics * code_statistics)8786 bool Isolate::GetHeapCodeAndMetadataStatistics(
8787 HeapCodeStatistics* code_statistics) {
8788 if (!code_statistics) return false;
8789
8790 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8791 isolate->heap()->CollectCodeStatistics();
8792
8793 code_statistics->code_and_metadata_size_ = isolate->code_and_metadata_size();
8794 code_statistics->bytecode_and_metadata_size_ =
8795 isolate->bytecode_and_metadata_size();
8796 code_statistics->external_script_source_size_ =
8797 isolate->external_script_source_size();
8798 return true;
8799 }
8800
MeasureMemory(std::unique_ptr<MeasureMemoryDelegate> delegate,MeasureMemoryExecution execution)8801 bool Isolate::MeasureMemory(std::unique_ptr<MeasureMemoryDelegate> delegate,
8802 MeasureMemoryExecution execution) {
8803 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8804 return isolate->heap()->MeasureMemory(std::move(delegate), execution);
8805 }
8806
Default(Isolate * isolate,Local<Context> context,Local<Promise::Resolver> promise_resolver,MeasureMemoryMode mode)8807 std::unique_ptr<MeasureMemoryDelegate> MeasureMemoryDelegate::Default(
8808 Isolate* isolate, Local<Context> context,
8809 Local<Promise::Resolver> promise_resolver, MeasureMemoryMode mode) {
8810 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8811 i::Handle<i::NativeContext> native_context =
8812 handle(Utils::OpenHandle(*context)->native_context(), i_isolate);
8813 i::Handle<i::JSPromise> js_promise =
8814 i::Handle<i::JSPromise>::cast(Utils::OpenHandle(*promise_resolver));
8815 return i_isolate->heap()->MeasureMemoryDelegate(native_context, js_promise,
8816 mode);
8817 }
8818
GetStackSample(const RegisterState & state,void ** frames,size_t frames_limit,SampleInfo * sample_info)8819 void Isolate::GetStackSample(const RegisterState& state, void** frames,
8820 size_t frames_limit, SampleInfo* sample_info) {
8821 RegisterState regs = state;
8822 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8823 if (i::TickSample::GetStackSample(isolate, ®s,
8824 i::TickSample::kSkipCEntryFrame, frames,
8825 frames_limit, sample_info)) {
8826 return;
8827 }
8828 sample_info->frames_count = 0;
8829 sample_info->vm_state = OTHER;
8830 sample_info->external_callback_entry = nullptr;
8831 }
8832
NumberOfPhantomHandleResetsSinceLastCall()8833 size_t Isolate::NumberOfPhantomHandleResetsSinceLastCall() {
8834 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8835 return isolate->global_handles()->GetAndResetGlobalHandleResetCount();
8836 }
8837
AdjustAmountOfExternalAllocatedMemory(int64_t change_in_bytes)8838 int64_t Isolate::AdjustAmountOfExternalAllocatedMemory(
8839 int64_t change_in_bytes) {
8840 // Try to check for unreasonably large or small values from the embedder.
8841 const int64_t kMaxReasonableBytes = int64_t(1) << 60;
8842 const int64_t kMinReasonableBytes = -kMaxReasonableBytes;
8843 STATIC_ASSERT(kMaxReasonableBytes >= i::JSArrayBuffer::kMaxByteLength);
8844
8845 CHECK(kMinReasonableBytes <= change_in_bytes &&
8846 change_in_bytes < kMaxReasonableBytes);
8847
8848 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
8849 int64_t amount = i_isolate->heap()->update_external_memory(change_in_bytes);
8850
8851 if (change_in_bytes <= 0) return amount;
8852
8853 if (amount > i_isolate->heap()->external_memory_limit()) {
8854 ReportExternalAllocationLimitReached();
8855 }
8856 return amount;
8857 }
8858
SetEventLogger(LogEventCallback that)8859 void Isolate::SetEventLogger(LogEventCallback that) {
8860 // Do not overwrite the event logger if we want to log explicitly.
8861 if (i::FLAG_log_internal_timer_events) return;
8862 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8863 isolate->set_event_logger(that);
8864 }
8865
AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback)8866 void Isolate::AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback) {
8867 if (callback == nullptr) return;
8868 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8869 isolate->AddBeforeCallEnteredCallback(callback);
8870 }
8871
RemoveBeforeCallEnteredCallback(BeforeCallEnteredCallback callback)8872 void Isolate::RemoveBeforeCallEnteredCallback(
8873 BeforeCallEnteredCallback callback) {
8874 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8875 isolate->RemoveBeforeCallEnteredCallback(callback);
8876 }
8877
AddCallCompletedCallback(CallCompletedCallback callback)8878 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
8879 if (callback == nullptr) return;
8880 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8881 isolate->AddCallCompletedCallback(callback);
8882 }
8883
RemoveCallCompletedCallback(CallCompletedCallback callback)8884 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
8885 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8886 isolate->RemoveCallCompletedCallback(callback);
8887 }
8888
Wake()8889 void Isolate::AtomicsWaitWakeHandle::Wake() {
8890 reinterpret_cast<i::AtomicsWaitWakeHandle*>(this)->Wake();
8891 }
8892
SetAtomicsWaitCallback(AtomicsWaitCallback callback,void * data)8893 void Isolate::SetAtomicsWaitCallback(AtomicsWaitCallback callback, void* data) {
8894 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8895 isolate->SetAtomicsWaitCallback(callback, data);
8896 }
8897
SetPromiseHook(PromiseHook hook)8898 void Isolate::SetPromiseHook(PromiseHook hook) {
8899 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8900 isolate->SetPromiseHook(hook);
8901 }
8902
SetPromiseRejectCallback(PromiseRejectCallback callback)8903 void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
8904 if (callback == nullptr) return;
8905 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8906 isolate->SetPromiseRejectCallback(callback);
8907 }
8908
PerformMicrotaskCheckpoint()8909 void Isolate::PerformMicrotaskCheckpoint() {
8910 DCHECK_NE(MicrotasksPolicy::kScoped, GetMicrotasksPolicy());
8911 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8912 isolate->default_microtask_queue()->PerformCheckpoint(this);
8913 }
8914
EnqueueMicrotask(Local<Function> v8_function)8915 void Isolate::EnqueueMicrotask(Local<Function> v8_function) {
8916 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8917 i::Handle<i::JSReceiver> function = Utils::OpenHandle(*v8_function);
8918 i::Handle<i::NativeContext> handler_context;
8919 if (!i::JSReceiver::GetContextForMicrotask(function).ToHandle(
8920 &handler_context))
8921 handler_context = isolate->native_context();
8922 MicrotaskQueue* microtask_queue = handler_context->microtask_queue();
8923 if (microtask_queue) microtask_queue->EnqueueMicrotask(this, v8_function);
8924 }
8925
EnqueueMicrotask(MicrotaskCallback callback,void * data)8926 void Isolate::EnqueueMicrotask(MicrotaskCallback callback, void* data) {
8927 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8928 isolate->default_microtask_queue()->EnqueueMicrotask(this, callback, data);
8929 }
8930
SetMicrotasksPolicy(MicrotasksPolicy policy)8931 void Isolate::SetMicrotasksPolicy(MicrotasksPolicy policy) {
8932 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8933 isolate->default_microtask_queue()->set_microtasks_policy(policy);
8934 }
8935
GetMicrotasksPolicy() const8936 MicrotasksPolicy Isolate::GetMicrotasksPolicy() const {
8937 i::Isolate* isolate =
8938 reinterpret_cast<i::Isolate*>(const_cast<Isolate*>(this));
8939 return isolate->default_microtask_queue()->microtasks_policy();
8940 }
8941
AddMicrotasksCompletedCallback(MicrotasksCompletedCallbackWithData callback,void * data)8942 void Isolate::AddMicrotasksCompletedCallback(
8943 MicrotasksCompletedCallbackWithData callback, void* data) {
8944 DCHECK(callback);
8945 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8946 isolate->default_microtask_queue()->AddMicrotasksCompletedCallback(callback,
8947 data);
8948 }
8949
RemoveMicrotasksCompletedCallback(MicrotasksCompletedCallbackWithData callback,void * data)8950 void Isolate::RemoveMicrotasksCompletedCallback(
8951 MicrotasksCompletedCallbackWithData callback, void* data) {
8952 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8953 isolate->default_microtask_queue()->RemoveMicrotasksCompletedCallback(
8954 callback, data);
8955 }
8956
SetUseCounterCallback(UseCounterCallback callback)8957 void Isolate::SetUseCounterCallback(UseCounterCallback callback) {
8958 reinterpret_cast<i::Isolate*>(this)->SetUseCounterCallback(callback);
8959 }
8960
SetCounterFunction(CounterLookupCallback callback)8961 void Isolate::SetCounterFunction(CounterLookupCallback callback) {
8962 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8963 isolate->counters()->ResetCounterFunction(callback);
8964 }
8965
SetCreateHistogramFunction(CreateHistogramCallback callback)8966 void Isolate::SetCreateHistogramFunction(CreateHistogramCallback callback) {
8967 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8968 isolate->counters()->ResetCreateHistogramFunction(callback);
8969 }
8970
SetAddHistogramSampleFunction(AddHistogramSampleCallback callback)8971 void Isolate::SetAddHistogramSampleFunction(
8972 AddHistogramSampleCallback callback) {
8973 reinterpret_cast<i::Isolate*>(this)
8974 ->counters()
8975 ->SetAddHistogramSampleFunction(callback);
8976 }
8977
SetMetricsRecorder(const std::shared_ptr<metrics::Recorder> & metrics_recorder)8978 void Isolate::SetMetricsRecorder(
8979 const std::shared_ptr<metrics::Recorder>& metrics_recorder) {
8980 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8981 isolate->metrics_recorder()->SetEmbedderRecorder(isolate, metrics_recorder);
8982 }
8983
SetAddCrashKeyCallback(AddCrashKeyCallback callback)8984 void Isolate::SetAddCrashKeyCallback(AddCrashKeyCallback callback) {
8985 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8986 isolate->SetAddCrashKeyCallback(callback);
8987 }
8988
IdleNotificationDeadline(double deadline_in_seconds)8989 bool Isolate::IdleNotificationDeadline(double deadline_in_seconds) {
8990 // Returning true tells the caller that it need not
8991 // continue to call IdleNotification.
8992 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8993 if (!i::FLAG_use_idle_notification) return true;
8994 return isolate->heap()->IdleNotification(deadline_in_seconds);
8995 }
8996
LowMemoryNotification()8997 void Isolate::LowMemoryNotification() {
8998 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8999 {
9000 i::NestedTimedHistogramScope idle_notification_scope(
9001 isolate->counters()->gc_low_memory_notification());
9002 TRACE_EVENT0("v8", "V8.GCLowMemoryNotification");
9003 isolate->heap()->CollectAllAvailableGarbage(
9004 i::GarbageCollectionReason::kLowMemoryNotification);
9005 }
9006 }
9007
ContextDisposedNotification(bool dependant_context)9008 int Isolate::ContextDisposedNotification(bool dependant_context) {
9009 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9010 #if V8_ENABLE_WEBASSEMBLY
9011 if (!dependant_context) {
9012 if (!isolate->context().is_null()) {
9013 // We left the current context, we can abort all WebAssembly compilations
9014 // of that context.
9015 // A handle scope for the native context.
9016 i::HandleScope handle_scope(isolate);
9017 i::wasm::GetWasmEngine()->DeleteCompileJobsOnContext(
9018 isolate->native_context());
9019 }
9020 }
9021 #endif // V8_ENABLE_WEBASSEMBLY
9022 // TODO(ahaas): move other non-heap activity out of the heap call.
9023 return isolate->heap()->NotifyContextDisposed(dependant_context);
9024 }
9025
IsolateInForegroundNotification()9026 void Isolate::IsolateInForegroundNotification() {
9027 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9028 return isolate->IsolateInForegroundNotification();
9029 }
9030
IsolateInBackgroundNotification()9031 void Isolate::IsolateInBackgroundNotification() {
9032 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9033 return isolate->IsolateInBackgroundNotification();
9034 }
9035
MemoryPressureNotification(MemoryPressureLevel level)9036 void Isolate::MemoryPressureNotification(MemoryPressureLevel level) {
9037 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9038 bool on_isolate_thread =
9039 v8::Locker::WasEverUsed()
9040 ? isolate->thread_manager()->IsLockedByCurrentThread()
9041 : i::ThreadId::Current() == isolate->thread_id();
9042 isolate->heap()->MemoryPressureNotification(level, on_isolate_thread);
9043 }
9044
ClearCachesForTesting()9045 void Isolate::ClearCachesForTesting() {
9046 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9047 isolate->AbortConcurrentOptimization(i::BlockingBehavior::kBlock);
9048 isolate->ClearSerializerData();
9049 }
9050
EnableMemorySavingsMode()9051 void Isolate::EnableMemorySavingsMode() {
9052 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9053 isolate->EnableMemorySavingsMode();
9054 }
9055
DisableMemorySavingsMode()9056 void Isolate::DisableMemorySavingsMode() {
9057 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9058 isolate->DisableMemorySavingsMode();
9059 }
9060
SetRAILMode(RAILMode rail_mode)9061 void Isolate::SetRAILMode(RAILMode rail_mode) {
9062 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9063 return isolate->SetRAILMode(rail_mode);
9064 }
9065
UpdateLoadStartTime()9066 void Isolate::UpdateLoadStartTime() {
9067 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9068 isolate->UpdateLoadStartTime();
9069 }
9070
IncreaseHeapLimitForDebugging()9071 void Isolate::IncreaseHeapLimitForDebugging() {
9072 // No-op.
9073 }
9074
RestoreOriginalHeapLimit()9075 void Isolate::RestoreOriginalHeapLimit() {
9076 // No-op.
9077 }
9078
IsHeapLimitIncreasedForDebugging()9079 bool Isolate::IsHeapLimitIncreasedForDebugging() { return false; }
9080
SetJitCodeEventHandler(JitCodeEventOptions options,JitCodeEventHandler event_handler)9081 void Isolate::SetJitCodeEventHandler(JitCodeEventOptions options,
9082 JitCodeEventHandler event_handler) {
9083 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9084 // Ensure that logging is initialized for our isolate.
9085 isolate->InitializeLoggingAndCounters();
9086 isolate->logger()->SetCodeEventHandler(options, event_handler);
9087 }
9088
SetStackLimit(uintptr_t stack_limit)9089 void Isolate::SetStackLimit(uintptr_t stack_limit) {
9090 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9091 CHECK(stack_limit);
9092 isolate->stack_guard()->SetStackLimit(stack_limit);
9093 }
9094
GetCodeRange(void ** start,size_t * length_in_bytes)9095 void Isolate::GetCodeRange(void** start, size_t* length_in_bytes) {
9096 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9097 const base::AddressRegion& code_region = isolate->heap()->code_region();
9098 *start = reinterpret_cast<void*>(code_region.begin());
9099 *length_in_bytes = code_region.size();
9100 }
9101
GetEmbeddedCodeRange(const void ** start,size_t * length_in_bytes)9102 void Isolate::GetEmbeddedCodeRange(const void** start,
9103 size_t* length_in_bytes) {
9104 // Note, we should return the embedded code rande from the .text section here.
9105 i::EmbeddedData d = i::EmbeddedData::FromBlob();
9106 *start = reinterpret_cast<const void*>(d.code());
9107 *length_in_bytes = d.code_size();
9108 }
9109
GetJSEntryStubs()9110 JSEntryStubs Isolate::GetJSEntryStubs() {
9111 JSEntryStubs entry_stubs;
9112
9113 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9114 std::array<std::pair<i::Builtin, JSEntryStub*>, 3> stubs = {
9115 {{i::Builtin::kJSEntry, &entry_stubs.js_entry_stub},
9116 {i::Builtin::kJSConstructEntry, &entry_stubs.js_construct_entry_stub},
9117 {i::Builtin::kJSRunMicrotasksEntry,
9118 &entry_stubs.js_run_microtasks_entry_stub}}};
9119 for (auto& pair : stubs) {
9120 i::Code js_entry = isolate->heap()->builtin(pair.first);
9121 pair.second->code.start =
9122 reinterpret_cast<const void*>(js_entry.InstructionStart());
9123 pair.second->code.length_in_bytes = js_entry.InstructionSize();
9124 }
9125
9126 return entry_stubs;
9127 }
9128
CopyCodePages(size_t capacity,MemoryRange * code_pages_out)9129 size_t Isolate::CopyCodePages(size_t capacity, MemoryRange* code_pages_out) {
9130 #if !defined(V8_TARGET_ARCH_64_BIT) && !defined(V8_TARGET_ARCH_ARM)
9131 // Not implemented on other platforms.
9132 UNREACHABLE();
9133 #else
9134
9135 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9136 std::vector<MemoryRange>* code_pages = isolate->GetCodePages();
9137
9138 DCHECK_NOT_NULL(code_pages);
9139
9140 // Copy as many elements into the output vector as we can. If the
9141 // caller-provided buffer is not big enough, we fill it, and the caller can
9142 // provide a bigger one next time. We do it this way because allocation is not
9143 // allowed in signal handlers.
9144 size_t limit = std::min(capacity, code_pages->size());
9145 for (size_t i = 0; i < limit; i++) {
9146 code_pages_out[i] = code_pages->at(i);
9147 }
9148 return code_pages->size();
9149 #endif
9150 }
9151
9152 #define CALLBACK_SETTER(ExternalName, Type, InternalName) \
9153 void Isolate::Set##ExternalName(Type callback) { \
9154 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); \
9155 isolate->set_##InternalName(callback); \
9156 }
9157
CALLBACK_SETTER(FatalErrorHandler,FatalErrorCallback,exception_behavior)9158 CALLBACK_SETTER(FatalErrorHandler, FatalErrorCallback, exception_behavior)
9159 CALLBACK_SETTER(OOMErrorHandler, OOMErrorCallback, oom_behavior)
9160 CALLBACK_SETTER(ModifyCodeGenerationFromStringsCallback,
9161 ModifyCodeGenerationFromStringsCallback2,
9162 modify_code_gen_callback2)
9163 CALLBACK_SETTER(AllowWasmCodeGenerationCallback,
9164 AllowWasmCodeGenerationCallback, allow_wasm_code_gen_callback)
9165
9166 CALLBACK_SETTER(WasmModuleCallback, ExtensionCallback, wasm_module_callback)
9167 CALLBACK_SETTER(WasmInstanceCallback, ExtensionCallback, wasm_instance_callback)
9168
9169 CALLBACK_SETTER(WasmStreamingCallback, WasmStreamingCallback,
9170 wasm_streaming_callback)
9171
9172 CALLBACK_SETTER(WasmLoadSourceMapCallback, WasmLoadSourceMapCallback,
9173 wasm_load_source_map_callback)
9174
9175 CALLBACK_SETTER(WasmSimdEnabledCallback, WasmSimdEnabledCallback,
9176 wasm_simd_enabled_callback)
9177
9178 CALLBACK_SETTER(WasmExceptionsEnabledCallback, WasmExceptionsEnabledCallback,
9179 wasm_exceptions_enabled_callback)
9180
9181 CALLBACK_SETTER(WasmDynamicTieringEnabledCallback,
9182 WasmDynamicTieringEnabledCallback,
9183 wasm_dynamic_tiering_enabled_callback)
9184
9185 CALLBACK_SETTER(SharedArrayBufferConstructorEnabledCallback,
9186 SharedArrayBufferConstructorEnabledCallback,
9187 sharedarraybuffer_constructor_enabled_callback)
9188
9189 void Isolate::InstallConditionalFeatures(Local<Context> context) {
9190 v8::HandleScope handle_scope(this);
9191 v8::Context::Scope context_scope(context);
9192 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9193 isolate->InstallConditionalFeatures(Utils::OpenHandle(*context));
9194 #if V8_ENABLE_WEBASSEMBLY
9195 if (i::FLAG_expose_wasm) {
9196 i::WasmJs::InstallConditionalFeatures(isolate, Utils::OpenHandle(*context));
9197 }
9198 #endif // V8_ENABLE_WEBASSEMBLY
9199 }
9200
AddNearHeapLimitCallback(v8::NearHeapLimitCallback callback,void * data)9201 void Isolate::AddNearHeapLimitCallback(v8::NearHeapLimitCallback callback,
9202 void* data) {
9203 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9204 isolate->heap()->AddNearHeapLimitCallback(callback, data);
9205 }
9206
RemoveNearHeapLimitCallback(v8::NearHeapLimitCallback callback,size_t heap_limit)9207 void Isolate::RemoveNearHeapLimitCallback(v8::NearHeapLimitCallback callback,
9208 size_t heap_limit) {
9209 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9210 isolate->heap()->RemoveNearHeapLimitCallback(callback, heap_limit);
9211 }
9212
AutomaticallyRestoreInitialHeapLimit(double threshold_percent)9213 void Isolate::AutomaticallyRestoreInitialHeapLimit(double threshold_percent) {
9214 DCHECK_GT(threshold_percent, 0.0);
9215 DCHECK_LT(threshold_percent, 1.0);
9216 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9217 isolate->heap()->AutomaticallyRestoreInitialHeapLimit(threshold_percent);
9218 }
9219
IsDead()9220 bool Isolate::IsDead() {
9221 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9222 return isolate->IsDead();
9223 }
9224
AddMessageListener(MessageCallback that,Local<Value> data)9225 bool Isolate::AddMessageListener(MessageCallback that, Local<Value> data) {
9226 return AddMessageListenerWithErrorLevel(that, kMessageError, data);
9227 }
9228
AddMessageListenerWithErrorLevel(MessageCallback that,int message_levels,Local<Value> data)9229 bool Isolate::AddMessageListenerWithErrorLevel(MessageCallback that,
9230 int message_levels,
9231 Local<Value> data) {
9232 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9233 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
9234 i::HandleScope scope(isolate);
9235 i::Handle<i::TemplateList> list = isolate->factory()->message_listeners();
9236 i::Handle<i::FixedArray> listener = isolate->factory()->NewFixedArray(3);
9237 i::Handle<i::Foreign> foreign =
9238 isolate->factory()->NewForeign(FUNCTION_ADDR(that));
9239 listener->set(0, *foreign);
9240 listener->set(1, data.IsEmpty() ? i::ReadOnlyRoots(isolate).undefined_value()
9241 : *Utils::OpenHandle(*data));
9242 listener->set(2, i::Smi::FromInt(message_levels));
9243 list = i::TemplateList::Add(isolate, list, listener);
9244 isolate->heap()->SetMessageListeners(*list);
9245 return true;
9246 }
9247
RemoveMessageListeners(MessageCallback that)9248 void Isolate::RemoveMessageListeners(MessageCallback that) {
9249 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9250 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
9251 i::HandleScope scope(isolate);
9252 i::DisallowGarbageCollection no_gc;
9253 i::TemplateList listeners = isolate->heap()->message_listeners();
9254 for (int i = 0; i < listeners.length(); i++) {
9255 if (listeners.get(i).IsUndefined(isolate)) continue; // skip deleted ones
9256 i::FixedArray listener = i::FixedArray::cast(listeners.get(i));
9257 i::Foreign callback_obj = i::Foreign::cast(listener.get(0));
9258 if (callback_obj.foreign_address() == FUNCTION_ADDR(that)) {
9259 listeners.set(i, i::ReadOnlyRoots(isolate).undefined_value());
9260 }
9261 }
9262 }
9263
SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback callback)9264 void Isolate::SetFailedAccessCheckCallbackFunction(
9265 FailedAccessCheckCallback callback) {
9266 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9267 isolate->SetFailedAccessCheckCallback(callback);
9268 }
9269
SetCaptureStackTraceForUncaughtExceptions(bool capture,int frame_limit,StackTrace::StackTraceOptions options)9270 void Isolate::SetCaptureStackTraceForUncaughtExceptions(
9271 bool capture, int frame_limit, StackTrace::StackTraceOptions options) {
9272 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9273 isolate->SetCaptureStackTraceForUncaughtExceptions(capture, frame_limit,
9274 options);
9275 }
9276
VisitExternalResources(ExternalResourceVisitor * visitor)9277 void Isolate::VisitExternalResources(ExternalResourceVisitor* visitor) {
9278 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9279 isolate->heap()->VisitExternalResources(visitor);
9280 }
9281
IsInUse()9282 bool Isolate::IsInUse() {
9283 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9284 return isolate->IsInUse();
9285 }
9286
VisitHandlesWithClassIds(PersistentHandleVisitor * visitor)9287 void Isolate::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) {
9288 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9289 i::DisallowGarbageCollection no_gc;
9290 isolate->global_handles()->IterateAllRootsWithClassIds(visitor);
9291 }
9292
VisitWeakHandles(PersistentHandleVisitor * visitor)9293 void Isolate::VisitWeakHandles(PersistentHandleVisitor* visitor) {
9294 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9295 i::DisallowGarbageCollection no_gc;
9296 isolate->global_handles()->IterateYoungWeakRootsWithClassIds(visitor);
9297 }
9298
SetAllowAtomicsWait(bool allow)9299 void Isolate::SetAllowAtomicsWait(bool allow) {
9300 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
9301 isolate->set_allow_atomics_wait(allow);
9302 }
9303
DateTimeConfigurationChangeNotification(TimeZoneDetection time_zone_detection)9304 void v8::Isolate::DateTimeConfigurationChangeNotification(
9305 TimeZoneDetection time_zone_detection) {
9306 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
9307 LOG_API(i_isolate, Isolate, DateTimeConfigurationChangeNotification);
9308 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
9309 i_isolate->date_cache()->ResetDateCache(
9310 static_cast<base::TimezoneCache::TimeZoneDetection>(time_zone_detection));
9311 #ifdef V8_INTL_SUPPORT
9312 i_isolate->clear_cached_icu_object(
9313 i::Isolate::ICUObjectCacheType::kDefaultSimpleDateFormat);
9314 i_isolate->clear_cached_icu_object(
9315 i::Isolate::ICUObjectCacheType::kDefaultSimpleDateFormatForTime);
9316 i_isolate->clear_cached_icu_object(
9317 i::Isolate::ICUObjectCacheType::kDefaultSimpleDateFormatForDate);
9318 #endif // V8_INTL_SUPPORT
9319 }
9320
LocaleConfigurationChangeNotification()9321 void v8::Isolate::LocaleConfigurationChangeNotification() {
9322 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
9323 LOG_API(i_isolate, Isolate, LocaleConfigurationChangeNotification);
9324 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
9325
9326 #ifdef V8_INTL_SUPPORT
9327 i_isolate->ResetDefaultLocale();
9328 i_isolate->clear_cached_icu_objects();
9329 #endif // V8_INTL_SUPPORT
9330 }
9331
IsCodeLike(v8::Isolate * isolate) const9332 bool v8::Object::IsCodeLike(v8::Isolate* isolate) const {
9333 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9334 LOG_API(i_isolate, Object, IsCodeLike);
9335 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
9336 i::HandleScope scope(i_isolate);
9337 return Utils::OpenHandle(this)->IsCodeLike(i_isolate);
9338 }
9339
9340 // static
New(Isolate * isolate,MicrotasksPolicy policy)9341 std::unique_ptr<MicrotaskQueue> MicrotaskQueue::New(Isolate* isolate,
9342 MicrotasksPolicy policy) {
9343 auto microtask_queue =
9344 i::MicrotaskQueue::New(reinterpret_cast<i::Isolate*>(isolate));
9345 microtask_queue->set_microtasks_policy(policy);
9346 std::unique_ptr<MicrotaskQueue> ret(std::move(microtask_queue));
9347 return ret;
9348 }
9349
MicrotasksScope(Isolate * isolate,MicrotasksScope::Type type)9350 MicrotasksScope::MicrotasksScope(Isolate* isolate, MicrotasksScope::Type type)
9351 : MicrotasksScope(isolate, nullptr, type) {}
9352
MicrotasksScope(Isolate * isolate,MicrotaskQueue * microtask_queue,MicrotasksScope::Type type)9353 MicrotasksScope::MicrotasksScope(Isolate* isolate,
9354 MicrotaskQueue* microtask_queue,
9355 MicrotasksScope::Type type)
9356 : isolate_(reinterpret_cast<i::Isolate*>(isolate)),
9357 microtask_queue_(microtask_queue
9358 ? static_cast<i::MicrotaskQueue*>(microtask_queue)
9359 : isolate_->default_microtask_queue()),
9360 run_(type == MicrotasksScope::kRunMicrotasks) {
9361 if (run_) microtask_queue_->IncrementMicrotasksScopeDepth();
9362 #ifdef DEBUG
9363 if (!run_) microtask_queue_->IncrementDebugMicrotasksScopeDepth();
9364 #endif
9365 }
9366
~MicrotasksScope()9367 MicrotasksScope::~MicrotasksScope() {
9368 if (run_) {
9369 microtask_queue_->DecrementMicrotasksScopeDepth();
9370 if (MicrotasksPolicy::kScoped == microtask_queue_->microtasks_policy() &&
9371 !isolate_->has_scheduled_exception()) {
9372 DCHECK_IMPLIES(isolate_->has_scheduled_exception(),
9373 isolate_->scheduled_exception() ==
9374 i::ReadOnlyRoots(isolate_).termination_exception());
9375 microtask_queue_->PerformCheckpoint(reinterpret_cast<Isolate*>(isolate_));
9376 }
9377 }
9378 #ifdef DEBUG
9379 if (!run_) microtask_queue_->DecrementDebugMicrotasksScopeDepth();
9380 #endif
9381 }
9382
9383 // static
PerformCheckpoint(Isolate * v8_isolate)9384 void MicrotasksScope::PerformCheckpoint(Isolate* v8_isolate) {
9385 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9386 auto* microtask_queue = isolate->default_microtask_queue();
9387 microtask_queue->PerformCheckpoint(v8_isolate);
9388 }
9389
9390 // static
GetCurrentDepth(Isolate * v8_isolate)9391 int MicrotasksScope::GetCurrentDepth(Isolate* v8_isolate) {
9392 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9393 auto* microtask_queue = isolate->default_microtask_queue();
9394 return microtask_queue->GetMicrotasksScopeDepth();
9395 }
9396
9397 // static
IsRunningMicrotasks(Isolate * v8_isolate)9398 bool MicrotasksScope::IsRunningMicrotasks(Isolate* v8_isolate) {
9399 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9400 auto* microtask_queue = isolate->default_microtask_queue();
9401 return microtask_queue->IsRunningMicrotasks();
9402 }
9403
Utf8Value(v8::Isolate * isolate,v8::Local<v8::Value> obj)9404 String::Utf8Value::Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> obj)
9405 : str_(nullptr), length_(0) {
9406 if (obj.IsEmpty()) return;
9407 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9408 ENTER_V8_DO_NOT_USE(i_isolate);
9409 i::HandleScope scope(i_isolate);
9410 Local<Context> context = isolate->GetCurrentContext();
9411 TryCatch try_catch(isolate);
9412 Local<String> str;
9413 if (!obj->ToString(context).ToLocal(&str)) return;
9414 length_ = str->Utf8Length(isolate);
9415 str_ = i::NewArray<char>(length_ + 1);
9416 str->WriteUtf8(isolate, str_);
9417 }
9418
~Utf8Value()9419 String::Utf8Value::~Utf8Value() { i::DeleteArray(str_); }
9420
Value(v8::Isolate * isolate,v8::Local<v8::Value> obj)9421 String::Value::Value(v8::Isolate* isolate, v8::Local<v8::Value> obj)
9422 : str_(nullptr), length_(0) {
9423 if (obj.IsEmpty()) return;
9424 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9425 ENTER_V8_DO_NOT_USE(i_isolate);
9426 i::HandleScope scope(i_isolate);
9427 Local<Context> context = isolate->GetCurrentContext();
9428 TryCatch try_catch(isolate);
9429 Local<String> str;
9430 if (!obj->ToString(context).ToLocal(&str)) return;
9431 length_ = str->Length();
9432 str_ = i::NewArray<uint16_t>(length_ + 1);
9433 str->Write(isolate, str_);
9434 }
9435
~Value()9436 String::Value::~Value() { i::DeleteArray(str_); }
9437
9438 #define DEFINE_ERROR(NAME, name) \
9439 Local<Value> Exception::NAME(v8::Local<v8::String> raw_message) { \
9440 i::Isolate* isolate = i::Isolate::Current(); \
9441 LOG_API(isolate, NAME, New); \
9442 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \
9443 i::Object error; \
9444 { \
9445 i::HandleScope scope(isolate); \
9446 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); \
9447 i::Handle<i::JSFunction> constructor = isolate->name##_function(); \
9448 error = *isolate->factory()->NewError(constructor, message); \
9449 } \
9450 i::Handle<i::Object> result(error, isolate); \
9451 return Utils::ToLocal(result); \
9452 }
9453
DEFINE_ERROR(RangeError,range_error)9454 DEFINE_ERROR(RangeError, range_error)
9455 DEFINE_ERROR(ReferenceError, reference_error)
9456 DEFINE_ERROR(SyntaxError, syntax_error)
9457 DEFINE_ERROR(TypeError, type_error)
9458 DEFINE_ERROR(WasmCompileError, wasm_compile_error)
9459 DEFINE_ERROR(WasmLinkError, wasm_link_error)
9460 DEFINE_ERROR(WasmRuntimeError, wasm_runtime_error)
9461 DEFINE_ERROR(Error, error)
9462
9463 #undef DEFINE_ERROR
9464
9465 Local<Message> Exception::CreateMessage(Isolate* isolate,
9466 Local<Value> exception) {
9467 i::Handle<i::Object> obj = Utils::OpenHandle(*exception);
9468 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9469 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
9470 i::HandleScope scope(i_isolate);
9471 return Utils::MessageToLocal(
9472 scope.CloseAndEscape(i_isolate->CreateMessage(obj, nullptr)));
9473 }
9474
GetStackTrace(Local<Value> exception)9475 Local<StackTrace> Exception::GetStackTrace(Local<Value> exception) {
9476 i::Handle<i::Object> obj = Utils::OpenHandle(*exception);
9477 if (!obj->IsJSObject()) return Local<StackTrace>();
9478 i::Handle<i::JSObject> js_obj = i::Handle<i::JSObject>::cast(obj);
9479 i::Isolate* isolate = js_obj->GetIsolate();
9480 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
9481 return Utils::StackTraceToLocal(isolate->GetDetailedStackTrace(js_obj));
9482 }
9483
PreviewEntries(bool * is_key_value)9484 v8::MaybeLocal<v8::Array> v8::Object::PreviewEntries(bool* is_key_value) {
9485 if (IsMap()) {
9486 *is_key_value = true;
9487 return Map::Cast(this)->AsArray();
9488 }
9489 if (IsSet()) {
9490 *is_key_value = false;
9491 return Set::Cast(this)->AsArray();
9492 }
9493
9494 i::Handle<i::JSReceiver> object = Utils::OpenHandle(this);
9495 i::Isolate* isolate = object->GetIsolate();
9496 Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
9497 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
9498 if (object->IsJSWeakCollection()) {
9499 *is_key_value = object->IsJSWeakMap();
9500 return Utils::ToLocal(i::JSWeakCollection::GetEntries(
9501 i::Handle<i::JSWeakCollection>::cast(object), 0));
9502 }
9503 if (object->IsJSMapIterator()) {
9504 i::Handle<i::JSMapIterator> it = i::Handle<i::JSMapIterator>::cast(object);
9505 MapAsArrayKind const kind =
9506 static_cast<MapAsArrayKind>(it->map().instance_type());
9507 *is_key_value = kind == MapAsArrayKind::kEntries;
9508 if (!it->HasMore()) return v8::Array::New(v8_isolate);
9509 return Utils::ToLocal(
9510 MapAsArray(isolate, it->table(), i::Smi::ToInt(it->index()), kind));
9511 }
9512 if (object->IsJSSetIterator()) {
9513 i::Handle<i::JSSetIterator> it = i::Handle<i::JSSetIterator>::cast(object);
9514 SetAsArrayKind const kind =
9515 static_cast<SetAsArrayKind>(it->map().instance_type());
9516 *is_key_value = kind == SetAsArrayKind::kEntries;
9517 if (!it->HasMore()) return v8::Array::New(v8_isolate);
9518 return Utils::ToLocal(
9519 SetAsArray(isolate, it->table(), i::Smi::ToInt(it->index()), kind));
9520 }
9521 return v8::MaybeLocal<v8::Array>();
9522 }
9523
GetFunctionName() const9524 Local<String> CpuProfileNode::GetFunctionName() const {
9525 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9526 i::Isolate* isolate = node->isolate();
9527 const i::CodeEntry* entry = node->entry();
9528 i::Handle<i::String> name =
9529 isolate->factory()->InternalizeUtf8String(entry->name());
9530 return ToApiHandle<String>(name);
9531 }
9532
GetFunctionNameStr() const9533 const char* CpuProfileNode::GetFunctionNameStr() const {
9534 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9535 return node->entry()->name();
9536 }
9537
GetScriptId() const9538 int CpuProfileNode::GetScriptId() const {
9539 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9540 const i::CodeEntry* entry = node->entry();
9541 return entry->script_id();
9542 }
9543
GetScriptResourceName() const9544 Local<String> CpuProfileNode::GetScriptResourceName() const {
9545 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9546 i::Isolate* isolate = node->isolate();
9547 return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
9548 node->entry()->resource_name()));
9549 }
9550
GetScriptResourceNameStr() const9551 const char* CpuProfileNode::GetScriptResourceNameStr() const {
9552 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9553 return node->entry()->resource_name();
9554 }
9555
IsScriptSharedCrossOrigin() const9556 bool CpuProfileNode::IsScriptSharedCrossOrigin() const {
9557 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9558 return node->entry()->is_shared_cross_origin();
9559 }
9560
GetLineNumber() const9561 int CpuProfileNode::GetLineNumber() const {
9562 return reinterpret_cast<const i::ProfileNode*>(this)->line_number();
9563 }
9564
GetColumnNumber() const9565 int CpuProfileNode::GetColumnNumber() const {
9566 return reinterpret_cast<const i::ProfileNode*>(this)
9567 ->entry()
9568 ->column_number();
9569 }
9570
GetHitLineCount() const9571 unsigned int CpuProfileNode::GetHitLineCount() const {
9572 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9573 return node->GetHitLineCount();
9574 }
9575
GetLineTicks(LineTick * entries,unsigned int length) const9576 bool CpuProfileNode::GetLineTicks(LineTick* entries,
9577 unsigned int length) const {
9578 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9579 return node->GetLineTicks(entries, length);
9580 }
9581
GetBailoutReason() const9582 const char* CpuProfileNode::GetBailoutReason() const {
9583 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9584 return node->entry()->bailout_reason();
9585 }
9586
GetHitCount() const9587 unsigned CpuProfileNode::GetHitCount() const {
9588 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
9589 }
9590
GetNodeId() const9591 unsigned CpuProfileNode::GetNodeId() const {
9592 return reinterpret_cast<const i::ProfileNode*>(this)->id();
9593 }
9594
GetSourceType() const9595 CpuProfileNode::SourceType CpuProfileNode::GetSourceType() const {
9596 return reinterpret_cast<const i::ProfileNode*>(this)->source_type();
9597 }
9598
GetChildrenCount() const9599 int CpuProfileNode::GetChildrenCount() const {
9600 return static_cast<int>(
9601 reinterpret_cast<const i::ProfileNode*>(this)->children()->size());
9602 }
9603
GetChild(int index) const9604 const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
9605 const i::ProfileNode* child =
9606 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
9607 return reinterpret_cast<const CpuProfileNode*>(child);
9608 }
9609
GetParent() const9610 const CpuProfileNode* CpuProfileNode::GetParent() const {
9611 const i::ProfileNode* parent =
9612 reinterpret_cast<const i::ProfileNode*>(this)->parent();
9613 return reinterpret_cast<const CpuProfileNode*>(parent);
9614 }
9615
GetDeoptInfos() const9616 const std::vector<CpuProfileDeoptInfo>& CpuProfileNode::GetDeoptInfos() const {
9617 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9618 return node->deopt_infos();
9619 }
9620
Delete()9621 void CpuProfile::Delete() {
9622 i::CpuProfile* profile = reinterpret_cast<i::CpuProfile*>(this);
9623 i::CpuProfiler* profiler = profile->cpu_profiler();
9624 DCHECK_NOT_NULL(profiler);
9625 profiler->DeleteProfile(profile);
9626 }
9627
GetTitle() const9628 Local<String> CpuProfile::GetTitle() const {
9629 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9630 i::Isolate* isolate = profile->top_down()->isolate();
9631 return ToApiHandle<String>(
9632 isolate->factory()->InternalizeUtf8String(profile->title()));
9633 }
9634
GetTopDownRoot() const9635 const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
9636 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9637 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
9638 }
9639
GetSample(int index) const9640 const CpuProfileNode* CpuProfile::GetSample(int index) const {
9641 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9642 return reinterpret_cast<const CpuProfileNode*>(profile->sample(index).node);
9643 }
9644
9645 const int CpuProfileNode::kNoLineNumberInfo;
9646 const int CpuProfileNode::kNoColumnNumberInfo;
9647
GetSampleTimestamp(int index) const9648 int64_t CpuProfile::GetSampleTimestamp(int index) const {
9649 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9650 return profile->sample(index).timestamp.since_origin().InMicroseconds();
9651 }
9652
GetStartTime() const9653 int64_t CpuProfile::GetStartTime() const {
9654 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9655 return profile->start_time().since_origin().InMicroseconds();
9656 }
9657
GetEndTime() const9658 int64_t CpuProfile::GetEndTime() const {
9659 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9660 return profile->end_time().since_origin().InMicroseconds();
9661 }
9662
GetSamplesCount() const9663 int CpuProfile::GetSamplesCount() const {
9664 return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
9665 }
9666
New(Isolate * isolate,CpuProfilingNamingMode naming_mode,CpuProfilingLoggingMode logging_mode)9667 CpuProfiler* CpuProfiler::New(Isolate* isolate,
9668 CpuProfilingNamingMode naming_mode,
9669 CpuProfilingLoggingMode logging_mode) {
9670 return reinterpret_cast<CpuProfiler*>(new i::CpuProfiler(
9671 reinterpret_cast<i::Isolate*>(isolate), naming_mode, logging_mode));
9672 }
9673
CpuProfilingOptions(CpuProfilingMode mode,unsigned max_samples,int sampling_interval_us,MaybeLocal<Context> filter_context)9674 CpuProfilingOptions::CpuProfilingOptions(CpuProfilingMode mode,
9675 unsigned max_samples,
9676 int sampling_interval_us,
9677 MaybeLocal<Context> filter_context)
9678 : mode_(mode),
9679 max_samples_(max_samples),
9680 sampling_interval_us_(sampling_interval_us) {
9681 if (!filter_context.IsEmpty()) {
9682 Local<Context> local_filter_context = filter_context.ToLocalChecked();
9683 filter_context_.Reset(local_filter_context->GetIsolate(),
9684 local_filter_context);
9685 filter_context_.SetWeak();
9686 }
9687 }
9688
raw_filter_context() const9689 void* CpuProfilingOptions::raw_filter_context() const {
9690 return reinterpret_cast<void*>(
9691 i::Context::cast(*Utils::OpenPersistent(filter_context_))
9692 .native_context()
9693 .address());
9694 }
9695
Dispose()9696 void CpuProfiler::Dispose() { delete reinterpret_cast<i::CpuProfiler*>(this); }
9697
9698 // static
CollectSample(Isolate * isolate)9699 void CpuProfiler::CollectSample(Isolate* isolate) {
9700 i::CpuProfiler::CollectSample(reinterpret_cast<i::Isolate*>(isolate));
9701 }
9702
SetSamplingInterval(int us)9703 void CpuProfiler::SetSamplingInterval(int us) {
9704 DCHECK_GE(us, 0);
9705 return reinterpret_cast<i::CpuProfiler*>(this)->set_sampling_interval(
9706 base::TimeDelta::FromMicroseconds(us));
9707 }
9708
SetUsePreciseSampling(bool use_precise_sampling)9709 void CpuProfiler::SetUsePreciseSampling(bool use_precise_sampling) {
9710 reinterpret_cast<i::CpuProfiler*>(this)->set_use_precise_sampling(
9711 use_precise_sampling);
9712 }
9713
StartProfiling(Local<String> title,CpuProfilingOptions options,std::unique_ptr<DiscardedSamplesDelegate> delegate)9714 CpuProfilingStatus CpuProfiler::StartProfiling(
9715 Local<String> title, CpuProfilingOptions options,
9716 std::unique_ptr<DiscardedSamplesDelegate> delegate) {
9717 return reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
9718 *Utils::OpenHandle(*title), options, std::move(delegate));
9719 }
9720
StartProfiling(Local<String> title,bool record_samples)9721 CpuProfilingStatus CpuProfiler::StartProfiling(Local<String> title,
9722 bool record_samples) {
9723 CpuProfilingOptions options(
9724 kLeafNodeLineNumbers,
9725 record_samples ? CpuProfilingOptions::kNoSampleLimit : 0);
9726 return reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
9727 *Utils::OpenHandle(*title), options);
9728 }
9729
StartProfiling(Local<String> title,CpuProfilingMode mode,bool record_samples,unsigned max_samples)9730 CpuProfilingStatus CpuProfiler::StartProfiling(Local<String> title,
9731 CpuProfilingMode mode,
9732 bool record_samples,
9733 unsigned max_samples) {
9734 CpuProfilingOptions options(mode, record_samples ? max_samples : 0);
9735 return reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
9736 *Utils::OpenHandle(*title), options);
9737 }
9738
StopProfiling(Local<String> title)9739 CpuProfile* CpuProfiler::StopProfiling(Local<String> title) {
9740 return reinterpret_cast<CpuProfile*>(
9741 reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
9742 *Utils::OpenHandle(*title)));
9743 }
9744
UseDetailedSourcePositionsForProfiling(Isolate * isolate)9745 void CpuProfiler::UseDetailedSourcePositionsForProfiling(Isolate* isolate) {
9746 reinterpret_cast<i::Isolate*>(isolate)
9747 ->SetDetailedSourcePositionsForProfiling(true);
9748 }
9749
GetCodeStartAddress()9750 uintptr_t CodeEvent::GetCodeStartAddress() {
9751 return reinterpret_cast<i::CodeEvent*>(this)->code_start_address;
9752 }
9753
GetCodeSize()9754 size_t CodeEvent::GetCodeSize() {
9755 return reinterpret_cast<i::CodeEvent*>(this)->code_size;
9756 }
9757
GetFunctionName()9758 Local<String> CodeEvent::GetFunctionName() {
9759 return ToApiHandle<String>(
9760 reinterpret_cast<i::CodeEvent*>(this)->function_name);
9761 }
9762
GetScriptName()9763 Local<String> CodeEvent::GetScriptName() {
9764 return ToApiHandle<String>(
9765 reinterpret_cast<i::CodeEvent*>(this)->script_name);
9766 }
9767
GetScriptLine()9768 int CodeEvent::GetScriptLine() {
9769 return reinterpret_cast<i::CodeEvent*>(this)->script_line;
9770 }
9771
GetScriptColumn()9772 int CodeEvent::GetScriptColumn() {
9773 return reinterpret_cast<i::CodeEvent*>(this)->script_column;
9774 }
9775
GetCodeType()9776 CodeEventType CodeEvent::GetCodeType() {
9777 return reinterpret_cast<i::CodeEvent*>(this)->code_type;
9778 }
9779
GetComment()9780 const char* CodeEvent::GetComment() {
9781 return reinterpret_cast<i::CodeEvent*>(this)->comment;
9782 }
9783
GetPreviousCodeStartAddress()9784 uintptr_t CodeEvent::GetPreviousCodeStartAddress() {
9785 return reinterpret_cast<i::CodeEvent*>(this)->previous_code_start_address;
9786 }
9787
GetCodeEventTypeName(CodeEventType code_event_type)9788 const char* CodeEvent::GetCodeEventTypeName(CodeEventType code_event_type) {
9789 switch (code_event_type) {
9790 case kUnknownType:
9791 return "Unknown";
9792 #define V(Name) \
9793 case k##Name##Type: \
9794 return #Name;
9795 CODE_EVENTS_LIST(V)
9796 #undef V
9797 }
9798 // The execution should never pass here
9799 UNREACHABLE();
9800 }
9801
CodeEventHandler(Isolate * isolate)9802 CodeEventHandler::CodeEventHandler(Isolate* isolate) {
9803 internal_listener_ =
9804 new i::ExternalCodeEventListener(reinterpret_cast<i::Isolate*>(isolate));
9805 }
9806
~CodeEventHandler()9807 CodeEventHandler::~CodeEventHandler() {
9808 delete reinterpret_cast<i::ExternalCodeEventListener*>(internal_listener_);
9809 }
9810
Enable()9811 void CodeEventHandler::Enable() {
9812 reinterpret_cast<i::ExternalCodeEventListener*>(internal_listener_)
9813 ->StartListening(this);
9814 }
9815
Disable()9816 void CodeEventHandler::Disable() {
9817 reinterpret_cast<i::ExternalCodeEventListener*>(internal_listener_)
9818 ->StopListening();
9819 }
9820
ToInternal(const HeapGraphEdge * edge)9821 static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
9822 return const_cast<i::HeapGraphEdge*>(
9823 reinterpret_cast<const i::HeapGraphEdge*>(edge));
9824 }
9825
GetType() const9826 HeapGraphEdge::Type HeapGraphEdge::GetType() const {
9827 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
9828 }
9829
GetName() const9830 Local<Value> HeapGraphEdge::GetName() const {
9831 i::HeapGraphEdge* edge = ToInternal(this);
9832 i::Isolate* isolate = edge->isolate();
9833 switch (edge->type()) {
9834 case i::HeapGraphEdge::kContextVariable:
9835 case i::HeapGraphEdge::kInternal:
9836 case i::HeapGraphEdge::kProperty:
9837 case i::HeapGraphEdge::kShortcut:
9838 case i::HeapGraphEdge::kWeak:
9839 return ToApiHandle<String>(
9840 isolate->factory()->InternalizeUtf8String(edge->name()));
9841 case i::HeapGraphEdge::kElement:
9842 case i::HeapGraphEdge::kHidden:
9843 return ToApiHandle<Number>(
9844 isolate->factory()->NewNumberFromInt(edge->index()));
9845 default:
9846 UNREACHABLE();
9847 }
9848 }
9849
GetFromNode() const9850 const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
9851 const i::HeapEntry* from = ToInternal(this)->from();
9852 return reinterpret_cast<const HeapGraphNode*>(from);
9853 }
9854
GetToNode() const9855 const HeapGraphNode* HeapGraphEdge::GetToNode() const {
9856 const i::HeapEntry* to = ToInternal(this)->to();
9857 return reinterpret_cast<const HeapGraphNode*>(to);
9858 }
9859
ToInternal(const HeapGraphNode * entry)9860 static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
9861 return const_cast<i::HeapEntry*>(
9862 reinterpret_cast<const i::HeapEntry*>(entry));
9863 }
9864
GetType() const9865 HeapGraphNode::Type HeapGraphNode::GetType() const {
9866 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
9867 }
9868
GetName() const9869 Local<String> HeapGraphNode::GetName() const {
9870 i::Isolate* isolate = ToInternal(this)->isolate();
9871 return ToApiHandle<String>(
9872 isolate->factory()->InternalizeUtf8String(ToInternal(this)->name()));
9873 }
9874
GetId() const9875 SnapshotObjectId HeapGraphNode::GetId() const { return ToInternal(this)->id(); }
9876
GetShallowSize() const9877 size_t HeapGraphNode::GetShallowSize() const {
9878 return ToInternal(this)->self_size();
9879 }
9880
GetChildrenCount() const9881 int HeapGraphNode::GetChildrenCount() const {
9882 return ToInternal(this)->children_count();
9883 }
9884
GetChild(int index) const9885 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
9886 return reinterpret_cast<const HeapGraphEdge*>(ToInternal(this)->child(index));
9887 }
9888
ToInternal(const HeapSnapshot * snapshot)9889 static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
9890 return const_cast<i::HeapSnapshot*>(
9891 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
9892 }
9893
Delete()9894 void HeapSnapshot::Delete() {
9895 i::Isolate* isolate = ToInternal(this)->profiler()->isolate();
9896 if (isolate->heap_profiler()->GetSnapshotsCount() > 1 ||
9897 isolate->heap_profiler()->IsTakingSnapshot()) {
9898 ToInternal(this)->Delete();
9899 } else {
9900 // If this is the last snapshot, clean up all accessory data as well.
9901 isolate->heap_profiler()->DeleteAllSnapshots();
9902 }
9903 }
9904
GetRoot() const9905 const HeapGraphNode* HeapSnapshot::GetRoot() const {
9906 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
9907 }
9908
GetNodeById(SnapshotObjectId id) const9909 const HeapGraphNode* HeapSnapshot::GetNodeById(SnapshotObjectId id) const {
9910 return reinterpret_cast<const HeapGraphNode*>(
9911 ToInternal(this)->GetEntryById(id));
9912 }
9913
GetNodesCount() const9914 int HeapSnapshot::GetNodesCount() const {
9915 return static_cast<int>(ToInternal(this)->entries().size());
9916 }
9917
GetNode(int index) const9918 const HeapGraphNode* HeapSnapshot::GetNode(int index) const {
9919 return reinterpret_cast<const HeapGraphNode*>(
9920 &ToInternal(this)->entries().at(index));
9921 }
9922
GetMaxSnapshotJSObjectId() const9923 SnapshotObjectId HeapSnapshot::GetMaxSnapshotJSObjectId() const {
9924 return ToInternal(this)->max_snapshot_js_object_id();
9925 }
9926
Serialize(OutputStream * stream,HeapSnapshot::SerializationFormat format) const9927 void HeapSnapshot::Serialize(OutputStream* stream,
9928 HeapSnapshot::SerializationFormat format) const {
9929 Utils::ApiCheck(format == kJSON, "v8::HeapSnapshot::Serialize",
9930 "Unknown serialization format");
9931 Utils::ApiCheck(stream->GetChunkSize() > 0, "v8::HeapSnapshot::Serialize",
9932 "Invalid stream chunk size");
9933 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
9934 serializer.Serialize(stream);
9935 }
9936
9937 // static
9938 STATIC_CONST_MEMBER_DEFINITION const SnapshotObjectId
9939 HeapProfiler::kUnknownObjectId;
9940
GetSnapshotCount()9941 int HeapProfiler::GetSnapshotCount() {
9942 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotsCount();
9943 }
9944
GetHeapSnapshot(int index)9945 const HeapSnapshot* HeapProfiler::GetHeapSnapshot(int index) {
9946 return reinterpret_cast<const HeapSnapshot*>(
9947 reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshot(index));
9948 }
9949
GetObjectId(Local<Value> value)9950 SnapshotObjectId HeapProfiler::GetObjectId(Local<Value> value) {
9951 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
9952 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj);
9953 }
9954
GetObjectId(NativeObject value)9955 SnapshotObjectId HeapProfiler::GetObjectId(NativeObject value) {
9956 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(value);
9957 }
9958
FindObjectById(SnapshotObjectId id)9959 Local<Value> HeapProfiler::FindObjectById(SnapshotObjectId id) {
9960 i::Handle<i::Object> obj =
9961 reinterpret_cast<i::HeapProfiler*>(this)->FindHeapObjectById(id);
9962 if (obj.is_null()) return Local<Value>();
9963 return Utils::ToLocal(obj);
9964 }
9965
ClearObjectIds()9966 void HeapProfiler::ClearObjectIds() {
9967 reinterpret_cast<i::HeapProfiler*>(this)->ClearHeapObjectMap();
9968 }
9969
TakeHeapSnapshot(ActivityControl * control,ObjectNameResolver * resolver,bool treat_global_objects_as_roots,bool capture_numeric_value)9970 const HeapSnapshot* HeapProfiler::TakeHeapSnapshot(
9971 ActivityControl* control, ObjectNameResolver* resolver,
9972 bool treat_global_objects_as_roots, bool capture_numeric_value) {
9973 return reinterpret_cast<const HeapSnapshot*>(
9974 reinterpret_cast<i::HeapProfiler*>(this)->TakeSnapshot(
9975 control, resolver, treat_global_objects_as_roots,
9976 capture_numeric_value));
9977 }
9978
StartTrackingHeapObjects(bool track_allocations)9979 void HeapProfiler::StartTrackingHeapObjects(bool track_allocations) {
9980 reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTracking(
9981 track_allocations);
9982 }
9983
StopTrackingHeapObjects()9984 void HeapProfiler::StopTrackingHeapObjects() {
9985 reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTracking();
9986 }
9987
GetHeapStats(OutputStream * stream,int64_t * timestamp_us)9988 SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream,
9989 int64_t* timestamp_us) {
9990 i::HeapProfiler* heap_profiler = reinterpret_cast<i::HeapProfiler*>(this);
9991 return heap_profiler->PushHeapObjectsStats(stream, timestamp_us);
9992 }
9993
StartSamplingHeapProfiler(uint64_t sample_interval,int stack_depth,SamplingFlags flags)9994 bool HeapProfiler::StartSamplingHeapProfiler(uint64_t sample_interval,
9995 int stack_depth,
9996 SamplingFlags flags) {
9997 return reinterpret_cast<i::HeapProfiler*>(this)->StartSamplingHeapProfiler(
9998 sample_interval, stack_depth, flags);
9999 }
10000
StopSamplingHeapProfiler()10001 void HeapProfiler::StopSamplingHeapProfiler() {
10002 reinterpret_cast<i::HeapProfiler*>(this)->StopSamplingHeapProfiler();
10003 }
10004
GetAllocationProfile()10005 AllocationProfile* HeapProfiler::GetAllocationProfile() {
10006 return reinterpret_cast<i::HeapProfiler*>(this)->GetAllocationProfile();
10007 }
10008
DeleteAllHeapSnapshots()10009 void HeapProfiler::DeleteAllHeapSnapshots() {
10010 reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots();
10011 }
10012
AddBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback,void * data)10013 void HeapProfiler::AddBuildEmbedderGraphCallback(
10014 BuildEmbedderGraphCallback callback, void* data) {
10015 reinterpret_cast<i::HeapProfiler*>(this)->AddBuildEmbedderGraphCallback(
10016 callback, data);
10017 }
10018
RemoveBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback,void * data)10019 void HeapProfiler::RemoveBuildEmbedderGraphCallback(
10020 BuildEmbedderGraphCallback callback, void* data) {
10021 reinterpret_cast<i::HeapProfiler*>(this)->RemoveBuildEmbedderGraphCallback(
10022 callback, data);
10023 }
10024
SetGetDetachednessCallback(GetDetachednessCallback callback,void * data)10025 void HeapProfiler::SetGetDetachednessCallback(GetDetachednessCallback callback,
10026 void* data) {
10027 reinterpret_cast<i::HeapProfiler*>(this)->SetGetDetachednessCallback(callback,
10028 data);
10029 }
10030
SetStackStart(void * stack_start)10031 void EmbedderHeapTracer::SetStackStart(void* stack_start) {
10032 CHECK(isolate_);
10033 reinterpret_cast<i::Isolate*>(isolate_)->global_handles()->SetStackStart(
10034 stack_start);
10035 }
10036
NotifyEmptyEmbedderStack()10037 void EmbedderHeapTracer::NotifyEmptyEmbedderStack() {
10038 CHECK(isolate_);
10039 reinterpret_cast<i::Isolate*>(isolate_)
10040 ->heap()
10041 ->local_embedder_heap_tracer()
10042 ->NotifyEmptyEmbedderStack();
10043 }
10044
FinalizeTracing()10045 void EmbedderHeapTracer::FinalizeTracing() {
10046 if (isolate_) {
10047 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(isolate_);
10048 if (isolate->heap()->incremental_marking()->IsMarking()) {
10049 isolate->heap()->FinalizeIncrementalMarkingAtomically(
10050 i::GarbageCollectionReason::kExternalFinalize);
10051 }
10052 }
10053 }
10054
GarbageCollectionForTesting(EmbedderStackState stack_state)10055 void EmbedderHeapTracer::GarbageCollectionForTesting(
10056 EmbedderStackState stack_state) {
10057 CHECK(isolate_);
10058 Utils::ApiCheck(i::FLAG_expose_gc,
10059 "v8::EmbedderHeapTracer::GarbageCollectionForTesting",
10060 "Must use --expose-gc");
10061 i::Heap* const heap = reinterpret_cast<i::Isolate*>(isolate_)->heap();
10062 heap->SetEmbedderStackStateForNextFinalization(stack_state);
10063 heap->PreciseCollectAllGarbage(i::Heap::kNoGCFlags,
10064 i::GarbageCollectionReason::kTesting,
10065 kGCCallbackFlagForced);
10066 }
10067
IncreaseAllocatedSize(size_t bytes)10068 void EmbedderHeapTracer::IncreaseAllocatedSize(size_t bytes) {
10069 if (isolate_) {
10070 i::LocalEmbedderHeapTracer* const tracer =
10071 reinterpret_cast<i::Isolate*>(isolate_)
10072 ->heap()
10073 ->local_embedder_heap_tracer();
10074 DCHECK_NOT_NULL(tracer);
10075 tracer->IncreaseAllocatedSize(bytes);
10076 }
10077 }
10078
DecreaseAllocatedSize(size_t bytes)10079 void EmbedderHeapTracer::DecreaseAllocatedSize(size_t bytes) {
10080 if (isolate_) {
10081 i::LocalEmbedderHeapTracer* const tracer =
10082 reinterpret_cast<i::Isolate*>(isolate_)
10083 ->heap()
10084 ->local_embedder_heap_tracer();
10085 DCHECK_NOT_NULL(tracer);
10086 tracer->DecreaseAllocatedSize(bytes);
10087 }
10088 }
10089
RegisterEmbedderReference(const BasicTracedReference<v8::Data> & ref)10090 void EmbedderHeapTracer::RegisterEmbedderReference(
10091 const BasicTracedReference<v8::Data>& ref) {
10092 if (ref.IsEmpty()) return;
10093
10094 i::Heap* const heap = reinterpret_cast<i::Isolate*>(isolate_)->heap();
10095 heap->RegisterExternallyReferencedObject(
10096 reinterpret_cast<i::Address*>(ref.val_));
10097 }
10098
IterateTracedGlobalHandles(TracedGlobalHandleVisitor * visitor)10099 void EmbedderHeapTracer::IterateTracedGlobalHandles(
10100 TracedGlobalHandleVisitor* visitor) {
10101 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(isolate_);
10102 i::DisallowGarbageCollection no_gc;
10103 isolate->global_handles()->IterateTracedNodes(visitor);
10104 }
10105
IsRootForNonTracingGC(const v8::TracedReference<v8::Value> & handle)10106 bool EmbedderHeapTracer::IsRootForNonTracingGC(
10107 const v8::TracedReference<v8::Value>& handle) {
10108 return true;
10109 }
10110
IsRootForNonTracingGC(const v8::TracedGlobal<v8::Value> & handle)10111 bool EmbedderHeapTracer::IsRootForNonTracingGC(
10112 const v8::TracedGlobal<v8::Value>& handle) {
10113 return true;
10114 }
10115
ResetHandleInNonTracingGC(const v8::TracedReference<v8::Value> & handle)10116 void EmbedderHeapTracer::ResetHandleInNonTracingGC(
10117 const v8::TracedReference<v8::Value>& handle) {
10118 UNREACHABLE();
10119 }
10120
CheckValue() const10121 void TracedReferenceBase::CheckValue() const {
10122 #ifdef V8_HOST_ARCH_64_BIT
10123 if (!val_) return;
10124
10125 CHECK_NE(internal::kGlobalHandleZapValue, *reinterpret_cast<uint64_t*>(val_));
10126 #endif // V8_HOST_ARCH_64_BIT
10127 }
10128
CFunction(const void * address,const CFunctionInfo * type_info)10129 CFunction::CFunction(const void* address, const CFunctionInfo* type_info)
10130 : address_(address), type_info_(type_info) {
10131 CHECK_NOT_NULL(address_);
10132 CHECK_NOT_NULL(type_info_);
10133 }
10134
CFunctionInfo(const CTypeInfo & return_info,unsigned int arg_count,const CTypeInfo * arg_info)10135 CFunctionInfo::CFunctionInfo(const CTypeInfo& return_info,
10136 unsigned int arg_count, const CTypeInfo* arg_info)
10137 : return_info_(return_info), arg_count_(arg_count), arg_info_(arg_info) {
10138 if (arg_count_ > 0) {
10139 for (unsigned int i = 0; i < arg_count_ - 1; ++i) {
10140 DCHECK(arg_info_[i].GetType() != CTypeInfo::kCallbackOptionsType);
10141 }
10142 }
10143 }
10144
ArgumentInfo(unsigned int index) const10145 const CTypeInfo& CFunctionInfo::ArgumentInfo(unsigned int index) const {
10146 DCHECK_LT(index, ArgumentCount());
10147 return arg_info_[index];
10148 }
10149
ValidateIndex(size_t index) const10150 void FastApiTypedArrayBase::ValidateIndex(size_t index) const {
10151 DCHECK_LT(index, length_);
10152 }
10153
RegisterState()10154 RegisterState::RegisterState()
10155 : pc(nullptr), sp(nullptr), fp(nullptr), lr(nullptr) {}
10156 RegisterState::~RegisterState() = default;
10157
RegisterState(const RegisterState & other)10158 RegisterState::RegisterState(const RegisterState& other) { *this = other; }
10159
operator =(const RegisterState & other)10160 RegisterState& RegisterState::operator=(const RegisterState& other) {
10161 if (&other != this) {
10162 pc = other.pc;
10163 sp = other.sp;
10164 fp = other.fp;
10165 lr = other.lr;
10166 if (other.callee_saved) {
10167 // Make a deep copy if {other.callee_saved} is non-null.
10168 callee_saved =
10169 std::make_unique<CalleeSavedRegisters>(*(other.callee_saved));
10170 } else {
10171 // Otherwise, set {callee_saved} to null to match {other}.
10172 callee_saved.reset();
10173 }
10174 }
10175 return *this;
10176 }
10177
10178 #if !V8_ENABLE_WEBASSEMBLY
10179 // If WebAssembly is disabled, we still need to provide an implementation of the
10180 // WasmStreaming API. Since {WasmStreaming::Unpack} will always fail, all
10181 // methods are unreachable.
10182
10183 class WasmStreaming::WasmStreamingImpl {};
10184
WasmStreaming(std::unique_ptr<WasmStreamingImpl>)10185 WasmStreaming::WasmStreaming(std::unique_ptr<WasmStreamingImpl>) {
10186 UNREACHABLE();
10187 }
10188
10189 WasmStreaming::~WasmStreaming() = default;
10190
OnBytesReceived(const uint8_t * bytes,size_t size)10191 void WasmStreaming::OnBytesReceived(const uint8_t* bytes, size_t size) {
10192 UNREACHABLE();
10193 }
10194
Finish()10195 void WasmStreaming::Finish() { UNREACHABLE(); }
10196
Abort(MaybeLocal<Value> exception)10197 void WasmStreaming::Abort(MaybeLocal<Value> exception) { UNREACHABLE(); }
10198
SetCompiledModuleBytes(const uint8_t * bytes,size_t size)10199 bool WasmStreaming::SetCompiledModuleBytes(const uint8_t* bytes, size_t size) {
10200 UNREACHABLE();
10201 }
10202
SetClient(std::shared_ptr<Client> client)10203 void WasmStreaming::SetClient(std::shared_ptr<Client> client) { UNREACHABLE(); }
10204
SetUrl(const char * url,size_t length)10205 void WasmStreaming::SetUrl(const char* url, size_t length) { UNREACHABLE(); }
10206
10207 // static
Unpack(Isolate * isolate,Local<Value> value)10208 std::shared_ptr<WasmStreaming> WasmStreaming::Unpack(Isolate* isolate,
10209 Local<Value> value) {
10210 FATAL("WebAssembly is disabled");
10211 }
10212 #endif // !V8_ENABLE_WEBASSEMBLY
10213
10214 namespace internal {
10215
10216 const size_t HandleScopeImplementer::kEnteredContextsOffset =
10217 offsetof(HandleScopeImplementer, entered_contexts_);
10218 const size_t HandleScopeImplementer::kIsMicrotaskContextOffset =
10219 offsetof(HandleScopeImplementer, is_microtask_context_);
10220
FreeThreadResources()10221 void HandleScopeImplementer::FreeThreadResources() { Free(); }
10222
ArchiveThread(char * storage)10223 char* HandleScopeImplementer::ArchiveThread(char* storage) {
10224 HandleScopeData* current = isolate_->handle_scope_data();
10225 handle_scope_data_ = *current;
10226 MemCopy(storage, this, sizeof(*this));
10227
10228 ResetAfterArchive();
10229 current->Initialize();
10230
10231 return storage + ArchiveSpacePerThread();
10232 }
10233
ArchiveSpacePerThread()10234 int HandleScopeImplementer::ArchiveSpacePerThread() {
10235 return sizeof(HandleScopeImplementer);
10236 }
10237
RestoreThread(char * storage)10238 char* HandleScopeImplementer::RestoreThread(char* storage) {
10239 MemCopy(this, storage, sizeof(*this));
10240 *isolate_->handle_scope_data() = handle_scope_data_;
10241 return storage + ArchiveSpacePerThread();
10242 }
10243
IterateThis(RootVisitor * v)10244 void HandleScopeImplementer::IterateThis(RootVisitor* v) {
10245 #ifdef DEBUG
10246 bool found_block_before_deferred = false;
10247 #endif
10248 // Iterate over all handles in the blocks except for the last.
10249 for (int i = static_cast<int>(blocks()->size()) - 2; i >= 0; --i) {
10250 Address* block = blocks()->at(i);
10251 // Cast possibly-unrelated pointers to plain Address before comparing them
10252 // to avoid undefined behavior.
10253 if (last_handle_before_deferred_block_ != nullptr &&
10254 (reinterpret_cast<Address>(last_handle_before_deferred_block_) <=
10255 reinterpret_cast<Address>(&block[kHandleBlockSize])) &&
10256 (reinterpret_cast<Address>(last_handle_before_deferred_block_) >=
10257 reinterpret_cast<Address>(block))) {
10258 v->VisitRootPointers(Root::kHandleScope, nullptr, FullObjectSlot(block),
10259 FullObjectSlot(last_handle_before_deferred_block_));
10260 DCHECK(!found_block_before_deferred);
10261 #ifdef DEBUG
10262 found_block_before_deferred = true;
10263 #endif
10264 } else {
10265 v->VisitRootPointers(Root::kHandleScope, nullptr, FullObjectSlot(block),
10266 FullObjectSlot(&block[kHandleBlockSize]));
10267 }
10268 }
10269
10270 DCHECK(last_handle_before_deferred_block_ == nullptr ||
10271 found_block_before_deferred);
10272
10273 // Iterate over live handles in the last block (if any).
10274 if (!blocks()->empty()) {
10275 v->VisitRootPointers(Root::kHandleScope, nullptr,
10276 FullObjectSlot(blocks()->back()),
10277 FullObjectSlot(handle_scope_data_.next));
10278 }
10279
10280 DetachableVector<Context>* context_lists[2] = {&saved_contexts_,
10281 &entered_contexts_};
10282 for (unsigned i = 0; i < arraysize(context_lists); i++) {
10283 context_lists[i]->shrink_to_fit();
10284 if (context_lists[i]->empty()) continue;
10285 FullObjectSlot start(&context_lists[i]->front());
10286 v->VisitRootPointers(Root::kHandleScope, nullptr, start,
10287 start + static_cast<int>(context_lists[i]->size()));
10288 }
10289 }
10290
Iterate(RootVisitor * v)10291 void HandleScopeImplementer::Iterate(RootVisitor* v) {
10292 HandleScopeData* current = isolate_->handle_scope_data();
10293 handle_scope_data_ = *current;
10294 IterateThis(v);
10295 }
10296
Iterate(RootVisitor * v,char * storage)10297 char* HandleScopeImplementer::Iterate(RootVisitor* v, char* storage) {
10298 HandleScopeImplementer* scope_implementer =
10299 reinterpret_cast<HandleScopeImplementer*>(storage);
10300 scope_implementer->IterateThis(v);
10301 return storage + ArchiveSpacePerThread();
10302 }
10303
DetachPersistent(Address * prev_limit)10304 std::unique_ptr<PersistentHandles> HandleScopeImplementer::DetachPersistent(
10305 Address* prev_limit) {
10306 std::unique_ptr<PersistentHandles> ph(new PersistentHandles(isolate()));
10307 DCHECK_NOT_NULL(prev_limit);
10308
10309 while (!blocks_.empty()) {
10310 Address* block_start = blocks_.back();
10311 Address* block_limit = &block_start[kHandleBlockSize];
10312 // We should not need to check for SealHandleScope here. Assert this.
10313 DCHECK_IMPLIES(block_start <= prev_limit && prev_limit <= block_limit,
10314 prev_limit == block_limit);
10315 if (prev_limit == block_limit) break;
10316 ph->blocks_.push_back(blocks_.back());
10317 #if DEBUG
10318 ph->ordered_blocks_.insert(blocks_.back());
10319 #endif
10320 blocks_.pop_back();
10321 }
10322
10323 // ph->blocks_ now contains the blocks installed on the
10324 // HandleScope stack since BeginDeferredScope was called, but in
10325 // reverse order.
10326
10327 // Switch first and last blocks, such that the last block is the one
10328 // that is potentially half full.
10329 DCHECK(!blocks_.empty() && !ph->blocks_.empty());
10330 std::swap(ph->blocks_.front(), ph->blocks_.back());
10331
10332 ph->block_next_ = isolate()->handle_scope_data()->next;
10333 Address* block_start = ph->blocks_.back();
10334 ph->block_limit_ = block_start + kHandleBlockSize;
10335
10336 DCHECK_NOT_NULL(last_handle_before_deferred_block_);
10337 last_handle_before_deferred_block_ = nullptr;
10338 return ph;
10339 }
10340
BeginDeferredScope()10341 void HandleScopeImplementer::BeginDeferredScope() {
10342 DCHECK_NULL(last_handle_before_deferred_block_);
10343 last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next;
10344 }
10345
InvokeAccessorGetterCallback(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Value> & info,v8::AccessorNameGetterCallback getter)10346 void InvokeAccessorGetterCallback(
10347 v8::Local<v8::Name> property,
10348 const v8::PropertyCallbackInfo<v8::Value>& info,
10349 v8::AccessorNameGetterCallback getter) {
10350 // Leaving JavaScript.
10351 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
10352 RCS_SCOPE(isolate, RuntimeCallCounterId::kAccessorGetterCallback);
10353 Address getter_address = reinterpret_cast<Address>(getter);
10354 ExternalCallbackScope call_scope(isolate, getter_address);
10355 getter(property, info);
10356 }
10357
InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value> & info,v8::FunctionCallback callback)10358 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
10359 v8::FunctionCallback callback) {
10360 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
10361 RCS_SCOPE(isolate, RuntimeCallCounterId::kFunctionCallback);
10362 Address callback_address = reinterpret_cast<Address>(callback);
10363 ExternalCallbackScope call_scope(isolate, callback_address);
10364 callback(info);
10365 }
10366
InvokeFinalizationRegistryCleanupFromTask(Handle<Context> context,Handle<JSFinalizationRegistry> finalization_registry,Handle<Object> callback)10367 void InvokeFinalizationRegistryCleanupFromTask(
10368 Handle<Context> context,
10369 Handle<JSFinalizationRegistry> finalization_registry,
10370 Handle<Object> callback) {
10371 Isolate* isolate = finalization_registry->native_context().GetIsolate();
10372 RCS_SCOPE(isolate,
10373 RuntimeCallCounterId::kFinalizationRegistryCleanupFromTask);
10374 // Do not use ENTER_V8 because this is always called from a running
10375 // FinalizationRegistryCleanupTask within V8 and we should not log it as an
10376 // API call. This method is implemented here to avoid duplication of the
10377 // exception handling and microtask running logic in CallDepthScope.
10378 if (IsExecutionTerminatingCheck(isolate)) return;
10379 Local<v8::Context> api_context = Utils::ToLocal(context);
10380 CallDepthScope<true> call_depth_scope(isolate, api_context);
10381 VMState<OTHER> state(isolate);
10382 Handle<Object> argv[] = {callback};
10383 if (Execution::CallBuiltin(isolate,
10384 isolate->finalization_registry_cleanup_some(),
10385 finalization_registry, arraysize(argv), argv)
10386 .is_null()) {
10387 call_depth_scope.Escape();
10388 }
10389 }
10390
10391 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10392 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10393 int32_t ConvertDouble(double d) {
10394 return internal::DoubleToInt32(d);
10395 }
10396
10397 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10398 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10399 uint32_t ConvertDouble(double d) {
10400 return internal::DoubleToUint32(d);
10401 }
10402
10403 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10404 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10405 float ConvertDouble(double d) {
10406 return internal::DoubleToFloat32(d);
10407 }
10408
10409 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10410 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10411 double ConvertDouble(double d) {
10412 return d;
10413 }
10414
10415 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10416 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10417 int64_t ConvertDouble(double d) {
10418 return internal::DoubleToWebIDLInt64(d);
10419 }
10420
10421 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10422 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10423 uint64_t ConvertDouble(double d) {
10424 return internal::DoubleToWebIDLUint64(d);
10425 }
10426
10427 template <>
EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)10428 EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
10429 bool ConvertDouble(double d) {
10430 // Implements https://tc39.es/ecma262/#sec-toboolean.
10431 return !std::isnan(d) && d != 0;
10432 }
10433
10434 // Undefine macros for jumbo build.
10435 #undef SET_FIELD_WRAPPED
10436 #undef NEW_STRING
10437 #undef CALLBACK_SETTER
10438
10439 } // namespace internal
10440
10441 template <>
TryToCopyAndConvertArrayToCppBuffer(Local<Array> src,int32_t * dst,uint32_t max_length)10442 bool V8_EXPORT V8_WARN_UNUSED_RESULT TryToCopyAndConvertArrayToCppBuffer<
10443 internal::CTypeInfoBuilder<int32_t>::Build().GetId(), int32_t>(
10444 Local<Array> src, int32_t* dst, uint32_t max_length) {
10445 return CopyAndConvertArrayToCppBuffer<
10446 CTypeInfo(CTypeInfo::Type::kInt32, CTypeInfo::SequenceType::kIsSequence)
10447 .GetId(),
10448 int32_t>(src, dst, max_length);
10449 }
10450
10451 template <>
TryToCopyAndConvertArrayToCppBuffer(Local<Array> src,uint32_t * dst,uint32_t max_length)10452 bool V8_EXPORT V8_WARN_UNUSED_RESULT TryToCopyAndConvertArrayToCppBuffer<
10453 internal::CTypeInfoBuilder<uint32_t>::Build().GetId(), uint32_t>(
10454 Local<Array> src, uint32_t* dst, uint32_t max_length) {
10455 return CopyAndConvertArrayToCppBuffer<
10456 CTypeInfo(CTypeInfo::Type::kUint32, CTypeInfo::SequenceType::kIsSequence)
10457 .GetId(),
10458 uint32_t>(src, dst, max_length);
10459 }
10460
10461 template <>
TryToCopyAndConvertArrayToCppBuffer(Local<Array> src,float * dst,uint32_t max_length)10462 bool V8_EXPORT V8_WARN_UNUSED_RESULT TryToCopyAndConvertArrayToCppBuffer<
10463 internal::CTypeInfoBuilder<float>::Build().GetId(), float>(
10464 Local<Array> src, float* dst, uint32_t max_length) {
10465 return CopyAndConvertArrayToCppBuffer<
10466 CTypeInfo(CTypeInfo::Type::kFloat32, CTypeInfo::SequenceType::kIsSequence)
10467 .GetId(),
10468 float>(src, dst, max_length);
10469 }
10470
10471 template <>
TryToCopyAndConvertArrayToCppBuffer(Local<Array> src,double * dst,uint32_t max_length)10472 bool V8_EXPORT V8_WARN_UNUSED_RESULT TryToCopyAndConvertArrayToCppBuffer<
10473 internal::CTypeInfoBuilder<double>::Build().GetId(), double>(
10474 Local<Array> src, double* dst, uint32_t max_length) {
10475 return CopyAndConvertArrayToCppBuffer<
10476 CTypeInfo(CTypeInfo::Type::kFloat64, CTypeInfo::SequenceType::kIsSequence)
10477 .GetId(),
10478 double>(src, dst, max_length);
10479 }
10480
10481 } // namespace v8
10482
10483 #undef TRACE_BS
10484 #include "src/api/api-macros-undef.h"
10485