Skip to content

New plugins - #10

Merged
listepo merged 45 commits into
mainfrom
new-plugins
Aug 20, 2026
Merged

New plugins#10
listepo merged 45 commits into
mainfrom
new-plugins

Conversation

@listepo

@listepo listepo commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added NativeScript support for building and running applications with Rspack.
    • Added a cross-platform Android and iOS sample app featuring widgets, navigation, dialogs, popups, gestures, animations, and responsive themes.
    • Added CLI support for standard builds and watch mode.
    • Added support for additional WebAssembly runtime plugins.
  • Documentation

    • Added setup, configuration, customization, and known limitations documentation.
  • Tests

    • Added coverage for configuration compatibility and build behavior.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 02107f2e-6fbe-47af-9984-67cf2967e38f

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The pull request adds the @cross-code/ns-rspack package, integrates Nx and workspace tooling, and adds a NativeScript Rspack test app with Android, iOS, and widgets-gallery implementations.

Changes

Repository tooling

Layer / File(s) Summary
Repository and workspace configuration
.gitignore, nx.json, package.json, pnpm-workspace.yaml, tsconfig.json
Nx gains Vite target mappings. Workspace permissions, release settings, dependencies, and project references change.

ns-rspack package

Layer / File(s) Summary
Package contract and TypeScript setup
packages/ns-rspack/package.json, packages/ns-rspack/README.md, packages/ns-rspack/tsconfig*.json, packages/ns-rspack/vitest.config.mts
The package defines exports, the ns-rspack binary, documentation, build settings, and Vitest settings.
Webpack-to-Rspack compatibility
packages/ns-rspack/src/lib/compat.ts, packages/ns-rspack/src/lib/compat.spec.ts
Configuration adaptation replaces plugins and loaders, rewrites copy patterns, adds entry exports handling, removes unsupported plugins, and adjusts output settings. Tests cover these transformations.
NativeScript-compatible public API
packages/ns-rspack/src/index.ts
The package exposes initialization, chain registration, merge, configuration selection, resolution, and NativeScript helper APIs.
CLI compilation and watch reporting
packages/ns-rspack/src/bin/index.ts, packages/ns-rspack/src/lib/watch-state-plugin.ts
The CLI loads configurations and runs one-shot or watch builds. WatchStatePlugin reports compilation state, assets, hashes, and IPC messages.

NativeScript test app

