Skip to content

Commit

Permalink
experiment: test React 19 with v8
Browse files Browse the repository at this point in the history
  • Loading branch information
CodyJasonBennett committed Apr 23, 2024
1 parent 62cecea commit 02b85a4
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 147 deletions.
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@
"@changesets/changelog-git": "^0.1.11",
"@changesets/cli": "^2.22.0",
"@preconstruct/cli": "^2.1.5",
"@testing-library/react": "^13.0.0-alpha.5",
"@testing-library/react": "^15.0.2",
"@types/jest": "^29.2.5",
"@types/react": "^18.0.5",
"@types/react-dom": "^18.0.1",
"@types/react": "^18.2.79",
"@types/react-dom": "^18.2.25",
"@types/react-native": "0.67.4",
"@types/react-test-renderer": "^17.0.1",
"@types/scheduler": "^0.16.2",
"@types/react-test-renderer": "^18.0.7",
"@types/scheduler": "^0.23.0",
"@types/three": "^0.139.0",
"@typescript-eslint/eslint-plugin": "^5.48.1",
"@typescript-eslint/parser": "^5.48.1",
Expand All @@ -76,10 +76,10 @@
"lint-staged": "^12.3.7",
"prettier": "^2.6.1",
"pretty-quick": "^3.1.3",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react": "19.0.0-canary-db913d8e17-20240422",
"react-dom": "19.0.0-canary-db913d8e17-20240422",
"react-native": "0.67.4",
"react-test-renderer": "^18.0.0",
"react-test-renderer": "19.0.0-canary-db913d8e17-20240422",
"regenerator-runtime": "^0.13.9",
"three": "^0.139.0",
"three-stdlib": "^2.8.11",
Expand Down
12 changes: 6 additions & 6 deletions packages/fiber/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@
},
"dependencies": {
"@babel/runtime": "^7.17.8",
"@types/react-reconciler": "^0.26.7",
"@types/react-reconciler": "^0.28.8",
"@types/webxr": "*",
"base64-js": "^1.5.1",
"buffer": "^6.0.3",
"its-fine": "^1.0.6",
"react-reconciler": "^0.27.0",
"its-fine": "^1.2.5",
"react-reconciler": "0.31.0-canary-db913d8e17-20240422",
"react-use-measure": "^2.1.1",
"scheduler": "^0.21.0",
"scheduler": "0.25.0-canary-db913d8e17-20240422",
"suspend-react": "^0.1.3",
"zustand": "^3.7.1"
},
Expand All @@ -59,8 +59,8 @@
"expo-asset": ">=8.4",
"expo-gl": ">=11.0",
"expo-file-system": ">=11.0",
"react": ">=18.0",
"react-dom": ">=18.0",
"react": ">=19.0",
"react-dom": ">=19.0",
"react-native": ">=0.64",
"three": ">=0.133"
},
Expand Down
16 changes: 14 additions & 2 deletions packages/fiber/src/core/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,19 @@ function createRoot<TCanvas extends Canvas>(canvas: TCanvas): ReconcilerRoot<TCa
const store = prevStore || createStore(invalidate, advance)
// Create renderer
const fiber =
prevFiber || reconciler.createContainer(store, ConcurrentRoot, null, false, null, '', logRecoverableError, null)
prevFiber ||
(reconciler as any).createContainer(
store, // container
ConcurrentRoot, // tag
null, // hydration callbacks
false, // isStrictMode
null, // concurrentUpdatesByDefaultOverride
'', // identifierPrefix
logRecoverableError, // onUncaughtError
logRecoverableError, // onCaughtError
logRecoverableError, // onRecoverableError
null, // transitionCallbacks
)
// Map it
if (!prevRoot) roots.set(canvas, { fiber, store })

Expand Down Expand Up @@ -583,7 +595,7 @@ reconciler.injectIntoDevTools({
version: React.version,
})

const act = (React as any).unstable_act
const act: <T = any>(cb: () => Promise<T>) => Promise<T> = (React as any).act

