Skip to content

Commit 1cb431f

Browse files
committed
Better support for Uint8Array in ReadableStream
There's always going to be ambiguity between a string and a Uint8Array. We already had TypedArray(u8) as a discriminator when _returning_ values. But now the type is also used by mapping JS values to Zig. To support this efficiently when probing the union, the typed array mapping logic was extracted into its own function (so that it can be used by the probe).
1 parent 74dc7b2 commit 1cb431f

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

src/runtime/js.zig

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,80 +1251,88 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
12511251
fn jsValueToTypedArray(_: *JsContext, comptime T: type, js_value: v8.Value) !?[]T {
12521252
var force_u8 = false;
12531253
var array_buffer: ?v8.ArrayBuffer = null;
1254+
var byte_len: usize = undefined;
1255+
var byte_offset: usize = undefined;
1256+
12541257
if (js_value.isTypedArray()) {
12551258
const buffer_view = js_value.castTo(v8.ArrayBufferView);
1259+
byte_len = buffer_view.getByteLength();
1260+
byte_offset = buffer_view.getByteOffset();
12561261
array_buffer = buffer_view.getBuffer();
12571262
} else if (js_value.isArrayBufferView()) {
12581263
force_u8 = true;
12591264
const buffer_view = js_value.castTo(v8.ArrayBufferView);
1265+
byte_len = buffer_view.getByteLength();
1266+
byte_offset = buffer_view.getByteOffset();
12601267
array_buffer = buffer_view.getBuffer();
12611268
} else if (js_value.isArrayBuffer()) {
12621269
force_u8 = true;
12631270
array_buffer = js_value.castTo(v8.ArrayBuffer);
1271+
byte_len = array_buffer.?.getByteLength();
1272+
byte_offset = 0;
12641273
}
12651274

12661275
const buffer = array_buffer orelse return null;
12671276

12681277
const backing_store = v8.BackingStore.sharedPtrGet(&buffer.getBackingStore());
12691278
const data = backing_store.getData();
1270-
const byte_len = backing_store.getByteLength();
12711279

12721280
switch (T) {
12731281
u8 => {
12741282
// need this sentinel check to keep the compiler happy
12751283
if (force_u8 or js_value.isUint8Array() or js_value.isUint8ClampedArray()) {
12761284
if (byte_len == 0) return &[_]u8{};
12771285
const arr_ptr = @as([*]u8, @ptrCast(@alignCast(data)));
1278-
return arr_ptr[0..byte_len];
1286+
return arr_ptr[byte_offset .. byte_offset + byte_len];
12791287
}
12801288
},
12811289
i8 => {
12821290
if (js_value.isInt8Array()) {
12831291
if (byte_len == 0) return &[_]i8{};
12841292
const arr_ptr = @as([*]i8, @ptrCast(@alignCast(data)));
1285-
return arr_ptr[0..byte_len];
1293+
return arr_ptr[byte_offset .. byte_offset + byte_len];
12861294
}
12871295
},
12881296
u16 => {
12891297
if (js_value.isUint16Array()) {
12901298
if (byte_len == 0) return &[_]u16{};
12911299
const arr_ptr = @as([*]u16, @ptrCast(@alignCast(data)));
1292-
return arr_ptr[0 .. byte_len / 2];
1300+
return arr_ptr[byte_offset .. byte_offset + byte_len / 2];
12931301
}
12941302
},
12951303
i16 => {
12961304
if (js_value.isInt16Array()) {
12971305
if (byte_len == 0) return &[_]i16{};
12981306
const arr_ptr = @as([*]i16, @ptrCast(@alignCast(data)));
1299-
return arr_ptr[0 .. byte_len / 2];
1307+
return arr_ptr[byte_offset .. byte_offset + byte_len / 2];
13001308
}
13011309
},
13021310
u32 => {
13031311
if (js_value.isUint32Array()) {
13041312
if (byte_len == 0) return &[_]u32{};
13051313
const arr_ptr = @as([*]u32, @ptrCast(@alignCast(data)));
1306-
return arr_ptr[0 .. byte_len / 4];
1314+
return arr_ptr[byte_offset .. byte_offset + byte_len / 4];
13071315
}
13081316
},
13091317
i32 => {
13101318
if (js_value.isInt32Array()) {
13111319
if (byte_len == 0) return &[_]i32{};
13121320
const arr_ptr = @as([*]i32, @ptrCast(@alignCast(data)));
1313-
return arr_ptr[0 .. byte_len / 4];
1321+
return arr_ptr[byte_offset .. byte_offset + byte_len / 4];
13141322
}
13151323
},
13161324
u64 => {
13171325
if (js_value.isBigUint64Array()) {
13181326
if (byte_len == 0) return &[_]u64{};
13191327
const arr_ptr = @as([*]u64, @ptrCast(@alignCast(data)));
1320-
return arr_ptr[0 .. byte_len / 8];
1328+
return arr_ptr[byte_offset .. byte_offset + byte_len / 8];
13211329
}
13221330
},
13231331
i64 => {
13241332
if (js_value.isBigInt64Array()) {
13251333
if (byte_len == 0) return &[_]i64{};
13261334
const arr_ptr = @as([*]i64, @ptrCast(@alignCast(data)));
1327-
return arr_ptr[0 .. byte_len / 8];
1335+
return arr_ptr[byte_offset .. byte_offset + byte_len / 8];
13281336
}
13291337
},
13301338
else => {},

0 commit comments

Comments
 (0)