blob: 2f6063f47454a06136739635410f0b865480c478 [file] [log] [blame]
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:developer" which contains all the imports
/// used by patches of that library. We plan to change this when we have a
/// shared front end and simply use parts.
import "dart:_internal" show patch;
import "dart:async" show Future, Zone;
import "dart:isolate" show SendPort;
/// These are the additional parts of this patch library:
part "profiler.dart";
part "timeline.dart";
@patch
@pragma("vm:recognized", "other")
@pragma("vm:external-name", "Developer_debugger")
external bool debugger({bool when = true, String? message});
@patch
@pragma("vm:external-name", "Developer_inspect")
external Object? inspect(Object? object);
@patch
void log(
String message, {
DateTime? time,
int? sequenceNumber,
int level = 0,
String name = '',
Zone? zone,
Object? error,
StackTrace? stackTrace,
}) {
if (message is! String) {
throw ArgumentError.value(message, "message", "Must be a String");
}
time ??= DateTime.now();
if (time is! DateTime) {
throw ArgumentError.value(time, "time", "Must be a DateTime");
}
if (sequenceNumber == null) {
sequenceNumber = _nextSequenceNumber++;
} else {
_nextSequenceNumber = sequenceNumber + 1;
}
_log(
message,
time.millisecondsSinceEpoch,
sequenceNumber,
level,
name,
zone,
error,
stackTrace,
);
}
@patch
@pragma("vm:external-name", "Developer_reachability_barrier")
external int get reachabilityBarrier;
int _nextSequenceNumber = 0;
@pragma("vm:external-name", "Developer_log")
external _log(
String message,
int timestamp,
int sequenceNumber,
int level,
String name,
Zone? zone,
Object? error,
StackTrace? stackTrace,
);
@patch
@pragma("vm:external-name", "Developer_postEvent")
external void _postEvent(String eventKind, String eventData);
@patch
@pragma("vm:external-name", "Developer_lookupExtension")
external ServiceExtensionHandler? _lookupExtension(String method);
@patch
@pragma("vm:external-name", "Developer_registerExtension")
external _registerExtension(String method, ServiceExtensionHandler handler);
// This code is only invoked when there is no other Dart code on the stack.
@pragma("vm:entry-point", !bool.fromEnvironment("dart.vm.product"))
_runExtension(
ServiceExtensionHandler handler,
String method,
List<String> parameterKeys,
List<String> parameterValues,
SendPort replyPort,
Object id,
bool trace_service,
) {
var parameters = <String, String>{};
for (var i = 0; i < parameterKeys.length; i++) {
parameters[parameterKeys[i]] = parameterValues[i];
}
var response;
try {
response = handler(method, parameters);
} catch (e, st) {
var errorDetails = (st == null) ? '$e' : '$e\n$st';
response = ServiceExtensionResponse.error(
ServiceExtensionResponse.extensionError,
errorDetails,
);
_postResponse(replyPort, id, response, trace_service);
return;
}
if (response is! Future) {
response = ServiceExtensionResponse.error(
ServiceExtensionResponse.extensionError,
"Extension handler must return a Future",
);
_postResponse(replyPort, id, response, trace_service);
return;
}
response
.catchError((e, st) {
// Catch any errors eagerly and wrap them in a ServiceExtensionResponse.
var errorDetails = (st == null) ? '$e' : '$e\n$st';
return ServiceExtensionResponse.error(
ServiceExtensionResponse.extensionError,
errorDetails,
);
})
.then((response) {
// Post the valid response or the wrapped error after verifying that
// the response is a ServiceExtensionResponse.
if (response is! ServiceExtensionResponse) {
response = ServiceExtensionResponse.error(
ServiceExtensionResponse.extensionError,
"Extension handler must complete to a ServiceExtensionResponse",
);
}
_postResponse(replyPort, id, response, trace_service);
})
.catchError((e, st) {
// We do not expect any errors to occur in the .then or .catchError blocks
// but, suppress them just in case.
});
}
// This code is only invoked by _runExtension.
_postResponse(
SendPort replyPort,
Object id,
ServiceExtensionResponse response,
bool trace_service,
) {
assert(replyPort != null);
if (id == null) {
if (trace_service) {
print("vm-service: posting no response for request");
}
// No id -> no response.
replyPort.send(null);
return;
}
assert(id != null);
StringBuffer sb = StringBuffer();
sb.write('{"jsonrpc":"2.0",');
if (response.isError()) {
if (trace_service) {
print("vm-service: posting error response for request $id");
}
sb.write('"error":');
} else {
if (trace_service) {
print("vm-service: posting response for request $id");
}
sb.write('"result":');
}
sb.write('${response._toString()},');
if (id is String) {
sb.write('"id":"$id"}');
} else {
sb.write('"id":$id}');
}
replyPort.send(sb.toString());
}
@patch
@pragma("vm:external-name", "Developer_getServiceMajorVersion")
external int _getServiceMajorVersion();
@patch
@pragma("vm:external-name", "Developer_getServiceMinorVersion")
external int _getServiceMinorVersion();
@patch
@pragma("vm:external-name", "Developer_getServerInfo")
external void _getServerInfo(SendPort sendPort);
@patch
@pragma("vm:external-name", "Developer_webServerControl")
external void _webServerControl(
SendPort sendPort,
bool enable,
bool? silenceOutput,
);
@patch
@pragma("vm:external-name", "Developer_getIsolateIdFromSendPort")
external String? _getIsolateIdFromSendPort(SendPort sendPort);
@patch
@pragma("vm:external-name", "Developer_getObjectId")
external String? _getObjectId(Object object);
@patch
abstract final class NativeRuntime {
@patch
@pragma("vm:external-name", "Developer_NativeRuntime_buildId")
external static String? get buildId;
@patch
@pragma("vm:external-name", "Developer_NativeRuntime_writeHeapSnapshotToFile")
external static void writeHeapSnapshotToFile(String filepath);
}