This repository was archived by the owner on Aug 27, 2026. It is now read-only.

Add ManagedPeer native registration feature switch - #1434

Merged
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch
May 26, 2026
Merged

Add ManagedPeer native registration feature switch#1434
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Adds a Java.Interop-owned feature switch for legacy ManagedPeer native registration.

.NET for Android trimmable typemap builds register native methods through generated JCW static initializers, so they do not need the legacy ManagedPeer native registration path. Keeping this behind a default-on switch preserves existing Java.Interop and non-trimmable behavior while allowing trimmable Android apps to disable the path and let ILLink remove the dead ManagedPeer root.

Validation:

  • dotnet build src/Java.Interop/Java.Interop.csproj -v:minimal

Allow callers to disable legacy ManagedPeer native registration so trimmable Android apps can avoid rooting ManagedPeer when they register native methods through generated JCW initializers instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 25, 2026 09:19

CopilotAI 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.

Pull request overview

Adds a Java.Interop-owned runtime feature switch to optionally disable the legacy ManagedPeer native registration path, primarily to enable trimming of the ManagedPeer root for trimmable .NET for Android typemap builds while preserving existing behavior by default.

Changes:

  • Introduces Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration backed by an AppContext feature switch (default: enabled).
  • Gates ManagedPeer.Init() during JniRuntime construction behind the feature switch.
  • Conditionally includes the net/dot/jni/ManagedPeer built-in type mapping only when the feature switch is enabled.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/Java.Interop/Java.Interop/RuntimeFeature.csAdds the new AppContext-based feature switch definition for runtime behavior control.
src/Java.Interop/Java.Interop/JniRuntime.csUses the feature switch to optionally skip legacy ManagedPeer native registration initialization.
src/Java.Interop/Java.Interop/JniBuiltinMarshalers.csUses the feature switch to optionally avoid adding the ManagedPeer type mapping (to reduce trimming roots).

Comment threadsrc/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.cs
simonrozsivaland others added 8 commits May 25, 2026 12:08
Let embedders opt out of ManagedPeer native registration through JniRuntime.CreationOptions instead of a Java.Interop runtimeconfig feature switch. This keeps the default Java.Interop behavior while allowing Android's trimmable runtime path to disable the legacy ManagedPeer registration path without emitting a Java.Interop-specific runtimeconfig value.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the generated JniBuiltinMarshalers template aligned with the generated source after removing the ManagedPeer simple-reference mapping, and add coverage that disabling ManagedPeer native registration skips the init hook.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a regression test that the built-in simple-reference map no longer resolves the internal ManagedPeer bridge type, documenting that the mapping removal is unconditional rather than driven by per-runtime options.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep legacy ManagedPeer native registration enabled by default and use the trim-aware Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration switch to disable it for trimmable consumers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add coverage that disabling Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration skips ManagedPeer.Init(), while keeping the switch trim-aware and default-enabled for legacy behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the test-only InitCallCount field from ManagedPeer so production code is not changed solely for test coverage.
Keep switch-off coverage by observing the ManagedPeer built-in type mapping instead of recording Init() calls.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evaluate the ManagedPeer builtin type mapping at lookup time instead of caching the runtime switch value in the lazy builtin map. This lets tests and embedders disable ManagedPeer native registration after the common builtin map has already been initialized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this ready-to-review This PR is ready to review/merge, thanks! labels May 25, 2026
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 26, 2026

Copy link
Copy Markdown

Java.Interop PR Reviewer completed successfully!

@github-actionsgithub-actionsBot 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.

✅ LGTM — Clean feature switch implementation

Summary: This PR adds a [FeatureSwitchDefinition]-backed RuntimeFeature.ManagedPeerNativeRegistration switch that gates legacy ManagedPeer native registration. The pattern is correct: default-on preserves existing behavior, and trimmable Android builds can set the switch to false so ILLink removes the dead code path.

What's done well:

  • Both the .tt template and generated .cs are updated consistently — T4 regen won't revert the change.
  • [FeatureSwitchDefinition] ensures the trimmer substitutes the property with a constant — zero runtime cost in trimmed builds.
  • [NonParallelizable] correctly applied since AppContext.SetSwitch mutates process-global state.
  • Tests cover both the default-on path and the switch-off path with proper try/finally cleanup.

Issues: 0 ❌ · 1 ⚠️ · 2 💡

SeverityFileIssue
⚠️JniRuntime.JniTypeManager.cs:376Swap condition order — put cheap string check before AppContext.TryGetSwitch
💡RuntimeFeature.cs:1Redundant #nullable enable (project-level setting)
💡JniRuntime.JniTypeManager.cs:140Spurious extra blank line

CI note: Only license/cla is visible in check runs. No build/test CI results were found to verify.

Generated by Java.Interop PR Reviewer for issue #1434 · ● 3.2M

Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/RuntimeFeature.cs Outdated
@jonathanpeppers

Copy link
Copy Markdown
Member

CopilotAI commented May 26, 2026

Copy link
Copy Markdown
Contributor

@copilot can you fix the two formatting comments:

Fixed in f628dba:

  • Removed the spurious extra blank line in JniRuntime.JniTypeManager.cs (now one blank line between the closing } and the // NOTE comment)
  • Removed the redundant #nullable enable from RuntimeFeature.cs (project-level <Nullable>enable</Nullable> already covers it)

@jonathanpeppers
jonathanpeppers merged commit 41d01af into mainMay 26, 2026
2 checks passed
@jonathanpeppers
jonathanpeppers deleted the dev/simonrozsival/managedpeer-feature-switch branch May 26, 2026 14:39
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, thanks!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

