polyfill structuredclone on legacy browsers

Fixes APP-T4SK
This commit is contained in:
Samuel Newman
2026-08-28 14:10:14 +01:00
parent 00dc9598fc
commit 3e48da80e4
4 changed files with 52 additions and 2 deletions
+2
View File
@@ -155,6 +155,7 @@
"@types/invariant": "^2.2.37",
"@types/lodash.throttle": "^4.1.9",
"@types/node": "^24.12.2",
"@ungap/structured-clone": "1.3.1",
"array.prototype.findlast": "^1.2.3",
"babel-plugin-transform-remove-console": "^6.9.4",
"bcp-47": "^2.1.0",
@@ -284,6 +285,7 @@
"@types/psl": "1.1.1",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@types/ungap__structured-clone": "1.2.0",
"@typescript/native": "npm:typescript@^7.0.2",
"babel-jest": "^29.7.0",
"babel-plugin-module-resolver": "^5.0.2",
+11
View File
@@ -410,6 +410,9 @@ importers:
'@types/node':
specifier: ^24.12.2
version: 24.12.4
'@ungap/structured-clone':
specifier: 1.3.1
version: 1.3.1
array.prototype.findlast:
specifier: ^1.2.3
version: 1.2.5
@@ -792,6 +795,9 @@ importers:
'@types/react-dom':
specifier: ^19.2.3
version: 19.2.4(@types/react@19.2.18)
'@types/ungap__structured-clone':
specifier: 1.2.0
version: 1.2.0
'@typescript/native':
specifier: npm:typescript@^7.0.2
version: typescript@7.0.2
@@ -3945,6 +3951,9 @@ packages:
'@types/tough-cookie@4.0.5':
resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
'@types/ungap__structured-clone@1.2.0':
resolution: {integrity: sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA==}
'@types/use-sync-external-store@0.0.6':
resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
@@ -13426,6 +13435,8 @@ snapshots:
'@types/tough-cookie@4.0.5': {}
'@types/ungap__structured-clone@1.2.0': {}
'@types/use-sync-external-store@0.0.6': {}
'@types/ws@8.18.1':
+29
View File
@@ -0,0 +1,29 @@
import {RichText} from '@bsky/sdk/richtext'
describe('web polyfills', () => {
const nativeStructuredClone = globalThis.structuredClone
afterEach(() => {
globalThis.structuredClone = nativeStructuredClone
})
it('supports rich text when structuredClone is unavailable', async () => {
Reflect.deleteProperty(globalThis, 'structuredClone')
let structuredCloneReady: Promise<void> | undefined
jest.isolateModules(() => {
const polyfills =
require('./polyfills.web') as typeof import('./polyfills.web')
structuredCloneReady = polyfills.structuredCloneReady
})
await structuredCloneReady
const richText = new RichText(
{text: 'hello\n\n\nworld'},
{cleanNewlines: true},
)
expect(richText.text).toBe('hello\n\nworld')
expect(richText.clone()).toEqual(richText)
})
})
+10 -2
View File
@@ -1,6 +1,16 @@
import 'array.prototype.findlast/auto'
import 'setimmediate'
export const structuredCloneReady: Promise<void> =
typeof globalThis.structuredClone === 'function'
? Promise.resolve()
: import('@ungap/structured-clone').then(({default: structuredClone}) => {
if (typeof globalThis.structuredClone !== 'function') {
globalThis.structuredClone =
structuredClone as typeof globalThis.structuredClone
}
})
if (process.env.NODE_ENV !== 'production') {
// In development, react-native-web's <View> tries to validate that
// text is wrapped into <Text>. It doesn't catch all cases but is useful.
@@ -30,5 +40,3 @@ if (process.env.NODE_ENV !== 'production') {
}
}
}
export {}