Skip to content

fix: generics closed over an enum resolve the right IID - #34

Merged
triniwiz merged 1 commit into
mainfrom
fix/enum-type-args
Oct 24, 2026
Merged

triniwiz merged 1 commit into
mainfrom
fix/enum-type-args

Conversation

@triniwiz

Copy link
Copy Markdown
Member

Problem

Any WinRT generic closed over an enum was unusable on every engine. For example, VibrationDevice.RequestAccessAsync() and Geolocator.RequestAccessAsync() both return IAsyncOperation<Enum>, and calling them failed with:

interface method 'GetResults' construction failed
interface property 'Completed' construction failed

So NSWinRT.toPromise(op) threw. IVector<Enum> failed the same way, for example DevicePicker().Filter.SupportedDeviceClasses.

Cause: Signature::get_string reduced every enum to Int32, including inside generic type arguments. The closed type's IID therefore came from IAsyncOperation<Int32> rather than IAsyncOperation<VibrationAccessStatus>, and the QueryInterface call failed. The IID builder itself was correct; it computes the right IID when given the enum name.

Fix

  • Type names: enums keep their name inside generic type arguments (get_string_in(.., in_type_arg)), so the IID hashes enum(Name;i4).
  • ABI lowering: an enum becomes Int32 only where a value crosses the ABI. substitute_type_vars is now depth-aware: a Var!N at the top level goes through abi_type_arg, and one nested inside another generic keeps its name. The delegate helpers (delegate_param_sigs, delegate_return_from_invoke) and the IReference<T> return path lower the same way.
  • IReference<Enum> parameters: these are now boxed as a real IReference<Enum> through struct_reference::create. PropertyValue can only produce IReference<Int32>, which matched only because the old IID was wrong in the same way.
  • Side fix: the old substitute_type_vars used chained str::replace, which turned Var!10 into <arg1>0. The new scanner parses the full index.

Tests

Where Result
windows-napi npm test (new enum-generic-test.js) 436 passed, 0 failed (was 427)
classic interop_test::enum_type_arguments passes
classic full suite 153 passed, 11 failed; all 11 also fail without this change (UI-thread / packaged-only tests)
new packages/test/enum-check.js on QuickJS, Hermes, V8, JSC 7/7 each; interop-check.js 22/22 each

The new Node and classic tests both fail without the fix.

Typings

Running typings-generator with this change emits the enum type where it used to emit number, e.g. IAsyncOperation<Windows.Devices.Haptics.VibrationAccessStatus> instead of IAsyncOperation<number>. The output type-checks with the same errors as before.

`Signature::get_string` reduced every enum to `Int32`, including inside generic type
arguments, so `IAsyncOperation<VibrationAccessStatus>` was asked for the IID of
`IAsyncOperation<Int32>` and every member failed to construct. The same broke
`IVector<Enum>` and computed the wrong IID for `IReference<Enum>`.

Enums now keep their name inside type arguments and become `Int32` only where a value
crosses the ABI: `substitute_type_vars` lowers a top-level `Var!N` enum, as do the
delegate helpers and the `IReference<T>` return path. An `IReference<Enum>` parameter is
boxed as a real `IReference<Enum>` instead of a `PropertyValue` Int32.
@coderabbitai

coderabbitai Bot commented Oct 24, 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
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: bdbb6a54-3665-43b3-a4a2-9a9e4ccb0597

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
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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 6730e43 into main Oct 24, 2026
3 checks passed
@triniwiz
triniwiz deleted the fix/enum-type-args branch October 24, 2026 00:17
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