@vscode/sync-api-service
Version:
A sync implementation of the VS Code API. Only supported from a worker in NodeJS and browser
247 lines (246 loc) • 10.4 kB
JavaScript
;
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApiService = void 0;
const vscode = __importStar(require("vscode"));
const sync_api_common_1 = require("@vscode/sync-api-common");
class ApiService {
constructor(_id, receiver, options) {
this.connection = receiver;
this.byteSources = new Map();
this.byteSinks = new Map();
this.options = options;
const console = new ConsoleTerminal();
this.stdio = {
stdin: console.fileDescriptor,
stdout: console.fileDescriptor,
stderr: console.fileDescriptor
};
this.registerCharacterDeviceDriver(console, false);
const handleError = (error) => {
if (error instanceof vscode.FileSystemError) {
return { errno: this.asFileSystemError(error) };
}
return { errno: sync_api_common_1.RPCErrno.UnknownError };
};
this.connection.onRequest('timer/sleep', async (params) => {
await new Promise((resolve) => {
(0, sync_api_common_1.RAL)().timer.setTimeout(resolve, params.ms);
});
return { errno: 0 };
});
this.connection.onRequest('byteSource/read', async (params) => {
const uri = vscode.Uri.from(params.uri);
const source = this.byteSources.get(uri.toString(true));
if (source === undefined) {
return { errno: sync_api_common_1.RPCErrno.NoHandlerFound };
}
const contents = await source.read(params.maxBytesToRead);
return { errno: 0, data: contents };
});
this.connection.onRequest('byteSink/write', async (params) => {
const uri = vscode.Uri.from(params.uri);
const sink = this.byteSinks.get(uri.toString(true));
if (sink === undefined) {
return { errno: sync_api_common_1.RPCErrno.NoHandlerFound };
}
const bytesWritten = await sink.write(params.binary);
const result = new Uint32Array(1);
result[0] = bytesWritten;
return { errno: 0, data: result };
});
this.connection.onRequest('fileSystem/stat', async (params, resultBuffer) => {
try {
const uri = vscode.Uri.from(params.uri);
const vStat = await vscode.workspace.fs.stat(uri);
const stat = sync_api_common_1.DTOs.Stat.create(resultBuffer);
stat.type = vStat.type;
stat.ctime = vStat.mtime;
stat.mtime = vStat.mtime;
stat.size = vStat.size;
if (vStat.permissions !== undefined) {
stat.permission = vStat.permissions;
}
return { errno: 0 };
}
catch (error) {
return handleError(error);
}
});
this.connection.onRequest('fileSystem/readFile', async (params) => {
try {
const uri = vscode.Uri.from(params.uri);
const contents = await vscode.workspace.fs.readFile(uri);
return { errno: 0, data: contents };
}
catch (error) {
return handleError(error);
}
});
this.connection.onRequest('fileSystem/writeFile', async (params) => {
try {
const uri = vscode.Uri.from(params.uri);
await vscode.workspace.fs.writeFile(uri, params.binary);
return { errno: 0 };
}
catch (error) {
return handleError(error);
}
});
this.connection.onRequest('fileSystem/readDirectory', async (params) => {
try {
const uri = vscode.Uri.from(params.uri);
const entries = await vscode.workspace.fs.readDirectory(uri);
return { errno: 0, data: entries };
}
catch (error) {
return handleError(error);
}
});
this.connection.onRequest('fileSystem/createDirectory', async (params) => {
try {
const uri = vscode.Uri.from(params.uri);
await vscode.workspace.fs.createDirectory(uri);
return { errno: 0 };
}
catch (error) {
return handleError(error);
}
});
this.connection.onRequest('fileSystem/delete', async (params) => {
try {
const uri = vscode.Uri.from(params.uri);
await vscode.workspace.fs.delete(uri, params.options);
return { errno: 0 };
}
catch (error) {
return handleError(error);
}
});
this.connection.onRequest('fileSystem/rename', async (params) => {
try {
const source = vscode.Uri.from(params.source);
const target = vscode.Uri.from(params.target);
await vscode.workspace.fs.rename(source, target, params.options);
return { errno: 0 };
}
catch (error) {
return handleError(error);
}
});
this.connection.onRequest('workspace/workspaceFolders', () => {
const folders = vscode.workspace.workspaceFolders ?? [];
return { errno: 0, data: folders.map(folder => { return { uri: folder.uri.toJSON(), name: folder.name, index: folder.index }; }) };
});
this.connection.onRequest('process/proc_exit', (params) => {
if (this.options?.exitHandler !== undefined) {
this.options.exitHandler(params.rval);
}
return { errno: 0 };
});
}
registerCharacterDeviceDriver(deviceDriver, useAsDefaultStdio) {
if (useAsDefaultStdio === true) {
this.setStdio(deviceDriver.fileDescriptor, deviceDriver.fileDescriptor, deviceDriver.fileDescriptor);
}
this.byteSources.set(deviceDriver.uri.toString(true), deviceDriver);
this.byteSinks.set(deviceDriver.uri.toString(true), deviceDriver);
}
setStdio(stdin, stdout, stderr) {
if (stdin !== undefined) {
this.stdio.stdin = stdin;
}
if (stdout !== undefined) {
this.stdio.stdout = stdout;
}
if (stderr !== undefined) {
this.stdio.stderr = stderr;
}
}
registerByteSource(source) {
this.byteSources.set(source.uri.toString(true), source);
}
registerByteSink(sink) {
this.byteSinks.set(sink.uri.toString(true), sink);
}
signalReady() {
const p = {
stdio: {
stdin: this.asFileDescriptorDescription(this.stdio.stdin),
stdout: this.asFileDescriptorDescription(this.stdio.stdout),
stderr: this.asFileDescriptorDescription(this.stdio.stderr),
}
};
this.connection.signalReady(p);
}
asFileSystemError(error) {
switch (error.code) {
case 'FileNotFound':
return sync_api_common_1.DTOs.FileSystemError.FileNotFound;
case 'FileExists':
return sync_api_common_1.DTOs.FileSystemError.FileExists;
case 'FileNotADirectory':
return sync_api_common_1.DTOs.FileSystemError.FileNotADirectory;
case 'FileIsADirectory':
return sync_api_common_1.DTOs.FileSystemError.FileIsADirectory;
case 'NoPermissions':
return sync_api_common_1.DTOs.FileSystemError.NoPermissions;
case 'Unavailable':
return sync_api_common_1.DTOs.FileSystemError.Unavailable;
default:
return sync_api_common_1.RPCErrno.UnknownError;
}
}
asFileDescriptorDescription(fileDescriptor) {
switch (fileDescriptor.kind) {
case 'fileSystem':
return { kind: fileDescriptor.kind, uri: fileDescriptor.uri.toJSON(), path: fileDescriptor.path };
case 'terminal':
return { kind: fileDescriptor.kind, uri: fileDescriptor.uri.toJSON() };
case 'console':
return { kind: fileDescriptor.kind, uri: fileDescriptor.uri.toJSON() };
}
}
}
exports.ApiService = ApiService;
class ConsoleTerminal {
constructor() {
this.decoder = (0, sync_api_common_1.RAL)().TextDecoder.create();
this.uri = vscode.Uri.from({ scheme: 'console', authority: ConsoleTerminal.authority });
this.fileDescriptor = { kind: 'console', uri: this.uri };
}
read() {
throw vscode.FileSystemError.Unavailable(`Can't read from console`);
}
write(bytes) {
(0, sync_api_common_1.RAL)().console.log(this.decoder.decode(bytes.slice()));
return Promise.resolve(bytes.byteLength);
}
}
ConsoleTerminal.authority = 'global';