aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-03-06 19:22:52 -0800
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-03-06 19:22:52 -0800
commit0a9cb0e13aba18c51eebcd4e246ac2620fac2fbc (patch)
treedd3005d750e87e459aef877a60c94b3bf7243b74
parentb211fb129865010da61e0913d0a0be1a24154458 (diff)
downloadbun-0a9cb0e13aba18c51eebcd4e246ac2620fac2fbc.tar.gz
bun-0a9cb0e13aba18c51eebcd4e246ac2620fac2fbc.tar.zst
bun-0a9cb0e13aba18c51eebcd4e246ac2620fac2fbc.zip
Fixes #2323
-rw-r--r--src/deps/lol-html.zig64
-rw-r--r--test/bun.js/html-rewriter.test.js28
2 files changed, 68 insertions, 24 deletions
diff --git a/src/deps/lol-html.zig b/src/deps/lol-html.zig
index bb4f4c371..ff7b02ed1 100644
--- a/src/deps/lol-html.zig
+++ b/src/deps/lol-html.zig
@@ -11,6 +11,21 @@ inline fn auto_disable() void {
unreachable;
}
+/// rust panics if the pointer itself is zero, even if the passed length is zero
+/// to work around that, we use a static null-terminated pointer
+/// https://github.com/oven-sh/bun/issues/2323
+fn ptrWithoutPanic(buf: []const u8) [*]const u8 {
+ const null_terminated_ptr = struct {
+ // we must use a static pointer so the lifetime of this pointer is long enough
+ const null_terminated_ptr: []const u8 = &[_]u8{0};
+ }.null_terminated_ptr;
+
+ if (buf.len == 0)
+ return null_terminated_ptr.ptr;
+
+ return buf.ptr;
+}
+
pub const HTMLRewriter = opaque {
extern fn lol_html_rewriter_write(rewriter: *HTMLRewriter, chunk: [*]const u8, chunk_len: usize) c_int;
extern fn lol_html_rewriter_end(rewriter: *HTMLRewriter) c_int;
@@ -18,7 +33,7 @@ pub const HTMLRewriter = opaque {
pub fn write(rewriter: *HTMLRewriter, chunk: []const u8) Error!void {
auto_disable();
- if (rewriter.lol_html_rewriter_write(chunk.ptr, chunk.len) < 0)
+ if (rewriter.lol_html_rewriter_write(ptrWithoutPanic(chunk), chunk.len) < 0)
return error.Fail;
}
@@ -275,7 +290,7 @@ pub const HTMLSelector = opaque {
pub fn parse(selector: []const u8) Error!*HTMLSelector {
auto_disable();
- if (lol_html_selector_parse(selector.ptr, selector.len)) |ptr|
+ if (lol_html_selector_parse(ptrWithoutPanic(selector), selector.len)) |ptr|
return ptr
else
return error.Fail;
@@ -318,7 +333,7 @@ pub const TextChunk = opaque {
/// can be obtained using `lol_html_take_last_error` function.
pub fn before(this: *TextChunk, content: []const u8, is_html: bool) Error!void {
auto_disable();
- if (this.lol_html_text_chunk_before(content.ptr, content.len, is_html) < 0)
+ if (this.lol_html_text_chunk_before(ptrWithoutPanic(content), content.len, is_html) < 0)
return error.Fail;
}
/// Inserts the content string after the text chunk either as raw text or as HTML.
@@ -329,7 +344,7 @@ pub const TextChunk = opaque {
/// can be obtained using `lol_html_take_last_error` function.
pub fn after(this: *TextChunk, content: []const u8, is_html: bool) Error!void {
auto_disable();
- if (this.lol_html_text_chunk_after(content.ptr, content.len, is_html) < 0)
+ if (this.lol_html_text_chunk_after(ptrWithoutPanic(content), content.len, is_html) < 0)
return error.Fail;
}
// Replace the text chunk with the content of the string which is interpreted
@@ -341,7 +356,7 @@ pub const TextChunk = opaque {
// can be obtained using `lol_html_take_last_error` function.
pub fn replace(this: *TextChunk, content: []const u8, is_html: bool) Error!void {
auto_disable();
- if (this.lol_html_text_chunk_replace(content.ptr, content.len, is_html) < 0)
+ if (this.lol_html_text_chunk_replace(ptrWithoutPanic(content), content.len, is_html) < 0)
return error.Fail;
}
/// Removes the text chunk.
@@ -382,11 +397,11 @@ pub const Element = opaque {
pub fn getAttribute(element: *const Element, name: []const u8) HTMLString {
auto_disable();
- return lol_html_element_get_attribute(element, name.ptr, name.len);
+ return lol_html_element_get_attribute(element, ptrWithoutPanic(name), name.len);
}
pub fn hasAttribute(element: *const Element, name: []const u8) Error!bool {
auto_disable();
- return switch (lol_html_element_has_attribute(element, name.ptr, name.len)) {
+ return switch (lol_html_element_has_attribute(element, ptrWithoutPanic(name), name.len)) {
0 => false,
1 => true,
-1 => error.Fail,
@@ -395,7 +410,7 @@ pub const Element = opaque {
}
pub fn setAttribute(element: *Element, name: []const u8, value: []const u8) Error!void {
auto_disable();
- return switch (lol_html_element_set_attribute(element, name.ptr, name.len, value.ptr, value.len)) {
+ return switch (lol_html_element_set_attribute(element, ptrWithoutPanic(name), name.len, ptrWithoutPanic(value), value.len)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -403,7 +418,7 @@ pub const Element = opaque {
}
pub fn removeAttribute(element: *Element, name: []const u8) Error!void {
auto_disable();
- return switch (lol_html_element_remove_attribute(element, name.ptr, name.len)) {
+ return switch (lol_html_element_remove_attribute(element, ptrWithoutPanic(name), name.len)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -411,7 +426,7 @@ pub const Element = opaque {
}
pub fn before(element: *Element, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_element_before(element, content.ptr, content.len, is_html)) {
+ return switch (lol_html_element_before(element, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -419,7 +434,7 @@ pub const Element = opaque {
}
pub fn prepend(element: *Element, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_element_prepend(element, content.ptr, content.len, is_html)) {
+ return switch (lol_html_element_prepend(element, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -427,7 +442,7 @@ pub const Element = opaque {
}
pub fn append(element: *Element, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_element_append(element, content.ptr, content.len, is_html)) {
+ return switch (lol_html_element_append(element, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -435,7 +450,7 @@ pub const Element = opaque {
}
pub fn after(element: *Element, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_element_after(element, content.ptr, content.len, is_html)) {
+ return switch (lol_html_element_after(element, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -443,7 +458,8 @@ pub const Element = opaque {
}
pub fn setInnerContent(element: *Element, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_element_set_inner_content(element, content.ptr, content.len, is_html)) {
+
+ return switch (lol_html_element_set_inner_content(element, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -457,7 +473,7 @@ pub const Element = opaque {
/// can be obtained using `lol_html_take_last_error` function.
pub fn replace(element: *Element, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_element_replace(element, content.ptr, content.len, is_html)) {
+ return switch (lol_html_element_replace(element, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -503,7 +519,7 @@ pub const Element = opaque {
}
pub fn setTagName(element: *Element, name: []const u8) Error!void {
- return switch (lol_html_element_tag_name_set(element, name.ptr, name.len)) {
+ return switch (lol_html_element_tag_name_set(element, ptrWithoutPanic(name), name.len)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -554,7 +570,7 @@ pub const EndTag = opaque {
pub fn before(end_tag: *EndTag, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_end_tag_before(end_tag, content.ptr, content.len, is_html)) {
+ return switch (lol_html_end_tag_before(end_tag, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -563,7 +579,7 @@ pub const EndTag = opaque {
pub fn after(end_tag: *EndTag, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_end_tag_after(end_tag, content.ptr, content.len, is_html)) {
+ return switch (lol_html_end_tag_after(end_tag, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -581,7 +597,7 @@ pub const EndTag = opaque {
pub fn setName(end_tag: *EndTag, name: []const u8) Error!void {
auto_disable();
- return switch (lol_html_end_tag_name_set(end_tag, name.ptr, name.len)) {
+ return switch (lol_html_end_tag_name_set(end_tag, ptrWithoutPanic(name), name.len)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -635,7 +651,7 @@ pub const Comment = opaque {
pub fn setText(comment: *Comment, text: []const u8) Error!void {
auto_disable();
- return switch (lol_html_comment_text_set(comment, text.ptr, text.len)) {
+ return switch (lol_html_comment_text_set(comment, ptrWithoutPanic(text), text.len)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -644,7 +660,7 @@ pub const Comment = opaque {
pub fn before(comment: *Comment, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_comment_before(comment, content.ptr, content.len, is_html)) {
+ return switch (lol_html_comment_before(comment, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -653,7 +669,7 @@ pub const Comment = opaque {
pub fn replace(comment: *Comment, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_comment_before(comment, content.ptr, content.len, is_html)) {
+ return switch (lol_html_comment_before(comment, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -662,7 +678,7 @@ pub const Comment = opaque {
pub fn after(comment: *Comment, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_comment_after(comment, content.ptr, content.len, is_html)) {
+ return switch (lol_html_comment_after(comment, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
@@ -687,7 +703,7 @@ pub const DocEnd = opaque {
pub fn append(this: *DocEnd, content: []const u8, is_html: bool) Error!void {
auto_disable();
- return switch (lol_html_doc_end_append(this, content.ptr, content.len, is_html)) {
+ return switch (lol_html_doc_end_append(this, ptrWithoutPanic(content), content.len, is_html)) {
0 => void{},
-1 => error.Fail,
else => unreachable,
diff --git a/test/bun.js/html-rewriter.test.js b/test/bun.js/html-rewriter.test.js
index 660c6e4f6..e33710f28 100644
--- a/test/bun.js/html-rewriter.test.js
+++ b/test/bun.js/html-rewriter.test.js
@@ -272,4 +272,32 @@ describe("HTMLRewriter", () => {
"<div><h1><span>1</span></h1><span>new</span><b>3</b></div>",
);
});
+
+ it("supports deleting innerContent", async () => {
+ expect(
+ await new HTMLRewriter()
+ .on("div", {
+ element(elem) {
+ // https://github.com/oven-sh/bun/issues/2323
+ elem.setInnerContent("");
+ },
+ })
+ .transform(new Response("<div>content</div>"))
+ .text(),
+ ).toEqual("<div></div>");
+ });
+
+ it("supports deleting innerHTML", async () => {
+ expect(
+ await new HTMLRewriter()
+ .on("div", {
+ element(elem) {
+ // https://github.com/oven-sh/bun/issues/2323
+ elem.setInnerContent("", { html: true });
+ },
+ })
+ .transform(new Response("<div><span>content</span></div>"))
+ .text(),
+ ).toEqual("<div></div>");
+ });
});