diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 1d7ed040c31..85ea5099915 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -5806,13 +5806,26 @@ static bool StreamTraceEvents(Dart_StreamConsumer consumer, char* output = NULL; intptr_t output_length = 0; js->Steal(const_cast(&output), &output_length); + if (output_length < 3) { + // Empty JSON array. + free(output); + return false; + } + // We want to send the JSON array without the leading '[' or trailing ']' + // characters. + ASSERT(output[0] == '['); + ASSERT(output[output_length - 1] == ']'); + // Replace the ']' with the null character. + output[output_length - 1] = '\0'; + // We are skipping the '['. + output_length -= 1; // Start the stream. StartStreamToConsumer(consumer, user_data, "timeline"); DataStreamToConsumer(consumer, user_data, - output, + &output[1], output_length, "timeline"); diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc index 501091ce930..b11ffb418aa 100644 --- a/runtime/vm/dart_api_impl_test.cc +++ b/runtime/vm/dart_api_impl_test.cc @@ -9562,6 +9562,12 @@ TEST_CASE(Timeline_Dart_TimelineGetTrace) { EXPECT(buffer_length > 0); EXPECT(buffer != NULL); + // Response starts with a '{' character and not a '['. + EXPECT(buffer[0] == '{'); + // Response ends with a '}' character and not a ']'. + EXPECT(buffer[buffer_length - 1] == '\0'); + EXPECT(buffer[buffer_length - 2] == '}'); + // Heartbeat test. EXPECT_SUBSTRING("\"cat\":\"Compiler\"", buffer); EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer); @@ -9609,6 +9615,12 @@ TEST_CASE(Timeline_Dart_TimelineGetTraceOnlyDartEvents) { EXPECT(buffer_length > 0); EXPECT(buffer != NULL); + // Response starts with a '{' character and not a '['. + EXPECT(buffer[0] == '{'); + // Response ends with a '}' character and not a ']'. + EXPECT(buffer[buffer_length - 1] == '\0'); + EXPECT(buffer[buffer_length - 2] == '}'); + // Heartbeat test. EXPECT_SUBSTRING("\"cat\":\"Dart\"", buffer); EXPECT_SUBSTRING("\"name\":\"DART_NAME\"", buffer); @@ -9654,6 +9666,12 @@ TEST_CASE(Timeline_Dart_TimelineGetTraceWithDartEvents) { EXPECT(buffer_length > 0); EXPECT(buffer != NULL); + // Response starts with a '{' character and not a '['. + EXPECT(buffer[0] == '{'); + // Response ends with a '}' character and not a ']'. + EXPECT(buffer[buffer_length - 1] == '\0'); + EXPECT(buffer[buffer_length - 2] == '}'); + // Heartbeat test. EXPECT_SUBSTRING("\"cat\":\"Compiler\"", buffer); EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer); @@ -9697,6 +9715,12 @@ TEST_CASE(Timeline_Dart_TimelineGetTraceGlobalOverride) { EXPECT(buffer_length > 0); EXPECT(buffer != NULL); + // Response starts with a '{' character and not a '['. + EXPECT(buffer[0] == '{'); + // Response ends with a '}' character and not a ']'. + EXPECT(buffer[buffer_length - 1] == '\0'); + EXPECT(buffer[buffer_length - 2] == '}'); + // Heartbeat test. EXPECT_SUBSTRING("\"cat\":\"Compiler\"", buffer); EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer); @@ -9745,6 +9769,12 @@ TEST_CASE(Timeline_Dart_GlobalTimelineGetTrace) { EXPECT(buffer_length > 0); EXPECT(buffer != NULL); + // Response starts with a '{' character and not a '['. + EXPECT(buffer[0] == '{'); + // Response ends with a '}' character and not a ']'. + EXPECT(buffer[buffer_length - 1] == '\0'); + EXPECT(buffer[buffer_length - 2] == '}'); + // Heartbeat test. EXPECT_SUBSTRING("\"name\":\"TestVMDuration\"", buffer); EXPECT_SUBSTRING("\"cat\":\"Compiler\"", buffer); @@ -9779,6 +9809,11 @@ TEST_CASE(Timeline_Dart_GlobalTimelineGetTrace) { buffer_length = data.buffer_length; EXPECT(buffer_length > 0); EXPECT(buffer != NULL); + // Response starts with a '{' character and not a '['. + EXPECT(buffer[0] == '{'); + // Response ends with a '}' character and not a ']'. + EXPECT(buffer[buffer_length - 1] == '\0'); + EXPECT(buffer[buffer_length - 2] == '}'); // Heartbeat test for old events. EXPECT_SUBSTRING("\"name\":\"TestVMDuration\"", buffer);