Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changeset/plain-lions-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---

---
12 changes: 6 additions & 6 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Comment thread
Yradex marked this conversation as resolved.
"./lepus": {
"types": "./runtime/lepus/index.d.ts",
Expand Down Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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();
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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} */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -41,7 +42,6 @@ const containedTestDirs = [
'css',
'debug',
'gesture',
'hooks',
'lifecycle',
'lynx',
'utils',
Expand Down Expand Up @@ -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));

Expand All @@ -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})(?:/|['"])`,
Expand All @@ -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',
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type LynxLike = {
performance?: PerformanceLike;
};

describe('debug/profile module', () => {
describe('shared/profile module', () => {
let originalLynx: LynxLike;
let originalProfileFlag: unknown;

Expand All @@ -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);
});
Expand All @@ -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();
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,33 @@
// 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';
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;
}
Expand All @@ -37,7 +50,9 @@ describe('react hooks profile', () => {
});

afterEach(() => {
render(null, scratch);
currentRender?.(null, scratch);
currentRender = undefined;
currentCreateElement = undefined;
elementTree.clear();
vi.restoreAllMocks();
});
Expand All @@ -52,16 +67,16 @@ describe('react hooks profile', () => {
useLayoutEffect(() => {
return () => {};
}, []);
return <view />;
return currentCreateElement('div');
}

lynx.performance.profileStart.mockClear();
lynx.performance.profileEnd.mockClear();
lynx.performance.profileFlowId.mockClear();

render(<App />, scratch);
currentRender(currentCreateElement(App), scratch);
await Promise.resolve();
render(null, scratch);
currentRender(null, scratch);
await Promise.resolve();

const starts = lynx.performance.profileStart.mock.calls;
Expand Down Expand Up @@ -103,10 +118,10 @@ describe('react hooks profile', () => {
function App() {
const [value, _setValue] = useState(0);
setValue = _setValue;
return <view value={value} />;
return currentCreateElement('div', { value });
}

render(<App />, scratch);
currentRender(currentCreateElement(App), scratch);

const OriginalError = globalThis.Error;
class ErrorWithoutStack extends OriginalError {
Expand Down Expand Up @@ -139,7 +154,7 @@ describe('react hooks profile', () => {

function App() {
useEffect(() => undefined, []);
return <view />;
return currentCreateElement('div');
}

const OriginalError = globalThis.Error;
Expand All @@ -155,7 +170,7 @@ describe('react hooks profile', () => {

try {
vi.stubGlobal('Error', ErrorWithoutStack);
render(<App />, scratch);
currentRender(currentCreateElement(App), scratch);
await Promise.resolve();
} finally {
vi.stubGlobal('Error', OriginalError);
Expand All @@ -179,10 +194,10 @@ describe('react hooks profile', () => {
function App() {
const [value, _setValue] = useState();
setValue = _setValue;
return <view value={value} />;
return currentCreateElement('div', { value });
}

render(<App />, scratch);
currentRender(currentCreateElement(App), scratch);

lynx.performance.profileStart.mockClear();
lynx.performance.profileEnd.mockClear();
Expand Down Expand Up @@ -210,10 +225,10 @@ describe('react hooks profile', () => {
function App() {
const [value, _setValue] = useState(0);
setValue = _setValue;
return <view value={value} />;
return currentCreateElement('div', { value });
}

render(<App />, scratch);
currentRender(currentCreateElement(App), scratch);

lynx.performance.profileStart.mockClear();
lynx.performance.profileEnd.mockClear();
Expand Down Expand Up @@ -245,7 +260,7 @@ describe('react hooks profile', () => {
setValue = _setValue;
useEffect(() => undefined, [value]);
useLayoutEffect(() => undefined, [value]);
return <view value={value} />;
return currentCreateElement('div', { value });
}

lynx.performance.profileStart.mockClear();
Expand All @@ -256,7 +271,7 @@ describe('react hooks profile', () => {
expect(useEffect).toBe(preactHooks.useEffect);
expect(useLayoutEffect).toBe(preactHooks.useEffect);

render(<App />, scratch);
currentRender(currentCreateElement(App), scratch);
await Promise.resolve();
setValue(v => v + 1);
await Promise.resolve();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
2 changes: 1 addition & 1 deletion packages/react/runtime/__test__/snapshot/event.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Loading
Loading