Skip to content

feat: add dual-thread commutation logs#2081

Merged
upupming merged 4 commits intomainfrom
feat/dual-thread-alog
Jan 4, 2026
Merged

feat: add dual-thread commutation logs#2081
upupming merged 4 commits intomainfrom
feat/dual-thread-alog

Conversation

@upupming
Copy link
Collaborator

@upupming upupming commented Dec 30, 2025

close #2045

An example log from our examples/react package is as below.

First screen:

Details
[BackgroundThread Component Render] name: Fragment, uniqID: undefined, __id: undefined
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #1: __CreatePage("0", 0) => page#10
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #2: __GetElementUniqueID(page#10) => 10
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #3: __SetCSSId([page#10], 0)
main-thread.js:3460 [MainThread Component Render] name: App
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #4: __CreateView(10) => view#11
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #5: __CreateView(10) => view#12
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #6: __SetClasses(view#12, "Background")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #7: __AppendElement(view#11, view#12) => view#12
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #8: __CreateView(10) => view#13
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #9: __SetClasses(view#13, "App")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #10: __AppendElement(view#11, view#13) => view#13
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #11: __CreateView(10) => view#14
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #12: __SetClasses(view#14, "Banner")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #13: __AppendElement(view#13, view#14) => view#14
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #14: __CreateWrapperElement(10) => wrapper#15
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #15: __AppendElement(view#14, wrapper#15) => wrapper#15
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #16: __CreateText(10) => text#16
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #17: __SetClasses(text#16, "Title")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #18: __SetAttribute(text#16, "text", "React")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #19: __AppendElement(view#14, text#16) => text#16
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #20: __CreateText(10) => text#17
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #21: __SetClasses(text#17, "Subtitle")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #22: __SetAttribute(text#17, "text", "on Lynx")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #23: __AppendElement(view#14, text#17) => text#17
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #24: __CreateView(10) => view#18
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #25: __SetClasses(view#18, "Content")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #26: __AppendElement(view#13, view#18) => view#18
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #27: __CreateImage(10) => image#19
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #28: __SetClasses(image#19, "Arrow")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #29: __AppendElement(view#18, image#19) => image#19
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #30: __CreateText(10) => text#20
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #31: __SetClasses(text#20, "Description")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #32: __SetAttribute(text#20, "text", "Tap the logo and have fun!")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #33: __AppendElement(view#18, text#20) => text#20
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #34: __CreateText(10) => text#21
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #35: __SetClasses(text#21, "Hint")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #36: __AppendElement(view#18, text#21) => text#21
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #37: __CreateRawText("Edit") => raw-text#22
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #38: __AppendElement(text#21, raw-text#22) => raw-text#22
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #39: __CreateWrapperElement(10) => wrapper#23
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #40: __AppendElement(text#21, wrapper#23) => wrapper#23
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #41: __CreateRawText("to see updates!") => raw-text#24
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #42: __AppendElement(text#21, raw-text#24) => raw-text#24
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #43: __CreateView(10) => view#25
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #44: __SetInlineStyles(view#25, "flex:1")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #45: __AppendElement(view#13, view#25) => view#25
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #46: __AppendElement(page#10, view#11) => view#11
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #47: __SetAttribute(image#19, "src", "http://1.1.1.1:3000/static/image/arrow.aee54ba7.png")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #48: __CreateView(10) => view#26
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #49: __SetClasses(view#26, "Logo")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #50: __ReplaceElement(view#26, wrapper#15)
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #51: __AddEvent(view#26, "bindEvent", "tap", "-3:0:")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #52: __CreateImage(10) => image#27
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #53: __SetClasses(image#27, "Logo--lynx")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #54: __AppendElement(view#26, image#27) => image#27
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #55: __SetAttribute(image#27, "src", "http://1.1.1.1:3000/static/image/lynx-logo.620eb8d1.png")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #56: __CreateText(10) => text#28
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #57: __SetInlineStyles(text#28, "font-style:italic;color:rgba(255, 255, 255, 0.85)")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #58: __ReplaceElement(text#28, wrapper#23)
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #59: __CreateRawText("") => raw-text#29
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #60: __SetAttribute(raw-text#29, "text", " src/App.tsx ")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #61: __AppendElement(text#28, raw-text#29) => raw-text#29
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #62: __OnLifecycleEvent(["rLynxFirstScreen", {"root":"{\"id\":-1,\"type\":\"root\",\"children\":[{\"id\":-5,\"type\":\"__snapshot_835da_b8ae7_1\",\"values\":[\"http://1.1.1.1:3000/static/image/arrow.aee54ba7.png\"],\"children\":[{\"id\":-3,\"type\":\"__snapshot_835da_b8ae7_2\",\"values\":[\"-3:0:\"],\"children\":[{\"id\":-2,\"type\":\"__snapshot_835da_b8ae7_4\",\"values\":[\"http://1.1.1.1:3000/static/image/lynx-logo.620eb8d1.png\"]}]},{\"id\":-4,\"type\":\"__snapshot_835da_b8ae7_5\",\"children\":[{\"id\":-6,\"type\":null,\"values\":[\" src/App.tsx \"]}]}]}]}","jsReadyEventIdSwap":{}}])
background.js:11351 [rspeedy-dev-server] Server started: Hot Module Replacement enabled, Live Reloading enabled, Progress disabled, Overlay disabled.
background.js:3564 [HMR] Waiting for update signal from WDS...
background.js:4476 [BackgroundThread Component Render] name: App, uniqID: __snapshot_835da_b8ae7_1, __id: 2
background.js:4476 [BackgroundThread Component Render] name: Fragment, uniqID: __snapshot_835da_b8ae7_1, __id: 2
background.js:214 Hello, ReactLynx
background.js:8011 [ReactLynxDebug] MTS -> BTS OnLifecycleEvent:
{
  "root": {
    "id": -1,
    "type": "root",
    "children": [
      {
        "id": -5,
        "type": "__snapshot_835da_b8ae7_1",
        "values": [
          "http://1.1.1.1:3000/static/image/arrow.aee54ba7.png"
        ],
        "children": [
          {
            "id": -3,
            "type": "__snapshot_835da_b8ae7_2",
            "values": [
              "-3:0:"
            ],
            "children": [
              {
                "id": -2,
                "type": "__snapshot_835da_b8ae7_4",
                "values": [
                  "http://1.1.1.1:3000/static/image/lynx-logo.620eb8d1.png"
                ]
              }
            ]
          },
          {
            "id": -4,
            "type": "__snapshot_835da_b8ae7_5",
            "children": [
              {
                "id": -6,
                "type": null,
                "values": [
                  " src/App.tsx "
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  "jsReadyEventIdSwap": {}
}
main-thread.js:5801 [ReactLynxDebug] BTS -> MTS updateMainThread:
{
  "data": {
    "patchList": [
      {
        "snapshotPatch": [],
        "id": 2
      }
    ]
  },
  "patchOptions": {
    "isHydration": true,
    "reloadVersion": 0,
    "pipelineOptions": {
      "pipelineID": "0x16c567000_29",
      "needTimestamps": true,
      "pipelineOrigin": "reactLynxHydrate",
      "dsl": "reactLynx",
      "stage": "hydrate"
    }
  }
}
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #63: __FlushElementTree(page#10, {"pipelineOptions":{"pipelineID":"0x16c567000_29","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})

Next update:

Details
[BackgroundThread Component Render] name: App, uniqID: __snapshot_835da_b8ae7_1, __id: -5
main-thread.js:5801 [ReactLynxDebug] BTS -> MTS updateMainThread:
{
  "data": {
    "patchList": [
      {
        "id": 3,
        "snapshotPatch": [
          {
            "op": "RemoveChild",
            "parentId": -3,
            "childId": -2
          },
          {
            "op": "CreateElement",
            "type": "__snapshot_835da_b8ae7_3",
            "id": 7
          },
          {
            "op": "SetAttributes",
            "id": 7,
            "values": [
              "http://1.1.1.1:3000/static/image/react-logo.75eb3837.png"
            ]
          },
          {
            "op": "InsertBefore",
            "parentId": -3,
            "childId": 7,
            "beforeId": null
          }
        ]
      }
    ]
  },
  "patchOptions": {
    "reloadVersion": 0,
    "pipelineOptions": {
      "pipelineID": "0x16c567000_30",
      "needTimestamps": false,
      "pipelineOrigin": "updateTriggeredByBts",
      "dsl": "reactLynx",
      "stage": "update"
    }
  }
}
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #64: __RemoveElement(view#26, image#27) => image#27
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #65: __CreateImage(10) => image#30
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #66: __SetClasses(image#30, "Logo--react")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #67: __SetAttribute(image#30, "src", "http://1.1.1.1:3000/static/image/react-logo.75eb3837.png")
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #68: __AppendElement(view#26, image#30) => image#30
main-thread.js:3421 [ReactLynxDebug] FiberElement API call #69: __FlushElementTree(page#10, {"pipelineOptions":{"pipelineID":"0x16c567000_30","needTimestamps":false,"pipelineOrigin":"updateTriggeredByBts","dsl":"reactLynx","stage":"update"}})

Summary by CodeRabbit

  • New Features
    • Enhanced debug logging: structured, dual-thread API-call, lifecycle and hydration traces when debug mode is enabled.
  • Tests
    • Added and expanded tests and snapshots to validate richer logging, API-call sequences, and hydration traces.
  • Chores
    • Development-only error messages now include a troubleshooting hint recommending the debug-mode option for easier diagnosis.

✏️ Tip: You can customize this high-level summary in your review settings.

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).
  • Changeset added, and when a BREAKING CHANGE occurs, it needs to be clearly marked (or not required).

@upupming upupming requested review from HuJean and hzy as code owners December 30, 2025 09:52
@changeset-bot
Copy link

changeset-bot bot commented Dec 30, 2025

🦋 Changeset detected

Latest commit: 0878692

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@lynx-js/react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 30, 2025

📝 Walkthrough

Walkthrough

Adds element-level FiberElement API instrumentation that logs structured console.alog entries, wires it into alog initialization and test setup, expands tests/snapshots to expect the logs, and appends dev-only troubleshooting hints to certain patch/snapshot error messages; also adds guarded pretty-printed patch/hydration logging.

Changes

Cohort / File(s) Summary
Changeset Documentation
.changeset/cruel-feet-grow.md
New changeset documenting dual-thread commutation logging gated by REACT_ALOG / global __ALOG__.
Element API Call Instrumentation
packages/react/runtime/src/alog/elementPAPICall.ts
New module exporting initElementPAPICallAlog() which wraps global FiberElement APIs, tracks element identities, formats args/results, emits structured console.alog entries and optional profiling marks.
Alog Integration
packages/react/runtime/src/alog/index.ts
Imports and invokes initElementPAPICallAlog() from initAlog().
Test Global Setup
packages/react/testing-library/src/vitest-global-setup.js
Calls initElementPAPICallAlog(target) during main-thread global setup for tests.
Element API Logging Tests
packages/react/runtime/__test__/alog/elementPAPICall.test.js
New Vitest test that mocks console.alog, exercises element APIs, and asserts exact API-call log sequence via inline snapshot.
Alog Snapshot Expansions
packages/react/testing-library/src/__tests__/alog.test.jsx, packages/react/testing-library/src/__tests__/lynx.test.jsx
Expanded inline snapshots to include extensive FiberElement API call logs and updated error snapshots with troubleshooting hint.
Patch & Hydration Logging
packages/react/runtime/src/lifecycle/patch/updateMainThread.ts, packages/react/runtime/src/lynx/tt.ts
Added guarded __ALOG__ logging that pretty-prints parsed patch/snapshot data during patch processing and first-screen hydration paths.
Error Message Hinting
packages/react/runtime/src/lifecycle/patch/error.ts, packages/react/runtime/src/snapshot.ts
Dev-only troubleshooting hint appended to certain error messages recommending REACT_ALOG=true.
Snapshot Test Updates
packages/react/runtime/__test__/snapshotPatch.test.jsx
Updated snapshots to include the appended troubleshooting hint in error messages.
Debug Printing Utilities
packages/react/runtime/src/debug/printSnapshot.ts
Added serialized snapshot printing and printSnapshotInstanceToString to support new guarded logs.
Debug Test Enhancements
packages/react/runtime/__test__/debug/printSnapshot.test.jsx
New tests for SnapshotInstance printing and serialized printing paths.
Webpack Test Adjustment
packages/webpack/react-webpack-plugin/test/cases/compat/component-pkg/index.jsx
Test now strips __CreateView occurrences before asserting absence of literal "View".

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • Yradex
  • hzy
  • colinaaa

Poem

🐇 I hopped through stacks and logged each tiny call,

I numbered tags and traced where elements fall.
Console.alog chimed with each create and bind,
Patches printed pretty so curious devs might find.
nibble a carrot, inspect — and hop along, kind!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add dual-thread commutation logs' directly matches the PR's primary objective of adding dual-thread commutation logging for React integration.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 681e415 and 0878692.

📒 Files selected for processing (4)
  • packages/react/runtime/__test__/debug/printSnapshot.test.jsx
  • packages/react/runtime/src/debug/printSnapshot.ts
  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/testing-library/src/__tests__/alog.test.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/react/runtime/src/lynx/tt.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with the configuration specified in tsconfig.json

Files:

  • packages/react/runtime/src/debug/printSnapshot.ts
packages/react/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use JSX syntax and ReactLynx components in React component files within packages/react/

Files:

  • packages/react/runtime/src/debug/printSnapshot.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,tsx}: Follow eslint rules as configured in eslint.config.js including React and TypeScript specific rules
Follow code formatting rules specified in .dprint.jsonc and biome.jsonc

Files:

  • packages/react/runtime/src/debug/printSnapshot.ts
🧠 Learnings (16)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 2081
File: packages/react/runtime/src/alog/elementPAPICall.ts:109-112
Timestamp: 2025-12-30T10:02:23.790Z
Learning: In packages/react/runtime/src/alog/elementPAPICall.ts, the helper APIs `__GetTag` and `__GetElementUniqueID` should always exist when instrumenting FiberElement PAPIs, so defensive checks for their existence are unnecessary.
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/runtime/__test__/debug/printSnapshot.test.jsx
  • packages/react/runtime/src/debug/printSnapshot.ts
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • packages/react/runtime/__test__/debug/printSnapshot.test.jsx
  • packages/react/runtime/src/debug/printSnapshot.ts
📚 Learning: 2025-09-23T08:54:39.966Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/test/hotCases/hot/hot-update-json/dual-thread/__snapshot__/index.css:6-8
Timestamp: 2025-09-23T08:54:39.966Z
Learning: In the lynx-stack CSS extract webpack plugin tests, many test fixture CSS files intentionally use invalid CSS syntax like `color: 'red';` with quoted values. The snapshots correctly reflect this invalid CSS from the source fixtures. To fix CSS validation issues, the source fixture files should be updated first, then snapshots regenerated, rather than manually editing snapshots.

Applied to files:

  • packages/react/runtime/__test__/debug/printSnapshot.test.jsx
  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-12-30T10:02:23.790Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 2081
File: packages/react/runtime/src/alog/elementPAPICall.ts:109-112
Timestamp: 2025-12-30T10:02:23.790Z
Learning: In packages/react/runtime/src/alog/elementPAPICall.ts, the helper APIs `__GetTag` and `__GetElementUniqueID` should always exist when instrumenting FiberElement PAPIs, so defensive checks for their existence are unnecessary.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/tests/**/*.spec.ts : Use Playwright for all E2E and functional tests with standard assertions like `expect(locator).toBeVisible()`, `expect(locator).toHaveCSS()`, and `diffScreenShot` for screenshot comparisons

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/tests/**/*.spec.ts : When a component makes external requests (e.g., via `iframe` or `fetch`), mock them using `page.route` in Playwright tests to ensure tests are hermetic and fast

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-08-13T09:20:00.936Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1502
File: packages/react/testing-library/types/entry.d.ts:71-71
Timestamp: 2025-08-13T09:20:00.936Z
Learning: In lynx-js/react testing library, wrapper components must have children as a required prop because they are always called with `h(WrapperComponent, null, innerElement)` where innerElement is passed as children. The type `React.JSXElementConstructor<{ children: React.ReactNode }>` correctly requires children to be mandatory.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-10-11T06:16:12.517Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1820
File: packages/web-platform/web-tests/tests/react.spec.ts:834-856
Timestamp: 2025-10-11T06:16:12.517Z
Learning: In packages/web-platform/web-tests/tests/react.spec.ts, the tests `basic-bindmouse` and `basic-mts-bindtouchstart` are NOT duplicates despite having similar test structures. They test different event types: `basic-bindmouse` validates mouse events (mousedown, mouseup, mousemove) with mouse-specific properties (button, buttons, x, y, pageX, pageY, clientX, clientY), while `basic-mts-bindtouchstart` validates touch events (touchstart) with touch arrays (touches, targetTouches, changedTouches). The similar test structure is coincidental and follows testing conventions.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (9)
packages/react/runtime/__test__/debug/printSnapshot.test.jsx (3)

10-11: LGTM! Imports are correct.

The new imports for printSerializedSnapshotInstance and SnapshotInstance are necessary for the new test cases and properly scoped.


76-108: Excellent test coverage for SnapshotInstance.

The test comprehensively verifies both live instance printing via printSnapshotInstance and serialized instance printing via printSerializedSnapshotInstance. The approach of serializing to JSON and deserializing before printing validates the round-trip behavior, which is essential for dual-thread communication.


127-151: LGTM! Proper verification of default logging behavior.

The test correctly verifies that when no log callback is provided, the functions fall back to logDebug (which doesn't write to the test's msg variable), hence the empty string expectations.

packages/react/runtime/src/debug/printSnapshot.ts (3)

4-6: LGTM! Import changes are correct.

The change to a value import for BackgroundSnapshotInstance (line 4) is necessary for the instanceof check in printSnapshotInstanceToString. The type import for SerializedSnapshotInstance (line 6) is appropriately scoped.


31-51: Well-structured serialized instance printer.

The function correctly mirrors the structure of printSnapshotInstance while using the appropriate property names for serialized instances (id vs __id, values vs __values, children vs childNodes). The null-coalescing operator on line 45 properly handles potentially missing children.


53-63: LGTM! Clean dispatch logic.

The function properly uses instanceof checks to determine whether to call printSnapshotInstance or printSerializedSnapshotInstance. The string accumulation pattern with logArr.push.bind(logArr) is clean and efficient.

packages/react/testing-library/src/__tests__/alog.test.jsx (3)

40-165: Comprehensive FiberElement API logging validated.

The inline snapshot correctly captures the complete sequence of 31 FiberElement API calls during initial render, including page creation, element tree construction, event binding, and hydration. The logged element IDs, operation order, and parent-child relationships align with the JSX structure. The lifecycle event and updateMainThread logs appropriately include detailed JSON payloads with snapshot tree metadata and pipeline options.


182-259: Background thread logging with snapshot tree visualization looks good.

The snapshots correctly capture lifecycle event propagation and snapshot instance tree structure at different hydration stages. The compact tree format with indentation clearly shows parent-child relationships, and the three tree snapshots effectively demonstrate ID transformations during hydration (positive IDs in BTS pre-hydration converting to negative IDs post-hydration to match MTS).


280-319: Update logging correctly captures incremental changes.

The snapshot validates that state updates produce minimal, targeted logs: the updateMainThread message with the specific patch operation, followed by the corresponding __SetAttribute call (#32) and __FlushElementTree call (#33). The earlier no-op update (lines 266-271) correctly produces no logs, confirming that logging only captures actual DOM changes.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/react/runtime/src/alog/elementPAPICall.ts (2)

55-58: Non-null assertion may throw if element not in map.

formatFiberElement uses fiberElementMap.get(fiberElement)! which will fail if the element isn't in the map. While current usage guards with fiberElementMap.has(), a defensive check would be safer.

🔎 Optional defensive refactor
  function formatFiberElement(fiberElement: FiberElement): string {
-   const fiberElementInfo = fiberElementMap.get(fiberElement)!;
+   const fiberElementInfo = fiberElementMap.get(fiberElement);
+   if (!fiberElementInfo) {
+     return `<unknown element>`;
+   }
    return `${fiberElementInfo.tag}#${fiberElementInfo.uniqueId}`;
  }

111-114: Non-null assertions on __GetTag and __GetElementUniqueID could throw.

If these APIs are not available in globalWithIndex, accessing them with ! will throw. Consider adding a guard or fallback.

🔎 Optional defensive refactor
          fiberElementMap.set(result as FiberElement, {
-           tag: originalFiberElementPAPIs['__GetTag']!(result as FiberElement) as string,
-           uniqueId: originalFiberElementPAPIs['__GetElementUniqueID']!(result as FiberElement) as number,
+           tag: originalFiberElementPAPIs['__GetTag']?.(result as FiberElement) as string ?? 'unknown',
+           uniqueId: originalFiberElementPAPIs['__GetElementUniqueID']?.(result as FiberElement) as number ?? -1,
          });

Based on learnings, the team prioritizes performance and compile-time safety over defensive runtime checks. If __GetTag and __GetElementUniqueID are guaranteed to be present when Create* APIs exist, this can be safely ignored.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 49ef14b and 556b08d.

📒 Files selected for processing (8)
  • .changeset/cruel-feet-grow.md
  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
  • packages/react/runtime/src/alog/elementPAPICall.ts
  • packages/react/runtime/src/alog/index.ts
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/testing-library/src/__tests__/alog.test.jsx
  • packages/react/testing-library/src/vitest-global-setup.js
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,tsx}: Follow eslint rules as configured in eslint.config.js including React and TypeScript specific rules
Follow code formatting rules specified in .dprint.jsonc and biome.jsonc

Files:

  • packages/react/testing-library/src/vitest-global-setup.js
  • packages/react/runtime/src/alog/elementPAPICall.ts
  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
  • packages/react/runtime/src/alog/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with the configuration specified in tsconfig.json

Files:

  • packages/react/runtime/src/alog/elementPAPICall.ts
  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
  • packages/react/runtime/src/alog/index.ts
packages/react/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use JSX syntax and ReactLynx components in React component files within packages/react/

Files:

  • packages/react/runtime/src/alog/elementPAPICall.ts
  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
  • packages/react/runtime/src/alog/index.ts
**/__test__/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

**/__test__/**/*.{ts,tsx,js}: Place test files in test/ directories adjacent to source files
Use vitest-based unit tests as configured in vitest.config.ts

Files:

  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
🧠 Learnings (34)
📓 Common learnings
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: The `web-elements` package provides a Native UI implementation for the LynxJS Web Platform using Web Components built on the `element-reactive` reactive framework
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/react/testing-library/src/vitest-global-setup.js
  • packages/react/runtime/src/alog/elementPAPICall.ts
  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
  • packages/react/testing-library/src/__tests__/alog.test.jsx
  • .changeset/cruel-feet-grow.md
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/react/testing-library/src/vitest-global-setup.js
  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/src/elements/all.ts : Export new components in `src/elements/all.ts` and add export configuration to `package.json` under `exports` for both types and default

Applied to files:

  • packages/react/testing-library/src/vitest-global-setup.js
  • packages/react/runtime/src/alog/elementPAPICall.ts
  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
  • packages/react/runtime/src/alog/index.ts
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/src/elements/**/*.ts : Group DOM updates to minimize layout thrashing in web component implementations

Applied to files:

  • packages/react/testing-library/src/vitest-global-setup.js
📚 Learning: 2025-09-28T08:46:43.177Z
Learnt from: f0rdream
Repo: lynx-family/lynx-stack PR: 1835
File: packages/react/worklet-runtime/src/workletRuntime.ts:52-55
Timestamp: 2025-09-28T08:46:43.177Z
Learning: The legacy worklet path with `_lepusWorkletHash` in `packages/react/worklet-runtime/src/workletRuntime.ts` is preserved for compatibility with MTS (Mini-app Threading Service) that doesn't support Initial Frame Rendering. This path will not be touched in current implementations.

Applied to files:

  • packages/react/testing-library/src/vitest-global-setup.js
  • packages/react/runtime/src/lynx/tt.ts
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/react/testing-library/src/vitest-global-setup.js
  • packages/react/runtime/src/alog/elementPAPICall.ts
  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/testing-library/src/__tests__/alog.test.jsx
  • .changeset/cruel-feet-grow.md
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/src/elements/**/*.ts : Minimize heavy computation in `attributeChangedCallback` as these elements run on the main thread

Applied to files:

  • packages/react/testing-library/src/vitest-global-setup.js
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/src/elements/**/*.ts : When creating new elements, inherit from `Element` via `Component` decorator and use reactive utilities provided by `element-reactive`

Applied to files:

  • packages/react/runtime/src/alog/elementPAPICall.ts
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/src/elements/**/index.ts : Ensure `index.ts` files and complex logic have clear, descriptive comments matching the implementation

Applied to files:

  • packages/react/runtime/src/alog/elementPAPICall.ts
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/testing-library/src/__tests__/alog.test.jsx
  • .changeset/cruel-feet-grow.md
📚 Learning: 2025-12-26T05:10:01.595Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-26T05:10:01.595Z
Learning: Applies to packages/react/components/**/*.{ts,tsx} : Optimize component library in packages/react/components/ using ReactLynx syntax

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
  • .changeset/cruel-feet-grow.md
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/tests/**/*.spec.ts : Create a separate spec file for new components (e.g., `tests/x-webview.spec.ts`) instead of adding to the monolithic `web-elements.spec.ts`

Applied to files:

  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/tests/**/*.spec.ts : Use Playwright for all E2E and functional tests with standard assertions like `expect(locator).toBeVisible()`, `expect(locator).toHaveCSS()`, and `diffScreenShot` for screenshot comparisons

Applied to files:

  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/tests/**/*.spec.ts : When a component makes external requests (e.g., via `iframe` or `fetch`), mock them using `page.route` in Playwright tests to ensure tests are hermetic and fast

Applied to files:

  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-08-13T09:20:00.936Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1502
File: packages/react/testing-library/types/entry.d.ts:71-71
Timestamp: 2025-08-13T09:20:00.936Z
Learning: In lynx-js/react testing library, wrapper components must have children as a required prop because they are always called with `h(WrapperComponent, null, innerElement)` where innerElement is passed as children. The type `React.JSXElementConstructor<{ children: React.ReactNode }>` correctly requires children to be mandatory.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-10-11T06:16:12.517Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1820
File: packages/web-platform/web-tests/tests/react.spec.ts:834-856
Timestamp: 2025-10-11T06:16:12.517Z
Learning: In packages/web-platform/web-tests/tests/react.spec.ts, the tests `basic-bindmouse` and `basic-mts-bindtouchstart` are NOT duplicates despite having similar test structures. They test different event types: `basic-bindmouse` validates mouse events (mousedown, mouseup, mousemove) with mouse-specific properties (button, buttons, x, y, pageX, pageY, clientX, clientY), while `basic-mts-bindtouchstart` validates touch events (touchstart) with touch arrays (touches, targetTouches, changedTouches). The similar test structure is coincidental and follows testing conventions.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-09-23T08:54:39.966Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/test/hotCases/hot/hot-update-json/dual-thread/__snapshot__/index.css:6-8
Timestamp: 2025-09-23T08:54:39.966Z
Learning: In the lynx-stack CSS extract webpack plugin tests, many test fixture CSS files intentionally use invalid CSS syntax like `color: 'red';` with quoted values. The snapshots correctly reflect this invalid CSS from the source fixtures. To fix CSS validation issues, the source fixture files should be updated first, then snapshots regenerated, rather than manually editing snapshots.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-11-06T01:17:14.493Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/src/tools/Runtime/ListConsole.ts:48-60
Timestamp: 2025-11-06T01:17:14.493Z
Learning: In the Lynx runtime, console messages always include stack traces, so defensive null checks for `stackTrace.callFrames` in console message handling code are not required.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • .changeset/cruel-feet-grow.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/cruel-feet-grow.md
📚 Learning: 2025-12-26T05:10:01.595Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-26T05:10:01.595Z
Learning: Use changeset tool with `pnpm changeset` to document changes before contribution

Applied to files:

  • .changeset/cruel-feet-grow.md
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/cruel-feet-grow.md
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • .changeset/cruel-feet-grow.md
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • .changeset/cruel-feet-grow.md
📚 Learning: 2025-10-10T08:22:12.051Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1837
File: packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts:266-266
Timestamp: 2025-10-10T08:22:12.051Z
Learning: In packages/web-platform/web-mainthread-apis, the handleUpdatedData function returned from prepareMainThreadAPIs is internal-only, used to serve web-core. It does not require public documentation, type exports, or SSR support.

Applied to files:

  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
📚 Learning: 2025-07-18T04:27:18.291Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1238
File: packages/react/runtime/src/debug/component-stack.ts:70-90
Timestamp: 2025-07-18T04:27:18.291Z
Learning: The component-stack.ts file in packages/react/runtime/src/debug/component-stack.ts is a direct fork from https://github.com/preactjs/preact/blob/main/debug/src/component-stack.js. The team prefers to keep it aligned with the upstream Preact version and may contribute improvements back to Preact in the future.

Applied to files:

  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
📚 Learning: 2025-09-28T07:52:03.601Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1837
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createNativeApp.ts:151-154
Timestamp: 2025-09-28T07:52:03.601Z
Learning: There are two different registerUpdateDataHandler functions in the lynx-stack codebase:
1. Main thread version in packages/web-platform/web-worker-runtime/src/mainThread/crossThreadHandlers/registerUpdateDataHandler.ts takes (mainThreadRpc: Rpc, backgroundThreadRpc: Rpc, runtime: MainThreadGlobalThis)
2. Background thread version in packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/crossThreadHandlers/registerUpdateDataHandler.ts takes only (rpc: Rpc, tt: NativeTTObject)

Applied to files:

  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
📚 Learning: 2025-09-28T07:52:03.601Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1837
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createNativeApp.ts:151-154
Timestamp: 2025-09-28T07:52:03.601Z
Learning: There are two different registerUpdateDataHandler functions in the lynx-stack codebase:
1. Main thread version in packages/web-platform/web-worker-runtime/src/mainThread/crossThreadHandlers/registerUpdateDataHandler.ts takes (mainThreadRpc: Rpc, backgroundThreadRpc: Rpc, runtime: MainThreadGlobalThis)
2. Background thread version in packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/crossThreadHandlers/registerUpdateDataHandler.ts takes only (rpc: Rpc, tt: any)

Applied to files:

  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
🧬 Code graph analysis (3)
packages/react/testing-library/src/vitest-global-setup.js (1)
packages/react/runtime/src/alog/elementPAPICall.ts (1)
  • initElementPAPICallAlog (49-133)
packages/react/runtime/src/lifecycle/patch/updateMainThread.ts (1)
packages/react/runtime/src/debug/formatPatch.ts (1)
  • prettyFormatSnapshotPatch (8-28)
packages/react/runtime/src/alog/index.ts (2)
packages/react/runtime/src/alog/render.ts (1)
  • initRenderAlog (11-32)
packages/react/runtime/src/alog/elementPAPICall.ts (1)
  • initElementPAPICallAlog (49-133)
🔇 Additional comments (12)
.changeset/cruel-feet-grow.md (1)

1-5: LGTM!

The changeset is properly formatted with a patch version bump for @lynx-js/react. The description clearly documents the new dual-thread commutation logging feature and its activation conditions.

packages/react/runtime/src/lynx/tt.ts (1)

91-103: LGTM!

The conditional logging block is well-guarded with the __ALOG__ check and uses optional chaining on console.alog. The structured JSON output with the parsed lepusSide is helpful for debugging hydration issues.

packages/react/runtime/src/lifecycle/patch/updateMainThread.ts (2)

11-11: LGTM!

Import of prettyFormatSnapshotPatch is correctly added to support the new debug logging.


41-61: LGTM!

The refactoring to extract parsedData improves readability, and the conditional logging block follows the same pattern as tt.ts. Using prettyFormatSnapshotPatch provides human-readable patch data in the debug output.

packages/react/runtime/src/alog/index.ts (1)

4-9: LGTM!

The new initElementPAPICallAlog is correctly imported and invoked after initRenderAlog(). Using the default globalThis parameter is appropriate for the runtime context.

packages/react/testing-library/src/vitest-global-setup.js (2)

11-11: LGTM!

Import correctly uses the compiled lib path for the testing library context.


112-113: LGTM!

Correctly passes target to initElementPAPICallAlog to patch the main thread globals in the testing environment rather than using the default globalThis.

packages/react/runtime/__test__/alog/elementPAPICall.test.js (1)

1-49: LGTM!

Good test coverage for the ElementPAPICall alogging. The test correctly:

  • Switches to the main thread environment
  • Mocks console.alog before initialization
  • Exercises various element creation and manipulation APIs
  • Verifies the exact sequence and format of log messages
packages/react/testing-library/src/__tests__/alog.test.jsx (3)

38-172: LGTM!

The extended snapshot comprehensively captures the new ElementPAPICall logs and BTS ↔ MTS communication logs. The sequence of 37 API calls covers element creation, manipulation, events, and lifecycle events.


188-235: LGTM!

The background thread snapshot correctly captures the new MTS -> BTS OnLifecycleEvent log with the pretty-printed hydration data structure.


256-301: LGTM!

The state change scenario snapshot correctly verifies that the logging continues to work after initial hydration, showing the SetAttribute operation and subsequent FlushElementTree calls.

packages/react/runtime/src/alog/elementPAPICall.ts (1)

49-133: Well-structured logging instrumentation.

The implementation correctly:

  • Filters to only existing APIs before wrapping
  • Preserves original API references for internal use
  • Uses optional chaining on console.alog
  • Provides readable formatted output for fiber elements and their IDs
  • Integrates profiling support with __PROFILE__ guard

@upupming upupming force-pushed the feat/dual-thread-alog branch from 556b08d to 0fa7bfb Compare December 30, 2025 09:58
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/react/runtime/__test__/alog/elementPAPICall.test.js (2)

6-49: Consider adding test cleanup for better isolation.

The test directly assigns console.alog = vi.fn() without restoring it afterward. While this works for a single test, it may affect other tests if they share the same console object or if additional tests are added to this suite.

🔎 Suggested cleanup pattern
+import { describe, it, vi, expect, afterEach } from 'vitest';
 import { initElementPAPICallAlog } from '../../src/alog/elementPAPICall';
 import { globalEnvManager } from '../utils/envManager';
-import { expect } from 'vitest';

 describe('ElementPAPICall Alog', () => {
+  let originalAlog;
+
+  afterEach(() => {
+    console.alog = originalAlog;
+  });
+
   it('should log ElementPAPICall as ALog', () => {
     globalEnvManager.switchToMainThread();
+    originalAlog = console.alog;
     console.alog = vi.fn();
     initElementPAPICallAlog();

1-4: Consolidate imports from the same module.

expect is imported separately from other vitest utilities.

🔎 Suggested fix
-import { describe, it, vi } from 'vitest';
+import { describe, it, vi, expect } from 'vitest';
 import { initElementPAPICallAlog } from '../../src/alog/elementPAPICall';
 import { globalEnvManager } from '../utils/envManager';
-import { expect } from 'vitest';
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 556b08d and 0fa7bfb.

📒 Files selected for processing (8)
  • .changeset/cruel-feet-grow.md
  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
  • packages/react/runtime/src/alog/elementPAPICall.ts
  • packages/react/runtime/src/alog/index.ts
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/testing-library/src/__tests__/alog.test.jsx
  • packages/react/testing-library/src/vitest-global-setup.js
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/react/testing-library/src/vitest-global-setup.js
  • packages/react/runtime/src/alog/index.ts
  • .changeset/cruel-feet-grow.md
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with the configuration specified in tsconfig.json

Files:

  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/runtime/src/alog/elementPAPICall.ts
packages/react/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use JSX syntax and ReactLynx components in React component files within packages/react/

Files:

  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/runtime/src/alog/elementPAPICall.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,tsx}: Follow eslint rules as configured in eslint.config.js including React and TypeScript specific rules
Follow code formatting rules specified in .dprint.jsonc and biome.jsonc

Files:

  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/runtime/src/alog/elementPAPICall.ts
  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
**/__test__/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

**/__test__/**/*.{ts,tsx,js}: Place test files in test/ directories adjacent to source files
Use vitest-based unit tests as configured in vitest.config.ts

Files:

  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
🧠 Learnings (22)
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/testing-library/src/__tests__/alog.test.jsx
  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
📚 Learning: 2025-12-26T05:10:01.595Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-26T05:10:01.595Z
Learning: Applies to packages/react/components/**/*.{ts,tsx} : Optimize component library in packages/react/components/ using ReactLynx syntax

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/testing-library/src/__tests__/alog.test.jsx
  • packages/react/runtime/src/alog/elementPAPICall.ts
📚 Learning: 2025-09-28T08:46:43.177Z
Learnt from: f0rdream
Repo: lynx-family/lynx-stack PR: 1835
File: packages/react/worklet-runtime/src/workletRuntime.ts:52-55
Timestamp: 2025-09-28T08:46:43.177Z
Learning: The legacy worklet path with `_lepusWorkletHash` in `packages/react/worklet-runtime/src/workletRuntime.ts` is preserved for compatibility with MTS (Mini-app Threading Service) that doesn't support Initial Frame Rendering. This path will not be touched in current implementations.

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/testing-library/src/__tests__/alog.test.jsx
  • packages/react/runtime/src/alog/elementPAPICall.ts
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/tests/**/*.spec.ts : When a component makes external requests (e.g., via `iframe` or `fetch`), mock them using `page.route` in Playwright tests to ensure tests are hermetic and fast

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-08-13T09:20:00.936Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1502
File: packages/react/testing-library/types/entry.d.ts:71-71
Timestamp: 2025-08-13T09:20:00.936Z
Learning: In lynx-js/react testing library, wrapper components must have children as a required prop because they are always called with `h(WrapperComponent, null, innerElement)` where innerElement is passed as children. The type `React.JSXElementConstructor<{ children: React.ReactNode }>` correctly requires children to be mandatory.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-10-11T06:16:12.517Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1820
File: packages/web-platform/web-tests/tests/react.spec.ts:834-856
Timestamp: 2025-10-11T06:16:12.517Z
Learning: In packages/web-platform/web-tests/tests/react.spec.ts, the tests `basic-bindmouse` and `basic-mts-bindtouchstart` are NOT duplicates despite having similar test structures. They test different event types: `basic-bindmouse` validates mouse events (mousedown, mouseup, mousemove) with mouse-specific properties (button, buttons, x, y, pageX, pageY, clientX, clientY), while `basic-mts-bindtouchstart` validates touch events (touchstart) with touch arrays (touches, targetTouches, changedTouches). The similar test structure is coincidental and follows testing conventions.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-09-23T08:54:39.966Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/test/hotCases/hot/hot-update-json/dual-thread/__snapshot__/index.css:6-8
Timestamp: 2025-09-23T08:54:39.966Z
Learning: In the lynx-stack CSS extract webpack plugin tests, many test fixture CSS files intentionally use invalid CSS syntax like `color: 'red';` with quoted values. The snapshots correctly reflect this invalid CSS from the source fixtures. To fix CSS validation issues, the source fixture files should be updated first, then snapshots regenerated, rather than manually editing snapshots.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-11-06T01:17:14.493Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/src/tools/Runtime/ListConsole.ts:48-60
Timestamp: 2025-11-06T01:17:14.493Z
Learning: In the Lynx runtime, console messages always include stack traces, so defensive null checks for `stackTrace.callFrames` in console message handling code are not required.

Applied to files:

  • packages/react/testing-library/src/__tests__/alog.test.jsx
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/src/elements/all.ts : Export new components in `src/elements/all.ts` and add export configuration to `package.json` under `exports` for both types and default

Applied to files:

  • packages/react/runtime/src/alog/elementPAPICall.ts
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/src/elements/**/*.ts : When creating new elements, inherit from `Element` via `Component` decorator and use reactive utilities provided by `element-reactive`

Applied to files:

  • packages/react/runtime/src/alog/elementPAPICall.ts
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/src/elements/**/index.ts : Ensure `index.ts` files and complex logic have clear, descriptive comments matching the implementation

Applied to files:

  • packages/react/runtime/src/alog/elementPAPICall.ts
📚 Learning: 2025-07-18T04:27:18.291Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1238
File: packages/react/runtime/src/debug/component-stack.ts:70-90
Timestamp: 2025-07-18T04:27:18.291Z
Learning: The component-stack.ts file in packages/react/runtime/src/debug/component-stack.ts is a direct fork from https://github.com/preactjs/preact/blob/main/debug/src/component-stack.js. The team prefers to keep it aligned with the upstream Preact version and may contribute improvements back to Preact in the future.

Applied to files:

  • packages/react/runtime/src/alog/elementPAPICall.ts
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/tests/**/*.spec.ts : Create a separate spec file for new components (e.g., `tests/x-webview.spec.ts`) instead of adding to the monolithic `web-elements.spec.ts`

Applied to files:

  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/tests/**/*.spec.ts : Use Playwright for all E2E and functional tests with standard assertions like `expect(locator).toBeVisible()`, `expect(locator).toHaveCSS()`, and `diffScreenShot` for screenshot comparisons

Applied to files:

  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
📚 Learning: 2025-12-29T11:26:09.487Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: packages/web-platform/web-elements/AGENTS.md:0-0
Timestamp: 2025-12-29T11:26:09.487Z
Learning: Applies to packages/web-platform/web-elements/tests/fixtures/**/*.html : Use HTML files for test fixtures and define a helper function `goto(page, fixtureName)` to handle navigation and waiting for resources like `document.fonts.ready`

Applied to files:

  • packages/react/runtime/__test__/alog/elementPAPICall.test.js
🧬 Code graph analysis (2)
packages/react/runtime/src/alog/elementPAPICall.ts (1)
packages/react/runtime/src/debug/utils.ts (2)
  • profileStart (9-15)
  • profileEnd (17-23)
packages/react/runtime/__test__/alog/elementPAPICall.test.js (2)
packages/react/runtime/__test__/utils/envManager.ts (1)
  • globalEnvManager (86-86)
packages/react/runtime/src/alog/elementPAPICall.ts (1)
  • initElementPAPICallAlog (47-131)
🔇 Additional comments (6)
packages/react/runtime/src/lynx/tt.ts (1)

91-103: LGTM!

The debug logging block is well-guarded with proper checks for __ALOG__ and uses optional chaining on console.alog. Positioning between the timing marks and using the parsed before object (rather than the raw string) for cleaner output is a nice touch.

packages/react/runtime/src/alog/elementPAPICall.ts (3)

7-45: LGTM!

The API list is well-organized and comprehensive. The previously flagged duplicate __FlushElementTree entries have been resolved.


47-63: LGTM!

The initialization logic is sound. The non-null assertion on line 54 is safe since formatFiberElement is only called after a fiberElementMap.has() check. The reduce pattern for collecting original APIs is acceptable given the small, fixed list size.


115-127: LGTM!

The result formatting and logging logic is correct. The nullish check on line 124 properly handles both null results and the undefined that JSON.stringify(undefined) returns. Optional chaining on console.alog ensures graceful degradation.

packages/react/testing-library/src/__tests__/alog.test.jsx (2)

40-171: LGTM!

The expanded snapshot comprehensively captures the new FiberElement API call logging format, including the human-readable element references (e.g., PAGE#0, VIEW#1) and the BTS → MTS communication logs. The three __FlushElementTree calls (#31-33) represent actual runtime behavior during hydration, not duplicate instrumentation.


188-301: LGTM!

The background thread snapshot now correctly captures the MTS -> BTS OnLifecycleEvent log with the parsed hydration data structure. The state update snapshot (lines 256-301) properly shows the incremental SetAttribute patch and subsequent flush operations, validating the end-to-end logging flow.

@upupming upupming requested a review from Yradex December 30, 2025 10:03
@codecov
Copy link

codecov bot commented Dec 30, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 30, 2025

CodSpeed Performance Report

Merging #2081 will degrade performance by 10.5%

Comparing feat/dual-thread-alog (0878692) with main (bba05e2)

Summary

⚡ 1 improvement
❌ 1 regression
✅ 61 untouched
⏩ 3 skipped1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Benchmark BASE HEAD Efficiency
transform 1000 view elements 41.7 ms 46.6 ms -10.5%
basic-performance-div-100 6.8 ms 6.2 ms +8.31%

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@relativeci
Copy link

relativeci bot commented Dec 30, 2025

React Example

#6810 Bundle Size — 237.01KiB (~+0.01%).

0878692(current) vs bba05e2 main#6800(baseline)

Bundle metrics  Change 3 changes
                 Current
#6810
     Baseline
#6800
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 38.5% 0%
No change  Chunks 0 0
No change  Assets 4 4
Change  Modules 165(+1.85%) 162
No change  Duplicate Modules 65 65
Change  Duplicate Code 46.48%(-0.56%) 46.74%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#6810
     Baseline
#6800
No change  IMG 145.76KiB 145.76KiB
Regression  Other 91.25KiB (+0.02%) 91.24KiB

Bundle analysis reportBranch feat/dual-thread-alogProject dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link

relativeci bot commented Dec 30, 2025

Web Explorer

#6970 Bundle Size — 379.18KiB (0%).

0878692(current) vs bba05e2 main#6960(baseline)

Bundle metrics  no changes
                 Current
#6970
     Baseline
#6960
No change  Initial JS 152.57KiB 152.57KiB
No change  Initial CSS 32.53KiB 32.53KiB
No change  Cache Invalidation 0% 0%
No change  Chunks 8 8
No change  Assets 8 8
No change  Modules 236 236
No change  Duplicate Modules 16 16
No change  Duplicate Code 3.03% 3.03%
No change  Packages 4 4
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#6970
     Baseline
#6960
No change  JS 249.67KiB 249.67KiB
No change  Other 96.98KiB 96.98KiB
No change  CSS 32.53KiB 32.53KiB

Bundle analysis reportBranch feat/dual-thread-alogProject dashboard


Generated by RelativeCIDocumentationReport issue

@upupming upupming requested a review from colinaaa as a code owner December 30, 2025 11:37
@upupming upupming force-pushed the feat/dual-thread-alog branch from 344b1a8 to 681e415 Compare December 31, 2025 04:15
@upupming upupming requested a review from HuJean December 31, 2025 04:46
@upupming upupming enabled auto-merge (squash) January 4, 2026 06:40
@upupming upupming merged commit 59f0408 into main Jan 4, 2026
46 of 47 checks passed
@upupming upupming deleted the feat/dual-thread-alog branch January 4, 2026 08:48
colinaaa pushed a commit that referenced this pull request Jan 4, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @lynx-js/gesture-runtime@2.1.1

### Patch Changes

- Add `NativeGesture`
([#2076](#2076))

## @lynx-js/react@0.115.3

### Patch Changes

- Add dual-thread commutation logs for troubleshooting when
`REACT_ALOG=true` or global define `__ALOG__` is set.
([#2081](#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](#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;
      }
    });
    ```

## @lynx-js/rspeedy@0.12.5

### Patch Changes

-   Updated dependencies \[]:
    -   @lynx-js/web-rsbuild-server-middleware@0.19.4

## @lynx-js/react-rsbuild-plugin@0.12.4

### Patch Changes

-   ([#2051](#2051))

-   Updated dependencies \[]:
    -   @lynx-js/react-alias-rsbuild-plugin@0.12.4
    -   @lynx-js/use-sync-external-store@1.5.0
    -   @lynx-js/react-refresh-webpack-plugin@0.3.4
    -   @lynx-js/react-webpack-plugin@0.7.3

## @lynx-js/testing-environment@0.1.9

### Patch Changes

- Fix duplicated `<page />` elements on body when multiple
`__CreatePage` called.
([#2065](#2065))

## @lynx-js/web-constants@0.19.4

### Patch Changes

- Updated dependencies
\[[`bba05e2`](bba05e2)]:
    -   @lynx-js/web-worker-rpc@0.19.4

## @lynx-js/web-core@0.19.4

### Patch Changes

- Updated dependencies
\[[`bba05e2`](bba05e2)]:
    -   @lynx-js/web-worker-rpc@0.19.4
    -   @lynx-js/web-constants@0.19.4
    -   @lynx-js/web-worker-runtime@0.19.4
    -   @lynx-js/web-mainthread-apis@0.19.4

## @lynx-js/web-elements@0.10.1

### Patch Changes

- feat: implement x-webview component
([#2061](#2061))

- feat: support `recyclable="false"` on `list-item` and enable overflow
visibility
([#2069](#2069))

## @lynx-js/web-mainthread-apis@0.19.4

### Patch Changes

-   Updated dependencies \[]:
    -   @lynx-js/web-constants@0.19.4

## @lynx-js/web-worker-rpc@0.19.4

### Patch Changes

- Ensure the `default` export entry is last in the package exports map.
([#2075](#2075))

## @lynx-js/web-worker-runtime@0.19.4

### Patch Changes

- Updated dependencies
\[[`bba05e2`](bba05e2)]:
    -   @lynx-js/web-worker-rpc@0.19.4
    -   @lynx-js/web-constants@0.19.4
    -   @lynx-js/web-mainthread-apis@0.19.4

## create-rspeedy@0.12.5



## @lynx-js/react-alias-rsbuild-plugin@0.12.4



## upgrade-rspeedy@0.12.5



## @lynx-js/web-core-server@0.19.4



## @lynx-js/web-rsbuild-server-middleware@0.19.4

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Allow enable REACT_ALOG mode to log Dual-Thread communication info

4 participants