Skip to content

feat: reloadApplication for JS bundle restart without restarting app process#1963

Open
NathanWalker wants to merge 5 commits into
mainfrom
feat/reload-app
Open

feat: reloadApplication for JS bundle restart without restarting app process#1963
NathanWalker wants to merge 5 commits into
mainfrom
feat/reload-app

Conversation

@NathanWalker

@NathanWalker NathanWalker commented Jun 7, 2026

Copy link
Copy Markdown
Contributor
NativeScriptRuntime.reloadApplication()

Helpful for programmatic reset of JS isolate for clean restart of JS application as well as OTA (over-the-air) updates without restarting the entire app process.

NativeScript/ios#384

Summary by CodeRabbit

  • New Features
    • Added hot-reload support via the public runtime API, including optional base directory handling.
  • Bug Fixes
    • Prevent duplicate hot-reload scheduling and improve hot-reload reliability.
    • Improve main runtime shutdown cleanup, including worker termination and safer runtime teardown.
    • Refined timezone change listener behavior to avoid duplicate registrations and stale receivers across reloads.

…process

Helpful for programmatic reset of JS isolate for clean restart of JS application as well as OTA (over-the-air) updates without restarting the entire app process.
@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ff7a1228-b4bd-4fdb-897a-7124797c704f

📥 Commits

Reviewing files that changed from the base of the PR and between 80cfbce and 0bc3036.

📒 Files selected for processing (2)
  • test-app/runtime/src/main/cpp/com_tns_Runtime.cpp
  • test-app/runtime/src/main/java/com/tns/Runtime.java

📝 Walkthrough

Walkthrough

The PR adds Java reload entry points, main-thread restart scheduling, runtime shutdown orchestration, and a native termination callback. It also updates timezone receiver registration to use a cached application context.

Changes

Application reload and runtime teardown

Layer / File(s) Summary
Reload facade
test-app/app/src/main/java/com/tns/NativeScriptRuntime.java
NativeScriptRuntime adds static reloadApplication overloads and a private constructor.
Reload state and timezone registration
test-app/app/src/main/java/com/tns/RuntimeHelper.java
RuntimeHelper adds reload state, caches application context during initialization, and updates timezone receiver registration to use the cached context and tracked receiver.
Main-thread reload execution
test-app/app/src/main/java/com/tns/RuntimeHelper.java
RuntimeHelper.reloadApplication() schedules restart work on the main thread, destroys the main runtime, reinitializes it from the cached context, runs it, and clears the scheduling guard in finally.
Runtime shutdown orchestration
test-app/runtime/src/main/java/com/tns/Runtime.java
Runtime adds a JNI declaration for TerminateRuntimeCallback(int) and destroyMainRuntime() validates the main runtime, unsubscribes listeners, clears runtime state, and calls the native termination callback.
Native termination callback
test-app/runtime/src/main/cpp/com_tns_Runtime.cpp
com_tns_Runtime.cpp adds WorkerWrapper.h and the native Java_com_tns_Runtime_TerminateRuntimeCallback, which resolves the runtime, terminates child workers, destroys the runtime, disposes the isolate, and deletes the runtime.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 I hop through reloads, quick and bright,
Main-thread sparks and runtime light.
Workers hush, then fresh code streams,
A bunny bounces through restart dreams.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding reloadApplication to restart the JS bundle without restarting the app process.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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.

@NathanWalker NathanWalker marked this pull request as ready for review June 25, 2026 19:05
@NathanWalker

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":500,"request":{"method":"PATCH","url":"https://api.github.com/repos/NativeScript/android/issues/comments/4644331376","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- review_stack_entry_start -->\n\n[![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/NativeScript/android/pull/1963?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)\n\n<!-- review_stack_entry_end -->\n<!-- This is an auto-generated comment: review in progress by coderabbit.ai -->\n\n> [!NOTE]\n> Currently processing new changes in this PR. This may take a few minutes, please wait...\n> \n> <details>\n> <summary>⚙️ Run configuration</summary>\n> \n> **Configuration used**: Repository UI\n> \n> **Review profile**: CHILL\n> \n> **Plan**: Pro\n> \n> **Run ID**: `c0734d0e-2bd3-477e-bb92-e2612ac6c7a8`\n> \n> </details>\n> \n> <details>\n> <summary>📥 Commits</summary>\n> \n> Reviewing files that changed from the base of the PR and between bfd765043aaa30cc1ef14d00e3cebfa04e980597 and 187b183c718ddee1b3d3804dd7ddfd1ee6b8839d.\n> \n> </details>\n> \n> <details>\n> <summary>📒 Files selected for processing (4)</summary>\n> \n> * `test-app/app/src/main/java/com/tns/NativeScriptRuntime.java`\n> * `test-app/app/src/main/java/com/tns/RuntimeHelper.java`\n> * `test-app/runtime/src/main/cpp/com_tns_Runtime.cpp`\n> * `test-app/runtime/src/main/java/com/tns/Runtime.java`\n> \n> </details>\n> \n> ```ascii\n>  ______________________________________________________________\n> < Ad Astra Per Codicem Fixis. To the stars through code fixes. >\n>  --------------------------------------------------------------\n>   \\\n>    \\   (\\__/)\n>        (•ㅅ•)\n>        /   づ\n> ```\n\n<!-- end of auto-generated comment: review in progress by coderabbit.ai -->\n\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing Touches</summary>\n\n<details>\n<summary>📝 Generate docstrings</summary>\n\n- [ ] <!-- {\"checkboxId\": \"7962f53c-55bc-4827-bfbf-6a18da830691\"} --> Create stacked PR\n- [ ] <!-- {\"checkboxId\": \"3e1879ae-f29b-4d0d-8e06-d12b7ba33d98\"} --> Commit on current branch\n\n</details>\n<details open>\n<summary>⚔️ Resolve merge conflicts</summary>\n\n- [ ] <!-- {\"checkboxId\": \"c3a5b2e1-4d7f-4a8c-b9d6-e1f2c3d4a5b6\"} --> Resolve merge conflict in branch `feat/reload-app`\n\n</details>\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n<!-- tips_start -->\n\n---\n\nThanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=NativeScript/android&utm_content=1963)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.\n\n<details>\n<summary>❤️ Share</summary>\n\n- [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)\n- [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)\n- [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)\n- [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)\n\n</details>\n\n\n<sub>Comment `@coderabbitai help` to get the list of available commands.</sub>\n\n<!-- tips_end -->"},"request":{"retryCount":3,"signal":{},"retries":3,"retryAfter":16}}}

