diff --git a/babel.config.json b/babel.config.json new file mode 100644 index 0000000000000..85ccdd2ace0fa --- /dev/null +++ b/babel.config.json @@ -0,0 +1,4 @@ +{ + "presets": ["@babel/preset-env", "@babel/preset-react"] + } + \ No newline at end of file diff --git a/packages/react-reconciler/src/ReactFiberReconciler.js b/packages/react-reconciler/src/ReactFiberReconciler.js index 4c319a14569a1..5f0125aeb72ec 100644 --- a/packages/react-reconciler/src/ReactFiberReconciler.js +++ b/packages/react-reconciler/src/ReactFiberReconciler.js @@ -272,6 +272,47 @@ export function createContainer( ); } +// Import necessary utilities and modules +import { preloadModules as preloadModulesUtil } from './utils'; // Preload utility +export { preloadModulesUtil as preloadModules }; + +export async function createInstance(type, props, rootContainer, hostContext, internalHandle) { + // Dynamically import the module based on the type + const Module = await import(`my-module-path/${type}`); + const instance = new Module.default(props); + return instance; +} + +export function appendChild(parent, child) { + if (parent.appendChild) { + parent.appendChild(child); + } +} + +// Traverses the React component tree and preloads components dynamically +export async function preloadModules(tree) { + const components = new Set(); + traverseTree(tree, (type) => components.add(type)); + await Promise.all( + [...components].map((type) => import(`my-module-path/${type}`)) + ); +} + +// Helper function for traversing the component tree +function traverseTree(node, callback) { + if (!node) return; + if (typeof node.type === 'string') callback(node.type); + if (node.props && node.props.children) { + React.Children.forEach(node.props.children, (child) => + traverseTree(child, callback) + ); + } +} + +// Ensure the rest of the file remains unchanged +// (The remaining logic is retained as-is from your original implementation.) + + export function createHydrationContainer( initialChildren: ReactNodeList, // TODO: Remove `callback` when we delete legacy mode. diff --git a/packages/react-reconciler/src/__tests__/customRenderer.test.js b/packages/react-reconciler/src/__tests__/customRenderer.test.js new file mode 100644 index 0000000000000..7d15c7eed60d5 --- /dev/null +++ b/packages/react-reconciler/src/__tests__/customRenderer.test.js @@ -0,0 +1,26 @@ +import React from 'react'; +import { render, preloadModules } from '../ReactFiberReconciler'; + +const Box = () =>
Box Component
; +const Sphere = () =>
Sphere Component
; + +// Mock components +jest.mock('my-module-path/box', () => Box, { virtual: true }); +jest.mock('my-module-path/sphere', () => Sphere, { virtual: true }); + +const App = () => ( + <> + + + +); + +const container = { + appendChild(child) { + console.log('Appended child:', child); + }, +}; + +preloadModules(App).then(() => { + render(, container); +}); diff --git a/packages/react-reconciler/src/utils.js b/packages/react-reconciler/src/utils.js new file mode 100644 index 0000000000000..fb72d6dee011b --- /dev/null +++ b/packages/react-reconciler/src/utils.js @@ -0,0 +1,19 @@ +import React from 'react'; + +export async function preloadModules(tree) { + const components = new Set(); + traverseTree(tree, (type) => components.add(type)); + await Promise.all( + [...components].map((type) => import(`my-module-path/${type}`)) + ); +} + +function traverseTree(node, callback) { + if (!node) return; + if (typeof node.type === 'string') callback(node.type); + if (node.props && node.props.children) { + React.Children.forEach(node.props.children, (child) => + traverseTree(child, callback) + ); + } +} diff --git a/packages/shared/ReactVersion.js b/packages/shared/ReactVersion.js index 647a57dfd286b..c75013e384467 100644 --- a/packages/shared/ReactVersion.js +++ b/packages/shared/ReactVersion.js @@ -1,15 +1 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -// TODO: this is special because it gets imported during build. -// -// It exists as a placeholder so that DevTools can support work tag changes between releases. -// When we next publish a release, update the matching TODO in backend/renderer.js -// TODO: This module is used both by the release scripts and to expose a version -// at runtime. We should instead inject the version number as part of the build -// process, and use the ReactVersions.js module as the single source of truth. -export default '19.1.0'; +export default '19.1.0-canary-0bf1f39e-20250110';