1// Copyright 2021 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#ifndef INCLUDE_V8_ISOLATE_CALLBACKS_H_
6#define INCLUDE_V8_ISOLATE_CALLBACKS_H_
7
8#include <stddef.h>
9
10#include <functional>
11#include <string>
12
13#include "cppgc/common.h"
14#include "v8-data.h"          // NOLINT(build/include_directory)
15#include "v8-local-handle.h"  // NOLINT(build/include_directory)
16#include "v8-promise.h"       // NOLINT(build/include_directory)
17#include "v8config.h"         // NOLINT(build/include_directory)
18
19#if defined(V8_OS_WIN)
20struct _EXCEPTION_POINTERS;
21#endif
22
23namespace v8 {
24
25template <typename T>
26class FunctionCallbackInfo;
27class Isolate;
28class Message;
29class Module;
30class Object;
31class Promise;
32class ScriptOrModule;
33class String;
34class UnboundScript;
35class Value;
36
37/**
38 * A JIT code event is issued each time code is added, moved or removed.
39 *
40 * \note removal events are not currently issued.
41 */
42struct JitCodeEvent {
43  enum EventType {
44    CODE_ADDED,
45    CODE_MOVED,
46    CODE_REMOVED,
47    CODE_ADD_LINE_POS_INFO,
48    CODE_START_LINE_INFO_RECORDING,
49    CODE_END_LINE_INFO_RECORDING
50  };
51  // Definition of the code position type. The "POSITION" type means the place
52  // in the source code which are of interest when making stack traces to
53  // pin-point the source location of a stack frame as close as possible.
54  // The "STATEMENT_POSITION" means the place at the beginning of each
55  // statement, and is used to indicate possible break locations.
56  enum PositionType { POSITION, STATEMENT_POSITION };
57
58  // There are three different kinds of CodeType, one for JIT code generated
59  // by the optimizing compiler, one for byte code generated for the
60  // interpreter, and one for code generated from Wasm. For JIT_CODE and
61  // WASM_CODE, |code_start| points to the beginning of jitted assembly code,
62  // while for BYTE_CODE events, |code_start| points to the first bytecode of
63  // the interpreted function.
64  enum CodeType { BYTE_CODE, JIT_CODE, WASM_CODE };
65
66  // Type of event.
67  EventType type;
68  CodeType code_type;
69  // Start of the instructions.
70  void* code_start;
71  // Size of the instructions.
72  size_t code_len;
73  // Script info for CODE_ADDED event.
74  Local<UnboundScript> script;
75  // User-defined data for *_LINE_INFO_* event. It's used to hold the source
76  // code line information which is returned from the
77  // CODE_START_LINE_INFO_RECORDING event. And it's passed to subsequent
78  // CODE_ADD_LINE_POS_INFO and CODE_END_LINE_INFO_RECORDING events.
79  void* user_data;
80
81  struct name_t {
82    // Name of the object associated with the code, note that the string is not
83    // zero-terminated.
84    const char* str;
85    // Number of chars in str.
86    size_t len;
87  };
88
89  struct line_info_t {
90    // PC offset
91    size_t offset;
92    // Code position
93    size_t pos;
94    // The position type.
95    PositionType position_type;
96  };
97
98  struct wasm_source_info_t {
99    // Source file name.
100    const char* filename;
101    // Length of filename.
102    size_t filename_size;
103    // Line number table, which maps offsets of JITted code to line numbers of
104    // source file.
105    const line_info_t* line_number_table;
106    // Number of entries in the line number table.
107    size_t line_number_table_size;
108  };
109
110  wasm_source_info_t* wasm_source_info = nullptr;
111
112  union {
113    // Only valid for CODE_ADDED.
114    struct name_t name;
115
116    // Only valid for CODE_ADD_LINE_POS_INFO
117    struct line_info_t line_info;
118
119    // New location of instructions. Only valid for CODE_MOVED.
120    void* new_code_start;
121  };
122
123  Isolate* isolate;
124};
125
126/**
127 * Option flags passed to the SetJitCodeEventHandler function.
128 */
129enum JitCodeEventOptions {
130  kJitCodeEventDefault = 0,
131  // Generate callbacks for already existent code.
132  kJitCodeEventEnumExisting = 1
133};
134
135/**
136 * Callback function passed to SetJitCodeEventHandler.
137 *
138 * \param event code add, move or removal event.
139 */
140using JitCodeEventHandler = void (*)(const JitCodeEvent* event);
141
142// --- Garbage Collection Callbacks ---
143
144/**
145 * Applications can register callback functions which will be called before and
146 * after certain garbage collection operations.  Allocations are not allowed in
147 * the callback functions, you therefore cannot manipulate objects (set or
148 * delete properties for example) since it is possible such operations will
149 * result in the allocation of objects.
150 */
151enum GCType {
152  kGCTypeScavenge = 1 << 0,
153  kGCTypeMinorMarkCompact = 1 << 1,
154  kGCTypeMarkSweepCompact = 1 << 2,
155  kGCTypeIncrementalMarking = 1 << 3,
156  kGCTypeProcessWeakCallbacks = 1 << 4,
157  kGCTypeAll = kGCTypeScavenge | kGCTypeMinorMarkCompact |
158               kGCTypeMarkSweepCompact | kGCTypeIncrementalMarking |
159               kGCTypeProcessWeakCallbacks
160};
161
162/**
163 * GCCallbackFlags is used to notify additional information about the GC
164 * callback.
165 *   - kGCCallbackFlagConstructRetainedObjectInfos: The GC callback is for
166 *     constructing retained object infos.
167 *   - kGCCallbackFlagForced: The GC callback is for a forced GC for testing.
168 *   - kGCCallbackFlagSynchronousPhantomCallbackProcessing: The GC callback
169 *     is called synchronously without getting posted to an idle task.
170 *   - kGCCallbackFlagCollectAllAvailableGarbage: The GC callback is called
171 *     in a phase where V8 is trying to collect all available garbage
172 *     (e.g., handling a low memory notification).
173 *   - kGCCallbackScheduleIdleGarbageCollection: The GC callback is called to
174 *     trigger an idle garbage collection.
175 */
176enum GCCallbackFlags {
177  kNoGCCallbackFlags = 0,
178  kGCCallbackFlagConstructRetainedObjectInfos = 1 << 1,
179  kGCCallbackFlagForced = 1 << 2,
180  kGCCallbackFlagSynchronousPhantomCallbackProcessing = 1 << 3,
181  kGCCallbackFlagCollectAllAvailableGarbage = 1 << 4,
182  kGCCallbackFlagCollectAllExternalMemory = 1 << 5,
183  kGCCallbackScheduleIdleGarbageCollection = 1 << 6,
184};
185
186using GCCallback = void (*)(GCType type, GCCallbackFlags flags);
187
188using InterruptCallback = void (*)(Isolate* isolate, void* data);
189
190/**
191 * This callback is invoked when the heap size is close to the heap limit and
192 * V8 is likely to abort with out-of-memory error.
193 * The callback can extend the heap limit by returning a value that is greater
194 * than the current_heap_limit. The initial heap limit is the limit that was
195 * set after heap setup.
196 */
197using NearHeapLimitCallback = size_t (*)(void* data, size_t current_heap_limit,
198                                         size_t initial_heap_limit);
199
200/**
201 * Callback function passed to SetUnhandledExceptionCallback.
202 */
203#if defined(V8_OS_WIN)
204using UnhandledExceptionCallback =
205    int (*)(_EXCEPTION_POINTERS* exception_pointers);
206#endif
207
208// --- Counters Callbacks ---
209
210using CounterLookupCallback = int* (*)(const char* name);
211
212using CreateHistogramCallback = void* (*)(const char* name, int min, int max,
213                                          size_t buckets);
214
215using AddHistogramSampleCallback = void (*)(void* histogram, int sample);
216
217// --- Exceptions ---
218
219using FatalErrorCallback = void (*)(const char* location, const char* message);
220
221struct OOMDetails {
222  bool is_heap_oom = false;
223  const char* detail = nullptr;
224};
225
226using OOMErrorCallback = void (*)(const char* location,
227                                  const OOMDetails& details);
228
229using MessageCallback = void (*)(Local<Message> message, Local<Value> data);
230
231// --- Tracing ---
232
233enum LogEventStatus : int { kStart = 0, kEnd = 1, kStamp = 2 };
234using LogEventCallback = void (*)(const char* name,
235                                  int /* LogEventStatus */ status);
236
237// --- Crashkeys Callback ---
238enum class CrashKeyId {
239  kIsolateAddress,
240  kReadonlySpaceFirstPageAddress,
241  kMapSpaceFirstPageAddress V8_ENUM_DEPRECATE_SOON("Map space got removed"),
242  kOldSpaceFirstPageAddress,
243  kCodeRangeBaseAddress,
244  kCodeSpaceFirstPageAddress,
245  kDumpType,
246  kSnapshotChecksumCalculated,
247  kSnapshotChecksumExpected,
248};
249
250using AddCrashKeyCallback = void (*)(CrashKeyId id, const std::string& value);
251
252// --- Enter/Leave Script Callback ---
253using BeforeCallEnteredCallback = void (*)(Isolate*);
254using CallCompletedCallback = void (*)(Isolate*);
255
256// --- AllowCodeGenerationFromStrings callbacks ---
257
258/**
259 * Callback to check if code generation from strings is allowed. See
260 * Context::AllowCodeGenerationFromStrings.
261 */
262using AllowCodeGenerationFromStringsCallback = bool (*)(Local<Context> context,
263                                                        Local<String> source);
264
265struct ModifyCodeGenerationFromStringsResult {
266  // If true, proceed with the codegen algorithm. Otherwise, block it.
267  bool codegen_allowed = false;
268  // Overwrite the original source with this string, if present.
269  // Use the original source if empty.
270  // This field is considered only if codegen_allowed is true.
271  MaybeLocal<String> modified_source;
272};
273
274/**
275 * Access type specification.
276 */
277enum AccessType {
278  ACCESS_GET,
279  ACCESS_SET,
280  ACCESS_HAS,
281  ACCESS_DELETE,
282  ACCESS_KEYS
283};
284
285// --- Failed Access Check Callback ---
286
287using FailedAccessCheckCallback = void (*)(Local<Object> target,
288                                           AccessType type, Local<Value> data);
289
290/**
291 * Callback to check if codegen is allowed from a source object, and convert
292 * the source to string if necessary. See: ModifyCodeGenerationFromStrings.
293 */
294using ModifyCodeGenerationFromStringsCallback =
295    ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
296                                              Local<Value> source);
297using ModifyCodeGenerationFromStringsCallback2 =
298    ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
299                                              Local<Value> source,
300                                              bool is_code_like);
301
302// --- WebAssembly compilation callbacks ---
303using ExtensionCallback = bool (*)(const FunctionCallbackInfo<Value>&);
304
305using AllowWasmCodeGenerationCallback = bool (*)(Local<Context> context,
306                                                 Local<String> source);
307
308// --- Callback for APIs defined on v8-supported objects, but implemented
309// by the embedder. Example: WebAssembly.{compile|instantiate}Streaming ---
310using ApiImplementationCallback = void (*)(const FunctionCallbackInfo<Value>&);
311
312// --- Callback for WebAssembly.compileStreaming ---
313using WasmStreamingCallback = void (*)(const FunctionCallbackInfo<Value>&);
314
315enum class WasmAsyncSuccess { kSuccess, kFail };
316
317// --- Callback called when async WebAssembly operations finish ---
318using WasmAsyncResolvePromiseCallback = void (*)(
319    Isolate* isolate, Local<Context> context, Local<Promise::Resolver> resolver,
320    Local<Value> result, WasmAsyncSuccess success);
321
322// --- Callback for loading source map file for Wasm profiling support
323using WasmLoadSourceMapCallback = Local<String> (*)(Isolate* isolate,
324                                                    const char* name);
325
326// --- Callback for checking if WebAssembly GC is enabled ---
327// If the callback returns true, it will also enable Wasm stringrefs.
328using WasmGCEnabledCallback = bool (*)(Local<Context> context);
329
330// --- Callback for checking if the SharedArrayBuffer constructor is enabled ---
331using SharedArrayBufferConstructorEnabledCallback =
332    bool (*)(Local<Context> context);
333
334/**
335 * HostImportModuleDynamicallyCallback is called when we
336 * require the embedder to load a module. This is used as part of the dynamic
337 * import syntax.
338 *
339 * The referrer contains metadata about the script/module that calls
340 * import.
341 *
342 * The specifier is the name of the module that should be imported.
343 *
344 * The import_assertions are import assertions for this request in the form:
345 * [key1, value1, key2, value2, ...] where the keys and values are of type
346 * v8::String. Note, unlike the FixedArray passed to ResolveModuleCallback and
347 * returned from ModuleRequest::GetImportAssertions(), this array does not
348 * contain the source Locations of the assertions.
349 *
350 * The embedder must compile, instantiate, evaluate the Module, and
351 * obtain its namespace object.
352 *
353 * The Promise returned from this function is forwarded to userland
354 * JavaScript. The embedder must resolve this promise with the module
355 * namespace object. In case of an exception, the embedder must reject
356 * this promise with the exception. If the promise creation itself
357 * fails (e.g. due to stack overflow), the embedder must propagate
358 * that exception by returning an empty MaybeLocal.
359 */
360using HostImportModuleDynamicallyWithImportAssertionsCallback =
361    MaybeLocal<Promise> (*)(Local<Context> context,
362                            Local<ScriptOrModule> referrer,
363                            Local<String> specifier,
364                            Local<FixedArray> import_assertions);
365using HostImportModuleDynamicallyCallback = MaybeLocal<Promise> (*)(
366    Local<Context> context, Local<Data> host_defined_options,
367    Local<Value> resource_name, Local<String> specifier,
368    Local<FixedArray> import_assertions);
369
370/**
371 * Callback for requesting a compile hint for a function from the embedder. The
372 * first parameter is the position of the function in source code and the second
373 * parameter is embedder data to be passed back.
374 */
375using CompileHintCallback = bool (*)(int, void*);
376
377/**
378 * HostInitializeImportMetaObjectCallback is called the first time import.meta
379 * is accessed for a module. Subsequent access will reuse the same value.
380 *
381 * The method combines two implementation-defined abstract operations into one:
382 * HostGetImportMetaProperties and HostFinalizeImportMeta.
383 *
384 * The embedder should use v8::Object::CreateDataProperty to add properties on
385 * the meta object.
386 */
387using HostInitializeImportMetaObjectCallback = void (*)(Local<Context> context,
388                                                        Local<Module> module,
389                                                        Local<Object> meta);
390
391/**
392 * HostCreateShadowRealmContextCallback is called each time a ShadowRealm is
393 * being constructed in the initiator_context.
394 *
395 * The method combines Context creation and implementation defined abstract
396 * operation HostInitializeShadowRealm into one.
397 *
398 * The embedder should use v8::Context::New or v8::Context:NewFromSnapshot to
399 * create a new context. If the creation fails, the embedder must propagate
400 * that exception by returning an empty MaybeLocal.
401 */
402using HostCreateShadowRealmContextCallback =
403    MaybeLocal<Context> (*)(Local<Context> initiator_context);
404
405/**
406 * PrepareStackTraceCallback is called when the stack property of an error is
407 * first accessed. The return value will be used as the stack value. If this
408 * callback is registed, the |Error.prepareStackTrace| API will be disabled.
409 * |sites| is an array of call sites, specified in
410 * https://v8.dev/docs/stack-trace-api
411 */
412using PrepareStackTraceCallback = MaybeLocal<Value> (*)(Local<Context> context,
413                                                        Local<Value> error,
414                                                        Local<Array> sites);
415
416}  // namespace v8
417
418#endif  // INCLUDE_V8_ISOLATE_CALLBACKS_H_
419