diff --git a/src/browser/webapi/DOMImplementation.zig b/src/browser/webapi/DOMImplementation.zig index 1e0a44b69..cce49bd0e 100644 --- a/src/browser/webapi/DOMImplementation.zig +++ b/src/browser/webapi/DOMImplementation.zig @@ -50,6 +50,7 @@ pub fn createHTMLDocument(_: *const DOMImplementation, title: ?js.NullableString const document = (try frame._factory.document(Node.Document.HTMLDocument{ ._proto = undefined })).asDocument(); document._ready_state = .complete; document._url = "about:blank"; + document._charset = "UTF-8"; { const doctype = try frame._factory.node(DocumentType{ @@ -101,6 +102,7 @@ pub fn createDocument(_: *const DOMImplementation, namespace_nullable: js.Nullab // Create XML Document const document = (try frame._factory.document(Node.Document.XMLDocument{ ._proto = undefined })).asDocument(); document._url = "about:blank"; + document._charset = "UTF-8"; // Per spec the content type depends on the requested namespace. document._content_type = blk: { const ns = namespace_ orelse break :blk "application/xml"; diff --git a/src/browser/webapi/Document.zig b/src/browser/webapi/Document.zig index b34de50ba..ec32cdc3b 100644 --- a/src/browser/webapi/Document.zig +++ b/src/browser/webapi/Document.zig @@ -56,6 +56,9 @@ _frame: ?*Frame = null, _url: ?[:0]const u8 = null, // URL for documents created via DOMImplementation (about:blank) // content type override for documents created via DOMImplementation.createDocument _content_type: ?[]const u8 = null, +// encoding override: documents synthesized by script (createHTMLDocument, +// createDocument) are UTF-8 regardless of the frame's encoding +_charset: ?[]const u8 = null, _ready_state: ReadyState = .loading, _current_script: ?*Element.Html.Script = null, _elements_by_id: std.StringHashMapUnmanaged(*Element) = .empty, @@ -159,6 +162,14 @@ pub fn setLocation(self: *Document, url: [:0]const u8) !void { return frame.scheduleNavigation(url, .{ .reason = .script, .kind = .{ .push = null } }, .{ .script = frame }); } +pub fn getCharset(self: *const Document) []const u8 { + if (self._charset) |charset| { + return charset; + } + const doc_frame = self._frame orelse return "UTF-8"; + return doc_frame.charset; +} + pub fn getContentType(self: *const Document) []const u8 { if (self._content_type) |content_type| { return content_type; @@ -1417,6 +1428,7 @@ pub const JsApi = struct { return frame._factory.node(Document{ ._proto = undefined, ._type = .generic, + ._charset = "UTF-8", }); } @@ -1508,8 +1520,7 @@ pub const JsApi = struct { pub const compatMode = bridge.property("CSS1Compat", .{ .template = false }); fn getCharacterSet(self: *const Document) []const u8 { - const doc_frame = self._frame orelse return "UTF-8"; - return doc_frame.charset; + return self.getCharset(); } pub const referrer = bridge.property("", .{ .template = false }); diff --git a/src/browser/webapi/Node.zig b/src/browser/webapi/Node.zig index 2151e1d14..bd0157a6f 100644 --- a/src/browser/webapi/Node.zig +++ b/src/browser/webapi/Node.zig @@ -582,7 +582,11 @@ pub const ResolveURLOpts = struct { pub fn resolveURL(self: *const Node, url: anytype, frame: *Frame, opts: ResolveURLOpts) ![:0]const u8 { const owner_frame = self.ownerFrame(frame); const allocator = opts.allocator orelse frame.call_arena; - return URL.resolve(allocator, owner_frame.base(), url, .{ .encoding = owner_frame.charset }); + // The owning document's encoding, not the frame's: script-created + // documents (e.g. createHTMLDocument) are always UTF-8. + const doc: ?*const Document = if (self._type == .document) self._type.document else self.ownerDocument(frame); + const encoding = if (doc) |d| d.getCharset() else owner_frame.charset; + return URL.resolve(allocator, owner_frame.base(), url, .{ .encoding = encoding }); } // Same as `resolveURL` but can't return `TypeError`, this is needed for multiple