UNPKG

@doc.e.dub/csound-browser

Version:

[![npm (scoped with tag)](https://shields.shivering-isles.com/npm/v/@csound/browser/latest)](https://www.npmjs.com/package/@csound/browser) [![GitHub Workflow Status](https://shields.shivering-isles.com/github/workflow/status/csound/csound/csound_wasm)](h

124 lines (103 loc) 3.34 kB
import { createFsFromVolume } from "memfs"; import { Volume } from "memfs/lib/volume"; import { difference } from "ramda"; // because workers come and go, for users to have some // persistency, we'll sync a non-worker storage // with the filesystems spawned on threads * @extends {typeof import("memfs").IFs} export const persistentStorage = new Volume(); /** * The in-browser filesystem based on nodejs's * built-in module "fs" * @name fs * @memberof CsoundObj * @type {IFs:memfs} */ export const persistentFilesystem = createFsFromVolume(persistentStorage); // modified from @wasmer/wasmfs function fromJSONFixed(vol, json) { const seperator = "/"; for (let filename in json) { const data = json[filename]; filename = filename.replace(/^\/sandbox\//i, ""); const isDirectory = data ? Object.getPrototypeOf(data) === null : data === null; if (!isDirectory) { const steps = filename.split(seperator); if (steps.length > 1) { const dirname = seperator + steps.slice(0, -1).join(seperator); vol.mkdirpBase(dirname, 0o777); } vol.writeFileSync(filename, data || ""); } else { vol.mkdirpBase(filename, 0o777); } } } // modified from @wasmer/wasmfs function _toJSON(link, json = {}) { let isEmpty = true; for (const name in link.children) { isEmpty = false; const child = link.getChild(name); if (child) { const node = child.getNode(); if (node && node.isFile()) { const filename = child.getPath(); json[filename] = node.getBuffer(); } else if (node && node.isDirectory()) { _toJSON(child, json); } } } const directoryPath = link.getPath(); if (directoryPath && isEmpty) { delete json[directoryPath]; } return json; } // modified from @wasmer/wasmfs function toJSONFixed(volume, paths, json = {}, isRelative = false) { const links = []; if (paths) { if (!Array.isArray(paths)) paths = [paths]; for (const path of paths) { const filename = path.split("/").slice(-1)[0]; const link = volume.getResolvedLink(filename); if (!link) continue; links.push(link); } } else { links.push(volume.root); } if (links.length === 0) return json; for (const link of links) _toJSON(link, json, isRelative ? link.getPath() : ""); return json; } const lastmods = {}; export const syncPersistentStorage = (workerStorage) => { fromJSONFixed(persistentStorage, workerStorage); }; export const getModifiedPersistentStorage = () => { const currentFs = toJSONFixed(persistentStorage, "/"); const needsSync = {}; for (const dataKey of Object.keys(currentFs)) { const lastModified = persistentFilesystem.statSync(dataKey).mtimeMs; if (!lastmods[dataKey]) { needsSync[dataKey] = currentFs[dataKey]; lastmods[dataKey] = lastModified; } else if (lastmods[dataKey] !== lastModified) { needsSync[dataKey] = currentFs[dataKey]; lastmods[dataKey] = lastModified; } } const needsUnlink = difference(Object.keys(lastmods), Object.keys(currentFs)); if (needsUnlink.length > 0) { needsSync.__unlink = needsUnlink; } return needsSync; }; export const clearFsLastmods = () => { const keys = Object.keys(lastmods); for (const key of keys) { key && delete lastmods[key]; } };