Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,43 @@ For deployment, see
| `--lang LANG` | No | `js` (default, emits `.js` + `.d.ts`) or `py` (emits `.py` + `.pyi` and `py.typed`) |
| `--no-pyi` | No | With `--lang py`, emit implementation files without type stubs |
| `--output DIR` | No | Output directory (default `./generated`) |
| `--shared-interface-members` | No | JS opt-in: reuse shared required-interface prototype descriptors instead of duplicating inherited member bodies in every concrete class |
| `--dry-run` | No | Validate input, don't write files |

For each WinRT class the codegen emits a typed wrapper, factory, interface registration, async + progress support, generic collections, structs, enums, delegates, and an `index.js` / `index.d.ts` that re-exports every emitted symbol.

### Shared interface members

Large JavaScript projections can opt into shared inherited-interface
implementations while preserving the public declaration API and import paths:

```powershell
dynwinrt-codegen generate `
--winmd-list .winapp\winmds.txt `
--class-name Microsoft.UI.Xaml.Controls.Button,Microsoft.UI.Xaml.Controls.TextBlock `
--output .winapp\bindings `
--shared-interface-members
```

The generated concrete prototypes receive the same method and accessor
descriptors from standalone shared interface prototypes. Overloaded or
conflicting members remain class-local, raw interface wrapper classes remain
available, and the public declaration API and import paths are preserved. Class
deep modules may replace inline required-interface declarations with equivalent
re-exports from canonical standalone interface declarations. Only required
interfaces already canonicalized as standalone shared wrappers participate;
one-off inline required interfaces remain class-local. Generation without this
flag remains byte-compatible with the default output. If a standalone
interface filename is ambiguous between distinct interface identities, none of
those identities participate in sharing and their inherited members remain
class-local.

Focused validation:

```powershell
cargo test -p dynwinrt-codegen --test shared_interface_members_test
```

## Local development — fix import paths in generated files

Generated files import from `'@microsoft/dynwinrt'`. When iterating against a locally-built runtime, rewrite imports to the relative path:
Expand Down
23 changes: 23 additions & 0 deletions tools/dynwinrt-codegen/npm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,31 @@ npx dynwinrt-codegen generate \
| `--ref PATH` | Additional `.winmd` files for type resolution only (no code emitted) |
| `--lang LANG` | `js` (default, emits `.js` + `.d.ts`) or `py` (Python) |
| `--output DIR` | Output directory (default `./generated`) |
| `--shared-interface-members` | JS opt-in that shares inherited interface member descriptors across concrete classes |
| `--dry-run` | Validate input, don't write files |

### Shared interface members

```powershell
npx dynwinrt-codegen generate `
--winmd-list .winapp\winmds.txt `
--class-name Microsoft.UI.Xaml.Controls.Button,Microsoft.UI.Xaml.Controls.TextBlock `
--output .winapp\bindings `
--shared-interface-members
```

The generated concrete prototypes reuse method and accessor descriptors from
the standalone required-interface prototypes. Overloaded or conflicting
members remain class-local, and raw interface wrappers remain available. The
public declaration API and import paths are preserved. Class deep modules may
replace inline required-interface declarations with equivalent re-exports from
canonical standalone interface declarations. Only interfaces already emitted
as canonical standalone shared wrappers participate; one-off inline required
interfaces remain class-local. Generation without the flag remains
byte-compatible with the default output. Generation excludes every identity
behind a standalone interface filename that is ambiguous between distinct
interface identities; those inherited members remain class-local.

## What gets generated

For each WinRT class, the codegen emits:
Expand Down
32 changes: 32 additions & 0 deletions tools/dynwinrt-codegen/src/codegen/winrt/javascript/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ pub struct ProjectedImport {
pub is_runtime_package: bool,
}

pub struct ProjectedReExport {
pub name: String,
pub from: String,
}

/// Disposition of a required interface.
pub enum RequiredIfaceDisposition {
/// Imported from its own generated file
Expand Down Expand Up @@ -257,18 +262,43 @@ pub struct ProjectedClass {
pub doc: Option<DocInfo>,
pub members: Vec<ProjectedMember>,
pub required_ifaces: Vec<ProjectedRequiredIface>,
/// Standalone shared sources imported by this class, including interfaces
/// whose descriptors remain class-local after conflict filtering.
pub shared_interface_sources: Vec<ProjectedSharedInterfaceSource>,
/// Required-interface members whose implementation descriptors are copied
/// from a shared standalone interface prototype.
pub shared_interface_members: Vec<ProjectedSharedInterfaceMembers>,
/// Static factory/static interface cache field declarations (JS only)
pub static_cache_fields: Vec<String>,
/// Static factory/static interface accessor methods (JS only)
pub static_accessors: Vec<String>,
}

pub struct ProjectedSharedInterfaceSource {
pub interface_name: String,
pub interface_identity: String,
}

pub struct ProjectedSharedInterfaceMembers {
pub interface_name: String,
/// Normalized metadata identity expected from the standalone source file.
pub interface_identity: String,
/// Projection-level member keys used to suppress duplicate class bodies.
pub member_keys: Vec<String>,
/// JavaScript property-key expressions copied from the interface prototype.
pub descriptor_keys: Vec<String>,
}

pub struct ProjectedIface {
pub name: String,
pub doc: Option<DocInfo>,
pub iid_const: Option<ProjectedIidConst>,
pub has_static_from: bool,
pub has_parameterized_cast: bool,
/// The interface prototype may be reused by concrete runtime classes.
pub shared_member_source: bool,
/// Normalized metadata identity stored on a shared member source.
pub interface_identity: String,
pub members: Vec<ProjectedMember>,
pub is_delegate: bool,
}
Expand All @@ -295,6 +325,8 @@ pub struct ProjectedDelegate {
pub struct ProjectedFile {
pub name: String,
pub imports: Vec<ProjectedImport>,
/// Public symbols preserved from a canonical sibling module.
pub re_exports: Vec<ProjectedReExport>,
/// IID constants (rendered as `const` in JS, `declare const` in DTS)
pub iid_consts: Vec<ProjectedIidConst>,
/// Interface registration blocks (JS only)
Expand Down
Loading
Loading