diff --git a/.eslintrc.js b/.eslintrc.js index f7f748516d9ab..4e023cd9d333b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -474,7 +474,7 @@ module.exports = { { files: ['packages/react-server-dom-turbopack/**/*.js'], globals: { - __turbopack_load__: 'readonly', + __turbopack_load_by_url__: 'readonly', __turbopack_require__: 'readonly', }, }, diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts index d0335fb3a435d..cd7d6a7a35b35 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts @@ -3001,6 +3001,8 @@ function isReorderableExpression( } } } + case 'TSAsExpression': + case 'TSNonNullExpression': case 'TypeCastExpression': { return isReorderableExpression( builder, diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-as-expression-default-value.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-as-expression-default-value.expect.md new file mode 100644 index 0000000000000..505224cf9ed92 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-as-expression-default-value.expect.md @@ -0,0 +1,67 @@ + +## Input + +```javascript +type Status = 'pending' | 'success' | 'error'; + +const StatusIndicator = ({status}: {status: Status}) => { + return
Status: {status}
; +}; + +const Component = ({status = 'pending' as Status}) => { + return ; +}; + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{status: 'success'}], +}; + +``` + +## Code + +```javascript +import { c as _c } from "react/compiler-runtime"; +type Status = "pending" | "success" | "error"; + +const StatusIndicator = (t0) => { + const $ = _c(3); + const { status } = t0; + const t1 = `status-${status}`; + let t2; + if ($[0] !== status || $[1] !== t1) { + t2 =
Status: {status}
; + $[0] = status; + $[1] = t1; + $[2] = t2; + } else { + t2 = $[2]; + } + return t2; +}; + +const Component = (t0) => { + const $ = _c(2); + const { status: t1 } = t0; + const status = t1 === undefined ? ("pending" as Status) : t1; + let t2; + if ($[0] !== status) { + t2 = ; + $[0] = status; + $[1] = t2; + } else { + t2 = $[1]; + } + return t2; +}; + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ status: "success" }], +}; + +``` + +### Eval output +(kind: ok)
Status: success
\ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-as-expression-default-value.tsx b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-as-expression-default-value.tsx new file mode 100644 index 0000000000000..715efd5bdc8d2 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-as-expression-default-value.tsx @@ -0,0 +1,14 @@ +type Status = 'pending' | 'success' | 'error'; + +const StatusIndicator = ({status}: {status: Status}) => { + return
Status: {status}
; +}; + +const Component = ({status = 'pending' as Status}) => { + return ; +}; + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{status: 'success'}], +}; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-non-null-expression-default-value.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-non-null-expression-default-value.expect.md new file mode 100644 index 0000000000000..7af6bc996a99a --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-non-null-expression-default-value.expect.md @@ -0,0 +1,54 @@ + +## Input + +```javascript +const THEME_MAP: ReadonlyMap = new Map([ + ['default', 'light'], + ['dark', 'dark'], +]); + +export const Component = ({theme = THEME_MAP.get('default')!}) => { + return
User preferences
; +}; + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{status: 'success'}], +}; + +``` + +## Code + +```javascript +import { c as _c } from "react/compiler-runtime"; +const THEME_MAP: ReadonlyMap = new Map([ + ["default", "light"], + ["dark", "dark"], +]); + +export const Component = (t0) => { + const $ = _c(2); + const { theme: t1 } = t0; + const theme = t1 === undefined ? THEME_MAP.get("default") : t1; + const t2 = `theme-${theme}`; + let t3; + if ($[0] !== t2) { + t3 =
User preferences
; + $[0] = t2; + $[1] = t3; + } else { + t3 = $[1]; + } + return t3; +}; + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ status: "success" }], +}; + +``` + +### Eval output +(kind: ok)
User preferences
\ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-non-null-expression-default-value.tsx b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-non-null-expression-default-value.tsx new file mode 100644 index 0000000000000..c1d835d6f0f06 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-non-null-expression-default-value.tsx @@ -0,0 +1,13 @@ +const THEME_MAP: ReadonlyMap = new Map([ + ['default', 'light'], + ['dark', 'dark'], +]); + +export const Component = ({theme = THEME_MAP.get('default')!}) => { + return
User preferences
; +}; + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{status: 'success'}], +}; diff --git a/packages/react-client/src/ReactFlightClient.js b/packages/react-client/src/ReactFlightClient.js index acc6e41cd4603..41dd877bb4fb3 100644 --- a/packages/react-client/src/ReactFlightClient.js +++ b/packages/react-client/src/ReactFlightClient.js @@ -1353,6 +1353,26 @@ function waitForReference( map: (response: Response, model: any, parentObject: Object, key: string) => T, path: Array, ): T { + if ( + __DEV__ && + // TODO: This should check for the existence of the "readable" side, not the "writable". + response._debugChannel === undefined + ) { + if ( + referencedChunk.status === PENDING && + parentObject[0] === REACT_ELEMENT_TYPE && + (key === '4' || key === '5') + ) { + // If the parent object is an unparsed React element tuple, and this is a reference + // to the owner or debug stack. Then we expect the chunk to have been emitted earlier + // in the stream. It might be blocked on other things but chunk should no longer be pending. + // If it's still pending that suggests that it was referencing an object in the debug + // channel, but no debug channel was wired up so it's missing. In this case we can just + // drop the debug info instead of halting the whole stream. + return (null: any); + } + } + let handler: InitializationHandler; if (initializingHandler) { handler = initializingHandler; diff --git a/packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackBrowser.js b/packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackBrowser.js index c418f51fa80ee..59aab436cbc2a 100644 --- a/packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackBrowser.js +++ b/packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackBrowser.js @@ -8,5 +8,5 @@ */ export function loadChunk(filename: string): Promise { - return __turbopack_load__(filename); + return __turbopack_load_by_url__(filename); } diff --git a/packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer.js b/packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer.js index c418f51fa80ee..59aab436cbc2a 100644 --- a/packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer.js +++ b/packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer.js @@ -8,5 +8,5 @@ */ export function loadChunk(filename: string): Promise { - return __turbopack_load__(filename); + return __turbopack_load_by_url__(filename); } diff --git a/scripts/flow/environment.js b/scripts/flow/environment.js index 39c792b449277..f52e6fd428e20 100644 --- a/scripts/flow/environment.js +++ b/scripts/flow/environment.js @@ -150,7 +150,7 @@ declare const __webpack_require__: ((id: string) => any) & { u: string => string, }; -declare function __turbopack_load__(id: string): Promise; +declare function __turbopack_load_by_url__(id: string): Promise; declare const __turbopack_require__: ((id: string) => any) & { u: string => string, }; diff --git a/scripts/rollup/validate/eslintrc.cjs.js b/scripts/rollup/validate/eslintrc.cjs.js index e7e172599d0e6..e4cf904e5974d 100644 --- a/scripts/rollup/validate/eslintrc.cjs.js +++ b/scripts/rollup/validate/eslintrc.cjs.js @@ -65,7 +65,7 @@ module.exports = { __webpack_require__: 'readonly', // Flight Turbopack - __turbopack_load__: 'readonly', + __turbopack_load_by_url__: 'readonly', __turbopack_require__: 'readonly', // Flight Parcel diff --git a/scripts/rollup/validate/eslintrc.cjs2015.js b/scripts/rollup/validate/eslintrc.cjs2015.js index 5e4feb64da8e8..4cda9b06a636e 100644 --- a/scripts/rollup/validate/eslintrc.cjs2015.js +++ b/scripts/rollup/validate/eslintrc.cjs2015.js @@ -62,7 +62,7 @@ module.exports = { __webpack_require__: 'readonly', // Flight Turbopack - __turbopack_load__: 'readonly', + __turbopack_load_by_url__: 'readonly', __turbopack_require__: 'readonly', // Flight Parcel diff --git a/scripts/rollup/validate/eslintrc.esm.js b/scripts/rollup/validate/eslintrc.esm.js index bef26bbd67efb..98fdc56c48c5f 100644 --- a/scripts/rollup/validate/eslintrc.esm.js +++ b/scripts/rollup/validate/eslintrc.esm.js @@ -65,7 +65,7 @@ module.exports = { __webpack_require__: 'readonly', // Flight Turbopack - __turbopack_load__: 'readonly', + __turbopack_load_by_url__: 'readonly', __turbopack_require__: 'readonly', // Flight Parcel