@dprint/formatter
Version:
Wasm formatter for dprint plugins.
227 lines (226 loc) • 9.5 kB
JavaScript
;
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);
}