diff --git a/packages/playwright-core/src/utils/isomorphic/utilityScriptSerializers.ts b/packages/playwright-core/src/utils/isomorphic/utilityScriptSerializers.ts index a523528f27975..6be0773adb097 100644 --- a/packages/playwright-core/src/utils/isomorphic/utilityScriptSerializers.ts +++ b/packages/playwright-core/src/utils/isomorphic/utilityScriptSerializers.ts @@ -28,7 +28,8 @@ export type SerializedValue = { o: { k: string, v: SerializedValue }[], id: number } | { ref: number } | { h: number } | - { ta: { b: string, k: TypedArrayKind } }; + { ta: { b: string, k: TypedArrayKind } } | + { ab: { b: string } }; type HandleOrValue = { h: number } | { fallThrough: any }; @@ -78,6 +79,14 @@ function isTypedArray(obj: any, constructor: Function): boolean { } } +function isArrayBuffer(obj: any): obj is ArrayBuffer { + try { + return obj instanceof ArrayBuffer || Object.prototype.toString.call(obj) === '[object ArrayBuffer]'; + } catch (error) { + return false; + } +} + const typedArrayConstructors: Record = { i8: Int8Array, ui8: Uint8Array, @@ -170,6 +179,8 @@ export function parseEvaluationResultValue(value: SerializedValue, handles: any[ return handles[value.h]; if ('ta' in value) return base64ToTypedArray(value.ta.b, typedArrayConstructors[value.ta.k]); + if ('ab' in value) + return base64ToTypedArray(value.ab.b, Uint8Array).buffer; } return value; } @@ -244,6 +255,8 @@ function innerSerialize(value: any, handleSerializer: (value: any) => HandleOrVa if (isTypedArray(value, ctor)) return { ta: { b: typedArrayToBase64(value), k } }; } + if (isArrayBuffer(value)) + return { ab: { b: typedArrayToBase64(new Uint8Array(value)) } }; const id = visitorInfo.visited.get(value); if (id) diff --git a/tests/assets/to-do-notifications/scripts/todo.js b/tests/assets/to-do-notifications/scripts/todo.js index 52fee476a9545..42dd19a0c4097 100644 --- a/tests/assets/to-do-notifications/scripts/todo.js +++ b/tests/assets/to-do-notifications/scripts/todo.js @@ -91,11 +91,13 @@ window.onload = () => { } // Check which suffix the deadline day of the month needs - const { hours, minutes, day, month, year, notified, taskTitle } = cursor.value; + const { hours, minutes, day, month, year, notified, taskTitle, binaryTitle } = cursor.value; const ordDay = ordinal(day); + const decodedBinaryTitle = new TextDecoder().decode(new Uint8Array(binaryTitle)); + // Build the to-do list entry and put it into the list item. - const toDoText = `${taskTitle} — ${hours}:${minutes}, ${month} ${ordDay} ${year}.`; + const toDoText = `${taskTitle} [${decodedBinaryTitle}] — ${hours}:${minutes}, ${month} ${ordDay} ${year}.`; const listItem = createListItem(toDoText); if (notified === 'yes') { @@ -140,7 +142,7 @@ window.onload = () => { // Grab the values entered into the form fields and store them in an object ready for being inserted into the IndexedDB const newItem = [ - { taskTitle: title.value, hours: hours.value, minutes: minutes.value, day: day.value, month: month.value, year: year.value, notified: 'no' }, + { taskTitle: title.value, hours: hours.value, minutes: minutes.value, day: day.value, month: month.value, year: year.value, notified: 'no', binaryTitle: new TextEncoder().encode(title.value).buffer }, ]; // Open a read/write DB transaction, ready for adding the data diff --git a/tests/library/browsercontext-storage-state.spec.ts b/tests/library/browsercontext-storage-state.spec.ts index 4f4fca6cee201..b3e0d5bae94b2 100644 --- a/tests/library/browsercontext-storage-state.spec.ts +++ b/tests/library/browsercontext-storage-state.spec.ts @@ -409,14 +409,18 @@ it('should support IndexedDB', async ({ page, server, contextFactory }) => { keyPath: 'taskTitle', records: [ { - value: { - day: '01', - hours: '1', - minutes: '1', - month: 'January', - notified: 'no', - taskTitle: 'Pet the cat', - year: '2025', + valueEncoded: { + id: 1, + o: [ + { k: 'taskTitle', v: 'Pet the cat' }, + { k: 'hours', v: '1' }, + { k: 'minutes', v: '1' }, + { k: 'day', v: '01' }, + { k: 'month', v: 'January' }, + { k: 'year', v: '2025' }, + { k: 'notified', v: 'no' }, + { k: 'binaryTitle', v: { ab: { b: 'UGV0IHRoZSBjYXQ=' } }, } + ] }, }, ], @@ -473,7 +477,7 @@ it('should support IndexedDB', async ({ page, server, contextFactory }) => { await expect(recreatedPage.locator('#task-list')).toMatchAriaSnapshot(` - list: - listitem: - - text: /Pet the cat/ + - text: /Pet the cat \\[Pet the cat\\]/ `); expect(await context.storageState()).toEqual({ cookies: [], origins: [] });