Add ManagedPeer native registration feature switch - #1434

Merged
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch
May 26, 2026
Merged

Add ManagedPeer native registration feature switch#1434
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Adds a Java.Interop-owned feature switch for legacy ManagedPeer native registration.

.NET for Android trimmable typemap builds register native methods through generated JCW static initializers, so they do not need the legacy ManagedPeer native registration path. Keeping this behind a default-on switch preserves existing Java.Interop and non-trimmable behavior while allowing trimmable Android apps to disable the path and let ILLink remove the dead ManagedPeer root.

Validation:

  • dotnet build src/Java.Interop/Java.Interop.csproj -v:minimal

Allow callers to disable legacy ManagedPeer native registration so trimmable Android apps can avoid rooting ManagedPeer when they register native methods through generated JCW initializers instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 25, 2026 09:19

CopilotAI 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.

Pull request overview

Adds a Java.Interop-owned runtime feature switch to optionally disable the legacy ManagedPeer native registration path, primarily to enable trimming of the ManagedPeer root for trimmable .NET for Android typemap builds while preserving existing behavior by default.

Changes:

  • Introduces Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration backed by an AppContext feature switch (default: enabled).
  • Gates ManagedPeer.Init() during JniRuntime construction behind the feature switch.
  • Conditionally includes the net/dot/jni/ManagedPeer built-in type mapping only when the feature switch is enabled.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/Java.Interop/Java.Interop/RuntimeFeature.csAdds the new AppContext-based feature switch definition for runtime behavior control.
src/Java.Interop/Java.Interop/JniRuntime.csUses the feature switch to optionally skip legacy ManagedPeer native registration initialization.
src/Java.Interop/Java.Interop/JniBuiltinMarshalers.csUses the feature switch to optionally avoid adding the ManagedPeer type mapping (to reduce trimming roots).

Comment threadsrc/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.cs
simonrozsivaland others added 8 commits May 25, 2026 12:08
Let embedders opt out of ManagedPeer native registration through JniRuntime.CreationOptions instead of a Java.Interop runtimeconfig feature switch. This keeps the default Java.Interop behavior while allowing Android's trimmable runtime path to disable the legacy ManagedPeer registration path without emitting a Java.Interop-specific runtimeconfig value.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the generated JniBuiltinMarshalers template aligned with the generated source after removing the ManagedPeer simple-reference mapping, and add coverage that disabling ManagedPeer native registration skips the init hook.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a regression test that the built-in simple-reference map no longer resolves the internal ManagedPeer bridge type, documenting that the mapping removal is unconditional rather than driven by per-runtime options.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep legacy ManagedPeer native registration enabled by default and use the trim-aware Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration switch to disable it for trimmable consumers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add coverage that disabling Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration skips ManagedPeer.Init(), while keeping the switch trim-aware and default-enabled for legacy behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the test-only InitCallCount field from ManagedPeer so production code is not changed solely for test coverage.
Keep switch-off coverage by observing the ManagedPeer built-in type mapping instead of recording Init() calls.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evaluate the ManagedPeer builtin type mapping at lookup time instead of caching the runtime switch value in the lazy builtin map. This lets tests and embedders disable ManagedPeer native registration after the common builtin map has already been initialized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this ready-to-review This PR is ready to review/merge, thanks! labels May 25, 2026
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 26, 2026

Copy link
Copy Markdown

Java.Interop PR Reviewer completed successfully!

@github-actionsgithub-actionsBot 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.

✅ LGTM — Clean feature switch implementation

Summary: This PR adds a [FeatureSwitchDefinition]-backed RuntimeFeature.ManagedPeerNativeRegistration switch that gates legacy ManagedPeer native registration. The pattern is correct: default-on preserves existing behavior, and trimmable Android builds can set the switch to false so ILLink removes the dead code path.

What's done well:

  • Both the .tt template and generated .cs are updated consistently — T4 regen won't revert the change.
  • [FeatureSwitchDefinition] ensures the trimmer substitutes the property with a constant — zero runtime cost in trimmed builds.
  • [NonParallelizable] correctly applied since AppContext.SetSwitch mutates process-global state.
  • Tests cover both the default-on path and the switch-off path with proper try/finally cleanup.

Issues: 0 ❌ · 1 ⚠️ · 2 💡

SeverityFileIssue
⚠️JniRuntime.JniTypeManager.cs:376Swap condition order — put cheap string check before AppContext.TryGetSwitch
💡RuntimeFeature.cs:1Redundant #nullable enable (project-level setting)
💡JniRuntime.JniTypeManager.cs:140Spurious extra blank line

CI note: Only license/cla is visible in check runs. No build/test CI results were found to verify.

Generated by Java.Interop PR Reviewer for issue #1434 · ● 3.2M

Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/RuntimeFeature.cs Outdated
@jonathanpeppers

Copy link
Copy Markdown
Member

CopilotAI commented May 26, 2026

Copy link
Copy Markdown
Contributor

@copilot can you fix the two formatting comments:

Fixed in f628dba:

  • Removed the spurious extra blank line in JniRuntime.JniTypeManager.cs (now one blank line between the closing } and the // NOTE comment)
  • Removed the redundant #nullable enable from RuntimeFeature.cs (project-level <Nullable>enable</Nullable> already covers it)

@jonathanpeppers
jonathanpeppers merged commit 41d01af into mainMay 26, 2026
2 checks passed
@jonathanpeppers
jonathanpeppers deleted the dev/simonrozsival/managedpeer-feature-switch branch May 26, 2026 14:39
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, thanks!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

Add ManagedPeer native registration feature switch - #1434

Merged
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch
May 26, 2026
Merged

