@@ -364,13 +364,25 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
364364 self .context_arena .deinit ();
365365 }
366366
367+ pub const CreateJsContextOpt = struct {
368+ global_callback : ? GlobalMissingCallback = null ,
369+ compilation_callback : ? CompilationCallback = null ,
370+ };
371+
367372 // Only the top JsContext in the Main ExecutionWorld should hold a handle_scope.
368373 // A v8.HandleScope is like an arena. Once created, any "Local" that
369374 // v8 creates will be released (or at least, releasable by the v8 GC)
370375 // when the handle_scope is freed.
371376 // We also maintain our own "context_arena" which allows us to have
372377 // all page related memory easily managed.
373- pub fn createJsContext (self : * ExecutionWorld , global : anytype , state : State , module_loader : anytype , enter : bool , global_callback : ? GlobalMissingCallback ) ! * JsContext {
378+ pub fn createJsContext (
379+ self : * ExecutionWorld ,
380+ global : anytype ,
381+ state : State ,
382+ module_loader : anytype ,
383+ enter : bool ,
384+ opt : CreateJsContextOpt ,
385+ ) ! * JsContext {
374386 std .debug .assert (self .js_context == null );
375387
376388 const ModuleLoader = switch (@typeInfo (@TypeOf (module_loader ))) {
@@ -401,7 +413,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
401413
402414 // Configure the missing property callback on the global
403415 // object.
404- if (global_callback != null ) {
416+ if (opt . global_callback != null ) {
405417 const configuration = v8.NamedPropertyHandlerConfiguration {
406418 .getter = struct {
407419 fn callback (c_name : ? * const v8.C_Name , raw_info : ? * const v8.C_PropertyCallbackInfo ) callconv (.c ) u8 {
@@ -505,7 +517,8 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
505517 .ptr = safe_module_loader ,
506518 .func = ModuleLoader .fetchModuleSource ,
507519 },
508- .global_callback = global_callback ,
520+ .global_callback = opt .global_callback ,
521+ .compilation_callback = opt .compilation_callback ,
509522 };
510523
511524 var js_context = & self .js_context .? ;
@@ -658,9 +671,12 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
658671 // necessary to lookup/store the dependent module in the module_cache.
659672 module_identifier : std .AutoHashMapUnmanaged (u32 , []const u8 ) = .empty ,
660673
661- // Global callback is called on missing property.
674+ // Global callback is called when a property is missing on the
675+ // global object.
662676 global_callback : ? GlobalMissingCallback = null ,
663677
678+ compilation_callback : ? CompilationCallback = null ,
679+
664680 const ModuleLoader = struct {
665681 ptr : * anyopaque ,
666682 func : * const fn (ptr : * anyopaque , specifier : []const u8 ) anyerror ! ? []const u8 ,
@@ -747,6 +763,8 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
747763 }
748764
749765 pub fn exec (self : * JsContext , src : []const u8 , name : ? []const u8 ) ! Value {
766+ if (self .compilation_callback ) | cbk | cbk .script (src , name , self );
767+
750768 const isolate = self .isolate ;
751769 const v8_context = self .v8_context ;
752770
@@ -770,6 +788,8 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
770788 // compile and eval a JS module
771789 // It doesn't wait for callbacks execution
772790 pub fn module (self : * JsContext , src : []const u8 , url : []const u8 , cacheable : bool ) ! void {
791+ if (self .compilation_callback ) | cbk | cbk .module (src , url , self );
792+
773793 if (! cacheable ) {
774794 return self .moduleNoCache (src , url );
775795 }
@@ -2604,6 +2624,43 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
26042624 return self .missingFn (self .ptr , name , ctx );
26052625 }
26062626 };
2627+
2628+ // CompilationCallback called before script and module compilation.
2629+ pub const CompilationCallback = struct {
2630+ ptr : * anyopaque ,
2631+ scriptFn : * const fn (ptr : * anyopaque , source : []const u8 , name : ? []const u8 , ctx : * JsContext ) void ,
2632+ moduleFn : * const fn (ptr : * anyopaque , source : []const u8 , url : []const u8 , ctx : * JsContext ) void ,
2633+
2634+ pub fn init (ptr : anytype ) CompilationCallback {
2635+ const T = @TypeOf (ptr );
2636+ const ptr_info = @typeInfo (T );
2637+
2638+ const gen = struct {
2639+ pub fn script (pointer : * anyopaque , source : []const u8 , name : ? []const u8 , ctx : * JsContext ) void {
2640+ const self : T = @ptrCast (@alignCast (pointer ));
2641+ return ptr_info .pointer .child .script (self , source , name , ctx );
2642+ }
2643+ pub fn module (pointer : * anyopaque , source : []const u8 , url : []const u8 , ctx : * JsContext ) void {
2644+ const self : T = @ptrCast (@alignCast (pointer ));
2645+ return ptr_info .pointer .child .module (self , source , url , ctx );
2646+ }
2647+ };
2648+
2649+ return .{
2650+ .ptr = ptr ,
2651+ .scriptFn = gen .script ,
2652+ .moduleFn = gen .module ,
2653+ };
2654+ }
2655+
2656+ pub fn script (self : CompilationCallback , source : []const u8 , name : ? []const u8 , ctx : * JsContext ) void {
2657+ return self .scriptFn (self .ptr , source , name , ctx );
2658+ }
2659+
2660+ pub fn module (self : CompilationCallback , source : []const u8 , url : []const u8 , ctx : * JsContext ) void {
2661+ return self .moduleFn (self .ptr , source , url , ctx );
2662+ }
2663+ };
26072664 };
26082665}
26092666
0 commit comments