pkg/dartpad/doc/worker-protocol.md
The bin/shared_worker.dart program is intended to run as a SharedWorker
in the browser. The client can communicate with the worker over the
MessagePort created when connecting to the SharedWorker. This document
describes the protocol for communication over this port.
In the description below the worker is bin/shared_worker.dart and client
is the web page that connected to the SharedWorker.
Concepts:
Communication with the worker uses JSON-RPC 2.0. Communication over the MessagePort takes place using raw JSON objects (utilizing the browser's structured clone algorithm), not JSON-encoded strings.
The following sections outline which methods are offered by the worker...
JSON-RPC 2.0 requests are usually on the form:
{
"jsonrpc": "2.0",
"method": "<name-of-method>",
"params": {
// parameters for the method
},
"id": 42 // unique ID per request, omitted for notifications!
}
If the id property is omitted, then the message is said to be a notification
and no response will be sent. For requests the id must be unique and must
be used by the client to find the matching response for the request.
Response objects are usually on the form:
{
"jsonrpc": "2.0",
"result": {
// result values from the method
},
"id": 42 // ID from the request
}
If an error occured when handling a request, then an error will be returned.
Errors will never be returned for notifications, since notifications don't
carry an id property, they never produce a response or an error.
Errors are usually on the form:
{
"jsonrpc": "2.0",
"error": {
"code": 1000, // Integer error code (negative numbers are reserved)
"message": "<human readable message>",
"data": {
// Arbitrary data associated from the error handler.
}
},
"id": 42 // ID from the request
}
When sending requests and notifications is possible to batch multiple messages into a single message by sending an array of requests and notifications.
For further details about JSON-RPC 2.0, refer to the specification.
Methods are prefixed based on what objects they operate on. Thus, all methods
prefixed workspace/ require a workspaceId parameter.
| Method Prefix | Required identifiers |
|---|---|
workspace/ | workspaceId |
workspace/languageServer/ | workspaceId and languageServerId |
workspace/hotReloadCompiler/ | workspaceId and hotReloadCompilerId |
createWorkspaceCreates workspace with a dedicated workspaceFolder.
Params:
{} // No parameters!
Result:
{
// The workspaceId is a unique number identifying the workspace created
"workspaceId": 42,
// Folder on the shared file-system dedicated to this workspace
"workspaceFolder": "file:///workspace/pad_42/",
}
workspace/disposeDeletes the workspace and all associated resources.
Params:
{
"workspaceId": 42,
}
Result:
{} // empty result
workspace/writeFileFromTextWrite a text string to a file as UTF-8.
Parent directories will be automatically created.
Params:
{
"workspaceId": 42,
// URI of the file that you want to write.
// Can be absolute file:// or relative to workspaceFolder
"uri": "bin/hello.dart",
// Text that should be written to the file.
// This will be written as UTF-8.
"text": "void main() => print('hello world');",
}
Result:
{} // empty result
workspace/writeFileFromBytesParams:
{
"workspaceId": 42,
"uri": "bin/hello.dart",
// Bytes that should be written to the file as base64
"base64": "<base64-encoded bytes>",
}
Result:
{} // empty result
workspace/readFileAsTextParams:
{
"workspaceId": 42,
"uri": "bin/hello.dart",
}
Result:
{
"text": "<contents of the file as UTF-8>"
}
workspace/readFileAsBytesParams:
{
"workspaceId": 42,
"uri": "bin/hello.dart",
}
Result:
{
"base64": "<bytes from the file encoded as base64>"
}
workspace/deleteFileSystemEntityParams:
{
"workspaceId": 42,
// URI of the file or folder that you want to delete.
"uri": "bin/hello.dart",
}
Result:
{} // empty result
workspace/statGet information about a file or folder.
Params:
{
"workspaceId": 42,
"uri": "bin/hello.dart",
}
Result:
{
// Type of the entity: "file", "folder" or "other"
"type": "file" | "folder" | "other",
// Size in bytes (only for files)
"size": 1024
}
workspace/createFolderParams:
{
"workspaceId": 42,
"uri": "lib",
}
Result:
{} // empty result
workspace/listDirectoryParams:
{
"workspaceId": 42,
"uri": "lib",
// Whether to list recursively (default: false)
"recursive": true,
// Whether to ignore hidden files (starting with .) (default: false)
"ignoreHidden": true
}
Result:
{
// List of entries. Paths are relative to the uri listed.
"entries": [
{"path": "main.dart", "type": "file"},
{"path": "src", "type": "folder"}
]
}
workspace/importTarArchiveImport a tar archive (uncompressed) into the workspace.
Params:
{
"workspaceId": 42,
// Path where to extract the archive.
"uri": ".",
// Base64 encoded tar archive.
"base64": "<base64-encoded-tar>"
}
Result:
{} // empty result
workspace/exportTarArchiveExport a directory as a tar archive (uncompressed).
Params:
{
"workspaceId": 42,
// Directory to export.
"uri": "."
}
Result:
{
// Base64 encoded tar archive.
"base64": "<base64-encoded-tar>"
}
workspace/pubRuns pub in the specified directory.
Params:
{
"workspaceId": 42,
// Directory to run pub in.
"uri": ".",
// Command to run.
"command": "get" | "add" | "downgrade" | "outdated" | "upgrade" | "remove" | "unpack",
// Arguments to pass to the pub command (optional)
"args": ["--dry-run"]
}
Result:
{
"log": "<output from pub get>",
}
workspace/startHotReloadCompilerStart a hot-reload compiler for uri.
Params:
{
"workspaceId": 42,
"uri": "bin/hello.dart",
}
Result:
{
// identifier for the hot-reload compiler just started
"hotReloadCompilerId": 67,
}
workspace/hotReloadCompiler/compileRun the hot-reload compiler for the uri it was started with.
Returns code and compiledLibraryUris, which must be supplied to the
hot-reload method as librariesToReload when hot-reloading.
Params:
{
"workspaceId": 42,
"hotReloadCompilerId": 67,
}
Result:
{
// Code is `null` if compilation failed!
"code": "<javascript code>" || null,
"compiledLibraryUris": ["package:myapp/myapp.dart", ...],
"log": "<log lines>",
}
workspace/hotReloadCompiler/closeClose the hot-reload compiler, releasing resources (memory) held.
Params:
{
"workspaceId": 42,
"hotReloadCompilerId": 67,
}
Result:
{} // empty result
workspace/startLanguageServerStart a language-server.
Params:
{
"workspaceId": 42,
}
Result:
{
"languageServerId": 36, // identifier for the language-server just started
}
workspace/languageServer/messageSends an LSP message to a running language server.
Params:
{
"workspaceId": 42,
"languageServerId": 36,
"message": {
// JSON-RPC 2.0 message for the language-server
"jsonrpc": "2.0",
"method": "...",
"params": {...},
"id": ...,
},
}
Result:
{} // empty result
workspace/languageServer/stopParams:
{
"workspaceId": 42,
"languageServerId": 36,
}
Result:
{} // empty result
workspace/languageServer/messageSent by the worker when the language server produces a message.
Params:
{
"workspaceId": 42,
"languageServerId": 36,
"message": {
// JSON-RPC 2.0 message from the language-server
}
}
workspace/languageServer/exitedSent by the worker when a language server process terminates.
Params:
{
"workspaceId": 42,
"languageServerId": 36
}
Errors returned by the worker use the following codes.
<!-- BEGIN GENERATED ERROR CODE TABLE -->| Code | Name | Description |
|---|---|---|
| 2001 | workspaceNotFound | The provided workspaceId does not exist. |
| 4001 | fileNotFound | The requested file or directory does not exist. |
| 4002 | fileWriteConflict | Could not write file (e.g. parent is a file). |
| 4003 | fileDeletionFailed | Could not delete the requested entity. |
| 5001 | languageServerNotFound | The languageServerId does not exist in this workspace. |
| 6001 | compilationFailed | Failed to compile code, usually due to an issue in the code being compiled. |
| 6020 | packageConfigNotFound | Unable to find .dart_tool/package_config.json in any parent directory. |
| 6100 | hotReloadCompilerNotFound | The hotReloadCompilerId does not exist in this workspace. |
| 6101 | hotReloadRejected | The hot reload request was rejected by the compiler. |
| 7001 | pubCommandFailed | The pub command failed to execute successfully. |
| 7064 | pubUsage | The command was used incorrectly. |
| 7065 | pubData | The input data was incorrect. |
| 7066 | pubNoInput | An input file did not exist or was unreadable. |
| 7067 | pubNoUser | The user specified did not exist. |
| 7068 | pubNoHost | The host specified did not exist. |
| 7069 | pubUnavailable | A service is unavailable. |
| 7070 | pubSoftware | An internal software error has been detected. |
| 7071 | pubOs | An operating system error has been detected. |
| 7072 | pubOsFile | Some system file did not exist or was unreadable. |
| 7073 | pubCantCreate | A user-specified output file cannot be created. |
| 7074 | pubIo | An error occurred while doing I/O on some file. |
| 7075 | pubTempFail | Temporary failure, indicating something that is not really an error. |
| 7076 | pubProtocol | The remote system returned something invalid during a protocol exchange. |
| 7077 | pubNoPerm | The user did not have sufficient permissions. |
| 7078 | pubConfig | Something was unconfigured or mis-configured. |
| 8001 | moduleLoaderNotAvailable | The DDC module loader is has not been loaded into the sandbox. |
| 8002 | flutterLoaderNotAvailable | The flutter loader has not been loaded into the sandbox. |
| 8100 | moduleLoadingFailed | Failed to load module into the sandbox. |
| 8200 | executionFailed | Error happened when running main() from user-code. |
| 8300 | hotRestartFailed | Hot-restart failed. |
| 8400 | hotReloadFailed | Hot-reload failed. |