GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — feat(runtime): primitive arrays, interop.Array.create, delegates boxed for Object params by triniwiz · Pull Request #41 · NativeScript/windows

Conversation

@triniwiz

@triniwiz triniwiz commented Nov 6, 2026

Copy link
Copy Markdown
Member

Arrays

Every primitive WinRT array parameter now marshals, on both engines. That covers Int32[], UInt32[], Int16[], UInt16[], Int64[], UInt64[], Single[], Double[], Boolean[], Char16[] and the byte types, and it covers both arrays the callee reads and arrays it fills. Before, only byte[] worked, and a plain JS array for byte[] failed with Unspecified error (HRESULT 0x80004005) (e.g. FileIO.WriteBytesAsync(file, [1, 2, 3])).

  • The call passes (count, pointer). The count is in elements, not bytes.

  • A typed array of the element's kind, an ArrayBuffer or a DataView is passed in place: the callee reads or writes JS memory directly. A typed array of the wrong kind is refused (Float64Array for Int32[]).

  • A plain JS array is copied, converting each element the way the matching typed array would.

  • A plain array is refused for a fill array, since the callee's writes would be lost. ParameterDeclaration::is_fill_array() reads the [out] param attribute: is_out() only means ByRef.

  • interop.Array.create(type, count) returns the matching zero-filled typed array, so an array can be allocated up front:

    const bytes = interop.Array.create('UInt8', reader.UnconsumedBufferLength);
    reader.ReadBytes(bytes);
    const ints = interop.Array.create('Int32', 4); // Int32Array
    

    Typings added in typings/nswinrt-helpers.d.ts.

Still unsupported: received arrays (out T[], e.g. IPropertyValue.GetInt32Array), array return values, and arrays of strings or objects.

Delegates passed as Object

UIElement.AddHandler(routedEvent, handler, handledEventsToo) takes its handler as Object and unboxes it with QueryInterface(IReference<TDelegate>). We passed the bare delegate, so it failed with E_INVALIDARG, and core falls back to instance events, which never see events a control has already handled.

JS delegates (classic JsDelegate and napi NapiDelegate) now embed a small tear-off (delegate_box.rs) that answers IInspectable and IReference<D>. Its get_Value returns the delegate itself, and its IUnknown methods forward to the delegate, so COM identity is preserved. AddHandler and RemoveHandler work.

The IID comes from GenericInstanceIdBuilder::ireference_of_delegate. A test checks it against RoGetParameterizedTypeInstanceIID. Note that windows-rs signs delegates as a bare {guid} rather than delegate({guid}), so IReference::<SomeDelegate>::IID from the windows crate doesn't match what WinRT uses.

Argument errors

When an argument can't be marshaled, the call now reports why instead of a bare E_FAIL (thread-local error::set_argument_error, picked up by format_hresult_message; napi throws a TypeError). For example: Expected an Int32Array, an ArrayBuffer, a plain array or null for parameter type Int32[]. Two interop tests asserted that such errors contain HRESULT; they now also accept these messages.

Testing

  • windows-napi npm test: 442/442.
  • New Rust tests: IReference<D> IID against the OS; the delegate box (QI, get_Value identity, refcounts); array element conversion, element counts and view checks.
  • End-to-end on Node with windows-napi, 26/26:
    • Array.create for each type.
    • ReadBytes filling a pre-allocated array, and refusing a plain array.
    • PropertyValue.Create*Array for every element type.
    • WriteBytesAsync with a plain array.
    • TextBox.AddHandler(KeyDownEvent, h, true) and RemoveHandler in a live XamlWindow; on main this throws 0x80070057.
    • The same synchronous checks pass on classic V8 (23/23).
  • cargo test -p runtime --lib: same failures as main (environment and network dependent), plus enum_type_arguments, whose 2 s wait times out under parallel load on some runs and passes alone.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@triniwiz
feat(runtime): primitive arrays, interop.Array.create, boxed delegates
a338cd8
Arrays: every primitive WinRT array parameter (Int32[], Double[],
Char16[], Boolean[], ...) now marshals, both arrays the callee reads and
arrays it fills; only byte[] did before. A typed array of the element's
kind, an ArrayBuffer or DataView is passed in place; a plain JS array is
copied, and refused for a fill array since the callee's writes would be
lost. interop.Array.create(type, count) allocates the matching typed
array up front, e.g. reader.ReadBytes(interop.Array.create('UInt8', n)).

Delegates: a JS delegate passed where WinRT expects an Object now also
answers IInspectable and IReference<D>, the way a projected delegate is
boxed. UIElement.AddHandler unboxes its handler that way and failed with
E_INVALIDARG; AddHandler(..., handledEventsToo) and RemoveHandler work
on both engines.

Errors: an argument that can't be marshaled reports what was expected
("Expected an Int32Array, an ArrayBuffer, a plain array or null for
parameter type Int32[]") instead of "Unspecified error (HRESULT
0x80004005)".
@coderabbitai

coderabbitai Bot commented Nov 6, 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: c956330b-475d-4f14-9b40-a559206bc323

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

  • X
  • Mastodon
  • Reddit
  • LinkedIn
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@triniwiz
triniwiz merged commit d7ae3d3 into main Nov 6, 2026
3 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@triniwiz
triniwiz deleted the feat/winrt-arrays-delegate-boxing branch November 6, 2026 07:20
@triniwiz triniwiz mentioned this pull request Nov 6, 2026
feat(runtime): arrays WinRT hands back, String[]/object arrays, boxed-argument leak #44
Merged
triniwiz added a commit to NativeScript/NativeScript that referenced this pull request Nov 6, 2026
@triniwiz
fix(windows): close modals on light dismiss
4fe2d65
The modal Popup's Closed handler was attached with
AddHandler(Popup.ClosedEvent, ...), but Popup.Closed is a plain event,
not a routed one: Popup.ClosedEvent is undefined, the call threw and
the empty catch hid it. Clicking outside a cancelable modal closed the
Popup without running the modal's close logic, so the view kept its
modal state and the close callback never fired. The handler is now
assigned to popup.Closed and cleared with null on close.

Also corrects the TextField comment: AddHandler(KeyDownEvent, handler,
true) works with a runtime that boxes JS delegates for Object
parameters (NativeScript/windows#41); the KeyDown event stays as the
fallback for runtimes that can't.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@triniwiz
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.