Add ManagedPeer native registration feature switch#1434
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Adds a Java.Interop-owned feature switch for legacy ManagedPeer native registration.

.NET for Android trimmable typemap builds register native methods through generated JCW static initializers, so they do not need the legacy ManagedPeer native registration path. Keeping this behind a default-on switch preserves existing Java.Interop and non-trimmable behavior while allowing trimmable Android apps to disable the path and let ILLink remove the dead ManagedPeer root.

Validation:

  • dotnet build src/Java.Interop/Java.Interop.csproj -v:minimal

Allow callers to disable legacy ManagedPeer native registration so trimmable Android apps can avoid rooting ManagedPeer when they register native methods through generated JCW initializers instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 25, 2026 09:19

CopilotAI 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.

Pull request overview

Adds a Java.Interop-owned runtime feature switch to optionally disable the legacy ManagedPeer native registration path, primarily to enable trimming of the ManagedPeer root for trimmable .NET for Android typemap builds while preserving existing behavior by default.

Changes:

  • Introduces Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration backed by an AppContext feature switch (default: enabled).
  • Gates ManagedPeer.Init() during JniRuntime construction behind the feature switch.
  • Conditionally includes the net/dot/jni/ManagedPeer built-in type mapping only when the feature switch is enabled.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/Java.Interop/Java.Interop/RuntimeFeature.csAdds the new AppContext-based feature switch definition for runtime behavior control.
src/Java.Interop/Java.Interop/JniRuntime.csUses the feature switch to optionally skip legacy ManagedPeer native registration initialization.
src/Java.Interop/Java.Interop/JniBuiltinMarshalers.csUses the feature switch to optionally avoid adding the ManagedPeer type mapping (to reduce trimming roots).

Comment threadsrc/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.cs
simonrozsivaland others added 8 commits May 25, 2026 12:08
Let embedders opt out of ManagedPeer native registration through JniRuntime.CreationOptions instead of a Java.Interop runtimeconfig feature switch. This keeps the default Java.Interop behavior while allowing Android's trimmable runtime path to disable the legacy ManagedPeer registration path without emitting a Java.Interop-specific runtimeconfig value.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the generated JniBuiltinMarshalers template aligned with the generated source after removing the ManagedPeer simple-reference mapping, and add coverage that disabling ManagedPeer native registration skips the init hook.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a regression test that the built-in simple-reference map no longer resolves the internal ManagedPeer bridge type, documenting that the mapping removal is unconditional rather than driven by per-runtime options.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep legacy ManagedPeer native registration enabled by default and use the trim-aware Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration switch to disable it for trimmable consumers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add coverage that disabling Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration skips ManagedPeer.Init(), while keeping the switch trim-aware and default-enabled for legacy behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the test-only InitCallCount field from ManagedPeer so production code is not changed solely for test coverage.
Keep switch-off coverage by observing the ManagedPeer built-in type mapping instead of recording Init() calls.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evaluate the ManagedPeer builtin type mapping at lookup time instead of caching the runtime switch value in the lazy builtin map. This lets tests and embedders disable ManagedPeer native registration after the common builtin map has already been initialized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this ready-to-review This PR is ready to review/merge, thanks! labels May 25, 2026
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 26, 2026

Copy link
Copy Markdown

Java.Interop PR Reviewer completed successfully!

@github-actionsgithub-actionsBot 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.

✅ LGTM — Clean feature switch implementation

Summary: This PR adds a [FeatureSwitchDefinition]-backed RuntimeFeature.ManagedPeerNativeRegistration switch that gates legacy ManagedPeer native registration. The pattern is correct: default-on preserves existing behavior, and trimmable Android builds can set the switch to false so ILLink removes the dead code path.

What's done well:

  • Both the .tt template and generated .cs are updated consistently — T4 regen won't revert the change.
  • [FeatureSwitchDefinition] ensures the trimmer substitutes the property with a constant — zero runtime cost in trimmed builds.
  • [NonParallelizable] correctly applied since AppContext.SetSwitch mutates process-global state.
  • Tests cover both the default-on path and the switch-off path with proper try/finally cleanup.

Issues: 0 ❌ · 1 ⚠️ · 2 💡

SeverityFileIssue
⚠️JniRuntime.JniTypeManager.cs:376Swap condition order — put cheap string check before AppContext.TryGetSwitch
💡RuntimeFeature.cs:1Redundant #nullable enable (project-level setting)
💡JniRuntime.JniTypeManager.cs:140Spurious extra blank line

CI note: Only license/cla is visible in check runs. No build/test CI results were found to verify.

Generated by Java.Interop PR Reviewer for issue #1434 · ● 3.2M

Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/RuntimeFeature.cs Outdated
@jonathanpeppers

Copy link
Copy Markdown
Member

CopilotAI commented May 26, 2026

Copy link
Copy Markdown
Contributor

@copilot can you fix the two formatting comments:

Fixed in f628dba:

  • Removed the spurious extra blank line in JniRuntime.JniTypeManager.cs (now one blank line between the closing } and the // NOTE comment)
  • Removed the redundant #nullable enable from RuntimeFeature.cs (project-level <Nullable>enable</Nullable> already covers it)

@jonathanpeppers
jonathanpeppers merged commit 41d01af into mainMay 26, 2026
2 checks passed
@jonathanpeppers
jonathanpeppers deleted the dev/simonrozsival/managedpeer-feature-switch branch May 26, 2026 14:39
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, thanks!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

Add ManagedPeer native registration feature switch - #1434

Merged
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch
May 26, 2026
Merged

