diff --git a/.changeset/tough-timers-admire.md b/.changeset/tough-timers-admire.md new file mode 100644 index 00000000..c628c843 --- /dev/null +++ b/.changeset/tough-timers-admire.md @@ -0,0 +1,5 @@ +--- +"vinxi": patch +--- + +fix: hash chunks with djb2 diff --git a/packages/vinxi/lib/chunks.js b/packages/vinxi/lib/chunks.js index 2e30f940..81242c4f 100644 --- a/packages/vinxi/lib/chunks.js +++ b/packages/vinxi/lib/chunks.js @@ -1,7 +1,7 @@ import { readFileSync } from "fs"; -import { join } from "vinxi/lib/path"; import { viteManifestPath } from "./manifest-path.js"; +import { join } from "./path.js"; const CHUNK_PREFIX = "c_"; @@ -57,19 +57,31 @@ export const chunksServerVirtualModule = `; }; +const hashes = new Map(); +const regexReturnCharacters = /\r/g; + /** + * djb2 hashing * - * @param {string} str - * @returns + * @param {string} input + * @returns {string} + * + * Source: https://github.com/sveltejs/svelte/blob/0203eb319b5d86138236158e3ae6ecf29e26864c/packages/svelte/src/utils.js#L7 + * Source License: MIT */ -export function hash(str) { - let hash = 0; +export function hash(input) { + const cachedResult = hashes.get(input); + if (cachedResult) return cachedResult; - for (let i = 0; i < str.length; i++) { - hash += str.charCodeAt(i); - } + let str = input.replace(regexReturnCharacters, ""); + let hash = 5381; + let i = str.length; + + while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i); + const result = (hash >>> 0).toString(36); + hashes.set(input, result); - return hash; + return result; } /** diff --git a/packages/vinxi/lib/chunks.test.js b/packages/vinxi/lib/chunks.test.js new file mode 100644 index 00000000..ae9acc55 --- /dev/null +++ b/packages/vinxi/lib/chunks.test.js @@ -0,0 +1,9 @@ +import { describe, expect, it } from "vitest"; + +import { hash } from "./chunks"; + +describe("hash", () => { + it("should create different hashes for abc and cba", () => { + expect(hash("abc")).not.toEqual(hash("cba")); + }); +});