Skip to content

Commit

Permalink
[v2] breaking: do not throw promises
Browse files Browse the repository at this point in the history
  • Loading branch information
dai-shi committed Nov 10, 2023
1 parent cdc9c30 commit 40636a2
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 104 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@
"postinstall-postinstall": "^2.1.0",
"prettier": "^3.0.3",
"proxy-memoize": "^2.0.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "18.3.0-canary-c47c306a7-20231109",
"react-dom": "18.3.0-canary-c47c306a7-20231109",
"redux": "^4.2.1",
"rollup": "^4.2.0",
"rollup-plugin-esbuild": "^6.1.0",
Expand Down
13 changes: 3 additions & 10 deletions src/react.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
/// <reference types="react/experimental" />

import ReactExports, {
useCallback,
useDebugValue,
useEffect,
useMemo,
useRef,
} from 'react'
import { useCallback, useDebugValue, useEffect, useMemo, useRef } from 'react'
import {
affectedToPathList,
createProxy as createProxyToCompare,
Expand All @@ -21,7 +15,6 @@ import useSyncExternalStoreExports from 'use-sync-external-store/shim'
import { snapshot, subscribe } from './vanilla.ts'
import type { INTERNAL_Snapshot as Snapshot } from './vanilla.ts'

const { use } = ReactExports
const { useSyncExternalStore } = useSyncExternalStoreExports

const useAffectedDebugValue = (
Expand Down Expand Up @@ -133,7 +126,7 @@ export function useSnapshot<T extends object>(
[proxyObject, notifyInSync]
),
() => {
const nextSnapshot = snapshot(proxyObject, use)
const nextSnapshot = snapshot(proxyObject)
try {
if (
!inRender &&
Expand All @@ -154,7 +147,7 @@ export function useSnapshot<T extends object>(
}
return nextSnapshot
},
() => snapshot(proxyObject, use)
() => snapshot(proxyObject)
)
inRender = false
const currAffected = new WeakMap()
Expand Down
47 changes: 5 additions & 42 deletions src/vanilla.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ type SnapshotIgnore =

type Snapshot<T> = T extends SnapshotIgnore
? T
: T extends Promise<unknown>
? Awaited<T>
: T extends object
? { readonly [K in keyof T]: Snapshot<T[K]> }
: T
Expand All @@ -45,13 +43,7 @@ type Snapshot<T> = T extends SnapshotIgnore
*/
export type INTERNAL_Snapshot<T> = Snapshot<T>

type HandlePromise = <P extends Promise<any>>(promise: P) => Awaited<P>

type CreateSnapshot = <T extends object>(
target: T,
version: number,
handlePromise?: HandlePromise
) => T
type CreateSnapshot = <T extends object>(target: T, version: number) => T

type RemoveListener = () => void
type AddListener = (listener: Listener) => RemoveListener
Expand Down Expand Up @@ -86,29 +78,11 @@ const buildProxyFunction = (
!(x instanceof RegExp) &&
!(x instanceof ArrayBuffer),

defaultHandlePromise = <P extends Promise<any>>(
promise: P & {
status?: 'pending' | 'fulfilled' | 'rejected'
value?: Awaited<P>
reason?: unknown
}
) => {
switch (promise.status) {
case 'fulfilled':
return promise.value as Awaited<P>
case 'rejected':
throw promise.reason
default:
throw promise
}
},

snapCache = new WeakMap<object, [version: number, snap: unknown]>(),

createSnapshot: CreateSnapshot = <T extends object>(
target: T,
version: number,
handlePromise: HandlePromise = defaultHandlePromise
version: number
): T => {
const cache = snapCache.get(target)
if (cache?.[0] === version) {
Expand Down Expand Up @@ -138,18 +112,11 @@ const buildProxyFunction = (
}
if (refSet.has(value as object)) {
markToTrack(value as object, false) // mark not to track
} else if (value instanceof Promise) {
delete desc.value
desc.get = () => handlePromise(value)
} else if (proxyStateMap.has(value as object)) {
const [target, ensureVersion] = proxyStateMap.get(
value as object
) as ProxyState
desc.value = createSnapshot(
target,
ensureVersion(),
handlePromise
) as Snapshot<T>
desc.value = createSnapshot(target, ensureVersion()) as Snapshot<T>
}
Object.defineProperty(snap, key, desc)
})
Expand Down Expand Up @@ -337,7 +304,6 @@ const buildProxyFunction = (
objectIs,
newProxy,
canProxy,
defaultHandlePromise,
snapCache,
createSnapshot,
proxyCache,
Expand Down Expand Up @@ -391,16 +357,13 @@ export function subscribe<T extends object>(
}
}

export function snapshot<T extends object>(
proxyObject: T,
handlePromise?: HandlePromise
): Snapshot<T> {
export function snapshot<T extends object>(proxyObject: T): Snapshot<T> {
const proxyState = proxyStateMap.get(proxyObject as object)
if (import.meta.env?.MODE !== 'production' && !proxyState) {
console.warn('Please use proxy object')
}
const [target, ensureVersion, createSnapshot] = proxyState as ProxyState
return createSnapshot(target, ensureVersion(), handlePromise) as Snapshot<T>
return createSnapshot(target, ensureVersion()) as Snapshot<T>
}

export function ref<T extends object>(obj: T): T & AsRef {
Expand Down
14 changes: 8 additions & 6 deletions tests/async.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { StrictMode, Suspense } from 'react'
import { StrictMode, Suspense, use } from 'react'

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (4.1.5)

Module '"../node_modules/@types/react/ts5.0"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (4.0.5)

Module '"../node_modules/@types/react/ts5.0"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (3.8.3)

Module '"../node_modules/@types/react/ts5.0"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (3.7.5)

Module '"../node_modules/@types/react/ts5.0"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (3.9.7)

Module '"../node_modules/@types/react/ts5.0"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (4.4.4)

Module '"react"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (4.5.5)

Module '"react"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (4.3.5)

Module '"react"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (4.6.4)

Module '"react"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (5.1.6)

Module '"react"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (5.0.4)

Module '"react"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (4.2.3)

Module '"react"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (4.7.4)

Module '"react"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (4.9.5)

Module '"react"' has no exported member 'use'.

Check failure on line 1 in tests/async.test.tsx

View workflow job for this annotation

GitHub Actions / test_matrix (4.8.4)

Module '"react"' has no exported member 'use'.
import { fireEvent, render, waitFor } from '@testing-library/react'
import { it } from 'vitest'
import { proxy, useSnapshot } from 'valtio'
Expand All @@ -8,6 +8,8 @@ const sleep = (ms: number) =>
setTimeout(resolve, ms)
})

const use2 = <T,>(x: T): T => (x instanceof Promise ? use(x) : x)

it('delayed increment', async () => {
const state = proxy<any>({ count: 0 })
const delayedIncrement = () => {
Expand All @@ -19,7 +21,7 @@ it('delayed increment', async () => {
const snap = useSnapshot(state)
return (
<>
<div>count: {snap.count}</div>
<div>count: {use2(snap.count)}</div>
<button onClick={delayedIncrement}>button</button>
</>
)
Expand Down Expand Up @@ -50,7 +52,7 @@ it('delayed object', async () => {
const snap = useSnapshot(state)
return (
<>
<div>text: {snap.object.text}</div>
<div>text: {use2(snap.object).text}</div>
<button onClick={delayedObject}>button</button>
</>
)
Expand Down Expand Up @@ -85,8 +87,8 @@ it('delayed object update fulfilled', async () => {
const snap = useSnapshot(state)
return (
<>
<div>text: {snap.object.text}</div>
<div>count: {snap.object.count}</div>
<div>text: {use2(snap.object).text}</div>
<div>count: {use2(snap.object).count}</div>
<button onClick={updateObject}>button</button>
</>
)
Expand Down Expand Up @@ -125,7 +127,7 @@ it('delayed falsy value', async () => {
const snap = useSnapshot(state)
return (
<>
<div>value: {String(snap.value)}</div>
<div>value: {String(use2(snap.value))}</div>
<button onClick={delayedValue}>button</button>
</>
)
Expand Down
31 changes: 0 additions & 31 deletions tests/snapshot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,6 @@ import { TypeEqual, expectType } from 'ts-expect'
import { describe, expect, it } from 'vitest'
import { INTERNAL_Snapshot as Snapshot, proxy, snapshot } from 'valtio'

const sleep = (ms: number) =>
new Promise((resolve) => {
setTimeout(resolve, ms)
})

it('getter returns value after promise is resolved', async () => {
const state = proxy<any>({ status: sleep(10).then(() => 'done') })
const snap = snapshot(state)

await new Promise((resolve) => {
resolve(snap.status)
})
.catch((thrown) => {
expect(thrown).toBeInstanceOf(Promise)
return thrown
})
.then((value) => {
expect(value).toBe('done')
expect(snap.status).toBe('done')
})
})

it('should return correct snapshots without subscribe', async () => {
const child = proxy({ count: 0 })
const state = proxy({ child })
Expand Down Expand Up @@ -119,15 +97,6 @@ describe('snapsoht typings', () => {
>(true)
})

it('infers Promise result from property value', () => {
expectType<
TypeEqual<
Snapshot<{ promise: Promise<string> }>,
{ readonly promise: string }
>
>(true)
})

it('converts arrays to readonly arrays', () => {
expectType<TypeEqual<Snapshot<number[]>, readonly number[]>>(true)
})
Expand Down
26 changes: 13 additions & 13 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4259,13 +4259,13 @@ randombytes@^2.1.0:
dependencies:
safe-buffer "^5.1.0"

react-dom@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
react-dom@18.3.0-canary-c47c306a7-20231109:
version "18.3.0-canary-c47c306a7-20231109"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.0-canary-c47c306a7-20231109.tgz#a5b881218f760a44e09469f7c1d38c8354b6e0b9"
integrity sha512-COjHi7Ve6fCDStLinhvKxUpAVRDwkHIXtH9m8crIc0d3KjE+PMTmmIwQQj3ceypDAARQ1VFwHOhMQgXcdRAxlA==
dependencies:
loose-envify "^1.1.0"
scheduler "^0.23.0"
scheduler "0.24.0-canary-c47c306a7-20231109"

react-is@^16.13.1:
version "16.13.1"
Expand All @@ -4282,10 +4282,10 @@ react-is@^18.0.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==

react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
react@18.3.0-canary-c47c306a7-20231109:
version "18.3.0-canary-c47c306a7-20231109"
resolved "https://registry.yarnpkg.com/react/-/react-18.3.0-canary-c47c306a7-20231109.tgz#53878c332f829d5b25f6df6c8c3746cd12a3b922"
integrity sha512-LtL67Bc+Mkuhwud559dUCU+QXL6mmtgKTGEyT41m5bDiEQdGAyYCxXo5/pigAx4p8mQb+KIT2AvCWlEDKut+PQ==
dependencies:
loose-envify "^1.1.0"

Expand Down Expand Up @@ -4522,10 +4522,10 @@ saxes@^6.0.0:
dependencies:
xmlchars "^2.2.0"

scheduler@^0.23.0:
version "0.23.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
scheduler@0.24.0-canary-c47c306a7-20231109:
version "0.24.0-canary-c47c306a7-20231109"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.24.0-canary-c47c306a7-20231109.tgz#9d2f0329d603279093b38999f78eac04bf64f8a0"
integrity sha512-VGLhOyPt1EIAsoGqu7DMxnVPdGAoxTmSjNJlGX31exX0stiZsvb3QuK5bKT1BaTpDOJD4VnNFoonMRN7BNh3Cg==
dependencies:
loose-envify "^1.1.0"

Expand Down

0 comments on commit 40636a2

Please sign in to comment.