Skip to content

Serialize whitespace-only Literal<T> values as elements instead of text (STUD-80981) - #405

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

Serialize whitespace-only Literal<T> values as elements instead of text (STUD-80981)#405
PavelDrg wants to merge 1 commit into
developfrom
fix/literal_whitespace_serialization

Conversation

@PavelDrg

@PavelDrg PavelDrg commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Description

A whitespace-only value in an Invoke Workflow File argument — e.g. a single space — is silently dropped when the workflow is reopened. This is the write-side half of the problem: the value is serialized in a form that parsers are entitled to discard, so every consumer that reads the file back loses it.

Companion to #403, which fixes the read side. Neither subsumes the other — see "Relationship to #403" below.

Root cause

Literal<T>.CanConvertToString reports that a whitespace-only string can be written as text, so XamlObjectReader emits the value as element content on the argument:

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

A XAML parser discards whitespace-only text in an element whose content property is not a string. InArgument<T> declares Expression — an Activity<T> — as its content property, so the text is dropped before the type converter that would have consumed it is ever consulted.

The same method already refuses text form for null and empty strings for exactly this reason (Value == null, and the IsNullOrEmpty guard added in 5c84ac5 for STUD-74008). Whitespace-only is the same case, and was simply missed.

Fix

One line — IsNullOrEmptyIsNullOrWhiteSpace. The value now serializes as an element:

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

Literal<T> declares Value as its content property, and that is a string, so this lands in the parser's existing prop.Type == XamlLanguage.String branch, which preserves the whitespace. No parser change is required for this form to round-trip.

Because it changes the data rather than a reader, every consumer benefits — designer, validation, the analyzer, the reference DB, WorkflowCompiler and Robot — without any of them being touched.

Values with surrounding whitespace (" x ") are unaffected and still serialize as text; only whitespace-only values change form.

Tests

Added to TestCases.Workflows/WF4Samples/LiteralTests.cs, alongside the existing null/empty cases:

  • CanConvertToString_WhitespaceOnlyString_ReturnsFalse — space, double space, tab
  • XamlSerialize_WhitespaceOnlyStringLiteral_WritesLiteralElement — asserts the element form is emitted
  • XamlRoundTrip_WhitespaceOnlyStringLiteral_PreservesTheValue — save then load, value intact
  • CanConvertToString_StringWithSurroundingWhitespace_ReturnsTrue — guards that " x " still uses text form

Verified independently of #403: with XamlPullParser.cs checked out from develop (i.e. the unfixed parser), LiteralTests is 29/29 green. That is what demonstrates the new format round-trips on an unpatched parser, including the WPF System.Xaml that the Studio designer and UiPath.Studio.Project actually load.

Suites run locally: TestCases.Workflows 271 + 265 passed, 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 #403

#403 this PR
Side read — XamlPullParser write — Literal.CanConvertToString
Fixes files already on disk files written from now on
Reaches consumers using CoreWF's System.Xaml every consumer

#403 remains necessary: it is the only thing that helps already-published packages, where Robot reads a legacy whitespace argument and gets an empty value at runtime. No write-side change can reach a .nupkg that has already shipped.

This PR is what closes STUD-80981 for newly authored workflows. Note it lands in System.Activities.dll, which Studio consumes via the UiPath.Workflow package — so it reaches Studio through a dependency bump, not a change in the Studio repo.

Jira

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

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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