Skip to content

Commit 05ad77f

Browse files
authored
Merge pull request #936 from lightpanda-io/runtime-empty-array
Fix crashes with empty array
2 parents 8552a57 + f463cb1 commit 05ad77f

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

src/runtime/js.zig

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -976,49 +976,57 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
976976
// need this sentinel check to keep the compiler happy
977977
if (ptr.sentinel() == null) {
978978
if (force_u8 or js_value.isUint8Array() or js_value.isUint8ClampedArray()) {
979+
if (byte_len == 0) return &[_]u8{};
979980
const arr_ptr = @as([*]u8, @alignCast(@ptrCast(data)));
980981
return arr_ptr[0..byte_len];
981982
}
982983
}
983984
},
984985
i8 => {
985986
if (js_value.isInt8Array()) {
987+
if (byte_len == 0) return &[_]i8{};
986988
const arr_ptr = @as([*]i8, @alignCast(@ptrCast(data)));
987989
return arr_ptr[0..byte_len];
988990
}
989991
},
990992
u16 => {
991993
if (js_value.isUint16Array()) {
994+
if (byte_len == 0) return &[_]u16{};
992995
const arr_ptr = @as([*]u16, @alignCast(@ptrCast(data)));
993996
return arr_ptr[0 .. byte_len / 2];
994997
}
995998
},
996999
i16 => {
9971000
if (js_value.isInt16Array()) {
1001+
if (byte_len == 0) return &[_]i16{};
9981002
const arr_ptr = @as([*]i16, @alignCast(@ptrCast(data)));
9991003
return arr_ptr[0 .. byte_len / 2];
10001004
}
10011005
},
10021006
u32 => {
10031007
if (js_value.isUint32Array()) {
1008+
if (byte_len == 0) return &[_]u32{};
10041009
const arr_ptr = @as([*]u32, @alignCast(@ptrCast(data)));
10051010
return arr_ptr[0 .. byte_len / 4];
10061011
}
10071012
},
10081013
i32 => {
10091014
if (js_value.isInt32Array()) {
1015+
if (byte_len == 0) return &[_]i32{};
10101016
const arr_ptr = @as([*]i32, @alignCast(@ptrCast(data)));
10111017
return arr_ptr[0 .. byte_len / 4];
10121018
}
10131019
},
10141020
u64 => {
10151021
if (js_value.isBigUint64Array()) {
1022+
if (byte_len == 0) return &[_]u64{};
10161023
const arr_ptr = @as([*]u64, @alignCast(@ptrCast(data)));
10171024
return arr_ptr[0 .. byte_len / 8];
10181025
}
10191026
},
10201027
i64 => {
10211028
if (js_value.isBigInt64Array()) {
1029+
if (byte_len == 0) return &[_]i64{};
10221030
const arr_ptr = @as([*]i64, @alignCast(@ptrCast(data)));
10231031
return arr_ptr[0 .. byte_len / 8];
10241032
}
@@ -3469,11 +3477,16 @@ fn simpleZigValueToJs(isolate: v8.Isolate, value: anytype, comptime fail: bool)
34693477
else => @compileError("Invalid TypeArray type: " ++ @typeName(value_type)),
34703478
};
34713479

3472-
const buffer_len = len * bits / 8;
3473-
const backing_store = v8.BackingStore.init(isolate, buffer_len);
3474-
const data: [*]u8 = @alignCast(@ptrCast(backing_store.getData()));
3475-
@memcpy(data[0..buffer_len], @as([]const u8, @ptrCast(values))[0..buffer_len]);
3476-
const array_buffer = v8.ArrayBuffer.initWithBackingStore(isolate, &backing_store.toSharedPtr());
3480+
var array_buffer: v8.ArrayBuffer = undefined;
3481+
if (len == 0) {
3482+
array_buffer = v8.ArrayBuffer.init(isolate, 0);
3483+
} else {
3484+
const buffer_len = len * bits / 8;
3485+
const backing_store = v8.BackingStore.init(isolate, buffer_len);
3486+
const data: [*]u8 = @alignCast(@ptrCast(backing_store.getData()));
3487+
@memcpy(data[0..buffer_len], @as([]const u8, @ptrCast(values))[0..buffer_len]);
3488+
array_buffer = v8.ArrayBuffer.initWithBackingStore(isolate, &backing_store.toSharedPtr());
3489+
}
34773490

34783491
switch (@typeInfo(value_type)) {
34793492
.int => |n| switch (n.signedness) {

src/runtime/test_primitive_types.zig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ const Primitives = struct {
118118
}
119119
}
120120

121+
pub fn _returnEmptyUint8(_: *const Primitives) Env.TypedArray(u8) {
122+
return .{ .values = &.{} };
123+
}
124+
121125
pub fn _returnUint8(_: *const Primitives) Env.TypedArray(u8) {
122126
return .{ .values = &.{ 10, 20, 250 } };
123127
}
@@ -277,6 +281,10 @@ test "JS: primitive types" {
277281

278282
// typed arrays
279283
try runner.testCases(&.{
284+
.{ "let empty_arr = new Int8Array([]);", "undefined" },
285+
.{ "p.int8(empty_arr)", "undefined" },
286+
.{ "empty_arr;", "" },
287+
280288
.{ "let arr_i8 = new Int8Array([-10, -20, -30]);", "undefined" },
281289
.{ "p.int8(arr_i8)", "undefined" },
282290
.{ "arr_i8;", "-13,-23,-33" },
@@ -325,6 +333,7 @@ test "JS: primitive types" {
325333
.{ "try { p.intu64(arr_i64) } catch(e) { e instanceof TypeError; }", "true" },
326334
.{ "try { p.intu64(arr_u32) } catch(e) { e instanceof TypeError; }", "true" },
327335

336+
.{ "p.returnEmptyUint8()", "" },
328337
.{ "p.returnUint8()", "10,20,250" },
329338
.{ "p.returnInt8()", "10,-20,-120" },
330339
.{ "p.returnUint16()", "10,200,2050" },

0 commit comments

Comments
 (0)