aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-12-29 05:53:12 -0800
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-12-29 06:05:43 -0800
commit85eda2058755261bf5ac64a3d82112d7bad5419c (patch)
tree924056e03bab81bf3d991fceaa2bee1b97b8181b
parent940ecd05a8a3a1f0326256148a93306b71936c1e (diff)
downloadbun-85eda2058755261bf5ac64a3d82112d7bad5419c.tar.gz
bun-85eda2058755261bf5ac64a3d82112d7bad5419c.tar.zst
bun-85eda2058755261bf5ac64a3d82112d7bad5419c.zip
Introduce `Bun.CryptoHasher`
-rw-r--r--Makefile2
-rw-r--r--bench/snippets/crypto-hasher.mjs30
-rw-r--r--packages/bun-types/bun.d.ts100
-rw-r--r--src/bun.js/api/bun.zig439
-rw-r--r--src/bun.js/api/crypto.classes.ts40
-rw-r--r--src/bun.js/base.zig72
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h4
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h4
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h12
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h10
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.cpp243
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.h27
-rw-r--r--src/bun.js/bindings/bindings.zig70
-rw-r--r--src/bun.js/bindings/generated_classes.zig120
-rw-r--r--src/bun.js/bindings/generated_classes_list.zig2
-rw-r--r--src/bun.js/node/types.zig106
-rw-r--r--src/bun.js/webcore/encoding.zig3
-rw-r--r--src/deps/boringssl.translated.zig17
-rw-r--r--test/bun.js/crypto.test.js47
19 files changed, 1142 insertions, 206 deletions
diff --git a/Makefile b/Makefile
index 5c9d59ce1..1fa249f57 100644
--- a/Makefile
+++ b/Makefile
@@ -416,9 +416,9 @@ MINIMUM_ARCHIVE_FILES = -L$(BUN_DEPS_OUT_DIR) \
-lz \
$(BUN_DEPS_OUT_DIR)/picohttpparser.o \
$(_MIMALLOC_LINK) \
+ -ldecrepit \
-lssl \
-lcrypto \
- -ldecrepit \
-llolhtml
ARCHIVE_FILES_WITHOUT_LIBCRYPTO = $(MINIMUM_ARCHIVE_FILES) \
diff --git a/bench/snippets/crypto-hasher.mjs b/bench/snippets/crypto-hasher.mjs
new file mode 100644
index 000000000..1e850e19f
--- /dev/null
+++ b/bench/snippets/crypto-hasher.mjs
@@ -0,0 +1,30 @@
+// so it can run in environments without node module resolution
+import { bench, run } from "mitata";
+
+import crypto from "node:crypto";
+
+var foo = new Uint8Array(65536);
+crypto.getRandomValues(foo);
+
+// if ("Bun" in globalThis) {
+// const { CryptoHasher } = Bun;
+// bench("CryptoHasher Blake2b256", () => {
+// var hasher = new CryptoHasher("blake2b256");
+// hasher.update(foo);
+// hasher.digest();
+// });
+// }
+
+bench('crypto.createHash("sha512")', () => {
+ var hasher = crypto.createHash("sha512");
+ hasher.update(foo);
+ hasher.digest();
+});
+
+bench('crypto.createHash("sha512")', () => {
+ var hasher = crypto.createHash("sha512");
+ hasher.update(foo);
+ hasher.digest();
+});
+
+await run();
diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts
index 2d93cf8a8..1a23d7326 100644
--- a/packages/bun-types/bun.d.ts
+++ b/packages/bun-types/bun.d.ts
@@ -1,3 +1,5 @@
+import { Encoding } from "crypto";
+
interface VoidFunction {
(): void;
}
@@ -1924,6 +1926,96 @@ declare module "bun" {
static hash(input: StringOrBuffer, encoding: DigestEncoding): string;
}
+ type SupportedCryptoAlgorithms =
+ | "blake2b256"
+ | "md4"
+ | "md5"
+ | "ripemd160"
+ | "sha1"
+ | "sha224"
+ | "sha256"
+ | "sha384"
+ | "sha512"
+ | "sha512-256";
+ /**
+ * Hardware-accelerated cryptographic hash functions
+ *
+ * Used for `crypto.createHash()`
+ */
+ export class CryptoHasher {
+ /**
+ * The algorithm chosen to hash the data
+ *
+ */
+ readonly algorithm: SupportedCryptoAlgorithms;
+
+ /**
+ * The length of the output hash in bytes
+ */
+ readonly byteLength: number;
+
+ /**
+ * Create a new hasher
+ *
+ * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms
+ */
+ constructor(algorithm: SupportedCryptoAlgorithms);
+
+ /**
+ * Update the hash with data
+ *
+ * @param input
+ */
+ update(input: StringOrBuffer, inputEncoding?: Encoding): CryptoHasher;
+
+ /**
+ * Finalize the hash
+ *
+ * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`.
+ */
+ digest(encoding: DigestEncoding): string;
+
+ /**
+ * Finalize the hash
+ *
+ * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time
+ */
+ digest(hashInto?: TypedArray): TypedArray;
+
+ /**
+ * Run the hash over the given data
+ *
+ * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster.
+ *
+ * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time
+ */
+ static hash(
+ algorithm: SupportedCryptoAlgorithms,
+ input: StringOrBuffer,
+ hashInto?: TypedArray,
+ ): TypedArray;
+
+ /**
+ * Run the hash over the given data
+ *
+ * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster.
+ *
+ * @param encoding `DigestEncoding` to return the hash in
+ */
+ static hash(
+ algorithm: SupportedCryptoAlgorithms,
+ input: StringOrBuffer,
+ encoding: DigestEncoding,
+ ): string;
+
+ /**
+ * List of supported hash algorithms
+ *
+ * These are hardware accelerated with BoringSSL
+ */
+ static readonly algorithms: SupportedCryptoAlgorithms[];
+ }
+
/**
* Sleep the thread for a given number of milliseconds
*
@@ -2045,14 +2137,6 @@ declare module "bun" {
*/
static readonly byteLength: 32;
}
- export class RIPEMD160 extends CryptoHashInterface<RIPEMD160> {
- constructor();
-
- /**
- * The number of bytes the hash will produce
- */
- static readonly byteLength: 20;
- }
/** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */
export type ZlibCompressionOptions = {
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index fc66098a4..31d536000 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -1279,12 +1279,12 @@ pub const Class = NewClass(
.SHA256 = .{
.get = Crypto.SHA256.getter,
},
- .RIPEMD160 = .{
- .get = Crypto.RIPEMD160.getter,
- },
.SHA512_256 = .{
.get = Crypto.SHA512_256.getter,
},
+ .CryptoHasher = .{
+ .get = Crypto.CryptoHasher.getter,
+ },
.FFI = .{
.get = FFI.getter,
},
@@ -1366,7 +1366,415 @@ pub fn indexOfLine(
pub const Crypto = struct {
const Hashers = @import("../../sha.zig");
- fn CryptoHasher(comptime Hasher: type, comptime name: [:0]const u8) type {
+ const BoringSSL = bun.BoringSSL;
+ const EVP = struct {
+ ctx: BoringSSL.EVP_MD_CTX = undefined,
+ md: *const BoringSSL.EVP_MD = undefined,
+ algorithm: Algorithm,
+
+ // we do this to avoid asking BoringSSL what the digest name is
+ // because that API is confusing
+ pub const Algorithm = enum {
+ // @"DSA-SHA",
+ // @"DSA-SHA1",
+ // @"MD5-SHA1",
+ // @"RSA-MD5",
+ // @"RSA-RIPEMD160",
+ // @"RSA-SHA1",
+ // @"RSA-SHA1-2",
+ // @"RSA-SHA224",
+ // @"RSA-SHA256",
+ // @"RSA-SHA384",
+ // @"RSA-SHA512",
+ // @"ecdsa-with-SHA1",
+ blake2b256,
+ md4,
+ md5,
+ ripemd160,
+ sha1,
+ sha224,
+ sha256,
+ sha384,
+ sha512,
+ @"sha512-256",
+
+ pub const names: std.EnumArray(Algorithm, ZigString) = brk: {
+ var all = std.EnumArray(Algorithm, ZigString).initUndefined();
+ var iter = all.iterator();
+ while (iter.next()) |entry| {
+ entry.value.* = ZigString.init(std.mem.span(@tagName(entry.key)));
+ }
+ break :brk all;
+ };
+
+ pub const map = bun.ComptimeStringMap(Algorithm, .{
+ .{ "blake2b256", .blake2b256 },
+ .{ "ripemd160", .ripemd160 },
+ .{ "rmd160", .ripemd160 },
+ .{ "md4", .md4 },
+ .{ "md5", .md5 },
+ .{ "sha1", .sha1 },
+ .{ "sha128", .sha1 },
+ .{ "sha224", .sha224 },
+ .{ "sha256", .sha256 },
+ .{ "sha384", .sha384 },
+ .{ "sha512", .sha512 },
+ .{ "sha-1", .sha1 },
+ .{ "sha-224", .sha224 },
+ .{ "sha-256", .sha256 },
+ .{ "sha-384", .sha384 },
+ .{ "sha-512", .sha512 },
+ .{ "sha-512/256", .@"sha512-256" },
+ .{ "sha-512_256", .@"sha512-256" },
+ .{ "sha-512256", .@"sha512-256" },
+ .{ "sha512-256", .@"sha512-256" },
+ .{ "sha384", .sha384 },
+ // .{ "md5-sha1", .@"MD5-SHA1" },
+ // .{ "dsa-sha", .@"DSA-SHA" },
+ // .{ "dsa-sha1", .@"DSA-SHA1" },
+ // .{ "ecdsa-with-sha1", .@"ecdsa-with-SHA1" },
+ // .{ "rsa-md5", .@"RSA-MD5" },
+ // .{ "rsa-sha1", .@"RSA-SHA1" },
+ // .{ "rsa-sha1-2", .@"RSA-SHA1-2" },
+ // .{ "rsa-sha224", .@"RSA-SHA224" },
+ // .{ "rsa-sha256", .@"RSA-SHA256" },
+ // .{ "rsa-sha384", .@"RSA-SHA384" },
+ // .{ "rsa-sha512", .@"RSA-SHA512" },
+ // .{ "rsa-ripemd160", .@"RSA-RIPEMD160" },
+ });
+ };
+
+ pub const Digest = [BoringSSL.EVP_MAX_MD_SIZE]u8;
+
+ pub fn init(algorithm: Algorithm, md: *const BoringSSL.EVP_MD, engine: *BoringSSL.ENGINE) EVP {
+ var ctx: BoringSSL.EVP_MD_CTX = undefined;
+ BoringSSL.EVP_MD_CTX_init(&ctx);
+ _ = BoringSSL.EVP_DigestInit_ex(&ctx, md, engine);
+
+ return .{
+ .ctx = ctx,
+ .md = md,
+ .algorithm = algorithm,
+ };
+ }
+
+ pub fn hash(this: *EVP, engine: *BoringSSL.ENGINE, input: []const u8, output: []u8) ?u32 {
+ var outsize: c_uint = @min(@truncate(u16, output.len), this.size());
+ if (BoringSSL.EVP_Digest(input.ptr, input.len, output.ptr, &outsize, this.md, engine) != 1) {
+ return null;
+ }
+
+ return outsize;
+ }
+
+ pub fn final(this: *EVP, output: []u8) []const u8 {
+ var outsize: u32 = @min(@truncate(u16, output.len), this.size());
+ if (BoringSSL.EVP_DigestFinal_ex(
+ &this.ctx,
+ output.ptr,
+ &outsize,
+ ) != 1) {
+ return "";
+ }
+
+ return output[0..outsize];
+ }
+
+ pub fn update(this: *EVP, input: []const u8) void {
+ _ = BoringSSL.EVP_DigestUpdate(&this.ctx, input.ptr, input.len);
+ }
+
+ pub fn size(this: *EVP) u16 {
+ return @truncate(u16, BoringSSL.EVP_MD_CTX_size(&this.ctx));
+ }
+
+ pub fn byNameAndEngine(engine: *BoringSSL.ENGINE, name: []const u8) ?EVP {
+
+ // none of the names are longer than 255
+ var buf: [256]u8 = undefined;
+ const len = @min(name.len, buf.len - 1);
+ _ = strings.copyLowercase(name, &buf);
+
+ if (Algorithm.map.get(buf[0..len])) |algorithm| {
+ if (algorithm == .blake2b256) {
+ return EVP.init(algorithm, BoringSSL.EVP_blake2b256(), engine);
+ }
+
+ if (BoringSSL.EVP_get_digestbyname(@tagName(algorithm))) |md| {
+ return EVP.init(algorithm, md, engine);
+ }
+ }
+
+ return null;
+ }
+
+ pub fn byName(name: ZigString, global: *JSC.JSGlobalObject) ?EVP {
+ var name_str = name.toSlice(global.allocator());
+ defer name_str.deinit();
+ return byNameAndEngine(global.bunVM().rareData().boringEngine(), name_str.slice());
+ }
+ };
+
+ fn createCryptoError(globalThis: *JSC.JSGlobalObject, err_code: u32) JSValue {
+ var outbuf: [128 + 1 + "BoringSSL error: ".len]u8 = undefined;
+ @memset(&outbuf, 0, outbuf.len);
+ outbuf[0.."BoringSSL error: ".len].* = "BoringSSL error: ".*;
+ var message_buf = outbuf["BoringSSL error: ".len..];
+
+ _ = BoringSSL.ERR_error_string_n(err_code, message_buf, message_buf.len);
+
+ const error_message: []const u8 = bun.span(std.meta.assumeSentinel(&outbuf, 0));
+ if (error_message.len == "BoringSSL error: ".len) {
+ return ZigString.static("Unknown BoringSSL error").toErrorInstance(globalThis);
+ }
+
+ return ZigString.fromUTF8(error_message).toErrorInstance(globalThis);
+ }
+ pub const CryptoHasher = struct {
+ evp: EVP = undefined,
+
+ const Digest = EVP.Digest;
+
+ pub usingnamespace JSC.Codegen.JSCryptoHasher;
+
+ pub const digest = JSC.wrapInstanceMethod(CryptoHasher, "digest_", false);
+ pub const hash = JSC.wrapStaticMethod(CryptoHasher, "hash_", false);
+
+ pub fn getByteLength(
+ this: *CryptoHasher,
+ _: *JSC.JSGlobalObject,
+ ) callconv(.C) JSC.JSValue {
+ return JSC.JSValue.jsNumber(@truncate(u16, this.evp.size()));
+ }
+
+ pub fn getAlgorithm(
+ this: *CryptoHasher,
+ globalObject: *JSC.JSGlobalObject,
+ ) callconv(.C) JSC.JSValue {
+ return ZigString.fromUTF8(std.mem.span(@tagName(this.evp.algorithm))).toValueGC(globalObject);
+ }
+
+ pub fn getAlgorithms(
+ globalThis_: *JSC.JSGlobalObject,
+ _: JSValue,
+ _: JSValue,
+ ) callconv(.C) JSC.JSValue {
+ var values = EVP.Algorithm.names.values;
+ return JSC.JSValue.createStringArray(globalThis_, &values, values.len, true);
+ }
+
+ fn hashToEncoding(
+ globalThis: *JSGlobalObject,
+ evp: *EVP,
+ input: JSC.Node.StringOrBuffer,
+ encoding: JSC.Node.Encoding,
+ ) JSC.JSValue {
+ var output_digest_buf: Digest = undefined;
+
+ const len = evp.hash(globalThis.bunVM().rareData().boringEngine(), input.slice(), &output_digest_buf) orelse {
+ const err = BoringSSL.ERR_get_error();
+ const instance = createCryptoError(globalThis, err);
+ BoringSSL.ERR_clear_error();
+ globalThis.throwValue(instance);
+ return .zero;
+ };
+ return encoding.encodeWithMaxSize(globalThis, len, BoringSSL.EVP_MAX_MD_SIZE, &output_digest_buf);
+ }
+
+ fn hashToBytes(
+ globalThis: *JSGlobalObject,
+ evp: *EVP,
+ input: JSC.Node.StringOrBuffer,
+ output: ?JSC.ArrayBuffer,
+ ) JSC.JSValue {
+ var output_digest_buf: Digest = undefined;
+ var output_digest_slice: []u8 = &output_digest_buf;
+ if (output) |output_buf| {
+ const size = evp.size();
+ var bytes = output_buf.byteSlice();
+ if (bytes.len < size) {
+ globalThis.throwInvalidArguments("TypedArray must be at least {d} bytes", .{size});
+ return JSC.JSValue.zero;
+ }
+ output_digest_slice = bytes[0..size];
+ }
+
+ const len = evp.hash(globalThis.bunVM().rareData().boringEngine(), input.slice(), output_digest_slice) orelse {
+ const err = BoringSSL.ERR_get_error();
+ const instance = createCryptoError(globalThis, err);
+ BoringSSL.ERR_clear_error();
+ globalThis.throwValue(instance);
+ return .zero;
+ };
+
+ if (output) |output_buf| {
+ return output_buf.value;
+ } else {
+ var array_buffer_out = JSC.ArrayBuffer.fromBytes(bun.default_allocator.dupe(u8, output_digest_slice[0..len]) catch unreachable, .Uint8Array);
+ return array_buffer_out.toJSUnchecked(globalThis, null);
+ }
+ }
+
+ pub fn hash_(
+ globalThis: *JSGlobalObject,
+ algorithm: ZigString,
+ input: JSC.Node.StringOrBuffer,
+ output: ?JSC.Node.StringOrBuffer,
+ ) JSC.JSValue {
+ var evp = EVP.byName(algorithm, globalThis) orelse {
+ globalThis.throwInvalidArguments("Unsupported algorithm \"{any}\"", .{algorithm});
+ return .zero;
+ };
+
+ if (output) |string_or_buffer| {
+ switch (string_or_buffer) {
+ .string => |str| {
+ const encoding = JSC.Node.Encoding.from(str) orelse {
+ globalThis.throwInvalidArguments("Unknown encoding: {s}", .{str});
+ return JSC.JSValue.zero;
+ };
+
+ return hashToEncoding(globalThis, &evp, input, encoding);
+ },
+ .buffer => |buffer| {
+ return hashToBytes(globalThis, &evp, input, buffer.buffer);
+ },
+ }
+ } else {
+ return hashToBytes(globalThis, &evp, input, null);
+ }
+ }
+
+ pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) ?*CryptoHasher {
+ var arguments = callframe.arguments(2);
+ if (arguments.len == 0) {
+ globalThis.throwInvalidArguments("Expected an algorithm name as an argument", .{});
+ return null;
+ }
+
+ const algorithm_name = arguments.ptr[0];
+ if (algorithm_name.isEmptyOrUndefinedOrNull() or !algorithm_name.isString()) {
+ globalThis.throwInvalidArguments("algorithm must be a string", .{});
+ return null;
+ }
+
+ const algorithm = algorithm_name.getZigString(globalThis);
+
+ if (algorithm.len == 0) {
+ globalThis.throwInvalidArguments("Invalid algorithm name", .{});
+ return null;
+ }
+
+ const evp = EVP.byName(algorithm, globalThis) orelse {
+ globalThis.throwInvalidArguments("Unsupported algorithm {any}", .{algorithm});
+ return null;
+ };
+ var this = bun.default_allocator.create(CryptoHasher) catch return null;
+ this.evp = evp;
+ return this;
+ }
+
+ pub fn getter(
+ _: void,
+ ctx: js.JSContextRef,
+ _: js.JSValueRef,
+ _: js.JSStringRef,
+ _: js.ExceptionRef,
+ ) js.JSValueRef {
+ return CryptoHasher.getConstructor(ctx).asObjectRef();
+ }
+
+ pub fn update(this: *CryptoHasher, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
+ const thisValue = callframe.this();
+ const arguments = callframe.arguments(2);
+ const input = arguments.ptr[0];
+ const encoding = arguments.ptr[1];
+ const buffer = JSC.Node.SliceOrBuffer.fromJSWithEncoding(globalThis.ptr(), globalThis.bunVM().allocator, input, encoding) orelse {
+ globalThis.throwInvalidArguments("expected string or buffer", .{});
+ return JSC.JSValue.zero;
+ };
+
+ defer buffer.deinit();
+
+ this.evp.update(buffer.slice());
+ const err = BoringSSL.ERR_get_error();
+ if (err != 0) {
+ const instance = createCryptoError(globalThis, err);
+ BoringSSL.ERR_clear_error();
+ globalThis.throwValue(instance);
+ return .zero;
+ }
+
+ return thisValue;
+ }
+
+ pub fn digest_(
+ this: *@This(),
+ globalThis: *JSGlobalObject,
+ output: ?JSC.Node.StringOrBuffer,
+ ) JSC.JSValue {
+ if (output) |string_or_buffer| {
+ switch (string_or_buffer) {
+ .string => |str| {
+ const encoding = JSC.Node.Encoding.from(str) orelse {
+ globalThis.throwInvalidArguments("Unknown encoding: {s}", .{str});
+ return JSC.JSValue.zero;
+ };
+
+ return this.digestToEncoding(globalThis, encoding);
+ },
+ .buffer => |buffer| {
+ return this.digestToBytes(
+ globalThis,
+ buffer.buffer,
+ );
+ },
+ }
+ } else {
+ return this.digestToBytes(globalThis, null);
+ }
+ }
+
+ fn digestToBytes(this: *CryptoHasher, globalThis: *JSGlobalObject, output: ?JSC.ArrayBuffer) JSC.JSValue {
+ var output_digest_buf: EVP.Digest = undefined;
+ var output_digest_slice: []u8 = &output_digest_buf;
+ if (output) |output_buf| {
+ var bytes = output_buf.byteSlice();
+ if (bytes.len < output_digest_buf.len) {
+ globalThis.throwInvalidArguments(comptime std.fmt.comptimePrint("TypedArray must be at least {d} bytes", .{output_digest_buf.len}), .{});
+ return JSC.JSValue.zero;
+ }
+ output_digest_slice = bytes[0..bytes.len];
+ } else {
+ output_digest_buf = std.mem.zeroes(EVP.Digest);
+ }
+
+ const result = this.evp.final(output_digest_slice);
+
+ if (output) |output_buf| {
+ return output_buf.value;
+ } else {
+ var array_buffer_out = JSC.ArrayBuffer.fromBytes(bun.default_allocator.dupe(u8, result) catch unreachable, .Uint8Array);
+ return array_buffer_out.toJSUnchecked(globalThis, null);
+ }
+ }
+
+ fn digestToEncoding(this: *CryptoHasher, globalThis: *JSGlobalObject, encoding: JSC.Node.Encoding) JSC.JSValue {
+ var output_digest_buf: EVP.Digest = std.mem.zeroes(EVP.Digest);
+
+ var output_digest_slice: []u8 = &output_digest_buf;
+
+ const out = this.evp.final(output_digest_slice);
+
+ return encoding.encodeWithMaxSize(globalThis, out.len, BoringSSL.EVP_MAX_MD_SIZE, out);
+ }
+
+ pub fn finalize(this: *CryptoHasher) callconv(.C) void {
+ VirtualMachine.get().allocator.destroy(this);
+ }
+ };
+
+ fn StaticCryptoHasher(comptime Hasher: type, comptime name: [:0]const u8) type {
return struct {
hashing: Hasher = Hasher{},
@@ -1494,13 +1902,13 @@ pub const Crypto = struct {
pub fn digest_(
this: *@This(),
globalThis: *JSGlobalObject,
- output: ?JSC.Node.StringOrBuffer,
+ output: ?JSC.Node.SliceOrBuffer,
) JSC.JSValue {
if (output) |string_or_buffer| {
switch (string_or_buffer) {
.string => |str| {
- const encoding = JSC.Node.Encoding.from(str) orelse {
- globalThis.throwInvalidArguments("Unknown encoding: {s}", .{str});
+ const encoding = JSC.Node.Encoding.from(str.slice()) orelse {
+ globalThis.throwInvalidArguments("Unknown encoding: \"{s}\"", .{str.slice()});
return JSC.JSValue.zero;
};
@@ -1574,15 +1982,14 @@ pub const Crypto = struct {
};
}
- pub const SHA1 = CryptoHasher(Hashers.SHA1, "SHA1");
- pub const MD5 = CryptoHasher(Hashers.MD5, "MD5");
- pub const MD4 = CryptoHasher(Hashers.MD4, "MD4");
- pub const SHA224 = CryptoHasher(Hashers.SHA224, "SHA224");
- pub const SHA512 = CryptoHasher(Hashers.SHA512, "SHA512");
- pub const SHA384 = CryptoHasher(Hashers.SHA384, "SHA384");
- pub const SHA256 = CryptoHasher(Hashers.SHA256, "SHA256");
- pub const SHA512_256 = CryptoHasher(Hashers.SHA512_256, "SHA512_256");
- pub const RIPEMD160 = CryptoHasher(Hashers.Hashers.RIPEMD160, "RIPEMD160");
+ pub const SHA1 = StaticCryptoHasher(Hashers.SHA1, "SHA1");
+ pub const MD5 = StaticCryptoHasher(Hashers.MD5, "MD5");
+ pub const MD4 = StaticCryptoHasher(Hashers.MD4, "MD4");
+ pub const SHA224 = StaticCryptoHasher(Hashers.SHA224, "SHA224");
+ pub const SHA512 = StaticCryptoHasher(Hashers.SHA512, "SHA512");
+ pub const SHA384 = StaticCryptoHasher(Hashers.SHA384, "SHA384");
+ pub const SHA256 = StaticCryptoHasher(Hashers.SHA256, "SHA256");
+ pub const SHA512_256 = StaticCryptoHasher(Hashers.SHA512_256, "SHA512_256");
};
pub fn nanoseconds(
diff --git a/src/bun.js/api/crypto.classes.ts b/src/bun.js/api/crypto.classes.ts
index 8ddd11caf..b3852157a 100644
--- a/src/bun.js/api/crypto.classes.ts
+++ b/src/bun.js/api/crypto.classes.ts
@@ -9,9 +9,8 @@ const names = [
"SHA384",
"SHA256",
"SHA512_256",
- "RIPEMD160",
];
-export default names.map((name) => {
+const named = names.map((name) => {
return define({
name: name,
construct: true,
@@ -41,3 +40,40 @@ export default names.map((name) => {
},
});
});
+
+export default [
+ ...named,
+ define({
+ name: "CryptoHasher",
+ construct: true,
+ finalize: true,
+ klass: {
+ hash: {
+ fn: "hash",
+ length: 2,
+ },
+ algorithms: {
+ getter: "getAlgorithms",
+ cache: true,
+ },
+ },
+ JSType: "0b11101110",
+ proto: {
+ digest: {
+ fn: "digest",
+ length: 0,
+ },
+ algorithm: {
+ getter: "getAlgorithm",
+ cache: true,
+ },
+ update: {
+ fn: "update",
+ length: 2,
+ },
+ byteLength: {
+ getter: "getByteLength",
+ },
+ },
+ }),
+];
diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig
index 79f1fe46a..427def275 100644
--- a/src/bun.js/base.zig
+++ b/src/bun.js/base.zig
@@ -2669,11 +2669,30 @@ pub fn wrapWithHasContainer(
},
?JSC.Node.StringOrBuffer => {
if (iter.nextEat()) |arg| {
- args[i] = JSC.Node.StringOrBuffer.fromJS(ctx.ptr(), iter.arena.allocator(), arg, exception) orelse {
- exception.* = JSC.toInvalidArguments("expected string or buffer", .{}, ctx).asObjectRef();
- iter.deinit();
- return null;
- };
+ if (!arg.isEmptyOrUndefinedOrNull()) {
+ args[i] = JSC.Node.StringOrBuffer.fromJS(ctx.ptr(), iter.arena.allocator(), arg, exception) orelse {
+ exception.* = JSC.toInvalidArguments("expected string or buffer", .{}, ctx).asObjectRef();
+ iter.deinit();
+ return null;
+ };
+ } else {
+ args[i] = null;
+ }
+ } else {
+ args[i] = null;
+ }
+ },
+ ?JSC.Node.SliceOrBuffer => {
+ if (iter.nextEat()) |arg| {
+ if (!arg.isEmptyOrUndefinedOrNull()) {
+ args[i] = JSC.Node.SliceOrBuffer.fromJS(ctx.ptr(), iter.arena.allocator(), arg, exception) orelse {
+ exception.* = JSC.toInvalidArguments("expected string or buffer", .{}, ctx).asObjectRef();
+ iter.deinit();
+ return null;
+ };
+ } else {
+ args[i] = null;
+ }
} else {
args[i] = null;
}
@@ -2693,11 +2712,15 @@ pub fn wrapWithHasContainer(
},
?JSC.ArrayBuffer => {
if (iter.nextEat()) |arg| {
- args[i] = arg.asArrayBuffer(ctx.ptr()) orelse {
- exception.* = JSC.toInvalidArguments("expected TypedArray", .{}, ctx).asObjectRef();
- iter.deinit();
- return null;
- };
+ if (!arg.isEmptyOrUndefinedOrNull()) {
+ args[i] = arg.asArrayBuffer(ctx.ptr()) orelse {
+ exception.* = JSC.toInvalidArguments("expected TypedArray", .{}, ctx).asObjectRef();
+ iter.deinit();
+ return null;
+ };
+ } else {
+ args[i] = null;
+ }
} else {
args[i] = null;
}
@@ -2855,11 +2878,30 @@ pub fn wrapInstanceMethod(
},
?JSC.Node.StringOrBuffer => {
if (iter.nextEat()) |arg| {
- args[i] = JSC.Node.StringOrBuffer.fromJS(globalThis.ptr(), iter.arena.allocator(), arg, null) orelse {
- globalThis.throwInvalidArguments("expected string or buffer", .{});
- iter.deinit();
- return JSC.JSValue.zero;
- };
+ if (!arg.isEmptyOrUndefinedOrNull()) {
+ args[i] = JSC.Node.StringOrBuffer.fromJS(globalThis.ptr(), iter.arena.allocator(), arg, null) orelse {
+ globalThis.throwInvalidArguments("expected string or buffer", .{});
+ iter.deinit();
+ return JSC.JSValue.zero;
+ };
+ } else {
+ args[i] = null;
+ }
+ } else {
+ args[i] = null;
+ }
+ },
+ ?JSC.Node.SliceOrBuffer => {
+ if (iter.nextEat()) |arg| {
+ if (!arg.isEmptyOrUndefinedOrNull()) {
+ args[i] = JSC.Node.SliceOrBuffer.fromJS(globalThis.ptr(), iter.arena.allocator(), arg) orelse {
+ globalThis.throwInvalidArguments("expected string or buffer", .{});
+ iter.deinit();
+ return JSC.JSValue.zero;
+ };
+ } else {
+ args[i] = null;
+ }
} else {
args[i] = null;
}
diff --git a/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h b/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h
index 484ae9c48..f74d54b02 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h
@@ -10,8 +10,8 @@ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA224Constructor;std:
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA512Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA384;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA384Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA256;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA256Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA512_256;
-std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA512_256Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForRIPEMD160;
-std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForRIPEMD160Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForServerWebSocket;
+std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA512_256Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCryptoHasher;
+std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCryptoHasherConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForServerWebSocket;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForServerWebSocketConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForFileSystemRouter;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForFileSystemRouterConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForMatchedRoute;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForExpect;
diff --git a/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h b/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h
index ebbb2f7b7..cda555fa9 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h
@@ -10,8 +10,8 @@ std::unique_ptr<IsoSubspace> m_subspaceForSHA224Constructor;std::unique_ptr<IsoS
std::unique_ptr<IsoSubspace> m_subspaceForSHA512Constructor;std::unique_ptr<IsoSubspace> m_subspaceForSHA384;
std::unique_ptr<IsoSubspace> m_subspaceForSHA384Constructor;std::unique_ptr<IsoSubspace> m_subspaceForSHA256;
std::unique_ptr<IsoSubspace> m_subspaceForSHA256Constructor;std::unique_ptr<IsoSubspace> m_subspaceForSHA512_256;
-std::unique_ptr<IsoSubspace> m_subspaceForSHA512_256Constructor;std::unique_ptr<IsoSubspace> m_subspaceForRIPEMD160;
-std::unique_ptr<IsoSubspace> m_subspaceForRIPEMD160Constructor;std::unique_ptr<IsoSubspace> m_subspaceForServerWebSocket;
+std::unique_ptr<IsoSubspace> m_subspaceForSHA512_256Constructor;std::unique_ptr<IsoSubspace> m_subspaceForCryptoHasher;
+std::unique_ptr<IsoSubspace> m_subspaceForCryptoHasherConstructor;std::unique_ptr<IsoSubspace> m_subspaceForServerWebSocket;
std::unique_ptr<IsoSubspace> m_subspaceForServerWebSocketConstructor;std::unique_ptr<IsoSubspace> m_subspaceForFileSystemRouter;
std::unique_ptr<IsoSubspace> m_subspaceForFileSystemRouterConstructor;std::unique_ptr<IsoSubspace> m_subspaceForMatchedRoute;
std::unique_ptr<IsoSubspace> m_subspaceForExpect;
diff --git a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h
index 73b96e5f6..2c0cf9929 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h
@@ -70,12 +70,12 @@ JSC::Structure* JSSHA512_256Structure() { return m_JSSHA512_256.getInitializedOn
JSC::LazyClassStructure m_JSSHA512_256;
bool hasJSSHA512_256SetterValue { false };
mutable JSC::WriteBarrier<JSC::Unknown> m_JSSHA512_256SetterValue;
-JSC::Structure* JSRIPEMD160Structure() { return m_JSRIPEMD160.getInitializedOnMainThread(this); }
- JSC::JSObject* JSRIPEMD160Constructor() { return m_JSRIPEMD160.constructorInitializedOnMainThread(this); }
- JSC::JSValue JSRIPEMD160Prototype() { return m_JSRIPEMD160.prototypeInitializedOnMainThread(this); }
- JSC::LazyClassStructure m_JSRIPEMD160;
- bool hasJSRIPEMD160SetterValue { false };
- mutable JSC::WriteBarrier<JSC::Unknown> m_JSRIPEMD160SetterValue;
+JSC::Structure* JSCryptoHasherStructure() { return m_JSCryptoHasher.getInitializedOnMainThread(this); }
+ JSC::JSObject* JSCryptoHasherConstructor() { return m_JSCryptoHasher.constructorInitializedOnMainThread(this); }
+ JSC::JSValue JSCryptoHasherPrototype() { return m_JSCryptoHasher.prototypeInitializedOnMainThread(this); }
+ JSC::LazyClassStructure m_JSCryptoHasher;
+ bool hasJSCryptoHasherSetterValue { false };
+ mutable JSC::WriteBarrier<JSC::Unknown> m_JSCryptoHasherSetterValue;
JSC::Structure* JSServerWebSocketStructure() { return m_JSServerWebSocket.getInitializedOnMainThread(this); }
JSC::JSObject* JSServerWebSocketConstructor() { return m_JSServerWebSocket.constructorInitializedOnMainThread(this); }
JSC::JSValue JSServerWebSocketPrototype() { return m_JSServerWebSocket.prototypeInitializedOnMainThread(this); }
diff --git a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h
index e0a13622a..8b4240876 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h
@@ -71,11 +71,11 @@ void GlobalObject::initGeneratedLazyClasses() {
init.setStructure(WebCore::JSSHA512_256::createStructure(init.vm, init.global, init.prototype));
init.setConstructor(WebCore::JSSHA512_256::createConstructor(init.vm, init.global, init.prototype));
});
- m_JSRIPEMD160.initLater(
+ m_JSCryptoHasher.initLater(
[](LazyClassStructure::Initializer& init) {
- init.setPrototype(WebCore::JSRIPEMD160::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global)));
- init.setStructure(WebCore::JSRIPEMD160::createStructure(init.vm, init.global, init.prototype));
- init.setConstructor(WebCore::JSRIPEMD160::createConstructor(init.vm, init.global, init.prototype));
+ init.setPrototype(WebCore::JSCryptoHasher::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global)));
+ init.setStructure(WebCore::JSCryptoHasher::createStructure(init.vm, init.global, init.prototype));
+ init.setConstructor(WebCore::JSCryptoHasher::createConstructor(init.vm, init.global, init.prototype));
});
m_JSServerWebSocket.initLater(
[](LazyClassStructure::Initializer& init) {
@@ -153,7 +153,7 @@ void GlobalObject::visitGeneratedLazyClasses(GlobalObject *thisObject, Visitor&
thisObject->m_JSSHA384.visit(visitor); visitor.append(thisObject->m_JSSHA384SetterValue);
thisObject->m_JSSHA256.visit(visitor); visitor.append(thisObject->m_JSSHA256SetterValue);
thisObject->m_JSSHA512_256.visit(visitor); visitor.append(thisObject->m_JSSHA512_256SetterValue);
- thisObject->m_JSRIPEMD160.visit(visitor); visitor.append(thisObject->m_JSRIPEMD160SetterValue);
+ thisObject->m_JSCryptoHasher.visit(visitor); visitor.append(thisObject->m_JSCryptoHasherSetterValue);
thisObject->m_JSServerWebSocket.visit(visitor); visitor.append(thisObject->m_JSServerWebSocketSetterValue);
thisObject->m_JSFileSystemRouter.visit(visitor); visitor.append(thisObject->m_JSFileSystemRouterSetterValue);
thisObject->m_JSMatchedRoute.visit(visitor); visitor.append(thisObject->m_JSMatchedRouteSetterValue);
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp
index df82bb7f0..b649229d4 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.cpp
+++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp
@@ -4265,13 +4265,13 @@ extern "C" EncodedJSValue SHA512_256__create(Zig::GlobalObject* globalObject, vo
return JSValue::encode(instance);
}
-class JSRIPEMD160Prototype final : public JSC::JSNonFinalObject {
+class JSCryptoHasherPrototype final : public JSC::JSNonFinalObject {
public:
using Base = JSC::JSNonFinalObject;
- static JSRIPEMD160Prototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure)
+ static JSCryptoHasherPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure)
{
- JSRIPEMD160Prototype* ptr = new (NotNull, JSC::allocateCell<JSRIPEMD160Prototype>(vm)) JSRIPEMD160Prototype(vm, globalObject, structure);
+ JSCryptoHasherPrototype* ptr = new (NotNull, JSC::allocateCell<JSCryptoHasherPrototype>(vm)) JSCryptoHasherPrototype(vm, globalObject, structure);
ptr->finishCreation(vm, globalObject);
return ptr;
}
@@ -4288,7 +4288,7 @@ public:
}
private:
- JSRIPEMD160Prototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
+ JSCryptoHasherPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
: Base(vm, structure)
{
}
@@ -4296,10 +4296,10 @@ private:
void finishCreation(JSC::VM&, JSC::JSGlobalObject*);
};
-class JSRIPEMD160Constructor final : public JSC::InternalFunction {
+class JSCryptoHasherConstructor final : public JSC::InternalFunction {
public:
using Base = JSC::InternalFunction;
- static JSRIPEMD160Constructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSRIPEMD160Prototype* prototype);
+ static JSCryptoHasherConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSCryptoHasherPrototype* prototype);
static constexpr unsigned StructureFlags = Base::StructureFlags;
static constexpr bool needsDestruction = false;
@@ -4313,15 +4313,15 @@ public:
{
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
return nullptr;
- return WebCore::subspaceForImpl<JSRIPEMD160Constructor, WebCore::UseCustomHeapCellType::No>(
+ return WebCore::subspaceForImpl<JSCryptoHasherConstructor, WebCore::UseCustomHeapCellType::No>(
vm,
- [](auto& spaces) { return spaces.m_clientSubspaceForRIPEMD160Constructor.get(); },
- [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForRIPEMD160Constructor = WTFMove(space); },
- [](auto& spaces) { return spaces.m_subspaceForRIPEMD160Constructor.get(); },
- [](auto& spaces, auto&& space) { spaces.m_subspaceForRIPEMD160Constructor = WTFMove(space); });
+ [](auto& spaces) { return spaces.m_clientSubspaceForCryptoHasherConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForCryptoHasherConstructor = WTFMove(space); },
+ [](auto& spaces) { return spaces.m_subspaceForCryptoHasherConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForCryptoHasherConstructor = WTFMove(space); });
}
- void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSRIPEMD160Prototype* prototype);
+ void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSCryptoHasherPrototype* prototype);
// Must be defined for each specialization class.
static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*);
@@ -4329,62 +4329,97 @@ public:
DECLARE_EXPORT_INFO;
private:
- JSRIPEMD160Constructor(JSC::VM& vm, JSC::Structure* structure);
- void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSRIPEMD160Prototype* prototype);
+ JSCryptoHasherConstructor(JSC::VM& vm, JSC::Structure* structure);
+ void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSCryptoHasherPrototype* prototype);
};
-extern "C" void* RIPEMD160Class__construct(JSC::JSGlobalObject*, JSC::CallFrame*);
-JSC_DECLARE_CUSTOM_GETTER(jsRIPEMD160Constructor);
-extern "C" void RIPEMD160Class__finalize(void*);
+extern "C" void* CryptoHasherClass__construct(JSC::JSGlobalObject*, JSC::CallFrame*);
+JSC_DECLARE_CUSTOM_GETTER(jsCryptoHasherConstructor);
+extern "C" void CryptoHasherClass__finalize(void*);
-extern "C" JSC::EncodedJSValue RIPEMD160Prototype__getByteLength(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
-JSC_DECLARE_CUSTOM_GETTER(RIPEMD160Prototype__byteLengthGetterWrap);
+extern "C" JSC::EncodedJSValue CryptoHasherPrototype__getAlgorithm(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(CryptoHasherPrototype__algorithmGetterWrap);
-extern "C" EncodedJSValue RIPEMD160Prototype__digest(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
-JSC_DECLARE_HOST_FUNCTION(RIPEMD160Prototype__digestCallback);
+extern "C" JSC::EncodedJSValue CryptoHasherPrototype__getByteLength(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(CryptoHasherPrototype__byteLengthGetterWrap);
-extern "C" EncodedJSValue RIPEMD160Prototype__update(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
-JSC_DECLARE_HOST_FUNCTION(RIPEMD160Prototype__updateCallback);
+extern "C" EncodedJSValue CryptoHasherPrototype__digest(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(CryptoHasherPrototype__digestCallback);
-STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSRIPEMD160Prototype, JSRIPEMD160Prototype::Base);
+extern "C" EncodedJSValue CryptoHasherPrototype__update(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(CryptoHasherPrototype__updateCallback);
-static const HashTableValue JSRIPEMD160PrototypeTableValues[] = {
- { "byteLength"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, RIPEMD160Prototype__byteLengthGetterWrap, 0 } },
- { "digest"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, RIPEMD160Prototype__digestCallback, 0 } },
- { "update"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, RIPEMD160Prototype__updateCallback, 1 } }
+STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSCryptoHasherPrototype, JSCryptoHasherPrototype::Base);
+
+static const HashTableValue JSCryptoHasherPrototypeTableValues[] = {
+ { "algorithm"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, CryptoHasherPrototype__algorithmGetterWrap, 0 } },
+ { "byteLength"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, CryptoHasherPrototype__byteLengthGetterWrap, 0 } },
+ { "digest"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, CryptoHasherPrototype__digestCallback, 0 } },
+ { "update"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, CryptoHasherPrototype__updateCallback, 2 } }
};
-const ClassInfo JSRIPEMD160Prototype::s_info = { "RIPEMD160"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSRIPEMD160Prototype) };
+const ClassInfo JSCryptoHasherPrototype::s_info = { "CryptoHasher"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCryptoHasherPrototype) };
-JSC_DEFINE_CUSTOM_GETTER(jsRIPEMD160Constructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName))
+JSC_DEFINE_CUSTOM_GETTER(jsCryptoHasherConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName))
{
VM& vm = JSC::getVM(lexicalGlobalObject);
auto throwScope = DECLARE_THROW_SCOPE(vm);
auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
- auto* prototype = jsDynamicCast<JSRIPEMD160Prototype*>(JSValue::decode(thisValue));
+ auto* prototype = jsDynamicCast<JSCryptoHasherPrototype*>(JSValue::decode(thisValue));
if (UNLIKELY(!prototype))
return throwVMTypeError(lexicalGlobalObject, throwScope);
- return JSValue::encode(globalObject->JSRIPEMD160Constructor());
+ return JSValue::encode(globalObject->JSCryptoHasherConstructor());
+}
+
+JSC_DEFINE_CUSTOM_GETTER(CryptoHasherPrototype__algorithmGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCryptoHasher* thisObject = jsCast<JSCryptoHasher*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ if (JSValue cachedValue = thisObject->m_algorithm.get())
+ return JSValue::encode(cachedValue);
+
+ JSC::JSValue result = JSC::JSValue::decode(
+ CryptoHasherPrototype__getAlgorithm(thisObject->wrapped(), globalObject));
+ RETURN_IF_EXCEPTION(throwScope, {});
+ thisObject->m_algorithm.set(vm, thisObject, result);
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
}
-JSC_DEFINE_CUSTOM_GETTER(RIPEMD160Prototype__byteLengthGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+extern "C" void CryptoHasherPrototype__algorithmSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value)
+{
+ auto& vm = globalObject->vm();
+ auto* thisObject = jsCast<JSCryptoHasher*>(JSValue::decode(thisValue));
+ thisObject->m_algorithm.set(vm, thisObject, JSValue::decode(value));
+}
+
+extern "C" EncodedJSValue CryptoHasherPrototype__algorithmGetCachedValue(JSC::EncodedJSValue thisValue)
+{
+ auto* thisObject = jsCast<JSCryptoHasher*>(JSValue::decode(thisValue));
+ return JSValue::encode(thisObject->m_algorithm.get());
+}
+
+JSC_DEFINE_CUSTOM_GETTER(CryptoHasherPrototype__byteLengthGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
{
auto& vm = lexicalGlobalObject->vm();
Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
auto throwScope = DECLARE_THROW_SCOPE(vm);
- JSRIPEMD160* thisObject = jsCast<JSRIPEMD160*>(JSValue::decode(thisValue));
+ JSCryptoHasher* thisObject = jsCast<JSCryptoHasher*>(JSValue::decode(thisValue));
JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
- JSC::EncodedJSValue result = RIPEMD160Prototype__getByteLength(thisObject->wrapped(), globalObject);
+ JSC::EncodedJSValue result = CryptoHasherPrototype__getByteLength(thisObject->wrapped(), globalObject);
RETURN_IF_EXCEPTION(throwScope, {});
RELEASE_AND_RETURN(throwScope, result);
}
-JSC_DEFINE_HOST_FUNCTION(RIPEMD160Prototype__digestCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+JSC_DEFINE_HOST_FUNCTION(CryptoHasherPrototype__digestCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
{
auto& vm = lexicalGlobalObject->vm();
- JSRIPEMD160* thisObject = jsDynamicCast<JSRIPEMD160*>(callFrame->thisValue());
+ JSCryptoHasher* thisObject = jsDynamicCast<JSCryptoHasher*>(callFrame->thisValue());
if (UNLIKELY(!thisObject)) {
auto throwScope = DECLARE_THROW_SCOPE(vm);
@@ -4393,14 +4428,14 @@ JSC_DEFINE_HOST_FUNCTION(RIPEMD160Prototype__digestCallback, (JSGlobalObject * l
JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
- return RIPEMD160Prototype__digest(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+ return CryptoHasherPrototype__digest(thisObject->wrapped(), lexicalGlobalObject, callFrame);
}
-JSC_DEFINE_HOST_FUNCTION(RIPEMD160Prototype__updateCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+JSC_DEFINE_HOST_FUNCTION(CryptoHasherPrototype__updateCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
{
auto& vm = lexicalGlobalObject->vm();
- JSRIPEMD160* thisObject = jsDynamicCast<JSRIPEMD160*>(callFrame->thisValue());
+ JSCryptoHasher* thisObject = jsDynamicCast<JSCryptoHasher*>(callFrame->thisValue());
if (UNLIKELY(!thisObject)) {
auto throwScope = DECLARE_THROW_SCOPE(vm);
@@ -4409,51 +4444,51 @@ JSC_DEFINE_HOST_FUNCTION(RIPEMD160Prototype__updateCallback, (JSGlobalObject * l
JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
- return RIPEMD160Prototype__update(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+ return CryptoHasherPrototype__update(thisObject->wrapped(), lexicalGlobalObject, callFrame);
}
-void JSRIPEMD160Prototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
+void JSCryptoHasherPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
{
Base::finishCreation(vm);
- reifyStaticProperties(vm, JSRIPEMD160::info(), JSRIPEMD160PrototypeTableValues, *this);
+ reifyStaticProperties(vm, JSCryptoHasher::info(), JSCryptoHasherPrototypeTableValues, *this);
JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
}
-extern "C" JSC_DECLARE_CUSTOM_GETTER(RIPEMD160Class__getByteLengthStatic);
-extern "C" JSC_DECLARE_HOST_FUNCTION(RIPEMD160Class__hash);
+extern "C" JSC_DECLARE_CUSTOM_GETTER(CryptoHasherClass__getAlgorithms);
+extern "C" JSC_DECLARE_HOST_FUNCTION(CryptoHasherClass__hash);
-static const HashTableValue JSRIPEMD160ConstructorTableValues[] = {
- { "byteLength"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, RIPEMD160Class__getByteLengthStatic, 0 } },
- { "hash"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, RIPEMD160Class__hash, 2 } }
+static const HashTableValue JSCryptoHasherConstructorTableValues[] = {
+ { "algorithms"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, CryptoHasherClass__getAlgorithms, 0 } },
+ { "hash"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, CryptoHasherClass__hash, 2 } }
};
-void JSRIPEMD160Constructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSRIPEMD160Prototype* prototype)
+void JSCryptoHasherConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSCryptoHasherPrototype* prototype)
{
- Base::finishCreation(vm, 0, "RIPEMD160"_s, PropertyAdditionMode::WithoutStructureTransition);
- reifyStaticProperties(vm, &JSRIPEMD160Constructor::s_info, JSRIPEMD160ConstructorTableValues, *this);
+ Base::finishCreation(vm, 0, "CryptoHasher"_s, PropertyAdditionMode::WithoutStructureTransition);
+ reifyStaticProperties(vm, &JSCryptoHasherConstructor::s_info, JSCryptoHasherConstructorTableValues, *this);
putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
ASSERT(inherits(info()));
}
-JSRIPEMD160Constructor::JSRIPEMD160Constructor(JSC::VM& vm, JSC::Structure* structure)
+JSCryptoHasherConstructor::JSCryptoHasherConstructor(JSC::VM& vm, JSC::Structure* structure)
: Base(vm, structure, construct, construct)
{
}
-JSRIPEMD160Constructor* JSRIPEMD160Constructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSRIPEMD160Prototype* prototype)
+JSCryptoHasherConstructor* JSCryptoHasherConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSCryptoHasherPrototype* prototype)
{
- JSRIPEMD160Constructor* ptr = new (NotNull, JSC::allocateCell<JSRIPEMD160Constructor>(vm)) JSRIPEMD160Constructor(vm, structure);
+ JSCryptoHasherConstructor* ptr = new (NotNull, JSC::allocateCell<JSCryptoHasherConstructor>(vm)) JSCryptoHasherConstructor(vm, structure);
ptr->finishCreation(vm, globalObject, prototype);
return ptr;
}
-JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSRIPEMD160Constructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
+JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSCryptoHasherConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
{
Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
JSC::VM& vm = globalObject->vm();
JSObject* newTarget = asObject(callFrame->newTarget());
- auto* constructor = globalObject->JSRIPEMD160Constructor();
- Structure* structure = globalObject->JSRIPEMD160Structure();
+ auto* constructor = globalObject->JSCryptoHasherConstructor();
+ Structure* structure = globalObject->JSCryptoHasherStructure();
if (constructor != newTarget) {
auto scope = DECLARE_THROW_SCOPE(vm);
@@ -4464,64 +4499,64 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSRIPEMD160Constructor::construct(J
structure = InternalFunction::createSubclassStructure(
globalObject,
newTarget,
- functionGlobalObject->JSRIPEMD160Structure());
+ functionGlobalObject->JSCryptoHasherStructure());
}
- void* ptr = RIPEMD160Class__construct(globalObject, callFrame);
+ void* ptr = CryptoHasherClass__construct(globalObject, callFrame);
if (UNLIKELY(!ptr)) {
return JSValue::encode(JSC::jsUndefined());
}
- JSRIPEMD160* instance = JSRIPEMD160::create(vm, globalObject, structure, ptr);
+ JSCryptoHasher* instance = JSCryptoHasher::create(vm, globalObject, structure, ptr);
return JSValue::encode(instance);
}
-void JSRIPEMD160Constructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSRIPEMD160Prototype* prototype)
+void JSCryptoHasherConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSCryptoHasherPrototype* prototype)
{
}
-const ClassInfo JSRIPEMD160Constructor::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSRIPEMD160Constructor) };
+const ClassInfo JSCryptoHasherConstructor::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCryptoHasherConstructor) };
-extern "C" EncodedJSValue RIPEMD160__getConstructor(Zig::GlobalObject* globalObject)
+extern "C" EncodedJSValue CryptoHasher__getConstructor(Zig::GlobalObject* globalObject)
{
- return JSValue::encode(globalObject->JSRIPEMD160Constructor());
+ return JSValue::encode(globalObject->JSCryptoHasherConstructor());
}
-JSRIPEMD160::~JSRIPEMD160()
+JSCryptoHasher::~JSCryptoHasher()
{
if (m_ctx) {
- RIPEMD160Class__finalize(m_ctx);
+ CryptoHasherClass__finalize(m_ctx);
}
}
-void JSRIPEMD160::destroy(JSCell* cell)
+void JSCryptoHasher::destroy(JSCell* cell)
{
- static_cast<JSRIPEMD160*>(cell)->JSRIPEMD160::~JSRIPEMD160();
+ static_cast<JSCryptoHasher*>(cell)->JSCryptoHasher::~JSCryptoHasher();
}
-const ClassInfo JSRIPEMD160::s_info = { "RIPEMD160"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSRIPEMD160) };
+const ClassInfo JSCryptoHasher::s_info = { "CryptoHasher"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCryptoHasher) };
-void JSRIPEMD160::finishCreation(VM& vm)
+void JSCryptoHasher::finishCreation(VM& vm)
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
}
-JSRIPEMD160* JSRIPEMD160::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx)
+JSCryptoHasher* JSCryptoHasher::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx)
{
- JSRIPEMD160* ptr = new (NotNull, JSC::allocateCell<JSRIPEMD160>(vm)) JSRIPEMD160(vm, structure, ctx);
+ JSCryptoHasher* ptr = new (NotNull, JSC::allocateCell<JSCryptoHasher>(vm)) JSCryptoHasher(vm, structure, ctx);
ptr->finishCreation(vm);
return ptr;
}
-extern "C" void* RIPEMD160__fromJS(JSC::EncodedJSValue value)
+extern "C" void* CryptoHasher__fromJS(JSC::EncodedJSValue value)
{
JSC::JSValue decodedValue = JSC::JSValue::decode(value);
if (!decodedValue || decodedValue.isUndefinedOrNull())
return nullptr;
- JSRIPEMD160* object = JSC::jsDynamicCast<JSRIPEMD160*>(decodedValue);
+ JSCryptoHasher* object = JSC::jsDynamicCast<JSCryptoHasher*>(decodedValue);
if (!object)
return nullptr;
@@ -4529,9 +4564,9 @@ extern "C" void* RIPEMD160__fromJS(JSC::EncodedJSValue value)
return object->wrapped();
}
-extern "C" bool RIPEMD160__dangerouslySetPtr(JSC::EncodedJSValue value, void* ptr)
+extern "C" bool CryptoHasher__dangerouslySetPtr(JSC::EncodedJSValue value, void* ptr)
{
- JSRIPEMD160* object = JSC::jsDynamicCast<JSRIPEMD160*>(JSValue::decode(value));
+ JSCryptoHasher* object = JSC::jsDynamicCast<JSCryptoHasher*>(JSValue::decode(value));
if (!object)
return false;
@@ -4539,11 +4574,11 @@ extern "C" bool RIPEMD160__dangerouslySetPtr(JSC::EncodedJSValue value, void* pt
return true;
}
-extern "C" const size_t RIPEMD160__ptrOffset = JSRIPEMD160::offsetOfWrapped();
+extern "C" const size_t CryptoHasher__ptrOffset = JSCryptoHasher::offsetOfWrapped();
-void JSRIPEMD160::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
+void JSCryptoHasher::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
{
- auto* thisObject = jsCast<JSRIPEMD160*>(cell);
+ auto* thisObject = jsCast<JSCryptoHasher*>(cell);
if (void* wrapped = thisObject->wrapped()) {
// if (thisObject->scriptExecutionContext())
// analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string());
@@ -4551,24 +4586,60 @@ void JSRIPEMD160::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
Base::analyzeHeap(cell, analyzer);
}
-JSObject* JSRIPEMD160::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+JSObject* JSCryptoHasher::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
- return WebCore::JSRIPEMD160Constructor::create(vm, globalObject, WebCore::JSRIPEMD160Constructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<WebCore::JSRIPEMD160Prototype*>(prototype));
+ return WebCore::JSCryptoHasherConstructor::create(vm, globalObject, WebCore::JSCryptoHasherConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<WebCore::JSCryptoHasherPrototype*>(prototype));
}
-JSObject* JSRIPEMD160::createPrototype(VM& vm, JSDOMGlobalObject* globalObject)
+JSObject* JSCryptoHasher::createPrototype(VM& vm, JSDOMGlobalObject* globalObject)
{
- return JSRIPEMD160Prototype::create(vm, globalObject, JSRIPEMD160Prototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
+ return JSCryptoHasherPrototype::create(vm, globalObject, JSCryptoHasherPrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
}
-extern "C" EncodedJSValue RIPEMD160__create(Zig::GlobalObject* globalObject, void* ptr)
+extern "C" EncodedJSValue CryptoHasher__create(Zig::GlobalObject* globalObject, void* ptr)
{
auto& vm = globalObject->vm();
- JSC::Structure* structure = globalObject->JSRIPEMD160Structure();
- JSRIPEMD160* instance = JSRIPEMD160::create(vm, globalObject, structure, ptr);
+ JSC::Structure* structure = globalObject->JSCryptoHasherStructure();
+ JSCryptoHasher* instance = JSCryptoHasher::create(vm, globalObject, structure, ptr);
return JSValue::encode(instance);
}
+
+template<typename Visitor>
+void JSCryptoHasher::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+ JSCryptoHasher* thisObject = jsCast<JSCryptoHasher*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+
+ visitor.append(thisObject->m_algorithms);
+ visitor.append(thisObject->m_algorithm);
+}
+
+DEFINE_VISIT_CHILDREN(JSCryptoHasher);
+
+template<typename Visitor>
+void JSCryptoHasher::visitAdditionalChildren(Visitor& visitor)
+{
+ JSCryptoHasher* thisObject = this;
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+
+ visitor.append(thisObject->m_algorithms);
+ visitor.append(thisObject->m_algorithm);
+ ;
+}
+
+DEFINE_VISIT_ADDITIONAL_CHILDREN(JSCryptoHasher);
+
+template<typename Visitor>
+void JSCryptoHasher::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor)
+{
+ JSCryptoHasher* thisObject = jsCast<JSCryptoHasher*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ thisObject->visitAdditionalChildren<Visitor>(visitor);
+}
+
+DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSCryptoHasher);
class JSServerWebSocketPrototype final : public JSC::JSNonFinalObject {
public:
using Base = JSC::JSNonFinalObject;
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.h b/src/bun.js/bindings/ZigGeneratedClasses.h
index 9046a002e..aee32a315 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses.h
@@ -725,22 +725,22 @@ public:
void finishCreation(JSC::VM&);
};
-class JSRIPEMD160 final : public JSC::JSDestructibleObject {
+class JSCryptoHasher final : public JSC::JSDestructibleObject {
public:
using Base = JSC::JSDestructibleObject;
- static JSRIPEMD160* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx);
+ static JSCryptoHasher* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx);
DECLARE_EXPORT_INFO;
template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
return nullptr;
- return WebCore::subspaceForImpl<JSRIPEMD160, WebCore::UseCustomHeapCellType::No>(
+ return WebCore::subspaceForImpl<JSCryptoHasher, WebCore::UseCustomHeapCellType::No>(
vm,
- [](auto& spaces) { return spaces.m_clientSubspaceForRIPEMD160.get(); },
- [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForRIPEMD160 = WTFMove(space); },
- [](auto& spaces) { return spaces.m_subspaceForRIPEMD160.get(); },
- [](auto& spaces, auto&& space) { spaces.m_subspaceForRIPEMD160 = WTFMove(space); });
+ [](auto& spaces) { return spaces.m_clientSubspaceForCryptoHasher.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForCryptoHasher = WTFMove(space); },
+ [](auto& spaces) { return spaces.m_subspaceForCryptoHasher.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForCryptoHasher = WTFMove(space); });
}
static void destroy(JSC::JSCell*);
@@ -752,7 +752,7 @@ public:
static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject);
static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype);
- ~JSRIPEMD160();
+ ~JSCryptoHasher();
void* wrapped() const { return m_ctx; }
@@ -762,17 +762,24 @@ public:
}
static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&);
- static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSRIPEMD160, m_ctx); }
+ static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSCryptoHasher, m_ctx); }
void* m_ctx { nullptr };
- JSRIPEMD160(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr)
+ JSCryptoHasher(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr)
: Base(vm, structure)
{
m_ctx = sinkPtr;
}
void finishCreation(JSC::VM&);
+
+ DECLARE_VISIT_CHILDREN;
+ template<typename Visitor> void visitAdditionalChildren(Visitor&);
+ DECLARE_VISIT_OUTPUT_CONSTRAINTS;
+
+ mutable JSC::WriteBarrier<JSC::Unknown> m_algorithms;
+ mutable JSC::WriteBarrier<JSC::Unknown> m_algorithm;
};
class JSServerWebSocket final : public JSC::JSDestructibleObject {
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index 2226d0fb5..5713a530b 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -91,6 +91,68 @@ pub const ZigString = extern struct {
ptr: [*]const u8,
len: usize,
+ /// This function is not optimized!
+ pub fn eqlCaseInsensitive(this: ZigString, other: ZigString) bool {
+ var fallback = std.heap.stackFallback(1024, bun.default_allocator);
+ var fallback_allocator = fallback.get();
+
+ var utf16_slice = this.toSliceLowercase(fallback_allocator);
+ var latin1_slice = other.toSliceLowercase(fallback_allocator);
+ defer utf16_slice.deinit();
+ defer latin1_slice.deinit();
+ return strings.eqlLong(utf16_slice.slice(), latin1_slice.slice(), true);
+ }
+
+ pub fn toSliceLowercase(this: ZigString, allocator: std.mem.Allocator) Slice {
+ if (this.len == 0)
+ return Slice.empty;
+ var fallback = std.heap.stackFallback(512, allocator);
+ var fallback_allocator = fallback.get();
+
+ var uppercase_buffer = this.toOwnedSlice(fallback_allocator) catch unreachable;
+ var buffer = allocator.alloc(u8, uppercase_buffer.len) catch unreachable;
+ var out = strings.copyLowercase(uppercase_buffer, buffer);
+
+ return Slice{
+ .allocator = NullableAllocator.init(allocator),
+ .ptr = out.ptr,
+ .len = @truncate(u32, out.len),
+ };
+ }
+
+ pub fn eql(this: ZigString, other: ZigString) bool {
+ const left_utf16 = this.is16Bit();
+ const right_utf16 = other.is16Bit();
+
+ if (left_utf16 == right_utf16 and left_utf16) {
+ return strings.eqlLong(std.mem.sliceAsBytes(this.utf16SliceAligned()), std.mem.sliceAsBytes(other.utf16SliceAligned()), true);
+ } else if (left_utf16 == right_utf16) {
+ return strings.eqlLong(this.slice(), other.slice(), true);
+ }
+
+ const utf16: ZigString = if (left_utf16) this else other;
+ const latin1: ZigString = if (left_utf16) other else this;
+
+ if (latin1.isAllASCII()) {
+ return strings.utf16EqlString(utf16.utf16SliceAligned(), latin1.slice());
+ }
+
+ // slow path
+ var utf16_slice = utf16.toSlice(bun.default_allocator);
+ var latin1_slice = latin1.toSlice(bun.default_allocator);
+ defer utf16_slice.deinit();
+ defer latin1_slice.deinit();
+ return strings.eqlLong(utf16_slice.slice(), latin1_slice.slice(), true);
+ }
+
+ pub fn isAllASCII(this: ZigString) bool {
+ if (this.is16Bit()) {
+ return strings.firstNonASCII16([]const u16, this.utf16SliceAligned()) == null;
+ }
+
+ return strings.isAllASCII(this.slice());
+ }
+
pub fn clone(this: ZigString, allocator: std.mem.Allocator) !ZigString {
var sliced = this.toSlice(allocator);
if (!sliced.isAllocated()) {
@@ -209,6 +271,14 @@ pub const ZigString = extern struct {
ptr: [*]const u8 = undefined,
len: u32 = 0,
+ pub fn from(input: []u8, allocator: std.mem.Allocator) Slice {
+ return .{
+ .ptr = input.ptr,
+ .len = @truncate(u32, input.len),
+ .allocator = NullableAllocator.init(allocator),
+ };
+ }
+
pub fn fromUTF8NeverFree(input: []const u8) Slice {
return .{
.ptr = input.ptr,
diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig
index 87ab124ce..c64acbef5 100644
--- a/src/bun.js/bindings/generated_classes.zig
+++ b/src/bun.js/bindings/generated_classes.zig
@@ -1284,88 +1284,114 @@ pub const JSSHA512_256 = struct {
}
}
};
-pub const JSRIPEMD160 = struct {
- const RIPEMD160 = Classes.RIPEMD160;
- const GetterType = fn (*RIPEMD160, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue;
- const GetterTypeWithThisValue = fn (*RIPEMD160, JSC.JSValue, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue;
- const SetterType = fn (*RIPEMD160, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool;
- const SetterTypeWithThisValue = fn (*RIPEMD160, JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool;
- const CallbackType = fn (*RIPEMD160, *JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue;
+pub const JSCryptoHasher = struct {
+ const CryptoHasher = Classes.CryptoHasher;
+ const GetterType = fn (*CryptoHasher, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue;
+ const GetterTypeWithThisValue = fn (*CryptoHasher, JSC.JSValue, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue;
+ const SetterType = fn (*CryptoHasher, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool;
+ const SetterTypeWithThisValue = fn (*CryptoHasher, JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool;
+ const CallbackType = fn (*CryptoHasher, *JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue;
/// Return the pointer to the wrapped object.
/// If the object does not match the type, return null.
- pub fn fromJS(value: JSC.JSValue) ?*RIPEMD160 {
+ pub fn fromJS(value: JSC.JSValue) ?*CryptoHasher {
JSC.markBinding(@src());
- return RIPEMD160__fromJS(value);
+ return CryptoHasher__fromJS(value);
}
- /// Get the RIPEMD160 constructor value.
+ extern fn CryptoHasherPrototype__algorithmSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void;
+
+ extern fn CryptoHasherPrototype__algorithmGetCachedValue(JSC.JSValue) JSC.JSValue;
+
+ /// `CryptoHasher.algorithm` setter
+ /// This value will be visited by the garbage collector.
+ pub fn algorithmSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void {
+ JSC.markBinding(@src());
+ CryptoHasherPrototype__algorithmSetCachedValue(thisValue, globalObject, value);
+ }
+
+ /// `CryptoHasher.algorithm` getter
+ /// This value will be visited by the garbage collector.
+ pub fn algorithmGetCached(thisValue: JSC.JSValue) ?JSC.JSValue {
+ JSC.markBinding(@src());
+ const result = CryptoHasherPrototype__algorithmGetCachedValue(thisValue);
+ if (result == .zero)
+ return null;
+
+ return result;
+ }
+
+ /// Get the CryptoHasher constructor value.
/// This loads lazily from the global object.
pub fn getConstructor(globalObject: *JSC.JSGlobalObject) JSC.JSValue {
JSC.markBinding(@src());
- return RIPEMD160__getConstructor(globalObject);
+ return CryptoHasher__getConstructor(globalObject);
}
- /// Create a new instance of RIPEMD160
- pub fn toJS(this: *RIPEMD160, globalObject: *JSC.JSGlobalObject) JSC.JSValue {
+ /// Create a new instance of CryptoHasher
+ pub fn toJS(this: *CryptoHasher, globalObject: *JSC.JSGlobalObject) JSC.JSValue {
JSC.markBinding(@src());
if (comptime Environment.allow_assert) {
- const value__ = RIPEMD160__create(globalObject, this);
- std.debug.assert(value__.as(RIPEMD160).? == this); // If this fails, likely a C ABI issue.
+ const value__ = CryptoHasher__create(globalObject, this);
+ std.debug.assert(value__.as(CryptoHasher).? == this); // If this fails, likely a C ABI issue.
return value__;
} else {
- return RIPEMD160__create(globalObject, this);
+ return CryptoHasher__create(globalObject, this);
}
}
- /// Modify the internal ptr to point to a new instance of RIPEMD160.
- pub fn dangerouslySetPtr(value: JSC.JSValue, ptr: ?*RIPEMD160) bool {
+ /// Modify the internal ptr to point to a new instance of CryptoHasher.
+ pub fn dangerouslySetPtr(value: JSC.JSValue, ptr: ?*CryptoHasher) bool {
JSC.markBinding(@src());
- return RIPEMD160__dangerouslySetPtr(value, ptr);
+ return CryptoHasher__dangerouslySetPtr(value, ptr);
}
/// Detach the ptr from the thisValue
- pub fn detachPtr(_: *RIPEMD160, value: JSC.JSValue) void {
+ pub fn detachPtr(_: *CryptoHasher, value: JSC.JSValue) void {
JSC.markBinding(@src());
- std.debug.assert(RIPEMD160__dangerouslySetPtr(value, null));
+ std.debug.assert(CryptoHasher__dangerouslySetPtr(value, null));
}
- extern fn RIPEMD160__fromJS(JSC.JSValue) ?*RIPEMD160;
- extern fn RIPEMD160__getConstructor(*JSC.JSGlobalObject) JSC.JSValue;
+ extern fn CryptoHasher__fromJS(JSC.JSValue) ?*CryptoHasher;
+ extern fn CryptoHasher__getConstructor(*JSC.JSGlobalObject) JSC.JSValue;
- extern fn RIPEMD160__create(globalObject: *JSC.JSGlobalObject, ptr: ?*RIPEMD160) JSC.JSValue;
+ extern fn CryptoHasher__create(globalObject: *JSC.JSGlobalObject, ptr: ?*CryptoHasher) JSC.JSValue;
- extern fn RIPEMD160__dangerouslySetPtr(JSC.JSValue, ?*RIPEMD160) bool;
+ extern fn CryptoHasher__dangerouslySetPtr(JSC.JSValue, ?*CryptoHasher) bool;
comptime {
- if (@TypeOf(RIPEMD160.constructor) != (fn (*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*RIPEMD160)) {
- @compileLog("RIPEMD160.constructor is not a constructor");
+ if (@TypeOf(CryptoHasher.constructor) != (fn (*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*CryptoHasher)) {
+ @compileLog("CryptoHasher.constructor is not a constructor");
}
- if (@TypeOf(RIPEMD160.finalize) != (fn (*RIPEMD160) callconv(.C) void)) {
- @compileLog("RIPEMD160.finalize is not a finalizer");
+ if (@TypeOf(CryptoHasher.finalize) != (fn (*CryptoHasher) callconv(.C) void)) {
+ @compileLog("CryptoHasher.finalize is not a finalizer");
}
- if (@TypeOf(RIPEMD160.getByteLength) != GetterType)
- @compileLog("Expected RIPEMD160.getByteLength to be a getter");
+ if (@TypeOf(CryptoHasher.getAlgorithm) != GetterType)
+ @compileLog("Expected CryptoHasher.getAlgorithm to be a getter");
+
+ if (@TypeOf(CryptoHasher.getByteLength) != GetterType)
+ @compileLog("Expected CryptoHasher.getByteLength to be a getter");
- if (@TypeOf(RIPEMD160.digest) != CallbackType)
- @compileLog("Expected RIPEMD160.digest to be a callback but received " ++ @typeName(@TypeOf(RIPEMD160.digest)));
- if (@TypeOf(RIPEMD160.update) != CallbackType)
- @compileLog("Expected RIPEMD160.update to be a callback but received " ++ @typeName(@TypeOf(RIPEMD160.update)));
- if (@TypeOf(RIPEMD160.getByteLengthStatic) != StaticGetterType)
- @compileLog("Expected RIPEMD160.getByteLengthStatic to be a static getter");
+ if (@TypeOf(CryptoHasher.digest) != CallbackType)
+ @compileLog("Expected CryptoHasher.digest to be a callback but received " ++ @typeName(@TypeOf(CryptoHasher.digest)));
+ if (@TypeOf(CryptoHasher.update) != CallbackType)
+ @compileLog("Expected CryptoHasher.update to be a callback but received " ++ @typeName(@TypeOf(CryptoHasher.update)));
+ if (@TypeOf(CryptoHasher.getAlgorithms) != StaticGetterType)
+ @compileLog("Expected CryptoHasher.getAlgorithms to be a static getter");
- if (@TypeOf(RIPEMD160.hash) != StaticCallbackType)
- @compileLog("Expected RIPEMD160.hash to be a static callback");
+ if (@TypeOf(CryptoHasher.hash) != StaticCallbackType)
+ @compileLog("Expected CryptoHasher.hash to be a static callback");
if (!JSC.is_bindgen) {
- @export(RIPEMD160.constructor, .{ .name = "RIPEMD160Class__construct" });
- @export(RIPEMD160.digest, .{ .name = "RIPEMD160Prototype__digest" });
- @export(RIPEMD160.finalize, .{ .name = "RIPEMD160Class__finalize" });
- @export(RIPEMD160.getByteLength, .{ .name = "RIPEMD160Prototype__getByteLength" });
- @export(RIPEMD160.getByteLengthStatic, .{ .name = "RIPEMD160Class__getByteLengthStatic" });
- @export(RIPEMD160.hash, .{ .name = "RIPEMD160Class__hash" });
- @export(RIPEMD160.update, .{ .name = "RIPEMD160Prototype__update" });
+ @export(CryptoHasher.constructor, .{ .name = "CryptoHasherClass__construct" });
+ @export(CryptoHasher.digest, .{ .name = "CryptoHasherPrototype__digest" });
+ @export(CryptoHasher.finalize, .{ .name = "CryptoHasherClass__finalize" });
+ @export(CryptoHasher.getAlgorithm, .{ .name = "CryptoHasherPrototype__getAlgorithm" });
+ @export(CryptoHasher.getAlgorithms, .{ .name = "CryptoHasherClass__getAlgorithms" });
+ @export(CryptoHasher.getByteLength, .{ .name = "CryptoHasherPrototype__getByteLength" });
+ @export(CryptoHasher.hash, .{ .name = "CryptoHasherClass__hash" });
+ @export(CryptoHasher.update, .{ .name = "CryptoHasherPrototype__update" });
}
}
};
@@ -3276,7 +3302,7 @@ comptime {
_ = JSSHA384;
_ = JSSHA256;
_ = JSSHA512_256;
- _ = JSRIPEMD160;
+ _ = JSCryptoHasher;
_ = JSServerWebSocket;
_ = JSFileSystemRouter;
_ = JSMatchedRoute;
diff --git a/src/bun.js/bindings/generated_classes_list.zig b/src/bun.js/bindings/generated_classes_list.zig
index bb386816d..2eaf30e04 100644
--- a/src/bun.js/bindings/generated_classes_list.zig
+++ b/src/bun.js/bindings/generated_classes_list.zig
@@ -11,7 +11,7 @@ pub const Classes = struct {
pub const SHA384 = JSC.API.Bun.Crypto.SHA384;
pub const SHA256 = JSC.API.Bun.Crypto.SHA256;
pub const SHA512_256 = JSC.API.Bun.Crypto.SHA512_256;
- pub const RIPEMD160 = JSC.API.Bun.Crypto.RIPEMD160;
+ pub const CryptoHasher = JSC.API.Bun.Crypto.CryptoHasher;
pub const TextDecoder = JSC.WebCore.TextDecoder;
pub const Blob = JSC.WebCore.Blob;
pub const Subprocess = JSC.Subprocess;
diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig
index ed202830c..deacd6d1e 100644
--- a/src/bun.js/node/types.zig
+++ b/src/bun.js/node/types.zig
@@ -373,6 +373,82 @@ pub const SliceOrBuffer = union(Tag) {
else => null,
};
}
+
+ pub fn fromJSWithEncoding(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding_value: JSC.JSValue) ?SliceOrBuffer {
+ if (encoding_value.isEmptyOrUndefinedOrNull())
+ return fromJS(global, allocator, value);
+
+ switch (value.jsType()) {
+ .ArrayBuffer,
+ .Int8Array,
+ .Uint8Array,
+ .Uint8ClampedArray,
+ .Int16Array,
+ .Uint16Array,
+ .Int32Array,
+ .Uint32Array,
+ .Float32Array,
+ .Float64Array,
+ .BigInt64Array,
+ .BigUint64Array,
+ .DataView,
+ => return SliceOrBuffer{
+ .buffer = JSC.MarkedArrayBuffer{
+ .buffer = value.asArrayBuffer(global) orelse return null,
+ .allocator = null,
+ },
+ },
+ else => {},
+ }
+
+ var encoding_str = encoding_value.toSlice(global, allocator);
+ if (encoding_str.len == 0)
+ return fromJS(global, allocator, value);
+
+ defer encoding_str.deinit();
+ // TODO: better error
+ const encoding = Encoding.from(encoding_str.slice()) orelse return null;
+ if (encoding == .utf8) {
+ return fromJS(global, allocator, value);
+ }
+
+ var zig_str = value.getZigString(global);
+ if (zig_str.len == 0) {
+ return fromJS(global, allocator, value);
+ }
+
+ const out = brk: {
+ if (zig_str.is16Bit()) {
+ const buf = zig_str.slice();
+ break :brk switch (encoding) {
+ Encoding.utf8 => JSC.WebCore.Encoder.constructFromU8(buf.ptr, buf.len, .utf8),
+ Encoding.ucs2 => JSC.WebCore.Encoder.constructFromU8(buf.ptr, buf.len, .ucs2),
+ Encoding.utf16le => JSC.WebCore.Encoder.constructFromU8(buf.ptr, buf.len, .utf16le),
+ Encoding.latin1 => JSC.WebCore.Encoder.constructFromU8(buf.ptr, buf.len, .latin1),
+ Encoding.ascii => JSC.WebCore.Encoder.constructFromU8(buf.ptr, buf.len, .ascii),
+ Encoding.base64 => JSC.WebCore.Encoder.constructFromU8(buf.ptr, buf.len, .base64),
+ Encoding.hex => JSC.WebCore.Encoder.constructFromU8(buf.ptr, buf.len, .hex),
+ Encoding.buffer => JSC.WebCore.Encoder.constructFromU8(buf.ptr, buf.len, .buffer),
+ Encoding.base64url => JSC.WebCore.Encoder.constructFromU8(buf.ptr, buf.len, .base64url),
+ };
+ } else {
+ const buf = zig_str.utf16SliceAligned();
+ break :brk switch (encoding) {
+ Encoding.utf8 => JSC.WebCore.Encoder.constructFromU16(buf.ptr, buf.len, .utf8),
+ Encoding.ucs2 => JSC.WebCore.Encoder.constructFromU16(buf.ptr, buf.len, .ucs2),
+ Encoding.utf16le => JSC.WebCore.Encoder.constructFromU16(buf.ptr, buf.len, .utf16le),
+ Encoding.latin1 => JSC.WebCore.Encoder.constructFromU16(buf.ptr, buf.len, .latin1),
+ Encoding.ascii => JSC.WebCore.Encoder.constructFromU16(buf.ptr, buf.len, .ascii),
+ Encoding.base64 => JSC.WebCore.Encoder.constructFromU16(buf.ptr, buf.len, .base64),
+ Encoding.hex => JSC.WebCore.Encoder.constructFromU16(buf.ptr, buf.len, .hex),
+ Encoding.buffer => JSC.WebCore.Encoder.constructFromU16(buf.ptr, buf.len, .buffer),
+ Encoding.base64url => JSC.WebCore.Encoder.constructFromU16(buf.ptr, buf.len, .base64url),
+ };
+ }
+ };
+
+ return .{ .string = JSC.ZigString.Slice.from(out, allocator) };
+ }
};
pub const ErrorCode = @import("./nodejs_error_code.zig").Code;
@@ -459,6 +535,36 @@ pub const Encoding = enum(u8) {
},
}
}
+
+ pub fn encodeWithMaxSize(encoding: Encoding, globalThis: *JSC.JSGlobalObject, size: usize, comptime max_size: usize, input: []const u8) JSC.JSValue {
+ switch (encoding) {
+ .base64 => {
+ var base64_buf: [std.base64.standard.Encoder.calcSize(max_size)]u8 = undefined;
+ var base64 = base64_buf[0..std.base64.standard.Encoder.calcSize(size)];
+ const result = JSC.ZigString.init(std.base64.standard.Encoder.encode(base64, input)).toValueGC(globalThis);
+ return result;
+ },
+ .base64url => {
+ var buf_: [std.base64.url_safe.Encoder.calcSize(max_size) + "data:;base64,".len]u8 = undefined;
+ var buf = buf_[0 .. std.base64.url_safe.Encoder.calcSize(size) + "data:;base64,".len];
+ var encoded = std.base64.url_safe.Encoder.encode(buf["data:;base64,".len..], input);
+ buf[0.."data:;base64,".len].* = "data:;base64,".*;
+
+ const result = JSC.ZigString.init(buf[0 .. "data:;base64,".len + encoded.len]).toValueGC(globalThis);
+ return result;
+ },
+ .hex => {
+ var buf: [max_size * 4]u8 = undefined;
+ var out = std.fmt.bufPrint(&buf, "{}", .{std.fmt.fmtSliceHexLower(input)}) catch unreachable;
+ const result = JSC.ZigString.init(out).toValueGC(globalThis);
+ return result;
+ },
+ else => {
+ globalThis.throwInvalidArguments("Unexpected encoding", .{});
+ return JSC.JSValue.zero;
+ },
+ }
+ }
};
const PathOrBuffer = union(Tag) {
diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig
index 9573b1f3a..19c370143 100644
--- a/src/bun.js/webcore/encoding.zig
+++ b/src/bun.js/webcore/encoding.zig
@@ -1145,7 +1145,8 @@ pub const Encoder = struct {
},
JSC.Node.Encoding.latin1, JSC.Node.Encoding.buffer, JSC.Node.Encoding.ascii => {
var to = allocator.alloc(u8, len) catch return &[_]u8{};
- @memcpy(to.ptr, input, len);
+ var input_bytes = std.mem.sliceAsBytes(input[0..len]);
+ @memcpy(to.ptr, input_bytes.ptr, input_bytes.len);
for (to[0..len]) |c, i| {
to[i] = @as(u8, @truncate(u7, c));
}
diff --git a/src/deps/boringssl.translated.zig b/src/deps/boringssl.translated.zig
index a26a64154..d2b863e2f 100644
--- a/src/deps/boringssl.translated.zig
+++ b/src/deps/boringssl.translated.zig
@@ -1339,9 +1339,22 @@ pub extern fn EVP_MD_CTX_move(out: [*c]EVP_MD_CTX, in: [*c]EVP_MD_CTX) void;
pub extern fn EVP_MD_CTX_reset(ctx: *EVP_MD_CTX) c_int;
pub extern fn EVP_DigestInit_ex(ctx: *EVP_MD_CTX, @"type": ?*const EVP_MD, engine: ?*ENGINE) c_int;
pub extern fn EVP_DigestInit(ctx: *EVP_MD_CTX, @"type": ?*const EVP_MD) c_int;
+/// EVP_DigestUpdate hashes |len| bytes from |data| into the hashing operation
+/// in |ctx|. It returns one.
pub extern fn EVP_DigestUpdate(ctx: *EVP_MD_CTX, data: ?[*]const u8, len: usize) c_int;
-pub extern fn EVP_DigestFinal_ex(ctx: *EVP_MD_CTX, md_out: [*]u8, out_size: ?[*]c_uint) c_int;
-pub extern fn EVP_DigestFinal(ctx: *EVP_MD_CTX, md_out: [*]u8, out_size: ?[*]c_uint) c_int;
+/// EVP_DigestFinal_ex finishes the digest in |ctx| and writes the output to
+/// |md_out|. |EVP_MD_CTX_size| bytes are written, which is at most
+/// |EVP_MAX_MD_SIZE|. If |out_size| is not NULL then |*out_size| is set to the
+/// number of bytes written. It returns one. After this call, the hash cannot be
+/// updated or finished again until |EVP_DigestInit_ex| is called to start
+/// another hashing operation.
+pub extern fn EVP_DigestFinal_ex(ctx: *EVP_MD_CTX, md_out: [*]u8, out_size: ?*u32) c_int;
+pub extern fn EVP_DigestFinal(ctx: *EVP_MD_CTX, md_out: [*]u8, out_size: ?*u32) c_int;
+/// EVP_Digest performs a complete hashing operation in one call. It hashes |len|
+/// bytes from |data| and writes the digest to |md_out|. |EVP_MD_CTX_size| bytes
+/// are written, which is at most |EVP_MAX_MD_SIZE|. If |out_size| is not NULL
+/// then |*out_size| is set to the number of bytes written. It returns one on
+/// success and zero otherwise.
pub extern fn EVP_Digest(data: ?[*]const u8, len: usize, md_out: [*c]u8, md_out_size: [*c]c_uint, @"type": ?*const EVP_MD, impl: ?*ENGINE) c_int;
pub extern fn EVP_MD_type(md: ?*const EVP_MD) c_int;
pub extern fn EVP_MD_flags(md: ?*const EVP_MD) u32;
diff --git a/test/bun.js/crypto.test.js b/test/bun.js/crypto.test.js
index 30a0f227d..8b93dab64 100644
--- a/test/bun.js/crypto.test.js
+++ b/test/bun.js/crypto.test.js
@@ -8,8 +8,8 @@ import {
SHA384,
SHA512,
SHA512_256,
- RIPEMD160,
gc,
+ CryptoHasher,
} from "bun";
import { it, expect, describe } from "bun:test";
import { readFileSync } from "fs";
@@ -23,9 +23,52 @@ const HashClasses = [
SHA384,
SHA512,
SHA512_256,
- RIPEMD160,
];
+describe("CryptoHasher", () => {
+ it("CryptoHasher.algorithms", () => {
+ expect(CryptoHasher.algorithms).toEqual([
+ "blake2b256",
+ "md4",
+ "md5",
+ "ripemd160",
+ "sha1",
+ "sha224",
+ "sha256",
+ "sha384",
+ "sha512",
+ "sha512-256",
+ ]);
+ });
+
+ it("CryptoHasher md5", () => {
+ var hasher = new CryptoHasher("md5");
+ hasher.update("hello world");
+ expect(hasher.digest("hex")).toBe("5eb63bbbe01eeed093cb22bb8f5acdc3");
+ expect(hasher.algorithm).toBe("md5");
+ });
+
+ it("CryptoHasher blake2b256", () => {
+ var hasher = new CryptoHasher("blake2b256");
+ hasher.update("hello world");
+ expect(hasher.algorithm).toBe("blake2b256");
+
+ expect(hasher.digest("hex")).toBe(
+ // b2sum --length=256
+ "256c83b297114d201b30179f3f0ef0cace9783622da5974326b436178aeef610",
+ );
+ });
+
+ it("CryptoHasher sha512", () => {
+ var hasher = new CryptoHasher("sha512");
+ hasher.update("hello world");
+ expect(hasher.digest("hex")).toBe(
+ "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f",
+ );
+ expect(hasher.algorithm).toBe("sha512");
+ });
+});
+
describe("crypto", () => {
for (let Hash of HashClasses) {
for (let [input, label] of [