Add ManagedPeer native registration feature switch#1434
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Adds a Java.Interop-owned feature switch for legacy ManagedPeer native registration.

.NET for Android trimmable typemap builds register native methods through generated JCW static initializers, so they do not need the legacy ManagedPeer native registration path. Keeping this behind a default-on switch preserves existing Java.Interop and non-trimmable behavior while allowing trimmable Android apps to disable the path and let ILLink remove the dead ManagedPeer root.

Validation:

  • dotnet build src/Java.Interop/Java.Interop.csproj -v:minimal

Allow callers to disable legacy ManagedPeer native registration so trimmable Android apps can avoid rooting ManagedPeer when they register native methods through generated JCW initializers instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 25, 2026 09:19

CopilotAI 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.

Pull request overview

Adds a Java.Interop-owned runtime feature switch to optionally disable the legacy ManagedPeer native registration path, primarily to enable trimming of the ManagedPeer root for trimmable .NET for Android typemap builds while preserving existing behavior by default.

Changes:

  • Introduces Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration backed by an AppContext feature switch (default: enabled).
  • Gates ManagedPeer.Init() during JniRuntime construction behind the feature switch.
  • Conditionally includes the net/dot/jni/ManagedPeer built-in type mapping only when the feature switch is enabled.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/Java.Interop/Java.Interop/RuntimeFeature.csAdds the new AppContext-based feature switch definition for runtime behavior control.
src/Java.Interop/Java.Interop/JniRuntime.csUses the feature switch to optionally skip legacy ManagedPeer native registration initialization.
src/Java.Interop/Java.Interop/JniBuiltinMarshalers.csUses the feature switch to optionally avoid adding the ManagedPeer type mapping (to reduce trimming roots).

Comment threadsrc/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.cs
simonrozsivaland others added 8 commits May 25, 2026 12:08
Let embedders opt out of ManagedPeer native registration through JniRuntime.CreationOptions instead of a Java.Interop runtimeconfig feature switch. This keeps the default Java.Interop behavior while allowing Android's trimmable runtime path to disable the legacy ManagedPeer registration path without emitting a Java.Interop-specific runtimeconfig value.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the generated JniBuiltinMarshalers template aligned with the generated source after removing the ManagedPeer simple-reference mapping, and add coverage that disabling ManagedPeer native registration skips the init hook.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a regression test that the built-in simple-reference map no longer resolves the internal ManagedPeer bridge type, documenting that the mapping removal is unconditional rather than driven by per-runtime options.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep legacy ManagedPeer native registration enabled by default and use the trim-aware Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration switch to disable it for trimmable consumers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add coverage that disabling Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration skips ManagedPeer.Init(), while keeping the switch trim-aware and default-enabled for legacy behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the test-only InitCallCount field from ManagedPeer so production code is not changed solely for test coverage.
Keep switch-off coverage by observing the ManagedPeer built-in type mapping instead of recording Init() calls.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evaluate the ManagedPeer builtin type mapping at lookup time instead of caching the runtime switch value in the lazy builtin map. This lets tests and embedders disable ManagedPeer native registration after the common builtin map has already been initialized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this ready-to-review This PR is ready to review/merge, thanks! labels May 25, 2026
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 26, 2026

Copy link
Copy Markdown

Java.Interop PR Reviewer completed successfully!

@github-actionsgithub-actionsBot 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.

✅ LGTM — Clean feature switch implementation

Summary: This PR adds a [FeatureSwitchDefinition]-backed RuntimeFeature.ManagedPeerNativeRegistration switch that gates legacy ManagedPeer native registration. The pattern is correct: default-on preserves existing behavior, and trimmable Android builds can set the switch to false so ILLink removes the dead code path.

What's done well:

  • Both the .tt template and generated .cs are updated consistently — T4 regen won't revert the change.
  • [FeatureSwitchDefinition] ensures the trimmer substitutes the property with a constant — zero runtime cost in trimmed builds.
  • [NonParallelizable] correctly applied since AppContext.SetSwitch mutates process-global state.
  • Tests cover both the default-on path and the switch-off path with proper try/finally cleanup.

Issues: 0 ❌ · 1 ⚠️ · 2 💡

SeverityFileIssue
⚠️JniRuntime.JniTypeManager.cs:376Swap condition order — put cheap string check before AppContext.TryGetSwitch
💡RuntimeFeature.cs:1Redundant #nullable enable (project-level setting)
💡JniRuntime.JniTypeManager.cs:140Spurious extra blank line

CI note: Only license/cla is visible in check runs. No build/test CI results were found to verify.

Generated by Java.Interop PR Reviewer for issue #1434 · ● 3.2M

Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/RuntimeFeature.cs Outdated
@jonathanpeppers

Copy link
Copy Markdown
Member

CopilotAI commented May 26, 2026

Copy link
Copy Markdown
Contributor

@copilot can you fix the two formatting comments:

Fixed in f628dba:

  • Removed the spurious extra blank line in JniRuntime.JniTypeManager.cs (now one blank line between the closing } and the // NOTE comment)
  • Removed the redundant #nullable enable from RuntimeFeature.cs (project-level <Nullable>enable</Nullable> already covers it)

@jonathanpeppers
jonathanpeppers merged commit 41d01af into mainMay 26, 2026
2 checks passed
@jonathanpeppers
jonathanpeppers deleted the dev/simonrozsival/managedpeer-feature-switch branch May 26, 2026 14:39
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, thanks!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

Add ManagedPeer native registration feature switch - #1434

Merged
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch
May 26, 2026
Merged

Add ManagedPeer native registration feature switch#1434
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Adds a Java.Interop-owned feature switch for legacy ManagedPeer native registration.

