Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: Security-Testing-Five/cppwinrt
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: microsoft/cppwinrt
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 7 commits
  • 20 files changed
  • 11 contributors

Commits on Jul 8, 2026

  1. Fix C4819 warning: replace non-ASCII em dash in base_macros.h comment (

    …microsoft#1606)
    
    * Initial plan
    
    * Fix C4819 warning: replace non-ASCII em dash with ASCII hyphen in base_macros.h comment
    
    ---------
    
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Copilot authored Jul 8, 2026
    Configuration menu
    Copy the full SHA
    a535d38 View commit details
    Browse the repository at this point in the history

Commits on Jul 27, 2026

  1. Fix race condition in cancellation setup/teardown (microsoft#1609)

    The code failed to handle three cases.
    
    1. A cancellation is in progress when a cancellable awaitable begins.
    2. A cancellation is in progress when a cancellable awaitable ends.
    3. A cancellation is in progress when a cancel() request is made.
    
    The m_canceller member has one of these three values:
    
    * nullptr, meaning that there is nothing to cancel.
      It has this value when the coroutine is not awaiting, or if it is
      awaiting something that cannot be cancelled.
    * cancelling_ptr, meaning that another thread (not the coroutine thread)
      is in the middle of cancellation request.
    * function pointer, representing the function to call to cancel the await.
    
    In case 1, we should not overwrite the canceling_ptr with the
    function pointer, because only the code doing the cancel()
    can transition into/out of cancelling_ptr.
    
    In case 2, we intended to spin until the m_canceller is no longer
    cancelling_ptr, but we used m_canceller.exchange(nullptr) in a loop,
    which means that if m_canceller was cancelling_ptr, we overwrite it
    with nullptr. As a result, the "while" loop always exits after one iteration.
    We need to spin on the m_canceller without modifying it if it is cancelling_ptr.
    
    In case 3, cancel() function resets m_cancelling back to nullptr,
    even if the value was cancelling_ptr on entry, prematurely declaring
    that the existing cancel() has completed. If the original value was
    cancelling_ptr, we should leave it that way.
    
    There are still other cases not handled:
    
    * Coroutine already cancelled when a co_await starts.
    
    In this case, we never call the canceller, so the coroutine fails
    to propagate cancellation. This will require a broader fix, so I'm not
    going to fix it in this PR. This PR is primarily about fixing the crash
    caused by case 2. Cases 1 and 3 were fixed opportunistically.
    oldnewthing authored Jul 27, 2026
    Configuration menu
    Copy the full SHA
    d3d92d7 View commit details
    Browse the repository at this point in the history

Commits on Jul 28, 2026

  1. Add <ratio> header to base_includes.h (microsoft#1612)

    base_types.h uses std::ratio_multiply, which is defined in <ratio>. Under strict include-what-you-use rules not referencing this header can lead to weird build breaks.
    Penguinwizzard authored Jul 28, 2026
    Configuration menu
    Copy the full SHA
    d6cff31 View commit details
    Browse the repository at this point in the history

Commits on Aug 19, 2026

  1. Remove WINRT_EXPORT in Component.g.cpp (microsoft#1597)

    Co-authored-by: Ryan Shepherd <ryansh@microsoft.com>
    YexuanXiao and DefaultRyan authored Aug 19, 2026
    Configuration menu
    Copy the full SHA
    a7f0233 View commit details
    Browse the repository at this point in the history

Commits on Aug 24, 2026

  1. C++/WinRT ABI interop improvements (microsoft#1608)

    * Add _hs literal for compile-time fast-pass HSTRING
    
    Passing a wide string literal to a WinRT API that takes an hstring runs
    wcslen and fills a seven-field HSTRING_HEADER on the stack on every call
    (via param::hstring -> create_hstring_on_stack). For a literal, all of
    that is knowable at compile time and only needs to happen once.
    
    Add a `_hs` user-defined literal that builds the fast-pass reference
    header as a constexpr static, so `L"value"_hs` reduces to a single
    pointer load at the call site with no per-call wcslen or header fill.
    
    The literal-operator-template is keyed on the characters themselves via a
    C++20 non-type template parameter (hstring_literal_storage<N>), so each
    distinct literal gets its own static header with static lifetime. It
    returns a non-owning winrt::hstring_reference (a plain winrt::hstring
    would assert/free the reference header in its destructor). A matching
    param::hstring constructor lets the result bind to projected setters in a
    single user-defined conversion.
    
    A bare `param::hstring(wchar_t const(&)[N])` overload is deliberately not
    added: it would also bind non-literal arrays (e.g. a partially-filled
    wchar_t buf[260]) and infer length N-1 past the null, silently
    corrupting; and a runtime constructor cannot produce a content-specific
    static anyway. `_hs` is the explicit, safe opt-in; bare literal calls keep
    their unchanged wcslen path.
    
    Gated on __cpp_nontype_template_args >= 201911L. Tested under C++20 in
    test_cpp20/hstring_literal.cpp; the non-gated types build under C++17.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1
    
    * Add make_ready for pre-completed async operations
    
    Returning an already-available value through an async-typed API (a cache
    hit, a fast path, or an API async-typed only for interface uniformity)
    still pays the full coroutine cost when written as `co_return value`:
    a heap-allocated coroutine frame plus a promise that is a complete COM
    object implementing IAsyncOperation and IAsyncInfo, carrying a slim_mutex,
    an agile completed-handler slot, an atomic status, and cancel machinery,
    all built and torn down on every call.
    
    Add winrt::make_ready<T>(value) and winrt::make_ready() that return a
    minimal already-completed IAsyncOperation<T> / IAsyncAction: it holds just
    the value with a fixed Completed status and no coroutine frame, no
    slim_mutex, no handler slot, and no cancel machinery. Setting a Completed
    handler on it invokes immediately, and Status()/GetResults() satisfy both
    the .get() and co_await consumer paths, so it is a drop-in for the
    synchronous-result case. `co_return` remains correct for genuinely
    suspending work, where the frame is doing real work and the overhead is
    amortized to noise.
    
    The one-shot Completed assignment is guarded with a lock-free atomic flag
    rather than a lock. Tested in test/make_ready.cpp.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1
    
    * Buffer range-for iteration over non-GetAt collections
    
    Range-for over a collection that lacks GetAt (a plain IIterable<T>, or a
    map yielding IKeyValuePair) drove the projected IIterator one element per
    ABI crossing via Current/MoveNext. For a large sequence that is one vtable
    call per item.
    
    Route that path through a buffered_iterator that pulls a block of elements
    with a single IIterator::GetMany call into a small stack buffer and yields
    from it, refilling only when the buffer is drained. Existing
    `for (auto&& x : v)` code gets the speedup with no source change. The block
    is sized like windows-rs' BufferedIterator -- clamp(2048 / sizeof(T), 1,
    128) -- to cap the buffer near 1-2 KB and bound over-fetch for large
    element types.
    
    Only the non-GetAt path changes. Collections with GetAt (IVector,
    IVectorView) keep the existing random-access fast_iterator, so no
    iterator-category guarantees are affected. The iterator is single-pass,
    matching IIterator's own semantics.
    
    Tested in test/buffered_iterator.cpp (multi-block, block boundary, empty,
    and a non-trivial element type).
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1
    
    * Perfect-forward make_ready value
    
    Use TResult&& + decay_t<TResult> so make_ready forwards its argument into
    the operation instead of taking it by value, saving a move and matching the
    make_unique/make_shared idiom.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1
    
    * Make _hs a constant expression
    
    Move the fast-pass header from a function-local static into an inline
    constexpr variable template and mark hstring_reference and the operator
    constexpr, so `constexpr auto s = L"x"_hs;` is a genuine compile-time
    construction rather than per-call work. Add a constexpr construction to the
    test to prove it.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1
    
    * Box scalars locally instead of via combase PropertyValue
    
    box_value on a scalar routed through the cached Windows.Foundation.
    PropertyValue activation factory into combase, which allocates a general
    IPropertyValue carrying the discriminated-union machinery for all property
    types. For the common scalar cases that round-trip is pure overhead.
    
    Point the scalar reference_traits (u8..u64, float, double, bool, char16,
    hstring, guid) at the in-process impl::reference<T> that already backs
    non-scalar IReference<T>, and make that type a correct IPropertyValue:
    report the right PropertyType per T (was always OtherType), fix
    IsNumericScalar (was true for bool), and return the value from the matching
    typed getter (GetString/GetGuid/GetBoolean/GetChar16/GetSingle/GetDouble
    previously threw). Mismatched numeric getters keep combase-style
    conversion (GetInt16 on a boxed int32 converts), so consumers see the same
    behavior minus the combase hop. This mirrors windows-rs' StockReference.
    
    Composite/array/inspectable cases (DateTime, TimeSpan, Point, Size, Rect,
    IReferenceArray, IInspectable) stay on combase PropertyValue.
    
    Two honest deltas vs combase, both matching windows-rs: GetRuntimeClassName
    is now the IReference`1<T> name rather than Windows.Foundation.
    PropertyValue, and cross-process the value marshals as an IReference proxy
    rather than by value. Tested in test/reference_boxing.cpp.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1
    
    * Marshal boxed scalars by value via combase PropertyValue
    
    The in-proc scalar reference<T> introduced in the prior commit is agile via the
    free-threaded marshaler, so cross-process it marshals by reference (an IReference
    proxy) rather than by value the way combase PropertyValue does. Mirror windows-rs
    and combase: for the stock scalar types, mark reference<T> non_agile and supply
    IMarshal from query_interface_tearoff by lazily building the equivalent combase
    PropertyValue and delegating marshaling to it, so the destination materializes a
    real PropertyValue copy. IAgileObject is still advertised (the reference is
    immutable and thread-safe) to keep the agile fast path. The combase hop is paid
    only on marshal, never on box_value/unbox_value.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    
    * Box DateTime, TimeSpan, and Point in-process too
    
    Extend the in-proc reference<T> to cover DateTime, TimeSpan, and Point: report
    the correct PropertyType, return the value from the matching typed getter, and
    mark them stock so they still marshal by value through combase PropertyValue.
    Drop their combase reference_traits specializations so box_value routes to the
    local reference<T> like the other scalars.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    
    * Buffer range-for over GetAt collections (batch IVector via GetMany)
    
    fast_iterator (used for random-access, GetAt-capable collections like IVector/
    IVectorView) now prefetches a block with a single GetMany call and serves in-window
    reads from it, so range-for crosses the ABI ~once per block instead of one GetAt per
    element. Random access is preserved: an out-of-window index re-anchors the block, and an
    at/after-end index defers to GetAt so E_BOUNDS behavior is unchanged. Elements are copied
    out (no move-out) so an index may be read repeatedly, as the random-access contract
    requires. This extends the non-GetAt buffering to vectors, closing the IterateVector gap
    to windows-rs.
    
    * Fix MSVC and clang-cl build breaks from the interop fast paths
    
    Three portability breaks surfaced by CI across MSVC and clang-cl:
    
    - Iterator batching assumed every collection/iterator has GetMany and every
      element type is default-constructible. IBindableVectorView has GetAt but no
      GetMany, IBindableIterator has no GetMany, and types like JsonValue have no
      default constructor. Gate the GetMany block buffer on both a GetMany detector
      and default-constructibility (can_batch); otherwise fall back to per-element
      GetAt / Current+MoveNext. The block buffer is elided entirely when unused.
    - reference<T>::query_interface_tearoff called .as<IMarshal>() on a dependent
      expression; clang requires .template as<IMarshal>().
    - hstring_reference::m_handle is only read via layout punning in get_abi, so
      clang -Werror,-Wunused-private-field rejected it. Mark it [[maybe_unused]].
    
    Verified: msbuild cppwinrt + test/test_old (MSVC) and test/test_nocoro/test_old
    (clang-cl), x64 Debug, all build clean.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    
    * Add optional clang compiler arg to build_test_all.cmd
    
    build_test_all.cmd only built the MSVC toolset, so a local pass did not catch
    clang-cl -Werror breaks that CI's clang-cl leg rejects. Add an optional 5th
    positional arg (default msvc); pass clang/clang-cl to append
    Clang=1,PlatformToolset=ClangCl to the cppwinrt.sln compiler and test builds,
    matching CI. natvis and NugetTest.sln stay on MSVC, as the clang CI leg does not
    cover them. Also fix a stray trailing quote on the nuget restore line and
    document the arg in README.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    
    * Guard _hs test's literals using-directive for non-conforming NTTP compilers
    
    hstring_literal.cpp had an unconditional using-directive for winrt::literals,
    but that namespace and its operator ""_hs only exist under
    __cpp_nontype_template_args >= 201911L. clang-cl reports 201411L (no class-type
    NTTP), so the namespace is absent and the using-directive failed to compile
    ("expected namespace name"), breaking the clang-cl test_cpp20 leg. Move the
    using-directive inside the same feature guard the rest of the test already uses.
    
    Verified: full CI test-project set builds clean on both MSVC v145 and clang-cl,
    x64 Debug.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    
    * Remove buffered-iterator and ready-async helpers
    
    Drop the batched range-for iterator (base_iterator.h) and the
    already-completed make_ready/ready_async async helpers
    (base_coroutine_foundation.h), reverting both headers to their base
    state. These will be reintroduced in wil/cppwinrt.h. Removes the
    buffered_iterator.cpp and make_ready.cpp tests accordingly.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    
    * Simplify reference_base_t and test in-proc agility
    
    Collapse reference_base_t to a single implements<> whose trailing marker
    is conditional (non_agile for stock scalars, an inert marker placeholder
    otherwise), instead of duplicating the interface list across a
    conditional_t. implements<> ignores non-interface, non-marker type
    parameters, so the placeholder is a no-op.
    
    Add a test that boxes a scalar in one STA and fetches it from another via
    the Global Interface Table, asserting the object identity is preserved -
    proving the IAgileObject in-proc fast path.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    
    * Box arrays locally and address review feedback
    
    Add an in-process reference_array<T> (IReferenceArray<T> + IPropertyValue),
    the array counterpart to reference<T>, so box_value/unbox_value of the stock
    array element types no longer builds a combase PropertyValue. hstring,
    TimeSpan, DateTime (projected type != ABI) and IInspectable/Size/Rect stay on
    combase. Collapse every IPropertyValue getter on both types into one internal
    get_as<To>() that holds the constexpr type check and throw, and share a
    scalar_property_type<T>()/array_property_type<T>() helper.
    
    Also fold in the earlier review fixes: single implements<> with a conditional
    trailing marker for reference_base_t, GetSize/GetRect fast paths, an _hs
    null-termination static_assert, and drop the duplicate test_module_lock_none
    build in build_test_all.cmd. Extend reference_boxing.cpp with array boxing,
    array marshal-by-value, and cross-STA agile identity coverage.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    
    * Share a producer base, drop comments and build-script changes
    
    Fold the duplicated IPropertyValue getters and IMarshal tearoff shared by
    reference<T> and reference_array<T> into a reference_producer CRTP base; the
    two leaves just supply storage, get_as, and create_property_value. Same codegen
    and per-instance footprint as the two-template version, ~80 fewer source lines.
    
    Per review feedback, strip the newly-added implementation comments from
    base_reference_produce.h and base_string.h, and revert the build_test_all.cmd
    compiler-selection helper and its README note so this PR carries only the
    projection/boxing functionality.
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
    Co-authored-by: Jon Wiswall <18537118+jonwis@users.noreply.github.com>
    Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1
    3 people authored Aug 24, 2026
    Configuration menu
    Copy the full SHA
    74a13c5 View commit details
    Browse the repository at this point in the history

Commits on Aug 26, 2026

  1. Add get_unchecked() to async operations (microsoft#1565)

    * Add get_only_safe_from_non_presenting_sta() to async operations
    
    Add a peer to .get() on IAsyncAction, IAsyncOperation, IAsyncActionWithProgress,
    and IAsyncOperationWithProgress that skips the _DEBUG-only STA blocking assert.
    
    The existing .get() asserts !is_sta_thread() to guard against blocking UI threads.
    However, not all STAs are UI threads — some never present UI, haven't presented yet,
    or never will. The assert is also _DEBUG-only, making it invisible to codebases that
    don't build with _DEBUG (e.g. the Windows OS).
    
    The new method get_only_safe_from_non_presenting_sta() is functionally identical to
    .get() but omits the STA check. The intentionally long name communicates the risk
    to callers.
    
    Changes:
    - strings/base_coroutine_foundation.h: Add wait_get_bypass_sta_check() impl helper
      and get_only_safe_from_non_presenting_sta() for all 4 async consume templates
    - cppwinrt/code_writers.h: Add declaration to generated code for all 4 async types
    - test/test_nocoro: Add test calling the new method from an STA thread using a
      real WinRT async operation (PathIO::ReadTextAsync on C:\Windows\win.ini)
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Rename STA bypassing async get method
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix STA test cleanup and assertions
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Chris Guzak (WINDOWS) <chrisg@ntdev.microsoft.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    3 people authored Aug 26, 2026
    Configuration menu
    Copy the full SHA
    9cf9564 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    856eaff View commit details
    Browse the repository at this point in the history
Loading