Skip to content

Commit d498224

Browse files
committed
Switch to isomorphic hash function to avoid build stress of getting crypto right
1 parent 76a99f6 commit d498224

File tree

4 files changed

+23
-15
lines changed

4 files changed

+23
-15
lines changed

src/class-model.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import type {
3030
} from "./types";
3131
import { $fastInstantiator, buildFastInstantiator } from "./fast-instantiator";
3232
import memoize from "lodash.memoize";
33-
import { sha1 } from "./utils";
33+
import { cyrb53 } from "./utils";
3434

3535
/** @internal */
3636
type ActionMetadata = {
@@ -296,7 +296,7 @@ export function register<Instance, Klass extends { new (...args: any[]): Instanc
296296
klass.schemaHash = memoize(async () => {
297297
const props = Object.entries(klass.properties as Record<string, IAnyType>).sort(([key1], [key2]) => key1.localeCompare(key2));
298298
const propHashes = await Promise.all(props.map(async ([key, prop]) => `${key}:${await prop.schemaHash()}`));
299-
return `model:${klass.name}:${await sha1(propHashes.join("|"))}`;
299+
return `model:${klass.name}:${cyrb53(propHashes.join("|"))}`;
300300
});
301301

302302
// create the MST type for not-readonly versions of this using the views and actions extracted from the class

src/model.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import type {
2323
IStateTreeNode,
2424
} from "./types";
2525
import memoize from "lodash.memoize";
26-
import { sha1 } from "./utils";
26+
import { cyrb53 } from "./utils";
2727

2828
export const propsFromModelPropsDeclaration = <Props extends ModelPropertiesDeclaration>(
2929
propsDecl: Props
@@ -257,7 +257,7 @@ export class ModelType<Props extends ModelProperties, Others> extends BaseType<
257257
schemaHash: () => Promise<string> = memoize(async () => {
258258
const props = Object.entries(this.properties).sort(([key1], [key2]) => key1.localeCompare(key2));
259259
const propHashes = await Promise.all(props.map(async ([key, prop]) => `${key}:${await prop.schemaHash()}`));
260-
return `model:${this.name}:${await sha1(propHashes.join("|"))}`;
260+
return `model:${this.name}:${cyrb53(propHashes.join("|"))}`;
261261
});
262262
}
263263

src/union.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import memoize from "lodash.memoize";
2-
import type { IType, UnionOptions as MSTUnionOptions } from "mobx-state-tree";
2+
import type { UnionOptions as MSTUnionOptions } from "mobx-state-tree";
33
import { types as mstTypes } from "mobx-state-tree";
44
import { BaseType } from "./base";
55
import { ensureRegistered, isClassModel } from "./class-model";
@@ -8,7 +8,7 @@ import { OptionalType } from "./optional";
88
import { isModelType, isType } from "./api";
99
import { LiteralType } from "./simple";
1010
import { InvalidDiscriminatorError } from "./errors";
11-
import { sha1 } from "./utils";
11+
import { cyrb53 } from "./utils";
1212

1313
export type ITypeDispatcher = (snapshot: any) => IAnyType;
1414

@@ -138,7 +138,7 @@ class UnionType<Types extends IAnyType[]> extends BaseType<
138138
}
139139

140140
schemaHash = memoize(async () => {
141-
return await sha1(`union:${(await Promise.all(this.types.map((type) => type.schemaHash()))).join("|")}`);
141+
return cyrb53(`union:${(await Promise.all(this.types.map((type) => type.schemaHash()))).join("|")}`).toString();
142142
});
143143
}
144144

src/utils.ts

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
const crypto = typeof window === "undefined" ? require("crypto") : window.crypto;
2-
3-
export async function sha1(source: string) {
4-
const sourceBytes = new TextEncoder().encode(source);
5-
const digest: ArrayBuffer = await crypto.subtle.digest("SHA-1", sourceBytes);
6-
const resultBytes = [...new Uint8Array(digest)];
7-
return resultBytes.map((x) => x.toString(16).padStart(2, "0")).join("");
8-
}
1+
/**
2+
* General purpose fast hashing function that works in the browser and in node.
3+
* Credit https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript
4+
**/
5+
export const cyrb53 = (str: string, seed = 0) => {
6+
let h1 = 0xdeadbeef ^ seed,
7+
h2 = 0x41c6ce57 ^ seed;
8+
for (let i = 0, ch; i < str.length; i++) {
9+
ch = str.charCodeAt(i);
10+
h1 = Math.imul(h1 ^ ch, 2654435761);
11+
h2 = Math.imul(h2 ^ ch, 1597334677);
12+
}
13+
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
14+
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
15+
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
16+
};

0 commit comments

Comments
 (0)