Skip to content

Commit 3f06e49

Browse files
committed
add fix
1 parent 8fd7f3b commit 3f06e49

4 files changed

Lines changed: 30 additions & 6 deletions

File tree

src/TraceEvent/Stacks/ChromiumStackSourceWriter.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ private static void WriteToFile(Dictionary<int, FrameInfo> frameIdToFrameTuple,
5555
IReadOnlyDictionary<ThreadInfo, IReadOnlyList<ProfileEvent>> sortedProfileEventsPerThread,
5656
TextWriter writer, string name)
5757
{
58+
Dictionary<string, string> escapedNames = new Dictionary<string, string>();
59+
5860
writer.Write("{");
59-
writer.Write($"\"otherData\": {{ \"name\": \"{name}\", \"exporter\": \"{GetExporterInfo()}\" }}, ");
61+
writer.Write($"\"otherData\": {{ \"name\": \"{GetEscaped(name, escapedNames)}\", \"exporter\": \"{GetExporterInfo()}\" }}, ");
6062
writer.Write("\"traceEvents\": [");
6163
bool isFirst = true;
6264
foreach (var perThread in sortedProfileEventsPerThread.OrderBy(pair => pair.Value.First().RelativeTime))
@@ -69,7 +71,7 @@ private static void WriteToFile(Dictionary<int, FrameInfo> frameIdToFrameTuple,
6971
isFirst = false;
7072

7173
writer.Write("{");
72-
writer.Write($"\"name\": \"{frameIdToFrameTuple[profileEvent.FrameId].Name}\", ");
74+
writer.Write($"\"name\": \"{GetEscaped(frameIdToFrameTuple[profileEvent.FrameId].Name, escapedNames)}\", ");
7375
writer.Write($"\"cat\": \"sampleEvent\", ");
7476
writer.Write($"\"ph\": \"{(profileEvent.Type == ProfileEventType.Open ? "B" : "E")}\", ");
7577
writer.Write($"\"ts\": {profileEvent.RelativeTime.ToString("R", CultureInfo.InvariantCulture)}, ");
@@ -93,7 +95,7 @@ private static void WriteToFile(Dictionary<int, FrameInfo> frameIdToFrameTuple,
9395
var frameId = frame.Key;
9496
var frameInfo = frame.Value;
9597
writer.Write($"\"{frameId}\": {{");
96-
writer.Write($"\"name\": \"{frameInfo.Name}\", ");
98+
writer.Write($"\"name\": \"{GetEscaped(frameInfo.Name, escapedNames)}\", ");
9799
writer.Write($"\"category\": \"{frameInfo.Category}\"");
98100
if (frameInfo.ParentId != -1)
99101
writer.Write($", \"parent\": {frameInfo.ParentId}");

src/TraceEvent/Stacks/SpeedScopeStackSourceWriter.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,18 @@ private static void Export(StackSource source, TextWriter writer, string name)
5252
private static void WriteToFile(IReadOnlyDictionary<string, IReadOnlyList<ProfileEvent>> sortedProfileEventsPerThread,
5353
IReadOnlyList<string> orderedFrameNames, TextWriter writer, string name)
5454
{
55+
Dictionary<string, string> escapedNames = new Dictionary<string, string>();
56+
5557
writer.Write("{");
5658
writer.Write($"\"exporter\": \"{GetExporterInfo()}\", ");
57-
writer.Write($"\"name\": \"{name}\", ");
59+
writer.Write($"\"name\": \"{GetEscaped(name, escapedNames)}\", ");
5860
writer.Write("\"activeProfileIndex\": 0, ");
5961
writer.Write("\"$schema\": \"https://www.speedscope.app/file-format-schema.json\", ");
6062

6163
writer.Write("\"shared\": { \"frames\": [ ");
6264
for (int i = 0; i < orderedFrameNames.Count; i++)
6365
{
64-
writer.Write($"{{ \"name\": \"{orderedFrameNames[i].Replace("\\", "\\\\").Replace("\"", "\\\"")}\" }}");
66+
writer.Write($"{{ \"name\": \"{GetEscaped(orderedFrameNames[i], escapedNames)}\" }}");
6567

6668
if (i != orderedFrameNames.Count - 1)
6769
writer.Write(", ");
@@ -82,7 +84,7 @@ private static void WriteToFile(IReadOnlyDictionary<string, IReadOnlyList<Profil
8284

8385
writer.Write("{ ");
8486
writer.Write("\"type\": \"evented\", ");
85-
writer.Write($"\"name\": \"{perThread.Key}\", ");
87+
writer.Write($"\"name\": \"{GetEscaped(perThread.Key, escapedNames)}\", ");
8688
writer.Write("\"unit\": \"milliseconds\", ");
8789
writer.Write($"\"startValue\": {sortedProfileEvents.First().RelativeTime.ToString("R", CultureInfo.InvariantCulture)}, ");
8890
writer.Write($"\"endValue\": {sortedProfileEvents.Last().RelativeTime.ToString("R", CultureInfo.InvariantCulture)}, ");

src/TraceEvent/Stacks/StackSourceWriterHelper.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,25 @@ internal static string GetExporterInfo()
228228
return $"{traceEvent.Name}@{traceEvent.Version}"; // sth like "Microsoft.Diagnostics.Tracing.TraceEvent@2.0.56.0"
229229
}
230230

231+
internal static string GetEscaped(string name, Dictionary<string, string> escapedNames)
232+
{
233+
if (!escapedNames.TryGetValue(name, out string escaped))
234+
{
235+
#if NETSTANDARD1_6 || DEBUG // the Debug check allows us to test this code path for other TFMs
236+
// System.Web.HttpUtility.JavaScriptStringEncode is not part of the .NET Standard 1.6
237+
// but it's part of .NET 4.0+. So we just use reflection to invoke it.
238+
escaped = escapedNames[name] = (string)Type
239+
.GetType("System.Web.HttpUtility, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
240+
.GetMethod("JavaScriptStringEncode", new Type[1] { typeof(string) })
241+
.Invoke(null, new object[] { name });
242+
#elif NETSTANDARD2_0 || NET45
243+
escaped = escapedNames[name] = System.Web.HttpUtility.JavaScriptStringEncode(name);
244+
#endif
245+
}
246+
247+
return escaped;
248+
}
249+
231250
private static int CompareSamplesByTime(Sample x, Sample y)
232251
{
233252
int timeComparison = x.RelativeTime.CompareTo(y.RelativeTime);

src/TraceEvent/TraceEvent.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
6262
<Reference Include="System.IO.Compression" />
6363
<Reference Include="System.Net.Http" />
64+
<Reference Include="System.Web" />
6465
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" />
6566
</ItemGroup>
6667

0 commit comments

Comments
 (0)