@@ -370,7 +370,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
370370 // when the handle_scope is freed.
371371 // We also maintain our own "context_arena" which allows us to have
372372 // all page related memory easily managed.
373- pub fn createJsContext (self : * ExecutionWorld , global : anytype , state : State , module_loader : anytype , enter : bool ) ! * JsContext {
373+ pub fn createJsContext (self : * ExecutionWorld , global : anytype , state : State , module_loader : anytype , enter : bool , global_callback : ? GlobalMissingCallback ) ! * JsContext {
374374 std .debug .assert (self .js_context == null );
375375
376376 const ModuleLoader = switch (@typeInfo (@TypeOf (module_loader ))) {
@@ -399,6 +399,30 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
399399 const global_template = js_global .getInstanceTemplate ();
400400 global_template .setInternalFieldCount (1 );
401401
402+ // Configure the missing property callback on the global
403+ // object.
404+ if (global_callback != null ) {
405+ const configuration = v8.NamedPropertyHandlerConfiguration {
406+ .getter = struct {
407+ fn callback (c_name : ? * const v8.C_Name , raw_info : ? * const v8.C_PropertyCallbackInfo ) callconv (.c ) u8 {
408+ const info = v8 .PropertyCallbackInfo .initFromV8 (raw_info );
409+ const _isolate = info .getIsolate ();
410+ const v8_context = _isolate .getCurrentContext ();
411+
412+ const js_context : * JsContext = @ptrFromInt (v8_context .getEmbedderData (1 ).castTo (v8 .BigInt ).getUint64 ());
413+
414+ const property = valueToString (js_context .call_arena , .{ .handle = c_name .? }, _isolate , v8_context ) catch "???" ;
415+ if (js_context .global_callback .? .missing (property , js_context )) {
416+ return v8 .Intercepted .Yes ;
417+ }
418+ return v8 .Intercepted .No ;
419+ }
420+ }.callback ,
421+ .flags = v8 .PropertyHandlerFlags .NonMasking | v8 .PropertyHandlerFlags .OnlyInterceptStrings ,
422+ };
423+ global_template .setNamedProperty (configuration , null );
424+ }
425+
402426 // All the FunctionTemplates that we created and setup in Env.init
403427 // are now going to get associated with our global instance.
404428 inline for (Types , 0.. ) | s , i | {
@@ -481,6 +505,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
481505 .ptr = safe_module_loader ,
482506 .func = ModuleLoader .fetchModuleSource ,
483507 },
508+ .global_callback = global_callback ,
484509 };
485510
486511 var js_context = & self .js_context .? ;
@@ -633,6 +658,9 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
633658 // necessary to lookup/store the dependent module in the module_cache.
634659 module_identifier : std .AutoHashMapUnmanaged (u32 , []const u8 ) = .empty ,
635660
661+ // Global callback is called on missing property.
662+ global_callback : ? GlobalMissingCallback = null ,
663+
636664 const ModuleLoader = struct {
637665 ptr : * anyopaque ,
638666 func : * const fn (ptr : * anyopaque , specifier : []const u8 ) anyerror ! ? []const u8 ,
@@ -2265,11 +2293,6 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
22652293
22662294 fn generateNamedIndexer (comptime Struct : type , template_proto : v8.ObjectTemplate ) void {
22672295 if (@hasDecl (Struct , "named_get" ) == false ) {
2268- if (comptime builtin .mode == .Debug ) {
2269- if (log .enabled (.unknown_prop , .debug )) {
2270- generateDebugNamedIndexer (Struct , template_proto );
2271- }
2272- }
22732296 return ;
22742297 }
22752298
@@ -2329,31 +2352,6 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
23292352 template_proto .setNamedProperty (configuration , null );
23302353 }
23312354
2332- fn generateDebugNamedIndexer (comptime Struct : type , template_proto : v8.ObjectTemplate ) void {
2333- const configuration = v8.NamedPropertyHandlerConfiguration {
2334- .getter = struct {
2335- fn callback (c_name : ? * const v8.C_Name , raw_info : ? * const v8.C_PropertyCallbackInfo ) callconv (.c ) u8 {
2336- const info = v8 .PropertyCallbackInfo .initFromV8 (raw_info );
2337- const isolate = info .getIsolate ();
2338- const v8_context = isolate .getCurrentContext ();
2339-
2340- const js_context : * JsContext = @ptrFromInt (v8_context .getEmbedderData (1 ).castTo (v8 .BigInt ).getUint64 ());
2341-
2342- const property = valueToString (js_context .call_arena , .{ .handle = c_name .? }, isolate , v8_context ) catch "???" ;
2343- log .debug (.unknown_prop , "unkown property" , .{ .@"struct" = @typeName (Struct ), .property = property });
2344- return v8 .Intercepted .No ;
2345- }
2346- }.callback ,
2347-
2348- // This is really cool. Without this, we'd intercept _all_ properties
2349- // even those explicitly set. So, node.length for example would get routed
2350- // to our `named_get`, rather than a `get_length`. This might be
2351- // useful if we run into a type that we can't model properly in Zig.
2352- .flags = v8 .PropertyHandlerFlags .OnlyInterceptStrings | v8 .PropertyHandlerFlags .NonMasking ,
2353- };
2354- template_proto .setNamedProperty (configuration , null );
2355- }
2356-
23572355 fn generateUndetectable (comptime Struct : type , template : v8.ObjectTemplate ) void {
23582356 const has_js_call_as_function = @hasDecl (Struct , "jsCallAsFunction" );
23592357
@@ -2577,6 +2575,35 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
25772575 self .callScopeEndFn (self .ptr );
25782576 }
25792577 };
2578+
2579+ // Callback called on global's property mssing.
2580+ // Return true to intercept the exectution or false to let the call
2581+ // continue the chain.
2582+ pub const GlobalMissingCallback = struct {
2583+ ptr : * anyopaque ,
2584+ missingFn : * const fn (ptr : * anyopaque , name : []const u8 , ctx : * JsContext ) bool ,
2585+
2586+ pub fn init (ptr : anytype ) GlobalMissingCallback {
2587+ const T = @TypeOf (ptr );
2588+ const ptr_info = @typeInfo (T );
2589+
2590+ const gen = struct {
2591+ pub fn missing (pointer : * anyopaque , name : []const u8 , ctx : * JsContext ) bool {
2592+ const self : T = @ptrCast (@alignCast (pointer ));
2593+ return ptr_info .pointer .child .missing (self , name , ctx );
2594+ }
2595+ };
2596+
2597+ return .{
2598+ .ptr = ptr ,
2599+ .missingFn = gen .missing ,
2600+ };
2601+ }
2602+
2603+ pub fn missing (self : GlobalMissingCallback , name : []const u8 , ctx : * JsContext ) bool {
2604+ return self .missingFn (self .ptr , name , ctx );
2605+ }
2606+ };
25802607 };
25812608}
25822609
0 commit comments