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.
139 lines • 5.86 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.EmscriptenWrapperOptions = exports.getEmscriptenWrapper = void 0;
const tslib_1 = require("tslib");
const shim_web_assembly_memory_js_1 = require("../util/shim-web-assembly-memory.js");
const broadcast_channel_js_1 = require("../../eventing/broadcast-channel.js");
const _debug_js_1 = require("../../debug/_debug.js");
const debug_weak_broadcast_event_js_1 = require("../../debug/debug-weak-broadcast-event.js");
const debug_shared_object_life_cycle_checker_js_1 = require("../../debug/debug-shared-object-life-cycle-checker.js");
const debug_weak_store_js_1 = require("../../debug/debug-weak-store.js");
const rtti_interop_js_1 = require("../../runtime/rtti-interop.js");
/**
* @public
* Factory for creating wrapped emscripten module.
*/
function getEmscriptenWrapper(memory_1, emscriptenModuleFactory_1, lifecycleStrategy_1, options_1) {
return tslib_1.__awaiter(this, arguments, void 0, function* (memory, emscriptenModuleFactory, lifecycleStrategy, options, extension = {}) {
let debugLabel = undefined;
try {
if (_BUILD.DEBUG) {
debugLabel = _debug_js_1._Debug.label;
_debug_js_1._Debug.label = "EmscriptenWrapper";
}
const memoryListener = _BUILD.DEBUG
? new debug_weak_broadcast_event_js_1.DebugWeakBroadcastChannel("onMemoryResize")
: new broadcast_channel_js_1.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_js_1._Debug.label = debugLabel;
}
}
});
}
exports.getEmscriptenWrapper = getEmscriptenWrapper;
/**
* @public
*/
class EmscriptenWrapperOptions {
constructor(initializeCallbacks) {
this.initializeCallbacks = initializeCallbacks;
}
extend(options) {
return new EmscriptenWrapperOptions(this.initializeCallbacks.concat(options.initializeCallbacks));
}
}
exports.EmscriptenWrapperOptions = EmscriptenWrapperOptions;
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 rtti_interop_js_1.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...
(0, shim_web_assembly_memory_js_1.shimWebAssemblyMemory)(memory, (buffer, previous, delta) => {
_BUILD.DEBUG && _debug_js_1._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 debug_weak_broadcast_event_js_1.DebugWeakBroadcastChannel("debugOnAllocate");
this.protectedViews = new debug_weak_store_js_1.DebugWeakStore();
this.sharedObjectLifeCycleChecks = new debug_shared_object_life_cycle_checker_js_1.DebugSharedObjectLifeCycleChecker();
this.uniquePointers = new Set();
}
error(message) {
_debug_js_1._Debug.error(message);
}
verboseLog(tags, message) {
_debug_js_1._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_js_1._Debug.assert(fn.length === 0, "initialization function must be parameterless");
fn();
}
}
}
//# sourceMappingURL=get-emscripten-wrapper.js.map