diff --git a/src/browser/js/ExecutionWorld.zig b/src/browser/js/ExecutionWorld.zig index 372709cb..2c381b9a 100644 --- a/src/browser/js/ExecutionWorld.zig +++ b/src/browser/js/ExecutionWorld.zig @@ -74,26 +74,23 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool) !*Context const env = self.env; const isolate = env.isolate; + const arena = self.context_arena.allocator(); var v8_context: v8.Context = blk: { var temp_scope: v8.HandleScope = undefined; v8.HandleScope.init(&temp_scope, isolate); defer temp_scope.deinit(); - if (comptime IS_DEBUG) { - // Getting this into the snapshot is tricky (anything involving the - // global is tricky). Easier to do here, and in debug mode, we're - // fine with paying the small perf hit. - const js_global = v8.FunctionTemplate.initDefault(isolate); - const global_template = js_global.getInstanceTemplate(); + // Creates a global template that inherits from Window. + const global_template = @import("Snapshot.zig").createGlobalTemplate(isolate, env.templates); - global_template.setNamedProperty(v8.NamedPropertyHandlerConfiguration{ - .getter = unknownPropertyCallback, - .flags = v8.PropertyHandlerFlags.NonMasking | v8.PropertyHandlerFlags.OnlyInterceptStrings, - }, null); - } + // Add the named property handler + global_template.setNamedProperty(v8.NamedPropertyHandlerConfiguration{ + .getter = unknownPropertyCallback, + .flags = v8.PropertyHandlerFlags.NonMasking | v8.PropertyHandlerFlags.OnlyInterceptStrings, + }, v8.External.init(isolate, page)); - const context_local = v8.Context.init(isolate, null, null); + const context_local = v8.Context.init(isolate, global_template, null); const v8_context = v8.Persistent(v8.Context).init(isolate, context_local).castToContext(); break :blk v8_context; }; @@ -124,7 +121,7 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool) !*Context .handle_scope = handle_scope, .script_manager = &page._script_manager, .call_arena = page.call_arena, - .arena = self.context_arena.allocator(), + .arena = arena, }; var context = &self.context.?; @@ -159,9 +156,13 @@ pub fn resumeExecution(self: *const ExecutionWorld) void { pub fn unknownPropertyCallback(c_name: ?*const v8.C_Name, raw_info: ?*const v8.C_PropertyCallbackInfo) callconv(.c) u8 { const info = v8.PropertyCallbackInfo.initFromV8(raw_info); - const context = Context.fromIsolate(info.getIsolate()); - const property = context.valueToString(.{ .handle = c_name.? }, .{}) catch "???"; + const data_value = info.getData(); + const external = data_value.castTo(v8.External); + const page: *Page = @ptrCast(@alignCast(external.get())); + + const context = Context.fromIsolate(info.getIsolate()); + const maybe_property: ?[]u8 = context.valueToString(.{ .handle = c_name.? }, .{}) catch null; const ignored = std.StaticStringMap(void).initComptime(.{ .{ "process", {} }, @@ -185,12 +186,25 @@ pub fn unknownPropertyCallback(c_name: ?*const v8.C_Name, raw_info: ?*const v8.C .{ "CLOSURE_FLAGS", {} }, }); - if (!ignored.has(property)) { - log.debug(.unknown_prop, "unkown global property", .{ - .info = "but the property can exist in pure JS", - .stack = context.stackTrace() catch "???", - .property = property, - }); + if (maybe_property) |prop| { + if (!ignored.has(prop)) { + const document = page.document; + + if (document.getElementById(prop)) |el| { + const js_value = context.zigValueToJs(el, .{}) catch { + return v8.Intercepted.No; + }; + + info.getReturnValue().set(js_value); + return v8.Intercepted.Yes; + } + + log.debug(.unknown_prop, "unknown global property", .{ + .info = "but the property can exist in pure JS", + .stack = context.stackTrace() catch "???", + .property = prop, + }); + } } return v8.Intercepted.No; diff --git a/src/browser/js/Object.zig b/src/browser/js/Object.zig index f2bc3a4d..4520e396 100644 --- a/src/browser/js/Object.zig +++ b/src/browser/js/Object.zig @@ -54,7 +54,7 @@ pub fn set(self: Object, key: []const u8, value: anytype, opts: SetOpts) error{ const context = self.context; const js_key = v8.String.initUtf8(context.isolate, key); - const js_value = try context.zigValueToJs(value); + const js_value = try context.zigValueToJs(value, .{}); const res = self.js_obj.defineOwnProperty(context.v8_context, js_key.toName(), js_value, @bitCast(opts)) orelse false; if (!res) { diff --git a/src/browser/js/Snapshot.zig b/src/browser/js/Snapshot.zig index d93a0f97..6a89e5e5 100644 --- a/src/browser/js/Snapshot.zig +++ b/src/browser/js/Snapshot.zig @@ -113,6 +113,17 @@ fn isValid(self: Snapshot) bool { return v8.SnapshotCreator.startupDataIsValid(self.startup_data); } +pub fn createGlobalTemplate(isolate: v8.Isolate, templates: []const v8.FunctionTemplate) v8.ObjectTemplate { + // Set up the global template to inherit from Window's template + // This way the global object gets all Window properties through inheritance + const js_global = v8.FunctionTemplate.initDefault(isolate); + js_global.setClassName(v8.String.initUtf8(isolate, "Window")); + // Find Window in JsApis by name (avoids circular import) + const window_index = comptime bridge.JsApiLookup.getId(Window.JsApi); + js_global.inherit(templates[window_index]); + return js_global.getInstanceTemplate(); +} + pub fn create(allocator: Allocator) !Snapshot { var external_references = collectExternalReferences(); @@ -154,14 +165,7 @@ pub fn create(allocator: Allocator) !Snapshot { // Set up the global template to inherit from Window's template // This way the global object gets all Window properties through inheritance - const js_global = v8.FunctionTemplate.initDefault(isolate); - js_global.setClassName(v8.String.initUtf8(isolate, "Window")); - - // Find Window in JsApis by name (avoids circular import) - const window_index = comptime bridge.JsApiLookup.getId(Window.JsApi); - js_global.inherit(templates[window_index]); - - const global_template = js_global.getInstanceTemplate(); + const global_template = createGlobalTemplate(isolate, templates[0..]); const context = v8.Context.init(isolate, global_template, null); context.enter(); diff --git a/src/browser/tests/window/named_access.html b/src/browser/tests/window/named_access.html new file mode 100644 index 00000000..4663dbdf --- /dev/null +++ b/src/browser/tests/window/named_access.html @@ -0,0 +1,21 @@ + + + +
+ + + + + + +