export * from './hooks'
export {
Expand Down
74 changes: 54 additions & 20 deletions packages/fiber/src/core/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import * as THREE from 'three'
import { UseBoundStore } from 'zustand'
import Reconciler from 'react-reconciler'
import { unstable_IdlePriority as idlePriority, unstable_scheduleCallback as scheduleCallback } from 'scheduler'
import { DefaultEventPriority } from 'react-reconciler/constants'
import {
// @ts-ignore
NoEventPriority,
ContinuousEventPriority,
DiscreteEventPriority,
DefaultEventPriority,
} from 'react-reconciler/constants'
import {
is,
prepare,
Expand Down Expand Up @@ -47,7 +53,7 @@ interface HostConfig {
suspenseInstance: Instance
hydratableInstance: Instance
publicInstance: Instance
hostContext: never
hostContext: {}
updatePayload: Array<boolean | number | DiffSet>
childSet: never
timeoutHandle: number | undefined
Expand Down Expand Up @@ -305,6 +311,10 @@ function createRenderer<TCanvas>(_roots: Map<TCanvas, Root>, _getEventPriority?:
const handleTextInstance = () =>
console.warn('Text is not allowed in the R3F tree! This could be stray whitespace or characters.')

const NO_CONTEXT: HostConfig['hostContext'] = {}

let currentUpdatePriority: number = NoEventPriority

const reconciler = Reconciler<
HostConfig['type'],
HostConfig['props'],
Expand All @@ -329,7 +339,6 @@ function createRenderer<TCanvas>(_roots: Map<TCanvas, Root>, _getEventPriority?:
isPrimaryRenderer: false,
supportsPersistence: false,
supportsHydration: false,
noTimeout: -1,
appendChildToContainer: (container, child) => {
if (!child) return

Expand All @@ -354,8 +363,8 @@ function createRenderer<TCanvas>(_roots: Map<TCanvas, Root>, _getEventPriority?:

insertBefore(scene, child, beforeChild)
},
getRootHostContext: () => null,
getChildHostContext: (parentHostContext) => parentHostContext,
getRootHostContext: () => NO_CONTEXT,
getChildHostContext: () => NO_CONTEXT,
finalizeInitialChildren(instance) {
const localState = instance?.__r3f ?? {}
// https://github.com/facebook/react/issues/20271
Expand Down Expand Up @@ -386,11 +395,15 @@ function createRenderer<TCanvas>(_roots: Map<TCanvas, Root>, _getEventPriority?:
return null
}
},
commitUpdate(instance, [reconstruct, diff]: [boolean, DiffSet], type, _oldProps, newProps, fiber) {
commitUpdate(instance, diff, type, _oldProps, newProps, fiber) {
if (!diff) return

const [reconstruct, changedProps] = diff as [boolean, DiffSet]

// Reconstruct when args or <primitive object={...} have changes
if (reconstruct) switchInstance(instance, type, newProps, fiber)
// Otherwise just overwrite props
else applyProps(instance, diff)
else applyProps(instance, changedProps)
},
commitMount(instance, _type, _props, _int) {
// https://github.com/facebook/react/issues/20271
Expand Down Expand Up @@ -425,21 +438,42 @@ function createRenderer<TCanvas>(_roots: Map<TCanvas, Root>, _getEventPriority?:
createTextInstance: handleTextInstance,
hideTextInstance: handleTextInstance,
unhideTextInstance: handleTextInstance,
// https://github.com/pmndrs/react-three-fiber/pull/2360#discussion_r916356874
// @ts-ignore
getCurrentEventPriority: () => (_getEventPriority ? _getEventPriority() : DefaultEventPriority),
beforeActiveInstanceBlur: () => {},
afterActiveInstanceBlur: () => {},
detachDeletedInstance: () => {},
now:
typeof performance !== 'undefined' && is.fun(performance.now)
? performance.now
: is.fun(Date.now)
? Date.now
: () => 0,
// https://github.com/pmndrs/react-three-fiber/pull/2360#discussion_r920883503
scheduleTimeout: (is.fun(setTimeout) ? setTimeout : undefined) as any,
cancelTimeout: (is.fun(clearTimeout) ? clearTimeout : undefined) as any,
noTimeout: -1,
getInstanceFromNode: () => null,
beforeActiveInstanceBlur() {},
afterActiveInstanceBlur() {},
detachDeletedInstance() {},
// @ts-ignore untyped react-experimental options inspired by react-art
// TODO: add shell types for these and upstream to DefinitelyTyped
// https://github.com/facebook/react/blob/main/packages/react-art/src/ReactFiberConfigART.js
shouldAttemptEagerTransition() {
return false
},
requestPostPaintCallback() {},
maySuspendCommit() {
return false
},
preloadInstance() {
return true // true indicates already loaded
},
startSuspendingCommit() {},
suspendInstance() {},
waitForCommitToBeReady() {
return null
},
NotPendingTransition: null,
setCurrentUpdatePriority(newPriority: number) {
currentUpdatePriority = newPriority
},
getCurrentUpdatePriority() {
return currentUpdatePriority
},
resolveUpdatePriority() {
if (currentUpdatePriority) return currentUpdatePriority
return _getEventPriority ? _getEventPriority() : DefaultEventPriority
},
})

return { reconciler, applyProps }
Expand Down
2 changes: 1 addition & 1 deletion packages/fiber/tests/native/canvas.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ describe('native Canvas', () => {
)
})

expect(() => renderer.unmount()).not.toThrow()
expect(async () => await act(async () => renderer.unmount())).not.toThrow()
})
})
2 changes: 1 addition & 1 deletion packages/test-renderer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
]
},
"peerDependencies": {
"react": ">=17.0",
"react": ">=19.0",
"@react-three/fiber": ">=8.0.0",
"three": ">=0.126"
}
Expand Down
7 changes: 2 additions & 5 deletions packages/test-renderer/src/fireEvent.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ReactReconciler from 'react-reconciler'
import { act } from '@react-three/fiber'