Layer / File(s) Summary
App foundation and platform resources
apps/rspack-test-app/.editorconfig, apps/rspack-test-app/.gitignore, apps/rspack-test-app/.vscode/*, apps/rspack-test-app/App_Resources/*, apps/rspack-test-app/app/app.ts, apps/rspack-test-app/references.d.ts, apps/rspack-test-app/nativescript.config.ts, apps/rspack-test-app/package.json, apps/rspack-test-app/rspack.config.ts, apps/rspack-test-app/tsconfig.json
The app gains NativeScript and Rspack configuration, startup wiring, TypeScript settings, Android resources, and iOS resources.
Widgets gallery UI
apps/rspack-test-app/app/app-root.xml, apps/rspack-test-app/app/app.css, apps/rspack-test-app/app/main-page.xml, apps/rspack-test-app/app/tabs-page.xml
The app adds the root layout, gallery styling, interactive widget examples, and a three-tab page.
Gallery behavior and navigation
apps/rspack-test-app/app/main-page.ts, apps/rspack-test-app/app/main-view-model.ts, apps/rspack-test-app/app/tabs-page.ts
The app adds observable gallery state, event handlers, dialogs, popups, animations, tab navigation, modal navigation, and page closure.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant NativeScriptApp
  participant MainPage
  participant WidgetsGalleryModel
  participant TabsPage
  NativeScriptApp->>MainPage: navigate to main page
  MainPage->>WidgetsGalleryModel: create binding context
  MainPage->>WidgetsGalleryModel: dispatch widget interaction
  WidgetsGalleryModel->>TabsPage: open tab page
  TabsPage->>MainPage: navigate back or close modal
``

</details>

<!-- walkthrough_end -->
<!-- pre_merge_checks_walkthrough_start -->

<details>
<summary>🚥 Pre-merge checks | ✅ 4 | ❌ 1</summary>

### ❌ Failed checks (1 warning)

|     Check name     | Status     | Explanation                                                                           | Resolution                                                                         |
| :----------------: | :--------- | :------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------- |
| Docstring Coverage | ⚠️ Warning | Docstring coverage is 61.90% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |

<details>
<summary>✅ Passed checks (4 passed)</summary>

|         Check name         | Status   | Explanation                                                                                                                                                    |
| :------------------------: | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|      Description Check     | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled.                                                                                                    |
|         Title check        | ✅ Passed | The title accurately identifies the addition of new plugins, which is a major part of the changeset, although it does not specify the Rspack and WASM plugins. |
|     Linked Issues check    | ✅ Passed | Check skipped because no linked issues were found for this pull request.                                                                                       |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request.                                                                                       |

</details>

</details>

<!-- pre_merge_checks_walkthrough_end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches 💡 1</summary>

<!-- finishing_touch_suggestion:fix_ci -->
<details open>
<summary>🛠️ Fix failing CI checks 💡</summary>

- [ ] <!-- {"checkboxId": "6d21cfe8-ec3f-40e2-9222-b8318b64d3b0", "radioGroupId": "fix-ci-output-choice-group-unknown_comment_id"} -->   Create stacked PR
- [ ] <!-- {"checkboxId": "9f0d24fb-b419-4f01-baf0-8b26b6424f34", "radioGroupId": "fix-ci-output-choice-group-unknown_comment_id"} -->   Commit on current branch

</details>
<details>
<summary>🧪 Generate unit tests (beta)</summary>

- [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Create PR with unit tests
- [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Commit unit tests in branch `new-plugins`

</details>

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=listepo/cross-code&utm_content=10)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>


<sub>Comment `@coderabbitai help` to get the list of available commands.</sub>

<!-- tips_end -->
Loading

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
nx.json (1)

46-50: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the deprecated serve target unless compatibility requires it.

Nx documents serveTargetName as deprecated and devTargetName as its replacement. The two names represent the same Vite development-server capability. (nx.dev)

Remove serveTargetName unless existing scripts or projects still require nx serve.

Suggested configuration
                 "devTargetName": "dev",
-                "serveTargetName": "serve",
                 "previewTargetName": "preview",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@nx.json` around lines 46 - 50, Remove the deprecated serveTargetName entry
from the Nx configuration, while retaining devTargetName as the
development-server target. Preserve serveTargetName only if repository scripts
or projects explicitly depend on nx serve.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@nx.json`:
- Line 60: Update the preVersionCommand release hook in nx.json to invoke Nx
through the repository-pinned pnpm executable, replacing the npx command with
pnpm exec nx while preserving the existing run-many build arguments.

In `@packages/ns-wamr/package.json`:
- Around line 158-159: Update the typings.ios and typings.android scripts in
package.json to execute their respective ns typings commands from the
apps/ns-wasm-test working directory, so generated declarations are written to
that app’s typings directory.

---

Nitpick comments:
In `@nx.json`:
- Around line 46-50: Remove the deprecated serveTargetName entry from the Nx
configuration, while retaining devTargetName as the development-server target.
Preserve serveTargetName only if repository scripts or projects explicitly
depend on nx serve.
🪄 Autofix

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 94995fd9-0c17-4fed-8215-abffeff53652

📥 Commits

Reviewing files that changed from the base of the PR and between dfc3acc and d6d9749.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • .gitignore
  • nx.json
  • package.json
  • packages/ns-wamr/package.json
  • pnpm-workspace.yaml

Comment thread nx.json Outdated
Comment thread packages/ns-wamr/package.json Outdated
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Fixes Applied Successfully

Fixed 2 file(s) based on 2 unresolved review comments.

Files modified:

  • nx.json
  • packages/ns-wamr/package.json

Commit: d16ad8647fc7a62a1d12eb74ce615d196c4811a5

The changes have been pushed to the new-plugins branch.

Time taken: 2m 18s

coderabbitai Bot and others added 3 commits August 8, 2026 20:47
Fixed 2 file(s) based on 2 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Replaces the hello-world page with a live gallery of every
@nativescript/core UI widget: text, inputs, pickers, images,
HtmlView/WebView, ListView/Repeater, Placeholder, all layouts,
gestures, animations, dialogs, and Frame/Page/TabView navigation.

The app root is now a RootLayout wrapping the Frame so the popup
and shade-cover demo exercises the real API.

Verified on the iOS simulator. Four core quirks worked around:

- {{ $value }} over a primitive array is a boxed String, which
  colour-typed properties cannot parse — item templates bind named
  object properties instead
- TabView is controller-backed on iOS and fills the whole Page, so
  it is the page's only content and Close lives inside a tab
- @nativescript/theme sets text-transform:capitalize on TabView and
  it inherits into tab content — overridden on .gallery
- the template logo.png is white on transparent, so the Image demos
  sit on a dark backdrop

SplitView is documented rather than demoed: at compact width the
collapsing UISplitViewController loops re-pushing nav controllers,
so it cannot be hosted in a Frame-pushed page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
apps/rspack-test-app/nativescript.config.ts (1)

3-11: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Set the NativeScript CLI package manager explicitly.

If this app can be run through NativeScript CLI, add cli.packageManager: 'pnpm'. The repository-local apps/ns-wasm-test/nativescript.config.ts uses this setting. NativeScript otherwise uses the CLI-wide default, or npm when no default is set. A different default can produce a dependency tree that differs from CI. (docs.nativescript.org)

Suggested configuration change
   appResourcesPath: 'App_Resources',
+  cli: {
+    packageManager: 'pnpm'
+  },
   android: {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/rspack-test-app/nativescript.config.ts` around lines 3 - 11, Update the
exported NativeScript configuration object to include a cli.packageManager
setting of 'pnpm', matching the existing configuration pattern in the repository
and ensuring CLI installs use pnpm.
apps/rspack-test-app/App_Resources/Android/src/main/AndroidManifest.xml (1)

11-12: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Remove legacy storage permissions when no storage feature requires them.

The manifest declares READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE, but the supplied app objective is a widgets gallery and no storage access is shown. If omitted app code does not require these permissions, remove them to keep the permission surface minimal.

Proposed cleanup
-	<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
-	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/rspack-test-app/App_Resources/Android/src/main/AndroidManifest.xml`
around lines 11 - 12, Remove the READ_EXTERNAL_STORAGE and
WRITE_EXTERNAL_STORAGE declarations from the Android manifest, provided no app
code requires storage access. Keep the manifest focused on permissions needed by
the widgets gallery.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/rspack-test-app/app/app.css`:
- Around line 25-27: Update the dark-mode card styles in .ns-dark .card and the
related title and hint selectors around the referenced card content to set
accessible light text colors against the `#212121` background. Preserve the
existing dark card background while ensuring both card titles and hint text meet
sufficient contrast.

In `@apps/rspack-test-app/app/tabs-page.xml`:
- Line 3: Update the Android NavigationButton in tabs-page to bind its tap
action to the existing onClose handler by adding the tap binding, while
preserving the current text and system icon attributes.

In `@apps/rspack-test-app/package.json`:
- Around line 6-15: Add the NativeScript 9.0-compatible `@nativescript/android`
package to the devDependencies in package.json, then regenerate or update the
corresponding package-lock.json entry while preserving the existing dependency
versions.

---

Nitpick comments:
In `@apps/rspack-test-app/App_Resources/Android/src/main/AndroidManifest.xml`:
- Around line 11-12: Remove the READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE
declarations from the Android manifest, provided no app code requires storage
access. Keep the manifest focused on permissions needed by the widgets gallery.

In `@apps/rspack-test-app/nativescript.config.ts`:
- Around line 3-11: Update the exported NativeScript configuration object to
include a cli.packageManager setting of 'pnpm', matching the existing
configuration pattern in the repository and ensuring CLI installs use pnpm.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ce3704b5-c38b-45f4-b949-8f93f89f703c

📥 Commits

Reviewing files that changed from the base of the PR and between 2d062da and ab38c2e.

⛔ Files ignored due to path filters (40)
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-hdpi/background.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-hdpi/logo.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-ldpi/background.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-ldpi/logo.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-mdpi/background.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-mdpi/logo.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-xhdpi/background.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-xhdpi/logo.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-xxhdpi/background.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-xxhdpi/logo.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-xxxhdpi/background.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-xxxhdpi/logo.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/mipmap-hdpi/ic_launcher.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/mipmap-mdpi/ic_launcher.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/mipmap-xhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/mipmap-xxhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/Android/src/main/res/mipmap-xxxhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@3x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png is excluded by !**/*.png
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@3x.png is excluded by !**/*.png
  • apps/rspack-test-app/app/images/logo.png is excluded by !**/*.png
  • apps/rspack-test-app/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (35)
  • apps/rspack-test-app/.editorconfig
  • apps/rspack-test-app/.gitignore
  • apps/rspack-test-app/.vscode/extensions.json
  • apps/rspack-test-app/App_Resources/Android/app.gradle
  • apps/rspack-test-app/App_Resources/Android/before-plugins.gradle
  • apps/rspack-test-app/App_Resources/Android/src/main/AndroidManifest.xml
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable-nodpi/splash_screen.xml
  • apps/rspack-test-app/App_Resources/Android/src/main/res/drawable/ic_launcher_foreground.xml
  • apps/rspack-test-app/App_Resources/Android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  • apps/rspack-test-app/App_Resources/Android/src/main/res/values-v21/colors.xml
  • apps/rspack-test-app/App_Resources/Android/src/main/res/values-v21/styles.xml
  • apps/rspack-test-app/App_Resources/Android/src/main/res/values-v29/styles.xml
  • apps/rspack-test-app/App_Resources/Android/src/main/res/values/colors.xml
  • apps/rspack-test-app/App_Resources/Android/src/main/res/values/ic_launcher_background.xml
  • apps/rspack-test-app/App_Resources/Android/src/main/res/values/styles.xml
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/Contents.json
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json
  • apps/rspack-test-app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json
  • apps/rspack-test-app/App_Resources/iOS/Info.plist
  • apps/rspack-test-app/App_Resources/iOS/LaunchScreen.storyboard
  • apps/rspack-test-app/App_Resources/iOS/build.xcconfig
  • apps/rspack-test-app/app/app-root.xml
  • apps/rspack-test-app/app/app.css
  • apps/rspack-test-app/app/app.ts
  • apps/rspack-test-app/app/main-page.ts
  • apps/rspack-test-app/app/main-page.xml
  • apps/rspack-test-app/app/main-view-model.ts
  • apps/rspack-test-app/app/tabs-page.ts
  • apps/rspack-test-app/app/tabs-page.xml
  • apps/rspack-test-app/nativescript.config.ts
  • apps/rspack-test-app/package.json
  • apps/rspack-test-app/references.d.ts
  • apps/rspack-test-app/tsconfig.json
  • apps/rspack-test-app/webpack.config.js

