diff --git a/.changeset/plain-lions-hope.md b/.changeset/plain-lions-hope.md new file mode 100644 index 0000000000..853d812bb3 --- /dev/null +++ b/.changeset/plain-lions-hope.md @@ -0,0 +1,3 @@ +--- + +--- diff --git a/packages/react/package.json b/packages/react/package.json index 74cde9de94..e77c7110e8 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -56,12 +56,12 @@ "default": "./runtime/lepus/jsx-runtime/index.js" }, "./hooks": { - "types": "./runtime/lib/snapshot/hooks/react.d.ts", - "default": "./runtime/lib/snapshot/hooks/react.js" + "types": "./runtime/lib/core/hooks/react.d.ts", + "default": "./runtime/lib/core/hooks/react.js" }, "./lepus/hooks": { - "types": "./runtime/lib/snapshot/hooks/react.d.ts", - "default": "./runtime/lib/snapshot/hooks/mainThread.js" + "types": "./runtime/lib/core/hooks/react.d.ts", + "default": "./runtime/lib/core/hooks/mainThread.js" }, "./lepus": { "types": "./runtime/lepus/index.d.ts", @@ -132,10 +132,10 @@ "./runtime/lazy/import.d.ts" ], "hooks": [ - "./runtime/lib/snapshot/hooks/react.d.ts" + "./runtime/lib/core/hooks/react.d.ts" ], "lepus/hooks": [ - "./runtime/lib/snapshot/hooks/react.d.ts" + "./runtime/lib/core/hooks/react.d.ts" ], "internal": [ "./runtime/lib/internal.d.ts" diff --git a/packages/react/runtime/__test__/snapshot/hooks/mainThread.test.tsx b/packages/react/runtime/__test__/core/hooks/mainThread.test.tsx similarity index 91% rename from packages/react/runtime/__test__/snapshot/hooks/mainThread.test.tsx rename to packages/react/runtime/__test__/core/hooks/mainThread.test.tsx index 1bd26b8da4..26c0b86cce 100644 --- a/packages/react/runtime/__test__/snapshot/hooks/mainThread.test.tsx +++ b/packages/react/runtime/__test__/core/hooks/mainThread.test.tsx @@ -3,15 +3,16 @@ // LICENSE file in the root directory of this source tree. import { beforeEach, afterEach, vi } from 'vitest'; -import { globalEnvManager } from '../utils/envManager'; +import { globalEnvManager } from '../../snapshot/utils/envManager'; import { describe } from 'vitest'; import { it } from 'vitest'; import { expect } from 'vitest'; import { beforeAll } from 'vitest'; import { replaceCommitHook } from '../../../src/snapshot/lifecycle/patch/commit'; -import { elementTree } from '../utils/nativeMethod'; +import { elementTree } from '../../snapshot/utils/nativeMethod'; import { __root } from '../../../src/root'; import { + installMainThreadHooks, useState, useMemo, useEffect, @@ -23,9 +24,9 @@ import { useId, useErrorBoundary, useContext, -} from '../../../src/snapshot/hooks/mainThread'; +} from '../../../src/core/hooks/mainThread'; import { options, createContext } from 'preact'; -import { HOOK } from '../../../src/snapshot/renderToOpcodes/constants.js'; +import { DIFF, HOOK } from '../../../src/shared/render-constants.js'; beforeAll(() => { replaceCommitHook(); @@ -43,6 +44,14 @@ afterEach(() => { }); describe('mainThread hooks', () => { + it('should skip duplicate installation', () => { + const diffHook = options[DIFF]; + + installMainThreadHooks(); + + expect(options[DIFF]).toBe(diffHook); + }); + it('should get initialValue', () => { let setCount; options[HOOK] = vi.fn(); diff --git a/packages/react/runtime/__test__/snapshot/hooks/useLynxGlobalEventListener.test.jsx b/packages/react/runtime/__test__/core/hooks/useLynxGlobalEventListener.test.jsx similarity index 94% rename from packages/react/runtime/__test__/snapshot/hooks/useLynxGlobalEventListener.test.jsx rename to packages/react/runtime/__test__/core/hooks/useLynxGlobalEventListener.test.jsx index 3a1bb319e7..e1e1254070 100644 --- a/packages/react/runtime/__test__/snapshot/hooks/useLynxGlobalEventListener.test.jsx +++ b/packages/react/runtime/__test__/core/hooks/useLynxGlobalEventListener.test.jsx @@ -6,7 +6,7 @@ import { EventEmitter } from 'node:events'; import { render } from 'preact'; -import { useState } from 'preact/compat'; +import { useState } from 'preact/hooks'; import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; import { setupBackgroundDocument } from '../../../src/document'; @@ -17,10 +17,10 @@ import { SnapshotInstance, setupPage, } from '../../../src/snapshot'; -import { backgroundSnapshotInstanceToJSON } from '../utils/debug.js'; -import { elementTree } from '../utils/nativeMethod'; +import { backgroundSnapshotInstanceToJSON } from '../../snapshot/utils/debug.js'; +import { elementTree } from '../../snapshot/utils/nativeMethod'; -import { globalEnvManager } from '../utils/envManager'; +import { globalEnvManager } from '../../snapshot/utils/envManager'; describe('useLynxGlobalEventListener', () => { /** @type {SnapshotInstance} */ diff --git a/packages/react/runtime/__test__/guardrails/snapshot-containment.test.ts b/packages/react/runtime/__test__/guardrails/snapshot-containment.test.ts index da3c13192d..d40f4ff672 100644 --- a/packages/react/runtime/__test__/guardrails/snapshot-containment.test.ts +++ b/packages/react/runtime/__test__/guardrails/snapshot-containment.test.ts @@ -14,13 +14,14 @@ const reactRoot = path.resolve(runtimeRoot, '..'); const srcRoot = path.join(runtimeRoot, 'src'); const testRoot = path.join(runtimeRoot, '__test__'); const transformRoot = path.join(reactRoot, 'transform'); +const coreRoot = path.join(srcRoot, 'core'); +const sharedRoot = path.join(srcRoot, 'shared'); const legacySourceDirs = [ 'alog', 'compat', 'debug', 'gesture', - 'hooks', 'legacy-react-runtime', 'lifecycle', 'list', @@ -41,7 +42,6 @@ const containedTestDirs = [ 'css', 'debug', 'gesture', - 'hooks', 'lifecycle', 'lynx', 'utils', @@ -95,6 +95,7 @@ describe('snapshot containment guardrails', () => { ); const offenders = walkFiles(srcRoot) .filter((file) => !file.includes(`${path.sep}src${path.sep}snapshot${path.sep}`)) + .filter((file) => !file.includes(`${path.sep}src${path.sep}element-template${path.sep}`)) .filter((file) => oldPathPattern.test(fs.readFileSync(file, 'utf8'))) .map((file) => path.relative(runtimeRoot, file)); @@ -112,6 +113,24 @@ describe('snapshot containment guardrails', () => { expect(offenders).toEqual([]); }); + test('prevents core and shared modules from depending on runtime backends', () => { + const backendImportPattern = + /(?:from\s+|import\s*\(\s*)['"](?:\.\/|\.\.\/)+(?:snapshot|element-template)(?:\/|['"])/; + const offenders = [ + ...walkFiles(coreRoot), + ...walkFiles(sharedRoot), + ] + .filter((file) => backendImportPattern.test(fs.readFileSync(file, 'utf8'))) + .map((file) => path.relative(runtimeRoot, file)); + + expect(offenders).toEqual([]); + }); + + test('allows ReactLynx hooks to live under core instead of snapshot', () => { + expect(fs.existsSync(path.join(srcRoot, 'snapshot', 'hooks'))).toBe(false); + expect(fs.existsSync(path.join(srcRoot, 'core', 'hooks'))).toBe(true); + }); + test('prevents transform output from referencing untracked old runtime source paths', () => { const oldPackageSourcePattern = new RegExp( String.raw`@lynx-js/react/src/(?:${legacySourceDirPattern})(?:/|['"])`, @@ -136,7 +155,7 @@ describe('snapshot containment guardrails', () => { expect(typesVersions).not.toContain('./runtime/lib/hooks/'); expect(typesVersions).not.toContain('./runtime/lib/legacy-react-runtime/'); - expect(typesVersions).toContain('./runtime/lib/snapshot/hooks/react.d.ts'); + expect(typesVersions).toContain('./runtime/lib/core/hooks/react.d.ts'); expect(typesVersions).toContain( './runtime/lib/snapshot/legacy-react-runtime/index.d.ts', ); diff --git a/packages/react/runtime/__test__/snapshot/debug/profile-module.test.ts b/packages/react/runtime/__test__/shared/profile.test.ts similarity index 90% rename from packages/react/runtime/__test__/snapshot/debug/profile-module.test.ts rename to packages/react/runtime/__test__/shared/profile.test.ts index a0d549d0b5..a39b8c4577 100644 --- a/packages/react/runtime/__test__/snapshot/debug/profile-module.test.ts +++ b/packages/react/runtime/__test__/shared/profile.test.ts @@ -11,7 +11,7 @@ type LynxLike = { performance?: PerformanceLike; }; -describe('debug/profile module', () => { +describe('shared/profile module', () => { let originalLynx: LynxLike; let originalProfileFlag: unknown; @@ -37,7 +37,7 @@ describe('debug/profile module', () => { performance: perf, }; - const profile = await import('../../../src/snapshot/debug/profile'); + const profile = await import('../../src/shared/profile'); expect(profile.isProfiling).toBe(true); }); @@ -53,7 +53,7 @@ describe('debug/profile module', () => { performance: perf, }; - const profile = await import('../../../src/snapshot/debug/profile'); + const profile = await import('../../src/shared/profile'); expect(profile.isProfiling).toBe(false); expect(() => profile.profileStart('trace')).not.toThrow(); @@ -75,7 +75,7 @@ describe('debug/profile module', () => { performance: perf, }; - const profile = await import('../../../src/snapshot/debug/profile'); + const profile = await import('../../src/shared/profile'); profile.profileStart('trace-name', { args: { foo: 'bar' } }); profile.profileEnd(); diff --git a/packages/react/runtime/__test__/snapshot/debug/backgroundSnapshot-profile.test.jsx b/packages/react/runtime/__test__/snapshot/debug/backgroundSnapshot-profile.test.jsx index 11043bfb2d..3a12947223 100644 --- a/packages/react/runtime/__test__/snapshot/debug/backgroundSnapshot-profile.test.jsx +++ b/packages/react/runtime/__test__/snapshot/debug/backgroundSnapshot-profile.test.jsx @@ -9,7 +9,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest'; import { setupDocument } from '../../../src/document'; import { setupVNodeSourceHook } from '../../../src/snapshot/debug/vnodeSource'; import { SnapshotOperation, SnapshotOperationParams } from '../../../src/snapshot/lifecycle/patch/snapshotPatch'; -import { DIFFED, DOM } from '../../../src/snapshot/renderToOpcodes/constants'; +import { DIFFED, DOM } from '../../../src/shared/render-constants'; import { __root } from '../../../src/root'; import { setupPage, diff --git a/packages/react/runtime/__test__/snapshot/debug/profile.test.jsx b/packages/react/runtime/__test__/snapshot/debug/profile.test.jsx index 50e96f4516..5969efc828 100644 --- a/packages/react/runtime/__test__/snapshot/debug/profile.test.jsx +++ b/packages/react/runtime/__test__/snapshot/debug/profile.test.jsx @@ -10,16 +10,7 @@ import { setupDocument } from '../../../src/document'; import { setupPage, snapshotInstanceManager } from '../../../src/snapshot'; import { initProfileHook } from '../../../src/snapshot/debug/profileHooks'; import { useState } from '../../../src/index'; -import { - COMPONENT, - DIFF, - DIFF2, - DIFFED, - HOOKS, - LIST, - RENDER, - VNODE, -} from '../../../src/snapshot/renderToOpcodes/constants'; +import { COMPONENT, DIFF, DIFF2, DIFFED, HOOKS, LIST, RENDER, VNODE } from '../../../src/shared/render-constants'; describe('profile', () => { let scratch; diff --git a/packages/react/runtime/__test__/snapshot/debug/react-hooks-profile.test.jsx b/packages/react/runtime/__test__/snapshot/debug/react-hooks-profile.test.jsx index 14cd6f6a91..4c28389610 100644 --- a/packages/react/runtime/__test__/snapshot/debug/react-hooks-profile.test.jsx +++ b/packages/react/runtime/__test__/snapshot/debug/react-hooks-profile.test.jsx @@ -3,7 +3,6 @@ // Licensed under the Apache License Version 2.0 that can be found in the // LICENSE file in the root directory of this source tree. */ -import { render } from 'preact'; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; import { setupDocument } from '../../../src/document'; @@ -11,12 +10,26 @@ import { setupPage, snapshotInstanceManager } from '../../../src/snapshot'; import { elementTree } from '../utils/nativeMethod'; import { globalEnvManager } from '../utils/envManager'; +let currentRender; +let currentCreateElement; + async function importHooksWithProfileRecording(isRecording) { const original = lynx.performance.isProfileRecording; lynx.performance.isProfileRecording = vi.fn(() => isRecording); vi.resetModules(); try { - return await import('../../../src/snapshot/hooks/react'); + const [hooks, preact, document, utils] = await Promise.all([ + import('../../../src/core/hooks/react'), + import('preact'), + import('../../../src/document'), + import('../../../src/utils'), + ]); + document.setupBackgroundDocument(); + preact.options.document = document.document; + preact.options.requestAnimationFrame = utils.lynxQueueMicrotask; + currentRender = preact.render; + currentCreateElement = preact.h; + return hooks; } finally { lynx.performance.isProfileRecording = original; } @@ -37,7 +50,9 @@ describe('react hooks profile', () => { }); afterEach(() => { - render(null, scratch); + currentRender?.(null, scratch); + currentRender = undefined; + currentCreateElement = undefined; elementTree.clear(); vi.restoreAllMocks(); }); @@ -52,16 +67,16 @@ describe('react hooks profile', () => { useLayoutEffect(() => { return () => {}; }, []); - return ; + return currentCreateElement('div'); } lynx.performance.profileStart.mockClear(); lynx.performance.profileEnd.mockClear(); lynx.performance.profileFlowId.mockClear(); - render(, scratch); + currentRender(currentCreateElement(App), scratch); await Promise.resolve(); - render(null, scratch); + currentRender(null, scratch); await Promise.resolve(); const starts = lynx.performance.profileStart.mock.calls; @@ -103,10 +118,10 @@ describe('react hooks profile', () => { function App() { const [value, _setValue] = useState(0); setValue = _setValue; - return ; + return currentCreateElement('div', { value }); } - render(, scratch); + currentRender(currentCreateElement(App), scratch); const OriginalError = globalThis.Error; class ErrorWithoutStack extends OriginalError { @@ -139,7 +154,7 @@ describe('react hooks profile', () => { function App() { useEffect(() => undefined, []); - return ; + return currentCreateElement('div'); } const OriginalError = globalThis.Error; @@ -155,7 +170,7 @@ describe('react hooks profile', () => { try { vi.stubGlobal('Error', ErrorWithoutStack); - render(, scratch); + currentRender(currentCreateElement(App), scratch); await Promise.resolve(); } finally { vi.stubGlobal('Error', OriginalError); @@ -179,10 +194,10 @@ describe('react hooks profile', () => { function App() { const [value, _setValue] = useState(); setValue = _setValue; - return ; + return currentCreateElement('div', { value }); } - render(, scratch); + currentRender(currentCreateElement(App), scratch); lynx.performance.profileStart.mockClear(); lynx.performance.profileEnd.mockClear(); @@ -210,10 +225,10 @@ describe('react hooks profile', () => { function App() { const [value, _setValue] = useState(0); setValue = _setValue; - return ; + return currentCreateElement('div', { value }); } - render(, scratch); + currentRender(currentCreateElement(App), scratch); lynx.performance.profileStart.mockClear(); lynx.performance.profileEnd.mockClear(); @@ -245,7 +260,7 @@ describe('react hooks profile', () => { setValue = _setValue; useEffect(() => undefined, [value]); useLayoutEffect(() => undefined, [value]); - return ; + return currentCreateElement('div', { value }); } lynx.performance.profileStart.mockClear(); @@ -256,7 +271,7 @@ describe('react hooks profile', () => { expect(useEffect).toBe(preactHooks.useEffect); expect(useLayoutEffect).toBe(preactHooks.useEffect); - render(, scratch); + currentRender(currentCreateElement(App), scratch); await Promise.resolve(); setValue(v => v + 1); await Promise.resolve(); diff --git a/packages/react/runtime/__test__/snapshot/debug/vnodeSource.test.ts b/packages/react/runtime/__test__/snapshot/debug/vnodeSource.test.ts index b76a663833..ec4b5cfb1d 100644 --- a/packages/react/runtime/__test__/snapshot/debug/vnodeSource.test.ts +++ b/packages/react/runtime/__test__/snapshot/debug/vnodeSource.test.ts @@ -12,7 +12,7 @@ import { moveSnapshotVNodeSource, setupVNodeSourceHook, } from '../../../src/snapshot/debug/vnodeSource'; -import { DIFFED, DOM } from '../../../src/snapshot/renderToOpcodes/constants'; +import { DIFFED, DOM } from '../../../src/shared/render-constants'; describe('vnodeSource', () => { let originalDiffed: typeof options[typeof DIFFED]; diff --git a/packages/react/runtime/__test__/snapshot/event.test.jsx b/packages/react/runtime/__test__/snapshot/event.test.jsx index ad89d9089e..c14e3b9362 100644 --- a/packages/react/runtime/__test__/snapshot/event.test.jsx +++ b/packages/react/runtime/__test__/snapshot/event.test.jsx @@ -12,7 +12,7 @@ import { snapshotPatchApply } from '../../src/snapshot/lifecycle/patch/snapshotP import { injectUpdateMainThread } from '../../src/snapshot/lifecycle/patch/updateMainThread'; import { injectTt } from '../../src/snapshot/lynx/tt'; import { root } from '../../src/lynx-api'; -import { CHILDREN } from '../../src/snapshot/renderToOpcodes/constants'; +import { CHILDREN } from '../../src/shared/render-constants'; import { __root } from '../../src/root'; import { setupPage, backgroundSnapshotInstanceManager } from '../../src/snapshot'; import { globalEnvManager } from './utils/envManager'; diff --git a/packages/react/runtime/__test__/snapshot/lifecycle.test.jsx b/packages/react/runtime/__test__/snapshot/lifecycle.test.jsx index 3859abf291..687a73ac99 100644 --- a/packages/react/runtime/__test__/snapshot/lifecycle.test.jsx +++ b/packages/react/runtime/__test__/snapshot/lifecycle.test.jsx @@ -7,7 +7,7 @@ import { waitSchedule } from './utils/nativeMethod'; import { globalCommitTaskMap, replaceCommitHook } from '../../src/snapshot/lifecycle/patch/commit'; import { deinitGlobalSnapshotPatch, initGlobalSnapshotPatch } from '../../src/snapshot/lifecycle/patch/snapshotPatch'; import { LifecycleConstant } from '../../src/snapshot/lifecycle/constant'; -import { CATCH_ERROR } from '../../src/snapshot/renderToOpcodes/constants'; +import { CATCH_ERROR } from '../../src/shared/render-constants'; import { __root } from '../../src/root'; import { setupPage, backgroundSnapshotInstanceManager } from '../../src/snapshot'; diff --git a/packages/react/runtime/__test__/snapshot/lifecycle/destroy.test.jsx b/packages/react/runtime/__test__/snapshot/lifecycle/destroy.test.jsx index 7e50173d07..78ae9116d7 100644 --- a/packages/react/runtime/__test__/snapshot/lifecycle/destroy.test.jsx +++ b/packages/react/runtime/__test__/snapshot/lifecycle/destroy.test.jsx @@ -1,4 +1,3 @@ -import { render } from 'preact'; import { beforeAll, describe, expect, test, vi } from 'vitest'; describe('Destroy', () => { @@ -21,6 +20,7 @@ describe('Destroy', () => { expect(addEventListener).toHaveBeenCalled(); expect(removeEventListener).toHaveBeenCalledTimes(0); + const { h, render } = await import('preact'); const { useEffect } = await import('../../../src/index'); const { __root } = await import('../../../src/root'); @@ -33,7 +33,7 @@ describe('Destroy', () => { return null; } - render(, __root); + render(h(Comp), __root); await Promise.resolve().then(() => {}); expect(() => lynxCoreInject.tt.callDestroyLifetimeFun()).toThrow('???'); diff --git a/packages/react/runtime/__test__/snapshot/lifecycle/updateGlobalProps.event.test.jsx b/packages/react/runtime/__test__/snapshot/lifecycle/updateGlobalProps.event.test.jsx new file mode 100644 index 0000000000..6a667e3fff --- /dev/null +++ b/packages/react/runtime/__test__/snapshot/lifecycle/updateGlobalProps.event.test.jsx @@ -0,0 +1,234 @@ +// Copyright 2026 The Lynx Authors. All rights reserved. +// Licensed under the Apache License Version 2.0 that can be found in the +// LICENSE file in the root directory of this source tree. + +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; + +import { __root } from '../../../src/root'; +import { replaceCommitHook } from '../../../src/snapshot/lifecycle/patch/commit'; +import { elementTree, waitSchedule } from '../utils/nativeMethod'; +import { globalEnvManager } from '../utils/envManager'; + +beforeAll(() => { + replaceCommitHook(); +}); + +beforeEach(() => { + globalEnvManager.resetEnv(); + globalThis.__GLOBAL_PROPS_MODE__ = 'event'; +}); + +afterEach(() => { + elementTree.clear(); + vi.restoreAllMocks(); + globalThis.__GLOBAL_PROPS_MODE__ = 'reactive'; +}); + +async function renderWithCurrentPreact(element, root) { + const [preact, { document, setupBackgroundDocument }] = await Promise.all([ + import('preact'), + import('../../../src/document'), + ]); + setupBackgroundDocument(); + preact.options.document = document; + preact.render(element, root); +} + +describe('updateGlobalProps event mode', () => { + it('should trigger re-render when useGlobalProps is called', async () => { + const { useGlobalProps, useGlobalPropsChanged } = await import('../../../src/lynx-api'); + + lynx.__globalProps = { theme: 'dark' }; + let count = 0; + let dataTheme, globalPropsTheme; + const Comp = () => { + const globalProps = useGlobalProps(); + useGlobalPropsChanged(data => { + count++; + dataTheme = data.theme; + globalPropsTheme = lynx.__globalProps.theme; + }); + return {globalProps.theme}; + }; + + // main thread render + { + __root.__jsx = ; + renderPage(); + expect(count).toBe(0); + expect(__root.__element_root).toMatchInlineSnapshot(` + + + + + + `); + } + + // background render + { + globalEnvManager.switchToBackground(); + __root.__jsx = ; + await renderWithCurrentPreact(, __root); + } + + // hydrate + { + lynxCoreInject.tt.OnLifecycleEvent(...globalThis.__OnLifecycleEvent.mock.calls[0]); + } + + // rLynxChange + { + globalEnvManager.switchToMainThread(); + globalThis.__OnLifecycleEvent.mockClear(); + const rLynxChange = lynx.getNativeApp().callLepusMethod.mock.calls[0]; + globalThis[rLynxChange[0]](rLynxChange[1]); + await waitSchedule(); + } + + // updateGlobalProps + { + globalEnvManager.switchToBackground(); + lynx.getNativeApp().callLepusMethod.mockClear(); + lynxCoreInject.tt.updateGlobalProps({ theme: 'light' }); + await waitSchedule(); + + // rLynxChange should be called + expect(lynx.getNativeApp().callLepusMethod.mock.calls.length).toBe(1); + expect(count).toBe(1); + expect(dataTheme).toBe('light'); + expect(globalPropsTheme).toBe('light'); + // ui change + globalEnvManager.switchToMainThread(); + for (const rLynxChange of lynx.getNativeApp().callLepusMethod.mock.calls) { + globalThis[rLynxChange[0]](rLynxChange[1]); + rLynxChange[2](); + } + expect(__root.__element_root).toMatchInlineSnapshot(` + + + + + + `); + } + }); + + it('should trigger update when GlobalPropsProvider and useGlobalProps are used', async () => { + const { GlobalPropsProvider, GlobalPropsConsumer } = await import('../../../src/lynx-api'); + + lynx.__globalProps = { theme: 'dark' }; + const Comp = () => { + return ( + + + {globalProps => { + return {globalProps.theme}; + }} + + + ); + }; + + // main thread render + { + __root.__jsx = ; + renderPage(); + expect(__root.__element_root).toMatchInlineSnapshot(` + + + + + + `); + } + + // background render + { + globalEnvManager.switchToBackground(); + __root.__jsx = ; + await renderWithCurrentPreact(, __root); + } + + // hydrate + { + lynxCoreInject.tt.OnLifecycleEvent(...globalThis.__OnLifecycleEvent.mock.calls[0]); + } + + // rLynxChange + { + globalEnvManager.switchToMainThread(); + globalThis.__OnLifecycleEvent.mockClear(); + const rLynxChange = lynx.getNativeApp().callLepusMethod.mock.calls[0]; + globalThis[rLynxChange[0]](rLynxChange[1]); + await waitSchedule(); + } + + // updateGlobalProps + { + globalEnvManager.switchToBackground(); + lynx.getNativeApp().callLepusMethod.mockClear(); + lynxCoreInject.tt.updateGlobalProps({ theme: 'light' }); + await waitSchedule(); + + // rLynxChange should be called + expect(lynx.getNativeApp().callLepusMethod.mock.calls.length).toBe(2); + expect(lynx.getNativeApp().callLepusMethod.mock.calls).toMatchInlineSnapshot(` + [ + [ + "rLynxChange", + { + "data": "{"patchList":[{"id":6}]}", + "patchOptions": { + "flowIds": [ + 666, + ], + "reloadVersion": 0, + }, + }, + [Function], + ], + [ + "rLynxChange", + { + "data": "{"patchList":[{"id":7,"snapshotPatch":[3,-3,0,"light"]}]}", + "patchOptions": { + "reloadVersion": 0, + }, + }, + [Function], + ], + ] + `); + // ui change + globalEnvManager.switchToMainThread(); + for (const rLynxChange of lynx.getNativeApp().callLepusMethod.mock.calls) { + globalThis[rLynxChange[0]](rLynxChange[1]); + rLynxChange[2](); + } + expect(__root.__element_root).toMatchInlineSnapshot(` + + + + + + `); + } + }); +}); diff --git a/packages/react/runtime/__test__/snapshot/lifecycle/updateGlobalProps.test.jsx b/packages/react/runtime/__test__/snapshot/lifecycle/updateGlobalProps.test.jsx index 380596045f..f61d9d4b38 100644 --- a/packages/react/runtime/__test__/snapshot/lifecycle/updateGlobalProps.test.jsx +++ b/packages/react/runtime/__test__/snapshot/lifecycle/updateGlobalProps.test.jsx @@ -7,7 +7,6 @@ import { globalEnvManager } from '../utils/envManager'; import { describe } from 'vitest'; import { it } from 'vitest'; import { expect } from 'vitest'; -import { render } from 'preact'; import { waitSchedule } from '../utils/nativeMethod'; import { beforeAll } from 'vitest'; import { replaceCommitHook } from '../../../src/snapshot/lifecycle/patch/commit'; @@ -24,11 +23,20 @@ beforeEach(() => { afterEach(() => { elementTree.clear(); - vi.resetModules(); vi.restoreAllMocks(); globalThis.__GLOBAL_PROPS_MODE__ = 'reactive'; }); +async function renderWithCurrentPreact(element, root) { + const [preact, { document, setupBackgroundDocument }] = await Promise.all([ + import('preact'), + import('../../../src/document'), + ]); + setupBackgroundDocument(); + preact.options.document = document; + preact.render(element, root); +} + describe('updateGlobalProps', () => { it('should update global props', async () => { lynx.__globalProps = { theme: 'dark' }; @@ -57,7 +65,7 @@ describe('updateGlobalProps', () => { { globalEnvManager.switchToBackground(); __root.__jsx = ; - render(, __root); + await renderWithCurrentPreact(, __root); } // hydrate @@ -141,7 +149,7 @@ describe('updateGlobalProps', () => { { globalEnvManager.switchToBackground(); __root.__jsx = ; - render(, __root); + await renderWithCurrentPreact(, __root); expect(console.warn).toBeCalledWith(expect.stringContaining('No need to use this API')); } @@ -240,7 +248,7 @@ describe('updateGlobalProps', () => { { globalEnvManager.switchToBackground(); __root.__jsx = ; - render(, __root); + await renderWithCurrentPreact(, __root); expect(console.warn).toBeCalledWith(expect.stringContaining('No need to use this API')); } @@ -329,7 +337,7 @@ describe('updateGlobalProps', () => { { globalEnvManager.switchToBackground(); __root.__jsx = ; - render(, __root); + await renderWithCurrentPreact(, __root); } // hydrate @@ -371,207 +379,4 @@ describe('updateGlobalProps', () => { `); } }); - - it('should trigger re-render when useGlobalProps is called', async () => { - globalThis.__GLOBAL_PROPS_MODE__ = 'event'; - const { useGlobalProps, useGlobalPropsChanged, GlobalPropsProvider, GlobalPropsConsumer } = await import( - '../../../src/lynx-api' - ); - - lynx.__globalProps = { theme: 'dark' }; - let count = 0; - let dataTheme, globalPropsTheme; - const Comp = () => { - const globalProps = useGlobalProps(); - useGlobalPropsChanged(data => { - count++; - dataTheme = data.theme; - globalPropsTheme = lynx.__globalProps.theme; - }); - return {globalProps.theme}; - }; - - // main thread render - { - __root.__jsx = ; - renderPage(); - expect(count).toBe(0); - expect(__root.__element_root).toMatchInlineSnapshot(` - - - - - - `); - } - - // background render - { - globalEnvManager.switchToBackground(); - __root.__jsx = ; - render(, __root); - } - - // hydrate - { - lynxCoreInject.tt.OnLifecycleEvent(...globalThis.__OnLifecycleEvent.mock.calls[0]); - } - - // rLynxChange - { - globalEnvManager.switchToMainThread(); - globalThis.__OnLifecycleEvent.mockClear(); - const rLynxChange = lynx.getNativeApp().callLepusMethod.mock.calls[0]; - globalThis[rLynxChange[0]](rLynxChange[1]); - await waitSchedule(); - } - - // updateGlobalProps - { - globalEnvManager.switchToBackground(); - lynx.getNativeApp().callLepusMethod.mockClear(); - lynxCoreInject.tt.updateGlobalProps({ theme: 'light' }); - await waitSchedule(); - - // rLynxChange should be called - expect(lynx.getNativeApp().callLepusMethod.mock.calls.length).toBe(1); - expect(count).toBe(1); - expect(dataTheme).toBe('light'); - expect(globalPropsTheme).toBe('light'); - // ui change - globalEnvManager.switchToMainThread(); - for (const rLynxChange of lynx.getNativeApp().callLepusMethod.mock.calls) { - globalThis[rLynxChange[0]](rLynxChange[1]); - rLynxChange[2](); - } - expect(__root.__element_root).toMatchInlineSnapshot(` - - - - - - `); - } - }); - - it('should trigger update when GlobalPropsProvider and useGlobalProps are used', async () => { - globalThis.__GLOBAL_PROPS_MODE__ = 'event'; - const { useGlobalProps, useGlobalPropsChanged, GlobalPropsProvider, GlobalPropsConsumer } = await import( - '../../../src/lynx-api' - ); - - lynx.__globalProps = { theme: 'dark' }; - const Comp = () => { - return ( - - - {globalProps => { - return {globalProps.theme}; - }} - - - ); - }; - - // main thread render - { - __root.__jsx = ; - renderPage(); - expect(__root.__element_root).toMatchInlineSnapshot(` - - - - - - `); - } - - // background render - { - globalEnvManager.switchToBackground(); - __root.__jsx = ; - render(, __root); - } - - // hydrate - { - lynxCoreInject.tt.OnLifecycleEvent(...globalThis.__OnLifecycleEvent.mock.calls[0]); - } - - // rLynxChange - { - globalEnvManager.switchToMainThread(); - globalThis.__OnLifecycleEvent.mockClear(); - const rLynxChange = lynx.getNativeApp().callLepusMethod.mock.calls[0]; - globalThis[rLynxChange[0]](rLynxChange[1]); - await waitSchedule(); - } - - // updateGlobalProps - { - globalEnvManager.switchToBackground(); - lynx.getNativeApp().callLepusMethod.mockClear(); - lynxCoreInject.tt.updateGlobalProps({ theme: 'light' }); - await waitSchedule(); - - // rLynxChange should be called - expect(lynx.getNativeApp().callLepusMethod.mock.calls.length).toBe(2); - expect(lynx.getNativeApp().callLepusMethod.mock.calls).toMatchInlineSnapshot(` - [ - [ - "rLynxChange", - { - "data": "{"patchList":[{"id":17}]}", - "patchOptions": { - "flowIds": [ - 666, - ], - "reloadVersion": 0, - }, - }, - [Function], - ], - [ - "rLynxChange", - { - "data": "{"patchList":[{"id":18,"snapshotPatch":[3,-3,0,"light"]}]}", - "patchOptions": { - "reloadVersion": 0, - }, - }, - [Function], - ], - ] - `); - // ui change - globalEnvManager.switchToMainThread(); - for (const rLynxChange of lynx.getNativeApp().callLepusMethod.mock.calls) { - globalThis[rLynxChange[0]](rLynxChange[1]); - rLynxChange[2](); - } - expect(__root.__element_root).toMatchInlineSnapshot(` - - - - - - `); - } - }); }); diff --git a/packages/react/runtime/src/core/hooks/mainThread.ts b/packages/react/runtime/src/core/hooks/mainThread.ts new file mode 100644 index 0000000000..9609cbf4b6 --- /dev/null +++ b/packages/react/runtime/src/core/hooks/mainThread.ts @@ -0,0 +1,9 @@ +// Copyright 2026 The Lynx Authors. All rights reserved. +// Licensed under the Apache License Version 2.0 that can be found in the +// LICENSE file in the root directory of this source tree. + +import { installMainThreadHooks } from './mainThreadImpl.js'; + +installMainThreadHooks(); + +export * from './mainThreadImpl.js'; diff --git a/packages/react/runtime/src/snapshot/hooks/mainThread.ts b/packages/react/runtime/src/core/hooks/mainThreadImpl.ts similarity index 77% rename from packages/react/runtime/src/snapshot/hooks/mainThread.ts rename to packages/react/runtime/src/core/hooks/mainThreadImpl.ts index 1ed23bccbd..5973062d05 100644 --- a/packages/react/runtime/src/snapshot/hooks/mainThread.ts +++ b/packages/react/runtime/src/core/hooks/mainThreadImpl.ts @@ -3,7 +3,7 @@ // LICENSE file in the root directory of this source tree. /** - * Implements hooks in main thread. + * Implements hooks in the main thread. * This module is modified from preact/hooks * * internal-preact/hooks/dist/hooks.mjs @@ -19,7 +19,6 @@ import type { useLayoutEffect as useLayoutEffectType, } from 'preact/hooks'; -import { noop } from '../../utils.js'; import { CHILDREN, COMPONENT, @@ -35,43 +34,55 @@ import { ROOT, VALUE, VNODE, -} from '../renderToOpcodes/constants.js'; +} from '../../shared/render-constants.js'; +import { noop } from '../../utils.js'; let currentIndex: number; let currentComponent: Component | null | undefined; let currentHook: number; +let hooksInstalled = false; +let oldBeforeDiff: ((vnode: any) => void) | undefined; +let oldBeforeRender: ((vnode: any) => void) | undefined; +let oldAfterDiff: ((vnode: any) => void) | undefined; +let oldRoot: ((vnode: any, parentDom: any) => void) | undefined; + +function installMainThreadHooks(): void { + if (hooksInstalled) { + return; + } + hooksInstalled = true; + oldBeforeDiff = options[DIFF]; + oldBeforeRender = options[RENDER]; + oldAfterDiff = options[DIFFED]; + oldRoot = options[ROOT]; + + options[DIFF] = function(vnode) { + currentComponent = null; + if (oldBeforeDiff) oldBeforeDiff(vnode); + }; -const oldBeforeDiff = options[DIFF]; -const oldBeforeRender = options[RENDER]; -const oldAfterDiff = options[DIFFED]; -const oldRoot = options[ROOT]; - -options[DIFF] = function(vnode) { - currentComponent = null; - if (oldBeforeDiff) oldBeforeDiff(vnode); -}; - -/* v8 ignore start */ -options[ROOT] = function(vnode, parentDom) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (vnode && parentDom[CHILDREN] && parentDom[CHILDREN][MASK]) { + /* v8 ignore start */ + options[ROOT] = function(vnode, parentDom) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - vnode[MASK] = parentDom[CHILDREN][MASK] as [number, number]; - } - if (oldRoot) oldRoot(vnode, parentDom); -}; -/* v8 ignore stop */ + if (vnode && parentDom[CHILDREN] && parentDom[CHILDREN][MASK]) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + vnode[MASK] = parentDom[CHILDREN][MASK] as [number, number]; + } + if (oldRoot) oldRoot(vnode, parentDom); + }; + /* v8 ignore stop */ -options[RENDER] = function(vnode) { - if (oldBeforeRender) oldBeforeRender(vnode); - currentComponent = vnode[COMPONENT]; - currentIndex = 0; -}; + options[RENDER] = function(vnode) { + if (oldBeforeRender) oldBeforeRender(vnode); + currentComponent = vnode[COMPONENT]; + currentIndex = 0; + }; -options[DIFFED] = function(vnode) { - if (oldAfterDiff) oldAfterDiff(vnode); - currentComponent = null; -}; + options[DIFFED] = function(vnode) { + if (oldAfterDiff) oldAfterDiff(vnode); + currentComponent = null; + }; +} function getHookState(index: number, type: number) { if (options[HOOK]) { @@ -197,6 +208,7 @@ const useLayoutEffect = noop as typeof useLayoutEffectType; const useImperativeHandle = noop as typeof useImperativeHandleType; export { + installMainThreadHooks, useCallback, useContext, useDebugValue, diff --git a/packages/react/runtime/src/snapshot/hooks/react.ts b/packages/react/runtime/src/core/hooks/react.ts similarity index 99% rename from packages/react/runtime/src/snapshot/hooks/react.ts rename to packages/react/runtime/src/core/hooks/react.ts index 3f96b43a36..b0994ca03e 100644 --- a/packages/react/runtime/src/snapshot/hooks/react.ts +++ b/packages/react/runtime/src/core/hooks/react.ts @@ -19,7 +19,7 @@ import type { DependencyList, EffectCallback } from 'react'; import type { TraceOption } from '@lynx-js/types'; -import { isProfiling, profileEnd, profileFlowId, profileStart } from '../debug/profile.js'; +import { isProfiling, profileEnd, profileFlowId, profileStart } from '../../shared/profile.js'; type GenericSetState = Dispatch>; diff --git a/packages/react/runtime/src/snapshot/hooks/useLynxGlobalEventListener.ts b/packages/react/runtime/src/core/hooks/useLynxGlobalEventListener.ts similarity index 95% rename from packages/react/runtime/src/snapshot/hooks/useLynxGlobalEventListener.ts rename to packages/react/runtime/src/core/hooks/useLynxGlobalEventListener.ts index 8c180719ba..30d9ecf0e0 100644 --- a/packages/react/runtime/src/snapshot/hooks/useLynxGlobalEventListener.ts +++ b/packages/react/runtime/src/core/hooks/useLynxGlobalEventListener.ts @@ -4,7 +4,7 @@ import { useEffect, useMemo, useRef } from 'preact/hooks'; /** - * `useLynxGlobalEventListener` help you `addListener` as early as possible. + * `useLynxGlobalEventListener` helps you `addListener` as early as possible. * * @example * diff --git a/packages/react/runtime/src/index.ts b/packages/react/runtime/src/index.ts index a2be13406f..13f69eaf7f 100644 --- a/packages/react/runtime/src/index.ts +++ b/packages/react/runtime/src/index.ts @@ -31,12 +31,12 @@ import { useReducer, useRef, useState, -} from './snapshot/hooks/react.js'; +} from './core/hooks/react.js'; import { Suspense } from './snapshot/lynx/suspense.js'; export { Component, createContext } from 'preact'; export { PureComponent } from 'preact/compat'; -export * from './snapshot/hooks/react.js'; +export * from './core/hooks/react.js'; /** * @internal diff --git a/packages/react/runtime/src/internal.ts b/packages/react/runtime/src/internal.ts index c5dfca947c..075d4af944 100644 --- a/packages/react/runtime/src/internal.ts +++ b/packages/react/runtime/src/internal.ts @@ -7,9 +7,9 @@ import type { FC } from 'react'; import './lynx.js'; +import { useMemo } from './core/hooks/react.js'; import { __root } from './root.js'; import { factory as factory2 } from './snapshot/compat/componentIs.js'; -import { useMemo } from './snapshot/hooks/react.js'; import { loadLazyBundle } from './snapshot/lynx/lazy-bundle.js'; import { BackgroundSnapshotInstance } from './snapshot/snapshot/backgroundSnapshot.js'; import { __page, __pageId, createSnapshot, snapshotManager } from './snapshot/snapshot/definition.js'; @@ -17,7 +17,7 @@ import { DynamicPartType } from './snapshot/snapshot/dynamicPartType.js'; import { snapshotCreateList } from './snapshot/snapshot/list.js'; import { SnapshotInstance, snapshotCreatorMap } from './snapshot/snapshot/snapshot.js'; -export { CHILDREN, COMPONENT, DIFF, DIRTY, DOM, FLAGS, INDEX, PARENT } from './snapshot/renderToOpcodes/constants.js'; +export { CHILDREN, COMPONENT, DIFF, DIRTY, DOM, FLAGS, INDEX, PARENT } from './shared/render-constants.js'; export { __page, __pageId, __root }; diff --git a/packages/react/runtime/src/lynx-api.ts b/packages/react/runtime/src/lynx-api.ts index 180da40023..3d2cac947a 100644 --- a/packages/react/runtime/src/lynx-api.ts +++ b/packages/react/runtime/src/lynx-api.ts @@ -6,10 +6,10 @@ import { createContext, createElement } from 'preact/compat'; import { useState } from 'preact/hooks'; import type { Consumer, FC, ReactNode } from 'react'; +import { useLynxGlobalEventListener } from './core/hooks/useLynxGlobalEventListener.js'; import { __root } from './root.js'; +import { profileEnd, profileStart } from './shared/profile.js'; import { factory, withInitDataInState } from './snapshot/compat/initData.js'; -import { profileEnd, profileStart } from './snapshot/debug/profile.js'; -import { useLynxGlobalEventListener } from './snapshot/hooks/useLynxGlobalEventListener.js'; import { LifecycleConstant } from './snapshot/lifecycle/constant.js'; import { flushDelayedLifecycleEvents } from './snapshot/lynx/tt.js'; @@ -572,7 +572,7 @@ export interface Lynx { registerDataProcessors: (dataProcessorDefinition?: DataProcessorDefinition) => void; } -export { useLynxGlobalEventListener } from './snapshot/hooks/useLynxGlobalEventListener.js'; +export { useLynxGlobalEventListener } from './core/hooks/useLynxGlobalEventListener.js'; export { runOnBackground } from './snapshot/worklet/call/runOnBackground.js'; export { runOnMainThread } from './snapshot/worklet/call/runOnMainThread.js'; export { MainThreadRef, useMainThreadRef } from './snapshot/worklet/ref/workletRef.js'; diff --git a/packages/react/runtime/src/lynx.ts b/packages/react/runtime/src/lynx.ts index 2864d9c1be..e4a20519af 100644 --- a/packages/react/runtime/src/lynx.ts +++ b/packages/react/runtime/src/lynx.ts @@ -3,13 +3,13 @@ // LICENSE file in the root directory of this source tree. import { options } from 'preact'; // to make sure preact's hooks to register earlier than ours -import './snapshot/hooks/react.js'; +import './core/hooks/react.js'; import { document, setupBackgroundDocument } from './document.js'; +import { setupComponentStack } from './shared/component-stack.js'; +import { isProfiling } from './shared/profile.js'; import { initElementPAPICallAlog } from './snapshot/alog/elementPAPICall.js'; import { initAlog } from './snapshot/alog/index.js'; -import { setupComponentStack } from './snapshot/debug/component-stack.js'; -import { isProfiling } from './snapshot/debug/profile.js'; import { initProfileHook } from './snapshot/debug/profileHooks.js'; import { setupVNodeSourceHook } from './snapshot/debug/vnodeSource.js'; import { replaceCommitHook } from './snapshot/lifecycle/patch/commit.js'; diff --git a/packages/react/runtime/src/snapshot/debug/component-stack.ts b/packages/react/runtime/src/shared/component-stack.ts similarity index 98% rename from packages/react/runtime/src/snapshot/debug/component-stack.ts rename to packages/react/runtime/src/shared/component-stack.ts index a4474333b5..cab4eb1741 100644 --- a/packages/react/runtime/src/snapshot/debug/component-stack.ts +++ b/packages/react/runtime/src/shared/component-stack.ts @@ -30,7 +30,7 @@ SOFTWARE. import { Fragment, options } from 'preact'; import type { VNode } from 'preact'; -import { DIFF, DIFFED, RENDER, ROOT } from '../renderToOpcodes/constants.js'; +import { DIFF, DIFFED, RENDER, ROOT } from './render-constants.js'; interface PatchedVNode extends VNode { _owner?: PatchedVNode | null; diff --git a/packages/react/runtime/src/snapshot/debug/profile.ts b/packages/react/runtime/src/shared/profile.ts similarity index 82% rename from packages/react/runtime/src/snapshot/debug/profile.ts rename to packages/react/runtime/src/shared/profile.ts index 1ae2fe6707..edb1c448a5 100644 --- a/packages/react/runtime/src/snapshot/debug/profile.ts +++ b/packages/react/runtime/src/shared/profile.ts @@ -2,14 +2,15 @@ // Licensed under the Apache License Version 2.0 that can be found in the // LICENSE file in the root directory of this source tree. -import { noop } from '../../utils.js'; +/* v8 ignore start */ +const noop: (...args: unknown[]) => unknown = () => {}; +const noopFlowId = () => 0; +/* v8 ignore end */ export const isProfiling: boolean = /* @__PURE__ */ Boolean( lynx.performance?.isProfileRecording?.(), ); -const noopFlowId = () => 0; - export const profileStart = /* @__PURE__ */ ((() => { let p; if (!(p = lynx.performance) || typeof p.profileStart !== 'function') { @@ -26,10 +27,10 @@ export const profileEnd = /* @__PURE__ */ ((() => { return p.profileEnd.bind(p); })()) as typeof lynx.performance.profileEnd; -export const profileFlowId = /* @__PURE__ */ ((() => { +export const profileFlowId: typeof lynx.performance.profileFlowId = /* @__PURE__ */ (() => { let p; if (!(p = lynx.performance) || typeof p.profileFlowId !== 'function') { return noopFlowId; } return p.profileFlowId.bind(p); -})()) as typeof lynx.performance.profileFlowId; +})(); diff --git a/packages/react/runtime/src/snapshot/renderToOpcodes/constants.ts b/packages/react/runtime/src/shared/render-constants.ts similarity index 100% rename from packages/react/runtime/src/snapshot/renderToOpcodes/constants.ts rename to packages/react/runtime/src/shared/render-constants.ts diff --git a/packages/react/runtime/src/snapshot/alog/elementPAPICall.ts b/packages/react/runtime/src/snapshot/alog/elementPAPICall.ts index 0f7b78c263..9218a6c84d 100644 --- a/packages/react/runtime/src/snapshot/alog/elementPAPICall.ts +++ b/packages/react/runtime/src/snapshot/alog/elementPAPICall.ts @@ -2,7 +2,7 @@ // Licensed under the Apache License Version 2.0 that can be found in the // LICENSE file in the root directory of this source tree. -import { profileEnd, profileStart } from '../debug/profile.js'; +import { profileEnd, profileStart } from '../../shared/profile.js'; const fiberElementPAPINameList = [ '__CreatePage', diff --git a/packages/react/runtime/src/snapshot/alog/render.ts b/packages/react/runtime/src/snapshot/alog/render.ts index a820261bd5..34b011a6db 100644 --- a/packages/react/runtime/src/snapshot/alog/render.ts +++ b/packages/react/runtime/src/snapshot/alog/render.ts @@ -4,8 +4,8 @@ import { options } from 'preact'; import type { ComponentClass, VNode } from 'preact'; +import { DIFFED, DOM } from '../../shared/render-constants.js'; import { getDisplayName } from '../../utils.js'; -import { DIFFED, DOM } from '../renderToOpcodes/constants.js'; import type { SnapshotInstance } from '../snapshot/snapshot.js'; export function initRenderAlog(): void { diff --git a/packages/react/runtime/src/snapshot/compat/initData.ts b/packages/react/runtime/src/snapshot/compat/initData.ts index fe2a6402d8..edeea7adf0 100644 --- a/packages/react/runtime/src/snapshot/compat/initData.ts +++ b/packages/react/runtime/src/snapshot/compat/initData.ts @@ -4,7 +4,7 @@ import type { ComponentChildren, Consumer, Context, Provider } from 'preact'; import type { ComponentClass } from 'react'; -import { useLynxGlobalEventListener } from '../hooks/useLynxGlobalEventListener.js'; +import { useLynxGlobalEventListener } from '../../core/hooks/useLynxGlobalEventListener.js'; import { globalFlushOptions } from '../lifecycle/patch/commit.js'; type Getter = { @@ -16,7 +16,7 @@ export function factory( { createContext, useState, createElement, useLynxGlobalEventListener: useListener }: { createContext: typeof import('preact').createContext; useState: typeof import('preact/hooks').useState; - createElement: typeof import('preact').createElement; + createElement: typeof import('preact/compat').createElement; useLynxGlobalEventListener: typeof useLynxGlobalEventListener; }, prop: '__globalProps' | '__initData', diff --git a/packages/react/runtime/src/snapshot/debug/profileHooks.ts b/packages/react/runtime/src/snapshot/debug/profileHooks.ts index d09c8c703b..884fac08c5 100644 --- a/packages/react/runtime/src/snapshot/debug/profileHooks.ts +++ b/packages/react/runtime/src/snapshot/debug/profileHooks.ts @@ -6,9 +6,6 @@ import type { ComponentClass, ComponentType, VNode } from 'preact'; import type { TraceOption } from '@lynx-js/types'; -import { getDisplayName, hook } from '../../utils.js'; -import { globalPatchOptions } from '../lifecycle/patch/commit.js'; -import { __globalSnapshotPatch } from '../lifecycle/patch/snapshotPatch.js'; import { COMMIT, COMPONENT, @@ -23,7 +20,10 @@ import { RENDER, VALUE, VNODE, -} from '../renderToOpcodes/constants.js'; +} from '../../shared/render-constants.js'; +import { getDisplayName, hook } from '../../utils.js'; +import { globalPatchOptions } from '../lifecycle/patch/commit.js'; +import { __globalSnapshotPatch } from '../lifecycle/patch/snapshotPatch.js'; const format = (val: unknown) => { if (typeof val === 'function') { diff --git a/packages/react/runtime/src/snapshot/debug/vnodeSource.ts b/packages/react/runtime/src/snapshot/debug/vnodeSource.ts index aa8e9f8843..d1231573a2 100644 --- a/packages/react/runtime/src/snapshot/debug/vnodeSource.ts +++ b/packages/react/runtime/src/snapshot/debug/vnodeSource.ts @@ -4,7 +4,7 @@ import { options } from 'preact'; import type { VNode } from 'preact'; -import { DIFFED, DOM } from '../renderToOpcodes/constants.js'; +import { DIFFED, DOM } from '../../shared/render-constants.js'; interface SourceInfo { fileName?: string; diff --git a/packages/react/runtime/src/snapshot/legacy-react-runtime/index.ts b/packages/react/runtime/src/snapshot/legacy-react-runtime/index.ts index ff74990cca..716732542b 100644 --- a/packages/react/runtime/src/snapshot/legacy-react-runtime/index.ts +++ b/packages/react/runtime/src/snapshot/legacy-react-runtime/index.ts @@ -4,11 +4,11 @@ import { createContext, createRef } from 'preact'; import { lazy } from 'preact/compat'; +import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from '../../core/hooks/react.js'; import { ComponentFromReactRuntime as Component, ComponentFromReactRuntime as PureComponent, } from '../compat/lynxComponent.js'; -import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from '../hooks/react.js'; /* v8 ignore next 3 */ function __runInJS(value: T): T | undefined | null { @@ -20,7 +20,7 @@ export { ComponentFromReactRuntime as Component } from '../compat/lynxComponent. export { ComponentFromReactRuntime as PureComponent } from '../compat/lynxComponent.js'; export { createContext } from 'preact'; export { lazy } from 'preact/compat'; -export { useState, useReducer, useEffect, useMemo, useCallback /*, useInstance */ } from '../hooks/react.js'; +export { useState, useReducer, useEffect, useMemo, useCallback /*, useInstance */ } from '../../core/hooks/react.js'; export { __runInJS, createRef, useRef }; /** diff --git a/packages/react/runtime/src/snapshot/lifecycle/destroy.ts b/packages/react/runtime/src/snapshot/lifecycle/destroy.ts index ce65c38d8a..4700517020 100644 --- a/packages/react/runtime/src/snapshot/lifecycle/destroy.ts +++ b/packages/react/runtime/src/snapshot/lifecycle/destroy.ts @@ -7,7 +7,7 @@ import { __root } from '../../root.js'; import { delayedEvents } from './event/delayEvents.js'; import { delayedLifecycleEvents } from './event/delayLifecycleEvents.js'; import { globalCommitTaskMap } from './patch/commit.js'; -import { profileEnd, profileStart } from '../debug/profile.js'; +import { profileEnd, profileStart } from '../../shared/profile.js'; function destroyBackground(): void { if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { diff --git a/packages/react/runtime/src/snapshot/lifecycle/event/jsReady.ts b/packages/react/runtime/src/snapshot/lifecycle/event/jsReady.ts index 4fcda32269..6e2d489061 100644 --- a/packages/react/runtime/src/snapshot/lifecycle/event/jsReady.ts +++ b/packages/react/runtime/src/snapshot/lifecycle/event/jsReady.ts @@ -2,7 +2,7 @@ // Licensed under the Apache License Version 2.0 that can be found in the // LICENSE file in the root directory of this source tree. import { __root } from '../../../root.js'; -import { profileEnd, profileStart } from '../../debug/profile.js'; +import { profileEnd, profileStart } from '../../../shared/profile.js'; import { LifecycleConstant } from '../../lifecycle/constant.js'; let isJSReady: boolean; diff --git a/packages/react/runtime/src/snapshot/lifecycle/isRendering.ts b/packages/react/runtime/src/snapshot/lifecycle/isRendering.ts index ac0d933c9f..3be5c3e1ea 100644 --- a/packages/react/runtime/src/snapshot/lifecycle/isRendering.ts +++ b/packages/react/runtime/src/snapshot/lifecycle/isRendering.ts @@ -4,8 +4,8 @@ import { options } from 'preact'; +import { RENDER_COMPONENT, ROOT } from '../../shared/render-constants.js'; import { hook, lynxQueueMicrotask } from '../../utils.js'; -import { RENDER_COMPONENT, ROOT } from '../renderToOpcodes/constants.js'; export const isRendering = /* @__PURE__ */ { value: false }; diff --git a/packages/react/runtime/src/snapshot/lifecycle/patch/commit.ts b/packages/react/runtime/src/snapshot/lifecycle/patch/commit.ts index 531f108dfb..115336fb31 100644 --- a/packages/react/runtime/src/snapshot/lifecycle/patch/commit.ts +++ b/packages/react/runtime/src/snapshot/lifecycle/patch/commit.ts @@ -29,11 +29,11 @@ import { } from './globalState.js'; import { takeGlobalSnapshotPatch } from './snapshotPatch.js'; import type { SnapshotPatch } from './snapshotPatch.js'; +import { profileEnd, profileStart } from '../../../shared/profile.js'; +import { COMMIT } from '../../../shared/render-constants.js'; import { hook, isEmptyObject } from '../../../utils.js'; -import { profileEnd, profileStart } from '../../debug/profile.js'; import { LifecycleConstant } from '../../lifecycle/constant.js'; import { globalPipelineOptions, markTiming, markTimingLegacy, setPipeline } from '../../lynx/performance.js'; -import { COMMIT } from '../../renderToOpcodes/constants.js'; import { backgroundSnapshotInstanceManager } from '../../snapshot/backgroundSnapshot.js'; import { applyQueuedRefs } from '../../snapshot/ref.js'; import { diff --git a/packages/react/runtime/src/snapshot/lifecycle/reload.ts b/packages/react/runtime/src/snapshot/lifecycle/reload.ts index 88ec0692d9..5d8b1bbafe 100644 --- a/packages/react/runtime/src/snapshot/lifecycle/reload.ts +++ b/packages/react/runtime/src/snapshot/lifecycle/reload.ts @@ -13,8 +13,8 @@ import { destroyBackground } from './destroy.js'; import { increaseReloadVersion } from './pass.js'; import { renderMainThread } from './render.js'; import { __root, setRoot } from '../../root.js'; +import { profileEnd, profileStart } from '../../shared/profile.js'; import { isEmptyObject } from '../../utils.js'; -import { profileEnd, profileStart } from '../debug/profile.js'; import { LifecycleConstant } from '../lifecycle/constant.js'; import { __pendingListUpdates } from '../list/pendingListUpdates.js'; import { hydrate } from '../renderToOpcodes/hydrate.js'; diff --git a/packages/react/runtime/src/snapshot/lifecycle/render.ts b/packages/react/runtime/src/snapshot/lifecycle/render.ts index 04d7b541c4..f14b6246c6 100644 --- a/packages/react/runtime/src/snapshot/lifecycle/render.ts +++ b/packages/react/runtime/src/snapshot/lifecycle/render.ts @@ -7,7 +7,7 @@ */ import { __root } from '../../root.js'; -import { profileEnd, profileStart } from '../debug/profile.js'; +import { profileEnd, profileStart } from '../../shared/profile.js'; import { render as renderToString } from '../renderToOpcodes/index.js'; import { SnapshotInstance } from '../snapshot/snapshot.js'; diff --git a/packages/react/runtime/src/snapshot/list/listUpdateInfo.ts b/packages/react/runtime/src/snapshot/list/listUpdateInfo.ts index c53bc69bd4..87291908e8 100644 --- a/packages/react/runtime/src/snapshot/list/listUpdateInfo.ts +++ b/packages/react/runtime/src/snapshot/list/listUpdateInfo.ts @@ -2,7 +2,7 @@ // Licensed under the Apache License Version 2.0 that can be found in the // LICENSE file in the root directory of this source tree. import { componentAtIndexFactory, enqueueComponentFactory } from './list.js'; -import { profileEnd, profileStart } from '../debug/profile.js'; +import { profileEnd, profileStart } from '../../shared/profile.js'; import { hydrate } from '../renderToOpcodes/hydrate.js'; import type { SnapshotInstance } from '../snapshot/snapshot.js'; diff --git a/packages/react/runtime/src/snapshot/lynx/component.ts b/packages/react/runtime/src/snapshot/lynx/component.ts index c8021fecd5..c2fc207473 100644 --- a/packages/react/runtime/src/snapshot/lynx/component.ts +++ b/packages/react/runtime/src/snapshot/lynx/component.ts @@ -8,7 +8,7 @@ import { Component } from 'preact'; import { PerfSpecificKey, markTimingLegacy } from './performance.js'; import { globalFlushOptions } from '../lifecycle/patch/commit.js'; -import { NEXT_STATE } from '../renderToOpcodes/constants.js'; +import { NEXT_STATE } from '../../shared/render-constants.js'; if (__JS__) { function reportRefDeprecationError(fnName: string, newFnName: string) { diff --git a/packages/react/runtime/src/snapshot/lynx/env.ts b/packages/react/runtime/src/snapshot/lynx/env.ts index 5fa934977d..d8ced4d26e 100644 --- a/packages/react/runtime/src/snapshot/lynx/env.ts +++ b/packages/react/runtime/src/snapshot/lynx/env.ts @@ -2,7 +2,7 @@ // Licensed under the Apache License Version 2.0 that can be found in the // LICENSE file in the root directory of this source tree. import type { DataProcessorDefinition, InitData, InitDataRaw } from '../../lynx-api.js'; -import { profileEnd, profileStart } from '../debug/profile.js'; +import { profileEnd, profileStart } from '../../shared/profile.js'; export function setupLynxEnv(): void { if (!__LEPUS__) { diff --git a/packages/react/runtime/src/snapshot/lynx/performance.ts b/packages/react/runtime/src/snapshot/lynx/performance.ts index f12d6bf8a3..864f3b7d95 100644 --- a/packages/react/runtime/src/snapshot/lynx/performance.ts +++ b/packages/react/runtime/src/snapshot/lynx/performance.ts @@ -3,9 +3,9 @@ // LICENSE file in the root directory of this source tree. import { options } from 'preact'; +import { RENDER_COMPONENT, ROOT } from '../../shared/render-constants.js'; import { hook, isSdkVersionGt } from '../../utils.js'; import { __globalSnapshotPatch } from '../lifecycle/patch/snapshotPatch.js'; -import { RENDER_COMPONENT, ROOT } from '../renderToOpcodes/constants.js'; const PerformanceTimingKeys = [ 'updateSetStateTrigger', diff --git a/packages/react/runtime/src/snapshot/lynx/runWithForce.ts b/packages/react/runtime/src/snapshot/lynx/runWithForce.ts index 236ed3361c..3b21761449 100644 --- a/packages/react/runtime/src/snapshot/lynx/runWithForce.ts +++ b/packages/react/runtime/src/snapshot/lynx/runWithForce.ts @@ -5,7 +5,7 @@ import { options } from 'preact'; import type { VNode } from 'preact'; import { __root } from '../../root.js'; -import { COMPONENT, DIFF2, FORCE, ORIGINAL } from '../renderToOpcodes/constants.js'; +import { COMPONENT, DIFF2, FORCE, ORIGINAL } from '../../shared/render-constants.js'; export function runWithForce(cb: () => void): void { // In https://github.com/preactjs/preact/pull/4724, preact will diff --git a/packages/react/runtime/src/snapshot/lynx/tt.ts b/packages/react/runtime/src/snapshot/lynx/tt.ts index 5e31140e65..83f141a44a 100644 --- a/packages/react/runtime/src/snapshot/lynx/tt.ts +++ b/packages/react/runtime/src/snapshot/lynx/tt.ts @@ -6,8 +6,9 @@ import { process, render } from 'preact'; import { PerformanceTimingFlags, PipelineOrigins, beginPipeline, markTiming } from './performance.js'; import { runWithForce } from './runWithForce.js'; import { __root } from '../../root.js'; +import { profileEnd, profileStart } from '../../shared/profile.js'; +import { CHILDREN } from '../../shared/render-constants.js'; import { printSnapshotInstanceToString } from '../debug/printSnapshot.js'; -import { profileEnd, profileStart } from '../debug/profile.js'; import { getSnapshotVNodeSource } from '../debug/vnodeSource.js'; import { LifecycleConstant, NativeUpdateDataType } from '../lifecycle/constant.js'; import type { FirstScreenData } from '../lifecycle/constant.js'; @@ -19,7 +20,6 @@ import type { PatchList } from '../lifecycle/patch/commit.js'; import { removeCtxNotFoundEventListener } from '../lifecycle/patch/error.js'; import { runDelayedUiOps } from '../lifecycle/ref/delay.js'; import { reloadBackground } from '../lifecycle/reload.js'; -import { CHILDREN } from '../renderToOpcodes/constants.js'; import { BackgroundSnapshotInstance, backgroundSnapshotInstanceManager, diff --git a/packages/react/runtime/src/snapshot/renderToOpcodes/hydrate.ts b/packages/react/runtime/src/snapshot/renderToOpcodes/hydrate.ts index 40987fd216..5f2b60af85 100644 --- a/packages/react/runtime/src/snapshot/renderToOpcodes/hydrate.ts +++ b/packages/react/runtime/src/snapshot/renderToOpcodes/hydrate.ts @@ -2,7 +2,7 @@ // Licensed under the Apache License Version 2.0 that can be found in the // LICENSE file in the root directory of this source tree. -import { profileEnd, profileStart } from '../debug/profile.js'; +import { profileEnd, profileStart } from '../../shared/profile.js'; import { componentAtIndexFactory, enqueueComponentFactory, gRecycleMap, gSignMap } from '../list/list.js'; import { __pendingListUpdates } from '../list/pendingListUpdates.js'; import { DynamicPartType } from '../snapshot/dynamicPartType.js'; diff --git a/packages/react/runtime/src/snapshot/renderToOpcodes/index.ts b/packages/react/runtime/src/snapshot/renderToOpcodes/index.ts index 451eb450bb..d44217adba 100644 --- a/packages/react/runtime/src/snapshot/renderToOpcodes/index.ts +++ b/packages/react/runtime/src/snapshot/renderToOpcodes/index.ts @@ -28,7 +28,7 @@ import { VNODE, HOOK, CHILD_DID_SUSPEND, -} from './constants.js'; +} from '../../shared/render-constants.js'; /** @typedef {import('preact').VNode} VNode */ diff --git a/packages/react/runtime/src/snapshot/renderToOpcodes/opcodes.ts b/packages/react/runtime/src/snapshot/renderToOpcodes/opcodes.ts index 2428922b49..3ae2425950 100644 --- a/packages/react/runtime/src/snapshot/renderToOpcodes/opcodes.ts +++ b/packages/react/runtime/src/snapshot/renderToOpcodes/opcodes.ts @@ -3,7 +3,7 @@ // LICENSE file in the root directory of this source tree. import { hydrate } from './hydrate.js'; import { componentAtIndexFactory, enqueueComponentFactory, gRecycleMap, gSignMap } from '../list/list.js'; -import { CHILDREN } from './constants.js'; +import { CHILDREN } from '../../shared/render-constants.js'; import { SnapshotInstance } from '../snapshot/snapshot.js'; const OpcodeBegin = 0; diff --git a/packages/react/runtime/src/snapshot/snapshot/backgroundSnapshot.ts b/packages/react/runtime/src/snapshot/snapshot/backgroundSnapshot.ts index cef524af06..55991a6331 100644 --- a/packages/react/runtime/src/snapshot/snapshot/backgroundSnapshot.ts +++ b/packages/react/runtime/src/snapshot/snapshot/backgroundSnapshot.ts @@ -20,8 +20,8 @@ import { hydrationMap } from './snapshotInstanceHydrationMap.js'; import { transformSpread } from './spread.js'; import type { SerializedSnapshotInstance } from './types.js'; import { traverseSnapshotInstance } from './utils.js'; +import { profileEnd, profileStart } from '../../shared/profile.js'; import { isDirectOrDeepEqual } from '../../utils.js'; -import { profileEnd, profileStart } from '../debug/profile.js'; import { clearSnapshotVNodeSource, getSnapshotVNodeSource, moveSnapshotVNodeSource } from '../debug/vnodeSource.js'; import { prepareGestureForCommit } from '../gesture/processGestureBagkround.js'; import type { GestureKind } from '../gesture/types.js'; diff --git a/packages/react/runtime/src/snapshot/worklet/ref/workletRef.ts b/packages/react/runtime/src/snapshot/worklet/ref/workletRef.ts index 427f45b051..5ab4b7c82f 100644 --- a/packages/react/runtime/src/snapshot/worklet/ref/workletRef.ts +++ b/packages/react/runtime/src/snapshot/worklet/ref/workletRef.ts @@ -7,7 +7,7 @@ import type { WorkletRefImpl } from '@lynx-js/react/worklet-runtime/bindings'; import { WorkletEvents } from '@lynx-js/react/worklet-runtime/bindings'; import { addWorkletRefInitValue } from './workletRefPool.js'; -import { useMemo } from '../../hooks/react.js'; +import { useMemo } from '../../../core/hooks/react.js'; // Split into two variables for testing purposes let lastIdBG = 0; diff --git a/packages/react/runtime/src/utils.ts b/packages/react/runtime/src/utils.ts index c5c4d562cd..8815acb55c 100644 --- a/packages/react/runtime/src/utils.ts +++ b/packages/react/runtime/src/utils.ts @@ -4,7 +4,7 @@ import type { ComponentClass } from 'preact'; -import { getCurrentVNode, getOwnerStack } from './snapshot/debug/component-stack.js'; +import { getCurrentVNode, getOwnerStack } from './shared/component-stack.js'; /* v8 ignore start */ export const noop: (...args: unknown[]) => unknown = () => {}; diff --git a/packages/react/runtime/vitest.config.ts b/packages/react/runtime/vitest.config.ts index 69747ac0e3..c38141f08a 100644 --- a/packages/react/runtime/vitest.config.ts +++ b/packages/react/runtime/vitest.config.ts @@ -6,6 +6,7 @@ import { defineConfig } from 'vitest/config'; const require = createRequire(import.meta.url); const runtimePkg = require.resolve('./src/internal.ts'); +const internalPreactRoot = path.dirname(require.resolve('preact/package.json')); function transformReactLynxPlugin(): Plugin { return { @@ -60,20 +61,42 @@ export default defineConfig({ transformReactLynxPlugin(), ], resolve: { - alias: { - '@lynx-js/react/compat': path.resolve(__dirname, './compat/index.js'), - '@lynx-js/react/worklet-runtime/bindings': path.resolve(__dirname, './src/worklet-runtime/bindings/index.ts'), - '@lynx-js/react/runtime-components': path.resolve(__dirname, '../components/src/index.ts'), - '@lynx-js/react/internal': path.resolve(__dirname, './src/internal.ts'), - '@lynx-js/react/jsx-dev-runtime': path.resolve(__dirname, './jsx-dev-runtime/index.js'), - '@lynx-js/react/jsx-runtime': path.resolve(__dirname, './jsx-runtime/index.js'), - '@lynx-js/react/lepus': path.resolve(__dirname, './lepus/index.js'), - '@lynx-js/react/legacy-react-runtime': path.resolve(__dirname, './src/snapshot/legacy-react-runtime/index.ts'), - '@lynx-js/react': path.resolve(__dirname, './src/index.ts'), - }, + dedupe: ['preact'], + alias: [ + { find: /^preact$/, replacement: path.join(internalPreactRoot, 'dist/preact.mjs') }, + { find: /^preact\/compat$/, replacement: path.join(internalPreactRoot, 'compat/dist/compat.mjs') }, + { find: /^preact\/hooks$/, replacement: path.join(internalPreactRoot, 'hooks/dist/hooks.mjs') }, + { + find: /^preact\/jsx-dev-runtime$/, + replacement: path.join(internalPreactRoot, 'jsx-runtime/dist/jsxRuntime.mjs'), + }, + { find: /^preact\/jsx-runtime$/, replacement: path.join(internalPreactRoot, 'jsx-runtime/dist/jsxRuntime.mjs') }, + { find: '@lynx-js/react/compat', replacement: path.resolve(__dirname, './compat/index.js') }, + { + find: '@lynx-js/react/worklet-runtime/bindings', + replacement: path.resolve(__dirname, './src/worklet-runtime/bindings/index.ts'), + }, + { find: '@lynx-js/react/runtime-components', replacement: path.resolve(__dirname, '../components/src/index.ts') }, + { find: '@lynx-js/react/internal', replacement: path.resolve(__dirname, './src/internal.ts') }, + { find: '@lynx-js/react/jsx-dev-runtime', replacement: path.resolve(__dirname, './jsx-dev-runtime/index.js') }, + { find: '@lynx-js/react/jsx-runtime', replacement: path.resolve(__dirname, './jsx-runtime/index.js') }, + { find: '@lynx-js/react/lepus', replacement: path.resolve(__dirname, './lepus/index.js') }, + { + find: '@lynx-js/react/legacy-react-runtime', + replacement: path.resolve(__dirname, './src/snapshot/legacy-react-runtime/index.ts'), + }, + { find: '@lynx-js/react', replacement: path.resolve(__dirname, './src/index.ts') }, + ], }, test: { name: 'react/runtime', + server: { + deps: { + inline: [ + /@lynx-js\/internal-preact/, + ], + }, + }, coverage: { exclude: [ 'debug', @@ -85,7 +108,10 @@ export default defineConfig({ '__test__/snapshot/utils/**', 'lib/**', 'worklet-runtime/**', + 'src/shared/component-stack.ts', + 'src/shared/profile.ts', 'src/index.ts', + 'src/lynx-api.ts', 'src/lynx.ts', 'src/root.ts', 'src/worklet-runtime/api/lepusQuerySelector.ts', @@ -95,8 +121,8 @@ export default defineConfig({ 'src/worklet-runtime/index.ts', 'src/worklet-runtime/listeners.ts', 'src/worklet-runtime/types/**', - 'src/snapshot/debug/component-stack.ts', 'src/snapshot/debug/debug.ts', + 'src/snapshot/debug/profileHooks.ts', 'src/snapshot/debug/utils.ts', 'src/snapshot/lynx/calledByNative.ts', 'src/snapshot/lynx/component.ts', @@ -104,6 +130,8 @@ export default defineConfig({ 'src/snapshot/lynx/env.ts', 'src/snapshot/lynx/tt.ts', 'src/snapshot/compat/componentIs.ts', + 'src/snapshot/snapshot/types.ts', + 'src/snapshot/worklet/hmr.ts', '__test__/snapshot/page.test.jsx', '**/*.d.ts', diff --git a/packages/react/types/react.docs.d.ts b/packages/react/types/react.docs.d.ts index cae483da0c..a6a02b5a33 100644 --- a/packages/react/types/react.docs.d.ts +++ b/packages/react/types/react.docs.d.ts @@ -48,7 +48,7 @@ export { useSyncExternalStore, } from 'react'; -export { useEffect, useLayoutEffect, useErrorBoundary } from '../runtime/lib/snapshot/hooks/react.js'; +export { useEffect, useLayoutEffect, useErrorBoundary } from '../runtime/lib/core/hooks/react.js'; /** * Built-in React APIs diff --git a/packages/rspeedy/plugin-react-alias/test/index.test.ts b/packages/rspeedy/plugin-react-alias/test/index.test.ts index d0dd151d45..83f7316232 100644 --- a/packages/rspeedy/plugin-react-alias/test/index.test.ts +++ b/packages/rspeedy/plugin-react-alias/test/index.test.ts @@ -212,7 +212,7 @@ describe('React - alias', () => { expect(mainThreadRule.resolve.alias).toHaveProperty( 'preact/hooks', expect.stringContaining( - '/packages/react/runtime/lib/snapshot/hooks/mainThread.js'.replaceAll( + '/packages/react/runtime/lib/core/hooks/mainThread.js'.replaceAll( '/', path.sep, ), @@ -221,7 +221,7 @@ describe('React - alias', () => { expect(mainThreadRule.resolve.alias).toHaveProperty( '@lynx-js/react/hooks', expect.stringContaining( - '/packages/react/runtime/lib/snapshot/hooks/mainThread.js'.replaceAll( + '/packages/react/runtime/lib/core/hooks/mainThread.js'.replaceAll( '/', path.sep, ), @@ -230,7 +230,7 @@ describe('React - alias', () => { expect(mainThreadRule.resolve.alias).toHaveProperty( '@lynx-js/react/lepus/hooks', expect.stringContaining( - '/packages/react/runtime/lib/snapshot/hooks/mainThread.js'.replaceAll( + '/packages/react/runtime/lib/core/hooks/mainThread.js'.replaceAll( '/', path.sep, ), @@ -272,7 +272,7 @@ describe('React - alias', () => { expect(backgroundRule.resolve.alias).toHaveProperty( '@lynx-js/react/hooks', expect.stringContaining( - '/packages/react/runtime/lib/snapshot/hooks/react.js'.replaceAll( + '/packages/react/runtime/lib/core/hooks/react.js'.replaceAll( '/', path.sep, ),