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)
20 struct _EXCEPTION_POINTERS;
21 #endif
22 
23 namespace v8 {
24 
25 template <typename T>
26 class FunctionCallbackInfo;
27 class Isolate;
28 class Message;
29 class Module;
30 class Object;
31 class Promise;
32 class ScriptOrModule;
33 class String;
34 class UnboundScript;
35 class 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  */
42 struct 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  */
129 enum 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  */
140 using 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  */
151 enum 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  */
176 enum 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 
186 using GCCallback = void (*)(GCType type, GCCallbackFlags flags);
187 
188 using 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  */
197 using 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)
204 using UnhandledExceptionCallback =
205     int (*)(_EXCEPTION_POINTERS* exception_pointers);
206 #endif
207 
208 // --- Counters Callbacks ---
209 
210 using CounterLookupCallback = int* (*)(const char* name);
211 
212 using CreateHistogramCallback = void* (*)(const char* name, int min, int max,
213                                           size_t buckets);
214 
215 using AddHistogramSampleCallback = void (*)(void* histogram, int sample);
216 
217 // --- Exceptions ---
218 
219 using FatalErrorCallback = void (*)(const char* location, const char* message);
220 
221 struct OOMDetails {
222   bool is_heap_oom = false;
223   const char* detail = nullptr;
224 };
225 
226 using OOMErrorCallback = void (*)(const char* location,
227                                   const OOMDetails& details);
228 
229 using MessageCallback = void (*)(Local<Message> message, Local<Value> data);
230 
231 // --- Tracing ---
232 
233 enum LogEventStatus : int { kStart = 0, kEnd = 1, kStamp = 2 };
234 using LogEventCallback = void (*)(const char* name,
235                                   int /* LogEventStatus */ status);
236 
237 // --- Crashkeys Callback ---
238 enum 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 
250 using AddCrashKeyCallback = void (*)(CrashKeyId id, const std::string& value);
251 
252 // --- Enter/Leave Script Callback ---
253 using BeforeCallEnteredCallback = void (*)(Isolate*);
254 using 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  */
262 using AllowCodeGenerationFromStringsCallback = bool (*)(Local<Context> context,
263                                                         Local<String> source);
264 
265 struct 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  */
277 enum AccessType {
278   ACCESS_GET,
279   ACCESS_SET,
280   ACCESS_HAS,
281   ACCESS_DELETE,
282   ACCESS_KEYS
283 };
284 
285 // --- Failed Access Check Callback ---
286 
287 using 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  */
294 using ModifyCodeGenerationFromStringsCallback =
295     ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
296                                               Local<Value> source);
297 using ModifyCodeGenerationFromStringsCallback2 =
298     ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
299                                               Local<Value> source,
300                                               bool is_code_like);
301 
302 // --- WebAssembly compilation callbacks ---
303 using ExtensionCallback = bool (*)(const FunctionCallbackInfo<Value>&);
304 
305 using 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 ---
310 using ApiImplementationCallback = void (*)(const FunctionCallbackInfo<Value>&);
311 
312 // --- Callback for WebAssembly.compileStreaming ---
313 using WasmStreamingCallback = void (*)(const FunctionCallbackInfo<Value>&);
314 
315 enum class WasmAsyncSuccess { kSuccess, kFail };
316 
317 // --- Callback called when async WebAssembly operations finish ---
318 using 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
323 using 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.
328 using WasmGCEnabledCallback = bool (*)(Local<Context> context);
329 
330 // --- Callback for checking if the SharedArrayBuffer constructor is enabled ---
331 using 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  */
360 using HostImportModuleDynamicallyWithImportAssertionsCallback =
361     MaybeLocal<Promise> (*)(Local<Context> context,
362                             Local<ScriptOrModule> referrer,
363                             Local<String> specifier,
364                             Local<FixedArray> import_assertions);
365 using 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  */
375 using 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  */
387 using 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  */
402 using 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  */
412 using 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