UNPKG

@dprint/formatter

Version:

Wasm formatter for dprint plugins.

227 lines (226 loc) 9.5 kB
"use strict"; 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.createFromInstance = exports.createHost = void 0; const dntShim = __importStar(require("./_dnt.shims.js")); const decoder = new TextDecoder(); const encoder = new TextEncoder(); /** * Creates host for host formatting. */ function createHost() { function writeStderr(buf) { try { // deno-lint-ignore no-explicit-any const global = dntShim.dntGlobalThis; if (global.Deno) { global.Deno.stderr.writeSync(buf); } else if (global.process) { global.process.stderr.writeSync(buf); } else { // ignore } } catch { // ignore } } let instance; let hostFormatter = undefined; let formattedText = ""; let errorText = ""; return { setInstance(wasmInstance) { instance = wasmInstance; }, setHostFormatter(formatWithHost) { hostFormatter = formatWithHost; }, createImportObject() { let sharedBuffer = new Uint8Array(0); return { env: { "fd_write": (fd, iovsPtr, iovsLen, nwrittenPtr) => { let totalWritten = 0; // deno-lint-ignore no-explicit-any const wasmMemoryBuffer = instance.exports.memory.buffer; const dataView = new DataView(wasmMemoryBuffer); for (let i = 0; i < iovsLen; i++) { const iovsOffset = iovsPtr + i * 8; const iovecBufPtr = dataView.getUint32(iovsOffset, true); const iovecBufLen = dataView.getUint32(iovsOffset + 4, true); const buf = new Uint8Array(wasmMemoryBuffer, iovecBufPtr, iovecBufLen); if (fd === 1 || fd === 2) { // just write both stdout and stderr to stderr writeStderr(buf); } else { return 1; // not supported fd } totalWritten += iovecBufLen; } dataView.setUint32(nwrittenPtr, totalWritten, true); return 0; // success }, }, dprint: { "host_has_cancelled": () => 0, "host_write_buffer": (pointer) => { getWasmBufferAtPointer(instance, pointer, sharedBuffer.length).set(sharedBuffer); }, "host_format": (filePathPtr, filePathLen, rangeStart, rangeEnd, overrideConfigPtr, overrideConfigLen, fileBytesPtr, fileBytesLen) => { const filePath = receiveString(filePathPtr, filePathLen); const overrideConfigRaw = receiveString(overrideConfigPtr, overrideConfigLen); const overrideConfig = overrideConfigRaw === "" ? {} : JSON.parse(overrideConfigRaw); const fileText = receiveString(fileBytesPtr, fileBytesLen); const bytesRange = rangeStart === 0 && rangeEnd === fileBytesLen ? undefined : [rangeStart, rangeEnd]; try { formattedText = hostFormatter?.({ filePath, fileText, bytesRange, overrideConfig, }) ?? fileText; return fileText === formattedText ? 0 : 1; } catch (error) { errorText = String(error); return 2; } }, "host_get_formatted_text": () => { sharedBuffer = encoder.encode(formattedText); return sharedBuffer.length; }, "host_get_error_text": () => { sharedBuffer = encoder.encode(errorText); return sharedBuffer.length; }, }, }; }, }; function receiveString(ptr, length) { return decoder.decode(getWasmBufferAtPointer(instance, ptr, length)); } } exports.createHost = createHost; function createFromInstance(wasmInstance, host) { host.setInstance(wasmInstance); // only a single config is supported in here atm const configId = 1; // deno-lint-ignore no-explicit-any const wasmExports = wasmInstance.exports; const { get_shared_bytes_ptr, set_file_path, set_override_config, clear_shared_bytes, get_formatted_text, format, format_range, get_error_text, get_plugin_info, get_config_file_matching, get_resolved_config, get_config_diagnostics, get_license_text, register_config, release_config, } = wasmExports; let configSet = false; return { setConfig(globalConfig, pluginConfig) { setConfig(globalConfig, pluginConfig); }, getConfigDiagnostics() { setConfigIfNotSet(); const length = get_config_diagnostics(configId); return JSON.parse(receiveString(length)); }, getResolvedConfig() { setConfigIfNotSet(); const length = get_resolved_config(configId); return JSON.parse(receiveString(length)); }, getFileMatchingInfo() { const length = get_config_file_matching(configId); return JSON.parse(receiveString(length)); }, getPluginInfo() { const length = get_plugin_info(); return JSON.parse(receiveString(length)); }, getLicenseText() { const length = get_license_text(); return receiveString(length); }, formatText(request, formatWithHost) { if (request.bytesRange != null && format_range == null) { // plugin doesn't support range formatting return request.fileText; } host.setHostFormatter(formatWithHost); setConfigIfNotSet(); if (request.overrideConfig != null) { sendString(JSON.stringify(request.overrideConfig)); set_override_config(); } sendString(request.filePath); set_file_path(); sendString(request.fileText); const responseCode = request.bytesRange != null ? format_range(configId, request.bytesRange[0], request.bytesRange[1]) : format(configId); switch (responseCode) { case 0: // no change return request.fileText; case 1: // change return receiveString(get_formatted_text()); case 2: // error throw new Error(receiveString(get_error_text())); default: throw new Error(`Unexpected response code: ${responseCode}`); } }, }; function setConfigIfNotSet() { if (!configSet) { setConfig({}, {}); } } function setConfig(globalConfig, pluginConfig) { release_config(configId); sendString(JSON.stringify({ global: globalConfig, plugin: pluginConfig, })); register_config(configId); configSet = true; } function sendString(value) { const bytes = encoder.encode(value); const ptr = clear_shared_bytes(bytes.length); getWasmBufferAtPointer(wasmInstance, ptr, bytes.length).set(bytes); } function receiveString(length) { const ptr = get_shared_bytes_ptr(); return decoder.decode(getWasmBufferAtPointer(wasmInstance, ptr, length)); } } exports.createFromInstance = createFromInstance; function getWasmBufferAtPointer(wasmInstance, pointer, length) { return new Uint8Array( // deno-lint-ignore no-explicit-any wasmInstance.exports.memory.buffer, pointer, length); }