.NET for Android trimmable typemap builds register native methods through generated JCW static initializers, so they do not need the legacy ManagedPeer native registration path. Keeping this behind a default-on switch preserves existing Java.Interop and non-trimmable behavior while allowing trimmable Android apps to disable the path and let ILLink remove the dead ManagedPeer root.

Validation:

  • dotnet build src/Java.Interop/Java.Interop.csproj -v:minimal

Allow callers to disable legacy ManagedPeer native registration so trimmable Android apps can avoid rooting ManagedPeer when they register native methods through generated JCW initializers instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 25, 2026 09:19

CopilotAI 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.

Pull request overview

Adds a Java.Interop-owned runtime feature switch to optionally disable the legacy ManagedPeer native registration path, primarily to enable trimming of the ManagedPeer root for trimmable .NET for Android typemap builds while preserving existing behavior by default.

Changes:

  • Introduces Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration backed by an AppContext feature switch (default: enabled).
  • Gates ManagedPeer.Init() during JniRuntime construction behind the feature switch.
  • Conditionally includes the net/dot/jni/ManagedPeer built-in type mapping only when the feature switch is enabled.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/Java.Interop/Java.Interop/RuntimeFeature.csAdds the new AppContext-based feature switch definition for runtime behavior control.
src/Java.Interop/Java.Interop/JniRuntime.csUses the feature switch to optionally skip legacy ManagedPeer native registration initialization.
src/Java.Interop/Java.Interop/JniBuiltinMarshalers.csUses the feature switch to optionally avoid adding the ManagedPeer type mapping (to reduce trimming roots).

Comment threadsrc/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.cs
simonrozsivaland others added 8 commits May 25, 2026 12:08
Let embedders opt out of ManagedPeer native registration through JniRuntime.CreationOptions instead of a Java.Interop runtimeconfig feature switch. This keeps the default Java.Interop behavior while allowing Android's trimmable runtime path to disable the legacy ManagedPeer registration path without emitting a Java.Interop-specific runtimeconfig value.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the generated JniBuiltinMarshalers template aligned with the generated source after removing the ManagedPeer simple-reference mapping, and add coverage that disabling ManagedPeer native registration skips the init hook.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a regression test that the built-in simple-reference map no longer resolves the internal ManagedPeer bridge type, documenting that the mapping removal is unconditional rather than driven by per-runtime options.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep legacy ManagedPeer native registration enabled by default and use the trim-aware Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration switch to disable it for trimmable consumers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add coverage that disabling Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration skips ManagedPeer.Init(), while keeping the switch trim-aware and default-enabled for legacy behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the test-only InitCallCount field from ManagedPeer so production code is not changed solely for test coverage.
Keep switch-off coverage by observing the ManagedPeer built-in type mapping instead of recording Init() calls.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evaluate the ManagedPeer builtin type mapping at lookup time instead of caching the runtime switch value in the lazy builtin map. This lets tests and embedders disable ManagedPeer native registration after the common builtin map has already been initialized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this ready-to-review This PR is ready to review/merge, thanks! labels May 25, 2026
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 26, 2026

Copy link
Copy Markdown

Java.Interop PR Reviewer completed successfully!

@github-actionsgithub-actionsBot 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.

✅ LGTM — Clean feature switch implementation

Summary: This PR adds a [FeatureSwitchDefinition]-backed RuntimeFeature.ManagedPeerNativeRegistration switch that gates legacy ManagedPeer native registration. The pattern is correct: default-on preserves existing behavior, and trimmable Android builds can set the switch to false so ILLink removes the dead code path.

What's done well:

  • Both the .tt template and generated .cs are updated consistently — T4 regen won't revert the change.
  • [FeatureSwitchDefinition] ensures the trimmer substitutes the property with a constant — zero runtime cost in trimmed builds.
  • [NonParallelizable] correctly applied since AppContext.SetSwitch mutates process-global state.
  • Tests cover both the default-on path and the switch-off path with proper try/finally cleanup.

Issues: 0 ❌ · 1 ⚠️ · 2 💡

SeverityFileIssue
⚠️JniRuntime.JniTypeManager.cs:376Swap condition order — put cheap string check before AppContext.TryGetSwitch
💡RuntimeFeature.cs:1Redundant #nullable enable (project-level setting)
💡JniRuntime.JniTypeManager.cs:140Spurious extra blank line

CI note: Only license/cla is visible in check runs. No build/test CI results were found to verify.

Generated by Java.Interop PR Reviewer for issue #1434 · ● 3.2M

Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/RuntimeFeature.cs Outdated
@jonathanpeppers

Copy link
Copy Markdown
Member

CopilotAI commented May 26, 2026

Copy link
Copy Markdown
Contributor

@copilot can you fix the two formatting comments:

Fixed in f628dba:

  • Removed the spurious extra blank line in JniRuntime.JniTypeManager.cs (now one blank line between the closing } and the // NOTE comment)
  • Removed the redundant #nullable enable from RuntimeFeature.cs (project-level <Nullable>enable</Nullable> already covers it)

@jonathanpeppers
jonathanpeppers merged commit 41d01af into mainMay 26, 2026
2 checks passed
@jonathanpeppers
jonathanpeppers deleted the dev/simonrozsival/managedpeer-feature-switch branch May 26, 2026 14:39
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, thanks!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

Add ManagedPeer native registration feature switch - #1434

Merged
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch
May 26, 2026
Merged

Add ManagedPeer native registration feature switch#1434
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Adds a Java.Interop-owned feature switch for legacy ManagedPeer native registration.

