@@ -24,6 +24,8 @@ const Allocator = std.mem.Allocator;
2424const Env = @import ("../env.zig" ).Env ;
2525
2626pub const Loader = struct {
27+ state : enum { empty , loading } = .empty ,
28+
2729 done : struct {
2830 fetch : bool = false ,
2931 } = .{},
@@ -42,17 +44,48 @@ pub const Loader = struct {
4244 }
4345
4446 pub fn missing (self : * Loader , name : []const u8 , js_context : * Env.JsContext ) bool {
45- if (! self .done .fetch and std .mem .eql (u8 , name , "fetch" )) {
46- // load the polyfill once.
47- self .done .fetch = true ;
47+ // Avoid recursive calls during polyfill loading.
48+ if (self .state == .loading ) {
49+ return false ;
50+ }
51+
52+ if (! self .done .fetch and isFetch (name )) {
53+ self .state = .loading ;
54+ defer self .state = .empty ;
4855
4956 const _name = "fetch" ;
5057 const source = @import ("fetch.zig" ).source ;
5158 log .debug (.polyfill , "dynamic load" , .{ .property = name });
5259 load (_name , source , js_context ) catch | err | {
5360 log .fatal (.app , "polyfill load" , .{ .name = name , .err = err });
5461 };
62+
63+ // load the polyfill once.
64+ self .done .fetch = true ;
65+
66+ // We return false here: We want v8 to continue the calling chain
67+ // to finally find the polyfill we just inserted. If we want to
68+ // return false and stops the call chain, we have to use
69+ // `info.GetReturnValue.Set()` function, or `undefined` will be
70+ // returned immediately.
71+ return false ;
72+ }
73+
74+ if (comptime builtin .mode == .Debug ) {
75+ log .debug (.unknown_prop , "unkown global property" , .{
76+ .info = "but the property can exist in pure JS" ,
77+ .property = name ,
78+ });
5579 }
80+
81+ return false ;
82+ }
83+
84+ fn isFetch (name : []const u8 ) bool {
85+ if (std .mem .eql (u8 , name , "fetch" )) return true ;
86+ if (std .mem .eql (u8 , name , "Request" )) return true ;
87+ if (std .mem .eql (u8 , name , "Response" )) return true ;
88+ if (std .mem .eql (u8 , name , "Headers" )) return true ;
5689 return false ;
5790 }
5891};
0 commit comments