UNPKG

rc-js-util

Version:

A collection of TS and C++ utilities to help writing performant and correct applications, achieved through strict typing and (removable) invariant checking.

134 lines 5.25 kB
import { __awaiter } from "tslib"; import { shimWebAssemblyMemory } from "../util/shim-web-assembly-memory.js"; import { BroadcastChannel } from "../../eventing/broadcast-channel.js"; import { _Debug } from "../../debug/_debug.js"; import { DebugWeakBroadcastChannel } from "../../debug/debug-weak-broadcast-event.js"; import { DebugSharedObjectLifeCycleChecker } from "../../debug/debug-shared-object-life-cycle-checker.js"; import { DebugWeakStore } from "../../debug/debug-weak-store.js"; import { StableIdStore } from "../../runtime/rtti-interop.js"; /** * @public * Factory for creating wrapped emscripten module. */ export function getEmscriptenWrapper(memory_1, emscriptenModuleFactory_1, lifecycleStrategy_1, options_1) { return __awaiter(this, arguments, void 0, function* (memory, emscriptenModuleFactory, lifecycleStrategy, options, extension = {}) { let debugLabel = undefined; try { if (_BUILD.DEBUG) { debugLabel = _Debug.label; _Debug.label = "EmscriptenWrapper"; } const memoryListener = _BUILD.DEBUG ? new DebugWeakBroadcastChannel("onMemoryResize") : new BroadcastChannel("onMemoryResize"); const debug = new EmscriptenDebug(); const binder = new EmscriptenBinder(); if (_BUILD.DEBUG) { const debugInstance = extension; debugInstance.JSU_DEBUG_UTIL = debug; } const instance = yield emscriptenModuleFactory(Object.assign({ wasmMemory: memory, INITIAL_MEMORY: memory.buffer.byteLength, JSU_BINDER: binder }, extension)); const wrapper = new EmscriptenWrapper(memoryListener, instance, memory, debug, binder, lifecycleStrategy, options); lifecycleStrategy.setWrapper(wrapper); // this depends on the lifecycle strategy having being initialized... wrapper.interopIds.initialize(); initializeSubmodules(instance); return wrapper; } finally { if (_BUILD.DEBUG) { _Debug.label = debugLabel; } } }); } /** * @public */ export class EmscriptenWrapperOptions { constructor(initializeCallbacks) { this.initializeCallbacks = initializeCallbacks; } extend(options) { return new EmscriptenWrapperOptions(this.initializeCallbacks.concat(options.initializeCallbacks)); } } class EmscriptenWrapper { constructor(memoryResize, instance, memory, debugUtils, binder, lifecycleStrategy, options, rootNode = lifecycleStrategy.createRootNode()) { this.memoryResize = memoryResize; this.instance = instance; this.memory = memory; this.debugUtils = debugUtils; this.binder = binder; this.lifecycleStrategy = lifecycleStrategy; this.rootNode = rootNode; this.interopIds = new StableIdStore(this); const state = this.state = new EWState(new DataView(memory.buffer)); // in debug builds there are retainers on the wasm memory from libraries, sidestep by passing sub-object // don't reference `this` here... shimWebAssemblyMemory(memory, (buffer, previous, delta) => { _BUILD.DEBUG && _Debug.verboseLog(["WASM", "MEMORY"], `WebAssembly memory grew from ${previous} to ${previous + delta} pages.`); state.dataView = new DataView(memory.buffer); memoryResize.emit(buffer, previous, delta); }); const callbacks = options.initializeCallbacks; for (let i = 0, iEnd = callbacks.length; i < iEnd; i++) { callbacks[i](this); } } destroyLinked() { this.rootNode.getLinked().unlinkAll(); } getDataView() { return this.state.dataView; } } class EmscriptenDebug { constructor() { this.onAllocate = new DebugWeakBroadcastChannel("debugOnAllocate"); this.protectedViews = new DebugWeakStore(); this.sharedObjectLifeCycleChecks = new DebugSharedObjectLifeCycleChecker(); this.uniquePointers = new Set(); } error(message) { _Debug.error(message); } verboseLog(tags, message) { _Debug.verboseLog(tags, message); } } class EmscriptenBinder { constructor() { this.bindingObjects = new Map(); this.counter = 0; } pushBinder(interopObject) { const index = this.counter; ++this.counter; this.bindingObjects.set(index, interopObject); return index; } getBinder(index) { return this.bindingObjects.get(index); } removeBinder(index) { return this.bindingObjects.delete(index); } } class EWState { constructor(dataView) { this.dataView = dataView; } } function initializeSubmodules(instance) { const keys = Object.keys(instance); for (let i = 0, iEnd = keys.length; i < iEnd; i++) { const key = keys[i]; if (key.startsWith("_jsuInitialize")) { const fn = instance[key]; _BUILD.DEBUG && _Debug.assert(fn.length === 0, "initialization function must be parameterless"); fn(); } } } //# sourceMappingURL=get-emscripten-wrapper.js.map