.NET for Android trimmable typemap builds register native methods through generated JCW static initializers, so they do not need the legacy ManagedPeer native registration path. Keeping this behind a default-on switch preserves existing Java.Interop and non-trimmable behavior while allowing trimmable Android apps to disable the path and let ILLink remove the dead ManagedPeer root.

Validation:

  • dotnet build src/Java.Interop/Java.Interop.csproj -v:minimal

Allow callers to disable legacy ManagedPeer native registration so trimmable Android apps can avoid rooting ManagedPeer when they register native methods through generated JCW initializers instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 25, 2026 09:19

CopilotAI 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.

Pull request overview

Adds a Java.Interop-owned runtime feature switch to optionally disable the legacy ManagedPeer native registration path, primarily to enable trimming of the ManagedPeer root for trimmable .NET for Android typemap builds while preserving existing behavior by default.

Changes:

  • Introduces Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration backed by an AppContext feature switch (default: enabled).
  • Gates ManagedPeer.Init() during JniRuntime construction behind the feature switch.
  • Conditionally includes the net/dot/jni/ManagedPeer built-in type mapping only when the feature switch is enabled.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/Java.Interop/Java.Interop/RuntimeFeature.csAdds the new AppContext-based feature switch definition for runtime behavior control.
src/Java.Interop/Java.Interop/JniRuntime.csUses the feature switch to optionally skip legacy ManagedPeer native registration initialization.
src/Java.Interop/Java.Interop/JniBuiltinMarshalers.csUses the feature switch to optionally avoid adding the ManagedPeer type mapping (to reduce trimming roots).

Comment threadsrc/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.cs
simonrozsivaland others added 8 commits May 25, 2026 12:08
Let embedders opt out of ManagedPeer native registration through JniRuntime.CreationOptions instead of a Java.Interop runtimeconfig feature switch. This keeps the default Java.Interop behavior while allowing Android's trimmable runtime path to disable the legacy ManagedPeer registration path without emitting a Java.Interop-specific runtimeconfig value.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the generated JniBuiltinMarshalers template aligned with the generated source after removing the ManagedPeer simple-reference mapping, and add coverage that disabling ManagedPeer native registration skips the init hook.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a regression test that the built-in simple-reference map no longer resolves the internal ManagedPeer bridge type, documenting that the mapping removal is unconditional rather than driven by per-runtime options.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep legacy ManagedPeer native registration enabled by default and use the trim-aware Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration switch to disable it for trimmable consumers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add coverage that disabling Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration skips ManagedPeer.Init(), while keeping the switch trim-aware and default-enabled for legacy behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the test-only InitCallCount field from ManagedPeer so production code is not changed solely for test coverage.
Keep switch-off coverage by observing the ManagedPeer built-in type mapping instead of recording Init() calls.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evaluate the ManagedPeer builtin type mapping at lookup time instead of caching the runtime switch value in the lazy builtin map. This lets tests and embedders disable ManagedPeer native registration after the common builtin map has already been initialized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this ready-to-review This PR is ready to review/merge, thanks! labels May 25, 2026
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 26, 2026

Copy link
Copy Markdown

Java.Interop PR Reviewer completed successfully!

@github-actionsgithub-actionsBot 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.

✅ LGTM — Clean feature switch implementation

Summary: This PR adds a [FeatureSwitchDefinition]-backed RuntimeFeature.ManagedPeerNativeRegistration switch that gates legacy ManagedPeer native registration. The pattern is correct: default-on preserves existing behavior, and trimmable Android builds can set the switch to false so ILLink removes the dead code path.

What's done well:

  • Both the .tt template and generated .cs are updated consistently — T4 regen won't revert the change.
  • [FeatureSwitchDefinition] ensures the trimmer substitutes the property with a constant — zero runtime cost in trimmed builds.
  • [NonParallelizable] correctly applied since AppContext.SetSwitch mutates process-global state.
  • Tests cover both the default-on path and the switch-off path with proper try/finally cleanup.

Issues: 0 ❌ · 1 ⚠️ · 2 💡

SeverityFileIssue
⚠️JniRuntime.JniTypeManager.cs:376Swap condition order — put cheap string check before AppContext.TryGetSwitch
💡RuntimeFeature.cs:1Redundant #nullable enable (project-level setting)
💡JniRuntime.JniTypeManager.cs:140Spurious extra blank line

CI note: Only license/cla is visible in check runs. No build/test CI results were found to verify.

Generated by Java.Interop PR Reviewer for issue #1434 · ● 3.2M

Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/RuntimeFeature.cs Outdated
@jonathanpeppers

Copy link
Copy Markdown
Member

CopilotAI commented May 26, 2026

Copy link
Copy Markdown
Contributor

@copilot can you fix the two formatting comments:

Fixed in f628dba:

  • Removed the spurious extra blank line in JniRuntime.JniTypeManager.cs (now one blank line between the closing } and the // NOTE comment)
  • Removed the redundant #nullable enable from RuntimeFeature.cs (project-level <Nullable>enable</Nullable> already covers it)

@jonathanpeppers
jonathanpeppers merged commit 41d01af into mainMay 26, 2026
2 checks passed
@jonathanpeppers
jonathanpeppers deleted the dev/simonrozsival/managedpeer-feature-switch branch May 26, 2026 14:39
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, thanks!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

Add ManagedPeer native registration feature switch - #1434

Merged
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch
May 26, 2026
Merged

Add ManagedPeer native registration feature switch#1434
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Adds a Java.Interop-owned feature switch for legacy ManagedPeer native registration.

.NET for Android trimmable typemap builds register native methods through generated JCW static initializers, so they do not need the legacy ManagedPeer native registration path. Keeping this behind a default-on switch preserves existing Java.Interop and non-trimmable behavior while allowing trimmable Android apps to disable the path and let ILLink remove the dead ManagedPeer root.

Validation:

  • dotnet build src/Java.Interop/Java.Interop.csproj -v:minimal

Allow callers to disable legacy ManagedPeer native registration so trimmable Android apps can avoid rooting ManagedPeer when they register native methods through generated JCW initializers instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 25, 2026 09:19

CopilotAI 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.

Pull request overview

Adds a Java.Interop-owned runtime feature switch to optionally disable the legacy ManagedPeer native registration path, primarily to enable trimming of the ManagedPeer root for trimmable .NET for Android typemap builds while preserving existing behavior by default.

Changes:

  • Introduces Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration backed by an AppContext feature switch (default: enabled).
  • Gates ManagedPeer.Init() during JniRuntime construction behind the feature switch.
  • Conditionally includes the net/dot/jni/ManagedPeer built-in type mapping only when the feature switch is enabled.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/Java.Interop/Java.Interop/RuntimeFeature.csAdds the new AppContext-based feature switch definition for runtime behavior control.
src/Java.Interop/Java.Interop/JniRuntime.csUses the feature switch to optionally skip legacy ManagedPeer native registration initialization.
src/Java.Interop/Java.Interop/JniBuiltinMarshalers.csUses the feature switch to optionally avoid adding the ManagedPeer type mapping (to reduce trimming roots).

Comment threadsrc/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.cs
simonrozsivaland others added 8 commits May 25, 2026 12:08
Let embedders opt out of ManagedPeer native registration through JniRuntime.CreationOptions instead of a Java.Interop runtimeconfig feature switch. This keeps the default Java.Interop behavior while allowing Android's trimmable runtime path to disable the legacy ManagedPeer registration path without emitting a Java.Interop-specific runtimeconfig value.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the generated JniBuiltinMarshalers template aligned with the generated source after removing the ManagedPeer simple-reference mapping, and add coverage that disabling ManagedPeer native registration skips the init hook.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a regression test that the built-in simple-reference map no longer resolves the internal ManagedPeer bridge type, documenting that the mapping removal is unconditional rather than driven by per-runtime options.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep legacy ManagedPeer native registration enabled by default and use the trim-aware Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration switch to disable it for trimmable consumers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add coverage that disabling Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration skips ManagedPeer.Init(), while keeping the switch trim-aware and default-enabled for legacy behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the test-only InitCallCount field from ManagedPeer so production code is not changed solely for test coverage.
Keep switch-off coverage by observing the ManagedPeer built-in type mapping instead of recording Init() calls.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evaluate the ManagedPeer builtin type mapping at lookup time instead of caching the runtime switch value in the lazy builtin map. This lets tests and embedders disable ManagedPeer native registration after the common builtin map has already been initialized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this ready-to-review This PR is ready to review/merge, thanks! labels May 25, 2026
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 26, 2026

Copy link
Copy Markdown

Java.Interop PR Reviewer completed successfully!

@github-actionsgithub-actionsBot 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.

✅ LGTM — Clean feature switch implementation

Summary: This PR adds a [FeatureSwitchDefinition]-backed RuntimeFeature.ManagedPeerNativeRegistration switch that gates legacy ManagedPeer native registration. The pattern is correct: default-on preserves existing behavior, and trimmable Android builds can set the switch to false so ILLink removes the dead code path.

What's done well:

  • Both the .tt template and generated .cs are updated consistently — T4 regen won't revert the change.
  • [FeatureSwitchDefinition] ensures the trimmer substitutes the property with a constant — zero runtime cost in trimmed builds.
  • [NonParallelizable] correctly applied since AppContext.SetSwitch mutates process-global state.
  • Tests cover both the default-on path and the switch-off path with proper try/finally cleanup.

Issues: 0 ❌ · 1 ⚠️ · 2 💡

SeverityFileIssue
⚠️JniRuntime.JniTypeManager.cs:376Swap condition order — put cheap string check before AppContext.TryGetSwitch
💡RuntimeFeature.cs:1Redundant #nullable enable (project-level setting)
💡JniRuntime.JniTypeManager.cs:140Spurious extra blank line

CI note: Only license/cla is visible in check runs. No build/test CI results were found to verify.

Generated by Java.Interop PR Reviewer for issue #1434 · ● 3.2M

Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/RuntimeFeature.cs Outdated
@jonathanpeppers

Copy link
Copy Markdown
Member

CopilotAI commented May 26, 2026

Copy link
Copy Markdown
Contributor

@copilot can you fix the two formatting comments:

Fixed in f628dba:

  • Removed the spurious extra blank line in JniRuntime.JniTypeManager.cs (now one blank line between the closing } and the // NOTE comment)
  • Removed the redundant #nullable enable from RuntimeFeature.cs (project-level <Nullable>enable</Nullable> already covers it)

@jonathanpeppers
jonathanpeppers merged commit 41d01af into mainMay 26, 2026
2 checks passed
@jonathanpeppers
jonathanpeppers deleted the dev/simonrozsival/managedpeer-feature-switch branch May 26, 2026 14:39
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, thanks!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

Add ManagedPeer native registration feature switch - #1434

Merged
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch
May 26, 2026
Merged

Add ManagedPeer native registration feature switch#1434
jonathanpeppers merged 10 commits into
mainfrom
dev/simonrozsival/managedpeer-feature-switch

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Adds a Java.Interop-owned feature switch for legacy ManagedPeer native registration.

