From d4381959756888a423bf7aa79585b73785b67d6d Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Sun, 22 Mar 2020 20:26:15 +0000 Subject: [PATCH] Fix hashing by generating random, stable key for non-objects Any object without any enumerable keys that isn't a plain object will now receive a random key. --- .../core/src/utils/stringifyVariables.test.ts | 15 +++++++++------ packages/core/src/utils/stringifyVariables.ts | 12 ++++++++++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/core/src/utils/stringifyVariables.test.ts b/packages/core/src/utils/stringifyVariables.test.ts index 4c72eb77ae..3489fb93a4 100644 --- a/packages/core/src/utils/stringifyVariables.test.ts +++ b/packages/core/src/utils/stringifyVariables.test.ts @@ -34,14 +34,17 @@ it('stringifies dates correctly', () => { expect(stringifyVariables(date)).toBe(date.toJSON()); }); +it('stringifies dictionaries (Object.create(null)) correctly', () => { + expect(stringifyVariables(Object.create(null))).toBe('{}'); +}); + it('stringifies files correctly', () => { const file = new File([0] as any, 'test.js'); Object.defineProperty(file, 'lastModified', { value: 123 }); + const str = stringifyVariables(file); + expect(str).toBe(stringifyVariables(file)); - expect(stringifyVariables(file)).toBe( - stringifyVariables({ - name: 'test.js', - lastModified: 123, - }) - ); + const otherFile = new File([0] as any, 'otherFile.js'); + Object.defineProperty(otherFile, 'lastModified', { value: 234 }); + expect(str).not.toBe(stringifyVariables(otherFile)); }); diff --git a/packages/core/src/utils/stringifyVariables.ts b/packages/core/src/utils/stringifyVariables.ts index 25884a9085..2ddab6c401 100644 --- a/packages/core/src/utils/stringifyVariables.ts +++ b/packages/core/src/utils/stringifyVariables.ts @@ -1,4 +1,5 @@ const seen = new Set(); +const cache = new WeakMap(); const stringify = (x: any): string => { if (x === undefined) { @@ -26,11 +27,18 @@ const stringify = (x: any): string => { return out; } else if (seen.has(x)) { throw new TypeError('Converting circular structure to JSON'); - } else if (typeof File === 'function' && x instanceof File) { - return stringify({ name: x.name, lastModified: x.lastModified }); } const keys = Object.keys(x).sort(); + if (!keys.length && x.constructor && x.constructor !== Object) { + const key = + cache.get(x) || + Math.random() + .toString(36) + .slice(2); + cache.set(x, key); + return `{"__key":"${key}"}`; + } seen.add(x); out = '{';