diff --git a/Src/Newtonsoft.Json/JsonTextWriter.Async.cs b/Src/Newtonsoft.Json/JsonTextWriter.Async.cs index 8223af64..c1588233 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.Async.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.Async.cs @@ -314,9 +314,26 @@ namespace Newtonsoft.Json return _safeAsync ? DoWritePropertyNameAsync(name, cancellationToken) : base.WritePropertyNameAsync(name, cancellationToken); } - internal async Task DoWritePropertyNameAsync(string name, CancellationToken cancellationToken) + internal Task DoWritePropertyNameAsync(string name, CancellationToken cancellationToken) { - await InternalWritePropertyNameAsync(name, cancellationToken).ConfigureAwait(false); + Task task = InternalWritePropertyNameAsync(name, cancellationToken); + if (!task.IsCompleted) + { + return DoWritePropertyNameAsync(task, name, cancellationToken); + } + + task = WriteEscapedStringAsync(name, _quoteName, cancellationToken); + if (!task.IsCompleted) + { + return JavaScriptUtils.WriteCharAsync(task, _writer, ':', cancellationToken); + } + + return _writer.WriteAsync(':', cancellationToken); + } + + private async Task DoWritePropertyNameAsync(Task task, string name, CancellationToken cancellationToken) + { + await task.ConfigureAwait(false); await WriteEscapedStringAsync(name, _quoteName, cancellationToken).ConfigureAwait(false); diff --git a/Src/Newtonsoft.Json/Linq/JProperty.Async.cs b/Src/Newtonsoft.Json/Linq/JProperty.Async.cs index 414d6335..560eb7ae 100644 --- a/Src/Newtonsoft.Json/Linq/JProperty.Async.cs +++ b/Src/Newtonsoft.Json/Linq/JProperty.Async.cs @@ -41,9 +41,28 @@ namespace Newtonsoft.Json.Linq /// The token to monitor for cancellation requests. /// A collection of which will be used when writing the token. /// A that represents the asynchronous write operation. - public override async Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) + public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { - await writer.WritePropertyNameAsync(_name, cancellationToken).ConfigureAwait(false); + Task task = writer.WritePropertyNameAsync(_name, cancellationToken); + if (!task.IsCompleted) + { + return WriteToAsync(task, writer, cancellationToken, converters); + } + + JToken value = Value; + if (value != null) + { + return value.WriteToAsync(writer, cancellationToken, converters); + } + else + { + return writer.WriteNullAsync(cancellationToken); + } + } + + private async Task WriteToAsync(Task task, JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) + { + await task.ConfigureAwait(false); JToken value = Value; if (value != null) diff --git a/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs b/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs index 87e91cf1..b017ad4a 100644 --- a/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs @@ -359,6 +359,11 @@ namespace Newtonsoft.Json.Utilities #if !(NET20 || NET35 || NET40 || PORTABLE40) public static Task WriteEscapedJavaScriptStringAsync(TextWriter writer, string s, char delimiter, bool appendDelimiters, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken = default(CancellationToken)) { + if (cancellationToken.IsCancellationRequested) + { + return cancellationToken.FromCanceled(); + } + if (appendDelimiters) { return WriteEscapedJavaScriptStringWithDelimitersAsync(writer, s, delimiter, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); @@ -372,10 +377,31 @@ namespace Newtonsoft.Json.Utilities return WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); } - private static async Task WriteEscapedJavaScriptStringWithDelimitersAsync(TextWriter writer, string s, char delimiter, + private static Task WriteEscapedJavaScriptStringWithDelimitersAsync(TextWriter writer, string s, char delimiter, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) { - await writer.WriteAsync(delimiter).ConfigureAwait(false); + Task task = writer.WriteAsync(delimiter, cancellationToken); + if (!task.IsCompleted) + { + return WriteEscapedJavaScriptStringWithDelimitersAsync(task, writer, s, delimiter, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); + } + + if (!string.IsNullOrEmpty(s)) + { + task = WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); + if (!task.IsCompleted) + { + return WriteCharAsync(task, writer, delimiter, cancellationToken); + } + } + + return writer.WriteAsync(delimiter, cancellationToken); + } + + private static async Task WriteEscapedJavaScriptStringWithDelimitersAsync(Task task, TextWriter writer, string s, char delimiter, + bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) + { + await task.ConfigureAwait(false); if (!string.IsNullOrEmpty(s)) { @@ -385,6 +411,12 @@ namespace Newtonsoft.Json.Utilities await writer.WriteAsync(delimiter).ConfigureAwait(false); } + public static async Task WriteCharAsync(Task task, TextWriter writer, char c, CancellationToken cancellationToken) + { + await task.ConfigureAwait(false); + await writer.WriteAsync(c, cancellationToken).ConfigureAwait(false); + } + private static Task WriteEscapedJavaScriptStringWithoutDelimitersAsync( TextWriter writer, string s, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken)