Skip to content

Metadata filtering from native-api-usage.json - #20

Merged
triniwiz merged 1 commit into
mainfrom
feat/metadata-filter
Sep 30, 2026
Merged

triniwiz merged 1 commit into
mainfrom
feat/metadata-filter

Conversation

@triniwiz

Copy link
Copy Markdown
Member

Summary

Apps and plugins can now limit the native API they use with App_Resources/Windows/native-api-usage.json, as on Android and iOS. The CLI already writes it out as whitelist.mdg / blacklist.mdg in platforms/windows (metadata-filtering-service.ts), but nothing on Windows read them.

The format and rules are those of the Android and iOS metadata generators:

  • one namespace:type pattern per line, with * and ? wildcards; a bare namespace covers every type in it; # and // start comments;
  • a whitelist, once present, is exclusive; the blacklist always wins;
  • NativeScript.* (the runtime's widgets and sbg's proxies) is always whitelisted, as Android always allows com.tns.gen*.

Android and iOS enforce the filter by leaving types out of build-time metadata. Windows resolves types from .winmd at run time, so it's enforced where JS reaches a type by name, and in the build's extension scan.

  • metadata-filter (new crate, no dependencies): the parser and matcher, shared by the runtime and the build tools.
  • Runtime: both engines load the files from next to the exe at startup. A type the filter leaves out is undefined to JS; namespaces stay traversable. The runtime's own lookups (return types, bases, interfaces, an instance's runtime class) are not filtered, so an allowed API still returns objects of filtered types. Each type's verdict is computed once and cached.
  • dotnet-tool:
    • It no longer takes names that can't be types (a minified Ua.$) for extensions.
    • It drops extensions of bases the filter leaves out.
    • It publishes dotnet-bridge only for .NET usage, or for an extension that is surely real: named, or with a Windows/Microsoft/System/NativeScript base. Before, any bundled library's classes (babylon.js, phaser) made it run dotnet publish on every build. The template's own incremental PublishDotNetBridge target is unchanged.
    • It removes a stale sbg_metadata.json when nothing is found.
  • sbg: skips extensions whose base the filter leaves out (SBG_WHITELIST / SBG_BLACKLIST), and shares the base check with dotnet-tool.
  • Template: copies the .mdg files next to the exe (removing a copy the app no longer has) and passes them to sbg.

Testing

  • Unit tests: cargo test -p metadata-filter (8), -p sbg (4, one new), -p dotnet-tool (3, new: a minified class, a library class, a WinUI extension and a named proxy); a metadata test that a filtered type resolves for the runtime but not for JS, and its namespace still does.
  • cargo test -p runtime --lib: 148/159. The same 11 fail on main (UI-dispatcher, XAML-thread, composition and PropertySet tests).
  • End to end, NativeScript canvas apps/demo with this branch's nativescript.dll, sbg and dotnet-tool (classic engine):
    • No filter: builds; dotnet-tool writes the bundle's library classes for sbg to skip, but no longer publishes the bridge for them. WebGL spec 81/81.
    • With a filter: a native-api-usage.json whitelisting 500 patterns (the matching ones last) and blacklisting Windows.Storage.Pickers:FileOpen*. The CLI writes the .mdg files; the build copies them next to the exe; dotnet-tool writes no metadata and publishes nothing. FileOpenPicker is undefined while FileSavePicker and StorageFile work, and the spec still passes 81/81.
    • Cost: 200k Windows.Foundation.Uri resolutions took 112–121 ms with and without the filter, and 20k constructions 413–440 ms: no measurable difference.
  • Not tested: the napi engine packages end to end (they build and share the lookup path).

…d iOS

An app (and its plugins) can now limit the native API it uses with
App_Resources/Windows/native-api-usage.json. The CLI already writes it out
as whitelist.mdg / blacklist.mdg in platforms/windows; nothing read them.
Same format and rules as the Android and iOS metadata generators: one
`namespace:type` pattern per line, `*` and `?` wildcards, a bare namespace
covers every type in it; a whitelist is exclusive, the blacklist wins.

- metadata-filter: the parser and matcher, shared by the runtime and the
  build tools. NativeScript.* (the runtime's widgets, sbg's proxies) is
  always whitelisted, as Android always allows com.tns.gen*.
- Runtime: both engines load the files from next to the exe at startup.
  A type the filter leaves out is not there for JS (undefined), as it isn't
  in the Android/iOS metadata; namespaces stay traversable, and the
  runtime's own lookups (return types, bases, an instance's runtime class)
  are not filtered. Each type's verdict is computed once.
- dotnet-tool no longer takes names that can't be types (minified `Ua.$`)
  for extensions, drops extensions of bases the filter leaves out, and
  publishes dotnet-bridge only for .NET usage or an extension that is
  surely real (named, or of a Windows/Microsoft/System/NativeScript base).
  A bundled library's classes (babylon.js, phaser) made it publish on
  every build. A stale sbg_metadata.json is removed when nothing is found.
- sbg skips extensions whose base the filter leaves out
  (SBG_WHITELIST / SBG_BLACKLIST) and shares the base check with dotnet-tool.
- Template: copies the .mdg files next to the exe (and removes a copy the
  app no longer has), and passes them to sbg.
@coderabbitai

coderabbitai Bot commented Sep 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: b3fccef7-e957-4cd0-b349-324ac0815265

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

@triniwiz
triniwiz merged commit a280a45 into main Sep 30, 2026
2 of 4 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