import { toEventHandlerName } from './helpers/strings'

Expand All @@ -7,10 +7,7 @@ import { ReactThreeTestInstance } from './createTestInstance'
import type { MockSyntheticEvent } from './types/public'
import type { MockUseStoreState, MockEventData } from './types/internal'

export const createEventFirer = (
act: ReactReconciler.Reconciler<unknown, unknown, unknown, unknown, unknown>['act'],
store: MockUseStoreState,
) => {
export const createEventFirer = (store: MockUseStoreState) => {
const findEventHandler = (
element: ReactThreeTestInstance,
eventName: string,
Expand Down
4 changes: 1 addition & 3 deletions packages/test-renderer/src/helpers/waitFor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import * as React from 'react'

const act: <T = any>(cb: () => Promise<T>) => Promise<T> = (React as any).unstable_act
import { act } from '@react-three/fiber'

export interface WaitOptions {
interval?: number
Expand Down
8 changes: 3 additions & 5 deletions packages/test-renderer/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react'
import * as THREE from 'three'

import { extend, _roots as mockRoots, createRoot, reconciler, act as _act } from '@react-three/fiber'
import { extend, _roots as mockRoots, createRoot, reconciler, act } from '@react-three/fiber'

import { toTree } from './helpers/tree'
import { toGraph } from './helpers/graph'
Expand All @@ -11,15 +11,13 @@ import { createCanvas } from './createTestCanvas'
import { createEventFirer } from './fireEvent'

import type { MockScene } from './types/internal'
import type { CreateOptions, Renderer, Act } from './types/public'
import type { CreateOptions, Renderer } from './types/public'
import { wrapFiber } from './createTestInstance'
import { waitFor, WaitOptions } from './helpers/waitFor'

// Extend catalogue for render API in tests.
extend(THREE)

const act = _act as unknown as Act

const create = async (element: React.ReactNode, options?: Partial<CreateOptions>): Promise<Renderer> => {
const canvas = createCanvas(options)

Expand Down Expand Up @@ -68,7 +66,7 @@ const create = async (element: React.ReactNode, options?: Partial<CreateOptions>
toGraph() {
return toGraph(scene)
},
fireEvent: createEventFirer(act, _store),
fireEvent: createEventFirer(_store),
async advanceFrames(frames: number, delta: number | number[] = 1) {
const state = _store.getState()
const storeSubscribers = state.internal.subscribers
Expand Down
Loading

0 comments on commit 02b85a4

Please sign in to comment.