From 3a907af08bb8c338c00f48c3032f15c82ed297bf Mon Sep 17 00:00:00 2001 From: mstrasinskis <98811342+mstrasinskis@users.noreply.github.com> Date: Fri, 3 Jun 2022 10:17:33 +0200 Subject: [PATCH] fix: add setBigUint64 polyfill (#577) * fix: add setBigUint64 polyfill * test: makeNonce setBigUint64 polyfill * test: update makeNonce polyfill test (should create same value) --- packages/agent/src/agent/http/http.test.ts | 48 +++++++++++++++++++--- packages/agent/src/agent/http/types.ts | 9 +++- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/packages/agent/src/agent/http/http.test.ts b/packages/agent/src/agent/http/http.test.ts index e68ddfd43..21cf8d002 100644 --- a/packages/agent/src/agent/http/http.test.ts +++ b/packages/agent/src/agent/http/http.test.ts @@ -362,10 +362,46 @@ describe('replace identity', () => { expect(mockFetch).toBeCalledTimes(1); }); }); -describe('makeNonce should create unique values', () => { - const nonces = new Set(); - for (let i = 0; i < 100; i++) { - nonces.add(toHexString(makeNonce())); - } - expect(nonces.size).toBe(100); + +describe('makeNonce', () => { + it('should create unique values', () => { + const nonces = new Set(); + for (let i = 0; i < 100; i++) { + nonces.add(toHexString(makeNonce())); + } + expect(nonces.size).toBe(100); + }); + + describe('setBigUint64 polyfill', () => { + const DataViewConstructor = DataView; + let spyOnSetUint32: jest.SpyInstance; + let usePolyfill = false; + + beforeAll(() => { + jest.spyOn(Math, 'random').mockImplementation(() => 0.5); + jest.spyOn(globalThis, 'DataView').mockImplementation(buffer => { + const view: DataView = new DataViewConstructor(buffer); + view.setBigUint64 = usePolyfill ? undefined : view.setBigUint64; + spyOnSetUint32 = jest.spyOn(view, 'setUint32'); + return view; + }); + }); + + afterAll(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('should create same value using polyfill', () => { + const originalNonce = toHexString(makeNonce()); + expect(spyOnSetUint32).toBeCalledTimes(2); + + usePolyfill = true; + + const nonce = toHexString(makeNonce()); + expect(spyOnSetUint32).toBeCalledTimes(4); + + expect(nonce).toBe(originalNonce); + }); + }); }); diff --git a/packages/agent/src/agent/http/types.ts b/packages/agent/src/agent/http/types.ts index ff8e3da92..e0dcfc489 100644 --- a/packages/agent/src/agent/http/types.ts +++ b/packages/agent/src/agent/http/types.ts @@ -110,7 +110,14 @@ export function makeNonce(): Nonce { const now = BigInt(+Date.now()); const randHi = Math.floor(Math.random() * 0xffffffff); const randLo = Math.floor(Math.random() * 0xffffffff); - view.setBigUint64(0, now); + // Fix for IOS < 14.8 setBigUint64 absence + if (typeof view.setBigUint64 === 'function') { + view.setBigUint64(0, now); + } else { + const TWO_TO_THE_32 = BigInt(1) << BigInt(32); + view.setUint32(0, Number(now >> BigInt(32))); + view.setUint32(4, Number(now % TWO_TO_THE_32)); + } view.setUint32(8, randHi); view.setUint32(12, randLo);