.NET for Android trimmable typemap builds register native methods through generated JCW static initializers, so they do not need the legacy ManagedPeer native registration path. Keeping this behind a default-on switch preserves existing Java.Interop and non-trimmable behavior while allowing trimmable Android apps to disable the path and let ILLink remove the dead ManagedPeer root.

Validation:

  • dotnet build src/Java.Interop/Java.Interop.csproj -v:minimal

Allow callers to disable legacy ManagedPeer native registration so trimmable Android apps can avoid rooting ManagedPeer when they register native methods through generated JCW initializers instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 25, 2026 09:19

CopilotAI 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.

Pull request overview

Adds a Java.Interop-owned runtime feature switch to optionally disable the legacy ManagedPeer native registration path, primarily to enable trimming of the ManagedPeer root for trimmable .NET for Android typemap builds while preserving existing behavior by default.

Changes:

  • Introduces Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration backed by an AppContext feature switch (default: enabled).
  • Gates ManagedPeer.Init() during JniRuntime construction behind the feature switch.
  • Conditionally includes the net/dot/jni/ManagedPeer built-in type mapping only when the feature switch is enabled.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/Java.Interop/Java.Interop/RuntimeFeature.csAdds the new AppContext-based feature switch definition for runtime behavior control.
src/Java.Interop/Java.Interop/JniRuntime.csUses the feature switch to optionally skip legacy ManagedPeer native registration initialization.
src/Java.Interop/Java.Interop/JniBuiltinMarshalers.csUses the feature switch to optionally avoid adding the ManagedPeer type mapping (to reduce trimming roots).

Comment threadsrc/Java.Interop/Java.Interop/JniBuiltinMarshalers.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.cs
simonrozsivaland others added 8 commits May 25, 2026 12:08
Let embedders opt out of ManagedPeer native registration through JniRuntime.CreationOptions instead of a Java.Interop runtimeconfig feature switch. This keeps the default Java.Interop behavior while allowing Android's trimmable runtime path to disable the legacy ManagedPeer registration path without emitting a Java.Interop-specific runtimeconfig value.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the generated JniBuiltinMarshalers template aligned with the generated source after removing the ManagedPeer simple-reference mapping, and add coverage that disabling ManagedPeer native registration skips the init hook.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a regression test that the built-in simple-reference map no longer resolves the internal ManagedPeer bridge type, documenting that the mapping removal is unconditional rather than driven by per-runtime options.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep legacy ManagedPeer native registration enabled by default and use the trim-aware Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration switch to disable it for trimmable consumers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add coverage that disabling Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration skips ManagedPeer.Init(), while keeping the switch trim-aware and default-enabled for legacy behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the test-only InitCallCount field from ManagedPeer so production code is not changed solely for test coverage.
Keep switch-off coverage by observing the ManagedPeer built-in type mapping instead of recording Init() calls.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evaluate the ManagedPeer builtin type mapping at lookup time instead of caching the runtime switch value in the lazy builtin map. This lets tests and embedders disable ManagedPeer native registration after the common builtin map has already been initialized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsivalsimonrozsival added copilot `copilot-cli` or other AIs were used to author this ready-to-review This PR is ready to review/merge, thanks! labels May 25, 2026
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

/review

@github-actions

github-actionsBot commented May 26, 2026

Copy link
Copy Markdown

Java.Interop PR Reviewer completed successfully!

@github-actionsgithub-actionsBot 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.

✅ LGTM — Clean feature switch implementation

Summary: This PR adds a [FeatureSwitchDefinition]-backed RuntimeFeature.ManagedPeerNativeRegistration switch that gates legacy ManagedPeer native registration. The pattern is correct: default-on preserves existing behavior, and trimmable Android builds can set the switch to false so ILLink removes the dead code path.

What's done well:

  • Both the .tt template and generated .cs are updated consistently — T4 regen won't revert the change.
  • [FeatureSwitchDefinition] ensures the trimmer substitutes the property with a constant — zero runtime cost in trimmed builds.
  • [NonParallelizable] correctly applied since AppContext.SetSwitch mutates process-global state.
  • Tests cover both the default-on path and the switch-off path with proper try/finally cleanup.

Issues: 0 ❌ · 1 ⚠️ · 2 💡

SeverityFileIssue
⚠️JniRuntime.JniTypeManager.cs:376Swap condition order — put cheap string check before AppContext.TryGetSwitch
💡RuntimeFeature.cs:1Redundant #nullable enable (project-level setting)
💡JniRuntime.JniTypeManager.cs:140Spurious extra blank line

CI note: Only license/cla is visible in check runs. No build/test CI results were found to verify.

Generated by Java.Interop PR Reviewer for issue #1434 · ● 3.2M

Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs
Comment threadsrc/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs Outdated
Comment threadsrc/Java.Interop/Java.Interop/RuntimeFeature.cs Outdated
@jonathanpeppers

Copy link
Copy Markdown
Member

CopilotAI commented May 26, 2026

Copy link
Copy Markdown
Contributor

@copilot can you fix the two formatting comments:

Fixed in f628dba:

  • Removed the spurious extra blank line in JniRuntime.JniTypeManager.cs (now one blank line between the closing } and the // NOTE comment)
  • Removed the redundant #nullable enable from RuntimeFeature.cs (project-level <Nullable>enable</Nullable> already covers it)

@jonathanpeppers
jonathanpeppers merged commit 41d01af into mainMay 26, 2026
2 checks passed
@jonathanpeppers
jonathanpeppers deleted the dev/simonrozsival/managedpeer-feature-switch branch May 26, 2026 14:39
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

copilot`copilot-cli` or other AIs were used to author thisready-to-reviewThis PR is ready to review/merge, thanks!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@simonrozsival@jonathanpeppers