UNPKG

@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
"use strict"; /* -------------------------------------------------------------------------------------------- * 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';