feat: Desktop Skia support, STJ migration, and CI modernization#38
feat: Desktop Skia support, STJ migration, and CI modernization#38clairernovotny wants to merge 323 commits intomainfrom
Conversation
Task: fn-1-implement-desktop-skia-target-for.7 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update task JSON files to match their actual completion state. Both tasks had stale "todo" status in their on-disk JSON while the internal state tracking had them as completed. Task: fn-1-implement-desktop-skia-target-for.7 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Sync task JSON metadata status to done for tasks 1-6 - Add Windows CI job for desktop CDP Playwright tests - Add WASM lifecycle exactly-once integration test - Add per-platform evidence matrix to task 7 spec Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n tests Add desktop CDP tests for markers, undo/redo keyboard operations, and all four language service APIs (Completion, Hover, CodeLens, Color). Update per-platform evidence matrix with detailed Windows test coverage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…test Replace API-existence checks with output-verifying tests for all four language services (Completion returns "foreach", Hover returns "Hit" content, CodeLens returns "Second Line Command", Color detects hex values). Add multi-instance test creating a second editor with independent state verification. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Linux validation is deferred due to no Linux runner/dev machine being available during this epic. The architecture fully supports Linux (single TFM, runtime detection, no preprocessor directives), but manual validation requires a Linux environment. Updated acceptance criteria and Known Gaps section accordingly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create MonacoJsonContext source-gen context with CamelCase naming, WhenWritingNull ignore, and UnsafeRelaxedJsonEscaping for Monaco interop - Register all ~25 cross-boundary types via [JsonSerializable] including Position, Range, Selection, CompletionItem, CodeAction, Hover, etc. - Add JsonSerializerIsReflectionEnabledByDefault=false to .csproj - Suppress SYSLIB1031 for Monaco.Uri / System.Uri name collision - Add 20 serialization contract tests: golden Newtonsoft baselines, STJ round-trip per type category, camelCase verification, null handling, and relaxed encoder verification - Numeric enums (MarkerSeverity, CompletionItemKind) stay as integers Task: fn-2-type-generation-pipeline-and.1
- Convert partial golden baseline assertions to full exact-match JSON comparisons (CompletionItem, CodeAction, Hover, MarkerData, ColorInformation) - Add detailed SYSLIB1031 rationale comment in .csproj since SG diagnostics cannot be suppressed via pragma in user code - Document SYSLIB1031 suppression in MonacoJsonContext remarks - Add UriCollision_BothTypesSerializeCorrectly test proving Monaco.Uri and System.Uri both serialize correctly despite SG name collision Task: fn-2-type-generation-pipeline-and.1
Replace all 30 custom Newtonsoft JsonConverter classes for string-backed enums with [JsonStringEnumMemberName] attributes and per-enum [JsonConverter(typeof(JsonStringEnumConverter<T>))]. Remove property-level converter references from StandaloneEditorConstructionOptions. Numeric enums remain untouched. Add 7 contract tests verifying round-trip for representative enums including hyphenated values and camelCase wire format. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The active Newtonsoft serialization path (WebViewExtensions.cs) still uses JsonConvert.SerializeObject for StandaloneEditorConstructionOptions. Without [EnumMember] attributes and a Newtonsoft StringEnumConverter, Newtonsoft would serialize string enums as integers after deleting the custom converters. Add [EnumMember(Value = "wireValue")] on each member and [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))] on each enum type for all 30 string-backed enums. Add 7 Newtonsoft dual-stack contract tests covering hyphenated, camelCase, and simple values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite InterfaceToClassConverter, CssStyleConverter, and ColorConverter as STJ JsonConverter<T> implementations while preserving Newtonsoft dual-stack converters for compatibility until Newtonsoft removal. - InterfaceToClassConverter<TInterface, TClass>: STJ JsonConverter<TInterface> that delegates Read to Deserialize<TClass> and Write to Serialize(typeof(TClass)) - CssStyleConverter: per-type STJ write-only converters (CssLineStyleConverter, CssGlyphStyleConverter, CssInlineStyleConverter) that serialize ICssStyle.Name - ColorConverter: STJ JsonConverter<Color> using Utf8JsonReader/Utf8JsonWriter for Monaco 0-1 float RGBA format - Migrate [JsonProperty] -> [JsonPropertyName] in ColorInformation.cs - Add dual-stack [JsonConverter] attributes on all usage sites - Add 10 contract tests covering round-trip, golden parity, and write-only behavior - Update rd.xml for NewtonsoftInterfaceToClassConverter reflection directive Task: fn-2-type-generation-pipeline-and.4 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- NewtonsoftCssStyleConverter.ReadJson now throws NotSupportedException instead of returning an exception object as data - NewtonsoftInterfaceToClassConverter uses Deserialize<TClass> instead of Populate(), removing last serializer.Populate() call - ColorConverter.Read clamps and rounds float values to prevent out-of-range payloads from silently corrupting color bytes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace [JsonProperty] with CamelCase naming policy across ~64 model files - Add [JsonPropertyName] only where wire name diverges from CamelCase convention - Remove per-property NullValueHandling.Ignore (handled globally by WhenWritingNull) - Replace using Newtonsoft.Json with using System.Text.Json.Serialization - Add [JsonInclude] on properties with non-public setters for STJ source gen - Change private set to internal set on Position, Range, Selection, WordAtPosition, ContextKey, IModelDeltaDecoration for STJ source generator visibility (SYSLIB1038) - Add dual-stack [Newtonsoft.Json.JsonIgnore] on Selection.Direction for compat - Update golden baseline test to use CamelCasePropertyNamesContractResolver - Add round-trip tests for Range, Selection, and interface-typed properties (IRange) Task: fn-2-type-generation-pipeline-and.3
- Add [JsonIgnore(Condition = JsonIgnoreCondition.Never)] on Model property to allow explicit null serialization for Monaco's "model: null" contract - Complete IModelDeltaDecoration round-trip test with deserialization and value verification via InterfaceToClassConverter - Add IPosition round-trip test verifying [JsonInclude] on internal setters Task: fn-2-type-generation-pipeline-and.3
Task: fn-2-type-generation-pipeline-and.3
CamelCase naming policy already produces "uris" from "Uris". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…essor for AOT - Replace all JsonConvert.SerializeObject/DeserializeObject/ToString in WebViewExtensions, CodeEditor.Methods, LanguagesHelper, ModelHelper with JsonSerializer using MonacoJsonContext.Default (deserialization) and MonacoJsonContext.Relaxed (JS interop serialization) - Delete _settings field from WebViewExtensions (CamelCase + NullIgnore now on MonacoJsonContext) - Redesign ParentAccessor.SetValue to use FQN-keyed Dictionary<string, JsonTypeInfo> lookup instead of AOT-hostile Type.GetType() + assembly scanning - Redesign ParentAccessor.GetJsonValue to use STJ with fail-fast InvalidOperationException for unregistered types - Delete LookForTypeByName from both ParentAccessor and ParentAccessorDesktop - Add RegisterTypeInfo extensibility API on IParentAccessor - Mark AddAssemblyForTypeLookup as [Obsolete] (no-op, retained for compat) - Add BuildTypeInfoMap() to MonacoJsonContext for AOT-safe type registry - Register additional types in MonacoJsonContext: ContextKey, FindMatch, WordAtPosition, ILanguageExtensionPoint, object, string, bool, and collection variants - Add callback round-trip contract tests for Completion, CodeAction, Hover, Color, Markers - Add ParentAccessor type registry tests for known/unknown type handling - Remove dead AddAssemblyForTypeLookup call from CodeEditor.Events Task: fn-2-type-generation-pipeline-and.5
- Return "null" instead of "{}" from GetJsonValue when property is null
to preserve JSON contract for JS callers expecting nullable values
- Harden unregistered-type exception handling in GetJsonValue to catch
both InvalidOperationException and NotSupportedException (STJ may
throw either depending on the code path)
- Add direct accessor behavior tests: RegisterTypeInfo extensibility,
SetValue unknown-type fail-fast, GetJsonValue null contract,
GetJsonValue unregistered-type exception wrapping, SetValue
known-type deserialization via type info map
Task: fn-2-type-generation-pipeline-and.5
Task: fn-2-type-generation-pipeline-and.5
…ment bugs - Use Position.Lift/Range.Lift for IPosition/IRange before STJ serialization to ensure concrete type metadata is available in AOT/source-gen mode - Materialize IEnumerable<ColorInformation/ColorPresentation> to arrays with typed overloads (ColorInformationArray/ColorPresentationArray) - Fix FindNextMatchAsync/FindPreviousMatchAsync passing searchString instead of searchStart as second argument - Let STJ metadata exceptions (InvalidOperationException, NotSupportedException) propagate through WebViewExtensions catch-all instead of being silently hidden Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use ConcurrentDictionary<string, JsonTypeInfo> for _typeInfoMap in ParentAccessor and ParentAccessorDesktop to prevent race conditions between RegisterTypeInfo writes and SetValue reads - Update MonacoJsonContext.BuildTypeInfoMap() to return ConcurrentDictionary - Stop swallowing STJ metadata/AOT failures in WebViewExtensions by excluding InvalidOperationException and NotSupportedException from the catch-all handler so unregistered types surface clearly - Add List<T>-to-array materialization tests for ColorPresentation and ColorInformation matching the LanguagesHelper serialization pattern Task: fn-2-type-generation-pipeline-and.5 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Task: fn-2-type-generation-pipeline-and.5 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ParentAccessor.SetValue(string, object) was calling BridgeEncoding.Desanitize on browser, but ManagedSetValue in ParentAccessor.wasm.cs already desanitizes at the JSExport boundary before calling SetValue. This double-decode could corrupt legitimate %NN text patterns in editor content. Remove the redundant desanitize from SetValue and document that JSExport entrypoints are the canonical decode boundary. Task: fn-2-type-generation-pipeline-and.5 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove Newtonsoft.Json PackageVersion from Directory.Packages.props - Remove Newtonsoft.Json PackageReference from MonacoEditorComponent.csproj - Remove Newtonsoft type directives from MonacoEditorComponent.rd.xml - Remove dual-stack Newtonsoft converter classes (NewtonsoftInterfaceToClassConverter, NewtonsoftCssStyleConverter, NewtonsoftColorConverter) - Remove all [Newtonsoft.Json.JsonConverter] attributes from ~30 string-backed enums - Remove [Newtonsoft.Json.JsonConverter] attributes from CssGlyphStyle, CssLineStyle, CssInlineStyle, ColorInformation - Remove [Newtonsoft.Json.JsonIgnore] from Selection, CssGlyphStyle, CssLineStyle - Remove using Newtonsoft.Json from all affected .cs files - Update serialization contract tests to use STJ golden baselines instead of Newtonsoft parity comparisons - Add changelog.md entry documenting the breaking change with migration guidance Task: fn-2-type-generation-pipeline-and.6
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 207 out of 646 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…der functionality
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 207 out of 646 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Decode JSON-RPC array string elements as strings in ParentAccessorDesktop so hover provider position payloads are deserialized as Monaco.Position instead of quoted JSON text. Also harden hover callback deserialization to log JsonException without faulting the RPC request and keep the host visually hidden (opacity 0) during forced init visibility to reduce white-frame flicker.
…dd feature probe for editor diagnostics
…r handling and improved error management
…der functionality
- Implemented project scaffold and build infrastructure for HybridWebViewComponent. - Defined core interfaces, control class, and XAML template for HybridWebView. - Created JavaScript bridge script and async task manager for interop. - Developed Desktop WebView2 presenter for C#↔JS communication. - Implemented WASM iframe presenter for hosting local content. - Added sample page and end-to-end validation for interop paths in MonacoEditorTestApp. - Initiated PoC for composition-mode WebView2 with DirectComposition in Uno Win32. - Validated flickering scenarios and airspace issues in both HWND and DComp modes.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 226 out of 666 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The Microsoft.Playwright package is now referenced without the ExcludeAssets="build;buildTransitive" attribute. This change allows all Playwright build assets to be included, removing previous suppression that avoided build target conflicts on some platforms.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 227 out of 667 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
This PR delivers three major initiatives for the Uno Monaco Editor:
Desktop Skia Support (fn-1)
net10.0-desktoptarget framework to MonacoEditorComponent and test appSystem.Text.Json Migration (fn-2)
Newtonsoft.Jsondependency entirely[JsonProperty]to[JsonPropertyName]MonacoJsonContextsource generator for trimming/AOT compatibilityJsonConverttoJsonSerializerCI Modernization (fn-3)
macos-15) build job for Apple Silicon validationnpm install && npm run buildstep to generate Monaco bundles in CITest plan
buildjob (ubuntu) passesdesktop-testsjob (windows) passesbuild-macosjob (macos-15) passes🤖 Generated with Claude Code