From 681a43374e47ce4c7172117c3ecb88c1e258bff0 Mon Sep 17 00:00:00 2001 From: HuJean <7037477+HuJean@users.noreply.github.com> Date: Wed, 14 Jan 2026 20:40:49 +0800 Subject: [PATCH] fix: add safety checks for all compilation macros --- .changeset/profile-safety-fix.md | 9 ++++ .../react/components/src/DeferredListItem.tsx | 6 ++- .../react/runtime/src/alog/elementPAPICall.ts | 4 +- packages/react/runtime/src/alog/render.ts | 4 +- .../react/runtime/src/backgroundSnapshot.ts | 6 +-- packages/react/runtime/src/debug/profile.ts | 8 +-- packages/react/runtime/src/hydrate.ts | 4 +- .../react/runtime/src/lifecycle/destroy.ts | 4 +- .../runtime/src/lifecycle/event/jsReady.ts | 6 +-- .../runtime/src/lifecycle/patch/commit.ts | 6 +-- .../react/runtime/src/lifecycle/reload.ts | 8 +-- .../react/runtime/src/lifecycle/render.ts | 8 +-- packages/react/runtime/src/listUpdateInfo.ts | 4 +- packages/react/runtime/src/lynx-api.ts | 6 +-- packages/react/runtime/src/lynx.ts | 8 +-- packages/react/runtime/src/lynx/env.ts | 4 +- packages/react/runtime/src/lynx/tt.ts | 8 +-- packages/react/runtime/src/root.ts | 4 +- packages/react/runtime/src/worklet/destroy.ts | 2 +- .../rspeedy/plugin-react/test/config.test.ts | 51 +++++++++++++++++++ .../test/fixtures/defineDCE/macros.js | 9 ++++ 21 files changed, 120 insertions(+), 49 deletions(-) create mode 100644 .changeset/profile-safety-fix.md create mode 100644 packages/rspeedy/plugin-react/test/fixtures/defineDCE/macros.js diff --git a/.changeset/profile-safety-fix.md b/.changeset/profile-safety-fix.md new file mode 100644 index 0000000000..b5d6da8ab8 --- /dev/null +++ b/.changeset/profile-safety-fix.md @@ -0,0 +1,9 @@ +--- +'@lynx-js/react': patch +--- + +Add safety checks for compilation macros to prevent runtime errors when they are undefined. + +Replaces direct usage of `__PROFILE__`, `__MAIN_THREAD__`, `__BACKGROUND__` with `typeof` checks. + +This improves robustness by checking variable existence before access, preventing runtime errors in environments where compilation macros are not defined. diff --git a/packages/react/components/src/DeferredListItem.tsx b/packages/react/components/src/DeferredListItem.tsx index aeb54af8c9..d61dfdafca 100644 --- a/packages/react/components/src/DeferredListItem.tsx +++ b/packages/react/components/src/DeferredListItem.tsx @@ -15,7 +15,9 @@ export interface DeferredListItemProps { } export const DeferredListItem: FC = ({ defer, renderListItem, renderChildren }) => { - const __cloneElement = __MAIN_THREAD__ ? _cloneElementMainThread : _cloneElement; + const __cloneElement = typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__ + ? _cloneElementMainThread + : _cloneElement; const initialDeferRef = useRef(defer); const prevDeferRef = useRef(defer); @@ -42,7 +44,7 @@ export const DeferredListItem: FC = ({ defer, renderListI }; }, []); - if (__BACKGROUND__) { + if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) { if (prevDeferRef.current && !defer) { setIsReady(true); } diff --git a/packages/react/runtime/src/alog/elementPAPICall.ts b/packages/react/runtime/src/alog/elementPAPICall.ts index af3a96e3a1..892919b554 100644 --- a/packages/react/runtime/src/alog/elementPAPICall.ts +++ b/packages/react/runtime/src/alog/elementPAPICall.ts @@ -66,7 +66,7 @@ export function initElementPAPICallAlog(globalWithIndex: Record const oldFiberElementPAPI = globalWithIndex[fiberElementPAPIName]; if (typeof oldFiberElementPAPI === 'function') { globalWithIndex[fiberElementPAPIName] = (...args: unknown[]): unknown => { - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart(`FiberElementPAPI: ${fiberElementPAPIName}`, { args: { args: JSON.stringify(args), @@ -74,7 +74,7 @@ export function initElementPAPICallAlog(globalWithIndex: Record }); } const result = (oldFiberElementPAPI as (...args: unknown[]) => unknown)(...args); - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } diff --git a/packages/react/runtime/src/alog/render.ts b/packages/react/runtime/src/alog/render.ts index 08db446eee..3d14955c9a 100644 --- a/packages/react/runtime/src/alog/render.ts +++ b/packages/react/runtime/src/alog/render.ts @@ -16,11 +16,11 @@ export function initRenderAlog(): void { const threadName = __MAIN_THREAD__ ? 'MainThread' : 'BackgroundThread'; const displayName = getDisplayName(vnode.type as ComponentClass); // log the component render into Alog - if (__MAIN_THREAD__) { + if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) { console.alog?.( `[${threadName} Component Render] name: ${displayName}`, ); - } else if (__BACKGROUND__) { + } else if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) { const dom = vnode[DOM]; console.alog?.( `[${threadName} Component Render] name: ${displayName}, uniqID: ${dom?.type}, __id: ${dom?.__id}`, diff --git a/packages/react/runtime/src/backgroundSnapshot.ts b/packages/react/runtime/src/backgroundSnapshot.ts index a09076244e..98866e1f7d 100644 --- a/packages/react/runtime/src/backgroundSnapshot.ts +++ b/packages/react/runtime/src/backgroundSnapshot.ts @@ -238,7 +238,7 @@ export class BackgroundSnapshotInstance { } setAttribute(key: string | number, value: unknown): void { - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('ReactLynx::BSI::setAttribute'); } if (key === 'values') { @@ -286,7 +286,7 @@ export class BackgroundSnapshotInstance { }); } this.__values = value as unknown[]; - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } return; @@ -305,7 +305,7 @@ export class BackgroundSnapshotInstance { key, value, ); - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } } diff --git a/packages/react/runtime/src/debug/profile.ts b/packages/react/runtime/src/debug/profile.ts index 16d85cad83..e079a45c0f 100644 --- a/packages/react/runtime/src/debug/profile.ts +++ b/packages/react/runtime/src/debug/profile.ts @@ -38,7 +38,7 @@ export function initProfileHook(): void { const sFlowID = Symbol('FLOW_ID'); type PatchedComponent = Component & { [sFlowID]?: number }; - if (__BACKGROUND__) { + if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) { function buildSetStateProfileMarkArgs( currentState: Record, nextState: Record, @@ -84,7 +84,7 @@ export function initProfileHook(): void { if (typeof vnode.type === 'function') { const profileOptions: TraceOption = {}; - if (__BACKGROUND__) { + if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) { const c: PatchedComponent = oldVNode[COMPONENT]!; if (c) { const flowId = c[sFlowID]; @@ -112,7 +112,7 @@ export function initProfileHook(): void { old?.(vnode); }); - if (__BACKGROUND__) { + if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) { hook(options, COMMIT, (old, vnode, commitQueue) => { profileStart('ReactLynx::commit', { ...globalPatchOptions.flowIds @@ -144,7 +144,7 @@ export function initProfileHook(): void { old?.(vnode); }); - if (__BACKGROUND__) { + if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) { const sPatchLength = Symbol('PATCH_LENGTH'); type PatchedVNode = VNode & { [sPatchLength]?: number }; diff --git a/packages/react/runtime/src/hydrate.ts b/packages/react/runtime/src/hydrate.ts index 4a12e54bb7..fed966a180 100644 --- a/packages/react/runtime/src/hydrate.ts +++ b/packages/react/runtime/src/hydrate.ts @@ -380,7 +380,7 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio updateAction, }; - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('ReactLynx::listHydrate::updateListInfo', { args: { 'list id': String(listID), @@ -403,7 +403,7 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio // avoid the newly created list's (behind snapshot instance `after`) "update-list-info" being recorded. __pendingListUpdates.clear(after.__id); - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } } diff --git a/packages/react/runtime/src/lifecycle/destroy.ts b/packages/react/runtime/src/lifecycle/destroy.ts index 39c24055a3..c2ffa75027 100644 --- a/packages/react/runtime/src/lifecycle/destroy.ts +++ b/packages/react/runtime/src/lifecycle/destroy.ts @@ -10,7 +10,7 @@ import { globalCommitTaskMap } from './patch/commit.js'; import { profileEnd, profileStart } from '../debug/utils.js'; function destroyBackground(): void { - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('ReactLynx::destroyBackground'); } @@ -27,7 +27,7 @@ function destroyBackground(): void { if (delayedEvents) { delayedEvents.length = 0; } - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } } diff --git a/packages/react/runtime/src/lifecycle/event/jsReady.ts b/packages/react/runtime/src/lifecycle/event/jsReady.ts index 526451b866..51ce9b5265 100644 --- a/packages/react/runtime/src/lifecycle/event/jsReady.ts +++ b/packages/react/runtime/src/lifecycle/event/jsReady.ts @@ -11,12 +11,12 @@ let jsReadyEventIdSwap: Record; function jsReady(): void { isJSReady = true; - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('ReactLynx::transferRoot'); profileStart('ReactLynx::serializeRoot'); } const root = JSON.stringify(__root); - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } __OnLifecycleEvent([ @@ -26,7 +26,7 @@ function jsReady(): void { jsReadyEventIdSwap, }, ]); - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } jsReadyEventIdSwap = {}; diff --git a/packages/react/runtime/src/lifecycle/patch/commit.ts b/packages/react/runtime/src/lifecycle/patch/commit.ts index b0bf145f63..c1cb8f2ef1 100644 --- a/packages/react/runtime/src/lifecycle/patch/commit.ts +++ b/packages/react/runtime/src/lifecycle/patch/commit.ts @@ -106,7 +106,7 @@ function replaceCommitHook(): void { commitQueue, ) => { // Skip commit phase for MT runtime - if (__MAIN_THREAD__) { + if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) { // for testing only commitQueue.length = 0; return; @@ -193,7 +193,7 @@ function commitPatchUpdate(patchList: PatchList, patchOptions: GlobalPatchOption // ); // console.debug('commitPatchUpdate:', prettyFormatSnapshotPatch(patchList.patchList[0]?.snapshotPatch)); - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('ReactLynx::commitChanges'); } markTiming('packChangesStart'); @@ -212,7 +212,7 @@ function commitPatchUpdate(patchList: PatchList, patchOptions: GlobalPatchOption obj.patchOptions.pipelineOptions = globalPipelineOptions; setPipeline(undefined); } - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } diff --git a/packages/react/runtime/src/lifecycle/reload.ts b/packages/react/runtime/src/lifecycle/reload.ts index 78d56ba446..7d5e52b24c 100644 --- a/packages/react/runtime/src/lifecycle/reload.ts +++ b/packages/react/runtime/src/lifecycle/reload.ts @@ -25,7 +25,7 @@ import { renderMainThread } from './render.js'; import { profileEnd, profileStart } from '../debug/utils.js'; function reloadMainThread(data: unknown, options: UpdatePageOption): void { - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('ReactLynx::reloadMainThread'); } @@ -62,14 +62,14 @@ function reloadMainThread(data: unknown, options: UpdatePageOption): void { __FlushElementTree(__page, options); - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } return; } function reloadBackground(updateData: Record): void { - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('ReactLynx::reloadBackground'); } @@ -86,7 +86,7 @@ function reloadBackground(updateData: Record): void { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument render(__root.__jsx, __root as any); - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } } diff --git a/packages/react/runtime/src/lifecycle/render.ts b/packages/react/runtime/src/lifecycle/render.ts index e3b50106c6..ff95c8b598 100644 --- a/packages/react/runtime/src/lifecycle/render.ts +++ b/packages/react/runtime/src/lifecycle/render.ts @@ -17,7 +17,7 @@ import { SnapshotInstance } from '../snapshot.js'; function renderMainThread(): void { let opcodes; try { - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('ReactLynx::renderMainThread'); } opcodes = renderToString(__root.__jsx, undefined); @@ -25,7 +25,7 @@ function renderMainThread(): void { lynx.reportError(e as Error); opcodes = []; } finally { - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } } @@ -40,7 +40,7 @@ function renderMainThread(): void { }); } - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('ReactLynx::renderOpcodes'); } // eslint-disable-next-line @typescript-eslint/no-unsafe-argument @@ -48,7 +48,7 @@ function renderMainThread(): void { if (__ENABLE_SSR__) { __root.__opcodes = opcodes; } - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } } diff --git a/packages/react/runtime/src/listUpdateInfo.ts b/packages/react/runtime/src/listUpdateInfo.ts index a9623cdb7a..aee6b5e726 100644 --- a/packages/react/runtime/src/listUpdateInfo.ts +++ b/packages/react/runtime/src/listUpdateInfo.ts @@ -85,7 +85,7 @@ export class ListUpdateInfoRecording implements ListUpdateInfo { // }); const updateListInfo = this.__toAttribute(); - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { const listID = __GetElementUniqueID(listElement); profileStart(`ReactLynx::listFlush::updateListInfo`, { args: { @@ -104,7 +104,7 @@ export class ListUpdateInfoRecording implements ListUpdateInfo { componentAtIndexes, ); - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } return this.list.__id; diff --git a/packages/react/runtime/src/lynx-api.ts b/packages/react/runtime/src/lynx-api.ts index 3e419e0158..28b465de03 100644 --- a/packages/react/runtime/src/lynx-api.ts +++ b/packages/react/runtime/src/lynx-api.ts @@ -84,16 +84,16 @@ export interface Root { export const root: Root = { render: (jsx: ReactNode): void => { /* v8 ignore next 2 */ - if (__MAIN_THREAD__) { + if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) { __root.__jsx = jsx; } else { __root.__jsx = jsx; - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('ReactLynx::renderBackground'); } // eslint-disable-next-line @typescript-eslint/no-unsafe-argument render(jsx, __root as any); - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } if (__FIRST_SCREEN_SYNC_TIMING__ === 'immediately') { diff --git a/packages/react/runtime/src/lynx.ts b/packages/react/runtime/src/lynx.ts index 9ae7a65905..50a31a53a2 100644 --- a/packages/react/runtime/src/lynx.ts +++ b/packages/react/runtime/src/lynx.ts @@ -23,14 +23,14 @@ import { injectUpdateMTRefInitValue } from './worklet/ref/updateInitValue.js'; export { runWithForce } from './lynx/runWithForce.js'; // @ts-expect-error Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature -if (__MAIN_THREAD__ && typeof globalThis.processEvalResult === 'undefined') { +if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__ && typeof globalThis.processEvalResult === 'undefined') { // @ts-expect-error Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature globalThis.processEvalResult = (result: ((schema: string) => T) | undefined, schema: string) => { return result?.(schema); }; } -if (__MAIN_THREAD__) { +if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) { injectCalledByNative(); injectUpdateMainThread(); injectUpdateMTRefInitValue(); @@ -44,7 +44,7 @@ if (__DEV__) { } // We are profiling both main-thread and background. -if (__MAIN_THREAD__ && __PROFILE__) { +if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__ && typeof __PROFILE__ !== 'undefined' && __PROFILE__) { initProfileHook(); } @@ -53,7 +53,7 @@ if (typeof __ALOG__ !== 'undefined' && __ALOG__) { initAlog(); } -if (__BACKGROUND__) { +if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) { // Trick Preact and TypeScript to accept our custom document adapter. options.document = document as unknown as Document; options.requestAnimationFrame = lynxQueueMicrotask; diff --git a/packages/react/runtime/src/lynx/env.ts b/packages/react/runtime/src/lynx/env.ts index 616942b9fb..2dd3fdba1a 100644 --- a/packages/react/runtime/src/lynx/env.ts +++ b/packages/react/runtime/src/lynx/env.ts @@ -51,7 +51,7 @@ export function setupLynxEnv(): void { ) { let hasDefaultDataProcessorExecuted = false; globalThis.processData = (data, processorName) => { - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('processData'); } @@ -70,7 +70,7 @@ export function setupLynxEnv(): void { r = {}; } - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } diff --git a/packages/react/runtime/src/lynx/tt.ts b/packages/react/runtime/src/lynx/tt.ts index e6febee621..04a89fabb1 100644 --- a/packages/react/runtime/src/lynx/tt.ts +++ b/packages/react/runtime/src/lynx/tt.ts @@ -58,7 +58,7 @@ function onLifecycleEvent([type, data]: [LifecycleConstant, unknown]) { return; } - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart(`OnLifecycleEvent::${type}`); } @@ -68,7 +68,7 @@ function onLifecycleEvent([type, data]: [LifecycleConstant, unknown]) { lynx.reportError(e as Error); } - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } } @@ -83,7 +83,7 @@ function onLifecycleEventImpl(type: LifecycleConstant, data: unknown): void { processErr = e; } const { root: lepusSide, jsReadyEventIdSwap } = data as FirstScreenData; - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileStart('ReactLynx::hydrate'); } beginPipeline(true, PipelineOrigins.reactLynxHydrate, PerformanceTimingFlags.reactLynxHydrate); @@ -122,7 +122,7 @@ function onLifecycleEventImpl(type: LifecycleConstant, data: unknown): void { + printSnapshotInstanceToString(__root as BackgroundSnapshotInstance), ); } - if (__PROFILE__) { + if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { profileEnd(); } markTiming('diffVdomEnd'); diff --git a/packages/react/runtime/src/root.ts b/packages/react/runtime/src/root.ts index 6310e89ce7..a3f0f6b4ad 100644 --- a/packages/react/runtime/src/root.ts +++ b/packages/react/runtime/src/root.ts @@ -29,9 +29,9 @@ function setRoot(root: typeof __root): void { } } -if (__MAIN_THREAD__) { +if (typeof __MAIN_THREAD__ !== 'undefined' && __MAIN_THREAD__) { setRoot(new SnapshotInstance('root')); -} else if (__BACKGROUND__) { +} else if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) { setRoot(new BackgroundSnapshotInstance('root')); } diff --git a/packages/react/runtime/src/worklet/destroy.ts b/packages/react/runtime/src/worklet/destroy.ts index dd9caca329..9f23fa5c6c 100644 --- a/packages/react/runtime/src/worklet/destroy.ts +++ b/packages/react/runtime/src/worklet/destroy.ts @@ -7,7 +7,7 @@ import { takeWorkletRefInitValuePatch } from './ref/workletRefPool.js'; export const destroyTasks: (() => void)[] = []; export function destroyWorklet(): void { - if (__BACKGROUND__) { + if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) { takeWorkletRefInitValuePatch(); } diff --git a/packages/rspeedy/plugin-react/test/config.test.ts b/packages/rspeedy/plugin-react/test/config.test.ts index e4db926828..d729186fd9 100644 --- a/packages/rspeedy/plugin-react/test/config.test.ts +++ b/packages/rspeedy/plugin-react/test/config.test.ts @@ -1,6 +1,7 @@ // Copyright 2024 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 { existsSync, readFileSync } from 'node:fs' import { createRequire } from 'node:module' import path from 'node:path' @@ -1925,6 +1926,56 @@ describe('Config', () => { expect.fail('build should succeed') } }) + + test('defineDCE should correctly eliminate dead code for compilation macros', async () => { + const { pluginReactLynx } = await import('../src/pluginReactLynx.js') + + // Production build with typical macro definitions + vi.stubEnv('NODE_ENV', 'production') + + const rsbuild = await createRspeedy({ + rspeedyConfig: { + source: { + entry: { + main: new URL('./fixtures/defineDCE/macros.js', import.meta.url) + .pathname, + }, + }, + environments: { + lynx: {}, + }, + plugins: [ + pluginReactLynx({ + defineDCE: { + define: { + __PROFILE__: 'false', + }, + }, + }), + ], + }, + }) + + try { + await rsbuild.build() + } catch (_error) { + expect.fail('build should succeed') + } + + const distPath = path.join( + rsbuild.context.distPath, + '.rspeedy/main', + 'main-thread.js', + ) + + if (!existsSync(distPath)) { + expect.fail(`Build output should exist at ${distPath}`) + } + + const builtCode = readFileSync(distPath, 'utf8') + expect(builtCode).not.toContain('profileStart(\'test\')') + expect(builtCode).toContain('Config is: profile-off-mode') + }) }) test('default LynxTemplatePlugin options', async () => { diff --git a/packages/rspeedy/plugin-react/test/fixtures/defineDCE/macros.js b/packages/rspeedy/plugin-react/test/fixtures/defineDCE/macros.js new file mode 100644 index 0000000000..e13e26d114 --- /dev/null +++ b/packages/rspeedy/plugin-react/test/fixtures/defineDCE/macros.js @@ -0,0 +1,9 @@ +if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) { + profileStart('test') +} + +const config = (typeof __PROFILE__ !== 'undefined' && __PROFILE__) + ? 'profile-mode' + : 'profile-off-mode' + +console.info(`Config is: ${config}`)