Copilot AI commented Jun 25, 2026

Copy link
Copy Markdown

@copilot resolve the merge conflicts in this pull request

Resolved and pushed via merge commit 7b1f57c8 (merged origin/main into this branch and fixed both conflict files: Runtime.java and com_tns_Runtime.cpp).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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 `@test-app/app/src/main/java/com/tns/NativeScriptRuntime.java`:
- Around line 11-12: The NativeScriptRuntime.reloadApplication(String baseDir)
overload currently drops its baseDir argument, so callers cannot reload from a
chosen bundle location. Update this method to either pass baseDir through to a
new RuntimeHelper.reloadApplication(String baseDir) implementation that rebuilds
the runtime config from that directory, or remove the overload if it is not
meant to be supported; keep the API behavior aligned with the method signature
and related RuntimeHelper reload logic.

In `@test-app/app/src/main/java/com/tns/RuntimeHelper.java`:
- Around line 340-349: `registerTimezoneChangedListener` is unregistering
`timezoneChangedReceiver` with whatever `context` is passed in, but that can
differ between the initial call and `reloadApplication`, causing the old
receiver to remain registered. Update the listener bookkeeping so the same
Context instance used for registration is also used for `unregisterReceiver`
(for example by storing the registering Context alongside
`timezoneChangedReceiver` or consistently using `applicationContext` in
`registerTimezoneChangedListener` and its callers). Keep the existing
`IllegalArgumentException` handling only for truly stale registrations, and
ensure the old receiver is fully removed before assigning and registering the
new one.

In `@test-app/runtime/src/main/cpp/com_tns_Runtime.cpp`:
- Around line 358-362: The null-runtime checks in the affected callbacks do not
stop execution, so `runtime->GetIsolate()` can still be called on a null pointer
and crash. In each callback that resolves a `runtime` and then uses it
(`com_tns_Runtime` helpers around the reported branches), add an immediate
return inside the `if (runtime == nullptr)` path before any dereference, and
apply the same early-exit pattern consistently to all listed null-runtime
branches.

In `@test-app/runtime/src/main/java/com/tns/Runtime.java`:
- Around line 478-500: The termination flow in Runtime.destroyMainRuntime() and
terminateWorkers() is racing because the TerminateThread message is posted
asynchronously and workerIdToHandler is cleared immediately afterward. Add a
blocking handshake so terminateWorkers() waits until each worker has actually
processed the termination signal before destroyMainRuntime() continues with
runtimeCache.remove(), pendingWorkerMessages.clear(), currentRuntime.remove(),
and TerminateRuntimeCallback. Use the existing Runtime and workerHandler
messaging path to coordinate completion, and only clear workerIdToHandler after
all workers confirm shutdown.
🪄 Autofix (Beta)

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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e52793de-9a24-4365-9c36-5c412d5895b3

📥 Commits

Reviewing files that changed from the base of the PR and between 92c2654 and 7b1f57c.

📒 Files selected for processing (4)
  • test-app/app/src/main/java/com/tns/NativeScriptRuntime.java
  • test-app/app/src/main/java/com/tns/RuntimeHelper.java
  • test-app/runtime/src/main/cpp/com_tns_Runtime.cpp
  • test-app/runtime/src/main/java/com/tns/Runtime.java

Comment thread test-app/app/src/main/java/com/tns/NativeScriptRuntime.java Outdated
Comment thread test-app/app/src/main/java/com/tns/RuntimeHelper.java Outdated
Comment thread test-app/runtime/src/main/cpp/com_tns_Runtime.cpp Outdated
Comment thread test-app/runtime/src/main/java/com/tns/Runtime.java Outdated
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.

2 participants