in src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/JavaScriptUtils.cs [118:261]
public static void WriteEscapedJavaScriptString(TextWriter writer, string? s, char delimiter, bool appendDelimiters,
bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, IArrayPool<char>? bufferPool, ref char[]? writeBuffer
)
{
// leading delimiter
if (appendDelimiters) writer.Write(delimiter);
if (!StringUtils.IsNullOrEmpty(s))
{
var lastWritePosition = FirstCharToEscape(s, charEscapeFlags, stringEscapeHandling);
if (lastWritePosition == -1)
writer.Write(s);
else
{
if (lastWritePosition != 0)
{
if (writeBuffer == null || writeBuffer.Length < lastWritePosition)
writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, lastWritePosition, writeBuffer);
// write unchanged chars at start of text.
s.CopyTo(0, writeBuffer, 0, lastWritePosition);
writer.Write(writeBuffer, 0, lastWritePosition);
}
int length;
for (var i = lastWritePosition; i < s.Length; i++)
{
var c = s[i];
if (c < charEscapeFlags.Length && !charEscapeFlags[c]) continue;
string? escapedValue;
switch (c)
{
case '\t':
escapedValue = @"\t";
break;
case '\n':
escapedValue = @"\n";
break;
case '\r':
escapedValue = @"\r";
break;
case '\f':
escapedValue = @"\f";
break;
case '\b':
escapedValue = @"\b";
break;
case '\\':
escapedValue = @"\\";
break;
case '\u0085': // Next Line
escapedValue = @"\u0085";
break;
case '\u2028': // Line Separator
escapedValue = @"\u2028";
break;
case '\u2029': // Paragraph Separator
escapedValue = @"\u2029";
break;
default:
if (c < charEscapeFlags.Length || stringEscapeHandling == StringEscapeHandling.EscapeNonAscii)
{
if (c == '\'' && stringEscapeHandling != StringEscapeHandling.EscapeHtml)
escapedValue = @"\'";
else if (c == '"' && stringEscapeHandling != StringEscapeHandling.EscapeHtml)
escapedValue = @"\""";
else
{
if (writeBuffer == null || writeBuffer.Length < UnicodeTextLength)
writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, UnicodeTextLength, writeBuffer);
StringUtils.ToCharAsUnicode(c, writeBuffer!);
// slightly hacky but it saves multiple conditions in if test
escapedValue = EscapedUnicodeText;
}
}
else
escapedValue = null;
break;
}
if (escapedValue == null) continue;
var isEscapedUnicodeText = string.Equals(escapedValue, EscapedUnicodeText, StringComparison.Ordinal);
if (i > lastWritePosition)
{
length = i - lastWritePosition + (isEscapedUnicodeText ? UnicodeTextLength : 0);
var start = isEscapedUnicodeText ? UnicodeTextLength : 0;
if (writeBuffer == null || writeBuffer.Length < length)
{
var newBuffer = BufferUtils.RentBuffer(bufferPool, length);
// the unicode text is already in the buffer
// copy it over when creating new buffer
if (isEscapedUnicodeText)
{
MiscellaneousUtils.Assert(writeBuffer != null,
"Write buffer should never be null because it is set when the escaped unicode text is encountered.");
Array.Copy(writeBuffer, newBuffer, UnicodeTextLength);
}
BufferUtils.ReturnBuffer(bufferPool, writeBuffer);
writeBuffer = newBuffer;
}
s.CopyTo(lastWritePosition, writeBuffer, start, length - start);
// write unchanged chars before writing escaped text
writer.Write(writeBuffer, start, length - start);
}
lastWritePosition = i + 1;
if (!isEscapedUnicodeText)
writer.Write(escapedValue);
else
writer.Write(writeBuffer, 0, UnicodeTextLength);
}
MiscellaneousUtils.Assert(lastWritePosition != 0);
length = s.Length - lastWritePosition;
if (length > 0)
{
if (writeBuffer == null || writeBuffer.Length < length)
writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, length, writeBuffer);
s.CopyTo(lastWritePosition, writeBuffer, 0, length);
// write remaining text
writer.Write(writeBuffer, 0, length);
}
}
}
// trailing delimiter
if (appendDelimiters) writer.Write(delimiter);
}