@dprint/formatter
Version:
Wasm formatter for dprint plugins.
222 lines (221 loc) • 9.12 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFromInstance = exports.createHost = void 0;
const decoder = new TextDecoder();
const encoder = new TextEncoder();
/**
* Creates host for host formatting.
*/
function createHost() {
let instance;
let hostFormatter = undefined;
let overrideConfig = {};
let filePath = "";
let formattedText = "";
let errorText = "";
return {
setInstance(wasmInstance) {
instance = wasmInstance;
},
setHostFormatter(formatWithHost) {
hostFormatter = formatWithHost;
},
createImportObject() {
let sharedBuffer = new Uint8Array(0);
let sharedBufferIndex = 0;
const resetSharedBuffer = (length) => {
sharedBuffer = new Uint8Array(length);
sharedBufferIndex = 0;
};
return {
dprint: {
"host_clear_bytes": (length) => {
resetSharedBuffer(length);
},
"host_read_buffer": (pointer, length) => {
sharedBuffer.set(getWasmBufferAtPointer(instance, pointer, length), sharedBufferIndex);
sharedBufferIndex += length;
},
"host_write_buffer": (pointer, index, length) => {
getWasmBufferAtPointer(instance, pointer, length).set(sharedBuffer.slice(index, index + length));
},
"host_take_file_path": () => {
filePath = decoder.decode(sharedBuffer);
resetSharedBuffer(0);
},
"host_take_override_config": () => {
overrideConfig = JSON.parse(decoder.decode(sharedBuffer));
resetSharedBuffer(0);
},
"host_format": () => {
const fileText = decoder.decode(sharedBuffer);
try {
formattedText = hostFormatter?.({
filePath,
fileText,
overrideConfig,
}) ?? fileText;
return fileText === formattedText ? 0 : 1;
}
catch (error) {
errorText = String(error);
return 2;
}
},
"host_get_formatted_text": () => {
sharedBuffer = encoder.encode(formattedText);
sharedBufferIndex = 0;
return sharedBuffer.length;
},
"host_get_error_text": () => {
sharedBuffer = encoder.encode(errorText);
sharedBufferIndex = 0;
return sharedBuffer.length;
},
},
};
},
};
}
exports.createHost = createHost;
function createFromInstance(wasmInstance, host) {
host.setInstance(wasmInstance);
// deno-lint-ignore no-explicit-any
const wasmExports = wasmInstance.exports;
const { get_plugin_schema_version, set_file_path, set_override_config, get_formatted_text, format, get_error_text, get_plugin_info, get_resolved_config, get_config_diagnostics, set_global_config, set_plugin_config, get_license_text, reset_config, } = wasmExports;
const pluginSchemaVersion = get_plugin_schema_version();
const expectedPluginSchemaVersion = 3;
if (pluginSchemaVersion !== 2
&& pluginSchemaVersion !== expectedPluginSchemaVersion) {
throw new Error(`Not compatible plugin. `
+ `Expected schema ${expectedPluginSchemaVersion}, `
+ `but plugin had ${pluginSchemaVersion}.`);
}
let configSet = false;
return {
setConfig(globalConfig, pluginConfig) {
setConfig(globalConfig, pluginConfig);
},
getConfigDiagnostics() {
setConfigIfNotSet();
const length = get_config_diagnostics();
return JSON.parse(receiveString(wasmInstance, length));
},
getResolvedConfig() {
setConfigIfNotSet();
const length = get_resolved_config();
return JSON.parse(receiveString(wasmInstance, length));
},
getFileMatchingInfo() {
const length = get_plugin_info();
const pluginInfo = JSON.parse(receiveString(wasmInstance, length));
return {
// deno-lint-ignore no-explicit-any
fileExtensions: pluginInfo.fileExtensions ?? [],
// deno-lint-ignore no-explicit-any
fileNames: pluginInfo.fileNames ?? [],
};
},
getPluginInfo() {
const length = get_plugin_info();
const pluginInfo = JSON.parse(receiveString(wasmInstance, length));
// deno-lint-ignore no-explicit-any
delete pluginInfo.fileNames;
// deno-lint-ignore no-explicit-any
delete pluginInfo.fileExtensions;
return pluginInfo;
},
getLicenseText() {
const length = get_license_text();
return receiveString(wasmInstance, length);
},
formatText(request, formatWithHost) {
if (request.bytesRange != null) {
// not supported for v3
return request.fileText;
}
host.setHostFormatter(formatWithHost);
setConfigIfNotSet();
if (request.overrideConfig != null) {
if (pluginSchemaVersion === 2) {
throw new Error("Cannot set the override configuration for this old plugin.");
}
sendString(wasmInstance, JSON.stringify(request.overrideConfig));
set_override_config();
}
sendString(wasmInstance, request.filePath);
set_file_path();
sendString(wasmInstance, request.fileText);
const responseCode = format();
switch (responseCode) {
case 0: // no change
return request.fileText;
case 1: // change
return receiveString(wasmInstance, get_formatted_text());
case 2: // error
throw new Error(receiveString(wasmInstance, get_error_text()));
default:
throw new Error(`Unexpected response code: ${responseCode}`);
}
},
};
function setConfigIfNotSet() {
if (!configSet) {
setConfig({}, {});
}
}
function setConfig(globalConfig, pluginConfig) {
if (reset_config != null) {
reset_config();
}
sendString(wasmInstance, JSON.stringify(globalConfig));
set_global_config();
sendString(wasmInstance, JSON.stringify(pluginConfig));
set_plugin_config();
configSet = true;
}
}
exports.createFromInstance = createFromInstance;
function sendString(wasmInstance, text) {
// deno-lint-ignore no-explicit-any
const exports = wasmInstance.exports;
const encodedText = encoder.encode(text);
const length = encodedText.length;
const memoryBufferSize = exports.get_wasm_memory_buffer_size();
const memoryBufferPointer = getWasmMemoryBufferPointer(wasmInstance);
exports.clear_shared_bytes(length);
let index = 0;
while (index < length) {
const writeCount = Math.min(length - index, memoryBufferSize);
const wasmBuffer = getWasmBufferAtPointer(wasmInstance, memoryBufferPointer, writeCount);
wasmBuffer.set(encodedText.slice(index, index + writeCount));
exports.add_to_shared_bytes_from_buffer(writeCount);
index += writeCount;
}
return length;
}
function receiveString(wasmInstance, length) {
// deno-lint-ignore no-explicit-any
const exports = wasmInstance.exports;
const memoryBufferSize = exports.get_wasm_memory_buffer_size();
const memoryBufferPointer = getWasmMemoryBufferPointer(wasmInstance);
const buffer = new Uint8Array(length);
let index = 0;
while (index < length) {
const readCount = Math.min(length - index, memoryBufferSize);
exports.set_buffer_with_shared_bytes(index, readCount);
const wasmBuffer = getWasmBufferAtPointer(wasmInstance, memoryBufferPointer, readCount);
buffer.set(wasmBuffer, index);
index += readCount;
}
return decoder.decode(buffer);
}
function getWasmMemoryBufferPointer(wasmInstance) {
// deno-lint-ignore no-explicit-any
return wasmInstance.exports.get_wasm_memory_buffer();
}
function getWasmBufferAtPointer(wasmInstance, pointer, length) {
return new Uint8Array(
// deno-lint-ignore no-explicit-any
wasmInstance.exports.memory.buffer, pointer, length);
}