UNPKG

hakojs

Version:

A secure, embeddable JavaScript engine that runs untrusted code inside WebAssembly sandboxes with fine-grained permissions and resource limits

166 lines (164 loc) 5.04 kB
// src/mem/memory.ts class MemoryManager { exports = null; encoder = new TextEncoder; decoder = new TextDecoder; setExports(exports) { this.exports = exports; } checkExports() { if (!this.exports) { throw new Error("Exports not set on MemoryManager"); } return this.exports; } allocateMemory(ctx, size) { if (size <= 0) { throw new Error("Size must be greater than 0"); } const exports = this.checkExports(); const ptr = exports.HAKO_Malloc(ctx, size); if (ptr === 0) { throw new Error(`Failed to allocate ${size} bytes of memory`); } return ptr; } allocateRuntimeMemory(rt, size) { if (size <= 0) { throw new Error("Size must be greater than 0"); } const exports = this.checkExports(); const ptr = exports.HAKO_RuntimeMalloc(rt, size); if (ptr === 0) { throw new Error(`Failed to allocate ${size} bytes of memory`); } return ptr; } freeMemory(ctx, ptr) { if (ptr !== 0) { const exports = this.checkExports(); exports.HAKO_Free(ctx, ptr); } } freeRuntimeMemory(rt, ptr) { if (ptr !== 0) { const exports = this.checkExports(); exports.HAKO_RuntimeFree(rt, ptr); } } writeBytes(ctx, bytes) { const exports = this.checkExports(); const ptr = this.allocateMemory(ctx, bytes.byteLength); const memory = new Uint8Array(exports.memory.buffer); memory.set(bytes.subarray(0, bytes.byteLength), ptr); return ptr; } allocateString(ctx, str) { const exports = this.checkExports(); const bytes = this.encoder.encode(str); const ptr = this.allocateMemory(ctx, bytes.byteLength + 1); const memory = new Uint8Array(exports.memory.buffer); memory.set(bytes, ptr); memory[ptr + bytes.length] = 0; return ptr; } copy(offset, length) { const exports = this.checkExports(); const memory = new Uint8Array(exports.memory.buffer); return memory.slice(offset, offset + length); } slice(offset, length) { const exports = this.checkExports(); const memory = new Uint8Array(exports.memory.buffer); return memory.subarray(offset, offset + length); } writeNullTerminatedString(ctx, str) { const exports = this.checkExports(); const bytes = this.encoder.encode(str); const ptr = this.allocateMemory(ctx, bytes.byteLength + 1); const memory = new Uint8Array(exports.memory.buffer); memory.set(bytes, ptr); memory[ptr + bytes.length] = 0; return { pointer: ptr, length: bytes.length + 1 }; } readString(ptr) { if (ptr === 0) return ""; const exports = this.checkExports(); const memory = new Uint8Array(exports.memory.buffer); let end = ptr; while (memory[end] !== 0) end++; return this.decoder.decode(memory.subarray(ptr, end)); } freeCString(ctx, ptr) { if (ptr !== 0) { const exports = this.checkExports(); exports.HAKO_FreeCString(ctx, ptr); } } freeValuePointer(ctx, ptr) { if (ptr !== 0) { const exports = this.checkExports(); exports.HAKO_FreeValuePointer(ctx, ptr); } } freeValuePointerRuntime(rt, ptr) { if (ptr !== 0) { const exports = this.checkExports(); exports.HAKO_FreeValuePointerRuntime(rt, ptr); } } dupValuePointer(ctx, ptr) { const exports = this.checkExports(); return exports.HAKO_DupValuePointer(ctx, ptr); } newArrayBuffer(ctx, data) { const exports = this.checkExports(); if (data.byteLength === 0) { return exports.HAKO_NewArrayBuffer(ctx, 0, 0); } const bufPtr = this.allocateMemory(ctx, data.byteLength); const memory = new Uint8Array(exports.memory.buffer); memory.set(data, bufPtr); return exports.HAKO_NewArrayBuffer(ctx, bufPtr, data.byteLength); } allocatePointerArray(ctx, count) { return this.allocateMemory(ctx, count * 4); } allocateRuntimePointerArray(rt, count) { return this.allocateRuntimeMemory(rt, count * 4); } writePointerToArray(arrayPtr, index, value) { const exports = this.checkExports(); const view = new DataView(exports.memory.buffer); const ptr = arrayPtr + index * 4; view.setUint32(ptr, value, true); return ptr; } readPointerFromArray(arrayPtr, index) { const exports = this.checkExports(); const view = new DataView(exports.memory.buffer); return view.getUint32(arrayPtr + index * 4, true); } readPointer(address) { const exports = this.checkExports(); const view = new DataView(exports.memory.buffer); return view.getUint32(address, true); } readUint32(address) { const exports = this.checkExports(); const view = new DataView(exports.memory.buffer); return view.getUint32(address, true); } writeUint32(address, value) { const exports = this.checkExports(); const view = new DataView(exports.memory.buffer); view.setUint32(address, value, true); } } export { MemoryManager }; //# debugId=BC1EDCC960093E7464756E2164756E21 //# sourceMappingURL=memory.js.map