Skip to content

Preserve whitespace-only argument values when parsing already-saved XAML (STUD-80981) - #403

Open
PavelDrg wants to merge 1 commit into
developfrom
fix/xaml_parser_preserve_whitespace
Open

Preserve whitespace-only argument values when parsing already-saved XAML (STUD-80981)#403
PavelDrg wants to merge 1 commit into
developfrom
fix/xaml_parser_preserve_whitespace

Conversation

@PavelDrg

@PavelDrg PavelDrg commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Description

XAML already on disk carries whitespace-only argument values in a form the parser discards:

<InArgument x:TypeArguments="x:String" xml:space="preserve"> </InArgument>

The value is present in the file, but is dropped on load, so the argument comes back empty.

This PR fixes the read side, for files that already exist. #405 fixes the write side so this form stops being produced in the first place. Neither subsumes the other — see "Relationship to #405" below.

What this covers, and what it does not

This changes CoreWF's System.Xaml, so it reaches consumers that load this parser:

  • Robot executing an already-published package — currently receives an empty argument at runtime where the author wrote a space
  • WorkflowCompiler, ActivityCompiler and the analyzer tooling reading existing project files

It does not reach the Studio designer. Both Studio processes resolve System.Xaml from the shared framework, not from CoreWF:

UiPath.Studio.exe          System.Xaml -> Microsoft.WindowsDesktop.App\8.0.29
UiPath.Studio.Project.exe  System.Xaml -> Microsoft.WindowsDesktop.App\8.0.29

There is a CoreWF System.Xaml.dll in the Studio tree, but at Output/bin/Debug/Studio/net8.0/ — the ActivityCompiler/analyzer tooling folder — not next to the app. So this PR alone does not close STUD-80981 for the designer; #405 does that.

The value here is runtime correctness for workflows already saved or published, which no write-side change can reach.

Root cause

XamlPullParser.Logic_IsDiscardableWhitespace decides whether whitespace-only text at the end of an element is significant. For elements with a content property it only keeps the whitespace when that property is a string or a whitespace-significant collection. InArgument<T> declares both a content property (Expression) and a type converter, so the content-property branch discards the whitespace before the type-converter branch — which would have kept it — is ever consulted. The original comment in that method already describes the intended behavior: .NET 3.0 surfaced whitespace for type-convertible content properties as long as the content property had not been set.

Fix

  • The content-property branch now falls through to the same type-converter check used for elements without a content property: preserved whitespace-only content is surfaced as initialization text when the element is type convertible, no real properties forced constructor use, and nothing has been assigned to the content property. The surfaced text flows through the existing initialization-text path, so InArgumentConverter receives the whitespace and produces Literal<string> with the original value.
  • A new ContentPropertyAssigned flag on XamlParserFrame tracks whether the current element's content property has already received content. PreviousChildType cannot serve this purpose because the implicit EndMember emitted after each content item resets it. The gate keeps documents with inherited xml:space="preserve" and child-element expressions (<InArgument><VisualBasicValue/> </InArgument>) loading exactly as before.

Property elements and attribute-set properties were already excluded via ForcedToUseConstructor, and frames are Reset() on recycling, so no stale state is possible.

Tests

Added to TestCases.Workflows/XamlTests.cs, running in both the JIT and AOT expression-compilation variants:

  • an end-to-end workflow where whitespace-only argument values (space, double space, tab) round-trip through Assign and come back intact — compiled only for net6.0, since the net6.0-windows test build uses the WPF System.Xaml which does not have the fix
  • a guard that a document-wide xml:space='preserve' with a child-element expression still loads

Suites run locally: TestCases.Workflows 261+255 passed, TestCases.Xaml 92+92, TestCases.Activities 770+770 — zero failures. System.Xaml.TestCases has a pre-existing compile error on develop (XamlObjectWriterTest.cs:2129, CS1503 with recent SDKs) unrelated to this change.

Relationship to #405

this PR #405
Side read — XamlPullParser write — Literal.CanConvertToString
Fixes files already saved or published files written from now on
Reaches consumers using CoreWF's System.Xaml every consumer, including the designer
Closes STUD-80981 no yes

Once #405 ships, newly authored workflows never produce the ambiguous form, so this PR's scope narrows over time to the existing corpus. It does not become redundant: published packages are immutable, and a .uipx shipped last year keeps its xml:space form forever.

Jira

https://uipath.atlassian.net/browse/STUD-80981

Context: this started as the proposed fix for STUD-80981, from review discussion on https://github.com/UiPath/Studio/pull/29107. Measuring which System.Xaml the Studio processes actually load showed the designer is on the framework parser, so the ticket is closed by the write-side fix in #405 instead. This PR is retained for the runtime/legacy path, and arguably warrants its own ticket.

🤖 Generated with Claude Code

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@PavelDrg
PavelDrg marked this pull request as draft August 3, 2026 13:47
@PavelDrg
PavelDrg requested a review from david-barzi August 3, 2026 13:59
@PavelDrg
PavelDrg marked this pull request as ready for review August 3, 2026 14:37
@PavelDrg PavelDrg changed the title Preserve whitespace-only argument values when loading XAML (STUD-80981) Preserve whitespace-only argument values when parsing already-saved XAML (STUD-80981) Aug 6, 2026
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.

3 participants