diff options
-rw-r--r-- | src/bun.js/api/html_rewriter.zig | 35 | ||||
-rw-r--r-- | src/deps/lol-html.zig | 22 | ||||
-rw-r--r-- | test/js/workerd/html-rewriter.test.js | 28 |
3 files changed, 57 insertions, 28 deletions
diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index 5e14d5503..532e0ae1e 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -996,26 +996,14 @@ const getterWrap = JSC.getterWrap; const setterWrap = JSC.setterWrap; const wrap = JSC.wrapSync; -pub fn free_html_writer_string(_: ?*anyopaque, ptr: ?*anyopaque, len: usize) callconv(.C) void { - var str = LOLHTML.HTMLString{ .ptr = bun.cast([*]const u8, ptr.?), .len = len }; - str.deinit(); -} - fn throwLOLHTMLError(global: *JSGlobalObject) JSValue { - var err = LOLHTML.HTMLString.lastError(); - return ZigString.init(err.slice()).toErrorInstance(global); + const err = LOLHTML.HTMLString.lastError(); + defer err.deinit(); + return ZigString.fromUTF8(err.slice()).toErrorInstance(global); } fn htmlStringValue(input: LOLHTML.HTMLString, globalObject: *JSGlobalObject) JSValue { - var str = ZigString.init( - input.slice(), - ); - str.detectEncoding(); - - return str.toExternalValueWithCallback( - globalObject, - free_html_writer_string, - ); + return input.toJS(globalObject); } pub const TextChunk = struct { @@ -1328,7 +1316,7 @@ pub const Comment = struct { pub fn getText(this: *Comment, global: *JSGlobalObject) JSValue { if (this.comment == null) return JSValue.jsNull(); - return ZigString.init(this.comment.?.getText().slice()).withEncoding().toValueGC(global); + return this.comment.?.getText().toJS(global); } pub fn setText( @@ -1458,7 +1446,7 @@ pub const EndTag = struct { if (this.end_tag == null) return JSC.JSValue.jsUndefined(); - return ZigString.init(this.end_tag.?.getName().slice()).withEncoding().toValueGC(global); + return this.end_tag.?.getName().toJS(global); } pub fn setName( @@ -1696,19 +1684,12 @@ pub const Element = struct { var slice = name.toSlice(bun.default_allocator); defer slice.deinit(); - var attr = this.element.?.getAttribute(slice.slice()).slice(); + var attr = this.element.?.getAttribute(slice.slice()); if (attr.len == 0) return JSC.JSValue.jsNull(); - var str = ZigString.init( - attr, - ); - - return str.toExternalValueWithCallback( - globalObject, - free_html_writer_string, - ); + return attr.toJS(globalObject); } /// Returns a boolean indicating whether an attribute exists on the element. diff --git a/src/deps/lol-html.zig b/src/deps/lol-html.zig index 9c5345046..50dab9592 100644 --- a/src/deps/lol-html.zig +++ b/src/deps/lol-html.zig @@ -1,6 +1,6 @@ pub const Error = error{Fail}; const std = @import("std"); - +const bun = @import("root").bun; pub const MemorySettings = extern struct { preallocated_parsing_buffer_size: usize, max_allowed_memory_usage: usize, @@ -563,6 +563,26 @@ pub const HTMLString = extern struct { @setRuntimeSafety(false); return this.ptr[0..this.len]; } + + fn deinit_external(ctx: *anyopaque, ptr: *anyopaque, len: u32) callconv(.C) void { + _ = ctx; + auto_disable(); + lol_html_str_free(.{ .ptr = @ptrCast([*]const u8, ptr), .len = len }); + } + + pub fn toJS(this: HTMLString, globalThis: *bun.JSC.JSGlobalObject) bun.JSC.JSValue { + const bytes = this.slice(); + if (bun.strings.isAllASCII(bytes)) { + var external = bun.String.createExternal(bytes, true, @constCast(bytes.ptr), &deinit_external); + defer external.deref(); + return external.toJS(globalThis); + } + defer this.deinit(); + + var str = bun.String.create(bytes); + defer str.deref(); + return str.toJS(globalThis); + } }; pub const EndTag = opaque { diff --git a/test/js/workerd/html-rewriter.test.js b/test/js/workerd/html-rewriter.test.js index 3f7b7493d..aaf912aff 100644 --- a/test/js/workerd/html-rewriter.test.js +++ b/test/js/workerd/html-rewriter.test.js @@ -337,3 +337,31 @@ it("#3334 regression", async () => { } Bun.gc(true); }); + +it("#3489", async () => { + var el; + await new HTMLRewriter() + .on("p", { + element(element) { + el = element.getAttribute("id"); + }, + }) + .transform(new Response('<p id="Šžõäöü"></p>')) + .text(); + expect(el).toEqual("Šžõäöü"); +}); + +it("get attribute - ascii", async () => { + for (let i = 0; i < 10; i++) { + var el; + await new HTMLRewriter() + .on("p", { + element(element) { + el = element.getAttribute("id"); + }, + }) + .transform(new Response(`<p id="asciii"></p>`)) + .text(); + expect(el).toEqual("asciii"); + } +}); |