commit 088d5beeacb1a4274e520e285f14737e7a6a634a
parent 98d91318c7ea8ef9b7e7f78749485a50f52a3bfb
Author: Florian Dold <florian@dold.me>
Date: Mon, 7 Aug 2023 19:20:56 +0200
make TextDecoder work with typed array views
Diffstat:
3 files changed, 54 insertions(+), 4 deletions(-)
diff --git a/prelude.js b/prelude.js
@@ -14,9 +14,10 @@ class TextEncoder {
class TextDecoder {
decode(bytes) {
if (ArrayBuffer.isView(bytes)) {
- return tart.decodeUtf8(bytes.buffer);
+ return tart.decodeUtf8(bytes.buffer, bytes.byteOffset, bytes.byteLength);
}
- return tart.decodeUtf8(bytes);
+ // Assume it is an ArrayBuffer
+ return tart.decodeUtf8(bytes, 0, bytes.byteLength);
}
}
diff --git a/tart_module.c b/tart_module.c
@@ -1250,16 +1250,42 @@ cleanup:
}
+// (ArrayBuffer, offset, len) => string
+// FIXME: Eventually, this should handle typed arrays properly as input as well.
static JSValue js_decode_utf8(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
size_t psize;
uint8_t *utf8_buf;
+ uint32_t offset;
+ uint32_t len;
+ JSValue ret_val;
+
utf8_buf = JS_GetArrayBuffer(ctx, &psize, argv[0]);
if (NULL == utf8_buf) {
- return JS_EXCEPTION;
+ goto exception;
+ }
+
+ if (0 != JS_ToUint32(ctx, &offset, argv[1])) {
+ goto exception;
+ }
+
+ if (0 != JS_ToUint32(ctx, &len, argv[2])) {
+ goto exception;
}
+
+ if (offset + len > psize) {
+ JS_ThrowRangeError(ctx, "offset %llu len %llu out of range (%llu)",
+ offset, len, psize);
+ goto exception;
+ }
+
return JS_NewStringLen(ctx, (char *) utf8_buf, psize);
+done:
+ return ret_val;
+exception:
+ ret_val = JS_EXCEPTION;
+ goto done;
}
static JSValue js_structured_clone(JSContext *ctx, JSValueConst this_val,
@@ -1383,7 +1409,7 @@ static JSValue js_talercrypto_hash_state_finish(JSContext *ctx, JSValue this_val
static const JSCFunctionListEntry tart_talercrypto_funcs[] = {
JS_CFUNC_DEF("structuredClone", 1, js_structured_clone),
JS_CFUNC_DEF("encodeUtf8", 1, js_encode_utf8),
- JS_CFUNC_DEF("decodeUtf8", 1, js_decode_utf8),
+ JS_CFUNC_DEF("decodeUtf8", 3, js_decode_utf8),
JS_CFUNC_DEF("randomBytes", 1, js_random_bytes),
JS_CFUNC_DEF("encodeCrock", 1, js_talercrypto_encode_crock),
JS_CFUNC_DEF("decodeCrock", 1, js_talercrypto_decode_crock),
diff --git a/test_prelude.js b/test_prelude.js
@@ -0,0 +1,23 @@
+const enc = new TextEncoder();
+const dec = new TextDecoder();
+
+const buf = enc.encode("Hello, World");
+
+console.log("byteOffset", buf.byteOffset);
+console.log("byteLength", buf.byteLength);
+
+const str = dec.decode(buf);
+
+if (str != "Hello, World") {
+ throw Error("test 1 failed");
+}
+
+// Put 4 bytes before and after!
+const buf2 = new Uint8Array(buf.byteLength + 8);
+
+buf2.set(buf, 4);
+
+const str2 = dec.decode(buf2.slice(4, buf2.byteLength - 4))
+if (str2 != "Hello, World") {
+ throw Error("test 2 failed");
+}