@lynx-js/react-canary 0.121.2-canary-20260617-bb7927bd → 0.121.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/CHANGELOG.md +62 -45
  2. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @lynx-js/react
2
2
 
3
- ## 0.121.2-canary-20260617035556-bb7927bdd9ccf5be6a0670538ca466770b320ee9
3
+ ## 0.121.2
4
4
 
5
5
  ### Patch Changes
6
6
 
@@ -9,13 +9,13 @@
9
9
  Previously, the compat transform could short-circuit while scanning opening attributes and treat:
10
10
 
11
11
  ```jsx
12
- <Component removeComponentElement={true} {...props} />
12
+ <Component removeComponentElement={true} {...props} />;
13
13
  ```
14
14
 
15
15
  differently from:
16
16
 
17
17
  ```jsx
18
- <Component {...props} removeComponentElement={true} />
18
+ <Component {...props} removeComponentElement={true} />;
19
19
  ```
20
20
 
21
21
  The transform now collects the full opening-attribute state first, so both prop orders compile the same way in normal and `compilerOnly` modes.
@@ -41,7 +41,7 @@
41
41
  - Support `React.createElement(type, props, children)` API. ([#2360](https://github.com/lynx-family/lynx-stack/pull/2360))
42
42
 
43
43
  ```jsx
44
- React.createElement("view", { style }, <text>hello</text>);
44
+ React.createElement('view', { style }, <text>hello</text>);
45
45
  // equivalent to
46
46
  <view style={style}>
47
47
  <text>hello</text>
@@ -103,6 +103,7 @@
103
103
  - 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))
104
104
 
105
105
  - fix: reduce redundant updates for main-thread handlers and gestures ([#2188](https://github.com/lynx-family/lynx-stack/pull/2188))
106
+
106
107
  - Updates are faster when the main-thread event handler or gesture object is stable across rerenders (fewer unnecessary native updates).
107
108
  - Spread props rerenders that don't semantically change the handler/gesture no longer trigger redundant updates.
108
109
  - Removing a gesture from spread props reliably clears the gesture state on the target element.
@@ -122,6 +123,7 @@
122
123
  - Remove stale gestures when gestures are removed ([#2297](https://github.com/lynx-family/lynx-stack/pull/2297))
123
124
 
124
125
  - Trace refactor ([#2466](https://github.com/lynx-family/lynx-stack/pull/2466))
126
+
125
127
  - Remove `ReactLynx::renderOpcodes` from the trace
126
128
  - Use `ReactLynx::transferRoot` to measure the time spent transferring the root to the background thread
127
129
 
@@ -132,8 +134,8 @@
132
134
  Create a config file `rstest.config.ts` with the following content:
133
135
 
134
136
  ```ts
135
- import { defineConfig } from "@rstest/core";
136
- import { withLynxConfig } from "@lynx-js/react/testing-library/rstest-config";
137
+ import { defineConfig } from '@rstest/core';
138
+ import { withLynxConfig } from '@lynx-js/react/testing-library/rstest-config';
137
139
 
138
140
  export default defineConfig({
139
141
  extends: withLynxConfig(),
@@ -183,6 +185,7 @@
183
185
  ### Minor Changes
184
186
 
185
187
  - feat: export `GlobalPropsProvider`, `GlobalPropsConsumer`, `useGlobalProps` and `useGlobalPropsChanged` for `__globalProps` ([#2346](https://github.com/lynx-family/lynx-stack/pull/2346))
188
+
186
189
  - `GlobalPropsProvider`: A Provider component that accepts `children`. It is used to provide the `lynx.__globalProps` context.
187
190
  - `GlobalPropsConsumer`: A Consumer component that accepts a function as a child. It is used to consume the `lynx.__globalProps` context.
188
191
  - `useGlobalProps`: A hook that returns the `lynx.__globalProps` object. It triggers a re-render when `lynx.__globalProps` changes.
@@ -197,6 +200,7 @@
197
200
  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).
198
201
 
199
202
  - feat: add `globalPropsMode` option to `PluginReactLynxOptions` ([#2346](https://github.com/lynx-family/lynx-stack/pull/2346))
203
+
200
204
  - When configured to `"event"`, `updateGlobalProps` will only trigger a global event and skip the `runWithForce` flow.
201
205
  - Defaults to `"reactive"`, which means `updateGlobalProps` will trigger re-render automatically.
202
206
 
@@ -216,6 +220,7 @@
216
220
 
217
221
  - Improve React runtime hook profiling. ([#2235](https://github.com/lynx-family/lynx-stack/pull/2235))
218
222
  Enable Profiling recording first, then enter the target page so the trace includes full render/hydrate phases.
223
+
219
224
  - Record trace events for `useEffect` / `useLayoutEffect` hook entry, callback, and cleanup phases.
220
225
  - Log trace events for `useState` setter calls.
221
226
  - Wire `profileFlowId` support in debug profile utilities and attach flow IDs to related hook traces.
@@ -264,6 +269,7 @@
264
269
  - Bump `swc_core` v56. ([#2154](https://github.com/lynx-family/lynx-stack/pull/2154))
265
270
 
266
271
  - Use `disableDeprecatedWarning` option to suppress BROKEN warnings during compilation. ([#2157](https://github.com/lynx-family/lynx-stack/pull/2157))
272
+
267
273
  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.
268
274
  2. BROKEN: `getElementById` on component instance is broken and MUST be migrated in ReactLynx 3.0, please use ref or lynx.getElementById instead.
269
275
 
@@ -301,9 +307,9 @@
301
307
 
302
308
  ```typescript
303
309
  function getStyle(ele: MainThread.Element) {
304
- "main thread";
305
- const width = ele.getComputedStyleProperty("width"); // Returns 300px
306
- const transformMatrix = ele.getComputedStyleProperty("transform"); // Returns matrix(2, 0, 0, 2, 200, 400)
310
+ 'main thread';
311
+ const width = ele.getComputedStyleProperty('width'); // Returns 300px
312
+ const transformMatrix = ele.getComputedStyleProperty('transform'); // Returns matrix(2, 0, 0, 2, 200, 400)
307
313
  }
308
314
  ```
309
315
 
@@ -318,7 +324,7 @@
318
324
  ```ts
319
325
  const LazyComponent = lazy(async () => {
320
326
  try {
321
- const mod = await import("./lazy-bundle");
327
+ const mod = await import('./lazy-bundle');
322
328
  return mod.default;
323
329
  } catch (error) {
324
330
  console.error(`Lazy Bundle load failed message: ${error.message}`);
@@ -346,13 +352,14 @@
346
352
  - Auto define lynx.loadLazyBundle when using `import(/* relative path */)`. ([#1956](https://github.com/lynx-family/lynx-stack/pull/1956))
347
353
 
348
354
  - 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))
355
+
349
356
  - Usage: Add `with { runtime: "shared" }` to the `import` statement. For example:
350
357
 
351
358
  ```ts
352
- import { func } from "./utils.js" with { runtime: "shared" };
359
+ import { func } from './utils.js' with { runtime: 'shared' };
353
360
 
354
361
  function worklet() {
355
- "main thread";
362
+ 'main thread';
356
363
  func(); // callable inside a main thread function
357
364
  }
358
365
  ```
@@ -368,11 +375,13 @@
368
375
  - **BREAKING CHANGE**: Delay the `createSnapshot` operation to `Snapshot` constructor to speed up IFR. ([#1899](https://github.com/lynx-family/lynx-stack/pull/1899))
369
376
 
370
377
  This change refactors how snapshots are created and registered:
378
+
371
379
  - Removed the `entryUniqID` function
372
380
  - Snapshots are now lazily created via `snapshotCreatorMap` instead of eagerly at bundle load time
373
381
  - Snapshot IDs are generated at compile time and only prefixed with `${globDynamicComponentEntry}:` for standalone lazy bundles
374
382
 
375
383
  **⚠️ Lazy Bundle Compatibility:**
384
+
376
385
  - **Backward compatibility (new runtime → old lazy bundles)**: ✅ **Supported**. Old lazy bundles will work with the new runtime.
377
386
 
378
387
  - **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.
@@ -427,11 +436,11 @@
427
436
  - 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))
428
437
 
429
438
  ```js
430
- import { defineConfig, mergeConfig } from "vitest/config";
431
- import { createVitestConfig } from "@lynx-js/react/testing-library/vitest-config";
439
+ import { defineConfig, mergeConfig } from 'vitest/config';
440
+ import { createVitestConfig } from '@lynx-js/react/testing-library/vitest-config';
432
441
 
433
442
  const defaultConfig = await createVitestConfig({
434
- runtimePkgName: "@lynx-js/react",
443
+ runtimePkgName: '@lynx-js/react',
435
444
  experimental_enableReactCompiler: true,
436
445
  });
437
446
 
@@ -461,7 +470,7 @@
461
470
  ```tsx
462
471
  function App() {
463
472
  function handleInnerTap(event: MainThread.TouchEvent) {
464
- "main thread";
473
+ 'main thread';
465
474
  event.stopPropagation();
466
475
  // Or stop immediate propagation with
467
476
  // event.stopImmediatePropagation();
@@ -559,10 +568,10 @@
559
568
  - 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))
560
569
 
561
570
  ```ts
562
- import type { MainThread } from "@lynx-js/types";
571
+ import type { MainThread } from '@lynx-js/types';
563
572
 
564
573
  function startAnimation(ele: MainThread.Element) {
565
- "main thread";
574
+ 'main thread';
566
575
  const animation = ele.animate([{ opacity: 0 }, { opacity: 1 }], {
567
576
  duration: 3000,
568
577
  });
@@ -591,12 +600,13 @@
591
600
  - 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))
592
601
 
593
602
  ```jsx
594
- <list-item recyclable={false} />
603
+ <list-item recyclable={false} />;
595
604
  ```
596
605
 
597
606
  - feat: Support using a host element as direct child of Suspense ([#1455](https://github.com/lynx-family/lynx-stack/pull/1455))
598
607
 
599
608
  - Add profile in production build: ([#1336](https://github.com/lynx-family/lynx-stack/pull/1336))
609
+
600
610
  1. `diff:__COMPONENT_NAME__`: how long ReactLynx diff took.
601
611
  2. `render:__COMPONENT_NAME__`: how long your render function took.
602
612
  3. `setState`: an instant trace event, indicate when your setState was called.
@@ -611,7 +621,7 @@
611
621
 
612
622
  ```ts
613
623
  function handleTap() {
614
- "main thread";
624
+ 'main thread';
615
625
  // The following check always returned false before this fix
616
626
  if (myHandleTap) {
617
627
  runOnBackground(myHandleTap)();
@@ -634,6 +644,7 @@
634
644
  - feat: Force synchronous rendering for background initial renders to support Suspense fallbacks ([#1323](https://github.com/lynx-family/lynx-stack/pull/1323))
635
645
 
636
646
  - Introduces `@lynx-js/react/compat` submodule exporting Preact implementations of: ([#1316](https://github.com/lynx-family/lynx-stack/pull/1316))
647
+
637
648
  - `startTransition`
638
649
  - `useTransition`
639
650
 
@@ -671,10 +682,10 @@
671
682
  Add the import to `@lynx-js/react/debug` at the first line of the entry:
672
683
 
673
684
  ```js
674
- import "@lynx-js/react/debug";
675
- import { root } from "@lynx-js/react";
685
+ import '@lynx-js/react/debug';
686
+ import { root } from '@lynx-js/react';
676
687
 
677
- import { App } from "./App.jsx";
688
+ import { App } from './App.jsx';
678
689
 
679
690
  root.render(<App />);
680
691
  ```
@@ -684,9 +695,9 @@
684
695
  For example, you can use it like this:
685
696
 
686
697
  ```jsx
687
- <list-item defer={{ unmountRecycled: true }} item-key="1">
698
+ <list-item defer={{ unmountRecycled: true }} item-key='1'>
688
699
  <WillBeUnmountIfRecycled />
689
- </list-item>
700
+ </list-item>;
690
701
  ```
691
702
 
692
703
  Now the component will be unmounted when it is recycled, which can help with performance in certain scenarios.
@@ -694,7 +705,7 @@
694
705
  - 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))
695
706
 
696
707
  ```jsx
697
- <image async-mode={undefined} />
708
+ <image async-mode={undefined} />;
698
709
  ```
699
710
 
700
711
  ## 0.111.1
@@ -733,13 +744,14 @@
733
744
  - 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))
734
745
 
735
746
  Notice:
747
+
736
748
  - Even if no data changes are actually processed after calling `updateData()`, the `lynxViewDidUpdate` callback will still be triggered.
737
749
  - 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.
738
750
 
739
751
  - Supports `act` in testing library. ([#1182](https://github.com/lynx-family/lynx-stack/pull/1182))
740
752
 
741
753
  ```js
742
- import { act } from "@lynx-js/react/testing-library";
754
+ import { act } from '@lynx-js/react/testing-library';
743
755
 
744
756
  act(() => {
745
757
  // ...
@@ -759,12 +771,14 @@
759
771
  - 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))
760
772
 
761
773
  **Breaking Changes**:
774
+
762
775
  - 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.
763
776
  - 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`.
764
777
 
765
778
  ### Patch Changes
766
779
 
767
780
  - Fixed two memory leaks: ([#1071](https://github.com/lynx-family/lynx-stack/pull/1071))
781
+
768
782
  1. When JSX is rendered on the main thread and removed, FiberElement can still be referenced by `__root.__jsx` through `props.children`;
769
783
 
770
784
  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.
@@ -843,7 +857,8 @@
843
857
  * 3: Full Resolution - Batch render with async property and element tree resolution for list item subtree
844
858
  */
845
859
  experimental-batch-render-strategy={3}
846
- ></list>
860
+ >
861
+ </list>;
847
862
  ```
848
863
 
849
864
  - rename @lynx-js/test-environment to @lynx-js/testing-environment ([#704](https://github.com/lynx-family/lynx-stack/pull/704))
@@ -869,6 +884,7 @@
869
884
  ### Minor Changes
870
885
 
871
886
  - 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))
887
+
872
888
  - `update_set_state_trigger` -> `updateSetStateTrigger`
873
889
  - `update_diff_vdom_start` -> `updateDiffVdomStart`
874
890
  - `update_diff_vdom_end` -> `updateDiffVdomEnd`
@@ -960,7 +976,7 @@
960
976
  You can now use `useErrorBoundary` it in TypeScript like this:
961
977
 
962
978
  ```tsx
963
- import { useErrorBoundary } from "@lynx-js/react";
979
+ import { useErrorBoundary } from '@lynx-js/react';
964
980
  ```
965
981
 
966
982
  - Modified the format of data sent from background threads to the main thread. ([#207](https://github.com/lynx-family/lynx-stack/pull/207))
@@ -1012,13 +1028,13 @@
1012
1028
  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.
1013
1029
 
1014
1030
  ```js
1015
- import { runOnBackground } from "@lynx-js/react";
1031
+ import { runOnBackground } from '@lynx-js/react';
1016
1032
 
1017
1033
  const onTap = async () => {
1018
- "main thread";
1034
+ 'main thread';
1019
1035
  const text = await runOnBackground(() => {
1020
- "background only";
1021
- return "Hello, world!";
1036
+ 'background only';
1037
+ return 'Hello, world!';
1022
1038
  })();
1023
1039
  console.log(text);
1024
1040
  };
@@ -1053,9 +1069,9 @@
1053
1069
 
1054
1070
  ```ts
1055
1071
  // These imports will be removed from the final bundle
1056
- import type { Foo } from "xyz";
1057
- import { type Bar } from "xyz";
1058
- import { xyz } from "xyz"; // When xyz is not used
1072
+ import type { Foo } from 'xyz';
1073
+ import { type Bar } from 'xyz';
1074
+ import { xyz } from 'xyz'; // When xyz is not used
1059
1075
  ```
1060
1076
 
1061
1077
  See [TypeScript - verbatimModuleSyntax](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) for details.
@@ -1095,7 +1111,7 @@
1095
1111
  const f = undefined;
1096
1112
 
1097
1113
  function mts() {
1098
- "main thread";
1114
+ 'main thread';
1099
1115
  // throws in background rendering
1100
1116
  f && runOnBackground(f)();
1101
1117
  }
@@ -1129,14 +1145,14 @@
1129
1145
  - a30c83d: Add `compat.removeComponentAttrRegex`.
1130
1146
 
1131
1147
  ```js
1132
- import { pluginReactLynx } from "@lynx-js/react-rsbuild-plugin";
1133
- import { defineConfig } from "@lynx-js/rspeedy";
1148
+ import { pluginReactLynx } from '@lynx-js/react-rsbuild-plugin';
1149
+ import { defineConfig } from '@lynx-js/rspeedy';
1134
1150
 
1135
1151
  export default defineConfig({
1136
1152
  plugins: [
1137
1153
  pluginReactLynx({
1138
1154
  compat: {
1139
- removeComponentAttrRegex: "YOUR REGEX",
1155
+ removeComponentAttrRegex: 'YOUR REGEX',
1140
1156
  },
1141
1157
  }),
1142
1158
  ],
@@ -1213,6 +1229,7 @@
1213
1229
  </table>
1214
1230
 
1215
1231
  This requires `@lynx-js/react-rsbuild-plugin` v0.5.1 to work.
1232
+
1216
1233
  - Inject `globDynamicComponentEntry` for background script. ([#311](https://github.com/lynx-wg/lynx-stack/pull/311))
1217
1234
  - Inject `globDynamicComponentEntry` for main thread script. ([#312](https://github.com/lynx-wg/lynx-stack/pull/312))
1218
1235
 
@@ -1221,22 +1238,22 @@
1221
1238
  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.
1222
1239
 
1223
1240
  ```tsx
1224
- import { useGesture, PanGesture } from "@lynx-js/gesture-runtime";
1241
+ import { useGesture, PanGesture } from '@lynx-js/gesture-runtime';
1225
1242
 
1226
1243
  function App() {
1227
1244
  const pan = useGesture(PanGesture);
1228
1245
 
1229
1246
  pan
1230
1247
  .onBegin((event, stateManager) => {
1231
- "main thread";
1248
+ 'main thread';
1232
1249
  // some logic
1233
1250
  })
1234
1251
  .onUpdate((event, stateManager) => {
1235
- "main thread";
1252
+ 'main thread';
1236
1253
  // some logic
1237
1254
  })
1238
1255
  .onEnd((event, stateManager) => {
1239
- "main thread";
1256
+ 'main thread';
1240
1257
  // some logic
1241
1258
  });
1242
1259
 
@@ -1256,7 +1273,7 @@
1256
1273
  return;
1257
1274
  }
1258
1275
 
1259
- console.log("not __LEPUS__"); // This can be removed now
1276
+ console.log('not __LEPUS__'); // This can be removed now
1260
1277
  }
1261
1278
  ```
1262
1279
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lynx-js/react-canary",
3
- "version": "0.121.2-canary-20260617-bb7927bd",
3
+ "version": "0.121.2",
4
4
  "description": "ReactLynx is a framework for developing Lynx applications with familiar React.",
5
5
  "repository": {
6
6
  "type": "git",