aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bun.js/api/html_rewriter.zig35
-rw-r--r--src/deps/lol-html.zig22
-rw-r--r--test/js/workerd/html-rewriter.test.js28
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");
+ }
+});