aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Julian <29632054+Parzival-3141@users.noreply.github.com> 2023-07-20 17:50:54 -0400
committerGravatar GitHub <noreply@github.com> 2023-07-20 14:50:54 -0700
commitc383c6cd810a80c6080096bbad737f9fa17f2e7b (patch)
tree21bb087d724facae5dba31666ead3abd03528a53
parent68b4a64569039f39c7bb661570bf65b80028cf92 (diff)
downloadbun-c383c6cd810a80c6080096bbad737f9fa17f2e7b.tar.gz
bun-c383c6cd810a80c6080096bbad737f9fa17f2e7b.tar.zst
bun-c383c6cd810a80c6080096bbad737f9fa17f2e7b.zip
Pass constructor arguments to TextDecoder (#3692)
* Make TextDecoder constructor use options parameter The constructor now actually sets TextDecoder properties using the options parameter. * Defer decoder allocation to end of constructor * Verify types of TextDecoder options * TextDecoder throw TypeError on failure * Tidying
-rw-r--r--src/bun.js/webcore/encoding.zig65
-rw-r--r--test/js/web/encoding/text-decoder.test.js19
2 files changed, 69 insertions, 15 deletions
diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig
index 42256a9ca..41a27ccd4 100644
--- a/src/bun.js/webcore/encoding.zig
+++ b/src/bun.js/webcore/encoding.zig
@@ -630,11 +630,13 @@ pub const TextDecoder = struct {
} else |err| {
switch (err) {
error.InvalidByteSequence => {
- globalThis.throw("Invalid byte sequence", .{});
+ globalThis.throwValue(
+ globalThis.createTypeErrorInstance("Invalid byte sequence", .{}),
+ );
return JSValue.zero;
},
error.OutOfMemory => {
- globalThis.throw("Out of memory", .{});
+ globalThis.throwOutOfMemory();
return JSValue.zero;
},
}
@@ -647,7 +649,7 @@ pub const TextDecoder = struct {
} else |err| {
switch (err) {
error.OutOfMemory => {
- globalThis.throw("Out of memory", .{});
+ globalThis.throwOutOfMemory();
return JSValue.zero;
},
}
@@ -676,26 +678,59 @@ pub const TextDecoder = struct {
globalThis: *JSC.JSGlobalObject,
callframe: *JSC.CallFrame,
) callconv(.C) ?*TextDecoder {
- var args_ = callframe.arguments(1);
+ var args_ = callframe.arguments(2);
var arguments: []const JSC.JSValue = args_.ptr[0..args_.len];
- var encoding = EncodingLabel.@"UTF-8";
+ var decoder = TextDecoder{};
+
if (arguments.len > 0) {
- if (!arguments[0].isString()) {
+ // encoding
+ if (arguments[0].isString()) {
+ var str = arguments[0].toSlice(globalThis, default_allocator);
+ defer if (str.isAllocated()) str.deinit();
+
+ if (EncodingLabel.which(str.slice())) |label| {
+ decoder.encoding = label;
+ } else {
+ globalThis.throwInvalidArguments("Unsupported encoding label \"{s}\"", .{str.slice()});
+ return null;
+ }
+ } else {
globalThis.throwInvalidArguments("TextDecoder(encoding) label is invalid", .{});
return null;
}
- var str = arguments[0].toSlice(globalThis, default_allocator);
- defer if (str.isAllocated()) str.deinit();
- encoding = EncodingLabel.which(str.slice()) orelse {
- globalThis.throwInvalidArguments("Unsupported encoding label \"{s}\"", .{str.slice()});
- return null;
- };
+ if (arguments.len >= 2) {
+ const options = arguments[1];
+
+ if (!options.isObject()) {
+ globalThis.throwInvalidArguments("TextDecoder(options) is invalid", .{});
+ return null;
+ }
+
+ if (options.get(globalThis, "fatal")) |fatal| {
+ if (fatal.isBoolean()) {
+ decoder.fatal = fatal.asBoolean();
+ } else {
+ globalThis.throwInvalidArguments("TextDecoder(options) fatal is invalid. Expected boolean value", .{});
+ return null;
+ }
+ }
+
+ if (options.get(globalThis, "ignoreBOM")) |ignoreBOM| {
+ if (ignoreBOM.isBoolean()) {
+ decoder.ignore_bom = ignoreBOM.asBoolean();
+ } else {
+ globalThis.throwInvalidArguments("TextDecoder(options) ignoreBOM is invalid. Expected boolean value", .{});
+ return null;
+ }
+ }
+ }
}
- var decoder = getAllocator(globalThis).create(TextDecoder) catch unreachable;
- decoder.* = TextDecoder{ .encoding = encoding };
- return decoder;
+
+ var result = getAllocator(globalThis).create(TextDecoder) catch unreachable;
+ result.* = decoder;
+ return result;
}
};
diff --git a/test/js/web/encoding/text-decoder.test.js b/test/js/web/encoding/text-decoder.test.js
index abd4c2a72..d8038e628 100644
--- a/test/js/web/encoding/text-decoder.test.js
+++ b/test/js/web/encoding/text-decoder.test.js
@@ -225,6 +225,25 @@ describe("TextDecoder", () => {
expect(decoder.decode(bytes.subarray(0, amount.written))).toBe(text);
gcTrace(true);
});
+
+ it("should respect fatal when encountering invalid data", () => {
+ const decoder = new TextDecoder("utf-8", { fatal: true });
+ expect(() => {
+ decoder.decode(new Uint8Array([0xC0])) // Invalid UTF8
+ }).toThrow(TypeError);
+ });
+
+ it("constructor should set values", () => {
+ const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: false });
+ expect(decoder.fatal).toBe(true);
+ // expect(decoder.ignoreBOM).toBe(false); // currently the getter for ignoreBOM doesn't work and always returns undefined
+ });
+
+ it("should throw on invalid input", () => {
+ expect(() => {
+ const decoder = new TextDecoder("utf-8", { fatal: 10, ignoreBOM: {} });
+ }).toThrow();
+ });
});
it("truncated sequences", () => {