swisseph-wasm
Version:
High-precision Swiss Ephemeris WebAssembly library for astronomical calculations in JavaScript
1,213 lines (1,191 loc) • 150 kB
JavaScript
var Swisseph = ( () => {
var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined;
return (function(moduleArg={}) {
var moduleRtn;
var Module = moduleArg;
var readyPromiseResolve, readyPromiseReject;
var readyPromise = new Promise( (resolve, reject) => {
readyPromiseResolve = resolve;
readyPromiseReject = reject
}
);
// Detect environment properly
var ENVIRONMENT_IS_NODE = typeof process !== 'undefined' && process.versions && process.versions.node;
var ENVIRONMENT_IS_WEB = typeof window !== 'undefined' || (typeof importScripts === 'function' && !ENVIRONMENT_IS_NODE);
var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
Module["expectedDataFileDownloads"] ??= 0;
Module["expectedDataFileDownloads"]++;
( () => {
var isPthread = typeof ENVIRONMENT_IS_PTHREAD != "undefined" && ENVIRONMENT_IS_PTHREAD;
var isWasmWorker = typeof ENVIRONMENT_IS_WASM_WORKER != "undefined" && ENVIRONMENT_IS_WASM_WORKER;
if (isPthread || isWasmWorker)
return;
function loadPackage(metadata) {
var PACKAGE_PATH = "";
if (typeof window === "object") {
PACKAGE_PATH = window["encodeURIComponent"](window.location.pathname.substring(0, window.location.pathname.lastIndexOf("/")) + "/")
} else if (typeof process === "undefined" && typeof location !== "undefined") {
PACKAGE_PATH = encodeURIComponent(location.pathname.substring(0, location.pathname.lastIndexOf("/")) + "/")
}
var PACKAGE_NAME = "wsam/swisseph.data";
var REMOTE_PACKAGE_BASE;
if (ENVIRONMENT_IS_NODE) {
// In Node.js, resolve relative to the current module
REMOTE_PACKAGE_BASE = new URL("./swisseph.data", import.meta.url).href;
} else {
// In browser, use import.meta.resolve if available, otherwise relative path
REMOTE_PACKAGE_BASE = import.meta.resolve ? import.meta.resolve("./swisseph.data") : "./swisseph.data";
}
var REMOTE_PACKAGE_NAME = Module["locateFile"] ? Module["locateFile"](REMOTE_PACKAGE_BASE, "") : REMOTE_PACKAGE_BASE;
var REMOTE_PACKAGE_SIZE = metadata["remote_package_size"];
function fetchRemotePackage(packageName, packageSize, callback, errback) {
Module["dataFileDownloads"] ??= {};
// Cross-platform fetch function
async function crossPlatformFetch(url) {
if (ENVIRONMENT_IS_NODE) {
// Node.js environment - use fs to read local files
try {
const { readFile } = await import('fs/promises');
const { fileURLToPath } = await import('url');
const { resolve, dirname } = await import('path');
let filePath;
if (url.startsWith('file://')) {
filePath = fileURLToPath(url);
} else if (url.startsWith('./') || url.startsWith('../')) {
// Resolve relative to current module
const currentDir = dirname(fileURLToPath(import.meta.url));
filePath = resolve(currentDir, url);
} else {
filePath = url;
}
const data = await readFile(filePath);
return {
ok: true,
arrayBuffer: () => Promise.resolve(data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength))
};
} catch (error) {
return {
ok: false,
status: 404,
url: url,
error: error
};
}
} else {
// Browser environment - use standard fetch
return fetch(url);
}
}
crossPlatformFetch(packageName).catch(cause => Promise.reject(new Error(`Network Error: ${packageName}`,{
cause
}))).then(response => {
if (!response.ok) {
return Promise.reject(new Error(`${response.status}: ${response.url}`))
}
if (!response.body && response.arrayBuffer) {
return response.arrayBuffer().then(callback)
}
const reader = response.body.getReader();
const iterate = () => reader.read().then(handleChunk).catch(cause => Promise.reject(new Error(`Unexpected error while handling : ${response.url} ${cause}`,{
cause
})));
const chunks = [];
const headers = response.headers;
const total = Number(headers.get("Content-Length") ?? packageSize);
let loaded = 0;
const handleChunk = ({done, value}) => {
if (!done) {
chunks.push(value);
loaded += value.length;
Module["dataFileDownloads"][packageName] = {
loaded,
total
};
let totalLoaded = 0;
let totalSize = 0;
for (const download of Object.values(Module["dataFileDownloads"])) {
totalLoaded += download.loaded;
totalSize += download.total
}
Module["setStatus"]?.(`Downloading data... (${totalLoaded}/${totalSize})`);
return iterate()
} else {
const packageData = new Uint8Array(chunks.map(c => c.length).reduce( (a, b) => a + b, 0));
let offset = 0;
for (const chunk of chunks) {
packageData.set(chunk, offset);
offset += chunk.length
}
callback(packageData.buffer)
}
}
;
Module["setStatus"]?.("Downloading data...");
return iterate()
}
)
}
function handleError(error) {
console.error("package error:", error)
}
var fetchedCallback = null;
var fetched = Module["getPreloadedPackage"] ? Module["getPreloadedPackage"](REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE) : null;
if (!fetched)
fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, data => {
if (fetchedCallback) {
fetchedCallback(data);
fetchedCallback = null
} else {
fetched = data
}
}
, handleError);
function runWithFS(Module) {
function assert(check, msg) {
if (!check)
throw msg + (new Error).stack
}
Module["FS_createPath"]("/", "sweph", true, true);
function DataRequest(start, end, audio) {
this.start = start;
this.end = end;
this.audio = audio
}
DataRequest.prototype = {
requests: {},
open: function(mode, name) {
this.name = name;
this.requests[name] = this;
Module["addRunDependency"](`fp ${this.name}`)
},
send: function() {},
onload: function() {
var byteArray = this.byteArray.subarray(this.start, this.end);
this.finish(byteArray)
},
finish: function(byteArray) {
var that = this;
Module["FS_createDataFile"](this.name, null, byteArray, true, true, true);
Module["removeRunDependency"](`fp ${that.name}`);
this.requests[this.name] = null
}
};
var files = metadata["files"];
for (var i = 0; i < files.length; ++i) {
new DataRequest(files[i]["start"],files[i]["end"],files[i]["audio"] || 0).open("GET", files[i]["filename"])
}
function processPackageData(arrayBuffer) {
assert(arrayBuffer, "Loading data file failed.");
assert(arrayBuffer.constructor.name === ArrayBuffer.name, "bad input to processPackageData");
var byteArray = new Uint8Array(arrayBuffer);
DataRequest.prototype.byteArray = byteArray;
var files = metadata["files"];
for (var i = 0; i < files.length; ++i) {
DataRequest.prototype.requests[files[i].filename].onload()
}
Module["removeRunDependency"]("datafile_wsam/swisseph.data")
}
Module["addRunDependency"]("datafile_wsam/swisseph.data");
Module["preloadResults"] ??= {};
Module["preloadResults"][PACKAGE_NAME] = {
fromCache: false
};
if (fetched) {
processPackageData(fetched);
fetched = null
} else {
fetchedCallback = processPackageData
}
}
if (Module["calledRun"]) {
runWithFS(Module)
} else {
(Module["preRun"] ??= []).push(runWithFS)
}
}
loadPackage({
files: [{
filename: "/sweph/seas_18.se1",
start: 0,
end: 223002
}, {
filename: "/sweph/seasnam.txt",
start: 223002,
end: 10153224
}, {
filename: "/sweph/sefstars.txt",
start: 10153224,
end: 10286461
}, {
filename: "/sweph/seleapsec.txt",
start: 10286461,
end: 10286743
}, {
filename: "/sweph/semo_18.se1",
start: 10286743,
end: 11591514
}, {
filename: "/sweph/seorbel.txt",
start: 11591514,
end: 11597371
}, {
filename: "/sweph/sepl_18.se1",
start: 11597371,
end: 12081426
}],
remote_package_size: 12081426
})
}
)();
var moduleOverrides = Object.assign({}, Module);
var arguments_ = [];
var thisProgram = "./this.program";
var scriptDirectory = "";
function locateFile(path) {
if (Module["locateFile"]) {
return Module["locateFile"](path, scriptDirectory)
}
return scriptDirectory + path
}
var readAsync, readBinary;
if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
if (ENVIRONMENT_IS_WORKER) {
scriptDirectory = self.location.href
} else if (typeof document != "undefined" && document.currentScript) {
scriptDirectory = document.currentScript.src
}
if (_scriptName) {
scriptDirectory = _scriptName
}
if (scriptDirectory.startsWith("blob:")) {
scriptDirectory = ""
} else {
scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1)
}
{
readAsync = async url => {
if (ENVIRONMENT_IS_NODE) {
// Node.js environment
try {
const { readFile } = await import('fs/promises');
const { fileURLToPath } = await import('url');
const { resolve, dirname } = await import('path');
let filePath;
if (url.startsWith('file://')) {
filePath = fileURLToPath(url);
} else if (url.startsWith('./') || url.startsWith('../')) {
const currentDir = dirname(fileURLToPath(import.meta.url));
filePath = resolve(currentDir, url);
} else {
filePath = url;
}
console.log('DEBUG: readAsync Node.js file read:', { url, filePath });
console.log('DEBUG: readAsync Node.js file read:', { url, filePath });
console.log('DEBUG: Node.js file read attempt:', { url, filePath });
const data = await readFile(filePath);
console.log('DEBUG: File read successful, size:', data.length);
return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
} catch (error) {
console.log('DEBUG: File read failed:', error.message);
throw new Error(`File read error: ${url} - ${error.message}`);
}
} else {
// Browser environment
var response = await fetch(url, {
credentials: "same-origin"
});
if (response.ok) {
return response.arrayBuffer()
}
throw new Error(response.status + " : " + response.url)
}
}
}
} else {
// Node.js environment
if (ENVIRONMENT_IS_NODE) {
readAsync = async url => {
try {
const { readFile } = await import('fs/promises');
const { fileURLToPath } = await import('url');
const { resolve, dirname } = await import('path');
let filePath;
if (url.startsWith('file://')) {
filePath = fileURLToPath(url);
} else if (url.startsWith('./') || url.startsWith('../')) {
const currentDir = dirname(fileURLToPath(import.meta.url));
filePath = resolve(currentDir, url);
} else {
filePath = url;
}
const data = await readFile(filePath);
return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
} catch (error) {
throw new Error(`File read error: ${url} - ${error.message}`);
}
};
// We'll set readBinary to null for now since we have readAsync
readBinary = null;
}
}
var out = Module["print"] || console.log.bind(console);
var err = Module["printErr"] || console.error.bind(console);
Object.assign(Module, moduleOverrides);
moduleOverrides = null;
if (Module["arguments"])
arguments_ = Module["arguments"];
if (Module["thisProgram"])
thisProgram = Module["thisProgram"];
var wasmBinary = Module["wasmBinary"];
var wasmMemory;
var ABORT = false;
var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
function updateMemoryViews() {
var b = wasmMemory.buffer;
Module["HEAP8"] = HEAP8 = new Int8Array(b);
Module["HEAP16"] = HEAP16 = new Int16Array(b);
Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
Module["HEAPU16"] = HEAPU16 = new Uint16Array(b);
Module["HEAP32"] = HEAP32 = new Int32Array(b);
Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
Module["HEAPF64"] = HEAPF64 = new Float64Array(b)
}
var __ATPRERUN__ = [];
var __ATINIT__ = [];
var __ATPOSTRUN__ = [];
var runtimeInitialized = false;
function preRun() {
if (Module["preRun"]) {
if (typeof Module["preRun"] == "function")
Module["preRun"] = [Module["preRun"]];
while (Module["preRun"].length) {
addOnPreRun(Module["preRun"].shift())
}
}
callRuntimeCallbacks(__ATPRERUN__)
}
function initRuntime() {
runtimeInitialized = true;
if (!Module["noFSInit"] && !FS.initialized)
FS.init();
FS.ignorePermissions = false;
TTY.init();
callRuntimeCallbacks(__ATINIT__)
}
function postRun() {
if (Module["postRun"]) {
if (typeof Module["postRun"] == "function")
Module["postRun"] = [Module["postRun"]];
while (Module["postRun"].length) {
addOnPostRun(Module["postRun"].shift())
}
}
callRuntimeCallbacks(__ATPOSTRUN__)
}
function addOnPreRun(cb) {
__ATPRERUN__.unshift(cb)
}
function addOnInit(cb) {
__ATINIT__.unshift(cb)
}
function addOnPostRun(cb) {
__ATPOSTRUN__.unshift(cb)
}
var runDependencies = 0;
var dependenciesFulfilled = null;
function getUniqueRunDependency(id) {
return id
}
function addRunDependency(id) {
runDependencies++;
Module["monitorRunDependencies"]?.(runDependencies)
}
function removeRunDependency(id) {
runDependencies--;
Module["monitorRunDependencies"]?.(runDependencies);
if (runDependencies == 0) {
if (dependenciesFulfilled) {
var callback = dependenciesFulfilled;
dependenciesFulfilled = null;
callback()
}
}
}
function abort(what) {
Module["onAbort"]?.(what);
what = "Aborted(" + what + ")";
err(what);
ABORT = true;
what += ". Build with -sASSERTIONS for more info.";
var e = new WebAssembly.RuntimeError(what);
readyPromiseReject(e);
throw e
}
var dataURIPrefix = "data:application/octet-stream;base64,";
var isDataURI = filename => filename.startsWith(dataURIPrefix);
function findWasmBinary() {
var f;
if (ENVIRONMENT_IS_NODE) {
// In Node.js, resolve relative to the current module
f = new URL("./swisseph.wasm", import.meta.url).href;
} else {
// In browser, try different approaches for different bundlers
if (import.meta.resolve) {
try {
f = import.meta.resolve("./swisseph.wasm");
} catch (e) {
// Fallback for bundlers that don't support import.meta.resolve
f = "./swisseph.wasm";
}
} else {
// Fallback for older browsers or bundlers
f = "./swisseph.wasm";
}
// For Vite and other dev servers, try to use a more reliable path
if (typeof window !== 'undefined' && window.location) {
const currentPath = window.location.pathname;
if (currentPath.includes('node_modules')) {
// We're likely in a dev environment, use relative path
f = "./swisseph.wasm";
}
}
}
if (!isDataURI(f)) {
return locateFile(f)
}
return f
}
var wasmBinaryFile;
function getBinarySync(file) {
if (file == wasmBinaryFile && wasmBinary) {
return new Uint8Array(wasmBinary)
}
if (readBinary) {
return readBinary(file)
}
throw "both async and sync fetching of the wasm failed"
}
async function getWasmBinary(binaryFile) {
if (!wasmBinary) {
try {
var response = await readAsync(binaryFile);
return new Uint8Array(response)
} catch (error) {
// Fall back to sync loading
}
}
return getBinarySync(binaryFile)
}
async function instantiateArrayBuffer(binaryFile, imports) {
try {
var binary = await getWasmBinary(binaryFile);
var instance = await WebAssembly.instantiate(binary, imports);
return instance
} catch (reason) {
err(`failed to asynchronously prepare wasm: ${reason}`);
abort(reason)
}
}
async function instantiateAsync(binary, binaryFile, imports) {
if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && !ENVIRONMENT_IS_NODE && typeof fetch == "function") {
try {
var response = fetch(binaryFile, {
credentials: "same-origin"
});
var instantiationResult = await WebAssembly.instantiateStreaming(response, imports);
return instantiationResult
} catch (reason) {
err(`wasm streaming compile failed: ${reason}`);
err("falling back to ArrayBuffer instantiation")
}
}
return instantiateArrayBuffer(binaryFile, imports)
}
function getWasmImports() {
return {
a: wasmImports
}
}
async function createWasm() {
function receiveInstance(instance, module) {
wasmExports = instance.exports;
wasmMemory = wasmExports["l"];
updateMemoryViews();
addOnInit(wasmExports["m"]);
removeRunDependency("wasm-instantiate");
return wasmExports
}
addRunDependency("wasm-instantiate");
function receiveInstantiationResult(result) {
receiveInstance(result["instance"])
}
var info = getWasmImports();
if (Module["instantiateWasm"]) {
try {
return Module["instantiateWasm"](info, receiveInstance)
} catch (e) {
err(`Module.instantiateWasm callback failed with error: ${e}`);
readyPromiseReject(e)
}
}
wasmBinaryFile ??= findWasmBinary();
try {
var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info);
receiveInstantiationResult(result);
return result
} catch (e) {
readyPromiseReject(e);
return
}
}
var tempDouble;
var tempI64;
class ExitStatus {
name = "ExitStatus";
constructor(status) {
this.message = `Program terminated with exit(${status})`;
this.status = status
}
}
var callRuntimeCallbacks = callbacks => {
while (callbacks.length > 0) {
callbacks.shift()(Module)
}
}
;
var noExitRuntime = Module["noExitRuntime"] || true;
var stackRestore = val => __emscripten_stack_restore(val);
var stackSave = () => _emscripten_stack_get_current();
var syscallGetVarargI = () => {
var ret = HEAP32[+SYSCALLS.varargs >> 2];
SYSCALLS.varargs += 4;
return ret
}
;
var syscallGetVarargP = syscallGetVarargI;
var PATH = {
isAbs: path => path.charAt(0) === "/",
splitPath: filename => {
var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
return splitPathRe.exec(filename).slice(1)
}
,
normalizeArray: (parts, allowAboveRoot) => {
var up = 0;
for (var i = parts.length - 1; i >= 0; i--) {
var last = parts[i];
if (last === ".") {
parts.splice(i, 1)
} else if (last === "..") {
parts.splice(i, 1);
up++
} else if (up) {
parts.splice(i, 1);
up--
}
}
if (allowAboveRoot) {
for (; up; up--) {
parts.unshift("..")
}
}
return parts
}
,
normalize: path => {
var isAbsolute = PATH.isAbs(path)
, trailingSlash = path.substr(-1) === "/";
path = PATH.normalizeArray(path.split("/").filter(p => !!p), !isAbsolute).join("/");
if (!path && !isAbsolute) {
path = "."
}
if (path && trailingSlash) {
path += "/"
}
return (isAbsolute ? "/" : "") + path
}
,
dirname: path => {
var result = PATH.splitPath(path)
, root = result[0]
, dir = result[1];
if (!root && !dir) {
return "."
}
if (dir) {
dir = dir.substr(0, dir.length - 1)
}
return root + dir
}
,
basename: path => {
if (path === "/")
return "/";
path = PATH.normalize(path);
path = path.replace(/\/$/, "");
var lastSlash = path.lastIndexOf("/");
if (lastSlash === -1)
return path;
return path.substr(lastSlash + 1)
}
,
join: (...paths) => PATH.normalize(paths.join("/")),
join2: (l, r) => PATH.normalize(l + "/" + r)
};
var initRandomFill = () => {
if (typeof crypto == "object" && typeof crypto["getRandomValues"] == "function") {
return view => crypto.getRandomValues(view)
} else
abort("initRandomDevice")
}
;
var randomFill = view => (randomFill = initRandomFill())(view);
var PATH_FS = {
resolve: (...args) => {
var resolvedPath = ""
, resolvedAbsolute = false;
for (var i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
var path = i >= 0 ? args[i] : FS.cwd();
if (typeof path != "string") {
throw new TypeError("Arguments to path.resolve must be strings")
} else if (!path) {
return ""
}
resolvedPath = path + "/" + resolvedPath;
resolvedAbsolute = PATH.isAbs(path)
}
resolvedPath = PATH.normalizeArray(resolvedPath.split("/").filter(p => !!p), !resolvedAbsolute).join("/");
return (resolvedAbsolute ? "/" : "") + resolvedPath || "."
}
,
relative: (from, to) => {
from = PATH_FS.resolve(from).substr(1);
to = PATH_FS.resolve(to).substr(1);
function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== "")
break
}
var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== "")
break
}
if (start > end)
return [];
return arr.slice(start, end - start + 1)
}
var fromParts = trim(from.split("/"));
var toParts = trim(to.split("/"));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
for (var i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break
}
}
var outputParts = [];
for (var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push("..")
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join("/")
}
};
var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder : undefined;
var UTF8ArrayToString = (heapOrArray, idx=0, maxBytesToRead=NaN) => {
var endIdx = idx + maxBytesToRead;
var endPtr = idx;
while (heapOrArray[endPtr] && !(endPtr >= endIdx))
++endPtr;
if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr))
}
var str = "";
while (idx < endPtr) {
var u0 = heapOrArray[idx++];
if (!(u0 & 128)) {
str += String.fromCharCode(u0);
continue
}
var u1 = heapOrArray[idx++] & 63;
if ((u0 & 224) == 192) {
str += String.fromCharCode((u0 & 31) << 6 | u1);
continue
}
var u2 = heapOrArray[idx++] & 63;
if ((u0 & 240) == 224) {
u0 = (u0 & 15) << 12 | u1 << 6 | u2
} else {
u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63
}
if (u0 < 65536) {
str += String.fromCharCode(u0)
} else {
var ch = u0 - 65536;
str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023)
}
}
return str
}
;
var FS_stdin_getChar_buffer = [];
var lengthBytesUTF8 = str => {
var len = 0;
for (var i = 0; i < str.length; ++i) {
var c = str.charCodeAt(i);
if (c <= 127) {
len++
} else if (c <= 2047) {
len += 2
} else if (c >= 55296 && c <= 57343) {
len += 4;
++i
} else {
len += 3
}
}
return len
}
;
var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
if (!(maxBytesToWrite > 0))
return 0;
var startIdx = outIdx;
var endIdx = outIdx + maxBytesToWrite - 1;
for (var i = 0; i < str.length; ++i) {
var u = str.charCodeAt(i);
if (u >= 55296 && u <= 57343) {
var u1 = str.charCodeAt(++i);
u = 65536 + ((u & 1023) << 10) | u1 & 1023
}
if (u <= 127) {
if (outIdx >= endIdx)
break;
heap[outIdx++] = u
} else if (u <= 2047) {
if (outIdx + 1 >= endIdx)
break;
heap[outIdx++] = 192 | u >> 6;
heap[outIdx++] = 128 | u & 63
} else if (u <= 65535) {
if (outIdx + 2 >= endIdx)
break;
heap[outIdx++] = 224 | u >> 12;
heap[outIdx++] = 128 | u >> 6 & 63;
heap[outIdx++] = 128 | u & 63
} else {
if (outIdx + 3 >= endIdx)
break;
heap[outIdx++] = 240 | u >> 18;
heap[outIdx++] = 128 | u >> 12 & 63;
heap[outIdx++] = 128 | u >> 6 & 63;
heap[outIdx++] = 128 | u & 63
}
}
heap[outIdx] = 0;
return outIdx - startIdx
}
;
function intArrayFromString(stringy, dontAddNull, length) {
var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
var u8array = new Array(len);
var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
if (dontAddNull)
u8array.length = numBytesWritten;
return u8array
}
var FS_stdin_getChar = () => {
if (!FS_stdin_getChar_buffer.length) {
var result = null;
if (typeof window != "undefined" && typeof window.prompt == "function") {
result = window.prompt("Input: ");
if (result !== null) {
result += "\n"
}
} else {}
if (!result) {
return null
}
FS_stdin_getChar_buffer = intArrayFromString(result, true)
}
return FS_stdin_getChar_buffer.shift()
}
;
var TTY = {
ttys: [],
init() {},
shutdown() {},
register(dev, ops) {
TTY.ttys[dev] = {
input: [],
output: [],
ops
};
FS.registerDevice(dev, TTY.stream_ops)
},
stream_ops: {
open(stream) {
var tty = TTY.ttys[stream.node.rdev];
if (!tty) {
throw new FS.ErrnoError(43)
}
stream.tty = tty;
stream.seekable = false
},
close(stream) {
stream.tty.ops.fsync(stream.tty)
},
fsync(stream) {
stream.tty.ops.fsync(stream.tty)
},
read(stream, buffer, offset, length, pos) {
if (!stream.tty || !stream.tty.ops.get_char) {
throw new FS.ErrnoError(60)
}
var bytesRead = 0;
for (var i = 0; i < length; i++) {
var result;
try {
result = stream.tty.ops.get_char(stream.tty)
} catch (e) {
throw new FS.ErrnoError(29)
}
if (result === undefined && bytesRead === 0) {
throw new FS.ErrnoError(6)
}
if (result === null || result === undefined)
break;
bytesRead++;
buffer[offset + i] = result
}
if (bytesRead) {
stream.node.atime = Date.now()
}
return bytesRead
},
write(stream, buffer, offset, length, pos) {
if (!stream.tty || !stream.tty.ops.put_char) {
throw new FS.ErrnoError(60)
}
try {
for (var i = 0; i < length; i++) {
stream.tty.ops.put_char(stream.tty, buffer[offset + i])
}
} catch (e) {
throw new FS.ErrnoError(29)
}
if (length) {
stream.node.mtime = stream.node.ctime = Date.now()
}
return i
}
},
default_tty_ops: {
get_char(tty) {
return FS_stdin_getChar()
},
put_char(tty, val) {
if (val === null || val === 10) {
out(UTF8ArrayToString(tty.output));
tty.output = []
} else {
if (val != 0)
tty.output.push(val)
}
},
fsync(tty) {
if (tty.output && tty.output.length > 0) {
out(UTF8ArrayToString(tty.output));
tty.output = []
}
},
ioctl_tcgets(tty) {
return {
c_iflag: 25856,
c_oflag: 5,
c_cflag: 191,
c_lflag: 35387,
c_cc: [3, 28, 127, 21, 4, 0, 1, 0, 17, 19, 26, 0, 18, 15, 23, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
},
ioctl_tcsets(tty, optional_actions, data) {
return 0
},
ioctl_tiocgwinsz(tty) {
return [24, 80]
}
},
default_tty1_ops: {
put_char(tty, val) {
if (val === null || val === 10) {
err(UTF8ArrayToString(tty.output));
tty.output = []
} else {
if (val != 0)
tty.output.push(val)
}
},
fsync(tty) {
if (tty.output && tty.output.length > 0) {
err(UTF8ArrayToString(tty.output));
tty.output = []
}
}
}
};
var alignMemory = (size, alignment) => Math.ceil(size / alignment) * alignment;
var mmapAlloc = size => {
abort()
}
;
var MEMFS = {
ops_table: null,
mount(mount) {
return MEMFS.createNode(null, "/", 16895, 0)
},
createNode(parent, name, mode, dev) {
if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
throw new FS.ErrnoError(63)
}
MEMFS.ops_table ||= {
dir: {
node: {
getattr: MEMFS.node_ops.getattr,
setattr: MEMFS.node_ops.setattr,
lookup: MEMFS.node_ops.lookup,
mknod: MEMFS.node_ops.mknod,
rename: MEMFS.node_ops.rename,
unlink: MEMFS.node_ops.unlink,
rmdir: MEMFS.node_ops.rmdir,
readdir: MEMFS.node_ops.readdir,
symlink: MEMFS.node_ops.symlink
},
stream: {
llseek: MEMFS.stream_ops.llseek
}
},
file: {
node: {
getattr: MEMFS.node_ops.getattr,
setattr: MEMFS.node_ops.setattr
},
stream: {
llseek: MEMFS.stream_ops.llseek,
read: MEMFS.stream_ops.read,
write: MEMFS.stream_ops.write,
allocate: MEMFS.stream_ops.allocate,
mmap: MEMFS.stream_ops.mmap,
msync: MEMFS.stream_ops.msync
}
},
link: {
node: {
getattr: MEMFS.node_ops.getattr,
setattr: MEMFS.node_ops.setattr,
readlink: MEMFS.node_ops.readlink
},
stream: {}
},
chrdev: {
node: {
getattr: MEMFS.node_ops.getattr,
setattr: MEMFS.node_ops.setattr
},
stream: FS.chrdev_stream_ops
}
};
var node = FS.createNode(parent, name, mode, dev);
if (FS.isDir(node.mode)) {
node.node_ops = MEMFS.ops_table.dir.node;
node.stream_ops = MEMFS.ops_table.dir.stream;
node.contents = {}
} else if (FS.isFile(node.mode)) {
node.node_ops = MEMFS.ops_table.file.node;
node.stream_ops = MEMFS.ops_table.file.stream;
node.usedBytes = 0;
node.contents = null
} else if (FS.isLink(node.mode)) {
node.node_ops = MEMFS.ops_table.link.node;
node.stream_ops = MEMFS.ops_table.link.stream
} else if (FS.isChrdev(node.mode)) {
node.node_ops = MEMFS.ops_table.chrdev.node;
node.stream_ops = MEMFS.ops_table.chrdev.stream
}
node.atime = node.mtime = node.ctime = Date.now();
if (parent) {
parent.contents[name] = node;
parent.atime = parent.mtime = parent.ctime = node.atime
}
return node
},
getFileDataAsTypedArray(node) {
if (!node.contents)
return new Uint8Array(0);
if (node.contents.subarray)
return node.contents.subarray(0, node.usedBytes);
return new Uint8Array(node.contents)
},
expandFileStorage(node, newCapacity) {
var prevCapacity = node.contents ? node.contents.length : 0;
if (prevCapacity >= newCapacity)
return;
var CAPACITY_DOUBLING_MAX = 1024 * 1024;
newCapacity = Math.max(newCapacity, prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0);
if (prevCapacity != 0)
newCapacity = Math.max(newCapacity, 256);
var oldContents = node.contents;
node.contents = new Uint8Array(newCapacity);
if (node.usedBytes > 0)
node.contents.set(oldContents.subarray(0, node.usedBytes), 0)
},
resizeFileStorage(node, newSize) {
if (node.usedBytes == newSize)
return;
if (newSize == 0) {
node.contents = null;
node.usedBytes = 0
} else {
var oldContents = node.contents;
node.contents = new Uint8Array(newSize);
if (oldContents) {
node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes)))
}
node.usedBytes = newSize
}
},
node_ops: {
getattr(node) {
var attr = {};
attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
attr.ino = node.id;
attr.mode = node.mode;
attr.nlink = 1;
attr.uid = 0;
attr.gid = 0;
attr.rdev = node.rdev;
if (FS.isDir(node.mode)) {
attr.size = 4096
} else if (FS.isFile(node.mode)) {
attr.size = node.usedBytes
} else if (FS.isLink(node.mode)) {
attr.size = node.link.length
} else {
attr.size = 0
}
attr.atime = new Date(node.atime);
attr.mtime = new Date(node.mtime);
attr.ctime = new Date(node.ctime);
attr.blksize = 4096;
attr.blocks = Math.ceil(attr.size / attr.blksize);
return attr
},
setattr(node, attr) {
for (const key of ["mode", "atime", "mtime", "ctime"]) {
if (attr[key]) {
node[key] = attr[key]
}
}
if (attr.size !== undefined) {
MEMFS.resizeFileStorage(node, attr.size)
}
},
lookup(parent, name) {
throw MEMFS.doesNotExistError
},
mknod(parent, name, mode, dev) {
return MEMFS.createNode(parent, name, mode, dev)
},
rename(old_node, new_dir, new_name) {
var new_node;
try {
new_node = FS.lookupNode(new_dir, new_name)
} catch (e) {}
if (new_node) {
if (FS.isDir(old_node.mode)) {
for (var i in new_node.contents) {
throw new FS.ErrnoError(55)
}
}
FS.hashRemoveNode(new_node)
}
delete old_node.parent.contents[old_node.name];
new_dir.contents[new_name] = old_node;
old_node.name = new_name;
new_dir.ctime = new_dir.mtime = old_node.parent.ctime = old_node.parent.mtime = Date.now()
},
unlink(parent, name) {
delete parent.contents[name];
parent.ctime = parent.mtime = Date.now()
},
rmdir(parent, name) {
var node = FS.lookupNode(parent, name);
for (var i in node.contents) {
throw new FS.ErrnoError(55)
}
delete parent.contents[name];
parent.ctime = parent.mtime = Date.now()
},
readdir(node) {
return [".", "..", ...Object.keys(node.contents)]
},
symlink(parent, newname, oldpath) {
var node = MEMFS.createNode(parent, newname, 511 | 40960, 0);
node.link = oldpath;
return node
},
readlink(node) {
if (!FS.isLink(node.mode)) {
throw new FS.ErrnoError(28)
}
return node.link
}
},
stream_ops: {
read(stream, buffer, offset, length, position) {
var contents = stream.node.contents;
if (position >= stream.node.usedBytes)
return 0;
var size = Math.min(stream.node.usedBytes - position, length);
if (size > 8 && contents.subarray) {
buffer.set(contents.subarray(position, position + size), offset)
} else {
for (var i = 0; i < size; i++)
buffer[offset + i] = contents[position + i]
}
return size
},
write(stream, buffer, offset, length, position, canOwn) {
if (buffer.buffer === HEAP8.buffer) {
canOwn = false
}
if (!length)
return 0;
var node = stream.node;
node.mtime = node.ctime = Date.now();
if (buffer.subarray && (!node.contents || node.contents.subarray)) {
if (canOwn) {
node.contents = buffer.subarray(offset, offset + length);
node.usedBytes = length;
return length
} else if (node.usedBytes === 0 && position === 0) {
node.contents = buffer.slice(offset, offset + length);
node.usedBytes = length;
return length
} else if (position + length <= node.usedBytes) {
node.contents.set(buffer.subarray(offset, offset + length), position);
return length
}
}
MEMFS.expandFileStorage(node, position + length);
if (node.contents.subarray && buffer.subarray) {
node.contents.set(buffer.subarray(offset, offset + length), position)
} else {
for (var i = 0; i < length; i++) {
node.contents[position + i] = buffer[offset + i]
}
}
nod