# @lynx-js/react

## 0.129.0

### Minor Changes

- Add the experimental `experimental_reEvalJSOnReload` option. When it is enabled, `reloadTemplate` evaluates the main-thread and background entries again, so module-level state starts over while the native element tree is reused. It is disabled by default. ([#4026](https://github.com/lynx-family/lynx-stack/pull/4026))

  Re-evaluating the background entry requires `reloadCard` from the Lynx client. Without it, the background keeps the existing reload behavior.

### Patch Changes

- Drop stale cross-thread function calls and return values after `reloadTemplate`. This prevents delayed calls from looking up cleared Element Template function contexts or resolving a newer call with an old result. Calls queued by old main-thread ref cleanup retain the old reload version. ([#4214](https://github.com/lynx-family/lynx-stack/pull/4214))

- Keep synchronous lazy import chains from changing unrelated Promise callbacks to run synchronously when the Lynx Promise polyfill caches fulfilled primitive values. This prevents a lazy component's mount effect from re-entering when it updates a parent component. ([#4204](https://github.com/lynx-family/lynx-stack/pull/4204))

- Keep failed background-function handle registrations retryable and release consumed delayed callback queues so completed callbacks can be garbage collected. ([#4222](https://github.com/lynx-family/lynx-stack/pull/4222))

- Send Element Template main-thread ref initialization in a separate event, independently of UI patch serialization and reload filtering. Add alog messages for initialization sends and receives in both Snapshot and Element Template. ([#4213](https://github.com/lynx-family/lynx-stack/pull/4213))

- Preserve imports such as `runOnBackground` when injecting background-only worklet definitions into the main thread. Keep imported bindings isolated between definitions and resolve relative imports from their original module. ([#4221](https://github.com/lynx-family/lynx-stack/pull/4221))

## 0.128.0

### Minor Changes

- Deliver the main-thread runtime through named imports from its init entry, including background-only definitions that carry their registration dependencies into the main-thread graph. Runtime code participates in business defines and release processing. Every supported transform supplies semantic runtime requirements, including for definitions injected from background-only modules; watch rebuilds refresh their dependencies and metadata. ([#4066](https://github.com/lynx-family/lynx-stack/pull/4066))

  Upgrade the build plugins and `@lynx-js/react` together. This release requires `@lynx-js/react@^0.128.0`; its runtime and bundled transform use the same module-delivery protocol. The refresh plugin adds support for `@lynx-js/react-webpack-plugin@^0.13.0` while retaining its existing supported versions. Older compiler output is unsupported. The prebuilt worklet-runtime chunk, its package entries, and `loadWorkletRuntime` are removed. Combined lazy chunks share their paired main runtime, and standalone lazy bundles bootstrap themselves.

  The worklet init entry follows `worklet.runtimePkg`: remove a trailing `/internal`, if present, and append `/worklet-runtime/init`. Its `registerWorklet` export uses the existing host registration function when the runtime is already initialized. Default worklet options use `@lynx-js/react/internal` for helpers.

  Testing-library initializes module-delivered worklets on its emulated main thread in Vitest and Rstest.

### Patch Changes

- Add the `@lynx-js/react/worklet-runtime/init` entry and resolve it to the published, unbundled runtime module in normal and lazy builds. The entry uses the existing runtime initialization guard, so loading it again preserves the runtime and its registrations. ([#4065](https://github.com/lynx-family/lynx-stack/pull/4065))

  Existing compiler output continues to use the legacy runtime-loading path.

## 0.127.0

### Minor Changes

- Add typed `MainThreadObject` handles whose target factory is defined by a Main Thread Function, with identity-preserving capture and hydration, runtime-owned reference release, and exact-type handle downcasting for readonly creation-payload access. V1 intentionally exposes no user-land disposal API. Applications import the APIs from `@lynx-js/react`. ([#3788](https://github.com/lynx-family/lynx-stack/pull/3788))

### Patch Changes

- Exclude nested `node_modules` symlinks from published packages. ([#4117](https://github.com/lynx-family/lynx-stack/pull/4117))

- Preserve MainThreadObject identity in member and nested captures, and support Main Thread object methods with receiver-bound captures. ([#3789](https://github.com/lynx-family/lynx-stack/pull/3789))

- Forward MainThreadObject APIs directly from the host runtime in standalone lazy bundles without feature-specific mismatch assertions. ([#4064](https://github.com/lynx-family/lynx-stack/pull/4064))

- Support MainThreadObject APIs and captures when using Element Template. ([#3788](https://github.com/lynx-family/lynx-stack/pull/3788))

- Include operation type and commit ID in the ctx-not-found diagnostic message. ([#4111](https://github.com/lynx-family/lynx-stack/pull/4111))

## 0.126.2

### Patch Changes

- Reduce profiling overhead in the Snapshot and Element Template backends by directly forwarding fixed arguments in diff, render, commit, and setState callbacks. Existing profiling events and state diagnostics are preserved. This change only affects execution with profiling hooks installed. ([#3998](https://github.com/lynx-family/lynx-stack/pull/3998))

- Preserve first-screen MainThreadRef values and delayed `runOnBackground` calls when a nested main-thread function's original context is garbage-collected before hydration. Hydration now reads the context already owned by the bound function without retaining the original context. ([#3958](https://github.com/lynx-family/lynx-stack/pull/3958))

- Add `registerRuntimeVersion()` and `getRuntimeVersion()` to record the host's `@lynx-js/react` runtime version and report versions from standalone lazy bundles. The build stamps each bundle with `__RUNTIME_VERSION__`; bundles built by older plugins that do not stamp the version are unaffected. ([#4035](https://github.com/lynx-family/lynx-stack/pull/4035))

- Keep both layers of a lazy bundle that a `webpackChunkName` names. The name is the identity of a chunk group, so writing one collapsed the main-thread and the background compilation into a single chunk: the bundle shipped with an empty `lepusCode`, and its intermediate outputs landed outside of `.lynx/lazy-bundle/<name>/`. The transform now appends `-react__<layer>` to a user-written name and the plugin strips it again, the way it did for the names the transform used to inject, so a named lazy bundle is built exactly like an unnamed one. ([#4002](https://github.com/lynx-family/lynx-stack/pull/4002))

- Preserve component owners in development error stacks after scheduled state updates, and enable background component stacks for Element Template. ([#3919](https://github.com/lynx-family/lynx-stack/pull/3919))

- Run a GC pass after `reloadTemplate`, and after an update that arrives before ([#4022](https://github.com/lynx-family/lynx-stack/pull/4022))
  the first screen is synced, when the engine exposes `lepusng_gc`. Both replace
  the rendered tree, and under reference counting the replaced tree is not freed
  on its own.
- Fix SSR hydration of list snapshots with surrounding elements so list callbacks and recycling state are restored on the list element while preserving the snapshot root. ([#3983](https://github.com/lynx-family/lynx-stack/pull/3983))

- Type `RenderResult.unmount` from `@lynx-js/react/testing-library` as returning `void`, matching the runtime. ([#3960](https://github.com/lynx-family/lynx-stack/pull/3960))

## 0.126.1

### Patch Changes

- Type the context argument of `use` with React's `Context`, matching the rest of the public surface. `@lynx-js/react` re-exports `createContext` from `react`, so declaring `use` against Preact's `Context` made a context created through the package fail to type-check. ([#3837](https://github.com/lynx-family/lynx-stack/pull/3837))

- Keep ordinary callback ref cleanup separate for each node binding. Sharing one callback between multiple nodes no longer cleans up another node's binding during attachment, replacement, or removal. Bindings retain their cleanup across hydration and keyed moves in both Snapshot and Element Template. ([#3902](https://github.com/lynx-family/lynx-stack/pull/3902))

- `withLynxConfig()` now loads `rsbuild.config.*` in an Rsbuild project, not only `lynx.config.*` in an Rspeedy one, so Rstest runs in both. ([#3864](https://github.com/lynx-family/lynx-stack/pull/3864))

- Clean up direct callback refs when they are set to `null` or `undefined` after hydration in the Snapshot backend. Call the binding's returned cleanup, or pass `null` to the callback when no cleanup was returned, without repeating cleanup on a later unmount. ([#3911](https://github.com/lynx-family/lynx-stack/pull/3911))

- Fix the queries returned by `render` from `@lynx-js/react/testing-library` being typed as a union of every query's result when no `queries` option is passed, which made `fireEvent.tap(await findByText(...))` fail to type-check. ([#3864](https://github.com/lynx-family/lynx-stack/pull/3864))

- Fix `use()` from `@lynx-js/react/compat` throwing `cannot read property '__cC0' of undefined` on the main thread. The main-thread renderer never set `_globalContext` on the components it builds, and `use` reads its context provider from there. `useContext` was unaffected because it reads `context` instead. ([#3838](https://github.com/lynx-family/lynx-stack/pull/3838))

## 0.126.0

### Minor Changes

- Export `useInsertionEffect` from `@lynx-js/react/compat`, currently an alias of `useEffect`. ([#3784](https://github.com/lynx-family/lynx-stack/pull/3784))

- Export `use` from `@lynx-js/react/compat`. ([#3672](https://github.com/lynx-family/lynx-stack/pull/3672))

- Upgrade the bundled Preact fork to Preact 11 (`@lynx-js/internal-preact` ([#3450](https://github.com/lynx-family/lynx-stack/pull/3450))
  based on `11.0.0-rc.1`).

  **Breaking:** `useEffect` cleanups of unmounted components no longer run
  synchronously during unmount. They run in the after-paint flush instead,
  matching React. This applies to `useLayoutEffect` too, which ReactLynx
  exports as an alias of `useEffect`. Page destroy is unaffected — it drains
  them synchronously, so cleanups that release native resources still run
  before the runtime goes away. Code that assumed a cleanup had already run
  right after a re-render removed the component needs to await a flush;
  ReactLynx does not currently export a hook whose cleanup stays inside the
  unmount commit.

  Other runtime-visible changes:

  - Context consumers no longer double-render on provider updates
    (preactjs/preact#4724), so fewer `rLynxChange` flushes are emitted and
    patches merge into the first flush.
  - List reorders use Preact 11's longest-increasing-subsequence diff, which
    may pick an equivalent-but-different minimal set of moves.

### Patch Changes

- Reach lynx-core's app object through `lynx.getApp()` instead of the ([#3553](https://github.com/lynx-family/lynx-stack/pull/3553))
  `lynxCoreInject` global the AMD wrapper injects. It is the same instance, so
  behavior is unchanged, and resolving it through `lynx` also stays correct once
  several cards share a runtime chunk. `@lynx-js/testing-environment` now exposes
  `lynx.getApp()` alongside the object it already provided.
- Move runtime attribute-name configuration to the page-scoped `lynx` object and ([#3718](https://github.com/lynx-family/lynx-stack/pull/3718))
  inject it from the host compilation through a standalone webpack plugin. Lazy
  and external bundles reuse the host-injected configuration without applying
  the plugin themselves. The runtime-config webpack plugin is published through
  its own DSL-neutral package entry and accepts arbitrary runtime configuration
  keys without depending on ReactLynx. The merged top-level configuration is
  shallow-frozen to prevent accidental mutation after host initialization.
- Keep `ref` in props for function components on the main thread, matching the background thread. ([#3688](https://github.com/lynx-family/lynx-stack/pull/3688))

- Update `swc_core` to 77 in the transform. ([#3793](https://github.com/lynx-family/lynx-stack/pull/3793))

## 0.125.0

### Minor Changes

- Add the `<background-only>` element, which renders its `fallback` on the main thread first screen and its children on the background thread. ([#3551](https://github.com/lynx-family/lynx-stack/pull/3551))

### Patch Changes

- Tag main-thread vnodes with `$$typeof: Symbol.for('react.element')` so `isValidElement` recognizes them, matching the background thread. ([#3514](https://github.com/lynx-family/lynx-stack/pull/3514))

- Release worklet refs when list items are logically removed while preserving native element recycling. ([#3590](https://github.com/lynx-family/lynx-stack/pull/3590))

## 0.124.0

### Minor Changes

- Register the snapshot and worklet definitions collected from the background build on the main thread, so a definition the main-thread bundle dropped no longer fails with `Snapshot not found`. ([#3393](https://github.com/lynx-family/lynx-stack/pull/3393))

### Patch Changes

- Add `compat.transformLegacyEventAttributeNames` to disable legacy event attribute-name conversion independently from other compatibility transforms. ([#3475](https://github.com/lynx-family/lynx-stack/pull/3475))

- Fix `snapshotPatchApply failed: ctx not found` when a lazy bundle is loaded during first-screen direct render. ([#3452](https://github.com/lynx-family/lynx-stack/pull/3452))

## 0.123.3

### Patch Changes

- Type `createPortal` as returning `ReactNode` instead of Preact's `VNode<any> | null`, matching the rest of the public surface, and document its behavioral contract. ([#3348](https://github.com/lynx-family/lynx-stack/pull/3348))

## 0.123.2

### Patch Changes

- Resolve the `preact` peer dependency to the vendored `@lynx-js/internal-preact`, preventing duplicate preact copies in the dependency tree. ([#3276](https://github.com/lynx-family/lynx-stack/pull/3276))

- Tell the main thread when a background commit produces no element mutations. ([#3010](https://github.com/lynx-family/lynx-stack/pull/3010))

  When a background render commits without any snapshot patch (or ElementTemplate update op) and without any pending `runOnMainThread` task, `__FlushElementTree` is now called with `emptyPatch: true`. Hosts that understand the flag can end the pipeline early instead of walking the whole update path; older hosts simply ignore the unknown option, so this is safe on every engine version.

- Optimize no-flatten attribute detection when transforming spread attributes. ([#3238](https://github.com/lynx-family/lynx-stack/pull/3238))

- Add the experimental `experimental_transformBuiltinAttributeNames` option for transforming builtin element attribute names. `false` preserves attribute names. `true` transforms `onClick` to `bindtap`, `onCatchTap` to `catchtap`, other `onXXX` event names to `bindxxx`, and remaining camelCase names to dash-case. An object supports serializable custom rules through `mode`, `preserve`, and `rename`. Explicit JSX attributes are transformed during compilation, and spread attributes are transformed at runtime. ([#3274](https://github.com/lynx-family/lynx-stack/pull/3274))

## 0.123.1

### Patch Changes

- refactor type of createElement and cloneElement ([#2995](https://github.com/lynx-family/lynx-stack/pull/2995))

- Prevent stale snapshot teardown from destroying list callbacks and recycling state after rendered elements are transferred to a new snapshot instance. ([#3122](https://github.com/lynx-family/lynx-stack/pull/3122))

- Update `@types/react` from `^18` to `^18 || ^19.0.0` ([#3144](https://github.com/lynx-family/lynx-stack/pull/3144))

## 0.123.0

### Minor Changes

- Stop injecting `webpackChunkName` into dynamic imports so lazy bundle intermediate files stay inside the output directory. ([#2961](https://github.com/lynx-family/lynx-stack/pull/2961))

  The ReactLynx transform injected `webpackChunkName: "<request>-react__<layer>"`, so a dynamic import resolving above the compiler context (e.g. `import('../../Foo.js')`) leaked `../` into `[name]`/`[id]` and the intermediate js/css/hmr files escaped the output directory. Async chunks now keep rspack's own ids, `__webpack_require__.lynx_aci` maps them by chunk id, and each lazy bundle's intermediate JS and CSS are emitted under `.rspeedy/async/<bundle-name>/<layer>.js` and `<layer>.css` next to its other intermediate outputs (`tasm.json`, `debug-metadata.json`, CSS hot-update files). Explicit `webpackChunkName` comments written by users are still honored and keep the user-controlled `[name]` placement. Main-thread chunks no longer emit CSS hot-update files — CSS only exists on the background thread, and the main-thread HMR runtime receives updates from it.

  These packages release together and must be upgraded together: `@lynx-js/react-webpack-plugin` and `@lynx-js/css-extract-webpack-plugin` require `@lynx-js/template-webpack-plugin` `^0.13.0`, and `@lynx-js/react-rsbuild-plugin` requires `@lynx-js/react` `^0.123.0`.

- Add the `lynx.fetchBundle`-based lazy bundle loader. Control whether the first ([#2584](https://github.com/lynx-family/lynx-stack/pull/2584))
  screen blocks on the fetch with the `mode` import attribute:

  ```js
  import('./Foo.jsx', { with: { mode: 'sync' } }); // block the first screen
  import('./Foo.jsx', { with: { mode: 'async' } }); // default, non-blocking
  ```

  Enable it by setting `engineVersion: '3.9'` (or higher) in `pluginReactLynx`. The
  lazy bundle's main-thread section is bytecoded by default (skipped in dev or when
  `DEBUG` includes `rspeedy`).

- Add `firstScreenSyncTiming: 'manual'` and a new `markFirstScreenSyncReady()` API exported by `@lynx-js/react`. ([#2826](https://github.com/lynx-family/lynx-stack/pull/2826))

  In `'manual'` mode, the main thread holds the UI control after the first screen until the business calls `markFirstScreenSyncReady()`, so the handover timing to the background thread (for hydration) is fully controlled by the user. The API can be called from both threads (a background-thread call is forwarded to the main thread) and takes effect once the first-screen tree has finished rendering.

  ```js
  pluginReactLynx({
    firstScreenSyncTiming: 'manual',
  });
  ```

  ```js
  import { markFirstScreenSyncReady } from '@lynx-js/react';

  markFirstScreenSyncReady();
  ```

### Patch Changes

- Add `compat.legacySlot` to `pluginReactLynx`. When enabled, dynamic children are compiled to the pre-SlotV2 form (JSX `children` + `wrapper` elements + `__DynamicPartChildren`/`__DynamicPartSlot` symbols instead of `$0`/`$1` slot props + `SlotV2`), so the compiled output stays compatible with legacy runtimes without `SlotV2` support (`< 0.120.0`, which shipped the SlotV2 refactor in #1764) — e.g. a standalone lazy bundle consumed by a host App that ships an older runtime. ([#2947](https://github.com/lynx-family/lynx-stack/pull/2947))

  ```js
  import { defineConfig } from '@lynx-js/rspeedy';
  import { pluginReactLynx } from '@lynx-js/react-rsbuild-plugin';

  export default defineConfig({
    plugins: [
      pluginReactLynx({
        compat: {
          legacySlot: true,
        },
      }),
    ],
  });
  ```

  The default (SlotV2) codegen is unchanged, and the runtime keeps supporting both forms.

- Keep DevTools Lepus ID mapping wired to the shared snapshot instance manager, so production devtools builds can resolve native unique IDs without importing the full snapshot runtime into the main-thread bundle. ([#2960](https://github.com/lynx-family/lynx-stack/pull/2960))

- Add ALOG diagnostics for list flush and hydration update information. ([#2975](https://github.com/lynx-family/lynx-stack/pull/2975))

- Fix the error when using dynamic `key` with spread attributes on `<list-item>`. ([#1948](https://github.com/lynx-family/lynx-stack/pull/1948))

  **Error Message:**

  ```text
  Native error:
  code: 220201
  message: Error for illegal list item-key in parse insert with indexes: [0, ]
  fix_suggestion: Please check the legality of the item-key.
  ```

- Preserve list item platform info when item-key is provided through spread props. ([#2918](https://github.com/lynx-family/lynx-stack/pull/2918))

- Bind the snapshot runtime via `import` in development instead of inline `require('@lynx-js/react/internal')`, so dev builds work with async (promise) externals. Dev snapshot creators now receive the runtime as a parameter (staying self-contained for cross-thread HMR `DEV_ONLY_AddSnapshot`) with a temporary `__runtime__ || require(...)` fallback for older runtimes that call creators with a single argument; production creators keep the statically tree-shakeable module-scope reference. ([#2939](https://github.com/lynx-family/lynx-stack/pull/2939))

## 0.122.1

### Patch Changes

- Support `cloneElement` for more ReactLynx snapshot scenarios, including compiled snapshots, runtime-created snapshots, and repeated clones. ([#2857](https://github.com/lynx-family/lynx-stack/pull/2857))

  Cloning compiled snapshots still cannot replace children and will warn in that case. Use components or runtime-created snapshots when clone-time children replacement is needed.

- Preserve list item platform info on background-thread snapshots for hydrate ([#2904](https://github.com/lynx-family/lynx-stack/pull/2904))
  diffing.

- Support enabling preact devtools in production via the `REACT_DEVTOOL` environment variable. ([#2880](https://github.com/lynx-family/lynx-stack/pull/2880))

  By default `@lynx-js/preact-devtools` is aliased away in production builds. Setting the `REACT_DEVTOOL` environment variable now:

  1. keeps a user-imported `@lynx-js/preact-devtools` from being stripped;
  2. defines `__REACT_DEVTOOL__`, which gates the dev-only runtime hooks devtools depends on (such as `injectLepusMethods`) so they also run in production;
  3. keeps function/class names during minification (`keep_fnames`/`keep_classnames`), which devtools needs to resolve component names (`type.name`) and to reconstruct the hook tree (it matches minified stack frames by function name).

  `@lynx-js/react/debug` remains development-only.

## 0.122.0

### Minor Changes

- Expose the `Children` API from ReactLynx and freeze the arrays returned by `Children.map`, `Children.forEach`, and `Children.toArray`. ([#2376](https://github.com/lynx-family/lynx-stack/pull/2376))

  Allow `@lynx-js/react` 0.121 and newer in GenUI peer dependency ranges.

### Patch Changes

- Report a development error when a page-data reset is combined with `withInitDataInState`. ([#2869](https://github.com/lynx-family/lynx-stack/pull/2869))

  `withInitDataInState` merges `lynx.__initData` into the wrapped component's state, so resetting the page data — `updatePage(..., { resetPageData: true })` on the main thread, or `updateData(..., { type: 'reset' })` on the background thread — cannot drop the keys the reset removed; the component keeps rendering the stale keys. A dev-only error is now reported (once per reset path) on both threads, pointing to `useInitData()` instead. The check is gated by `__DEV__` and is fully removed from production builds.

- Fix `withInitDataInState` not refreshing the component state on a main-thread re-render. ([#2868](https://github.com/lynx-family/lynx-stack/pull/2868))

  `withInitDataInState` injected `lynx.__initData` into the class component's state only in the constructor, and its `onDataChanged` listener was active on the background thread only. On the main thread the component instance is reused across an `updatePage` re-render (the constructor never re-runs), so the injected state stayed frozen at the data from the first render. This surfaces whenever the main thread re-renders the screen itself before hydration (an `updatePage` while `firstScreenSyncTiming` is `'jsReady'`). The HOC now re-reads `lynx.__initData` on every render via `getDerivedStateFromProps`, composing with — and not overriding — the wrapped component's own `getDerivedStateFromProps`.

## 0.121.2

### Patch Changes

- Fix `addComponentElement` compat transforms so explicit `removeComponentElement={true}` is honored consistently even when it appears before a JSX spread like `{...props}`. ([#2758](https://github.com/lynx-family/lynx-stack/pull/2758))

  Previously, the compat transform could short-circuit while scanning opening attributes and treat:

  ```jsx
  <Component removeComponentElement={true} {...props} />;
  ```

  differently from:

  ```jsx
  <Component {...props} removeComponentElement={true} />;
  ```

  The transform now collects the full opening-attribute state first, so both prop orders compile the same way in normal and `compilerOnly` modes.

- Fix directive DCE for TypeScript async output with nested `"background only"` directives. ([#2830](https://github.com/lynx-family/lynx-stack/pull/2830))

- Rename the `bundle-url` element attribute to `lazy-bundle-url`. ([#2723](https://github.com/lynx-family/lynx-stack/pull/2723))

  The attribute set on lazy bundle border elements (when a child belongs to a different lazy bundle entry than its parent) is renamed from `bundle-url` to `lazy-bundle-url` to make its purpose explicit.

## 0.121.1

### Patch Changes

- Disable vnode reuse of different slot index in preact's diff, fixing a bug that `__RemoveElement` was called with mismatched parent and child element. ([#2664](https://github.com/lynx-family/lynx-stack/pull/2664))

- Fix list update indices when existing items are updated after inserting siblings before them. ([#2518](https://github.com/lynx-family/lynx-stack/pull/2518))

## 0.121.0

### Minor Changes

- Support `React.createElement(type, props, children)` API. ([#2360](https://github.com/lynx-family/lynx-stack/pull/2360))

  ```jsx
  React.createElement('view', { style }, <text>hello</text>);
  // equivalent to
  <view style={style}>
    <text>hello</text>
  </view>;

  React.createElement(MyComponent, { style }, <view />);
  // equivalent to
  <MyComponent style={style}>
    <view />
  </MyComponent>;
  ```

### Patch Changes

- Clear transient snapshot child props when removed snapshot subtrees are detached, preventing compiled `$*` child references from retaining deleted list holder or list item subtrees after removal. ([#2590](https://github.com/lynx-family/lynx-stack/pull/2590))

- Add `createPortal` for rendering a subtree into a different ReactLynx element identified by a `NodesRef`. ([#2543](https://github.com/lynx-family/lynx-stack/pull/2543))

  ```tsx
  function App() {
    const [host, setHost] = useState(null);
    return (
      <view>
        <view ref={setHost} />
        {host && createPortal(<text>hi</text>, host)}
      </view>
    );
  }
  ```

- Default `fireEvent` to `bubbles: true` for the TouchEvent family in testing-library to match Lynx runtime semantics, and stop reassigning the read-only `Event.prototype` accessors which threw `TypeError` in strict mode. ([#2532](https://github.com/lynx-family/lynx-stack/pull/2532))

- Set `bundle-url` on lazy bundle border elements. ([#2537](https://github.com/lynx-family/lynx-stack/pull/2537))

- Stop warning when `runWorklet` receives an invalid or missing main-thread function object. Invalid worklet contexts are still ignored, but nullish handler values no longer produce noisy `MainThreadFunction: Invalid function object` console output. ([#2586](https://github.com/lynx-family/lynx-stack/pull/2586))

- Retain main-thread worklet context references before offscreen snapshot elements are materialized, so event, ref, gesture, and spread callbacks stay alive until the DOM update path can attach them. ([#2592](https://github.com/lynx-family/lynx-stack/pull/2592))

- Update the @lynx-js/tasm dependency to 0.0.39 and align React template attribute descriptors with it. ([#2643](https://github.com/lynx-family/lynx-stack/pull/2643))

- Avoid retaining transformed nested worklet contexts after worklet transformation. ([#2591](https://github.com/lynx-family/lynx-stack/pull/2591))

  Nested worklets transformed by the worklet runtime now keep their context recovery metadata through a weak reference, preventing cached transformed worklet functions from keeping list-item worklet contexts alive.

## 0.120.0

### Minor Changes

- Bump `@lynx-js/internal-preact` from `10.28.4-dfff9aa` to `10.29.1-20260424024911-12b794f` ([diff](https://github.com/lynx-family/internal-preact/compare/10.28.4-dfff9aa...10.29.1-20260424024911-12b794f)). ([#2512](https://github.com/lynx-family/lynx-stack/pull/2512))

  Fixes wrong DOM order when a keyed child moves to a different `$N` slot across a re-render. Cross-slot moves now land at the correct slot position instead of being appended past stable siblings.

- Refactor preact to support multi-slots children and reduce the number and depth of snapshot. ([#1764](https://github.com/lynx-family/lynx-stack/pull/1764))

### Patch Changes

- Fix stale callback-local references when transforming JSX inside `children={array.map(...)}` prop expressions. ([#2524](https://github.com/lynx-family/lynx-stack/pull/2524))

- Fix ref callbacks not being cleaned up or re-applied correctly when the ref at the same element slot changes across rerenders that happen before hydration (e.g. a `useEffect` triggering `setState` during the initial background render). ([#2500](https://github.com/lynx-family/lynx-stack/pull/2500))

- fix: reduce redundant updates for main-thread handlers and gestures ([#2188](https://github.com/lynx-family/lynx-stack/pull/2188))

  - Updates are faster when the main-thread event handler or gesture object is stable across rerenders (fewer unnecessary native updates).
  - Spread props rerenders that don't semantically change the handler/gesture no longer trigger redundant updates.
  - Removing a gesture from spread props reliably clears the gesture state on the target element.

- Fix hydration edge cases by tolerating serialized snapshot nodes with missing `values` ([#2481](https://github.com/lynx-family/lynx-stack/pull/2481))

- Keep ReactLynx Testing Library imports aligned with the contained snapshot runtime paths. ([#2498](https://github.com/lynx-family/lynx-stack/pull/2498))

## 0.119.0

### Minor Changes

- Simplify hooks for main-thread runtime, which only can run during the first screen. ([#2441](https://github.com/lynx-family/lynx-stack/pull/2441))

### Patch Changes

- Remove stale gestures when gestures are removed ([#2297](https://github.com/lynx-family/lynx-stack/pull/2297))

- Trace refactor ([#2466](https://github.com/lynx-family/lynx-stack/pull/2466))

  - Remove `ReactLynx::renderOpcodes` from the trace
  - Use `ReactLynx::transferRoot` to measure the time spent transferring the root to the background thread

- refactor: set state of suspense to render fallback ([#2450](https://github.com/lynx-family/lynx-stack/pull/2450))

- Support rstest for testing library, you can use rstest with RLTL now: ([#2328](https://github.com/lynx-family/lynx-stack/pull/2328))

  Create a config file `rstest.config.ts` with the following content:

  ```ts
  import { defineConfig } from '@rstest/core';
  import { withLynxConfig } from '@lynx-js/react/testing-library/rstest-config';

  export default defineConfig({
    extends: withLynxConfig(),
  });
  ```

  `@lynx-js/react/testing-library/rstest-config` will automatically load your `lynx.config.ts` and apply the same configuration to rstest, so you can keep your test environment consistent with your development environment.

  And then use rstest as usual:

  ```bash
  $ rstest
  ```

  For more usage detail, see https://rstest.rs/

- Update preact version ([#2456](https://github.com/lynx-family/lynx-stack/pull/2456))

- Add `nodeIndex` to generated FiberElement creation calls and expose React transform debug metadata as `uiSourceMapRecords`. ([#2402](https://github.com/lynx-family/lynx-stack/pull/2402))

## 0.118.0

### Minor Changes

- refactor: create SnapshotInstance in renderToString directly ([#2393](https://github.com/lynx-family/lynx-stack/pull/2393))

- Add `removeCall` for shake function calls. Its initial default value matches the hooks that were previously in `removeCallParams`, and `removeCallParams` now defaults to empty. ([#2423](https://github.com/lynx-family/lynx-stack/pull/2423))

  `removeCall` removes matched runtime hook calls entirely, replacing them with `undefined` in expression positions and dropping them in statement positions. `removeCallParams` keeps the existing behavior of preserving the call while stripping its arguments.

### Patch Changes

- Improve `shake.removeCall` and `shake.removeCallParams` in the React transform so they also match aliased runtime imports such as `import { useEffect as myUseEffect } ...` and member calls such as `ReactLynxRuntime.useEffect(...)` from default or namespace runtime imports. ([#2437](https://github.com/lynx-family/lynx-stack/pull/2437))

- Create element without ref for suspense in main thread. ([#2426](https://github.com/lynx-family/lynx-stack/pull/2426))

- refactor: make `useEffect`, `useLayoutEffect` and `useImperativeHandle` no-op on the main thread ([#2424](https://github.com/lynx-family/lynx-stack/pull/2424))

## 0.117.1

### Patch Changes

- Update preact version to simplify `setProperty` implementation ([#2367](https://github.com/lynx-family/lynx-stack/pull/2367))

## 0.117.0

### Minor Changes

- feat: export `GlobalPropsProvider`, `GlobalPropsConsumer`, `useGlobalProps` and `useGlobalPropsChanged` for `__globalProps` ([#2346](https://github.com/lynx-family/lynx-stack/pull/2346))

  - `GlobalPropsProvider`: A Provider component that accepts `children`. It is used to provide the `lynx.__globalProps` context.
  - `GlobalPropsConsumer`: A Consumer component that accepts a function as a child. It is used to consume the `lynx.__globalProps` context.
  - `useGlobalProps`: A hook that returns the `lynx.__globalProps` object. It triggers a re-render when `lynx.__globalProps` changes.
  - `useGlobalPropsChanged`: A hook that accepts a callback function. The callback is invoked when `lynx.__globalProps` changes.

  Note: When `globalPropsMode` is not set to `'event'` (default is `'reactive'`), these APIs will be ineffective (pass-through) and will log a warning in development mode, as updates are triggered automatically by full re-render.

- **BREAKING CHANGE**: ([#2319](https://github.com/lynx-family/lynx-stack/pull/2319))

  Change preact package from `@hongzhiyuan/preact` to `@lynx-js/internal-preact`.

  Upgrade preact from [f7693b72](https://github.com/preactjs/preact/commit/f7693b72ecb4a40c66e6e47f54e2d4edc374c9f0) to [55254ef7](https://github.com/preactjs/preact/commit/55254ef7021e563cc1a86fb816058964a1b6a29a), see diffs at [f7693b72...55254ef7](https://github.com/preactjs/preact/compare/f7693b72ecb4a40c66e6e47f54e2d4edc374c9f0...preactjs:preact:55254ef7021e563cc1a86fb816058964a1b6a29a?expand=1).

- feat: add `globalPropsMode` option to `PluginReactLynxOptions` ([#2346](https://github.com/lynx-family/lynx-stack/pull/2346))

  - When configured to `"event"`, `updateGlobalProps` will only trigger a global event and skip the `runWithForce` flow.
  - Defaults to `"reactive"`, which means `updateGlobalProps` will trigger re-render automatically.

### Patch Changes

- Add `__BACKGROUND__` guard on `onBackgroundSnapshotInstanceUpdateId` event to prevent bundling to main-thread on dev environment. ([#2332](https://github.com/lynx-family/lynx-stack/pull/2332))

- refactor: extract static string in template literal ([#2334](https://github.com/lynx-family/lynx-stack/pull/2334))

- fix: avoid crash when spread undefined ref ([#2333](https://github.com/lynx-family/lynx-stack/pull/2333))

- Avoid registering lifecycle refs for main-thread functions (MTF) that have not received an `execId` during `renderPage()` first-screen binding. ([#2320](https://github.com/lynx-family/lynx-stack/pull/2320))

## 0.116.5

### Patch Changes

- Improve React runtime hook profiling. ([#2235](https://github.com/lynx-family/lynx-stack/pull/2235))
  Enable Profiling recording first, then enter the target page so the trace includes full render/hydrate phases.

  - Record trace events for `useEffect` / `useLayoutEffect` hook entry, callback, and cleanup phases.
  - Log trace events for `useState` setter calls.
  - Wire `profileFlowId` support in debug profile utilities and attach flow IDs to related hook traces.
  - Instrument hydrate/background snapshot profiling around patch operations with richer args (e.g. snapshot id/type, dynamic part index, value type, and source when available).
  - Capture vnode source mapping in dev and use it in profiling args to improve trace attribution.
  - Expand debug test coverage for profile utilities, hook profiling behavior, vnode source mapping, and hydrate profiling branches.

- refactor: call loadWorkletRuntime once in each module ([#2315](https://github.com/lynx-family/lynx-stack/pull/2315))

## 0.116.4

### Patch Changes

- Support `ReactLynx::hooks::setState` trace for function components. ([#2198](https://github.com/lynx-family/lynx-stack/pull/2198))

- fix: properly cleanup `__DestroyLifetime` listeners and listCallbacks in `snapshotDestroyList`. ([#2224](https://github.com/lynx-family/lynx-stack/pull/2224))

## 0.116.3

### Patch Changes

- fix: remove `lynx.createSelectorQuery` deprecated warning in production ([#2195](https://github.com/lynx-family/lynx-stack/pull/2195))

- Add a DEV-only guard that detects MainThread flush loops caused by re-entrant MTS handlers. ([#2159](https://github.com/lynx-family/lynx-stack/pull/2159))

  This typically happens when a MainThread handler (e.g. event callback or `MainThreadRef`) performs UI mutations (like `Element.setStyleProperty`, `setStyleProperties`, `setAttribute`, or `invoke`) that synchronously trigger a flush which re-enters the handler again.

- Avoid DEV_ONLY_SetSnapshotEntryName on standalone lazy bundle. ([#2184](https://github.com/lynx-family/lynx-stack/pull/2184))

- Add alog and trace for BTS event handlers. ([#2102](https://github.com/lynx-family/lynx-stack/pull/2102))

- fix: Main thread functions cannot access properties on `this` before hydration completes. ([#2194](https://github.com/lynx-family/lynx-stack/pull/2194))

  This fixes the `cannot convert to object` error.

- Remove element api calls alog by default, and only enable it when `__ALOG_ELEMENT_API__` is defined to `true` or environment variable `REACT_ALOG_ELEMENT_API` is set to `true`. ([#2192](https://github.com/lynx-family/lynx-stack/pull/2192))

- fix: captured variables in main thread functions within class components do not update correctly ([#2197](https://github.com/lynx-family/lynx-stack/pull/2197))

## 0.116.2

### Patch Changes

- Fix "TypeError: not a function" error caused by `replaceAll` not supported in ES5. ([#2142](https://github.com/lynx-family/lynx-stack/pull/2142))

- Bump `swc_core` v56. ([#2154](https://github.com/lynx-family/lynx-stack/pull/2154))

- Use `disableDeprecatedWarning` option to suppress BROKEN warnings during compilation. ([#2157](https://github.com/lynx-family/lynx-stack/pull/2157))

  1. BROKEN: `getNodeRef`/`getNodeRefFromRoot`/`createSelectorQuery` on component instance is broken and MUST be migrated in ReactLynx 3.0, please use ref or lynx.createSelectorQuery instead.
  2. BROKEN: `getElementById` on component instance is broken and MUST be migrated in ReactLynx 3.0, please use ref or lynx.getElementById instead.

- Fix memory leak by clearing list callbacks when \_\_DestroyLifetime event is triggered. ([#2112](https://github.com/lynx-family/lynx-stack/pull/2112))

## 0.116.1

### Patch Changes

- Fix the issue that lazy bundle HMR will lost CSS. ([#2134](https://github.com/lynx-family/lynx-stack/pull/2134))

## 0.116.0

### Minor Changes

- **BREAKING CHANGE**: Bump Preact from [10.24.0](https://github.com/preactjs/preact/commit/1807173df5e18b6b1a3cd667ee2a31af37f4282b) to [10.28.0](https://github.com/preactjs/preact/commit/f7693b72ecb4a40c66e6e47f54e2d4edc374c9f0), see diffs at [hzy/preact#6](https://github.com/hzy/preact/pull/6). ([#2042](https://github.com/lynx-family/lynx-stack/pull/2042))

### Patch Changes

- Add safety checks for compilation macros to prevent runtime errors when they are undefined. ([#2110](https://github.com/lynx-family/lynx-stack/pull/2110))

  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.

## 0.115.4

### Patch Changes

- fix: unable to access `MainThreadRef` in some scenarios ([#1996](https://github.com/lynx-family/lynx-stack/pull/1996))

- Add `getComputedStyleProperty` for `MainThread.Element` to retrieve computed style values synchronously. ([#2005](https://github.com/lynx-family/lynx-stack/pull/2005))

  **Requires Lynx SDK >= 3.5**

  ```typescript
  function getStyle(ele: MainThread.Element) {
    'main thread';
    const width = ele.getComputedStyleProperty('width'); // Returns 300px
    const transformMatrix = ele.getComputedStyleProperty('transform'); // Returns matrix(2, 0, 0, 2, 200, 400)
  }
  ```

## 0.115.3

### Patch Changes

- Add dual-thread commutation logs for troubleshooting when `REACT_ALOG=true` or global define `__ALOG__` is set. ([#2081](https://github.com/lynx-family/lynx-stack/pull/2081))

- Use error cause to simplify the error msg of lazy bundle loading. User can catch the error cause to get the original result: ([#2056](https://github.com/lynx-family/lynx-stack/pull/2056))

  ```ts
  const LazyComponent = lazy(async () => {
    try {
      const mod = await import('./lazy-bundle');
      return mod.default;
    } catch (error) {
      console.error(`Lazy Bundle load failed message: ${error.message}`);
      // User can catch the error cause to get the original result
      console.error(`Lazy Bundle load failed result: ${error.cause}`);
      throw error;
    }
  });
  ```

## 0.115.2

### Patch Changes

- Fix `undefined factory (react:background)/./node_modules/.pnpm/@lynx-js+react...` error when loading a standalone lazy bundle after hydration. ([#2048](https://github.com/lynx-family/lynx-stack/pull/2048))

- Partially fix "main-thread.js exception: TypeError: cannot read property '\_\_elements' of undefined" by recursively calling `snapshotDestroyList`. ([#2041](https://github.com/lynx-family/lynx-stack/pull/2041))

- Fix a bug where React throws `CtxNotFound` error when lazy bundle resolves after unmount. ([#2003](https://github.com/lynx-family/lynx-stack/pull/2003))

## 0.115.1

### Patch Changes

- Auto define lynx.loadLazyBundle when using `import(/* relative path */)`. ([#1956](https://github.com/lynx-family/lynx-stack/pull/1956))

- feat: support declaring cross-thread shared modules via Import Attributes, enabling Main Thread Functions to call standard JS functions directly. ([#1968](https://github.com/lynx-family/lynx-stack/pull/1968))

  - Usage: Add `with { runtime: "shared" }` to the `import` statement. For example:

    ```ts
    import { func } from './utils.js' with { runtime: 'shared' };

    function worklet() {
      'main thread';
      func(); // callable inside a main thread function
    }
    ```

  - Limitations:
    - Only directly imported identifiers are treated as shared; assigning the import to a new variable will result in the loss of this shared capability.
    - Functions defined within shared modules do not automatically become Main Thread Functions. Accessing main-thread-only APIs (e.g., `MainThreadRef`) will cause errors.

## 0.115.0

### Minor Changes

- **BREAKING CHANGE**: Delay the `createSnapshot` operation to `Snapshot` constructor to speed up IFR. ([#1899](https://github.com/lynx-family/lynx-stack/pull/1899))

  This change refactors how snapshots are created and registered:

  - Removed the `entryUniqID` function
  - Snapshots are now lazily created via `snapshotCreatorMap` instead of eagerly at bundle load time
  - Snapshot IDs are generated at compile time and only prefixed with `${globDynamicComponentEntry}:` for standalone lazy bundles

  **⚠️ Lazy Bundle Compatibility:**

  - **Backward compatibility (new runtime → old lazy bundles)**: ✅ **Supported**. Old lazy bundles will work with the new runtime.

  - **Forward compatibility (old runtime → new lazy bundles)**: ❌ **NOT Supported**. Lower version consumers **will not be able to load lazy bundles produced by this version** due to the changed snapshot creation mechanism.

  **Migration guidance**:
  If you are using lazy bundles, ensure all consumers are upgraded to this version or later **before** deploying lazy bundles built with this version. For monorepo setups, coordinate the upgrade across all consuming applications.

### Patch Changes

- Preserve assignments to webpack runtime variables like `__webpack_public_path__`, `__webpack_require__.p`, etc. ([#1958](https://github.com/lynx-family/lynx-stack/pull/1958))

- Fixed blank screen issues with nested lists. Lazily created nested lists were being flushed but not properly recorded, causing rendering failures. ([#1963](https://github.com/lynx-family/lynx-stack/pull/1963))

- fix: export `createRef` and `useRef` from `@lynx-js/react/legacy-react-runtime` ([#1953](https://github.com/lynx-family/lynx-stack/pull/1953))

## 0.114.5

### Patch Changes

- Reduce `__SetInlineStyles` element API call when attrs in spread not changed ([#1919](https://github.com/lynx-family/lynx-stack/pull/1919))

## 0.114.4

### Patch Changes

- During hydration, replace update with insert + remove for same-type `<list-item />` with different `item-key` so the Lynx Engine detects changes. ([#1598](https://github.com/lynx-family/lynx-stack/pull/1598))

  ```html
  Hydrate List B into List A: List A:
  <list>
    <list-item item-key="a">hello</list-item>
    <list-item item-key="a">world</list-item>
  </list>

  List B:
  <list>
    <list-item item-key="a1">hello</list-item>
    <list-item item-key="a2">world</list-item>
  </list>
  ```

  Previously this case was hydrated as an update; it is now emitted as insert + remove to ensure SDK detection.

- Bump `swc_core` v47. ([#1916](https://github.com/lynx-family/lynx-stack/pull/1916))

- Pass sourcemap generated by rspack to swc transformer. ([#1910](https://github.com/lynx-family/lynx-stack/pull/1910))

- When engineVersion is greater than or equal to 3.1, use `__SetAttribute` to set text attribute for text node instead of creating a raw text node. ([#1880](https://github.com/lynx-family/lynx-stack/pull/1880))

- Add profile for list `update-list-info`. ([#1480](https://github.com/lynx-family/lynx-stack/pull/1480))

- Support testing React Compiler in testing library. Enable React Compiler by setting the `experimental_enableReactCompiler` option of `createVitestConfig` to `true`. ([#1269](https://github.com/lynx-family/lynx-stack/pull/1269))

  ```js
  import { defineConfig, mergeConfig } from 'vitest/config';
  import { createVitestConfig } from '@lynx-js/react/testing-library/vitest-config';

  const defaultConfig = await createVitestConfig({
    runtimePkgName: '@lynx-js/react',
    experimental_enableReactCompiler: true,
  });

  export default mergeConfig(defaultConfig, config);
  ```

## 0.114.3

### Patch Changes

- Initialize `ctxNotFoundEventListener` before each test in testing library ([#1888](https://github.com/lynx-family/lynx-stack/pull/1888))

- fix: main thread functions created during the initial render cannot correctly modify `MainThreadRef`s after hydration ([#1884](https://github.com/lynx-family/lynx-stack/pull/1884))

## 0.114.2

### Patch Changes

- fix: main thread functions created during the initial render cannot correctly call `runOnBackground()` after hydration ([#1878](https://github.com/lynx-family/lynx-stack/pull/1878))

## 0.114.1

### Patch Changes

- Add `event.stopPropagation` and `event.stopImmediatePropagation` in MTS, to help with event propagation control ([#1835](https://github.com/lynx-family/lynx-stack/pull/1835))

  ```tsx
  function App() {
    function handleInnerTap(event: MainThread.TouchEvent) {
      'main thread';
      event.stopPropagation();
      // Or stop immediate propagation with
      // event.stopImmediatePropagation();
    }

    // OuterTap will not be triggered
    return (
      <view main-thread:bindtap={handleOuterTap}>
        <view main-thread:bindtap={handleInnerTap}>
          <text>Hello, world</text>
        </view>
      </view>
    );
  }
  ```

  Note, if this feature is used in [Lazy Loading Standalone Project](https://lynxjs.org/react/code-splitting.html#lazy-loading-standalone-project), both the Producer and the Consumer should update to latest version of `@lynx-js/react` to make sure the feature is available.

- Fix the "ReferenceError: Node is not defined" error. ([#1850](https://github.com/lynx-family/lynx-stack/pull/1850))

  This error would happen when upgrading to `@testing-library/jest-dom` [v6.9.0](https://github.com/testing-library/jest-dom/releases/tag/v6.9.0).

- fix: optimize main thread event error message ([#1838](https://github.com/lynx-family/lynx-stack/pull/1838))

## 0.114.0

### Minor Changes

- Partially fix the "cannot read property 'update' of undefined" error. ([#1771](https://github.com/lynx-family/lynx-stack/pull/1771))

  This error happens when rendering a JSX expression in a [background-only](https://lynxjs.org/react/thinking-in-reactlynx.html) context.

  See [lynx-family/lynx-stack#894](https://github.com/lynx-family/lynx-stack/issues/894) for more details.

### Patch Changes

- Reduce extra snapshot when children are pure text ([#1562](https://github.com/lynx-family/lynx-stack/pull/1562))

- feat: Support `SelectorQuery` `animation` APIs ([#1768](https://github.com/lynx-family/lynx-stack/pull/1768))

- Fix spread props inside list-item caused redundant snapshot patch ([#1760](https://github.com/lynx-family/lynx-stack/pull/1760))

- fix: `ref is not initialized` error on template reload ([#1757](https://github.com/lynx-family/lynx-stack/pull/1757))

## 0.113.0

### Minor Changes

- fix: Delay execution of `runOnMainThread()` during initial render ([#1667](https://github.com/lynx-family/lynx-stack/pull/1667))

  When called during the initial render, `runOnMainThread()` would execute before the `main-thread:ref` was hydrated, causing it to be incorrectly set to null.

  This change delays the function's execution to ensure the ref is available and correctly assigned.

### Patch Changes

- Fix "TypeError: cannot read property '0' of undefined" in deferred list-item scenarios. ([#1692](https://github.com/lynx-family/lynx-stack/pull/1692))

  Deferred `componentAtIndex` causes nodes that quickly appear/disappear to be enqueued without `__elements`. Update `signMap` before `__FlushElementTree` to resolve the issue.

- Keep the same `<page/>` element when calling `rerender` in testing library. ([#1656](https://github.com/lynx-family/lynx-stack/pull/1656))

- Bump `swc_core` to `39.0.3`. ([#1721](https://github.com/lynx-family/lynx-stack/pull/1721))

## 0.112.6

### Patch Changes

- Support nested list. ([#1581](https://github.com/lynx-family/lynx-stack/pull/1581))

- Should only recycle off-screen `list-item` in recursive hydration. ([#1641](https://github.com/lynx-family/lynx-stack/pull/1641))

- fix `fireEvent` type error in testing library ([#1596](https://github.com/lynx-family/lynx-stack/pull/1596))

## 0.112.5

### Patch Changes

- Remove the "key is not on root element of snapshot" warning. ([#1558](https://github.com/lynx-family/lynx-stack/pull/1558))

## 0.112.4

### Patch Changes

- fix `withInitDataInState` got wrong state in 2nd or more times `defaultDataProcessor`, now it will keep its own state. ([#1478](https://github.com/lynx-family/lynx-stack/pull/1478))

- change `__CreateElement('raw-text')` to `__CreateRawText('')` to avoid `setNativeProps` not working ([#1570](https://github.com/lynx-family/lynx-stack/pull/1570))

- Fix wrong render result when using expression as `key`. ([#1541](https://github.com/lynx-family/lynx-stack/pull/1541))

  See [lynx-family/lynx-stack#1371](https://github.com/lynx-family/lynx-stack/issues/1371) for more details.

- fix: `Cannot read properties of undefined` error when using `Suspense` ([#1569](https://github.com/lynx-family/lynx-stack/pull/1569))

- Add `animate` API in Main Thread Script(MTS), so you can now control a CSS animation imperatively ([#1534](https://github.com/lynx-family/lynx-stack/pull/1534))

  ```ts
  import type { MainThread } from '@lynx-js/types';

  function startAnimation(ele: MainThread.Element) {
    'main thread';
    const animation = ele.animate([{ opacity: 0 }, { opacity: 1 }], {
      duration: 3000,
    });

    // Can also be paused
    // animation.pause()
  }
  ```

## 0.112.3

### Patch Changes

- fix css transform error in testing library ([#1500](https://github.com/lynx-family/lynx-stack/pull/1500))

- fix the type error of `wrapper` option in testing library's `render` and `renderHook` function ([#1502](https://github.com/lynx-family/lynx-stack/pull/1502))

- Introduce recursive hydration for lists to prevent double remove/insert on moves. ([#1401](https://github.com/lynx-family/lynx-stack/pull/1401))

- Handle `<frame/>` correctly. ([#1497](https://github.com/lynx-family/lynx-stack/pull/1497))

## 0.112.2

### Patch Changes

- Supports `recyclable` attribute in `<list-item>` to control whether the list item is recyclable. The `recyclable` attribute depends on Lynx Engine 3.4 or later. ([#1388](https://github.com/lynx-family/lynx-stack/pull/1388))

  ```jsx
  <list-item recyclable={false} />;
  ```

- feat: Support using a host element as direct child of Suspense ([#1455](https://github.com/lynx-family/lynx-stack/pull/1455))

- Add profile in production build: ([#1336](https://github.com/lynx-family/lynx-stack/pull/1336))

  1. `diff:__COMPONENT_NAME__`: how long ReactLynx diff took.
  2. `render:__COMPONENT_NAME__`: how long your render function took.
  3. `setState`: an instant trace event, indicate when your setState was called.

  NOTE: `__COMPONENT_NAME__` may be unreadable when minified, setting `displayName` may help.

- Add `onBackgroundSnapshotInstanceUpdateId` event on dev for Preact Devtools to keep the correct snapshotInstanceId info. ([#1173](https://github.com/lynx-family/lynx-stack/pull/1173))

- fix: Prevent error when spreading component props onto an element ([#1459](https://github.com/lynx-family/lynx-stack/pull/1459))

- fix: Correctly check for the existence of background functions in MTS ([#1416](https://github.com/lynx-family/lynx-stack/pull/1416))

  ```ts
  function handleTap() {
    'main thread';
    // The following check always returned false before this fix
    if (myHandleTap) {
      runOnBackground(myHandleTap)();
    }
  }
  ```

## 0.112.1

### Patch Changes

- Fix crash caused by not removing event listeners during destroy. ([#1379](https://github.com/lynx-family/lynx-stack/pull/1379))

- Fix missing "type" in "update-list-info" in hydrate ([#1392](https://github.com/lynx-family/lynx-stack/pull/1392))

## 0.112.0

### Minor Changes

- feat: Force synchronous rendering for background initial renders to support Suspense fallbacks ([#1323](https://github.com/lynx-family/lynx-stack/pull/1323))

- Introduces `@lynx-js/react/compat` submodule exporting Preact implementations of: ([#1316](https://github.com/lynx-family/lynx-stack/pull/1316))

  - `startTransition`
  - `useTransition`

### Patch Changes

- fix: Ensure useEffect callbacks execute before event handlers from the same render cycle ([#1348](https://github.com/lynx-family/lynx-stack/pull/1348))

- Enable rendering of the `Suspense` fallback on initial render. ([#1285](https://github.com/lynx-family/lynx-stack/pull/1285))

- fix: Prevent "cannot set property 'current' of undefined" error thrown by MainThreadRef on engine data updates ([#1342](https://github.com/lynx-family/lynx-stack/pull/1342))

## 0.111.2

### Patch Changes

- Optimize `componentAtIndex` by a few hundreds microseconds: avoiding manipulate `__pendingListUpdates` unless SnapshotInstance tree is changed ([#1201](https://github.com/lynx-family/lynx-stack/pull/1201))

- Support alog of component rendering on production for better error reporting. Enable it by using `REACT_ALOG=true rspeedy dev/build` or defining `__ALOG__` to `true` in `lynx.config.js`: ([#1164](https://github.com/lynx-family/lynx-stack/pull/1164))

  ```js
  export default defineConfig({
    // ...
    source: {
      define: {
        __ALOG__: true,
      },
    },
  });
  ```

- Make `preact/debug` work with `@lynx-js/react`. ([#1222](https://github.com/lynx-family/lynx-stack/pull/1222))

- Introduce `@lynx-js/react/debug` which would include debugging warnings and error messages for common mistakes found. ([#1250](https://github.com/lynx-family/lynx-stack/pull/1250))

  Add the import to `@lynx-js/react/debug` at the first line of the entry:

  ```js
  import '@lynx-js/react/debug';
  import { root } from '@lynx-js/react';

  import { App } from './App.jsx';

  root.render(<App />);
  ```

- `<list-item/>` deferred now accepts an object with `unmountRecycled` property to control unmounting behavior when the item is recycled. ([#1302](https://github.com/lynx-family/lynx-stack/pull/1302))

  For example, you can use it like this:

  ```jsx
  <list-item defer={{ unmountRecycled: true }} item-key='1'>
    <WillBeUnmountIfRecycled />
  </list-item>;
  ```

  Now the component will be unmounted when it is recycled, which can help with performance in certain scenarios.

- Avoid some unexpected `__SetAttribute` in hydrate when `undefined` is passed as an attribute value to intrinsic elements, for example: ([#1318](https://github.com/lynx-family/lynx-stack/pull/1318))

  ```jsx
  <image async-mode={undefined} />;
  ```

## 0.111.1

### Patch Changes

- Wrap the main thread `renderPage` in preact `act` to ensure that the effects are flushed. ([#1170](https://github.com/lynx-family/lynx-stack/pull/1170))

## 0.111.0

### Minor Changes

- Allow some `<list-item/>`s to be deferred and rendered in the background thread. ([#204](https://github.com/lynx-family/lynx-stack/pull/204))

  Use the following syntax:

  ```diff
  <list>
  -  <list-item item-key="...">
  +  <list-item item-key="..." defer>
        <SomeHeavyComponent />
    </list-item>
  </list>
  ```

  You should render your heavyweight components with the `defer` attribute to avoid blocking the main thread.

### Patch Changes

- Add missing alias of `@lynx-js/react` and `preact` in testing library, it will fix the `Failed to resolve import "@lynx-js/react/internal"` error in node_modules. ([#1182](https://github.com/lynx-family/lynx-stack/pull/1182))

- Allow any types of `dataProcessors` in `lynx.registerDataProcessors`. ([#1200](https://github.com/lynx-family/lynx-stack/pull/1200))

- Make `loadLazyBundle` being able to render the content on the first screen of the background thread. ([#1212](https://github.com/lynx-family/lynx-stack/pull/1212))

- Fixed: An issue where the `lynxViewDidUpdate` callback did not trigger when data was updated from native. ([#1171](https://github.com/lynx-family/lynx-stack/pull/1171))

  Notice:

  - Even if no data changes are actually processed after calling `updateData()`, the `lynxViewDidUpdate` callback will still be triggered.
  - Only one `lynxViewDidUpdate` callback will be triggered per render cycle. Consequently, if multiple `updateData()` calls are made within a single cycle but the data updates are batched, the number of `lynxViewDidUpdate` callbacks triggered may be less than the number of `updateData()` calls.

- Supports `act` in testing library. ([#1182](https://github.com/lynx-family/lynx-stack/pull/1182))

  ```js
  import { act } from '@lynx-js/react/testing-library';

  act(() => {
    // ...
  });
  ```

## 0.110.1

### Patch Changes

- Fix a memory leak when using `<list/>`. ([#1144](https://github.com/lynx-family/lynx-stack/pull/1144))

## 0.110.0

### Minor Changes

- Fixed closure variable capture issue in effect hooks to prevent stale values and ensured proper execution order between refs, effects, and event handlers. ([#770](https://github.com/lynx-family/lynx-stack/pull/770))

  **Breaking Changes**:

  - The execution timing of `ref`, `useEffect()` callback, `componentDidMount`, `componentDidUpdate`, `componentWillUnmount` and the callback of `setState` have been moved forward. These effects will now execute before hydration is complete, rather than waiting for the main thread update to complete.
  - For components inside `<list />`, `ref` callbacks will now be triggered during background thread rendering, regardless of component visibility. If your code depends on component visibility timing, use `main-thread:ref` instead of regular `ref`.

### Patch Changes

- Fixed two memory leaks: ([#1071](https://github.com/lynx-family/lynx-stack/pull/1071))

  1. When JSX is rendered on the main thread and removed, FiberElement can still be referenced by `__root.__jsx` through `props.children`;

  2. When the SnapshotInstance tree is removed from the root node, its child nodes form a cycle reference because the `__previousSibling` and `__nextSibling` properties point to each other, thus causing a FiberElement leak.

- Optimize the error message when snapshots cannot be found in the main thread. ([#1083](https://github.com/lynx-family/lynx-stack/pull/1083))

- Fix a problem causing `MainThreadRef`s to not be updated correctly during hydration when they are set to `main-thread:ref`s. ([#1001](https://github.com/lynx-family/lynx-stack/pull/1001))

- Add snapshot id report when throwing `snapshotPatchApply failed: ctx not found` error. ([#1107](https://github.com/lynx-family/lynx-stack/pull/1107))

- Fix a bug in ReactLynx Testing Library that rendered snapshot of inline style was normalized incorrectly (eg. `flex:1` was normalized to `flex: 1 1 0%;` incorrectly). ([#1040](https://github.com/lynx-family/lynx-stack/pull/1040))

## 0.109.2

### Patch Changes

- Support for locating errors in the source code directly on the device when exceptions occur when using MTS. ([#1019](https://github.com/lynx-family/lynx-stack/pull/1019))

  This requires Lynx engine v3.4 or later.

- Fix the "main-thread.js exception: ReferenceError: `__webpack_require__` is not defined" error in HMR. ([#985](https://github.com/lynx-family/lynx-stack/pull/985))

  This error occurred when setting `output.iife: true`, which is the default value in `@lynx-js/rspeedy` v0.9.8.

## 0.109.1

### Patch Changes

- Support the 'main-thread' directive as an alias for 'main thread'. ([#970](https://github.com/lynx-family/lynx-stack/pull/970))

- Reduce calls to `__AddInlineStyle` by pass non-literal object directly to `__SetInlineStyles`. ([#941](https://github.com/lynx-family/lynx-stack/pull/941))

## 0.109.0

### Minor Changes

- Support MTS functions running on the first screen. ([#840](https://github.com/lynx-family/lynx-stack/pull/840))

### Patch Changes

- Fix type error when using `Suspense` with `"jsx": "react-jsx"`. ([#854](https://github.com/lynx-family/lynx-stack/pull/854))

- Support lazy bundle in ReactLynx testing library. ([#869](https://github.com/lynx-family/lynx-stack/pull/869))

- Fix a bug in HMR that snapshots are always updated because the same unique ID check is not performed correctly. ([#869](https://github.com/lynx-family/lynx-stack/pull/869))

- Fix missing types of `key` on components when using `"jsx": "react-jsx"`. ([#872](https://github.com/lynx-family/lynx-stack/pull/872))

## 0.108.1

### Patch Changes

- Bump swc_core v23.2.0. ([#827](https://github.com/lynx-family/lynx-stack/pull/827))

## 0.108.0

### Minor Changes

- Reverts #239: "batch multiple patches for main thread communication" ([#649](https://github.com/lynx-family/lynx-stack/pull/649))

  This reverts the change that batched updates sent to the main thread in a single render pass.

### Patch Changes

- Add support for batch rendering in `<list>` with async resolution of sub-tree properties and element trees. ([#624](https://github.com/lynx-family/lynx-stack/pull/624))

  Use the `experimental-batch-render-strategy` attribute of `<list>`:

  ```tsx
  <list
    /**
     * Batch render strategy:
     * 0: (Default) Disabled - No batch rendering
     * 1: Basic - Only batch rendering enabled
     * 2: Property Resolution - Batch render with async property resolution for list item subtree
     * 3: Full Resolution - Batch render with async property and element tree resolution for list item subtree
     */
    experimental-batch-render-strategy={3}
  >
  </list>;
  ```

- rename @lynx-js/test-environment to @lynx-js/testing-environment ([#704](https://github.com/lynx-family/lynx-stack/pull/704))

- Auto import `@lynx-js/react/experimental/lazy/import` when using `import(url)` ([#667](https://github.com/lynx-family/lynx-stack/pull/667))

- Auto import `@lynx-js/react/experimental/lazy/import` when using `<component is={url} />` ([#666](https://github.com/lynx-family/lynx-stack/pull/666))

- Fixed a race condition when updating states and GlobalProps simultaneously. ([#707](https://github.com/lynx-family/lynx-stack/pull/707))

  This fix prevents the "Attempt to render more than one `<page />`" error from occurring during normal application usage.

- Fix error like `Unterminated string constant` when using multi-line JSX StringLiteral. ([#654](https://github.com/lynx-family/lynx-stack/pull/654))

## 0.107.1

### Patch Changes

- Fix error `OnPipelineStart arg count must == 1` on app load. ([#669](https://github.com/lynx-family/lynx-stack/pull/669))

## 0.107.0

### Minor Changes

- Some of the timing keys are renamed to match the naming convention of the Lynx Engine. ([#438](https://github.com/lynx-family/lynx-stack/pull/438))

  - `update_set_state_trigger` -> `updateSetStateTrigger`
  - `update_diff_vdom_start` -> `updateDiffVdomStart`
  - `update_diff_vdom_end` -> `updateDiffVdomEnd`
  - `diff_vdom_start` -> `diffVdomStart`
  - `diff_vdom_end` -> `diffVdomEnd`
  - `pack_changes_start` -> `packChangesStart`
  - `pack_changes_end` -> `packChangesEnd`
  - `parse_changes_start` -> `parseChangesStart`
  - `parse_changes_end` -> `parseChangesEnd`
  - `patch_changes_start` -> `patchChangesStart`
  - `patch_changes_end` -> `patchChangesEnd`
  - `hydrate_parse_snapshot_start` -> `hydrateParseSnapshotStart`
  - `hydrate_parse_snapshot_end` -> `hydrateParseSnapshotEnd`
  - `mts_render_start` -> `mtsRenderStart`
  - `mts_render_end` -> `mtsRenderEnd`

### Patch Changes

- Add testing library for ReactLynx ([#74](https://github.com/lynx-family/lynx-stack/pull/74))

- Refactor: Improved naming for list operation related types. Renamed `UpdateAction` interface to `ListOperations`. ([#592](https://github.com/lynx-family/lynx-stack/pull/592))

- Support using `"jsx": "react-jsx"` along with `"jsxImportSource": "@lynx-js/react"` in `tsconfig.json`. ([#545](https://github.com/lynx-family/lynx-stack/pull/545))

  ```json
  {
    "compilerOptions": {
      "jsx": "react-jsx",
      "jsxImportSource": "@lynx-js/react"
    }
  }
  ```

  This configuration enhances TypeScript definitions for standard JSX elements,
  providing type errors for unsupported elements like `<div>` or `<button>`.

- fix: JSX elements with dynamic `key={expr}` now wrapped in `wrapper` element to prevent merging. ([#547](https://github.com/lynx-family/lynx-stack/pull/547))

## 0.106.5

### Patch Changes

- Fix `lynx.loadLazyBundle` is not a function ([#568](https://github.com/lynx-family/lynx-stack/pull/568))

- fix: flushDelayedLifecycleEvents stack overflow error ([#540](https://github.com/lynx-family/lynx-stack/pull/540))

## 0.106.4

### Patch Changes

- Disable MTS HMR functionality temporarily to address stability issues. This is a temporary fix while we work on a more robust solution. ([#512](https://github.com/lynx-family/lynx-stack/pull/512))

## 0.106.3

### Patch Changes

- Do some global var initialize in hydrate, which fixes error like `cannot read property '-21' of undefined` and some style issue. ([#461](https://github.com/lynx-family/lynx-stack/pull/461))

- fix: ensure ref lifecycle events run after firstScreen in the background thread ([#434](https://github.com/lynx-family/lynx-stack/pull/434))

  This patch fixes an issue where ref lifecycle events were running before firstScreen events in the background thread async render mode, which could cause refs to be undefined when components try to access them.

## 0.106.2

### Patch Changes

- fix: prevent multiple firstScreen events when reloading before `jsReady` ([#377](https://github.com/lynx-family/lynx-stack/pull/377))

- Optimize the bundle size by eliminating unnecessary code when the lazy bundle is not utilized. ([#284](https://github.com/lynx-family/lynx-stack/pull/284))

## 0.106.1

### Patch Changes

- Fix a stack underflow issue when running on PrimJS. ([#326](https://github.com/lynx-family/lynx-stack/pull/326))

## 0.106.0

### Minor Changes

- Improved rendering performance by batching updates sent to the main thread in a single render pass. This optimization reduces redundant layout operations on the main thread, accelerates rendering, and prevents screen flickering. ([#239](https://github.com/lynx-family/lynx-stack/pull/239))

  **BREAKING CHANGE**: This commit changes the behavior of Timing API. Previously, timing events were fired for each update individually. With the new batching mechanism, timing events related to the rendering pipeline will now be triggered once per render cycle rather than for each individual update, affecting applications that rely on the previous timing behavior.

### Patch Changes

- Add missing typing for `useErrorBoundary`. ([#263](https://github.com/lynx-family/lynx-stack/pull/263))

  You can now use `useErrorBoundary` it in TypeScript like this:

  ```tsx
  import { useErrorBoundary } from '@lynx-js/react';
  ```

- Modified the format of data sent from background threads to the main thread. ([#207](https://github.com/lynx-family/lynx-stack/pull/207))

- Support Lynx SSR. ([#60](https://github.com/lynx-family/lynx-stack/pull/60))

## 0.105.2

### Patch Changes

- Support new css properties: `offset-path` and `offset-distance` ([#152](https://github.com/lynx-family/lynx-stack/pull/152))

- Fix 'SystemInfo is not defined' error when using MTS and not importing anything manually from the react package. ([#172](https://github.com/lynx-family/lynx-stack/pull/172))

- Fix `not a function` error when using lazy bundle without MTS. ([#170](https://github.com/lynx-family/lynx-stack/pull/170))

- fix: gesture config not processed correctly ([#175](https://github.com/lynx-family/lynx-stack/pull/175))

  ```typescript
  const pan = Gesture.Pan().minDistance(100);
  ```

  After this commit, gesture config like `minDistance` should work as expected.

## 0.105.1

### Patch Changes

- Support NPM provenance. ([#30](https://github.com/lynx-family/lynx-stack/pull/30))

- feat: add compiler only version of addComponentElement, it does not support spread props but have no runtime overhead, use it by: ([#15](https://github.com/lynx-family/lynx-stack/pull/15))

  ```js
  pluginReactLynx({
    compat: {
      addComponentElement: {
        compilerOnly: true,
      },
    },
  });
  ```

- Fix error `createRef is not a function` ([#16](https://github.com/lynx-family/lynx-stack/pull/16))

- Support `MIXED` target for worklet, it will be used by unit testing frameworks, etc. ([#27](https://github.com/lynx-family/lynx-stack/pull/27))

- Support return value for `runOnBackground()` and `runOnMainThread()`. ([#119](https://github.com/lynx-family/lynx-stack/pull/119))

  Now you can get the return value from `runOnBackground()` and `runOnMainThread()`, which enables more flexible data flow between the main thread and the background thread.

  ```js
  import { runOnBackground } from '@lynx-js/react';

  const onTap = async () => {
    'main thread';
    const text = await runOnBackground(() => {
      'background only';
      return 'Hello, world!';
    })();
    console.log(text);
  };
  ```

## 0.105.0

### Minor Changes

- 1abf8f0: Support `estimated-main-axis-size-px`

  NOTE: This changes behavior of `transformReactLynx` so certain features (like lazy bundle) will be BROKEN if version mismatch.

- 1abf8f0: Support JSXSpread on `<list-item/>` component.

  NOTE: This changes behavior of `transformReactLynx` so certain features (like lazy bundle) will be BROKEN if version mismatch.

### Patch Changes

- 1abf8f0: Update readme.
- 1abf8f0: Save some bytes if `<page/>` is not used.
- 1abf8f0: Should escape newline character in jsx

## 0.104.1

### Patch Changes

- 9ce9ec0: Fix argument cannot be accessed correctly in default exported MTS functions.
- 99a4de6: Change TypeScript configuration to improve tree-shaking by setting `verbatimModuleSyntax: false`.

  This change allows the bundler to properly remove unused imports and type-only imports, resulting in smaller bundle sizes. For example:

  ```ts
  // These imports will be removed from the final bundle
  import type { Foo } from 'xyz';
  import { type Bar } from 'xyz';
  import { xyz } from 'xyz'; // When xyz is not used
  ```

  See [TypeScript - verbatimModuleSyntax](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) for details.

## 0.104.0

### Minor Changes

- 575e804: Remove misleading API `createRoot`

### Patch Changes

- 797ff68: Workaround the `cannot find module './snapshot/event.js'` error avoid tree-shaking `event.js` in development.
- 1bf9271: fix(react): default `compat` in transform to `false`

## 0.103.5

### Patch Changes

- 74e0ea3: Supports new `__MAIN_THREAD__` and `__BACKGROUND__` macro as an alternative to `__LEPUS__` and `__JS__`.

## 0.103.4

### Patch Changes

- 89a9f7a: Improve the speed of MTS.

## 0.103.3

### Patch Changes

- 4e94846: Fix variables being renamed in MTS.
- 297c6ea: Fix the issue that when `runOnBackground()`'s parameter is not legal, it will still report an error in the rendering process of the background thread even though it won't actually be called.

  ```tsx
  function App() {
    const f = undefined;

    function mts() {
      'main thread';
      // throws in background rendering
      f && runOnBackground(f)();
    }
  }
  ```

- 763ad4e: Stop reporting ctx id in the `ctx not found` error.
- 480611d: Avoid error from changing theme.
- 3bf5830: Avoid overriding `processEvalResult`.

## 0.103.2

### Patch Changes

- 580ce54: Fix snapshot not found in HMR updates.

## 0.103.1

### Patch Changes

- 80a4e38: Use hooks `useLynxGlobalEventListener` to make `useInitData` addListener as early as possible. This will fix the issue that `onDataChanged` has been called before the event listener is added.
- 8aa3979: Fix generating wrong JavaScript when using a variable multiple times in the main thread script.
- 318245e: Avoid snapshot ID conflict between different templates and bundles.
- b520862: Remove unnecessary sideEffects to reduce bundle size.
- 7cd840c: Integrate with `@lynx-js/types`.

## 0.103.0

### Minor Changes

- a30c83d: Add `compat.removeComponentAttrRegex`.

  ```js
  import { pluginReactLynx } from '@lynx-js/react-rsbuild-plugin';
  import { defineConfig } from '@lynx-js/rspeedy';

  export default defineConfig({
    plugins: [
      pluginReactLynx({
        compat: {
          removeComponentAttrRegex: 'YOUR REGEX',
        },
      }),
    ],
  });
  ```

  NOTE: This feature is deprecated and will be removed in the future. Use codemod instead.

- 5f8d492: Deprecate `compat.simplifyCtorLikeReactLynx2`

### Patch Changes

- ca3a639: Fix `cssId` collision issue when hash generated `@jsxCSSId` for jsx snapshot hit the range of auto increased cssId of `@file`.
- 8fbea78: Fix 'main thread' and 'background only' directives not working in export default declarations.
- ff18049: Bump swc_core v0.109.2.

  This would add `/*#__PURE__*/` to the output of TypeScript `enum`. See [swc-project/swc#9558](https://github.com/swc-project/swc/pull/9558) for details.

## 0.102.0

### Minor Changes

- e3be842: Fix some attribute updating of nodes in list does not take effect
- 2e6b549: Add ability to be compat with pre-0.99 version of ReactLynx

### Patch Changes

- 75725cb: Fix a memory leak in MTS.
- 09e0ec0: Reduce the size of `background.js`.
- 9e40f33: Slightly improve MTS execution speed.
- f24599e: Fix the infinite mount and unmount loops of lazy bundle when its JS file fails to execute.

## 0.101.0

### Minor Changes

- 6730c58: Change the snapshot transform result by adding `cssId` and `entryName`.

  <table>
    <thead>
      <tr>
        <th>Remove Scoped CSS(Default)</th>
        <th>Scoped CSS</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>
          <pre><code>
  createSnapshot(
    $uid,
    $create,
    $update,
    $slot,
    /** cssId */ undefined,
    /** entryName */ globDynamicComponentEntry
  );
          </code></pre>
        </td>
        <td>
          <pre><code>
  createSnapshot(
    $uid,
    $create,
    $update,
    $slot,
    /** cssId */ 0x3da39a,
    /** entryName */ globDynamicComponentEntry
  );
          </code></pre>
        </td>
      </tr>
    </tbody>
  </table>

  This requires `@lynx-js/react-rsbuild-plugin` v0.5.1 to work.

  - Inject `globDynamicComponentEntry` for background script. ([#311](https://github.com/lynx-wg/lynx-stack/pull/311))
  - Inject `globDynamicComponentEntry` for main thread script. ([#312](https://github.com/lynx-wg/lynx-stack/pull/312))

- efbb7d4: Support Gesture.

  Gesture Handler is a set of gesture handling capabilities built on top of the Main Thread Script. It currently supports drag, inertial scrolling, long press, and tap gestures for `<view>`, `<scroll-view>`, `<list>`, and `<text>`. In the future, it will also support multi-finger zoom, multi-finger rotation, and other gesture capabilities.

  ```tsx
  import { useGesture, PanGesture } from '@lynx-js/gesture-runtime';

  function App() {
    const pan = useGesture(PanGesture);

    pan
      .onBegin((event, stateManager) => {
        'main thread';
        // some logic
      })
      .onUpdate((event, stateManager) => {
        'main thread';
        // some logic
      })
      .onEnd((event, stateManager) => {
        'main thread';
        // some logic
      });

    return <view main-thread:gesture={pan}></view>;
  }
  ```

### Patch Changes

- b2032eb: Better DCE.

  Now DCE can remove dead branch:

  ```ts
  function f() {
    if (__LEPUS__) {
      return;
    }

    console.log('not __LEPUS__'); // This can be removed now
  }
  ```

- 45edafa: Support using `import()` with variables.

## 0.100.0

### Minor Changes

- 587a782: Release `@lynx-js/react` v0.100.0

### Patch Changes

- a335490: Fix an issue where events might not fire after calling `ReloadTemplate`.