Comment thread apps/rspack-test-app/app/app.css
Comment thread apps/rspack-test-app/app/tabs-page.xml Outdated
Comment thread apps/rspack-test-app/package.json

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (7)
packages/ns-rspack/src/lib/compat.ts (2)

184-198: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Guard the entry-exports shim against an empty entry set.

If entryPoints is empty, pattern is an empty string. The generated test is /^()\.[cm]?js$/, which matches no real asset and still registers NsEntryExportsShim. Skip the plugin when there are no entries.

♻️ Proposed guard
         const entries = [...(config.entryPoints as unknown as ChainedMapLike).store.keys()]
+
+        if (entries.length === 0) {
+            return config
+        }
+
         const pattern = entries.map((name) => name.replace(/[.*+?^${}()|[\]\\/]/g, '\\$&')).join('|')

Note: an early return here would skip the later WatchStatePlugin and Terser steps. Wrap the block in an if (entries.length > 0) condition instead if you keep the flow linear.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ns-rspack/src/lib/compat.ts` around lines 184 - 198, Guard the
NsEntryExportsShim registration using the entries collected from
config.entryPoints in the non-outputModule path. Only create the pattern and
register the BannerPlugin when entries.length is greater than zero; keep the
surrounding flow linear so later WatchStatePlugin and Terser processing still
executes.

68-72: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

toRspackGlob covers only the +(...) extglob form.

globby also supports @(...), ?(...), *(...), and !(...). A user copy rule that uses those forms silently copies nothing, the same failure this function exists to prevent. Extend the rewrite for @(a|b) and ?(a|b), or document the limitation in the README.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ns-rspack/src/lib/compat.ts` around lines 68 - 72, The toRspackGlob
function only rewrites +(…) extglobs, leaving supported @ (a|b) and ?(a|b)
patterns unusable. Extend its rewrite logic to handle the requested @ and ?
forms while preserving the existing +(…) conversion, or document this limitation
in the README.
packages/ns-rspack/src/index.ts (1)

71-76: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

A caller-supplied chain skips adaptChain.

resolveConfig applies adaptChain only through resolveChainableConfig(). If a caller builds a chain and passes it directly, the webpack-only plugins and ts-loader stay in place, and the build fails at compile time. adaptChain is effectively idempotent for an already-adapted chain, so apply it unconditionally.

