taglib-wasm
Version:
TagLib for TypeScript platforms: Deno, Node.js, Bun, Electron, browsers, and Cloudflare Workers
116 lines (115 loc) • 3.98 kB
JavaScript
import { TagLibInitializationError } from "./errors.js";
const DEFAULT_WORKERS_CONFIG = {
memory: {
initial: 8 * 1024 * 1024,
// 8MB (reduced from 16MB)
maximum: 64 * 1024 * 1024
// 64MB (reduced from 256MB)
},
debug: false
};
function createModuleConfig(wasmBinary, config) {
const mergedConfig = { ...DEFAULT_WORKERS_CONFIG, ...config };
return {
wasmBinary,
wasmMemory: new WebAssembly.Memory({
initial: (mergedConfig.memory?.initial ?? 8 * 1024 * 1024) / (64 * 1024),
maximum: (mergedConfig.memory?.maximum ?? 64 * 1024 * 1024) / (64 * 1024)
}),
print: mergedConfig.debug ? console.log : () => {
},
printErr: mergedConfig.debug ? console.error : () => {
},
onRuntimeInitialized: () => {
if (mergedConfig.debug) {
console.log("taglib-wasm module initialized in Workers");
}
},
// Workers-specific settings
locateFile: () => "",
// Empty string since we're providing wasmBinary directly
noFSInit: true,
// Disable file system access
noExitRuntime: true
};
}
function setupMemoryArrays(wasmInstance) {
if (!wasmInstance.HEAPU8) {
const buffer = wasmInstance.buffer ?? wasmInstance.wasmMemory?.buffer;
if (buffer) {
wasmInstance.HEAPU8 = new Uint8Array(buffer);
wasmInstance.HEAP8 = new Int8Array(buffer);
wasmInstance.HEAP16 = new Int16Array(buffer);
wasmInstance.HEAP32 = new Int32Array(buffer);
wasmInstance.HEAPU16 = new Uint16Array(buffer);
wasmInstance.HEAPU32 = new Uint32Array(buffer);
wasmInstance.HEAPF32 = new Float32Array(buffer);
wasmInstance.HEAPF64 = new Float64Array(buffer);
}
}
}
async function loadTagLibModuleForWorkers(wasmBinary, config = {}) {
const moduleConfig = createModuleConfig(wasmBinary, config);
try {
const TagLibWasm = await createWorkersCompatibleModule();
if (typeof TagLibWasm !== "function") {
throw new TagLibInitializationError(
"Failed to load taglib-wasm module for Workers. The module may not be properly bundled for the Workers environment."
);
}
const wasmInstance = await TagLibWasm(moduleConfig);
setupMemoryArrays(wasmInstance);
return wasmInstance;
} catch (error) {
if (error instanceof TagLibInitializationError) {
throw error;
}
throw new TagLibInitializationError(
`Failed to load taglib-wasm for Workers: ${error.message}`,
{ error: error.message }
);
}
}
async function createWorkersCompatibleModule() {
try {
const wasmModule = await import("../taglib-wrapper.js");
return wasmModule.default ?? wasmModule;
} catch (error) {
throw new TagLibInitializationError(
`Workers-compatible Wasm module not available. Please build with Workers target or use a bundler that supports Wasm modules. Original error: ${error.message}`,
{ error: error.message }
);
}
}
function cStringToJS(module, ptr) {
if (ptr === 0) return "";
const view = new Uint8Array(module.HEAPU8.buffer, ptr);
let length = 0;
while (view[length] !== 0) length++;
return new TextDecoder().decode(view.subarray(0, length));
}
function jsToCString(module, str) {
const encoder = new TextEncoder();
const bytes = encoder.encode(str + "\0");
if (module.allocate && module.ALLOC_NORMAL !== void 0) {
return module.allocate(bytes, module.ALLOC_NORMAL);
} else {
const ptr = module._malloc(bytes.length);
try {
module.HEAPU8.set(bytes, ptr);
return ptr;
} catch (error) {
module._free(ptr);
throw error;
}
}
}
function isCloudflareWorkers() {
return typeof globalThis !== "undefined" && typeof globalThis.caches !== "undefined" && typeof globalThis.Request !== "undefined" && typeof globalThis.Response !== "undefined" && typeof globalThis.process === "undefined" && typeof globalThis.Deno === "undefined";
}
export {
cStringToJS,
isCloudflareWorkers,
jsToCString,
loadTagLibModuleForWorkers
};