Back to Dart Lang

DartPad Worker Protocol

pkg/dartpad/doc/worker-protocol.md

3.13.0-152.0.dev11.7 KB
Original Source

DartPad Worker Protocol

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:

  • Session, when a client connects to the worker, a session is created. Sessions do share the same file-system and thread. But are otherwise independent, and should be using differnet parts of the virtual file-system.
  • Workspace, a workspace is a folder and associated resources for running language-servers and compiling source code.
  • Language-server, a process running within a workspace that provides a language-server-protocol server for Dart.
  • Hot-reload compiler, a process running with a workspace that faciliates incremental compilation of a single entry-point.

JSON-RPC 2.0

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:

js
{
  "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:

js
{
  "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:

js
{
  "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.

Server Methods and Notifications

Methods are prefixed based on what objects they operate on. Thus, all methods prefixed workspace/ require a workspaceId parameter.

Method PrefixRequired identifiers
workspace/workspaceId
workspace/languageServer/workspaceId and languageServerId
workspace/hotReloadCompiler/workspaceId and hotReloadCompilerId

Method createWorkspace

Creates workspace with a dedicated workspaceFolder.

Params:

js
{} // No parameters!

Result:

js
{
  // 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/",
}

Method workspace/dispose

Deletes the workspace and all associated resources.

Params:

js
{
  "workspaceId": 42,
}

Result:

js
{} // empty result

Method workspace/writeFileFromText

Write a text string to a file as UTF-8. Parent directories will be automatically created.

Params:

js
{
  "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:

js
{} // empty result

Method workspace/writeFileFromBytes

Params:

js
{
  "workspaceId": 42,
  "uri": "bin/hello.dart",
  // Bytes that should be written to the file as base64
  "base64": "<base64-encoded bytes>",
}

Result:

js
{} // empty result

Method workspace/readFileAsText

Params:

js
{
  "workspaceId": 42,
  "uri": "bin/hello.dart",
}

Result:

js
{
  "text": "<contents of the file as UTF-8>"
}

Method workspace/readFileAsBytes

Params:

js
{
  "workspaceId": 42,
  "uri": "bin/hello.dart",
}

Result:

js
{
  "base64": "<bytes from the file encoded as base64>"
}

Method workspace/deleteFileSystemEntity

Params:

js
{
  "workspaceId": 42,
  // URI of the file or folder that you want to delete.
  "uri": "bin/hello.dart",
}

Result:

js
{} // empty result

Method workspace/stat

Get information about a file or folder.

Params:

js
{
  "workspaceId": 42,
  "uri": "bin/hello.dart",
}

Result:

js
{
  // Type of the entity: "file", "folder" or "other"
  "type": "file" | "folder" | "other",
  // Size in bytes (only for files)
  "size": 1024
}

Method workspace/createFolder

Params:

js
{
  "workspaceId": 42,
  "uri": "lib",
}

Result:

js
{} // empty result

Method workspace/listDirectory

Params:

js
{
  "workspaceId": 42,
  "uri": "lib",
  // Whether to list recursively (default: false)
  "recursive": true,
  // Whether to ignore hidden files (starting with .) (default: false)
  "ignoreHidden": true
}

Result:

js
{
  // List of entries. Paths are relative to the uri listed.
  "entries": [
    {"path": "main.dart", "type": "file"},
    {"path": "src", "type": "folder"}
  ]
}

Method workspace/importTarArchive

Import a tar archive (uncompressed) into the workspace.

Params:

js
{
  "workspaceId": 42,
  // Path where to extract the archive.
  "uri": ".",
  // Base64 encoded tar archive.
  "base64": "<base64-encoded-tar>"
}

Result:

js
{} // empty result

Method workspace/exportTarArchive

Export a directory as a tar archive (uncompressed).

Params:

js
{
  "workspaceId": 42,
  // Directory to export.
  "uri": "."
}

Result:

js
{
  // Base64 encoded tar archive.
  "base64": "<base64-encoded-tar>"
}

Method workspace/pub

Runs pub in the specified directory.

Params:

js
{
  "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:

js
{
  "log": "<output from pub get>",
}

Method workspace/startHotReloadCompiler

Start a hot-reload compiler for uri.

Params:

js
{
  "workspaceId": 42,
  "uri": "bin/hello.dart",
}

Result:

js
{
  // identifier for the hot-reload compiler just started
  "hotReloadCompilerId": 67,
}

Method workspace/hotReloadCompiler/compile

Run 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:

js
{
  "workspaceId": 42,
  "hotReloadCompilerId": 67,
}

Result:

js
{
  // Code is `null` if compilation failed!
  "code": "<javascript code>" || null,
  "compiledLibraryUris": ["package:myapp/myapp.dart", ...],
  "log": "<log lines>",
}

Method workspace/hotReloadCompiler/close

Close the hot-reload compiler, releasing resources (memory) held.

Params:

js
{
  "workspaceId": 42,
  "hotReloadCompilerId": 67,
}

Result:

js
{} // empty result

Method workspace/startLanguageServer

Start a language-server.

Params:

js
{
  "workspaceId": 42,
}

Result:

js
{
  "languageServerId": 36, // identifier for the language-server just started
}

Method workspace/languageServer/message

Sends an LSP message to a running language server.

Params:

js
{
  "workspaceId": 42,
  "languageServerId": 36,
  "message": {
    // JSON-RPC 2.0 message for the language-server
    "jsonrpc": "2.0",
    "method": "...",
    "params": {...},
    "id": ...,
  },
}

Result:

js
{} // empty result

Method workspace/languageServer/stop

Params:

js
{
  "workspaceId": 42,
  "languageServerId": 36,
}

Result:

js
{} // empty result

Client Notifications

Notification workspace/languageServer/message

Sent by the worker when the language server produces a message.

Params:

js
{
  "workspaceId": 42,
  "languageServerId": 36,
  "message": {
    // JSON-RPC 2.0 message from the language-server
  }
}

Notification workspace/languageServer/exited

Sent by the worker when a language server process terminates.

Params:

js
{
  "workspaceId": 42,
  "languageServerId": 36
}

Error codes

Errors returned by the worker use the following codes.

<!-- BEGIN GENERATED ERROR CODE TABLE -->
CodeNameDescription
2001workspaceNotFoundThe provided workspaceId does not exist.
4001fileNotFoundThe requested file or directory does not exist.
4002fileWriteConflictCould not write file (e.g. parent is a file).
4003fileDeletionFailedCould not delete the requested entity.
5001languageServerNotFoundThe languageServerId does not exist in this workspace.
6001compilationFailedFailed to compile code, usually due to an issue in the code being compiled.
6020packageConfigNotFoundUnable to find .dart_tool/package_config.json in any parent directory.
6100hotReloadCompilerNotFoundThe hotReloadCompilerId does not exist in this workspace.
6101hotReloadRejectedThe hot reload request was rejected by the compiler.
7001pubCommandFailedThe pub command failed to execute successfully.
7064pubUsageThe command was used incorrectly.
7065pubDataThe input data was incorrect.
7066pubNoInputAn input file did not exist or was unreadable.
7067pubNoUserThe user specified did not exist.
7068pubNoHostThe host specified did not exist.
7069pubUnavailableA service is unavailable.
7070pubSoftwareAn internal software error has been detected.
7071pubOsAn operating system error has been detected.
7072pubOsFileSome system file did not exist or was unreadable.
7073pubCantCreateA user-specified output file cannot be created.
7074pubIoAn error occurred while doing I/O on some file.
7075pubTempFailTemporary failure, indicating something that is not really an error.
7076pubProtocolThe remote system returned something invalid during a protocol exchange.
7077pubNoPermThe user did not have sufficient permissions.
7078pubConfigSomething was unconfigured or mis-configured.
8001moduleLoaderNotAvailableThe DDC module loader is has not been loaded into the sandbox.
8002flutterLoaderNotAvailableThe flutter loader has not been loaded into the sandbox.
8100moduleLoadingFailedFailed to load module into the sandbox.
8200executionFailedError happened when running main() from user-code.
8300hotRestartFailedHot-restart failed.
8400hotReloadFailedHot-reload failed.
<!-- END GENERATED ERROR CODE TABLE -->