♻️ Proposed fix
 export function resolveConfig(chainableConfig?: RspackChain): Configuration {
-    const chain = chainableConfig ?? resolveChainableConfig()
+    const chain = chainableConfig ? adaptChain(chainableConfig) : resolveChainableConfig()
     const resolved = nsWebpack.resolveConfig(asWebpackChain(chain))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ns-rspack/src/index.ts` around lines 71 - 76, Update resolveConfig
to apply adaptChain unconditionally to the selected chain, including
caller-supplied chainableConfig, before passing it to asWebpackChain and
nsWebpack.resolveConfig. Preserve the existing resolveChainableConfig path while
ensuring already-adapted chains remain supported.
packages/ns-rspack/src/lib/watch-state-plugin.ts (1)

36-70: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Call callback() after the hook work, not before.

Both hooks signal completion first and then read state and send IPC. Two consequences follow. First, the compiler can continue past the hook while the plugin still reads compilation.getStats(), so the reported state can belong to a compilation the compiler has already moved on from in watch mode. Second, any exception thrown after callback() escapes the hook and becomes an unhandled error instead of a compilation error. Move each callback() to the end of the hook.

♻️ Proposed reordering for `afterEmit`
         compiler.hooks.afterEmit.tapAsync(id, (compilation, callback) => {
-            callback()
-
             if (this.options.stats) {
@@
             this.notify({
                 type: 'compilation',
                 version: 1,
                 hash: compilation.hash ?? undefined,
                 data: { emittedAssets, staleAssets },
             })
+
+            callback()
         })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ns-rspack/src/lib/watch-state-plugin.ts` around lines 36 - 70, Move
the callback() invocation to the end of both the watchRun and afterEmit
handlers, after all state updates, logging, stats processing, and notify work
completes. Preserve the existing hook logic, ensuring exceptions from that work
occur before signaling completion and the compiler cannot proceed until each
handler finishes.
packages/ns-rspack/src/lib/compat.spec.ts (1)

30-40: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the exact replacement plugin.

not.toBe(FakeCustomPlugin) passes for any substitution, including a wrong one. Assert the exported ContextExclusionPlugin instead.

♻️ Proposed stronger assertion
-import { adaptChain, adaptConfig } from './compat.js'
+import { ContextExclusionPlugin, adaptChain, adaptConfig } from './compat.js'
-        expect(config.plugin('ContextExclusionPlugin|App_Resources').get('plugin')).not.toBe(
-            FakeCustomPlugin,
-        )
+        expect(config.plugin('ContextExclusionPlugin|App_Resources').get('plugin')).toBe(
+            ContextExclusionPlugin,
+        )
+        expect(config.plugin('ContextExclusionPlugin|App_Resources').get('args')).toEqual([/x/])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ns-rspack/src/lib/compat.spec.ts` around lines 30 - 40, Update the
assertion in the plugin registration test to verify that the adapted plugin is
exactly the exported ContextExclusionPlugin, replacing the broad
not.toBe(FakeCustomPlugin) check while preserving the existing lookup key and
adaptation flow.
packages/ns-rspack/src/bin/index.ts (1)

104-112: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Watch mode never closes the compiler.

compiler.watch returns a Watching handle. The CLI discards it, so no code path calls watching.close(). On SIGINT or SIGTERM the process exits with the file watchers and the output file system still active. Keep the handle and close it on termination signals.

♻️ Proposed handling
-        compiler.watch(configuration.watchOptions ?? {}, (err, stats) => report(env, err, stats))
+        const watching = compiler.watch(configuration.watchOptions ?? {}, (err, stats) =>
+            report(env, err, stats),
+        )
+
+        for (const signal of ['SIGINT', 'SIGTERM'] as const) {
+            process.once(signal, () => {
+                watching.close(() => process.exit(0))
+            })
+        }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ns-rspack/src/bin/index.ts` around lines 104 - 112, Update the
watch-mode branch around compiler.watch to retain its returned Watching handle
and register SIGINT and SIGTERM handlers that call watching.close() before
termination. Preserve the existing report callback and normal watch-mode flow,
ensuring cleanup occurs only for the active watch instance.
apps/rspack-test-app/nativescript.config.ts (1)

21-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Narrow the compatibility type.

bundler: string accepts invalid bundler names and weakens compile-time checking. Keep the NativeScript bundler type and add only 'rspack'. Use satisfies instead of as so the remaining fields stay checked. The NativeScript CLI has a dedicated Rspack path; unknown values can fall through to webpack executable resolution. (github.com)

This follows the supplied NativeScript CLI and package context.

Proposed type-safe declaration
-} as Omit<NativeScriptConfig, 'bundler'> & { bundler: string };
+} satisfies Omit<NativeScriptConfig, 'bundler'> & {
+  bundler: NativeScriptConfig['bundler'] | 'rspack';
+};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/rspack-test-app/nativescript.config.ts` at line 21, Update the
NativeScript config declaration to preserve the existing NativeScript bundler
type while extending it with only the literal 'rspack'. Replace the broad type
assertion with satisfies so all remaining configuration fields continue to
receive structural validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ns-rspack/src/bin/index.ts`:
- Around line 86-88: Update the environment setup around env.config and
process.env.NATIVESCRIPT_CONFIG_NAME so the variable is assigned only when
env.config is a string. Preserve the existing nullish assignment behavior when a
valid config name is provided, but avoid assigning when env.config is absent to
prevent the literal "undefined" value.
- Around line 27-28: Update parseEnvFlags to convert exact string values "true"
and "false" into boolean true and false while preserving all other values as
strings. Ensure the resulting env.stats value is a boolean so the existing
checks in report and the compatibility logic honor --env.stats=false.

In `@packages/ns-rspack/src/lib/compat.ts`:
- Around line 18-32: Update ContextExclusionPlugin.apply and its
contextModuleFactory hook integration so missing contextModuleFiles support
cannot silently disable exclusions: use a supported ContextModuleFactory hook
for filtering, or throw an explicit compatibility error when no supported hook
exists. Preserve negativeMatcher filtering for supported runtimes.

