@peterspackman/occjs
Version:
JavaScript/WebAssembly bindings for OCC - a quantum chemistry and crystallography library
102 lines (91 loc) • 3.15 kB
JavaScript
// Temporary module worker for running OCC commands (fresh state each time).
// Spawn with: new Worker('occ-run-worker.js', { type: 'module' })
import createOccCliModule from '../dist/occ.js';
self.onmessage = async function (e) {
const { command, cwd, files } = e.data;
let Module;
try {
Module = await createOccCliModule({
print: (text) => self.postMessage({ type: 'output', text }),
printErr: (text) => self.postMessage({ type: 'error', text }),
onAbort: (msg) => {
self.postMessage({ type: 'error', text: `Module aborted: ${msg}` });
self.postMessage({ type: 'exit', code: 1, files: {} });
},
noInitialRun: true,
locateFile: (path) => new URL(`../dist/${path}`, import.meta.url).href,
});
} catch (error) {
self.postMessage({ type: 'error', text: `Failed to load occ.js: ${error.message}` });
self.postMessage({ type: 'exit', code: 1, files: {} });
return;
}
function collectFiles(dir, outputFiles) {
let contents;
try {
contents = Module.FS.readdir(dir);
} catch (e) {
return;
}
for (const item of contents) {
if (item === '.' || item === '..') continue;
const fullPath = dir === '/' ? '/' + item : dir + '/' + item;
try {
const stat = Module.FS.stat(fullPath);
if (Module.FS.isDir(stat.mode)) {
collectFiles(fullPath, outputFiles);
} else {
outputFiles[fullPath] = Module.FS.readFile(fullPath);
}
} catch (e) {
// Skip files we can't read
}
}
}
try {
// Sync files from persistent storage
if (files) {
for (const [path, content] of Object.entries(files)) {
// Create parent directories if needed
const parts = path.split('/').filter((p) => p);
let currentPath = '/';
for (let i = 0; i < parts.length - 1; i++) {
currentPath += parts[i];
try {
Module.FS.mkdir(currentPath);
} catch (e) {
// Directory might already exist
}
currentPath += '/';
}
Module.FS.writeFile(path, content);
}
}
// Set working directory
if (cwd) {
try {
Module.FS.chdir(cwd);
} catch (e) {
// If directory doesn't exist, stay in root
}
}
self.postMessage({ type: 'ready' });
// Call main with arguments
const args = command.split(/\s+/).filter((a) => a.length > 0);
const exitCode = Module.callMain(args);
// Collect all files from filesystem to send back
const outputFiles = {};
collectFiles('/', outputFiles);
self.postMessage({ type: 'exit', code: exitCode, files: outputFiles });
} catch (error) {
if (error && error.name === 'ExitStatus') {
// Still collect files even on non-zero exit
const outputFiles = {};
collectFiles('/', outputFiles);
self.postMessage({ type: 'exit', code: error.status, files: outputFiles });
} else {
self.postMessage({ type: 'error', text: `Runtime error: ${error.message}` });
self.postMessage({ type: 'exit', code: 1, files: {} });
}
}
};