UNPKG

@casual-simulation/aux-vm-browser

Version:

A set of utilities required to securely run an AUX in a web browser.

218 lines 7.38 kB
import { remapProgressPercent } from '@casual-simulation/aux-common'; // import Worker from './AuxWorker'; // import Worker from './AuxChannel.worker?worker&inline'; import { BrowserAuxChannel } from './BrowserAuxChannel'; import { Subject } from 'rxjs'; export const DEFAULT_IFRAME_ALLOW_ATTRIBUTE = 'accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking'; export const DEFAULT_IFRAME_SANDBOX_ATTRIBUTE = 'allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts allow-downloads'; /** * Defines an interface for an AUX that is run inside a virtual machine. * That is, the AUX is run inside a web worker. * * This implementation works similarly to the one in AuxVMImpl, but instead of using an iframe, it loads the web worker directly. */ export default class StaticAuxVMImpl { /** * The ID of the simulation. */ get id() { return this._id; } get configBotId() { return this._config.configBotId; } /** * Creates a new Simulation VM. * @param id The ID of the simulation. * @param origin The origin of the simulation. * @param config The config that should be used. * @param relaxOrigin Whether to relax the origin of the VM. */ constructor(id, origin, config, relaxOrigin = false) { this._id = id; this._origin = origin; this._config = config; this._relaxOrigin = relaxOrigin; this._localEvents = new Subject(); this._deviceEvents = new Subject(); this._stateUpdated = new Subject(); this._versionUpdated = new Subject(); this._connectionStateChanged = new Subject(); this._onError = new Subject(); this._subVMAdded = new Subject(); this._subVMRemoved = new Subject(); this._subVMMap = new Map(); this._onAuthMessage = new Subject(); } get origin() { return this._origin; } get subVMAdded() { return this._subVMAdded; } get subVMRemoved() { return this._subVMRemoved; } get connectionStateChanged() { return this._connectionStateChanged; } get onError() { return this._onError; } get onAuthMessage() { return this._onAuthMessage; } /** * The observable list of events that should be produced locally. */ get localEvents() { return this._localEvents; } get deviceEvents() { return this._deviceEvents; } /** * The observable list of bot state updates from this simulation. */ get stateUpdated() { return this._stateUpdated; } get versionUpdated() { return this._versionUpdated; } /** * Initaializes the VM. */ async init() { return await this._init(); } async _init() { this._connectionStateChanged.next({ type: 'progress', message: 'Initializing web worker...', progress: 0.1, }); this._connectionStateChanged.next({ type: 'progress', message: 'Creating VM...', progress: 0.2, }); if (!this._channel) { this._channel = new BrowserAuxChannel(location.origin, this._config); } return await this._connect(); } async _connect() { let statusMapper = remapProgressPercent(0.2, 1); return await this._channel.init((events) => this._localEvents.next(events), (events) => this._deviceEvents.next(events), (state) => this._stateUpdated.next(state), (version) => this._versionUpdated.next(version), (state) => this._connectionStateChanged.next(statusMapper(state)), (err) => this._onError.next(err), (channel) => this._handleAddedSubChannel(channel), (id) => this._handleRemovedSubChannel(id), (message) => this._onAuthMessage.next(message)); } /** * Sends the given list of events to the simulation. * @param events The events to send to the simulation. */ async sendEvents(events) { if (!this._channel) return null; return await this._channel.sendEvents(events); } /** * Executes a shout with the given event name on the given bot IDs with the given argument. * Also dispatches any actions and errors that occur. * Returns the results from the event. * @param eventName The name of the event. * @param botIds The IDs of the bots that the shout is being sent to. * @param arg The argument to include in the shout. */ async shout(eventName, botIds, arg) { if (!this._channel) return null; return await this._channel.shout(eventName, botIds, arg); } async formulaBatch(formulas) { if (!this._channel) return null; return await this._channel.formulaBatch(formulas); } async forkAux(newId) { if (!this._channel) return null; return await this._channel.forkAux(newId); } async exportBots(botIds) { if (!this._channel) return null; return await this._channel.exportBots(botIds); } /** * Exports the causal tree for the simulation. */ async export() { if (!this._channel) return null; return await this._channel.export(); } async getTags() { if (!this._channel) return null; return await this._channel.getTags(); } async updateDevice(device) { if (!this._channel) return null; return await this._channel.updateDevice(device); } /** * Gets a new endpoint for the aux channel. * Can then be used with a ConnectableAuxVM. */ createEndpoint() { return null; // return this._channel[createEndpoint](); } sendAuthMessage(message) { return this._channel.sendAuthMessage(message); } unsubscribe() { if (this.closed) { return; } this.closed = true; if (this._channel) { this._channel.unsubscribe(); this._channel = null; } this._connectionStateChanged.unsubscribe(); this._connectionStateChanged = null; this._localEvents.unsubscribe(); this._localEvents = null; } _createSubVM(id, origin, configBotId, channel) { const vm = new StaticAuxVMImpl(id, origin, { ...this._config, configBotId, }); vm._channel = channel; return vm; // return null; // return new RemoteAuxVM(id, origin, configBotId, channel); } async _handleAddedSubChannel(subChannel) { const { id, configBotId } = await subChannel.getInfo(); const channel = (await subChannel.getChannel()); const subVM = { id: id, vm: this._createSubVM(id, this.origin, configBotId, channel), channel, }; this._subVMMap.set(id, subVM); this._subVMAdded.next(subVM); } async _handleRemovedSubChannel(channelId) { const vm = this._subVMMap.get(channelId); if (vm) { this._subVMMap.delete(channelId); this._subVMRemoved.next(vm); } } } //# sourceMappingURL=StaticAuxVMImpl.js.map