---

Nitpick comments:
In `@apps/rspack-test-app/nativescript.config.ts`:
- Line 21: Update the NativeScript config declaration to preserve the existing
NativeScript bundler type while extending it with only the literal 'rspack'.
Replace the broad type assertion with satisfies so all remaining configuration
fields continue to receive structural validation.

In `@packages/ns-rspack/src/bin/index.ts`:
- Around line 104-112: Update the watch-mode branch around compiler.watch to
retain its returned Watching handle and register SIGINT and SIGTERM handlers
that call watching.close() before termination. Preserve the existing report
callback and normal watch-mode flow, ensuring cleanup occurs only for the active
watch instance.

In `@packages/ns-rspack/src/index.ts`:
- Around line 71-76: Update resolveConfig to apply adaptChain unconditionally to
the selected chain, including caller-supplied chainableConfig, before passing it
to asWebpackChain and nsWebpack.resolveConfig. Preserve the existing
resolveChainableConfig path while ensuring already-adapted chains remain
supported.

In `@packages/ns-rspack/src/lib/compat.spec.ts`:
- Around line 30-40: Update the assertion in the plugin registration test to
verify that the adapted plugin is exactly the exported ContextExclusionPlugin,
replacing the broad not.toBe(FakeCustomPlugin) check while preserving the
existing lookup key and adaptation flow.

In `@packages/ns-rspack/src/lib/compat.ts`:
- Around line 184-198: Guard the NsEntryExportsShim registration using the
entries collected from config.entryPoints in the non-outputModule path. Only
create the pattern and register the BannerPlugin when entries.length is greater
than zero; keep the surrounding flow linear so later WatchStatePlugin and Terser
processing still executes.
- Around line 68-72: The toRspackGlob function only rewrites +(…) extglobs,
leaving supported @ (a|b) and ?(a|b) patterns unusable. Extend its rewrite logic
to handle the requested @ and ? forms while preserving the existing +(…)
conversion, or document this limitation in the README.

In `@packages/ns-rspack/src/lib/watch-state-plugin.ts`:
- Around line 36-70: Move the callback() invocation to the end of both the
watchRun and afterEmit handlers, after all state updates, logging, stats
processing, and notify work completes. Preserve the existing hook logic,
ensuring exceptions from that work occur before signaling completion and the
compiler cannot proceed until each handler finishes.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fb9ac7c9-fa39-4ecc-b8d5-605083909380

📥 Commits

Reviewing files that changed from the base of the PR and between ab38c2e and d0cdf2d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (18)
  • apps/rspack-test-app/nativescript.config.ts
  • apps/rspack-test-app/package.json
  • apps/rspack-test-app/rspack.config.ts
  • apps/rspack-test-app/tsconfig.json
  • package.json
  • packages/ns-rspack/README.md
  • packages/ns-rspack/package.json
  • packages/ns-rspack/src/bin/index.ts
  • packages/ns-rspack/src/index.ts
  • packages/ns-rspack/src/lib/compat.spec.ts
  • packages/ns-rspack/src/lib/compat.ts
  • packages/ns-rspack/src/lib/watch-state-plugin.ts
  • packages/ns-rspack/tsconfig.json
  • packages/ns-rspack/tsconfig.lib.json
  • packages/ns-rspack/tsconfig.spec.json
  • packages/ns-rspack/vitest.config.mts
  • pnpm-workspace.yaml
  • tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/rspack-test-app/package.json
  • apps/rspack-test-app/tsconfig.json
  • package.json

