···11+---
22+'@urql/core': patch
33+---
44+55+Reuse output of `stringifyDocument` in place of repeated `print`. This will mean that we now prevent calling `print` repeatedly for identical operations and are instead only reusing the result once.
66+77+This change has a subtle consequence of our internals. Operation keys will change due to this
88+refactor and we will no longer sanitise strip newlines from queries that `@urql/core` has printed.
···11+import { HashValue, phash } from './hash';
22+import { expect, it } from 'vitest';
33+44+it('hashes given strings', () => {
55+ expect(phash('hello')).toMatchInlineSnapshot('261238937');
66+});
77+88+it('hashes given strings and seeds', () => {
99+ let hash: HashValue;
1010+ expect((hash = phash('hello'))).toMatchInlineSnapshot('261238937');
1111+ expect((hash = phash('world', hash))).toMatchInlineSnapshot('-152191');
1212+ expect((hash = phash('!', hash))).toMatchInlineSnapshot('-5022270');
1313+ expect(typeof hash).toBe('number');
1414+});
+5-5
packages/core/src/utils/hash.ts
···11+export type HashValue = number & { readonly _opaque: unique symbol };
22+13// When we have separate strings it's useful to run a progressive
24// version of djb2 where we pretend that we're still looping over
35// the same string
44-export const phash = (h: number, x: string): number => {
66+export const phash = (x: string, seed?: HashValue): HashValue => {
77+ let h = typeof seed === 'number' ? seed | 0 : 5381;
58 for (let i = 0, l = x.length | 0; i < l; i++)
69 h = (h << 5) + h + x.charCodeAt(i);
77- return h | 0;
1010+ return h as HashValue;
811};
99-1010-// This is a djb2 hashing function
1111-export const hash = (x: string): number => phash(5381 | 0, x) >>> 0;