Comment thread packages/ns-rspack/src/bin/index.ts Outdated
Comment thread packages/ns-rspack/src/bin/index.ts Outdated
Comment thread packages/ns-rspack/src/lib/compat.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ns-rspack/AGENTS.md`:
- Line 25: Update the build command reference in AGENTS.md to invoke the
workspace-local Nx through pnpm, changing the `nx run ns-rspack:build` example
to `pnpm exec nx run ns-rspack:build` while preserving the surrounding
documentation.
- Line 19: Add language identifiers to both fenced code blocks in AGENTS.md:
mark the architecture listing as text and the command block as bash or console,
preserving their existing contents.

In `@README.md`:
- Around line 233-235: Update the shared WebAssembly documentation row in
README.md to accurately reflect the newly added `@cross-code/ns-wasm-edge`,
`@cross-code/ns-wasm-chicory`, and `@cross-code/ns-endive` packages, listing all six
plugins or explicitly limiting WASM.md’s scope to the original wasm3, WAMR, and
WasmKit plugins.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c5fedc77-d393-425c-a6db-7f594ccfd420

📥 Commits

Reviewing files that changed from the base of the PR and between d0cdf2d and 3ffdbc7.

📒 Files selected for processing (3)
  • AGENTS.md
  • README.md
  • packages/ns-rspack/AGENTS.md

Comment thread packages/ns-rspack/AGENTS.md Outdated
Comment thread packages/ns-rspack/AGENTS.md Outdated
Comment thread README.md
listepo and others added 16 commits August 12, 2026 09:55
- --env.<key>=true/false now yield real booleans, matching webpack's CLI
- only set NATIVESCRIPT_CONFIG_NAME when a config name was actually passed
- ContextExclusionPlugin throws when the bundler exposes no
  contextModuleFiles hook instead of silently bundling excluded files
- test app: wire NavigationButton back to onClose, dark-theme card colors
- bump TypeScript ~5.4.0 → ~6.0.3 to match the workspace (the shared
  tsconfig.base.json uses noUncheckedSideEffectImports, a TS ≥5.6 option)
- add @nativescript/types-android/types-ios as direct devDependencies —
  the umbrella @nativescript/types references them via ../ paths, and
  pnpm only links direct deps into node_modules/@NativeScript
- tsconfig: ignoreDeprecations 6.0 (baseUrl), composite + outDir/tsBuildInfoFile
  so the nx typecheck target (tsc --build --emitDeclarationOnly) works
- root tsconfig: nx sync registers the app as a project reference
… webpack

Both apps now set bundler: 'rspack' in nativescript.config.ts and ship a
rspack.config.ts; @nativescript/webpack, ts-loader and postcss-loader are
replaced by @nativescript/rspack (file: alias to @cross-code/ns-rspack,
the name the {N} CLI resolves the bundler by). The ns-wasm-test WASM
copy rules and Vitest test entry move from webpack.config.js into
rspack.config.ts.

- vitest-ns webpack.cjs helper is now bundler-agnostic: it calls
  chainRspack when the module exposes it, chainWebpack otherwise — the
  chain API is identical in both
- add @nativescript/types-android/types-ios devDeps to both apps so the
  umbrella @nativescript/types references resolve (pnpm only links
  direct deps)
- ns-wasm-test/nativescript.config.ts type widened for bundler: 'rspack'
- project.json typecheck inputs track rspack.config.ts
- CI: build ns-rspack before the app installs (file: snapshot), and
  trigger app jobs when packages/ns-rspack changes
- rspack-test-app tsconfig: nx sync's TS6 rewrite (drop baseUrl,
  relative paths, ignoreDeprecations no longer needed)
The standalone apps are their own pnpm workspace roots; they now expose the
sibling packages they consume through the workspace: protocol
(pnpm-workspace.yaml packages: ../../packages/...), replacing file:
dependencies. The apps stay separate installs with their own lockfiles —
only the listed packages are reachable, never the root workspace.

- ns-wasm-test: ns-wasm-core override dropped; the plugins' workspace:*
  core reference now resolves against the app's own workspace
- ns-wry-app: ns-wry and ns-rspack linked via workspace:
- CI: reword the build-before-install comments (workspace: links, no
  file: snapshotting)
- AGENTS.md: package wiring section updated
rspack 2.x's ContextModuleFactory exposes only beforeResolve/afterResolve
and enumerates context files in Rust, so the contextModuleFiles hook never
exists — the previous fail-loudly behavior broke every rspack build at
plugin apply time (the wasm-test app bundle failed, ns run exited 127, and
vitest then timed out tearing the device worker down).

The exclusion is best-effort: the ~/ context is scoped to the app dir
(App_Resources is a sibling), and platform-suffixed files are rare. Warn
once instead of throwing; keep the hook tap for bundlers that do expose it.

Verified end-to-end: the ns-wasm-test iOS bundle compiles, emits the
vitest-ns worker entry, enumerates all 8 spec files via require.context,
and copies both .wasm fixtures.
The app's hooks dir had two before-checkForChanges trampolines:
nativescript-core.mjs (core 9.0.20, correct) and nativescript-core.js
(stale, requiring a .js cli-hook that core 9.0.20 does not ship). The
CLI loads every file in the hooks dir, so the stale .js one threw
'Cannot find module @nativescript/core/cli-hooks/before-checkForChanges.js'
after the first rspack compilation and ns run exited 127.

The .js trampoline is written by @nativescript/core 8.9.9's postinstall
(@nativescript/hook 2.0.0). It entered the app's install because the app
workspace now includes packages/* as members and pnpm installs their
devDependencies — ns-wamr declared a vestigial @nativescript/core ^8.9.0
devDep that nothing imports.

- remove the unused @nativescript/core devDep from packages/ns-wamr
- regenerate root + app lockfiles (core 8.9.9 and hook 2.0.0 gone)
- delete the stale nativescript-core.js trampolines in both apps (hooks/
  is gitignored; core 9.0.20's postinstall regenerates the .mjs hook)
- nx sync: apps' tsconfigs gain the ns-rspack project reference
- ci.yml: drop continue-on-error from wasm-test-android per the
  never-continue-on-error policy (AGENTS.md)
Rstest has no custom-pool API, so @cross-code/ns-rstest owns its own Node
host: runNativeScriptTests() globs the spec files, launches the NativeScript
CLI (ns run --env.rstestNativeScript), round-robins files across device
worker slots, and reports through Rstest's Reporter interface. On device it
drives Rstest's own browser runtime (@rstest/core/internal/browser-runtime)
inside a Worker; a shim on globalThis['@rstest/core'] forwards the per-file
API Rstest publishes, and the optional results view ships from
@cross-code/ns-rstest/ui.

- new package packages/ns-rstest (Node host, protocol, worker runtime, shim,
  UI); deletes packages/vitest-ns and packages/vitest-ns-ui
- app: vitest-ns.ts/.worker.ts -> ns-rstest.ts/.worker.ts; specs import from
  @rstest/core; host runners are ns-rstest.ios.mts / .android.mts run via
  node (type stripping); rspack.config.ts swaps the bundler hook for
  configureNativeScriptRstest (env.rstestNativeScript, Istanbul coverage)
- nx-ns-app: drop the vitest pool option from NsTestOptions
- CI/docs: vitest-ns references -> ns-rstest; device jobs build ns-rstest
  before installing the app
- crlf -> lf normalization in ci.yml / code-review.yml

Verified: 16-project test+typecheck+build all pass; the ns-rstest host
launches the CLI, rspack emits the worker bundle with all 8 spec files
enumerated, and the rstest entry swaps in under env.rstestNativeScript.
Adds @cross-code/ns-lynx, a NativeScript plugin embedding the Lynx engine as
a <LynxView> inside a NativeScript host page. NativeScript is the host; Lynx
renders a ReactLynx bundle subtree. The plugin has no native layer: Lynx
ships its engine via CocoaPods (iOS) and Maven Central (Android), and the
metadata/static-binding generators expose those classes to JS directly.

- src/lib/bundle.ts — src→location rules + JSON coercion (unit-tested)
- lynx-view-{common,ios,android}.ts — properties/events, File.readSync bytes
  handed to LynxLoadMeta.binaryData (no TemplateProvider subclass)
- platforms/ios/Podfile + platforms/android/include.gradle — pinned Lynx 4.0.1
  / PrimJS 4.0.0; Demote iOS warnings-as-errors and drop PrimJS's module map
  so the metadata generator stops crashing on its C++ headers
- apps/ns-lynx-app — worked example: rspeedy ReactLynx bundle copied into the
  app folder by rspack, rendered in a <LynxView> beside native views
- CI: build + coverage ns-lynx; docs in root AGENTS/README
Replace the @nativescript/webpack compat layer with a first-party rspack
pipeline, prove it on ns-lynx-app via ns-rstest, and prefix test entries
so they stay out of require.context.

Co-authored-by: Cursor <cursoragent@cursor.com>
native-class-strip-loader only matched `class` and `export class`, so
`@NativeClass export default class X extends NSObject` reached the device
as an ES6 class and threw when the runtime constructed it. Extend the
lookahead to `export default` and `abstract` in every valid combination.

getIPS() returned loopback addresses alongside real ones, so
`__NS_DEV_HOST_IPS__` told the device to look for the dev host at
127.0.0.1 — itself. Skip internal interfaces.

Dev builds now always inline source maps, for the reason the comment
already gave: Chrome DevTools cannot fetch external .map files in this
debugging flow, so the external maps {N} 9 used to get were unusable.

Also keep the test-only project fixture out of the published build, and
stop claiming there is no webpack in the dependency tree — webpack-merge
is still there as a deep-merge helper.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…g them

`ns typings` output is generated from the built platform project, but the
root ignore rule was `/typings` — anchored to the repo root, so it only
covered a directory that never existed there. Running `ns typings android`
from a plugin package left a stray `typings/` behind in ns-wamr, ns-wasm3
and ns-wasm-chicory, permanently visible as untracked noise. Ignore
`typings/` at any depth and drop the three strays.

Give the generation a home instead: ns-wasm-test owns `platforms/`, so it
owns the Nx targets, which depend on `prepare.<platform>` and declare
`typings/<platform>` as cacheable output. ns-wamr's package scripts now
delegate there rather than repeating the command with a relative `cd` —
the shape that produced the strays in the first place.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
webpack-merge was the last thing keeping "webpack" in this package's
dependency tree, and it was only ever there for one function. rspack-merge
is the replacement rspack's own docs name: a zero-dependency fork with an
identical signature, published under the same org as rspack-chain, which
this package already depends on. The swap is an import change — `merge`,
`Utils.merge` and the plugin-facing `api.merge` keep working unchanged for
third-party configs.

`merge` is public API, so its semantics are now pinned by tests rather than
by whatever the dependency happens to do: plugins concatenate as live
instances instead of being deep-merged, RegExp rule tests survive, nested
splitChunks cacheGroups deep-merge, function values stay callable, and the
inputs are not mutated.

Tests move from vitest to Rstest, rspack's own runner. Two things that
migration forces, both of which are properties of Rstest bundling sources
through rspack rather than transforming them per file:

  - hmr-runtime.ts now reads `module` through a local binding. A direct
    `module.hot` test is statically folded to a constant and the branch
    deleted — and that function is stringified, not executed, so the
    bundler was silently emitting an empty HMR runtime.
  - the module-mock APIs are rewritten by a native rspack plugin and must
    be called literally as `rs.mock()` / `rs.resetModules()`, so the specs
    rename the identifier rather than aliasing the import.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Istanbul instruments the source, so the numbers do not depend on the engine
running the tests, and it is what the device suites in @cross-code/ns-rstest
already have to use — the {N} runtimes expose no V8 coverage. Both halves of
the repo now report the same way. Rstest offers no third provider.

Switching provider surfaced a latent hazard rather than just changing a
number: hmr-runtime.ts exports a function that is stringified and appended
to the app bundle, never called. Istanbul instrumented it, so the text
carried `cov_*()` counters referencing a global that does not exist on
device, and two specs failed with a ReferenceError. An `istanbul ignore
next` keeps the function reaching `.toString()` untouched — the same
constraint that already forces it to read `module` through a local binding.

Also ignore `test-output/` at any depth: the coverage report lands there,
and the previous rule was pinned to apps/ns-wasm-test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Move NSArray/Java byte helpers into ns-wasm-core and replace adapter `any`
with structural native-api types so wrong selectors fail at compile time.
Fix wamr-ffi call_raw slot sizing and add regression tests for multi-return calls.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add durable agent gotchas at the repo and ns-rspack package roots, split
ns-lynx-app production vs rstest tsconfig like ns-wasm-test, run nx-ns-app
executors from the app directory, and fix rstest results double-rendering.

Co-authored-by: Cursor <cursoragent@cursor.com>
listepo and others added 16 commits August 20, 2026 02:25
Import WamrError from wire.js so toThrow assertions match at runtime, drop
spec `any`, and link tsconfig.spec.json to the library project for build mode.

Co-authored-by: Cursor <cursoragent@cursor.com>
Apply the same structural native-api declarations and ns-wasm-core bridge
helpers as wasm3/wamr, and tighten the device-mirror fakes so typecheck passes.

Co-authored-by: Cursor <cursoragent@cursor.com>
…switch

Update ns-wasm-test and ns-wry-app pnpm-lock.yaml so frozen-lockfile CI
installs match @rstest/coverage-istanbul in packages/ns-rspack/package.json.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add tools/verify-nested-lockfiles.mjs and run it in unit-tests so stale
apps/*/pnpm-lock.yaml files fail fast when linked packages like ns-rspack
change dependencies without regenerating each nested lockfile.

Co-authored-by: Cursor <cursoragent@cursor.com>
The lockfile verification commit accidentally staged unrelated deletions.
Restore the ambient native declarations both plugins still reference.

Co-authored-by: Cursor <cursoragent@cursor.com>
…-edge, wry

Same pattern already applied to wamr/wasm3/wasm-kit: replace `any`-typed
globalThis probes with ambient declarations scoped to the surface each
adapter actually calls, so a renamed method or wrong arity fails the build
instead of returning `undefined` on a device.

ns-wasm-core's nativeArrayToJs now also handles java.util.List's
size()-based length (iOS NativeArrayLike only had .count/.length), which is
what lets ns-endive drop its local copy of the same list-walking loop.

.oxlintrc.json un-ignores hand-written src/**/*.d.ts — it was blanket-
ignoring every .d.ts, generated or not, so oxlint's no-explicit-any rule
never actually reached these ambient declarations. ns-wry's Rust crates get
the same #![deny(unsafe_op_in_unsafe_fn)] already applied to the other
native crates, verified via `cargo check`.

Also cleans up the remaining `any` in the two test apps and in nx-ns-app's
executor specs, and wires nx-ns-app's tsconfig.spec.json into typecheck so
the spec files stay covered going forward.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
On edition 2021, a temporary created in an `if let` scrutinee lives to the
end of the whole `if let` block, not just the condition — so
`lock(&GLOBAL_LAST_RESULTS)`'s MutexGuard stayed alive through the entire
body, and the body's own `*lock(&GLOBAL_LAST_RESULTS) = None` re-lock
deadlocked against it. `cargo test -p wamr-sys` hung indefinitely at 0% CPU.

Read the handle out and drop the guard before branching on it, same as the
call sites already do elsewhere in this file.

Verified with `cargo test -p wamr-sys --test integration_test` (bounded to
90s given the prior hang): 7/7 pass in under a millisecond.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Five iOS bridge methods were declared and called under the wrong
flattened @objc selector: the first, unlabeled Swift parameter was
mistakenly folded into the name (e.g. loadModuleBytesError instead of
loadModuleFromBytesError). An unlabeled Swift parameter contributes
nothing to the selector, so these calls resolved to methods the real
NSWasmKit runtime never exposed, failing every device test.

Corrected linkHostFunctionModuleNameNameSignatureCallbackError,
getGlobalNameError, setGlobalNameValueError, loadModuleBytesError, and
loadModuleFileError to match the actual Swift signatures.
NSCWamrHostFunction/NSCWasm3HostFunction are Kotlin fun interfaces
(single-abstract-method), not classes. The adapters called them
through NativeScript's .extend() subclassing hook, which only applies
to real subclassable classes; against a fun interface it fails
resolving a nonexistent 0-arg super-constructor on every device test.

Construct the interface directly with an object exposing `invoke`,
matching the working pattern already used for ns-wasm-chicory's
NSCChicoryHostFunction. Retype NSCWa{mr,sm3}HostFunctionClass from
.extend() to a constructor signature, and drop the now-unreachable
static extend() shim from the three Vitest fakes.
Whitespace-only rustfmt reflow to fix the failing fmt.rust CI check
for ns-wamr, ns-wasm3, ns-wry. No behavior change.
Every host-import call on-device failed with "host function returned
invalid values" once the prior SAM-constructor fix let the callback
actually run: linkHostFunction boxed the result as java.lang.Double
before returning it from the invoke() callback, but that boxing is
only correct for values passed *into* a Java method call. A value
returned *from* a JS callback needs to cross the NativeScript bridge
as a plain JS type so the bridge can convert it itself — mirroring
ns-wasm-chicory's makeAndroidHostCallback, which already documents
this exact distinction.

Not caught locally: the Vitest fakes invoke the callback directly in
JS with no native marshaling involved, so this class of bug only
surfaces on a real device.
nativeArrayToJs only knew how to read an NSArray (.count/.objectAtIndex)
or a java.util.List (.size()/.get()). A host-import's arguments cross
the NativeScript Android bridge as neither: a plain-JS-like wrapper
with .length and indexed access only. Every element silently read as
undefined, normalized to the literal string "undefined", so every
host function on Android ran on garbage input — the same trap
("host function returned invalid values") the prior return-boxing fix
addressed, but from the argument side, which is why wamr/wasm3's
fixture-module host-function tests kept failing after that fix.

ns-wasm-chicory already worked around this with its own local
javaArrayToJs; folded the same fallback into the shared helper so
wamr and wasm3 (and any future adapter) get it too, and added
native-bridge.spec.ts to cover the three known array shapes directly
— this class of bug has repeatedly only surfaced on-device.
- Remove prebuilt iOS XCFrameworks, Android AARs, and native symbols from Git

- Add .gitignore patterns for native build outputs and SwiftPM caches

- Update AGENTS.md with the new nx-buck2/Buck2 build workflow

- Update CI to install Buck2 and build artifacts on demand

- Add nx-buck2 executor support for debug/release profiles

- Update BUCK files, package.json files, and Rust build configs
Migrate nx-buck2 compiled output to dist/ via @nx/js:tsc and pin
RUSTUP_HOME/CARGO_HOME when buck2 overrides HOME so cargo-ndk finds the
toolchain. Redirect Gradle build dirs outside platforms/android/, fix
jniLibs paths to follow the redirect, add gradlew-retry for transient
genrule failures, and correct the CI emulator script's per-line shell
constraints.

Co-authored-by: Cursor <cursoragent@cursor.com>
@listepo

listepo commented Aug 20, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review skipped: 504 files exceed the limit of 100.

@listepo

listepo commented Aug 20, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review skipped: 504 files exceed the limit of 100.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

listepo and others added 5 commits August 20, 2026 15:06
Buck2 genrules write nativescript-*.aar into the srcs sandbox, so CI
built the app without the engine AARs and device tests failed with
native runtime not found. Install the artifact next to include.gradle
and fail fast if it is missing.

Co-authored-by: Cursor <cursoragent@cursor.com>
@listepo
listepo merged commit b5fa08e into main Aug 20, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant