From 9078973618c3614f99ccd8dac90afcd82acdc4a6 Mon Sep 17 00:00:00 2001 From: Aaron C Date: Mon, 7 Sep 2026 21:29:40 -0400 Subject: [PATCH 1/9] feat: blob UI APIs and client-side rmLines renderer --- .gitmodules | 3 + internal/storage/fs/blobstore.go | 21 + internal/ui/backend10.go | 9 + internal/ui/backend15.go | 8 + internal/ui/handlers.go | 32 +- internal/ui/routes.go | 2 + internal/ui/ui.go | 4 + ui/extra/simplerenderer/CMakeLists.txt | 17 + ui/extra/simplerenderer/diff-colors | 56 + ui/extra/simplerenderer/librm_lines | 1 + ui/extra/simplerenderer/librm_lines.patch | 65 + ui/extra/simplerenderer/src/main.cpp | 70 + ui/index.html | 2 + ui/public/assets/rm_lines_simple_renderer.js | 4942 +++++++++++++++++ .../assets/rm_lines_simple_renderer.wasm | Bin 0 -> 1041117 bytes ui/src/common/blobapi.ts | 53 + ui/src/components/RmLinesRenderer.tsx | 243 + 17 files changed, 5527 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 100644 ui/extra/simplerenderer/CMakeLists.txt create mode 100644 ui/extra/simplerenderer/diff-colors create mode 160000 ui/extra/simplerenderer/librm_lines create mode 100644 ui/extra/simplerenderer/librm_lines.patch create mode 100644 ui/extra/simplerenderer/src/main.cpp create mode 100644 ui/public/assets/rm_lines_simple_renderer.js create mode 100755 ui/public/assets/rm_lines_simple_renderer.wasm create mode 100644 ui/src/common/blobapi.ts create mode 100644 ui/src/components/RmLinesRenderer.tsx diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..668c66bf --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ui/extra/simplerenderer/librm_lines"] + path = ui/extra/simplerenderer/librm_lines + url = https://github.com/RedTTGMoss/librm_lines diff --git a/internal/storage/fs/blobstore.go b/internal/storage/fs/blobstore.go index cffa85f0..d89e21ba 100644 --- a/internal/storage/fs/blobstore.go +++ b/internal/storage/fs/blobstore.go @@ -760,3 +760,24 @@ func generationFromFileSize(size int64) int64 { //time + 1 space + 64 hash + 1 newline return size / 86 } + +func (fs *FileSystemStorage) GetRawBlob(uid, hash string) (stream io.ReadCloser, err error) { + reader, _, _, _, err := fs.LoadBlob(uid, hash) + return reader, err +} + +func (fs *FileSystemStorage) GetBlobDocumentTree(uid, docid string) (m map[string]string, err error) { + tree, err := fs.GetCachedTree(uid) + if err != nil { + return nil, err + } + doc, err := tree.FindDoc(docid) + if err != nil { + return nil, err + } + output := make(map[string]string, len(doc.Files)) + for _, entry := range doc.Files { + output[entry.EntryName] = entry.Hash + } + return output, nil +} diff --git a/internal/ui/backend10.go b/internal/ui/backend10.go index feb09c28..767ffee4 100644 --- a/internal/ui/backend10.go +++ b/internal/ui/backend10.go @@ -1,6 +1,7 @@ package ui import ( + "errors" "io" "time" @@ -130,3 +131,11 @@ func (d *backend10) DeleteDocument(uid, docID string) (err error) { d.hub.Notify(uid, webDevice, ntf, messages.DocDeletedEvent) return nil } + +func (d *backend10) GetRawBlob(uid, hash string) (reader io.ReadCloser, err error) { + return nil, errors.New("cannot get raw blob on the older backend version") +} + +func (d *backend10) GetBlobDocumentTree(uid, docid string) (m map[string]string, err error) { + return nil, errors.New("cannot use the blob API on the older backend version") +} diff --git a/internal/ui/backend15.go b/internal/ui/backend15.go index 135df89d..9bf1a66c 100644 --- a/internal/ui/backend15.go +++ b/internal/ui/backend15.go @@ -49,3 +49,11 @@ func (b *backend15) DeleteDocument(uid, docID string) (err error) { func (b *backend15) Sync(uid string) { b.h.NotifySync(uid, uuid.NewString()) } + +func (b *backend15) GetRawBlob(uid, hash string) (stream io.ReadCloser, err error) { + return b.blobHandler.GetRawBlob(uid, hash) +} + +func (b *backend15) GetBlobDocumentTree(uid, docid string) (m map[string]string, err error) { + return b.blobHandler.GetBlobDocumentTree(uid, docid) +} diff --git a/internal/ui/handlers.go b/internal/ui/handlers.go index 54c5b579..9571d4ab 100644 --- a/internal/ui/handlers.go +++ b/internal/ui/handlers.go @@ -23,8 +23,10 @@ import ( const ( userIDContextKey = "userID" browserIDContextKey = "browserID" + suByContextKey = "suBy" isSync15Key = "sync15" docIDParam = "docid" + blobIDParam = "blobid" intIDParam = "intid" uiLogger = "[ui] " ui10 = " [10] " @@ -262,6 +264,7 @@ func (app *ReactAppWrapper) listDocuments(c *gin.Context) { } c.JSON(http.StatusOK, tree) } + func (app *ReactAppWrapper) getDocument(c *gin.Context) { uid := userID(c) docid := common.ParamS(docIDParam, c) @@ -301,7 +304,6 @@ func (app *ReactAppWrapper) getDocumentMetadata(c *gin.Context) { } -// move rename func (app *ReactAppWrapper) updateDocument(c *gin.Context) { upd := viewmodel.UpdateDoc{} if err := c.ShouldBindJSON(&upd); err != nil { @@ -320,6 +322,7 @@ func (app *ReactAppWrapper) updateDocument(c *gin.Context) { c.Status(http.StatusOK) } + func (app *ReactAppWrapper) deleteDocument(c *gin.Context) { uid := userID(c) docid := c.Param("docid") @@ -495,6 +498,7 @@ func (app *ReactAppWrapper) updateUser(c *gin.Context) { } c.Status(http.StatusAccepted) } + func (app *ReactAppWrapper) deleteUser(c *gin.Context) { uid := c.Param(useridParam) if uid == userID(c) { @@ -894,3 +898,29 @@ func (app *ReactAppWrapper) screenshareDeleteRoom(c *gin.Context) { c.Status(http.StatusNoContent) } +func (app *ReactAppWrapper) getRawBlob(c *gin.Context) { + uid := userID(c) + blobid := common.ParamS(blobIDParam, c) + backend := app.getBackend(c) + reader, err := backend.GetRawBlob(uid, blobid) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + defer reader.Close() + c.DataFromReader(http.StatusOK, -1, "application/octet-stream", reader, nil) +} + +func (app *ReactAppWrapper) getBlobTree(c *gin.Context) { + uid := userID(c) + docid := common.ParamS(docIDParam, c) + backend := app.getBackend(c) + files, err := backend.GetBlobDocumentTree(uid, docid) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + c.JSON(http.StatusOK, files) +} diff --git a/internal/ui/routes.go b/internal/ui/routes.go index a463f7f2..d77b557d 100644 --- a/internal/ui/routes.go +++ b/internal/ui/routes.go @@ -86,6 +86,8 @@ func (app *ReactAppWrapper) RegisterRoutes(router *gin.Engine) { auth.GET("integrations/:intid/metadata/*path", app.getMetadataIntegration) auth.GET("integrations/:intid/download/*path", app.downloadThroughIntegration) + auth.GET("blobs/:blobid", app.getRawBlob) + auth.GET("documents/:docid/blobs", app.getBlobTree) ss := auth.Group("screenshare") ss.GET("room", app.screenshareJoinActive) ss.GET("room/:roomId", app.screenshareGetRoom) diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 6a7d6c98..898afdc7 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -28,6 +28,8 @@ type backend interface { UpdateDocument(uid, docID, name, parent string) (err error) DeleteDocument(uid, docID string) (err error) Sync(uid string) + GetRawBlob(uid, hash string) (stream io.ReadCloser, err error) + GetBlobDocumentTree(uid, docid string) (m map[string]string, err error) } type codeGenerator interface { NewCode(string) (string, error) @@ -51,6 +53,8 @@ type blobHandler interface { CreateBlobFolder(uid, name, parent string) (doc *storage.Document, err error) Export(uid, docid string) (io.ReadCloser, error) ExportRmDoc(uid, docid string) (io.ReadCloser, error) + GetRawBlob(uid, hash string) (stream io.ReadCloser, err error) + GetBlobDocumentTree(uid, docid string) (m map[string]string, err error) } type notificationHub interface { diff --git a/ui/extra/simplerenderer/CMakeLists.txt b/ui/extra/simplerenderer/CMakeLists.txt new file mode 100644 index 00000000..e1006fab --- /dev/null +++ b/ui/extra/simplerenderer/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.30) +project(rm_lines_simple_renderer) + +set(CMAKE_CXX_STANDARD 20) +include_directories(librm_lines/rm_lines/headers) + +add_subdirectory(librm_lines) + +add_executable(rm_lines_simple_renderer src/main.cpp) +target_link_libraries(rm_lines_simple_renderer rm_lines nlohmann_json::nlohmann_json) +target_link_options(rm_lines_simple_renderer PRIVATE + -sMODULARIZE=1 + -sEXPORT_NAME=RmRenderer + -sEXPORTED_RUNTIME_METHODS=['FS_writeFile','FS_readFile','callMain'] + -sINVOKE_RUN=0 + -sALLOW_MEMORY_GROWTH +) diff --git a/ui/extra/simplerenderer/diff-colors b/ui/extra/simplerenderer/diff-colors new file mode 100644 index 00000000..c1708467 --- /dev/null +++ b/ui/extra/simplerenderer/diff-colors @@ -0,0 +1,56 @@ +diff --git a/rm_lines/headers/common/scene_items.h b/rm_lines/headers/common/scene_items.h +index d3ac174..3c686b7 100644 +--- a/rm_lines/headers/common/scene_items.h ++++ b/rm_lines/headers/common/scene_items.h +@@ -38,10 +38,6 @@ enum PenColor { + GRAY = 1, + WHITE = 2, + +- YELLOW = 3, +- GREEN = 4, +- PINK = 5, +- + BLUE = 6, + RED = 7, + +@@ -53,11 +49,10 @@ enum PenColor { + // that might contain additional color information. + HIGHLIGHT = 9, + +- GREEN_2 = 10, ++ GREEN = 10, + CYAN = 11, + MAGENTA = 12, +- +- YELLOW_2 = 13, ++ YELLOW = 13, + }; + + struct Point { +diff --git a/rm_lines/headers/renderer/rm_lines_stroker/rm_pens/colors.h b/rm_lines/headers/renderer/rm_lines_stroker/rm_pens/colors.h +index b7c38af..faf599c 100644 +--- a/rm_lines/headers/renderer/rm_lines_stroker/rm_pens/colors.h ++++ b/rm_lines/headers/renderer/rm_lines_stroker/rm_pens/colors.h +@@ -6,16 +6,17 @@ constexpr std::pair rMPallet[] = { + {BLACK, Color(0, 0, 0, 255)}, + {GRAY, Color(125, 125, 125, 255)}, + {WHITE, Color(255, 255, 255, 255)}, +- {YELLOW, Color(255, 255, 99, 255)}, +- {GREEN, Color(0, 255, 0, 255)}, +- {PINK, Color(255, 20, 147, 255)}, ++ {BLACK, Color(0, 0, 0, 255)}, ++ {BLACK, Color(0, 0, 0, 255)}, ++ {BLACK, Color(0, 0, 0, 255)}, + {BLUE, Color(0, 98, 204, 255)}, + {RED, Color(217, 7, 7, 255)}, + {GRAY_OVERLAP, Color(125, 125, 125, 255)}, +- {GREEN_2, Color(145, 218, 113, 255)}, ++ {HIGHLIGHT, Color(255, 255, 0, 255)}, ++ {GREEN, Color(145, 218, 113, 255)}, + {CYAN, Color(116, 210, 232, 255)}, + {MAGENTA, Color(192, 127, 210, 255)}, +- {YELLOW_2, Color(250, 231, 25, 255)} ++ {YELLOW, Color(250, 231, 25, 255)} + }; + + inline Color blendMultiply(const Color base, const Color blend, const float blend_amount) { diff --git a/ui/extra/simplerenderer/librm_lines b/ui/extra/simplerenderer/librm_lines new file mode 160000 index 00000000..b1391310 --- /dev/null +++ b/ui/extra/simplerenderer/librm_lines @@ -0,0 +1 @@ +Subproject commit b139131056c6866079ab1f2c146bf6a6773dc61c diff --git a/ui/extra/simplerenderer/librm_lines.patch b/ui/extra/simplerenderer/librm_lines.patch new file mode 100644 index 00000000..0c2b674b --- /dev/null +++ b/ui/extra/simplerenderer/librm_lines.patch @@ -0,0 +1,65 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b96274e..540cc5a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -27,7 +27,7 @@ file(GLOB RM_PENS_FILES rm_lines/src/renderer/rm_lines_stroker/rm_pens/*.cpp) + file(GLOB RM_TEMPLATE_FILES rm_lines/src/renderer/rm_lines_stroker/templates/*.cpp) + file(GLOB STB rm_lines/src/stb/*.cpp) + +-add_library(rm_lines SHARED rm_lines/src/library.cpp ++add_library(rm_lines STATIC rm_lines/src/library.cpp + rm_lines/src/scene_tree/scene_tree_export.cpp + rm_lines/src/reader/tagged_block_reader.cpp + rm_lines/src/v5/reader.cpp +diff --git a/rm_lines/src/library.cpp b/rm_lines/src/library.cpp +index 7b1a7c8..861093e 100644 +--- a/rm_lines/src/library.cpp ++++ b/rm_lines/src/library.cpp +@@ -58,47 +58,3 @@ off_t getFileSize(FILE *file) { + + return size; + } +- +-#ifdef _WIN32 +-#include +-#include +-#pragma comment(lib, "dbghelp.lib") +- +-std::string getStackTrace() { +- void* stack[100]; +- unsigned short frames = CaptureStackBackTrace(0, 100, stack, NULL); +- SYMBOL_INFO* symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); +- symbol->MaxNameLen = 255; +- symbol->SizeOfStruct = sizeof(SYMBOL_INFO); +- +- std::string stackTrace; +- HANDLE process = GetCurrentProcess(); +- SymInitialize(process, NULL, TRUE); +- +- for (unsigned int i = 0; i < frames; i++) { +- SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); +- stackTrace += std::to_string(frames - i - 1) + ": " + symbol->Name + "\n"; +- } +- +- free(symbol); +- return stackTrace; +-} +- +-#else +-#include +-#include +- +-std::string getStackTrace() { +- void *buffer[100]; +- int nptrs = backtrace(buffer, 100); +- char **strings = backtrace_symbols(buffer, nptrs); +- +- std::ostringstream stackTrace; +- for (int i = 0; i < nptrs; i++) { +- stackTrace << i << ": " << strings[i] << "\n"; +- } +- +- free(strings); +- return stackTrace.str(); +-} +-#endif diff --git a/ui/extra/simplerenderer/src/main.cpp b/ui/extra/simplerenderer/src/main.cpp new file mode 100644 index 00000000..6f13638d --- /dev/null +++ b/ui/extra/simplerenderer/src/main.cpp @@ -0,0 +1,70 @@ +#include "library.h" +#include "renderer/renderer_export.h" +#include "scene_tree/scene_tree_export.h" +#include +#include +#include +#include + +static inline void write32BitInt(std::ostream &ostr, uint32_t i) { + uint8_t data[4] = { + (uint8_t) ((i >> 24) & 0xFF), + (uint8_t) ((i >> 16) & 0xFF), + (uint8_t) ((i >> 8) & 0xFF), + (uint8_t) ((i >> 0) & 0xFF), + }; + ostr.write((char*) data, sizeof(data)); +} + +int main(int argc, char **argv){ + if(argc != 3) { + std::cerr << "Usage: " << *argv << " " << std::endl; + return -2; + } + std::string in(argv[1]); + std::string out(argv[2]); + + // Render the file: + const char *treeId = buildTree(in.c_str()); + if(!treeId) { + std::cerr << "Failed to build the tree!" << std::endl; + return -1; + } + + auto tree = getSceneTree(treeId); + std::optional renderer; + try { + renderer = Renderer(tree.get(), NOTEBOOK, false); + } catch (const std::exception &e) { + std::cerr << "Failed to create renderer!" << std::endl; + destroyTree(treeId); + return -1; + } + std::ofstream outputFile(out.c_str()); + + Rect track(0, 0, 0, 0); + for(auto &ref : renderer->layers) { + auto layer = renderer->getSizeTracker(ref.groupId); + if (layer->getBottom() > track.getBottom()) { + track.setBottom(layer->getBottom()); + } + if (layer->getTop() < track.getTop()) { + track.setTop(layer->getTop()); + } + if (layer->getLeft() < track.getLeft()) { + track.setLeft(layer->getLeft()); + } + if (layer->getRight() > track.getRight()) { + track.setRight(layer->getRight()); + } + } + uint32_t width = std::max((uint32_t) (track.getRight() - track.getLeft()), renderer->paperSize.first); + uint32_t height = std::max((uint32_t) (track.getBottom() - track.getTop()), renderer->paperSize.second); + uint32_t size = width * height * 4; + uint32_t *rawFrame = (uint32_t*) malloc(size); + renderer->getFrame(rawFrame, size, Vector(track.getLeft(), track.getTop()), Vector(width, height), Vector(width, height), true); + write32BitInt(outputFile, width); + write32BitInt(outputFile, height); + outputFile.write((char *) rawFrame, size); + destroyTree(treeId); +} diff --git a/ui/index.html b/ui/index.html index 1eb06d6c..a43f857c 100644 --- a/ui/index.html +++ b/ui/index.html @@ -3,11 +3,13 @@ + rmfakecloud
+ diff --git a/ui/public/assets/rm_lines_simple_renderer.js b/ui/public/assets/rm_lines_simple_renderer.js new file mode 100644 index 00000000..ed9e78da --- /dev/null +++ b/ui/public/assets/rm_lines_simple_renderer.js @@ -0,0 +1,4942 @@ +// This code implements the `-sMODULARIZE` settings by taking the generated +// JS program code (INNER_JS_CODE) and wrapping it in a factory function. + +// Single threaded MINIMAL_RUNTIME programs do not need access to +// document.currentScript, so a simple export declaration is enough. +var RmRenderer = (() => { + // When MODULARIZE this JS may be executed later, + // after document.currentScript is gone, so we save it. + // In EXPORT_ES6 mode we can just use 'import.meta.url'. + var _scriptName = globalThis.document?.currentScript?.src; + return async function(moduleArg = {}) { + var moduleRtn; + +// include: shell.js +// include: minimum_runtime_check.js +(function() { + // "30.0.0" -> 300000 + function humanReadableVersionToPacked(str) { + str = str.split('-')[0]; // Remove any trailing part from e.g. "12.53.3-alpha" + var vers = str.split('.').slice(0, 3); + while(vers.length < 3) vers.push('00'); + vers = vers.map((n, i, arr) => n.padStart(2, '0')); + return vers.join(''); + } + // 300000 -> "30.0.0" + var packedVersionToHumanReadable = n => [n / 10000 | 0, (n / 100 | 0) % 100, n % 100].join('.'); + + var TARGET_NOT_SUPPORTED = 2147483647; + + var currentNodeVersion = typeof process !== 'undefined' && process?.versions?.node ? humanReadableVersionToPacked(process.versions.node) : TARGET_NOT_SUPPORTED; + if (currentNodeVersion < 160000) { + throw new Error(`This emscripten-generated code requires node v${ packedVersionToHumanReadable(160000) } (detected v${packedVersionToHumanReadable(currentNodeVersion)})`); + } + + var currentSafariVersion = typeof navigator !== 'undefined' && navigator?.userAgent?.includes("Safari/") && navigator.userAgent.match(/Version\/(\d+\.?\d*\.?\d*)/) ? humanReadableVersionToPacked(navigator.userAgent.match(/Version\/(\d+\.?\d*\.?\d*)/)[1]) : TARGET_NOT_SUPPORTED; + if (currentSafariVersion < 150000) { + throw new Error(`This emscripten-generated code requires Safari v${ packedVersionToHumanReadable(150000) } (detected v${currentSafariVersion})`); + } + + var currentFirefoxVersion = typeof navigator !== 'undefined' && navigator?.userAgent?.match(/Firefox\/(\d+(?:\.\d+)?)/) ? parseFloat(navigator.userAgent.match(/Firefox\/(\d+(?:\.\d+)?)/)[1]) : TARGET_NOT_SUPPORTED; + if (currentFirefoxVersion < 79) { + throw new Error(`This emscripten-generated code requires Firefox v79 (detected v${currentFirefoxVersion})`); + } + + var currentChromeVersion = typeof navigator !== 'undefined' && navigator?.userAgent?.match(/Chrome\/(\d+(?:\.\d+)?)/) ? parseFloat(navigator.userAgent.match(/Chrome\/(\d+(?:\.\d+)?)/)[1]) : TARGET_NOT_SUPPORTED; + if (currentChromeVersion < 85) { + throw new Error(`This emscripten-generated code requires Chrome v85 (detected v${currentChromeVersion})`); + } +})(); + +// end include: minimum_runtime_check.js +// The Module object: Our interface to the outside world. We import +// and export values on it. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(moduleArg) => Promise +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to check if Module already exists (e.g. case 3 above). +// Substitution will be replaced with actual code on later stage of the build, +// this way Closure Compiler will not mangle it (e.g. case 4. above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module = moduleArg; + +// Determine the runtime environment we are in. You can customize this by +// setting the ENVIRONMENT setting at compile time (see settings.js). + +// Attempt to auto-detect the environment +var ENVIRONMENT_IS_WEB = !!globalThis.window; +var ENVIRONMENT_IS_WORKER = !!globalThis.WorkerGlobalScope; +// N.b. Electron.js environment is simultaneously a NODE-environment, but +// also a web environment. +var ENVIRONMENT_IS_NODE = globalThis.process?.versions?.node && globalThis.process?.type != 'renderer'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + +// --pre-jses are emitted after the Module integration code, so that they can +// refer to Module (if they choose; they can also define Module) + + +var arguments_ = []; +var thisProgram = './this.program'; +var quit_ = (status, toThrow) => { + throw toThrow; +}; + +if (typeof __filename != 'undefined') { // Node + _scriptName = __filename; +} else +if (ENVIRONMENT_IS_WORKER) { + _scriptName = self.location.href; +} + +// `/` should be present at the end if `scriptDirectory` is not empty +var scriptDirectory = ''; +function locateFile(path) { + if (Module['locateFile']) { + return Module['locateFile'](path, scriptDirectory); + } + return scriptDirectory + path; +} + +// Hooks that are implemented differently in different runtime environments. +var readAsync, readBinary; + +if (ENVIRONMENT_IS_NODE) { + const isNode = globalThis.process?.versions?.node && globalThis.process?.type != 'renderer'; + if (!isNode) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + // These modules will usually be used on Node.js. Load them eagerly to avoid + // the complexity of lazy-loading. + var fs = require('fs'); + + scriptDirectory = __dirname + '/'; + +// include: node_shell_read.js +readBinary = (filename) => { + // We need to re-wrap `file://` strings to URLs. + filename = isFileURI(filename) ? new URL(filename) : filename; + var ret = fs.readFileSync(filename); + assert(Buffer.isBuffer(ret)); + return ret; +}; + +readAsync = async (filename, binary = true) => { + // See the comment in the `readBinary` function. + filename = isFileURI(filename) ? new URL(filename) : filename; + var ret = fs.readFileSync(filename, binary ? undefined : 'utf8'); + assert(binary ? Buffer.isBuffer(ret) : typeof ret == 'string'); + return ret; +}; +// end include: node_shell_read.js + if (process.argv.length > 1) { + thisProgram = process.argv[1].replace(/\\/g, '/'); + } + + arguments_ = process.argv.slice(2); + + quit_ = (status, toThrow) => { + process.exitCode = status; + throw toThrow; + }; + +} else +if (ENVIRONMENT_IS_SHELL) { + +} else + +// Note that this includes Node.js workers when relevant (pthreads is enabled). +// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and +// ENVIRONMENT_IS_NODE. +if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + try { + scriptDirectory = new URL('.', _scriptName).href; // includes trailing slash + } catch { + // Must be a `blob:` or `data:` URL (e.g. `blob:http://site.com/etc/etc`), we cannot + // infer anything from them. + } + + if (!(globalThis.window || globalThis.WorkerGlobalScope)) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + { +// include: web_or_worker_shell_read.js +if (ENVIRONMENT_IS_WORKER) { + readBinary = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.responseType = 'arraybuffer'; + xhr.send(null); + return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response)); + }; + } + + readAsync = async (url) => { + // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url. + // See https://github.com/github/fetch/pull/92#issuecomment-140665932 + // Cordova or Electron apps are typically loaded from a file:// url. + // So use XHR on webview if URL is a file URL. + if (isFileURI(url)) { + return new Promise((resolve, reject) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = () => { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + resolve(xhr.response); + return; + } + reject(xhr.status); + }; + xhr.onerror = reject; + xhr.send(null); + }); + } + var response = await fetch(url, { credentials: 'same-origin' }); + if (response.ok) { + return response.arrayBuffer(); + } + throw new Error(response.status + ' : ' + response.url); + }; +// end include: web_or_worker_shell_read.js + } +} else +{ + throw new Error('environment detection error'); +} + +var out = console.log.bind(console); +var err = console.error.bind(console); + +var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js'; +var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js'; +var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js'; +var FETCHFS = 'FETCHFS is no longer included by default; build with -lfetchfs.js'; +var ICASEFS = 'ICASEFS is no longer included by default; build with -licasefs.js'; +var JSFILEFS = 'JSFILEFS is no longer included by default; build with -ljsfilefs.js'; +var OPFS = 'OPFS is no longer included by default; build with -lopfs.js'; + +var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js'; + +// perform assertions in shell.js after we set up out() and err(), as otherwise +// if an assertion fails it cannot print the message + +assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.'); + +// end include: shell.js + +// include: preamble.js +// === Preamble library stuff === + +// Documentation for the public APIs defined in this file must be updated in: +// site/source/docs/api_reference/preamble.js.rst +// A prebuilt local version of the documentation is available at: +// site/build/text/docs/api_reference/preamble.js.txt +// You can also build docs locally as HTML or other formats in site/ +// An online HTML version (which may be of a different version of Emscripten) +// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html + +var wasmBinary; + +if (!globalThis.WebAssembly) { + err('no native wasm support detected'); +} + +// Wasm globals + +//======================================== +// Runtime essentials +//======================================== + +// whether we are quitting the application. no code should run after this. +// set in exit() and abort() +var ABORT = false; + +// set by exit() and abort(). Passed to 'onExit' handler. +// NOTE: This is also used as the process return code code in shell environments +// but only when noExitRuntime is false. +var EXITSTATUS; + +// In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we +// don't define it at all in release modes. This matches the behaviour of +// MINIMAL_RUNTIME. +// TODO(sbc): Make this the default even without STRICT enabled. +/** @type {function(*, string=)} */ +function assert(condition, text) { + if (!condition) { + abort('Assertion failed' + (text ? ': ' + text : '')); + } +} + +// We used to include malloc/free by default in the past. Show a helpful error in +// builds with assertions. +function _malloc() { + abort('malloc() called but not included in the build - add `_malloc` to EXPORTED_FUNCTIONS'); +} +function _free() { + // Show a helpful error since we used to include free by default in the past. + abort('free() called but not included in the build - add `_free` to EXPORTED_FUNCTIONS'); +} + +/** + * Indicates whether filename is delivered via file protocol (as opposed to http/https) + * @noinline + */ +var isFileURI = (filename) => filename.startsWith('file://'); + +// include: runtime_common.js +// include: runtime_stack_check.js +// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode. +function writeStackCookie() { + var max = _emscripten_stack_get_end(); + assert((max & 3) == 0); + // If the stack ends at address zero we write our cookies 4 bytes into the + // stack. This prevents interference with SAFE_HEAP and ASAN which also + // monitor writes to address zero. + if (max == 0) { + max += 4; + } + // The stack grow downwards towards _emscripten_stack_get_end. + // We write cookies to the final two words in the stack and detect if they are + // ever overwritten. + HEAPU32[((max)>>2)] = 0x02135467; + HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE; + // Also test the global address 0 for integrity. + HEAPU32[((0)>>2)] = 1668509029; +} + +function checkStackCookie() { + if (ABORT) return; + var max = _emscripten_stack_get_end(); + // See writeStackCookie(). + if (max == 0) { + max += 4; + } + var cookie1 = HEAPU32[((max)>>2)]; + var cookie2 = HEAPU32[(((max)+(4))>>2)]; + if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) { + abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`); + } + // Also test the global address 0 for integrity. + if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) { + abort('Runtime error: The application has corrupted its heap memory area (address zero)!'); + } +} +// end include: runtime_stack_check.js +// include: runtime_exceptions.js +// end include: runtime_exceptions.js +// include: runtime_debug.js +var runtimeDebug = true; // Switch to false at runtime to disable logging at the right times + +// Used by XXXXX_DEBUG settings to output debug messages. +function dbg(...args) { + if (!runtimeDebug && typeof runtimeDebug != 'undefined') return; + // TODO(sbc): Make this configurable somehow. Its not always convenient for + // logging to show up as warnings. + console.warn(...args); +} + +// Endianness check +(() => { + var h16 = new Int16Array(1); + var h8 = new Int8Array(h16.buffer); + h16[0] = 0x6373; + if (h8[0] !== 0x73 || h8[1] !== 0x63) abort('Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)'); +})(); + +function consumedModuleProp(prop) { + if (!Object.getOwnPropertyDescriptor(Module, prop)) { + Object.defineProperty(Module, prop, { + configurable: true, + set() { + abort(`Attempt to set \`Module.${prop}\` after it has already been processed. This can happen, for example, when code is injected via '--post-js' rather than '--pre-js'`); + + } + }); + } +} + +function makeInvalidEarlyAccess(name) { + return () => assert(false, `call to '${name}' via reference taken before Wasm module initialization`); + +} + +function ignoredModuleProp(prop) { + if (Object.getOwnPropertyDescriptor(Module, prop)) { + abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`); + } +} + +// forcing the filesystem exports a few things by default +function isExportedByForceFilesystem(name) { + return name === 'FS_createPath' || + name === 'FS_createDataFile' || + name === 'FS_createPreloadedFile' || + name === 'FS_preloadFile' || + name === 'FS_unlink' || + name === 'addRunDependency' || + // The old FS has some functionality that WasmFS lacks. + name === 'FS_createLazyFile' || + name === 'FS_createDevice' || + name === 'removeRunDependency'; +} + +function missingLibrarySymbol(sym) { + + // Any symbol that is not included from the JS library is also (by definition) + // not exported on the Module object. + unexportedRuntimeSymbol(sym); +} + +function unexportedRuntimeSymbol(sym) { + if (!Object.getOwnPropertyDescriptor(Module, sym)) { + Object.defineProperty(Module, sym, { + configurable: true, + get() { + var msg = `'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + abort(msg); + }, + }); + } +} + +// end include: runtime_debug.js +var readyPromiseResolve, readyPromiseReject; + +// Memory management +var +/** @type {!Int8Array} */ + HEAP8, +/** @type {!Uint8Array} */ + HEAPU8, +/** @type {!Int16Array} */ + HEAP16, +/** @type {!Uint16Array} */ + HEAPU16, +/** @type {!Int32Array} */ + HEAP32, +/** @type {!Uint32Array} */ + HEAPU32, +/** @type {!Float32Array} */ + HEAPF32, +/** @type {!Float64Array} */ + HEAPF64; + +// BigInt64Array type is not correctly defined in closure +var +/** not-@type {!BigInt64Array} */ + HEAP64, +/* BigUint64Array type is not correctly defined in closure +/** not-@type {!BigUint64Array} */ + HEAPU64; + +var runtimeInitialized = false; + + + +function updateMemoryViews() { + var b = wasmMemory.buffer; + HEAP8 = new Int8Array(b); + HEAP16 = new Int16Array(b); + HEAPU8 = new Uint8Array(b); + HEAPU16 = new Uint16Array(b); + HEAP32 = new Int32Array(b); + HEAPU32 = new Uint32Array(b); + HEAPF32 = new Float32Array(b); + HEAPF64 = new Float64Array(b); + HEAP64 = new BigInt64Array(b); + HEAPU64 = new BigUint64Array(b); +} + +// include: memoryprofiler.js +// end include: memoryprofiler.js +// end include: runtime_common.js +assert(globalThis.Int32Array && globalThis.Float64Array && Int32Array.prototype.subarray && Int32Array.prototype.set, + 'JS engine does not provide full typed array support'); + +function preRun() { + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + consumedModuleProp('preRun'); + // Begin ATPRERUNS hooks + callRuntimeCallbacks(onPreRuns); + // End ATPRERUNS hooks +} + +function initRuntime() { + assert(!runtimeInitialized); + runtimeInitialized = true; + + checkStackCookie(); + + // Begin ATINITS hooks + if (!Module['noFSInit'] && !FS.initialized) FS.init(); +TTY.init(); + // End ATINITS hooks + + wasmExports['__wasm_call_ctors'](); + + // Begin ATPOSTCTORS hooks + FS.ignorePermissions = false; + // End ATPOSTCTORS hooks +} + +function preMain() { + checkStackCookie(); + // No ATMAINS hooks +} + +function postRun() { + checkStackCookie(); + // PThreads reuse the runtime from the main thread. + + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + consumedModuleProp('postRun'); + + // Begin ATPOSTRUNS hooks + callRuntimeCallbacks(onPostRuns); + // End ATPOSTRUNS hooks +} + +/** @param {string|number=} what */ +function abort(what) { + Module['onAbort']?.(what); + + what = 'Aborted(' + what + ')'; + // TODO(sbc): Should we remove printing and leave it up to whoever + // catches the exception? + err(what); + + ABORT = true; + + // Use a wasm runtime error, because a JS error might be seen as a foreign + // exception, which means we'd run destructors on it. We need the error to + // simply make the program stop. + // FIXME This approach does not work in Wasm EH because it currently does not assume + // all RuntimeErrors are from traps; it decides whether a RuntimeError is from + // a trap or not based on a hidden field within the object. So at the moment + // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that + // allows this in the wasm spec. + + // Suppress closure compiler warning here. Closure compiler's builtin extern + // definition for WebAssembly.RuntimeError claims it takes no arguments even + // though it can. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed. + /** @suppress {checkTypes} */ + var e = new WebAssembly.RuntimeError(what); + + readyPromiseReject?.(e); + // Throw the error whether or not MODULARIZE is set because abort is used + // in code paths apart from instantiation where an exception is expected + // to be thrown when abort is called. + throw e; +} + +function createExportWrapper(name, nargs) { + return (...args) => { + assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`); + var f = wasmExports[name]; + assert(f, `exported native function \`${name}\` not found`); + // Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled. + assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`); + return f(...args); + }; +} + +var wasmBinaryFile; + +function findWasmBinary() { + return locateFile('rm_lines_simple_renderer.wasm'); +} + +function getBinarySync(file) { + if (file == wasmBinaryFile && wasmBinary) { + return new Uint8Array(wasmBinary); + } + if (readBinary) { + return readBinary(file); + } + // Throwing a plain string here, even though it not normally adviables since + // this gets turning into an `abort` in instantiateArrayBuffer. + throw 'both async and sync fetching of the wasm failed'; +} + +async function getWasmBinary(binaryFile) { + // If we don't have the binary yet, load it asynchronously using readAsync. + if (!wasmBinary) { + // Fetch the binary using readAsync + try { + var response = await readAsync(binaryFile); + return new Uint8Array(response); + } catch { + // Fall back to getBinarySync below; + } + } + + // Otherwise, getBinarySync should be able to get it synchronously + 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}`); + + // Warn on some common problems. + if (isFileURI(binaryFile)) { + err(`warning: Loading from a file URI (${binaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`); + } + abort(reason); + } +} + +async function instantiateAsync(binary, binaryFile, imports) { + if (!binary + // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously. + && !isFileURI(binaryFile) + // Avoid instantiateStreaming() on Node.js environment for now, as while + // Node.js v18.1.0 implements it, it does not have a full fetch() + // implementation yet. + // + // Reference: + // https://github.com/emscripten-core/emscripten/pull/16917 + && !ENVIRONMENT_IS_NODE + ) { + try { + var response = fetch(binaryFile, { credentials: 'same-origin' }); + var instantiationResult = await WebAssembly.instantiateStreaming(response, imports); + return instantiationResult; + } catch (reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + err(`wasm streaming compile failed: ${reason}`); + err('falling back to ArrayBuffer instantiation'); + // fall back of instantiateArrayBuffer below + }; + } + return instantiateArrayBuffer(binaryFile, imports); +} + +function getWasmImports() { + // prepare imports + return { + 'env': wasmImports, + 'wasi_snapshot_preview1': wasmImports, + } +} + +// Create the wasm instance. +// Receives the wasm imports, returns the exports. +async function createWasm() { + // Load the wasm module and create an instance of using native support in the JS engine. + // handle a generated wasm instance, receiving its exports and + // performing other necessary setup + /** @param {WebAssembly.Module=} module*/ + function receiveInstance(instance, module) { + wasmExports = instance.exports; + + + + assignWasmExports(wasmExports); + + updateMemoryViews(); + + return wasmExports; + } + + // Prefer streaming instantiation if available. + // Async compilation can be confusing when an error on the page overwrites Module + // (for example, if the order of elements is wrong, and the one defining Module is + // later), so we save Module and check it later. + var trueModule = Module; + function receiveInstantiationResult(result) { + // 'result' is a ResultObject object which has both the module and instance. + // receiveInstance() will swap in the exports (to Module.asm) so they can be called + assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); + trueModule = null; + // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line. + // When the regression is fixed, can restore the above PTHREADS-enabled path. + return receiveInstance(result['instance']); + } + + var info = getWasmImports(); + + // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback + // to manually instantiate the Wasm module themselves. This allows pages to + // run the instantiation parallel to any other async startup actions they are + // performing. + // Also pthreads and wasm workers initialize the wasm instance through this + // path. + if (Module['instantiateWasm']) { + return new Promise((resolve, reject) => { + try { + Module['instantiateWasm'](info, (inst, mod) => { + resolve(receiveInstance(inst, mod)); + }); + } catch(e) { + err(`Module.instantiateWasm callback failed with error: ${e}`); + reject(e); + } + }); + } + + wasmBinaryFile ??= findWasmBinary(); + var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info); + var exports = receiveInstantiationResult(result); + return exports; +} + +// end include: preamble.js + +// Begin JS library code + + + class ExitStatus { + name = 'ExitStatus'; + constructor(status) { + this.message = `Program terminated with exit(${status})`; + this.status = status; + } + } + + var callRuntimeCallbacks = (callbacks) => { + while (callbacks.length > 0) { + // Pass the module as the first argument. + callbacks.shift()(Module); + } + }; + var onPostRuns = []; + var addOnPostRun = (cb) => onPostRuns.push(cb); + + var onPreRuns = []; + var addOnPreRun = (cb) => onPreRuns.push(cb); + + + + /** + * @param {number} ptr + * @param {string} type + */ + function getValue(ptr, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': return HEAP8[ptr]; + case 'i8': return HEAP8[ptr]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': return HEAP64[((ptr)>>3)]; + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + case '*': return HEAPU32[((ptr)>>2)]; + default: abort(`invalid type for getValue: ${type}`); + } + } + + var noExitRuntime = true; + + var ptrToString = (ptr) => { + assert(typeof ptr === 'number', `ptrToString expects a number, got ${typeof ptr}`); + // Convert to 32-bit unsigned value + ptr >>>= 0; + return '0x' + ptr.toString(16).padStart(8, '0'); + }; + + + /** + * @param {number} ptr + * @param {number} value + * @param {string} type + */ + function setValue(ptr, value, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': HEAP8[ptr] = value; break; + case 'i8': HEAP8[ptr] = value; break; + case 'i16': HEAP16[((ptr)>>1)] = value; break; + case 'i32': HEAP32[((ptr)>>2)] = value; break; + case 'i64': HEAP64[((ptr)>>3)] = BigInt(value); break; + case 'float': HEAPF32[((ptr)>>2)] = value; break; + case 'double': HEAPF64[((ptr)>>3)] = value; break; + case '*': HEAPU32[((ptr)>>2)] = value; break; + default: abort(`invalid type for setValue: ${type}`); + } + } + + var stackRestore = (val) => __emscripten_stack_restore(val); + + var stackSave = () => _emscripten_stack_get_current(); + + var warnOnce = (text) => { + warnOnce.shown ||= {}; + if (!warnOnce.shown[text]) { + warnOnce.shown[text] = 1; + if (ENVIRONMENT_IS_NODE) text = 'warning: ' + text; + err(text); + } + }; + + var UTF8Decoder = globalThis.TextDecoder && new TextDecoder(); + + var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => { + var maxIdx = idx + maxBytesToRead; + if (ignoreNul) return maxIdx; + // TextDecoder needs to know the byte length in advance, it doesn't stop on + // null terminator by itself. + // As a tiny code save trick, compare idx against maxIdx using a negation, + // so that maxBytesToRead=undefined/NaN means Infinity. + while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx; + return idx; + }; + + + /** + * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given + * array that contains uint8 values, returns a copy of that string as a + * Javascript String object. + * heapOrArray is either a regular array, or a JavaScript typed array view. + * @param {number=} idx + * @param {number=} maxBytesToRead + * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character. + * @return {string} + */ + var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => { + + var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul); + + // When using conditional TextDecoder, skip it for short strings as the overhead of the native call is not worth it. + if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { + return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); + } + var str = ''; + while (idx < endPtr) { + // For UTF8 byte structure, see: + // http://en.wikipedia.org/wiki/UTF-8#Description + // https://www.ietf.org/rfc/rfc2279.txt + // https://tools.ietf.org/html/rfc3629 + var u0 = heapOrArray[idx++]; + if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 0xF0) == 0xE0) { + u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; + } else { + if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!'); + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); + } + + if (u0 < 0x10000) { + str += String.fromCharCode(u0); + } else { + var ch = u0 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } + } + return str; + }; + + /** + * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the + * emscripten HEAP, returns a copy of that string as a Javascript String object. + * + * @param {number} ptr + * @param {number=} maxBytesToRead - An optional length that specifies the + * maximum number of bytes to read. You can omit this parameter to scan the + * string until the first 0 byte. If maxBytesToRead is passed, and the string + * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the + * string will cut short at that byte index. + * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character. + * @return {string} + */ + var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => { + assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`); + return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead, ignoreNul) : ''; + }; + var ___assert_fail = (condition, filename, line, func) => + abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); + + class ExceptionInfo { + // excPtr - Thrown object pointer to wrap. Metadata pointer is calculated from it. + constructor(excPtr) { + this.excPtr = excPtr; + this.ptr = excPtr - 24; + } + + set_type(type) { + HEAPU32[(((this.ptr)+(4))>>2)] = type; + } + + get_type() { + return HEAPU32[(((this.ptr)+(4))>>2)]; + } + + set_destructor(destructor) { + HEAPU32[(((this.ptr)+(8))>>2)] = destructor; + } + + get_destructor() { + return HEAPU32[(((this.ptr)+(8))>>2)]; + } + + set_caught(caught) { + caught = caught ? 1 : 0; + HEAP8[(this.ptr)+(12)] = caught; + } + + get_caught() { + return HEAP8[(this.ptr)+(12)] != 0; + } + + set_rethrown(rethrown) { + rethrown = rethrown ? 1 : 0; + HEAP8[(this.ptr)+(13)] = rethrown; + } + + get_rethrown() { + return HEAP8[(this.ptr)+(13)] != 0; + } + + // Initialize native structure fields. Should be called once after allocated. + init(type, destructor) { + this.set_adjusted_ptr(0); + this.set_type(type); + this.set_destructor(destructor); + } + + set_adjusted_ptr(adjustedPtr) { + HEAPU32[(((this.ptr)+(16))>>2)] = adjustedPtr; + } + + get_adjusted_ptr() { + return HEAPU32[(((this.ptr)+(16))>>2)]; + } + } + + var exceptionLast = 0; + + var uncaughtExceptionCount = 0; + var ___cxa_throw = (ptr, type, destructor) => { + var info = new ExceptionInfo(ptr); + // Initialize ExceptionInfo content after it was allocated in __cxa_allocate_exception. + info.init(type, destructor); + exceptionLast = ptr; + uncaughtExceptionCount++; + assert(false, 'Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.'); + }; + + /** @suppress {duplicate } */ + var syscallGetVarargI = () => { + assert(SYSCALLS.varargs != undefined); + // the `+` prepended here is necessary to convince the JSCompiler that varargs is indeed a number. + 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) => { + // if the path tries to go above the root, `up` ends up > 0 + 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 the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up; up--) { + parts.unshift('..'); + } + } + return parts; + }, + normalize:(path) => { + var isAbsolute = PATH.isAbs(path), + trailingSlash = path.slice(-1) === '/'; + // Normalize the path + 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) { + // No dirname whatsoever + return '.'; + } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.slice(0, -1); + } + return root + dir; + }, + basename:(path) => path && path.match(/([^\/]+|\/)\/*$/)[1], + join:(...paths) => PATH.normalize(paths.join('/')), + join2:(l, r) => PATH.normalize(l + '/' + r), + }; + + var initRandomFill = () => { + // This block is not needed on v19+ since crypto.getRandomValues is builtin + if (ENVIRONMENT_IS_NODE) { + var nodeCrypto = require('crypto'); + return (view) => nodeCrypto.randomFillSync(view); + } + + return (view) => crypto.getRandomValues(view); + }; + var randomFill = (view) => { + // Lazily init on the first invocation. + (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(); + // Skip empty and invalid entries + if (typeof path != 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + return ''; // an invalid portion invalidates the whole thing + } + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = PATH.isAbs(path); + } + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter((p) => !!p), !resolvedAbsolute).join('/'); + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + }, + relative:(from, to) => { + from = PATH_FS.resolve(from).slice(1); + to = PATH_FS.resolve(to).slice(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 FS_stdin_getChar_buffer = []; + + var lengthBytesUTF8 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var c = str.charCodeAt(i); // possibly a lead surrogate + if (c <= 0x7F) { + len++; + } else if (c <= 0x7FF) { + len += 2; + } else if (c >= 0xD800 && c <= 0xDFFF) { + len += 4; ++i; + } else { + len += 3; + } + } + return len; + }; + + var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + assert(typeof str === 'string', `stringToUTF8Array expects a string (got ${typeof str})`); + // Parameter maxBytesToWrite is not optional. Negative values, 0, null, + // undefined and false each don't write out any bytes. + if (!(maxBytesToWrite > 0)) + return 0; + + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. + for (var i = 0; i < str.length; ++i) { + // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description + // and https://www.ietf.org/rfc/rfc2279.txt + // and https://tools.ietf.org/html/rfc3629 + var u = str.codePointAt(i); + if (u <= 0x7F) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 0x7FF) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 0xC0 | (u >> 6); + heap[outIdx++] = 0x80 | (u & 63); + } else if (u <= 0xFFFF) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 0xE0 | (u >> 12); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } else { + if (outIdx + 3 >= endIdx) break; + if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).'); + heap[outIdx++] = 0xF0 | (u >> 18); + heap[outIdx++] = 0x80 | ((u >> 12) & 63); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16. + // We need to manually skip over the second code unit for correct iteration. + i++; + } + } + // Null-terminate the pointer to the buffer. + heap[outIdx] = 0; + return outIdx - startIdx; + }; + /** @type {function(string, boolean=, number=)} */ + var 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 (ENVIRONMENT_IS_NODE) { + // we will read data by chunks of BUFSIZE + var BUFSIZE = 256; + var buf = Buffer.alloc(BUFSIZE); + var bytesRead = 0; + + // For some reason we must suppress a closure warning here, even though + // fd definitely exists on process.stdin, and is even the proper way to + // get the fd of stdin, + // https://github.com/nodejs/help/issues/2136#issuecomment-523649904 + // This started to happen after moving this logic out of library_tty.js, + // so it is related to the surrounding code in some unclear manner. + /** @suppress {missingProperties} */ + var fd = process.stdin.fd; + + try { + bytesRead = fs.readSync(fd, buf, 0, BUFSIZE); + } catch(e) { + // Cross-platform differences: on Windows, reading EOF throws an + // exception, but on other OSes, reading EOF returns 0. Uniformize + // behavior by treating the EOF exception to return 0. + if (e.toString().includes('EOF')) bytesRead = 0; + else throw e; + } + + if (bytesRead > 0) { + result = buf.slice(0, bytesRead).toString('utf-8'); + } + } else + if (globalThis.window?.prompt) { + // Browser. + result = window.prompt('Input: '); // returns null on cancel + 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() { + // https://github.com/emscripten-core/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // currently, FS.init does not distinguish if process.stdin is a file or TTY + // // device, it always assumes it's a TTY device. because of this, we're forcing + // // process.stdin to UTF8 encoding to at least make stdin reading compatible + // // with text files until FS.init can be refactored. + // process.stdin.setEncoding('utf8'); + // } + }, + shutdown() { + // https://github.com/emscripten-core/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? + // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation + // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists? + // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle + // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call + // process.stdin.pause(); + // } + }, + register(dev, ops) { + TTY.ttys[dev] = { input: [], output: [], ops: 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) { + // flush any pending line data + stream.tty.ops.fsync(stream.tty); + }, + fsync(stream) { + stream.tty.ops.fsync(stream.tty); + }, + read(stream, buffer, offset, length, pos /* ignored */) { + 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); // val == 0 would cut text output off in the middle. + } + }, + fsync(tty) { + if (tty.output?.length > 0) { + out(UTF8ArrayToString(tty.output)); + tty.output = []; + } + }, + ioctl_tcgets(tty) { + // typical setting + return { + c_iflag: 25856, + c_oflag: 5, + c_cflag: 191, + c_lflag: 35387, + c_cc: [ + 0x03, 0x1c, 0x7f, 0x15, 0x04, 0x00, 0x01, 0x00, 0x11, 0x13, 0x1a, 0x00, + 0x12, 0x0f, 0x17, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + }; + }, + ioctl_tcsets(tty, optional_actions, data) { + // currently just ignore + 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?.length > 0) { + err(UTF8ArrayToString(tty.output)); + tty.output = []; + } + }, + }, + }; + + + var mmapAlloc = (size) => { + abort('internal error: mmapAlloc called but `emscripten_builtin_memalign` native symbol not exported'); + }; + 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)) { + // no supported + 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, + 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; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity. + // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred + // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size + // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme. + 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(); + // add the new node to the parent + 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); // Make sure to not return excess unused bytes. + return new Uint8Array(node.contents); + }, + expandFileStorage(node, newCapacity) { + var prevCapacity = node.contents ? node.contents.length : 0; + if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough. + // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity. + // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to + // avoid overshooting the allocation cap by a very large margin. + var CAPACITY_DOUBLING_MAX = 1024 * 1024; + newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0); + if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding. + var oldContents = node.contents; + node.contents = new Uint8Array(newCapacity); // Allocate new storage. + if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage. + }, + resizeFileStorage(node, newSize) { + if (node.usedBytes == newSize) return; + if (newSize == 0) { + node.contents = null; // Fully decommit when requesting a resize to zero. + node.usedBytes = 0; + } else { + var oldContents = node.contents; + node.contents = new Uint8Array(newSize); // Allocate new storage. + if (oldContents) { + node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage. + } + node.usedBytes = newSize; + } + }, + node_ops:{ + getattr(node) { + var attr = {}; + // device numbers reuse inode numbers. + 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); + // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), + // but this is not required by the standard. + 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] != null) { + node[key] = attr[key]; + } + } + if (attr.size !== undefined) { + MEMFS.resizeFileStorage(node, attr.size); + } + }, + lookup(parent, name) { + throw new FS.ErrnoError(44); + }, + 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)) { + // if we're overwriting a directory at new_name, make sure it's empty. + for (var i in new_node.contents) { + throw new FS.ErrnoError(55); + } + } + FS.hashRemoveNode(new_node); + } + // do the internal rewiring + 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, 0o777 | 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); + assert(size >= 0); + if (size > 8 && contents.subarray) { // non-trivial, and typed array + 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) { + // The data buffer should be a typed array view + assert(!(buffer instanceof ArrayBuffer)); + // If the buffer is located in main memory (HEAP), and if + // memory can grow, we can't hold on to references of the + // memory buffer, as they may get invalidated. That means we + // need to do copy its contents. + 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)) { // This write is from a typed array to a typed array? + if (canOwn) { + assert(position === 0, 'canOwn must imply no weird position inside the file'); + node.contents = buffer.subarray(offset, offset + length); + node.usedBytes = length; + return length; + } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data. + node.contents = buffer.slice(offset, offset + length); + node.usedBytes = length; + return length; + } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file? + node.contents.set(buffer.subarray(offset, offset + length), position); + return length; + } + } + + // Appending to an existing file and we need to reallocate, or source data did not come as a typed array. + MEMFS.expandFileStorage(node, position+length); + if (node.contents.subarray && buffer.subarray) { + // Use typed array write which is available. + node.contents.set(buffer.subarray(offset, offset + length), position); + } else { + for (var i = 0; i < length; i++) { + node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not. + } + } + node.usedBytes = Math.max(node.usedBytes, position + length); + return length; + }, + llseek(stream, offset, whence) { + var position = offset; + if (whence === 1) { + position += stream.position; + } else if (whence === 2) { + if (FS.isFile(stream.node.mode)) { + position += stream.node.usedBytes; + } + } + if (position < 0) { + throw new FS.ErrnoError(28); + } + return position; + }, + mmap(stream, length, position, prot, flags) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + var ptr; + var allocated; + var contents = stream.node.contents; + // Only make a new copy when MAP_PRIVATE is specified. + if (!(flags & 2) && contents && contents.buffer === HEAP8.buffer) { + // We can't emulate MAP_SHARED when the file is not backed by the + // buffer we're mapping to (e.g. the HEAP buffer). + allocated = false; + ptr = contents.byteOffset; + } else { + allocated = true; + ptr = mmapAlloc(length); + if (!ptr) { + throw new FS.ErrnoError(48); + } + if (contents) { + // Try to avoid unnecessary slices. + if (position > 0 || position + length < contents.length) { + if (contents.subarray) { + contents = contents.subarray(position, position + length); + } else { + contents = Array.prototype.slice.call(contents, position, position + length); + } + } + HEAP8.set(contents, ptr); + } + } + return { ptr, allocated }; + }, + msync(stream, buffer, offset, length, mmapFlags) { + MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false); + // should we check if bytesWritten and length are the same? + return 0; + }, + }, + }; + + var FS_modeStringToFlags = (str) => { + var flagModes = { + 'r': 0, + 'r+': 2, + 'w': 512 | 64 | 1, + 'w+': 512 | 64 | 2, + 'a': 1024 | 64 | 1, + 'a+': 1024 | 64 | 2, + }; + var flags = flagModes[str]; + if (typeof flags == 'undefined') { + throw new Error(`Unknown file open mode: ${str}`); + } + return flags; + }; + + var FS_getMode = (canRead, canWrite) => { + var mode = 0; + if (canRead) mode |= 292 | 73; + if (canWrite) mode |= 146; + return mode; + }; + + + + + var strError = (errno) => UTF8ToString(_strerror(errno)); + + var ERRNO_CODES = { + 'EPERM': 63, + 'ENOENT': 44, + 'ESRCH': 71, + 'EINTR': 27, + 'EIO': 29, + 'ENXIO': 60, + 'E2BIG': 1, + 'ENOEXEC': 45, + 'EBADF': 8, + 'ECHILD': 12, + 'EAGAIN': 6, + 'EWOULDBLOCK': 6, + 'ENOMEM': 48, + 'EACCES': 2, + 'EFAULT': 21, + 'ENOTBLK': 105, + 'EBUSY': 10, + 'EEXIST': 20, + 'EXDEV': 75, + 'ENODEV': 43, + 'ENOTDIR': 54, + 'EISDIR': 31, + 'EINVAL': 28, + 'ENFILE': 41, + 'EMFILE': 33, + 'ENOTTY': 59, + 'ETXTBSY': 74, + 'EFBIG': 22, + 'ENOSPC': 51, + 'ESPIPE': 70, + 'EROFS': 69, + 'EMLINK': 34, + 'EPIPE': 64, + 'EDOM': 18, + 'ERANGE': 68, + 'ENOMSG': 49, + 'EIDRM': 24, + 'ECHRNG': 106, + 'EL2NSYNC': 156, + 'EL3HLT': 107, + 'EL3RST': 108, + 'ELNRNG': 109, + 'EUNATCH': 110, + 'ENOCSI': 111, + 'EL2HLT': 112, + 'EDEADLK': 16, + 'ENOLCK': 46, + 'EBADE': 113, + 'EBADR': 114, + 'EXFULL': 115, + 'ENOANO': 104, + 'EBADRQC': 103, + 'EBADSLT': 102, + 'EDEADLOCK': 16, + 'EBFONT': 101, + 'ENOSTR': 100, + 'ENODATA': 116, + 'ETIME': 117, + 'ENOSR': 118, + 'ENONET': 119, + 'ENOPKG': 120, + 'EREMOTE': 121, + 'ENOLINK': 47, + 'EADV': 122, + 'ESRMNT': 123, + 'ECOMM': 124, + 'EPROTO': 65, + 'EMULTIHOP': 36, + 'EDOTDOT': 125, + 'EBADMSG': 9, + 'ENOTUNIQ': 126, + 'EBADFD': 127, + 'EREMCHG': 128, + 'ELIBACC': 129, + 'ELIBBAD': 130, + 'ELIBSCN': 131, + 'ELIBMAX': 132, + 'ELIBEXEC': 133, + 'ENOSYS': 52, + 'ENOTEMPTY': 55, + 'ENAMETOOLONG': 37, + 'ELOOP': 32, + 'EOPNOTSUPP': 138, + 'EPFNOSUPPORT': 139, + 'ECONNRESET': 15, + 'ENOBUFS': 42, + 'EAFNOSUPPORT': 5, + 'EPROTOTYPE': 67, + 'ENOTSOCK': 57, + 'ENOPROTOOPT': 50, + 'ESHUTDOWN': 140, + 'ECONNREFUSED': 14, + 'EADDRINUSE': 3, + 'ECONNABORTED': 13, + 'ENETUNREACH': 40, + 'ENETDOWN': 38, + 'ETIMEDOUT': 73, + 'EHOSTDOWN': 142, + 'EHOSTUNREACH': 23, + 'EINPROGRESS': 26, + 'EALREADY': 7, + 'EDESTADDRREQ': 17, + 'EMSGSIZE': 35, + 'EPROTONOSUPPORT': 66, + 'ESOCKTNOSUPPORT': 137, + 'EADDRNOTAVAIL': 4, + 'ENETRESET': 39, + 'EISCONN': 30, + 'ENOTCONN': 53, + 'ETOOMANYREFS': 141, + 'EUSERS': 136, + 'EDQUOT': 19, + 'ESTALE': 72, + 'ENOTSUP': 138, + 'ENOMEDIUM': 148, + 'EILSEQ': 25, + 'EOVERFLOW': 61, + 'ECANCELED': 11, + 'ENOTRECOVERABLE': 56, + 'EOWNERDEAD': 62, + 'ESTRPIPE': 135, + }; + + var asyncLoad = async (url) => { + var arrayBuffer = await readAsync(url); + assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`); + return new Uint8Array(arrayBuffer); + }; + + + var FS_createDataFile = (...args) => FS.createDataFile(...args); + + var getUniqueRunDependency = (id) => { + var orig = id; + while (1) { + if (!runDependencyTracking[id]) return id; + id = orig + Math.random(); + } + }; + + var runDependencies = 0; + + + var dependenciesFulfilled = null; + + var runDependencyTracking = { + }; + + var runDependencyWatcher = null; + var removeRunDependency = (id) => { + runDependencies--; + + Module['monitorRunDependencies']?.(runDependencies); + + assert(id, 'removeRunDependency requires an ID'); + assert(runDependencyTracking[id]); + delete runDependencyTracking[id]; + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } + }; + + + var addRunDependency = (id) => { + runDependencies++; + + Module['monitorRunDependencies']?.(runDependencies); + + assert(id, 'addRunDependency requires an ID') + assert(!runDependencyTracking[id]); + runDependencyTracking[id] = 1; + if (runDependencyWatcher === null && globalThis.setInterval) { + // Check for missing dependencies every few seconds + runDependencyWatcher = setInterval(() => { + if (ABORT) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + return; + } + var shown = false; + for (var dep in runDependencyTracking) { + if (!shown) { + shown = true; + err('still waiting on run dependencies:'); + } + err(`dependency: ${dep}`); + } + if (shown) { + err('(end of list)'); + } + }, 10000); + // Prevent this timer from keeping the runtime alive if nothing + // else is. + runDependencyWatcher.unref?.() + } + }; + + + var preloadPlugins = []; + var FS_handledByPreloadPlugin = async (byteArray, fullname) => { + // Ensure plugins are ready. + if (typeof Browser != 'undefined') Browser.init(); + + for (var plugin of preloadPlugins) { + if (plugin['canHandle'](fullname)) { + assert(plugin['handle'].constructor.name === 'AsyncFunction', 'Filesystem plugin handlers must be async functions (See #24914)') + return plugin['handle'](byteArray, fullname); + } + } + // In no plugin handled this file then return the original/unmodified + // byteArray. + return byteArray; + }; + var FS_preloadFile = async (parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish) => { + // TODO we should allow people to just pass in a complete filename instead + // of parent and name being that we just join them anyways + var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent; + var dep = getUniqueRunDependency(`cp ${fullname}`); // might have several active requests for the same fullname + addRunDependency(dep); + + try { + var byteArray = url; + if (typeof url == 'string') { + byteArray = await asyncLoad(url); + } + + byteArray = await FS_handledByPreloadPlugin(byteArray, fullname); + preFinish?.(); + if (!dontCreateFile) { + FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + } + } finally { + removeRunDependency(dep); + } + }; + var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => { + FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror); + }; + var FS = { + root:null, + mounts:[], + devices:{ + }, + streams:[], + nextInode:1, + nameTable:null, + currentPath:"/", + initialized:false, + ignorePermissions:true, + filesystems:null, + syncFSRequests:0, + readFiles:{ + }, + ErrnoError:class extends Error { + name = 'ErrnoError'; + // We set the `name` property to be able to identify `FS.ErrnoError` + // - the `name` is a standard ECMA-262 property of error objects. Kind of good to have it anyway. + // - when using PROXYFS, an error can come from an underlying FS + // as different FS objects have their own FS.ErrnoError each, + // the test `err instanceof FS.ErrnoError` won't detect an error coming from another filesystem, causing bugs. + // we'll use the reliable test `err.name == "ErrnoError"` instead + constructor(errno) { + super(runtimeInitialized ? strError(errno) : ''); + this.errno = errno; + for (var key in ERRNO_CODES) { + if (ERRNO_CODES[key] === errno) { + this.code = key; + break; + } + } + } + }, + FSStream:class { + shared = {}; + get object() { + return this.node; + } + set object(val) { + this.node = val; + } + get isRead() { + return (this.flags & 2097155) !== 1; + } + get isWrite() { + return (this.flags & 2097155) !== 0; + } + get isAppend() { + return (this.flags & 1024); + } + get flags() { + return this.shared.flags; + } + set flags(val) { + this.shared.flags = val; + } + get position() { + return this.shared.position; + } + set position(val) { + this.shared.position = val; + } + }, + FSNode:class { + node_ops = {}; + stream_ops = {}; + readMode = 292 | 73; + writeMode = 146; + mounted = null; + constructor(parent, name, mode, rdev) { + if (!parent) { + parent = this; // root node sets parent to itself + } + this.parent = parent; + this.mount = parent.mount; + this.id = FS.nextInode++; + this.name = name; + this.mode = mode; + this.rdev = rdev; + this.atime = this.mtime = this.ctime = Date.now(); + } + get read() { + return (this.mode & this.readMode) === this.readMode; + } + set read(val) { + val ? this.mode |= this.readMode : this.mode &= ~this.readMode; + } + get write() { + return (this.mode & this.writeMode) === this.writeMode; + } + set write(val) { + val ? this.mode |= this.writeMode : this.mode &= ~this.writeMode; + } + get isFolder() { + return FS.isDir(this.mode); + } + get isDevice() { + return FS.isChrdev(this.mode); + } + }, + lookupPath(path, opts = {}) { + if (!path) { + throw new FS.ErrnoError(44); + } + opts.follow_mount ??= true + + if (!PATH.isAbs(path)) { + path = FS.cwd() + '/' + path; + } + + // limit max consecutive symlinks to 40 (SYMLOOP_MAX). + linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) { + // split the absolute path + var parts = path.split('/').filter((p) => !!p); + + // start at the root + var current = FS.root; + var current_path = '/'; + + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + // stop resolving + break; + } + + if (parts[i] === '.') { + continue; + } + + if (parts[i] === '..') { + current_path = PATH.dirname(current_path); + if (FS.isRoot(current)) { + path = current_path + '/' + parts.slice(i + 1).join('/'); + // We're making progress here, don't let many consecutive ..'s + // lead to ELOOP + nlinks--; + continue linkloop; + } else { + current = current.parent; + } + continue; + } + + current_path = PATH.join2(current_path, parts[i]); + try { + current = FS.lookupNode(current, parts[i]); + } catch (e) { + // if noent_okay is true, suppress a ENOENT in the last component + // and return an object with an undefined node. This is needed for + // resolving symlinks in the path when creating a file. + if ((e?.errno === 44) && islast && opts.noent_okay) { + return { path: current_path }; + } + throw e; + } + + // jump to the mount's root node if this is a mountpoint + if (FS.isMountpoint(current) && (!islast || opts.follow_mount)) { + current = current.mounted.root; + } + + // by default, lookupPath will not follow a symlink if it is the final path component. + // setting opts.follow = true will override this behavior. + if (FS.isLink(current.mode) && (!islast || opts.follow)) { + if (!current.node_ops.readlink) { + throw new FS.ErrnoError(52); + } + var link = current.node_ops.readlink(current); + if (!PATH.isAbs(link)) { + link = PATH.dirname(current_path) + '/' + link; + } + path = link + '/' + parts.slice(i + 1).join('/'); + continue linkloop; + } + } + return { path: current_path, node: current }; + } + throw new FS.ErrnoError(32); + }, + getPath(node) { + var path; + while (true) { + if (FS.isRoot(node)) { + var mount = node.mount.mountpoint; + if (!path) return mount; + return mount[mount.length-1] !== '/' ? `${mount}/${path}` : mount + path; + } + path = path ? `${node.name}/${path}` : node.name; + node = node.parent; + } + }, + hashName(parentid, name) { + var hash = 0; + + for (var i = 0; i < name.length; i++) { + hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; + } + return ((parentid + hash) >>> 0) % FS.nameTable.length; + }, + hashAddNode(node) { + var hash = FS.hashName(node.parent.id, node.name); + node.name_next = FS.nameTable[hash]; + FS.nameTable[hash] = node; + }, + hashRemoveNode(node) { + var hash = FS.hashName(node.parent.id, node.name); + if (FS.nameTable[hash] === node) { + FS.nameTable[hash] = node.name_next; + } else { + var current = FS.nameTable[hash]; + while (current) { + if (current.name_next === node) { + current.name_next = node.name_next; + break; + } + current = current.name_next; + } + } + }, + lookupNode(parent, name) { + var errCode = FS.mayLookup(parent); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + var hash = FS.hashName(parent.id, name); + for (var node = FS.nameTable[hash]; node; node = node.name_next) { + var nodeName = node.name; + if (node.parent.id === parent.id && nodeName === name) { + return node; + } + } + // if we failed to find it in the cache, call into the VFS + return FS.lookup(parent, name); + }, + createNode(parent, name, mode, rdev) { + assert(typeof parent == 'object') + var node = new FS.FSNode(parent, name, mode, rdev); + + FS.hashAddNode(node); + + return node; + }, + destroyNode(node) { + FS.hashRemoveNode(node); + }, + isRoot(node) { + return node === node.parent; + }, + isMountpoint(node) { + return !!node.mounted; + }, + isFile(mode) { + return (mode & 61440) === 32768; + }, + isDir(mode) { + return (mode & 61440) === 16384; + }, + isLink(mode) { + return (mode & 61440) === 40960; + }, + isChrdev(mode) { + return (mode & 61440) === 8192; + }, + isBlkdev(mode) { + return (mode & 61440) === 24576; + }, + isFIFO(mode) { + return (mode & 61440) === 4096; + }, + isSocket(mode) { + return (mode & 49152) === 49152; + }, + flagsToPermissionString(flag) { + var perms = ['r', 'w', 'rw'][flag & 3]; + if ((flag & 512)) { + perms += 'w'; + } + return perms; + }, + nodePermissions(node, perms) { + if (FS.ignorePermissions) { + return 0; + } + // return 0 if any user, group or owner bits are set. + if (perms.includes('r') && !(node.mode & 292)) { + return 2; + } else if (perms.includes('w') && !(node.mode & 146)) { + return 2; + } else if (perms.includes('x') && !(node.mode & 73)) { + return 2; + } + return 0; + }, + mayLookup(dir) { + if (!FS.isDir(dir.mode)) return 54; + var errCode = FS.nodePermissions(dir, 'x'); + if (errCode) return errCode; + if (!dir.node_ops.lookup) return 2; + return 0; + }, + mayCreate(dir, name) { + if (!FS.isDir(dir.mode)) { + return 54; + } + try { + var node = FS.lookupNode(dir, name); + return 20; + } catch (e) { + } + return FS.nodePermissions(dir, 'wx'); + }, + mayDelete(dir, name, isdir) { + var node; + try { + node = FS.lookupNode(dir, name); + } catch (e) { + return e.errno; + } + var errCode = FS.nodePermissions(dir, 'wx'); + if (errCode) { + return errCode; + } + if (isdir) { + if (!FS.isDir(node.mode)) { + return 54; + } + if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { + return 10; + } + } else { + if (FS.isDir(node.mode)) { + return 31; + } + } + return 0; + }, + mayOpen(node, flags) { + if (!node) { + return 44; + } + if (FS.isLink(node.mode)) { + return 32; + } else if (FS.isDir(node.mode)) { + if (FS.flagsToPermissionString(flags) !== 'r' // opening for write + || (flags & (512 | 64))) { // TODO: check for O_SEARCH? (== search for dir only) + return 31; + } + } + return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); + }, + checkOpExists(op, err) { + if (!op) { + throw new FS.ErrnoError(err); + } + return op; + }, + MAX_OPEN_FDS:4096, + nextfd() { + for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) { + if (!FS.streams[fd]) { + return fd; + } + } + throw new FS.ErrnoError(33); + }, + getStreamChecked(fd) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(8); + } + return stream; + }, + getStream:(fd) => FS.streams[fd], + createStream(stream, fd = -1) { + assert(fd >= -1); + + // clone it, so we can return an instance of FSStream + stream = Object.assign(new FS.FSStream(), stream); + if (fd == -1) { + fd = FS.nextfd(); + } + stream.fd = fd; + FS.streams[fd] = stream; + return stream; + }, + closeStream(fd) { + FS.streams[fd] = null; + }, + dupStream(origStream, fd = -1) { + var stream = FS.createStream(origStream, fd); + stream.stream_ops?.dup?.(stream); + return stream; + }, + doSetAttr(stream, node, attr) { + var setattr = stream?.stream_ops.setattr; + var arg = setattr ? stream : node; + setattr ??= node.node_ops.setattr; + FS.checkOpExists(setattr, 63) + setattr(arg, attr); + }, + chrdev_stream_ops:{ + open(stream) { + var device = FS.getDevice(stream.node.rdev); + // override node's stream ops with the device's + stream.stream_ops = device.stream_ops; + // forward the open call + stream.stream_ops.open?.(stream); + }, + llseek() { + throw new FS.ErrnoError(70); + }, + }, + major:(dev) => ((dev) >> 8), + minor:(dev) => ((dev) & 0xff), + makedev:(ma, mi) => ((ma) << 8 | (mi)), + registerDevice(dev, ops) { + FS.devices[dev] = { stream_ops: ops }; + }, + getDevice:(dev) => FS.devices[dev], + getMounts(mount) { + var mounts = []; + var check = [mount]; + + while (check.length) { + var m = check.pop(); + + mounts.push(m); + + check.push(...m.mounts); + } + + return mounts; + }, + syncfs(populate, callback) { + if (typeof populate == 'function') { + callback = populate; + populate = false; + } + + FS.syncFSRequests++; + + if (FS.syncFSRequests > 1) { + err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`); + } + + var mounts = FS.getMounts(FS.root.mount); + var completed = 0; + + function doCallback(errCode) { + assert(FS.syncFSRequests > 0); + FS.syncFSRequests--; + return callback(errCode); + } + + function done(errCode) { + if (errCode) { + if (!done.errored) { + done.errored = true; + return doCallback(errCode); + } + return; + } + if (++completed >= mounts.length) { + doCallback(null); + } + }; + + // sync all mounts + mounts.forEach((mount) => { + if (!mount.type.syncfs) { + return done(null); + } + mount.type.syncfs(mount, populate, done); + }); + }, + mount(type, opts, mountpoint) { + if (typeof type == 'string') { + // The filesystem was not included, and instead we have an error + // message stored in the variable. + throw type; + } + var root = mountpoint === '/'; + var pseudo = !mountpoint; + var node; + + if (root && FS.root) { + throw new FS.ErrnoError(10); + } else if (!root && !pseudo) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + mountpoint = lookup.path; // use the absolute path + node = lookup.node; + + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + + if (!FS.isDir(node.mode)) { + throw new FS.ErrnoError(54); + } + } + + var mount = { + type, + opts, + mountpoint, + mounts: [] + }; + + // create a root node for the fs + var mountRoot = type.mount(mount); + mountRoot.mount = mount; + mount.root = mountRoot; + + if (root) { + FS.root = mountRoot; + } else if (node) { + // set as a mountpoint + node.mounted = mount; + + // add the new mount to the current mount's children + if (node.mount) { + node.mount.mounts.push(mount); + } + } + + return mountRoot; + }, + unmount(mountpoint) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + if (!FS.isMountpoint(lookup.node)) { + throw new FS.ErrnoError(28); + } + + // destroy the nodes for this mount, and all its child mounts + var node = lookup.node; + var mount = node.mounted; + var mounts = FS.getMounts(mount); + + Object.keys(FS.nameTable).forEach((hash) => { + var current = FS.nameTable[hash]; + + while (current) { + var next = current.name_next; + + if (mounts.includes(current.mount)) { + FS.destroyNode(current); + } + + current = next; + } + }); + + // no longer a mountpoint + node.mounted = null; + + // remove this mount from the child mounts + var idx = node.mount.mounts.indexOf(mount); + assert(idx !== -1); + node.mount.mounts.splice(idx, 1); + }, + lookup(parent, name) { + return parent.node_ops.lookup(parent, name); + }, + mknod(path, mode, dev) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + if (!name) { + throw new FS.ErrnoError(28); + } + if (name === '.' || name === '..') { + throw new FS.ErrnoError(20); + } + var errCode = FS.mayCreate(parent, name); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.mknod) { + throw new FS.ErrnoError(63); + } + return parent.node_ops.mknod(parent, name, mode, dev); + }, + statfs(path) { + return FS.statfsNode(FS.lookupPath(path, {follow: true}).node); + }, + statfsStream(stream) { + // We keep a separate statfsStream function because noderawfs overrides + // it. In noderawfs, stream.node is sometimes null. Instead, we need to + // look at stream.path. + return FS.statfsNode(stream.node); + }, + statfsNode(node) { + // NOTE: None of the defaults here are true. We're just returning safe and + // sane values. Currently nodefs and rawfs replace these defaults, + // other file systems leave them alone. + var rtn = { + bsize: 4096, + frsize: 4096, + blocks: 1e6, + bfree: 5e5, + bavail: 5e5, + files: FS.nextInode, + ffree: FS.nextInode - 1, + fsid: 42, + flags: 2, + namelen: 255, + }; + + if (node.node_ops.statfs) { + Object.assign(rtn, node.node_ops.statfs(node.mount.opts.root)); + } + return rtn; + }, + create(path, mode = 0o666) { + mode &= 4095; + mode |= 32768; + return FS.mknod(path, mode, 0); + }, + mkdir(path, mode = 0o777) { + mode &= 511 | 512; + mode |= 16384; + return FS.mknod(path, mode, 0); + }, + mkdirTree(path, mode) { + var dirs = path.split('/'); + var d = ''; + for (var dir of dirs) { + if (!dir) continue; + if (d || PATH.isAbs(path)) d += '/'; + d += dir; + try { + FS.mkdir(d, mode); + } catch(e) { + if (e.errno != 20) throw e; + } + } + }, + mkdev(path, mode, dev) { + if (typeof dev == 'undefined') { + dev = mode; + mode = 0o666; + } + mode |= 8192; + return FS.mknod(path, mode, dev); + }, + symlink(oldpath, newpath) { + if (!PATH_FS.resolve(oldpath)) { + throw new FS.ErrnoError(44); + } + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var newname = PATH.basename(newpath); + var errCode = FS.mayCreate(parent, newname); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.symlink) { + throw new FS.ErrnoError(63); + } + return parent.node_ops.symlink(parent, newname, oldpath); + }, + rename(old_path, new_path) { + var old_dirname = PATH.dirname(old_path); + var new_dirname = PATH.dirname(new_path); + var old_name = PATH.basename(old_path); + var new_name = PATH.basename(new_path); + // parents must exist + var lookup, old_dir, new_dir; + + // let the errors from non existent directories percolate up + lookup = FS.lookupPath(old_path, { parent: true }); + old_dir = lookup.node; + lookup = FS.lookupPath(new_path, { parent: true }); + new_dir = lookup.node; + + if (!old_dir || !new_dir) throw new FS.ErrnoError(44); + // need to be part of the same mount + if (old_dir.mount !== new_dir.mount) { + throw new FS.ErrnoError(75); + } + // source must exist + var old_node = FS.lookupNode(old_dir, old_name); + // old path should not be an ancestor of the new path + var relative = PATH_FS.relative(old_path, new_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(28); + } + // new path should not be an ancestor of the old path + relative = PATH_FS.relative(new_path, old_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(55); + } + // see if the new path already exists + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + // not fatal + } + // early out if nothing needs to change + if (old_node === new_node) { + return; + } + // we'll need to delete the old entry + var isdir = FS.isDir(old_node.mode); + var errCode = FS.mayDelete(old_dir, old_name, isdir); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + // need delete permissions if we'll be overwriting. + // need create permissions if new doesn't already exist. + errCode = new_node ? + FS.mayDelete(new_dir, new_name, isdir) : + FS.mayCreate(new_dir, new_name); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!old_dir.node_ops.rename) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) { + throw new FS.ErrnoError(10); + } + // if we are going to change the parent, check write permissions + if (new_dir !== old_dir) { + errCode = FS.nodePermissions(old_dir, 'w'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + } + // remove the node from the lookup hash + FS.hashRemoveNode(old_node); + // do the underlying fs rename + try { + old_dir.node_ops.rename(old_node, new_dir, new_name); + // update old node (we do this here to avoid each backend + // needing to) + old_node.parent = new_dir; + } catch (e) { + throw e; + } finally { + // add the node back to the hash (in case node_ops.rename + // changed its name) + FS.hashAddNode(old_node); + } + }, + rmdir(path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var errCode = FS.mayDelete(parent, name, true); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.rmdir) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + parent.node_ops.rmdir(parent, name); + FS.destroyNode(node); + }, + readdir(path) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + var readdir = FS.checkOpExists(node.node_ops.readdir, 54); + return readdir(node); + }, + unlink(path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var errCode = FS.mayDelete(parent, name, false); + if (errCode) { + // According to POSIX, we should map EISDIR to EPERM, but + // we instead do what Linux does (and we must, as we use + // the musl linux libc). + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.unlink) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + parent.node_ops.unlink(parent, name); + FS.destroyNode(node); + }, + readlink(path) { + var lookup = FS.lookupPath(path); + var link = lookup.node; + if (!link) { + throw new FS.ErrnoError(44); + } + if (!link.node_ops.readlink) { + throw new FS.ErrnoError(28); + } + return link.node_ops.readlink(link); + }, + stat(path, dontFollow) { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var node = lookup.node; + var getattr = FS.checkOpExists(node.node_ops.getattr, 63); + return getattr(node); + }, + fstat(fd) { + var stream = FS.getStreamChecked(fd); + var node = stream.node; + var getattr = stream.stream_ops.getattr; + var arg = getattr ? stream : node; + getattr ??= node.node_ops.getattr; + FS.checkOpExists(getattr, 63) + return getattr(arg); + }, + lstat(path) { + return FS.stat(path, true); + }, + doChmod(stream, node, mode, dontFollow) { + FS.doSetAttr(stream, node, { + mode: (mode & 4095) | (node.mode & ~4095), + ctime: Date.now(), + dontFollow + }); + }, + chmod(path, mode, dontFollow) { + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + FS.doChmod(null, node, mode, dontFollow); + }, + lchmod(path, mode) { + FS.chmod(path, mode, true); + }, + fchmod(fd, mode) { + var stream = FS.getStreamChecked(fd); + FS.doChmod(stream, stream.node, mode, false); + }, + doChown(stream, node, dontFollow) { + FS.doSetAttr(stream, node, { + timestamp: Date.now(), + dontFollow + // we ignore the uid / gid for now + }); + }, + chown(path, uid, gid, dontFollow) { + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + FS.doChown(null, node, dontFollow); + }, + lchown(path, uid, gid) { + FS.chown(path, uid, gid, true); + }, + fchown(fd, uid, gid) { + var stream = FS.getStreamChecked(fd); + FS.doChown(stream, stream.node, false); + }, + doTruncate(stream, node, len) { + if (FS.isDir(node.mode)) { + throw new FS.ErrnoError(31); + } + if (!FS.isFile(node.mode)) { + throw new FS.ErrnoError(28); + } + var errCode = FS.nodePermissions(node, 'w'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + FS.doSetAttr(stream, node, { + size: len, + timestamp: Date.now() + }); + }, + truncate(path, len) { + if (len < 0) { + throw new FS.ErrnoError(28); + } + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: true }); + node = lookup.node; + } else { + node = path; + } + FS.doTruncate(null, node, len); + }, + ftruncate(fd, len) { + var stream = FS.getStreamChecked(fd); + if (len < 0 || (stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(28); + } + FS.doTruncate(stream, stream.node, len); + }, + utime(path, atime, mtime) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + var setattr = FS.checkOpExists(node.node_ops.setattr, 63); + setattr(node, { + atime: atime, + mtime: mtime + }); + }, + open(path, flags, mode = 0o666) { + if (path === "") { + throw new FS.ErrnoError(44); + } + flags = typeof flags == 'string' ? FS_modeStringToFlags(flags) : flags; + if ((flags & 64)) { + mode = (mode & 4095) | 32768; + } else { + mode = 0; + } + var node; + var isDirPath; + if (typeof path == 'object') { + node = path; + } else { + isDirPath = path.endsWith("/"); + // noent_okay makes it so that if the final component of the path + // doesn't exist, lookupPath returns `node: undefined`. `path` will be + // updated to point to the target of all symlinks. + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072), + noent_okay: true + }); + node = lookup.node; + path = lookup.path; + } + // perhaps we need to create the node + var created = false; + if ((flags & 64)) { + if (node) { + // if O_CREAT and O_EXCL are set, error out if the node already exists + if ((flags & 128)) { + throw new FS.ErrnoError(20); + } + } else if (isDirPath) { + throw new FS.ErrnoError(31); + } else { + // node doesn't exist, try to create it + // Ignore the permission bits here to ensure we can `open` this new + // file below. We use chmod below the apply the permissions once the + // file is open. + node = FS.mknod(path, mode | 0o777, 0); + created = true; + } + } + if (!node) { + throw new FS.ErrnoError(44); + } + // can't truncate a device + if (FS.isChrdev(node.mode)) { + flags &= ~512; + } + // if asked only for a directory, then this must be one + if ((flags & 65536) && !FS.isDir(node.mode)) { + throw new FS.ErrnoError(54); + } + // check permissions, if this is not a file we just created now (it is ok to + // create and write to a file with read-only permissions; it is read-only + // for later use) + if (!created) { + var errCode = FS.mayOpen(node, flags); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + } + // do truncation if necessary + if ((flags & 512) && !created) { + FS.truncate(node, 0); + } + // we've already handled these, don't pass down to the underlying vfs + flags &= ~(128 | 512 | 131072); + + // register the stream with the filesystem + var stream = FS.createStream({ + node, + path: FS.getPath(node), // we want the absolute path to the node + flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + // used by the file family libc calls (fopen, fwrite, ferror, etc.) + ungotten: [], + error: false + }); + // call the new stream's open function + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + if (created) { + FS.chmod(node, mode & 0o777); + } + if (Module['logReadFiles'] && !(flags & 1)) { + if (!(path in FS.readFiles)) { + FS.readFiles[path] = 1; + } + } + return stream; + }, + close(stream) { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (stream.getdents) stream.getdents = null; // free readdir state + try { + if (stream.stream_ops.close) { + stream.stream_ops.close(stream); + } + } catch (e) { + throw e; + } finally { + FS.closeStream(stream.fd); + } + stream.fd = null; + }, + isClosed(stream) { + return stream.fd === null; + }, + llseek(stream, offset, whence) { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (!stream.seekable || !stream.stream_ops.llseek) { + throw new FS.ErrnoError(70); + } + if (whence != 0 && whence != 1 && whence != 2) { + throw new FS.ErrnoError(28); + } + stream.position = stream.stream_ops.llseek(stream, offset, whence); + stream.ungotten = []; + return stream.position; + }, + read(stream, buffer, offset, length, position) { + assert(offset >= 0); + if (length < 0 || position < 0) { + throw new FS.ErrnoError(28); + } + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(8); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(31); + } + if (!stream.stream_ops.read) { + throw new FS.ErrnoError(28); + } + var seeking = typeof position != 'undefined'; + if (!seeking) { + position = stream.position; + } else if (!stream.seekable) { + throw new FS.ErrnoError(70); + } + var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); + if (!seeking) stream.position += bytesRead; + return bytesRead; + }, + write(stream, buffer, offset, length, position, canOwn) { + assert(offset >= 0); + if (length < 0 || position < 0) { + throw new FS.ErrnoError(28); + } + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(8); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(31); + } + if (!stream.stream_ops.write) { + throw new FS.ErrnoError(28); + } + if (stream.seekable && stream.flags & 1024) { + // seek to the end before writing in append mode + FS.llseek(stream, 0, 2); + } + var seeking = typeof position != 'undefined'; + if (!seeking) { + position = stream.position; + } else if (!stream.seekable) { + throw new FS.ErrnoError(70); + } + var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); + if (!seeking) stream.position += bytesWritten; + return bytesWritten; + }, + mmap(stream, length, position, prot, flags) { + // User requests writing to file (prot & PROT_WRITE != 0). + // Checking if we have permissions to write to the file unless + // MAP_PRIVATE flag is set. According to POSIX spec it is possible + // to write to file opened in read-only mode with MAP_PRIVATE flag, + // as all modifications will be visible only in the memory of + // the current process. + if ((prot & 2) !== 0 + && (flags & 2) === 0 + && (stream.flags & 2097155) !== 2) { + throw new FS.ErrnoError(2); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(2); + } + if (!stream.stream_ops.mmap) { + throw new FS.ErrnoError(43); + } + if (!length) { + throw new FS.ErrnoError(28); + } + return stream.stream_ops.mmap(stream, length, position, prot, flags); + }, + msync(stream, buffer, offset, length, mmapFlags) { + assert(offset >= 0); + if (!stream.stream_ops.msync) { + return 0; + } + return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags); + }, + ioctl(stream, cmd, arg) { + if (!stream.stream_ops.ioctl) { + throw new FS.ErrnoError(59); + } + return stream.stream_ops.ioctl(stream, cmd, arg); + }, + readFile(path, opts = {}) { + opts.flags = opts.flags || 0; + opts.encoding = opts.encoding || 'binary'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + abort(`Invalid encoding type "${opts.encoding}"`); + } + var stream = FS.open(path, opts.flags); + var stat = FS.stat(path); + var length = stat.size; + var buf = new Uint8Array(length); + FS.read(stream, buf, 0, length, 0); + if (opts.encoding === 'utf8') { + buf = UTF8ArrayToString(buf); + } + FS.close(stream); + return buf; + }, + writeFile(path, data, opts = {}) { + opts.flags = opts.flags || 577; + var stream = FS.open(path, opts.flags, opts.mode); + if (typeof data == 'string') { + data = new Uint8Array(intArrayFromString(data, true)); + } + if (ArrayBuffer.isView(data)) { + FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn); + } else { + abort('Unsupported data type'); + } + FS.close(stream); + }, + cwd:() => FS.currentPath, + chdir(path) { + var lookup = FS.lookupPath(path, { follow: true }); + if (lookup.node === null) { + throw new FS.ErrnoError(44); + } + if (!FS.isDir(lookup.node.mode)) { + throw new FS.ErrnoError(54); + } + var errCode = FS.nodePermissions(lookup.node, 'x'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + FS.currentPath = lookup.path; + }, + createDefaultDirectories() { + FS.mkdir('/tmp'); + FS.mkdir('/home'); + FS.mkdir('/home/web_user'); + }, + createDefaultDevices() { + // create /dev + FS.mkdir('/dev'); + // setup /dev/null + FS.registerDevice(FS.makedev(1, 3), { + read: () => 0, + write: (stream, buffer, offset, length, pos) => length, + llseek: () => 0, + }); + FS.mkdev('/dev/null', FS.makedev(1, 3)); + // setup /dev/tty and /dev/tty1 + // stderr needs to print output using err() rather than out() + // so we register a second tty just for it. + TTY.register(FS.makedev(5, 0), TTY.default_tty_ops); + TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops); + FS.mkdev('/dev/tty', FS.makedev(5, 0)); + FS.mkdev('/dev/tty1', FS.makedev(6, 0)); + // setup /dev/[u]random + // use a buffer to avoid overhead of individual crypto calls per byte + var randomBuffer = new Uint8Array(1024), randomLeft = 0; + var randomByte = () => { + if (randomLeft === 0) { + randomFill(randomBuffer); + randomLeft = randomBuffer.byteLength; + } + return randomBuffer[--randomLeft]; + }; + FS.createDevice('/dev', 'random', randomByte); + FS.createDevice('/dev', 'urandom', randomByte); + // we're not going to emulate the actual shm device, + // just create the tmp dirs that reside in it commonly + FS.mkdir('/dev/shm'); + FS.mkdir('/dev/shm/tmp'); + }, + createSpecialDirectories() { + // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the + // name of the stream for fd 6 (see test_unistd_ttyname) + FS.mkdir('/proc'); + var proc_self = FS.mkdir('/proc/self'); + FS.mkdir('/proc/self/fd'); + FS.mount({ + mount() { + var node = FS.createNode(proc_self, 'fd', 16895, 73); + node.stream_ops = { + llseek: MEMFS.stream_ops.llseek, + }; + node.node_ops = { + lookup(parent, name) { + var fd = +name; + var stream = FS.getStreamChecked(fd); + var ret = { + parent: null, + mount: { mountpoint: 'fake' }, + node_ops: { readlink: () => stream.path }, + id: fd + 1, + }; + ret.parent = ret; // make it look like a simple root node + return ret; + }, + readdir() { + return Array.from(FS.streams.entries()) + .filter(([k, v]) => v) + .map(([k, v]) => k.toString()); + } + }; + return node; + } + }, {}, '/proc/self/fd'); + }, + createStandardStreams(input, output, error) { + // TODO deprecate the old functionality of a single + // input / output callback and that utilizes FS.createDevice + // and instead require a unique set of stream ops + + // by default, we symlink the standard streams to the + // default tty devices. however, if the standard streams + // have been overwritten we create a unique device for + // them instead. + if (input) { + FS.createDevice('/dev', 'stdin', input); + } else { + FS.symlink('/dev/tty', '/dev/stdin'); + } + if (output) { + FS.createDevice('/dev', 'stdout', null, output); + } else { + FS.symlink('/dev/tty', '/dev/stdout'); + } + if (error) { + FS.createDevice('/dev', 'stderr', null, error); + } else { + FS.symlink('/dev/tty1', '/dev/stderr'); + } + + // open default streams for the stdin, stdout and stderr devices + var stdin = FS.open('/dev/stdin', 0); + var stdout = FS.open('/dev/stdout', 1); + var stderr = FS.open('/dev/stderr', 1); + assert(stdin.fd === 0, `invalid handle for stdin (${stdin.fd})`); + assert(stdout.fd === 1, `invalid handle for stdout (${stdout.fd})`); + assert(stderr.fd === 2, `invalid handle for stderr (${stderr.fd})`); + }, + staticInit() { + FS.nameTable = new Array(4096); + + FS.mount(MEMFS, {}, '/'); + + FS.createDefaultDirectories(); + FS.createDefaultDevices(); + FS.createSpecialDirectories(); + + FS.filesystems = { + 'MEMFS': MEMFS, + }; + }, + init(input, output, error) { + assert(!FS.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); + FS.initialized = true; + + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + input ??= Module['stdin']; + output ??= Module['stdout']; + error ??= Module['stderr']; + + FS.createStandardStreams(input, output, error); + }, + quit() { + FS.initialized = false; + // force-flush all streams, so we get musl std streams printed out + _fflush(0); + // close all of our streams + for (var stream of FS.streams) { + if (stream) { + FS.close(stream); + } + } + }, + findObject(path, dontResolveLastLink) { + var ret = FS.analyzePath(path, dontResolveLastLink); + if (!ret.exists) { + return null; + } + return ret.object; + }, + analyzePath(path, dontResolveLastLink) { + // operate from within the context of the symlink's target + try { + var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + path = lookup.path; + } catch (e) { + } + var ret = { + isRoot: false, exists: false, error: 0, name: null, path: null, object: null, + parentExists: false, parentPath: null, parentObject: null + }; + try { + var lookup = FS.lookupPath(path, { parent: true }); + ret.parentExists = true; + ret.parentPath = lookup.path; + ret.parentObject = lookup.node; + ret.name = PATH.basename(path); + lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + ret.exists = true; + ret.path = lookup.path; + ret.object = lookup.node; + ret.name = lookup.node.name; + ret.isRoot = lookup.path === '/'; + } catch (e) { + ret.error = e.errno; + }; + return ret; + }, + createPath(parent, path, canRead, canWrite) { + parent = typeof parent == 'string' ? parent : FS.getPath(parent); + var parts = path.split('/').reverse(); + while (parts.length) { + var part = parts.pop(); + if (!part) continue; + var current = PATH.join2(parent, part); + try { + FS.mkdir(current); + } catch (e) { + if (e.errno != 20) throw e; + } + parent = current; + } + return current; + }, + createFile(parent, name, properties, canRead, canWrite) { + var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + var mode = FS_getMode(canRead, canWrite); + return FS.create(path, mode); + }, + createDataFile(parent, name, data, canRead, canWrite, canOwn) { + var path = name; + if (parent) { + parent = typeof parent == 'string' ? parent : FS.getPath(parent); + path = name ? PATH.join2(parent, name) : parent; + } + var mode = FS_getMode(canRead, canWrite); + var node = FS.create(path, mode); + if (data) { + if (typeof data == 'string') { + var arr = new Array(data.length); + for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i); + data = arr; + } + // make sure we can write to the file + FS.chmod(node, mode | 146); + var stream = FS.open(node, 577); + FS.write(stream, data, 0, data.length, 0, canOwn); + FS.close(stream); + FS.chmod(node, mode); + } + }, + createDevice(parent, name, input, output) { + var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + var mode = FS_getMode(!!input, !!output); + FS.createDevice.major ??= 64; + var dev = FS.makedev(FS.createDevice.major++, 0); + // Create a fake device that a set of stream ops to emulate + // the old behavior. + FS.registerDevice(dev, { + open(stream) { + stream.seekable = false; + }, + close(stream) { + // flush any pending line data + if (output?.buffer?.length) { + output(10); + } + }, + read(stream, buffer, offset, length, pos /* ignored */) { + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = input(); + } 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) { + for (var i = 0; i < length; i++) { + try { + output(buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(29); + } + } + if (length) { + stream.node.mtime = stream.node.ctime = Date.now(); + } + return i; + } + }); + return FS.mkdev(path, mode, dev); + }, + forceLoadFile(obj) { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + if (globalThis.XMLHttpRequest) { + abort("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else { // Command-line. + try { + obj.contents = readBinary(obj.url); + } catch (e) { + throw new FS.ErrnoError(29); + } + } + }, + createLazyFile(parent, name, url, canRead, canWrite) { + // Lazy chunked Uint8Array (implements get and length from Uint8Array). + // Actual getting is abstracted away for eventual reuse. + class LazyUint8Array { + lengthKnown = false; + chunks = []; // Loaded chunks. Index is the chunk number + get(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = (idx / this.chunkSize)|0; + return this.getter(chunkNum)[chunkOffset]; + } + setDataGetter(getter) { + this.getter = getter; + } + cacheLength() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status); + var datalength = Number(xhr.getResponseHeader("Content-length")); + var header; + var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; + var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip"; + + var chunkSize = 1024*1024; // Chunk size in bytes + + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (from, to) => { + if (from > to) abort("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) abort("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + xhr.responseType = 'arraybuffer'; + if (xhr.overrideMimeType) { + xhr.overrideMimeType('text/plain; charset=x-user-defined'); + } + + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(/** @type{Array} */(xhr.response || [])); + } + return intArrayFromString(xhr.responseText || '', true); + }; + var lazyArray = this; + lazyArray.setDataGetter((chunkNum) => { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof lazyArray.chunks[chunkNum] == 'undefined') { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof lazyArray.chunks[chunkNum] == 'undefined') abort('doXHR failed!'); + return lazyArray.chunks[chunkNum]; + }); + + if (usesGzip || !datalength) { + // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length + chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file + datalength = this.getter(0).length; + chunkSize = datalength; + out("LazyFiles on gzip forces download of the whole file when length is accessed"); + } + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } + get length() { + if (!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + get chunkSize() { + if (!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + } + + if (globalThis.XMLHttpRequest) { + if (!ENVIRONMENT_IS_WORKER) abort('Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'); + var lazyArray = new LazyUint8Array(); + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + + var node = FS.createFile(parent, name, properties, canRead, canWrite); + // This is a total hack, but I want to get this lazy file code out of the + // core of MEMFS. If we want to keep this lazy file concept I feel it should + // be its own thin LAZYFS proxying calls to MEMFS. + if (properties.contents) { + node.contents = properties.contents; + } else if (properties.url) { + node.contents = null; + node.url = properties.url; + } + // Add a function that defers querying the file size until it is asked the first time. + Object.defineProperties(node, { + usedBytes: { + get: function() { return this.contents.length; } + } + }); + // override each stream op with one that tries to force load the lazy file first + var stream_ops = {}; + var keys = Object.keys(node.stream_ops); + keys.forEach((key) => { + var fn = node.stream_ops[key]; + stream_ops[key] = (...args) => { + FS.forceLoadFile(node); + return fn(...args); + }; + }); + function writeChunks(stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (contents.slice) { // normal array + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } else { + for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR + buffer[offset + i] = contents.get(position + i); + } + } + return size; + } + // use a custom read function + stream_ops.read = (stream, buffer, offset, length, position) => { + FS.forceLoadFile(node); + return writeChunks(stream, buffer, offset, length, position) + }; + // use a custom mmap function + stream_ops.mmap = (stream, length, position, prot, flags) => { + FS.forceLoadFile(node); + var ptr = mmapAlloc(length); + if (!ptr) { + throw new FS.ErrnoError(48); + } + writeChunks(stream, HEAP8, ptr, length, position); + return { ptr, allocated: true }; + }; + node.stream_ops = stream_ops; + return node; + }, + absolutePath() { + abort('FS.absolutePath has been removed; use PATH_FS.resolve instead'); + }, + createFolder() { + abort('FS.createFolder has been removed; use FS.mkdir instead'); + }, + createLink() { + abort('FS.createLink has been removed; use FS.symlink instead'); + }, + joinPath() { + abort('FS.joinPath has been removed; use PATH.join instead'); + }, + mmapAlloc() { + abort('FS.mmapAlloc has been replaced by the top level function mmapAlloc'); + }, + standardizePath() { + abort('FS.standardizePath has been removed; use PATH.normalize instead'); + }, + }; + + var SYSCALLS = { + DEFAULT_POLLMASK:5, + calculateAt(dirfd, path, allowEmpty) { + if (PATH.isAbs(path)) { + return path; + } + // relative path + var dir; + if (dirfd === -100) { + dir = FS.cwd(); + } else { + var dirstream = SYSCALLS.getStreamFromFD(dirfd); + dir = dirstream.path; + } + if (path.length == 0) { + if (!allowEmpty) { + throw new FS.ErrnoError(44);; + } + return dir; + } + return dir + '/' + path; + }, + writeStat(buf, stat) { + HEAPU32[((buf)>>2)] = stat.dev; + HEAPU32[(((buf)+(4))>>2)] = stat.mode; + HEAPU32[(((buf)+(8))>>2)] = stat.nlink; + HEAPU32[(((buf)+(12))>>2)] = stat.uid; + HEAPU32[(((buf)+(16))>>2)] = stat.gid; + HEAPU32[(((buf)+(20))>>2)] = stat.rdev; + HEAP64[(((buf)+(24))>>3)] = BigInt(stat.size); + HEAP32[(((buf)+(32))>>2)] = 4096; + HEAP32[(((buf)+(36))>>2)] = stat.blocks; + var atime = stat.atime.getTime(); + var mtime = stat.mtime.getTime(); + var ctime = stat.ctime.getTime(); + HEAP64[(((buf)+(40))>>3)] = BigInt(Math.floor(atime / 1000)); + HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000 * 1000; + HEAP64[(((buf)+(56))>>3)] = BigInt(Math.floor(mtime / 1000)); + HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000 * 1000; + HEAP64[(((buf)+(72))>>3)] = BigInt(Math.floor(ctime / 1000)); + HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000 * 1000; + HEAP64[(((buf)+(88))>>3)] = BigInt(stat.ino); + return 0; + }, + writeStatFs(buf, stats) { + HEAPU32[(((buf)+(4))>>2)] = stats.bsize; + HEAPU32[(((buf)+(60))>>2)] = stats.bsize; + HEAP64[(((buf)+(8))>>3)] = BigInt(stats.blocks); + HEAP64[(((buf)+(16))>>3)] = BigInt(stats.bfree); + HEAP64[(((buf)+(24))>>3)] = BigInt(stats.bavail); + HEAP64[(((buf)+(32))>>3)] = BigInt(stats.files); + HEAP64[(((buf)+(40))>>3)] = BigInt(stats.ffree); + HEAPU32[(((buf)+(48))>>2)] = stats.fsid; + HEAPU32[(((buf)+(64))>>2)] = stats.flags; // ST_NOSUID + HEAPU32[(((buf)+(56))>>2)] = stats.namelen; + }, + doMsync(addr, stream, len, flags, offset) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + if (flags & 2) { + // MAP_PRIVATE calls need not to be synced back to underlying fs + return 0; + } + var buffer = HEAPU8.slice(addr, addr + len); + FS.msync(stream, buffer, offset, len, flags); + }, + getStreamFromFD(fd) { + var stream = FS.getStreamChecked(fd); + return stream; + }, + varargs:undefined, + getStr(ptr) { + var ret = UTF8ToString(ptr); + return ret; + }, + }; + function ___syscall_fcntl64(fd, cmd, varargs) { + SYSCALLS.varargs = varargs; + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + switch (cmd) { + case 0: { + var arg = syscallGetVarargI(); + if (arg < 0) { + return -28; + } + while (FS.streams[arg]) { + arg++; + } + var newStream; + newStream = FS.dupStream(stream, arg); + return newStream.fd; + } + case 1: + case 2: + return 0; // FD_CLOEXEC makes no sense for a single process. + case 3: + return stream.flags; + case 4: { + var arg = syscallGetVarargI(); + stream.flags |= arg; + return 0; + } + case 12: { + var arg = syscallGetVarargP(); + var offset = 0; + // We're always unlocked. + HEAP16[(((arg)+(offset))>>1)] = 2; + return 0; + } + case 13: + case 14: + // Pretend that the locking is successful. These are process-level locks, + // and Emscripten programs are a single process. If we supported linking a + // filesystem between programs, we'd need to do more here. + // See https://github.com/emscripten-core/emscripten/issues/23697 + return 0; + } + return -28; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_ioctl(fd, op, varargs) { + SYSCALLS.varargs = varargs; + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + switch (op) { + case 21509: { + if (!stream.tty) return -59; + return 0; + } + case 21505: { + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tcgets) { + var termios = stream.tty.ops.ioctl_tcgets(stream); + var argp = syscallGetVarargP(); + HEAP32[((argp)>>2)] = termios.c_iflag || 0; + HEAP32[(((argp)+(4))>>2)] = termios.c_oflag || 0; + HEAP32[(((argp)+(8))>>2)] = termios.c_cflag || 0; + HEAP32[(((argp)+(12))>>2)] = termios.c_lflag || 0; + for (var i = 0; i < 32; i++) { + HEAP8[(argp + i)+(17)] = termios.c_cc[i] || 0; + } + return 0; + } + return 0; + } + case 21510: + case 21511: + case 21512: { + if (!stream.tty) return -59; + return 0; // no-op, not actually adjusting terminal settings + } + case 21506: + case 21507: + case 21508: { + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tcsets) { + var argp = syscallGetVarargP(); + var c_iflag = HEAP32[((argp)>>2)]; + var c_oflag = HEAP32[(((argp)+(4))>>2)]; + var c_cflag = HEAP32[(((argp)+(8))>>2)]; + var c_lflag = HEAP32[(((argp)+(12))>>2)]; + var c_cc = [] + for (var i = 0; i < 32; i++) { + c_cc.push(HEAP8[(argp + i)+(17)]); + } + return stream.tty.ops.ioctl_tcsets(stream.tty, op, { c_iflag, c_oflag, c_cflag, c_lflag, c_cc }); + } + return 0; // no-op, not actually adjusting terminal settings + } + case 21519: { + if (!stream.tty) return -59; + var argp = syscallGetVarargP(); + HEAP32[((argp)>>2)] = 0; + return 0; + } + case 21520: { + if (!stream.tty) return -59; + return -28; // not supported + } + case 21537: + case 21531: { + var argp = syscallGetVarargP(); + return FS.ioctl(stream, op, argp); + } + case 21523: { + // TODO: in theory we should write to the winsize struct that gets + // passed in, but for now musl doesn't read anything on it + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tiocgwinsz) { + var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty); + var argp = syscallGetVarargP(); + HEAP16[((argp)>>1)] = winsize[0]; + HEAP16[(((argp)+(2))>>1)] = winsize[1]; + } + return 0; + } + case 21524: { + // TODO: technically, this ioctl call should change the window size. + // but, since emscripten doesn't have any concept of a terminal window + // yet, we'll just silently throw it away as we do TIOCGWINSZ + if (!stream.tty) return -59; + return 0; + } + case 21515: { + if (!stream.tty) return -59; + return 0; + } + default: return -28; // not supported + } + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_openat(dirfd, path, flags, varargs) { + SYSCALLS.varargs = varargs; + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + var mode = varargs ? syscallGetVarargI() : 0; + return FS.open(path, flags, mode).fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + var __abort_js = () => + abort('native code called abort()'); + + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => { + assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); + }; + + var __tzset_js = (timezone, daylight, std_name, dst_name) => { + // TODO: Use (malleable) environment variables instead of system settings. + var currentYear = new Date().getFullYear(); + var winter = new Date(currentYear, 0, 1); + var summer = new Date(currentYear, 6, 1); + var winterOffset = winter.getTimezoneOffset(); + var summerOffset = summer.getTimezoneOffset(); + + // Local standard timezone offset. Local standard time is not adjusted for + // daylight savings. This code uses the fact that getTimezoneOffset returns + // a greater value during Standard Time versus Daylight Saving Time (DST). + // Thus it determines the expected output during Standard Time, and it + // compares whether the output of the given date the same (Standard) or less + // (DST). + var stdTimezoneOffset = Math.max(winterOffset, summerOffset); + + // timezone is specified as seconds west of UTC ("The external variable + // `timezone` shall be set to the difference, in seconds, between + // Coordinated Universal Time (UTC) and local standard time."), the same + // as returned by stdTimezoneOffset. + // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html + HEAPU32[((timezone)>>2)] = stdTimezoneOffset * 60; + + HEAP32[((daylight)>>2)] = Number(winterOffset != summerOffset); + + var extractZone = (timezoneOffset) => { + // Why inverse sign? + // Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset + var sign = timezoneOffset >= 0 ? "-" : "+"; + + var absOffset = Math.abs(timezoneOffset) + var hours = String(Math.floor(absOffset / 60)).padStart(2, "0"); + var minutes = String(absOffset % 60).padStart(2, "0"); + + return `UTC${sign}${hours}${minutes}`; + } + + var winterName = extractZone(winterOffset); + var summerName = extractZone(summerOffset); + assert(winterName); + assert(summerName); + assert(lengthBytesUTF8(winterName) <= 16, `timezone name truncated to fit in TZNAME_MAX (${winterName})`); + assert(lengthBytesUTF8(summerName) <= 16, `timezone name truncated to fit in TZNAME_MAX (${summerName})`); + if (summerOffset < winterOffset) { + // Northern hemisphere + stringToUTF8(winterName, std_name, 17); + stringToUTF8(summerName, dst_name, 17); + } else { + stringToUTF8(winterName, dst_name, 17); + stringToUTF8(summerName, std_name, 17); + } + }; + + var getHeapMax = () => + // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate + // full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side + // for any code that deals with heap sizes, which would require special + // casing all heap size related code to treat 0 specially. + 2147483648; + + var alignMemory = (size, alignment) => { + assert(alignment, "alignment argument is required"); + return Math.ceil(size / alignment) * alignment; + }; + + var growMemory = (size) => { + var oldHeapSize = wasmMemory.buffer.byteLength; + var pages = ((size - oldHeapSize + 65535) / 65536) | 0; + try { + // round size grow request up to wasm page size (fixed 64KB per spec) + wasmMemory.grow(pages); // .grow() takes a delta compared to the previous size + updateMemoryViews(); + return 1 /*success*/; + } catch(e) { + err(`growMemory: Attempted to grow heap from ${oldHeapSize} bytes to ${size} bytes, but got error: ${e}`); + } + // implicit 0 return to save code size (caller will cast "undefined" into 0 + // anyhow) + }; + var _emscripten_resize_heap = (requestedSize) => { + var oldSize = HEAPU8.length; + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + requestedSize >>>= 0; + // With multithreaded builds, races can happen (another thread might increase the size + // in between), so return a failure, and let the caller retry. + assert(requestedSize > oldSize); + + // Memory resize rules: + // 1. Always increase heap size to at least the requested size, rounded up + // to next page multiple. + // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap + // geometrically: increase the heap size according to + // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most + // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB). + // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap + // linearly: increase the heap size by at least + // MEMORY_GROWTH_LINEAR_STEP bytes. + // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by + // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest + // 4. If we were unable to allocate as much memory, it may be due to + // over-eager decision to excessively reserve due to (3) above. + // Hence if an allocation fails, cut down on the amount of excess + // growth, in an attempt to succeed to perform a smaller allocation. + + // A limit is set for how much we can grow. We should not exceed that + // (the wasm binary specifies it, so if we tried, we'd fail anyhow). + var maxHeapSize = getHeapMax(); + if (requestedSize > maxHeapSize) { + err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`); + return false; + } + + // Loop through potential heap size increases. If we attempt a too eager + // reservation that fails, cut down on the attempted size and reserve a + // smaller bump instead. (max 3 times, chosen somewhat arbitrarily) + for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { + var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth + // but limit overreserving (default to capping at +96MB overgrowth at most) + overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 ); + + var newSize = Math.min(maxHeapSize, alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536)); + + var replacement = growMemory(newSize); + if (replacement) { + + return true; + } + } + err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`); + return false; + }; + + var ENV = { + }; + + var getExecutableName = () => thisProgram || './this.program'; + var getEnvStrings = () => { + if (!getEnvStrings.strings) { + // Default values. + // Browser language detection #8751 + var lang = ((typeof navigator == 'object' && navigator.language) || 'C').replace('-', '_') + '.UTF-8'; + var env = { + 'USER': 'web_user', + 'LOGNAME': 'web_user', + 'PATH': '/', + 'PWD': '/', + 'HOME': '/home/web_user', + 'LANG': lang, + '_': getExecutableName() + }; + // Apply the user-provided values, if any. + for (var x in ENV) { + // x is a key in ENV; if ENV[x] is undefined, that means it was + // explicitly set to be so. We allow user code to do that to + // force variables with default values to remain unset. + if (ENV[x] === undefined) delete env[x]; + else env[x] = ENV[x]; + } + var strings = []; + for (var x in env) { + strings.push(`${x}=${env[x]}`); + } + getEnvStrings.strings = strings; + } + return getEnvStrings.strings; + }; + + var _environ_get = (__environ, environ_buf) => { + var bufSize = 0; + var envp = 0; + for (var string of getEnvStrings()) { + var ptr = environ_buf + bufSize; + HEAPU32[(((__environ)+(envp))>>2)] = ptr; + bufSize += stringToUTF8(string, ptr, Infinity) + 1; + envp += 4; + } + return 0; + }; + + + var _environ_sizes_get = (penviron_count, penviron_buf_size) => { + var strings = getEnvStrings(); + HEAPU32[((penviron_count)>>2)] = strings.length; + var bufSize = 0; + for (var string of strings) { + bufSize += lengthBytesUTF8(string) + 1; + } + HEAPU32[((penviron_buf_size)>>2)] = bufSize; + return 0; + }; + + function _fd_close(fd) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + FS.close(stream); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + /** @param {number=} offset */ + var doReadv = (stream, iov, iovcnt, offset) => { + var ret = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + var curr = FS.read(stream, HEAP8, ptr, len, offset); + if (curr < 0) return -1; + ret += curr; + if (curr < len) break; // nothing more to read + if (typeof offset != 'undefined') { + offset += curr; + } + } + return ret; + }; + + function _fd_read(fd, iov, iovcnt, pnum) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var num = doReadv(stream, iov, iovcnt); + HEAPU32[((pnum)>>2)] = num; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + + var INT53_MAX = 9007199254740992; + + var INT53_MIN = -9007199254740992; + var bigintToI53Checked = (num) => (num < INT53_MIN || num > INT53_MAX) ? NaN : Number(num); + function _fd_seek(fd, offset, whence, newOffset) { + offset = bigintToI53Checked(offset); + + + try { + + if (isNaN(offset)) return 61; + var stream = SYSCALLS.getStreamFromFD(fd); + FS.llseek(stream, offset, whence); + HEAP64[((newOffset)>>3)] = BigInt(stream.position); + if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + ; + } + + /** @param {number=} offset */ + var doWritev = (stream, iov, iovcnt, offset) => { + var ret = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + var curr = FS.write(stream, HEAP8, ptr, len, offset); + if (curr < 0) return -1; + ret += curr; + if (curr < len) { + // No more space to write. + break; + } + if (typeof offset != 'undefined') { + offset += curr; + } + } + return ret; + }; + + function _fd_write(fd, iov, iovcnt, pnum) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var num = doWritev(stream, iov, iovcnt); + HEAPU32[((pnum)>>2)] = num; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + function _random_get(buffer, size) { + try { + + randomFill(HEAPU8.subarray(buffer, buffer + size)); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + + var runtimeKeepaliveCounter = 0; + var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0; + var _proc_exit = (code) => { + EXITSTATUS = code; + if (!keepRuntimeAlive()) { + Module['onExit']?.(code); + ABORT = true; + } + quit_(code, new ExitStatus(code)); + }; + + + /** @param {boolean|number=} implicit */ + var exitJS = (status, implicit) => { + EXITSTATUS = status; + + checkUnflushedContent(); + + // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down + if (keepRuntimeAlive() && !implicit) { + var msg = `program exited (with status: ${status}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`; + readyPromiseReject?.(msg); + err(msg); + } + + _proc_exit(status); + }; + + var handleException = (e) => { + // Certain exception types we do not treat as errors since they are used for + // internal control flow. + // 1. ExitStatus, which is thrown by exit() + // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others + // that wish to return to JS event loop. + if (e instanceof ExitStatus || e == 'unwind') { + return EXITSTATUS; + } + checkStackCookie(); + if (e instanceof WebAssembly.RuntimeError) { + if (_emscripten_stack_get_current() <= 0) { + err('Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to 65536)'); + } + } + quit_(1, e); + }; + + + + var stackAlloc = (sz) => __emscripten_stack_alloc(sz); + var stringToUTF8OnStack = (str) => { + var size = lengthBytesUTF8(str) + 1; + var ret = stackAlloc(size); + stringToUTF8(str, ret, size); + return ret; + }; + + var FS_writeFile = (...args) => FS.writeFile(...args); + + var FS_readFile = (...args) => FS.readFile(...args); + + FS.createPreloadedFile = FS_createPreloadedFile; + FS.preloadFile = FS_preloadFile; + FS.staticInit();; +// End JS library code + +// include: postlibrary.js +// This file is included after the automatically-generated JS library code +// but before the wasm module is created. + +{ + + // Begin ATMODULES hooks + if (Module['noExitRuntime']) noExitRuntime = Module['noExitRuntime']; +if (Module['preloadPlugins']) preloadPlugins = Module['preloadPlugins']; +if (Module['print']) out = Module['print']; +if (Module['printErr']) err = Module['printErr']; +if (Module['wasmBinary']) wasmBinary = Module['wasmBinary']; + // End ATMODULES hooks + + checkIncomingModuleAPI(); + + if (Module['arguments']) arguments_ = Module['arguments']; + if (Module['thisProgram']) thisProgram = Module['thisProgram']; + + // Assertions on removed incoming Module JS APIs. + assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead'); + assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead'); + assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead'); + assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead'); + assert(typeof Module['read'] == 'undefined', 'Module.read option was removed'); + assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)'); + assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)'); + assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)'); + assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY'); + assert(typeof Module['ENVIRONMENT'] == 'undefined', 'Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)'); + assert(typeof Module['STACK_SIZE'] == 'undefined', 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time') + // If memory is defined in wasm, the user can't provide it, or set INITIAL_MEMORY + assert(typeof Module['wasmMemory'] == 'undefined', 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally'); + assert(typeof Module['INITIAL_MEMORY'] == 'undefined', 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically'); + + if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].shift()(); + } + } + consumedModuleProp('preInit'); +} + +// Begin runtime exports + Module['callMain'] = callMain; + Module['FS_readFile'] = FS_readFile; + Module['FS_writeFile'] = FS_writeFile; + var missingLibrarySymbols = [ + 'writeI53ToI64', + 'writeI53ToI64Clamped', + 'writeI53ToI64Signaling', + 'writeI53ToU64Clamped', + 'writeI53ToU64Signaling', + 'readI53FromI64', + 'readI53FromU64', + 'convertI32PairToI53', + 'convertI32PairToI53Checked', + 'convertU32PairToI53', + 'getTempRet0', + 'setTempRet0', + 'createNamedFunction', + 'zeroMemory', + 'withStackSave', + 'inetPton4', + 'inetNtop4', + 'inetPton6', + 'inetNtop6', + 'readSockaddr', + 'writeSockaddr', + 'readEmAsmArgs', + 'jstoi_q', + 'autoResumeAudioContext', + 'getDynCaller', + 'dynCall', + 'runtimeKeepalivePush', + 'runtimeKeepalivePop', + 'callUserCallback', + 'maybeExit', + 'asmjsMangle', + 'HandleAllocator', + 'getNativeTypeSize', + 'addOnInit', + 'addOnPostCtor', + 'addOnPreMain', + 'addOnExit', + 'STACK_SIZE', + 'STACK_ALIGN', + 'POINTER_SIZE', + 'ASSERTIONS', + 'ccall', + 'cwrap', + 'convertJsFunctionToWasm', + 'getEmptyTableSlot', + 'updateTableMap', + 'getFunctionAddress', + 'addFunction', + 'removeFunction', + 'intArrayToString', + 'AsciiToString', + 'stringToAscii', + 'UTF16ToString', + 'stringToUTF16', + 'lengthBytesUTF16', + 'UTF32ToString', + 'stringToUTF32', + 'lengthBytesUTF32', + 'stringToNewUTF8', + 'writeArrayToMemory', + 'registerKeyEventCallback', + 'maybeCStringToJsString', + 'findEventTarget', + 'getBoundingClientRect', + 'fillMouseEventData', + 'registerMouseEventCallback', + 'registerWheelEventCallback', + 'registerUiEventCallback', + 'registerFocusEventCallback', + 'fillDeviceOrientationEventData', + 'registerDeviceOrientationEventCallback', + 'fillDeviceMotionEventData', + 'registerDeviceMotionEventCallback', + 'screenOrientation', + 'fillOrientationChangeEventData', + 'registerOrientationChangeEventCallback', + 'fillFullscreenChangeEventData', + 'registerFullscreenChangeEventCallback', + 'JSEvents_requestFullscreen', + 'JSEvents_resizeCanvasForFullscreen', + 'registerRestoreOldStyle', + 'hideEverythingExceptGivenElement', + 'restoreHiddenElements', + 'setLetterbox', + 'softFullscreenResizeWebGLRenderTarget', + 'doRequestFullscreen', + 'fillPointerlockChangeEventData', + 'registerPointerlockChangeEventCallback', + 'registerPointerlockErrorEventCallback', + 'requestPointerLock', + 'fillVisibilityChangeEventData', + 'registerVisibilityChangeEventCallback', + 'registerTouchEventCallback', + 'fillGamepadEventData', + 'registerGamepadEventCallback', + 'registerBeforeUnloadEventCallback', + 'fillBatteryEventData', + 'registerBatteryEventCallback', + 'setCanvasElementSize', + 'getCanvasElementSize', + 'jsStackTrace', + 'getCallstack', + 'convertPCtoSourceLocation', + 'checkWasiClock', + 'wasiRightsToMuslOFlags', + 'wasiOFlagsToMuslOFlags', + 'safeSetTimeout', + 'setImmediateWrapped', + 'safeRequestAnimationFrame', + 'clearImmediateWrapped', + 'registerPostMainLoop', + 'registerPreMainLoop', + 'getPromise', + 'makePromise', + 'idsToPromises', + 'makePromiseCallback', + 'findMatchingCatch', + 'Browser_asyncPrepareDataCounter', + 'isLeapYear', + 'ydayFromDate', + 'arraySum', + 'addDays', + 'getSocketFromFD', + 'getSocketAddress', + 'FS_mkdirTree', + '_setNetworkCallback', + 'heapObjectForWebGLType', + 'toTypedArrayIndex', + 'webgl_enable_ANGLE_instanced_arrays', + 'webgl_enable_OES_vertex_array_object', + 'webgl_enable_WEBGL_draw_buffers', + 'webgl_enable_WEBGL_multi_draw', + 'webgl_enable_EXT_polygon_offset_clamp', + 'webgl_enable_EXT_clip_control', + 'webgl_enable_WEBGL_polygon_mode', + 'emscriptenWebGLGet', + 'computeUnpackAlignedImageSize', + 'colorChannelsInGlTextureFormat', + 'emscriptenWebGLGetTexPixelData', + 'emscriptenWebGLGetUniform', + 'webglGetUniformLocation', + 'webglPrepareUniformLocationsBeforeFirstUse', + 'webglGetLeftBracePos', + 'emscriptenWebGLGetVertexAttrib', + '__glGetActiveAttribOrUniform', + 'writeGLArray', + 'registerWebGlEventCallback', + 'runAndAbortIfError', + 'ALLOC_NORMAL', + 'ALLOC_STACK', + 'allocate', + 'writeStringToMemory', + 'writeAsciiToMemory', + 'demangle', + 'stackTrace', +]; +missingLibrarySymbols.forEach(missingLibrarySymbol) + + var unexportedSymbols = [ + 'run', + 'out', + 'err', + 'abort', + 'wasmMemory', + 'wasmExports', + 'HEAPF32', + 'HEAPF64', + 'HEAP8', + 'HEAPU8', + 'HEAP16', + 'HEAPU16', + 'HEAP32', + 'HEAPU32', + 'HEAP64', + 'HEAPU64', + 'writeStackCookie', + 'checkStackCookie', + 'INT53_MAX', + 'INT53_MIN', + 'bigintToI53Checked', + 'stackSave', + 'stackRestore', + 'stackAlloc', + 'ptrToString', + 'exitJS', + 'getHeapMax', + 'growMemory', + 'ENV', + 'ERRNO_CODES', + 'strError', + 'DNS', + 'Protocols', + 'Sockets', + 'timers', + 'warnOnce', + 'readEmAsmArgsArray', + 'getExecutableName', + 'handleException', + 'keepRuntimeAlive', + 'asyncLoad', + 'alignMemory', + 'mmapAlloc', + 'wasmTable', + 'getUniqueRunDependency', + 'noExitRuntime', + 'addRunDependency', + 'removeRunDependency', + 'addOnPreRun', + 'addOnPostRun', + 'freeTableIndexes', + 'functionsInTableMap', + 'setValue', + 'getValue', + 'PATH', + 'PATH_FS', + 'UTF8Decoder', + 'UTF8ArrayToString', + 'UTF8ToString', + 'stringToUTF8Array', + 'stringToUTF8', + 'lengthBytesUTF8', + 'intArrayFromString', + 'UTF16Decoder', + 'stringToUTF8OnStack', + 'JSEvents', + 'specialHTMLTargets', + 'findCanvasEventTarget', + 'currentFullscreenStrategy', + 'restoreOldWindowedStyle', + 'UNWIND_CACHE', + 'ExitStatus', + 'getEnvStrings', + 'doReadv', + 'doWritev', + 'initRandomFill', + 'randomFill', + 'emSetImmediate', + 'emClearImmediate_deps', + 'emClearImmediate', + 'promiseMap', + 'uncaughtExceptionCount', + 'exceptionLast', + 'exceptionCaught', + 'ExceptionInfo', + 'Browser', + 'requestFullscreen', + 'requestFullScreen', + 'setCanvasSize', + 'getUserMedia', + 'createContext', + 'getPreloadedImageData__data', + 'wget', + 'MONTH_DAYS_REGULAR', + 'MONTH_DAYS_LEAP', + 'MONTH_DAYS_REGULAR_CUMULATIVE', + 'MONTH_DAYS_LEAP_CUMULATIVE', + 'SYSCALLS', + 'preloadPlugins', + 'FS_createPreloadedFile', + 'FS_preloadFile', + 'FS_modeStringToFlags', + 'FS_getMode', + 'FS_stdin_getChar_buffer', + 'FS_stdin_getChar', + 'FS_unlink', + 'FS_createPath', + 'FS_createDevice', + 'FS', + 'FS_root', + 'FS_mounts', + 'FS_devices', + 'FS_streams', + 'FS_nextInode', + 'FS_nameTable', + 'FS_currentPath', + 'FS_initialized', + 'FS_ignorePermissions', + 'FS_filesystems', + 'FS_syncFSRequests', + 'FS_readFiles', + 'FS_lookupPath', + 'FS_getPath', + 'FS_hashName', + 'FS_hashAddNode', + 'FS_hashRemoveNode', + 'FS_lookupNode', + 'FS_createNode', + 'FS_destroyNode', + 'FS_isRoot', + 'FS_isMountpoint', + 'FS_isFile', + 'FS_isDir', + 'FS_isLink', + 'FS_isChrdev', + 'FS_isBlkdev', + 'FS_isFIFO', + 'FS_isSocket', + 'FS_flagsToPermissionString', + 'FS_nodePermissions', + 'FS_mayLookup', + 'FS_mayCreate', + 'FS_mayDelete', + 'FS_mayOpen', + 'FS_checkOpExists', + 'FS_nextfd', + 'FS_getStreamChecked', + 'FS_getStream', + 'FS_createStream', + 'FS_closeStream', + 'FS_dupStream', + 'FS_doSetAttr', + 'FS_chrdev_stream_ops', + 'FS_major', + 'FS_minor', + 'FS_makedev', + 'FS_registerDevice', + 'FS_getDevice', + 'FS_getMounts', + 'FS_syncfs', + 'FS_mount', + 'FS_unmount', + 'FS_lookup', + 'FS_mknod', + 'FS_statfs', + 'FS_statfsStream', + 'FS_statfsNode', + 'FS_create', + 'FS_mkdir', + 'FS_mkdev', + 'FS_symlink', + 'FS_rename', + 'FS_rmdir', + 'FS_readdir', + 'FS_readlink', + 'FS_stat', + 'FS_fstat', + 'FS_lstat', + 'FS_doChmod', + 'FS_chmod', + 'FS_lchmod', + 'FS_fchmod', + 'FS_doChown', + 'FS_chown', + 'FS_lchown', + 'FS_fchown', + 'FS_doTruncate', + 'FS_truncate', + 'FS_ftruncate', + 'FS_utime', + 'FS_open', + 'FS_close', + 'FS_isClosed', + 'FS_llseek', + 'FS_read', + 'FS_write', + 'FS_mmap', + 'FS_msync', + 'FS_ioctl', + 'FS_cwd', + 'FS_chdir', + 'FS_createDefaultDirectories', + 'FS_createDefaultDevices', + 'FS_createSpecialDirectories', + 'FS_createStandardStreams', + 'FS_staticInit', + 'FS_init', + 'FS_quit', + 'FS_findObject', + 'FS_analyzePath', + 'FS_createFile', + 'FS_createDataFile', + 'FS_forceLoadFile', + 'FS_createLazyFile', + 'FS_absolutePath', + 'FS_createFolder', + 'FS_createLink', + 'FS_joinPath', + 'FS_mmapAlloc', + 'FS_standardizePath', + 'MEMFS', + 'TTY', + 'PIPEFS', + 'SOCKFS', + 'tempFixedLengthArray', + 'miniTempWebGLFloatBuffers', + 'miniTempWebGLIntBuffers', + 'GL', + 'AL', + 'GLUT', + 'EGL', + 'GLEW', + 'IDBStore', + 'SDL', + 'SDL_gfx', + 'allocateUTF8', + 'allocateUTF8OnStack', + 'print', + 'printErr', + 'jstoi_s', +]; +unexportedSymbols.forEach(unexportedRuntimeSymbol); + + // End runtime exports + // Begin JS library exports + // End JS library exports + +// end include: postlibrary.js + +function checkIncomingModuleAPI() { + ignoredModuleProp('fetchSettings'); +} + +// Imports from the Wasm binary. +var _main = Module['_main'] = makeInvalidEarlyAccess('_main'); +var _fflush = makeInvalidEarlyAccess('_fflush'); +var _strerror = makeInvalidEarlyAccess('_strerror'); +var _emscripten_stack_get_end = makeInvalidEarlyAccess('_emscripten_stack_get_end'); +var _emscripten_stack_get_base = makeInvalidEarlyAccess('_emscripten_stack_get_base'); +var _emscripten_stack_init = makeInvalidEarlyAccess('_emscripten_stack_init'); +var _emscripten_stack_get_free = makeInvalidEarlyAccess('_emscripten_stack_get_free'); +var __emscripten_stack_restore = makeInvalidEarlyAccess('__emscripten_stack_restore'); +var __emscripten_stack_alloc = makeInvalidEarlyAccess('__emscripten_stack_alloc'); +var _emscripten_stack_get_current = makeInvalidEarlyAccess('_emscripten_stack_get_current'); +var wasmMemory = makeInvalidEarlyAccess('wasmMemory'); +var wasmTable = makeInvalidEarlyAccess('wasmTable'); + +function assignWasmExports(wasmExports) { + _main = Module['_main'] = createExportWrapper('__main_argc_argv', 2); + _fflush = createExportWrapper('fflush', 1); + _strerror = createExportWrapper('strerror', 1); + _emscripten_stack_get_end = wasmExports['emscripten_stack_get_end']; + _emscripten_stack_get_base = wasmExports['emscripten_stack_get_base']; + _emscripten_stack_init = wasmExports['emscripten_stack_init']; + _emscripten_stack_get_free = wasmExports['emscripten_stack_get_free']; + __emscripten_stack_restore = wasmExports['_emscripten_stack_restore']; + __emscripten_stack_alloc = wasmExports['_emscripten_stack_alloc']; + _emscripten_stack_get_current = wasmExports['emscripten_stack_get_current']; + wasmMemory = wasmExports['memory']; + wasmTable = wasmExports['__indirect_function_table']; +} + +var wasmImports = { + /** @export */ + __assert_fail: ___assert_fail, + /** @export */ + __cxa_throw: ___cxa_throw, + /** @export */ + __syscall_fcntl64: ___syscall_fcntl64, + /** @export */ + __syscall_ioctl: ___syscall_ioctl, + /** @export */ + __syscall_openat: ___syscall_openat, + /** @export */ + _abort_js: __abort_js, + /** @export */ + _tzset_js: __tzset_js, + /** @export */ + emscripten_resize_heap: _emscripten_resize_heap, + /** @export */ + environ_get: _environ_get, + /** @export */ + environ_sizes_get: _environ_sizes_get, + /** @export */ + fd_close: _fd_close, + /** @export */ + fd_read: _fd_read, + /** @export */ + fd_seek: _fd_seek, + /** @export */ + fd_write: _fd_write, + /** @export */ + random_get: _random_get +}; + + +// include: postamble.js +// === Auto-generated postamble setup entry stuff === + +var calledRun; + +function callMain(args = []) { + assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])'); + assert(typeof onPreRuns === 'undefined' || onPreRuns.length == 0, 'cannot call main when preRun functions remain to be called'); + + var entryFunction = _main; + + args.unshift(thisProgram); + + var argc = args.length; + var argv = stackAlloc((argc + 1) * 4); + var argv_ptr = argv; + args.forEach((arg) => { + HEAPU32[((argv_ptr)>>2)] = stringToUTF8OnStack(arg); + argv_ptr += 4; + }); + HEAPU32[((argv_ptr)>>2)] = 0; + + try { + + var ret = entryFunction(argc, argv); + + // if we're not running an evented main loop, it's time to exit + exitJS(ret, /* implicit = */ true); + return ret; + } catch (e) { + return handleException(e); + } +} + +function stackCheckInit() { + // This is normally called automatically during __wasm_call_ctors but need to + // get these values before even running any of the ctors so we call it redundantly + // here. + _emscripten_stack_init(); + // TODO(sbc): Move writeStackCookie to native to to avoid this. + writeStackCookie(); +} + +function run(args = arguments_) { + + if (runDependencies > 0) { + dependenciesFulfilled = run; + return; + } + + stackCheckInit(); + + preRun(); + + // a preRun added a dependency, run will be called later + if (runDependencies > 0) { + dependenciesFulfilled = run; + return; + } + + function doRun() { + // run may have just been called through dependencies being fulfilled just in this very frame, + // or while the async setStatus time below was happening + assert(!calledRun); + calledRun = true; + Module['calledRun'] = true; + + if (ABORT) return; + + initRuntime(); + + preMain(); + + readyPromiseResolve?.(Module); + Module['onRuntimeInitialized']?.(); + consumedModuleProp('onRuntimeInitialized'); + + var noInitialRun = Module['noInitialRun'] || true; + if (!noInitialRun) callMain(args); + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(() => { + setTimeout(() => Module['setStatus'](''), 1); + doRun(); + }, 1); + } else + { + doRun(); + } + checkStackCookie(); +} + +function checkUnflushedContent() { + // Compiler settings do not allow exiting the runtime, so flushing + // the streams is not possible. but in ASSERTIONS mode we check + // if there was something to flush, and if so tell the user they + // should request that the runtime be exitable. + // Normally we would not even include flush() at all, but in ASSERTIONS + // builds we do so just for this check, and here we see if there is any + // content to flush, that is, we check if there would have been + // something a non-ASSERTIONS build would have not seen. + // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0 + // mode (which has its own special function for this; otherwise, all + // the code is inside libc) + var oldOut = out; + var oldErr = err; + var has = false; + out = err = (x) => { + has = true; + } + try { // it doesn't matter if it fails + _fflush(0); + // also flush in the JS FS layer + ['stdout', 'stderr'].forEach((name) => { + var info = FS.analyzePath('/dev/' + name); + if (!info) return; + var stream = info.object; + var rdev = stream.rdev; + var tty = TTY.ttys[rdev]; + if (tty?.output?.length) { + has = true; + } + }); + } catch(e) {} + out = oldOut; + err = oldErr; + if (has) { + warnOnce('stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc.'); + } +} + +var wasmExports; + +// In modularize mode the generated code is within a factory function so we +// can use await here (since it's not top-level-await). +wasmExports = await (createWasm()); + +run(); + +// end include: postamble.js + +// include: postamble_modularize.js +// In MODULARIZE mode we wrap the generated code in a factory function +// and return either the Module itself, or a promise of the module. +// +// We assign to the `moduleRtn` global here and configure closure to see +// this as and extern so it won't get minified. + +if (runtimeInitialized) { + moduleRtn = Module; +} else { + // Set up the promise that indicates the Module is initialized + moduleRtn = new Promise((resolve, reject) => { + readyPromiseResolve = resolve; + readyPromiseReject = reject; + }); +} + +// Assertion for attempting to access module properties on the incoming +// moduleArg. In the past we used this object as the prototype of the module +// and assigned properties to it, but now we return a distinct object. This +// keeps the instance private until it is ready (i.e the promise has been +// resolved). +for (const prop of Object.keys(Module)) { + if (!(prop in moduleArg)) { + Object.defineProperty(moduleArg, prop, { + configurable: true, + get() { + abort(`Access to module property ('${prop}') is no longer possible via the module constructor argument; Instead, use the result of the module constructor.`) + } + }); + } +} +// end include: postamble_modularize.js + + + + return moduleRtn; + }; +})(); + +// Export using a UMD style export, or ES6 exports if selected +if (typeof exports === 'object' && typeof module === 'object') { + module.exports = RmRenderer; + // This default export looks redundant, but it allows TS to import this + // commonjs style module. + module.exports.default = RmRenderer; +} else if (typeof define === 'function' && define['amd']) + define([], () => RmRenderer); + diff --git a/ui/public/assets/rm_lines_simple_renderer.wasm b/ui/public/assets/rm_lines_simple_renderer.wasm new file mode 100755 index 0000000000000000000000000000000000000000..5c3fc94fd7c7c3c0545b2415c0615b8c4adcff76 GIT binary patch literal 1041117 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�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 { + let res: Response; + try { + res = await fetch(`${constants.ROOT_URL}/documents/${id}/blobs`, { + credentials: "same-origin", + }); + } catch { + return null; + } + if (!res.ok) { + return null; + } + let blobTree: Record; + try { + blobTree = JSON.parse(new TextDecoder().decode(await res.arrayBuffer())) as Record; + } catch { + return null; + } + const contentKey = `${id}.content`; + if (!blobTree[contentKey]) { + return null; + } + const hasRm = Object.keys(blobTree).some((k) => k.endsWith(".rm")); + if (!hasRm) { + return null; + } + + return { + rootDocId: id, + pageCount: Object.keys(blobTree).filter((e) => e.endsWith(".rm")).length, + loadSubFile: async (subFile: string) => { + const hash = blobTree[subFile]; + if (!hash) { + throw new Error(`missing blob mapping for ${subFile}`); + } + const br = await fetch(`${constants.ROOT_URL}/blobs/${hash}`, { + credentials: "same-origin", + }); + if (!br.ok) { + throw new Error(`blob fetch failed ${br.status}`); + } + return new Uint8Array(await br.arrayBuffer()); + }, + }; +} diff --git a/ui/src/components/RmLinesRenderer.tsx b/ui/src/components/RmLinesRenderer.tsx new file mode 100644 index 00000000..4f4ee1b3 --- /dev/null +++ b/ui/src/components/RmLinesRenderer.tsx @@ -0,0 +1,243 @@ +import { useEffect, useRef, useState } from "react"; + +export interface DocumentEnvironment { + rootDocId: string; + pageCount: number; + loadSubFile(name: string): Promise; +} + +interface RmRendererApi { + callMain(args: string[]): Promise; + FS_writeFile(name: string, data: Uint8Array): void; + FS_readFile(name: string): Uint8Array; +} + +interface RmLinesRendererProps { + environment: DocumentEnvironment | null; + page: number; +} + +interface Page { + uuid: string; +} + +/** reMarkable .content uses top-level `pages` (UUID strings) and sometimes cPages.pages with { id }. */ +function pageIdsFromContentJson(contentData: unknown): string[] { + if (!contentData || typeof contentData !== "object") { + return []; + } + const o = contentData as Record; + const cPages = o.cPages as { pages?: { id?: string; deleted?: unknown }[] } | undefined; + if (cPages?.pages?.length) { + return cPages.pages.filter((e) => e && !e.deleted && e.id).map((e) => String(e.id)); + } + const pages = o.pages; + if (!Array.isArray(pages)) { + return []; + } + const out: string[] = []; + for (const p of pages) { + if (typeof p === "string" && p) { + out.push(p); + } else if (p && typeof p === "object" && "id" in p && (p as { id?: string }).id) { + out.push(String((p as { id: string }).id)); + } + } + return out; +} + +async function loadPages(env: DocumentEnvironment): Promise { + const contentFile = `${env.rootDocId}.content`; + const raw = await env.loadSubFile(contentFile); + const contentData = JSON.parse(new TextDecoder().decode(raw)) as unknown; + return pageIdsFromContentJson(contentData).map((uuid) => ({ uuid })); +} + +async function loadRmBytes(env: DocumentEnvironment, uuid: string): Promise { + const candidates = [`${uuid}.rm`, `${env.rootDocId}/${uuid}.rm`]; + let lastErr: Error | null = null; + for (const path of candidates) { + try { + return await env.loadSubFile(path); + } catch (e) { + lastErr = e instanceof Error ? e : new Error(String(e)); + } + } + throw lastErr ?? new Error("no .rm blob for page"); +} + +async function renderFrame(renderer: RmRendererApi, rawData: Uint8Array) { + renderer.FS_writeFile("/rm", rawData); + await renderer.callMain(["/rm", "/bmp"]); + const bitmap = renderer.FS_readFile("/bmp"); + const u8 = bitmap instanceof Uint8Array ? bitmap : new Uint8Array(bitmap); + const dv = new DataView(u8.buffer, u8.byteOffset, u8.byteLength); + const width = dv.getUint32(0, false); + const height = dv.getUint32(4, false); + const expected = 8 + width * height * 4; + if (u8.byteLength < expected) { + throw new Error(`bitmap too small: ${u8.byteLength} < ${expected}`); + } + const rawContent = new Uint8ClampedArray(u8.buffer, u8.byteOffset + 8, width * height * 4); + const data = new ImageData(rawContent, width, height); + return { width, height, data }; +} + +export function RmLinesRenderer(props: RmLinesRendererProps) { + const [module, setModule] = useState(null); + const [moduleError, setModuleError] = useState(false); + const [pages, setPages] = useState([]); + const [pagesError, setPagesError] = useState(false); + const [busy, setBusy] = useState(false); + const [renderError, setRenderError] = useState(false); + const [drawnData, setDrawnData] = useState<{ + width: number; + height: number; + data: ImageData; + } | null>(null); + const canvasRef = useRef(null); + + useEffect(() => { + let cancelled = false; + (async () => { + try { + const Rm = (window as unknown as { RmRenderer?: () => Promise }).RmRenderer; + if (!Rm) { + setModuleError(true); + return; + } + const m = await Rm(); + if (!cancelled) { + setModule(m); + setModuleError(false); + } + } catch { + if (!cancelled) { + setModuleError(true); + } + } + })(); + return () => { + cancelled = true; + }; + }, []); + + useEffect(() => { + (async () => { + setPages([]); + setPagesError(false); + if (!props.environment) { + return; + } + try { + setPages(await loadPages(props.environment)); + } catch { + setPagesError(true); + } + })(); + }, [props.environment]); + + useEffect(() => { + if (!module || !props.environment) { + setDrawnData(null); + setBusy(false); + setRenderError(false); + return; + } + const pg = pages[props.page]; + if (!pg) { + setDrawnData(null); + setBusy(false); + setRenderError(false); + return; + } + + let cancelled = false; + (async () => { + setBusy(true); + setRenderError(false); + setDrawnData(null); + try { + const raw = await loadRmBytes(props.environment!, pg.uuid); + if (cancelled) { + return; + } + const frame = await renderFrame(module, raw); + if (!cancelled) { + setDrawnData(frame); + } + } catch (e) { + console.warn("RmLines render:", e); + if (!cancelled) { + setRenderError(true); + } + } finally { + if (!cancelled) { + setBusy(false); + } + } + })(); + return () => { + cancelled = true; + }; + }, [module, props.page, pages, props.environment]); + + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas || !drawnData) { + return; + } + const ctx = canvas.getContext("2d"); + if (!ctx) { + return; + } + canvas.width = drawnData.width; + canvas.height = drawnData.height; + ctx.putImageData(drawnData.data, 0, 0); + }, [drawnData]); + + if (moduleError) { + return ( +

+ Notebook line renderer (WASM) failed to load. Try refreshing the page. +

+ ); + } + + if (!module) { + return Loading line renderer…; + } + + if (pagesError) { + return ( +

+ Could not read notebook page list (.content). +

+ ); + } + + if (pages.length === 0 && props.environment) { + return

No pages in this notebook.

; + } + + return ( +
+ {busy && Rendering…} + {renderError && ( +

+ Could not render this page with the line engine (unsupported or corrupt .rm). +

+ )} + +
+ ); +} From 6854dcd7beafde71b7d2c83e497a4f94327fa7f2 Mon Sep 17 00:00:00 2001 From: Aaron C Date: Mon, 7 Sep 2026 21:29:40 -0400 Subject: [PATCH 2/9] feat: Templates & Methods browser --- internal/storage/filetypes.go | 1 + internal/storage/fs/documents.go | 37 +- internal/storage/models/hashdoc.go | 36 +- internal/storage/models/metadatafile.go | 1 + internal/ui/doc_tree.go | 46 +++ internal/ui/handlers.go | 69 +++- internal/ui/methods/methods.go | 131 +++++++ internal/ui/routes.go | 3 + internal/ui/templates/templates.go | 106 +++++ internal/ui/viewmodel/models.go | 165 ++++++-- ui/src/App.scss | 12 +- ui/src/common/constants.js | 6 +- ui/src/pages/Documents/FileList.jsx | 133 ++++++- ui/src/pages/Documents/MethodViewer.jsx | 15 + ui/src/pages/Documents/SvgDocViewer.jsx | 70 ++++ ui/src/pages/Documents/TemplateViewer.jsx | 15 + .../pages/Documents/TemplatesMethodsGrid.jsx | 362 ++++++++++++++++++ ui/src/pages/Documents/Tree.jsx | 2 +- ui/src/pages/Documents/index.jsx | 64 +++- ui/src/services/api.service.js | 250 +++++++++++- 20 files changed, 1441 insertions(+), 83 deletions(-) create mode 100644 internal/ui/doc_tree.go create mode 100644 internal/ui/methods/methods.go create mode 100644 internal/ui/templates/templates.go create mode 100644 ui/src/pages/Documents/MethodViewer.jsx create mode 100644 ui/src/pages/Documents/SvgDocViewer.jsx create mode 100644 ui/src/pages/Documents/TemplateViewer.jsx create mode 100644 ui/src/pages/Documents/TemplatesMethodsGrid.jsx diff --git a/internal/storage/filetypes.go b/internal/storage/filetypes.go index e1bf49e7..62716f66 100644 --- a/internal/storage/filetypes.go +++ b/internal/storage/filetypes.go @@ -5,6 +5,7 @@ const ( PageFileExt = ".pagedata" ContentFileExt = ".content" RmFileExt = ".rm" + TemplateFileExt = ".template" //ZipFileExt zip file extension ZipFileExt = ".zip" diff --git a/internal/storage/fs/documents.go b/internal/storage/fs/documents.go index f6a4335a..1324d7b1 100644 --- a/internal/storage/fs/documents.go +++ b/internal/storage/fs/documents.go @@ -8,6 +8,7 @@ import ( "os" "path" "path/filepath" + "strings" "time" "github.com/golang-jwt/jwt/v4" @@ -69,22 +70,14 @@ func (fs *FileSystemStorage) ExportDocument(uid, id, outputType string, exportOp return nil, fmt.Errorf("cant find raw document %v", err) } - outputFilePath := path.Join(cacheDirPath, sanitizedID+"-annotated.pdf") - outStat, err := os.Stat(outputFilePath) - - // exists and not older - if err == nil && !rawStat.ModTime().After(outStat.ModTime()) { - return os.Open(outputFilePath) - } - - size := rawStat.Size() - arch := &exporter.MyArchive{} zipFile, err := os.Open(zipFilePath) if err != nil { return nil, err } defer zipFile.Close() - err = arch.Read(zipFile, size) + + arch := &exporter.MyArchive{} + err = arch.Read(zipFile, rawStat.Size()) if err != nil { return nil, err } @@ -93,6 +86,28 @@ func (fs *FileSystemStorage) ExportDocument(uid, id, outputType string, exportOp arch.PayloadReader = exporter.NewSeekCloser(arch.Payload) } + // PDF: return original file bytes only (no annotation merge / re-render). + if strings.EqualFold(arch.Content.FileType, "pdf") && arch.PayloadReader != nil { + if _, err := arch.PayloadReader.Seek(0, io.SeekStart); err != nil { + return nil, err + } + return arch.PayloadReader, nil + } + + if strings.TrimSpace(fs.Cfg.RmrlPython) != "" { + if r, ok := tryExportPDFViaRmrl(fs.Cfg.RmrlPython, zipFilePath); ok { + return r, nil + } + } + + outputFilePath := path.Join(cacheDirPath, sanitizedID+"-annotated.pdf") + outStat, err := os.Stat(outputFilePath) + + // exists and not older + if err == nil && !rawStat.ModTime().After(outStat.ModTime()) { + return os.Open(outputFilePath) + } + outputFile, err := os.Create(outputFilePath) if err != nil { return nil, err diff --git a/internal/storage/models/hashdoc.go b/internal/storage/models/hashdoc.go index b46a9cf0..369f75bf 100644 --- a/internal/storage/models/hashdoc.go +++ b/internal/storage/models/hashdoc.go @@ -9,11 +9,13 @@ import ( "errors" "fmt" "io" + "path" "sort" "strconv" "strings" "github.com/ddvk/rmfakecloud/internal/common" + "github.com/ddvk/rmfakecloud/internal/storage" log "github.com/sirupsen/logrus" ) @@ -85,6 +87,35 @@ func (d *HashDoc) MetadataReader() (hash string, reader io.Reader, err error) { return } +// HasWritings returns true if the document has any .rm annotation pages. +func (d *HashDoc) HasWritings() bool { + for _, f := range d.Files { + if strings.ToLower(path.Ext(f.EntryName)) == storage.RmFileExt { + return true + } + } + return false +} + +// PayloadTypeFromFiles returns document type from file extensions only. +// Returns "epub", "pdf", "template", or "" (caller should use "notebook" or d.PayloadType when ""). +func (d *HashDoc) PayloadTypeFromFiles() string { + low := func(s string) string { return strings.ToLower(s) } + for _, f := range d.Files { + name := low(f.EntryName) + if strings.HasSuffix(name, storage.EpubFileExt) { + return "epub" + } + if strings.HasSuffix(name, storage.PdfFileExt) { + return "pdf" + } + if strings.HasSuffix(name, storage.TemplateFileExt) { + return "template" + } + } + return "" +} + // AddFile adds an entry func (d *HashDoc) AddFile(e *HashEntry) error { d.Files = append(d.Files, e) @@ -96,6 +127,7 @@ func (d *HashDoc) AddFile(e *HashEntry) error { return d.Rehash() } + type ErrDocumentExists struct { DocID string Name string @@ -180,7 +212,9 @@ func (d *HashDoc) readContent(hash string, r RemoteStorage) error { if err != nil { log.Printf("cannot read content %s %v", hash, err) } - d.PayloadType = contentFile.FileType + if len(contentBytes) > 4 && contentFile.FileType != "" { + d.PayloadType = contentFile.FileType + } if len(contentFile.SizeInBytes) > 0 { d.Size, err = strconv.ParseInt(contentFile.SizeInBytes, 10, 64) diff --git a/internal/storage/models/metadatafile.go b/internal/storage/models/metadatafile.go index 72c25082..28327a3c 100644 --- a/internal/storage/models/metadatafile.go +++ b/internal/storage/models/metadatafile.go @@ -12,6 +12,7 @@ import ( type MetadataFile struct { DocumentName string `json:"visibleName"` CollectionType common.EntryType `json:"type"` + Source string `json:"source,omitempty"` // e.g. "com.remarkable.methods" Parent string `json:"parent"` CreatedTime string `json:"createdTime"` LastModified string `json:"lastModified"` diff --git a/internal/ui/doc_tree.go b/internal/ui/doc_tree.go new file mode 100644 index 00000000..1e0d6e08 --- /dev/null +++ b/internal/ui/doc_tree.go @@ -0,0 +1,46 @@ +package ui + +import ( + "github.com/ddvk/rmfakecloud/internal/ui/methods" + "github.com/ddvk/rmfakecloud/internal/ui/templates" + "github.com/ddvk/rmfakecloud/internal/ui/viewmodel" +) + +// documentTreeFromBlob builds the web UI tree from the hash-tree (sync 1.5+ storage), +// merging builtin templates/methods. Used for both sync backends so types and previews match. +func documentTreeFromBlob(blobHandler blobHandler, uid string) (*viewmodel.DocumentTree, error) { + hashTree, err := blobHandler.GetCachedTree(uid) + if err != nil { + return nil, err + } + tree := viewmodel.DocTreeFromHashTree(hashTree) + tDir := templates.BuiltinTemplatesDirectory() + if len(tree.Templates) > 0 { + if d, ok := tree.Templates[0].(*viewmodel.Directory); ok { + tDir.Entries = append(tDir.Entries, d.Entries...) + } + } + tree.Templates = []viewmodel.Entry{tDir} + mDir := methods.BuiltinMethodsDirectory() + if len(tree.Methods) > 0 { + if d, ok := tree.Methods[0].(*viewmodel.Directory); ok { + mDir.Entries = append(mDir.Entries, d.Entries...) + } + } + tree.Methods = []viewmodel.Entry{mDir} + for _, e := range tDir.Entries { + if doc, ok := e.(*viewmodel.Document); ok { + if o, err := blobHandler.GetDocumentOrientation(uid, doc.ID); err == nil { + doc.Orientation = o + } + } + } + for _, e := range mDir.Entries { + if doc, ok := e.(*viewmodel.Document); ok { + if o, err := blobHandler.GetDocumentOrientation(uid, doc.ID); err == nil { + doc.Orientation = o + } + } + } + return tree, nil +} diff --git a/internal/ui/handlers.go b/internal/ui/handlers.go index 9571d4ab..81b88c3a 100644 --- a/internal/ui/handlers.go +++ b/internal/ui/handlers.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "net/http" "time" @@ -12,6 +13,8 @@ import ( "github.com/ddvk/rmfakecloud/internal/model" "github.com/ddvk/rmfakecloud/internal/storage" "github.com/ddvk/rmfakecloud/internal/storage/models" + "github.com/ddvk/rmfakecloud/internal/ui/methods" + "github.com/ddvk/rmfakecloud/internal/ui/templates" "github.com/ddvk/rmfakecloud/internal/ui/viewmodel" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v4" @@ -269,10 +272,10 @@ func (app *ReactAppWrapper) getDocument(c *gin.Context) { uid := userID(c) docid := common.ParamS(docIDParam, c) - exportType := c.DefaultQuery("type", "pdf") + exportType := "pdf" var exportOption storage.ExportOption = 0 - log.Info("exporting ", docid, " as ", exportType) + log.Info("exporting ", docid) backend := app.getBackend(c) reader, err := backend.Export(uid, docid, exportType, exportOption) @@ -283,12 +286,11 @@ func (app *ReactAppWrapper) getDocument(c *gin.Context) { } defer reader.Close() - - if exportType == "rmdoc" { - c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s.rmdoc\"", docid)) - } - - c.DataFromReader(http.StatusOK, -1, "application/octet-stream", reader, nil) + // Raw PDF bytes; filename uses visible document name when available. + filename := backend.PDFInlineFilename(uid, docid) + c.Header("Content-Disposition", fmt.Sprintf("inline; filename=%q", filename)) + c.Header("X-Content-Type-Options", "nosniff") + c.DataFromReader(http.StatusOK, -1, "application/pdf", reader, nil) } func (app *ReactAppWrapper) getDocumentMetadata(c *gin.Context) { @@ -898,6 +900,57 @@ func (app *ReactAppWrapper) screenshareDeleteRoom(c *gin.Context) { c.Status(http.StatusNoContent) } +func (app *ReactAppWrapper) getTemplate(c *gin.Context) { + uid := userID(c) + docid := common.ParamS(docIDParam, c) + + backend := app.getBackend(c) + // only sync15 backends have templates + type templateGetter interface { + GetTemplate(uid, docid string) (io.ReadCloser, error) + } + tg, ok := backend.(templateGetter) + if !ok { + c.AbortWithStatus(http.StatusNotFound) + return + } + reader, err := tg.GetTemplate(uid, docid) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusNotFound) + return + } + defer reader.Close() + + c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%q", docid+storage.TemplateFileExt)) + c.Header("X-Content-Type-Options", "nosniff") + c.DataFromReader(http.StatusOK, -1, "application/octet-stream", reader, nil) +} + +func (app *ReactAppWrapper) getBuiltinTemplate(c *gin.Context) { + id := c.Param("id") + svg := templates.GetSVG(id) + if svg == "" { + c.AbortWithStatus(http.StatusNotFound) + return + } + c.Header("Content-Type", "image/svg+xml") + c.Header("X-Content-Type-Options", "nosniff") + c.String(http.StatusOK, svg) +} + +func (app *ReactAppWrapper) getBuiltinMethod(c *gin.Context) { + id := c.Param("id") + svg := methods.GetSVG(id) + if svg == "" { + c.AbortWithStatus(http.StatusNotFound) + return + } + c.Header("Content-Type", "image/svg+xml") + c.Header("X-Content-Type-Options", "nosniff") + c.String(http.StatusOK, svg) +} + func (app *ReactAppWrapper) getRawBlob(c *gin.Context) { uid := userID(c) blobid := common.ParamS(blobIDParam, c) diff --git a/internal/ui/methods/methods.go b/internal/ui/methods/methods.go new file mode 100644 index 00000000..d9cd7a04 --- /dev/null +++ b/internal/ui/methods/methods.go @@ -0,0 +1,131 @@ +package methods + +import ( + "fmt" + "math" + "time" + + "github.com/ddvk/rmfakecloud/internal/ui/viewmodel" +) + +// reMarkable 2 nominal dimensions (points at 1404x1872) +const width = 1404 +const height = 1872 + +var builtins = []struct { + id string + name string + svg string +}{ + {id: "cornell", name: "Cornell Notes", svg: cornellSVG()}, + {id: "outline", name: "Outline", svg: outlineSVG()}, + {id: "mindmap", name: "Mind Map", svg: mindmapSVG()}, + {id: "flowchart", name: "Flowchart", svg: flowchartSVG()}, + {id: "checklist", name: "Checklist", svg: checklistSVG()}, +} + +func cornellSVG() string { + // Left column ~25%, right margin, bottom summary area + cueW := width / 4 + summaryH := height / 5 + return fmt.Sprintf(` + + + +Cues +Notes +Summary +`, + width, height, width, height, + cueW, cueW, height, + height-summaryH, width, height-summaryH, + cueW/2-20, cueW+40, + height-summaryH+32, + ) +} + +func outlineSVG() string { + indent := 80 + lineH := 52 + lines := "" + for i := 0; i < 28; i++ { + y := 60 + i*lineH + level := i % 4 + x := 40 + level*indent + lines += fmt.Sprintf(``, x, y+20, width-40, y+20) + } + return fmt.Sprintf(`%s`, width, height, width, height, lines) +} + +func mindmapSVG() string { + cx, cy := width/2, height/2 + r := 120 + nodes := 6 + lines := "" + for i := 0; i < nodes; i++ { + angle := float64(i) * (2 * math.Pi / float64(nodes)) + x := int(float64(cx) + float64(r)*math.Cos(angle)) + y := int(float64(cy) + float64(r)*math.Sin(angle)) + lines += fmt.Sprintf(``, cx, cy, x, y) + lines += fmt.Sprintf(``, x, y) + } + lines += fmt.Sprintf(``, cx, cy) + return fmt.Sprintf(`%sTopic`, width, height, width, height, lines, cx, cy+8) +} + +func flowchartSVG() string { + // Simple flowchart: start -> process -> decision -> end + bw, bh := 200, 56 + x1, y := width/2-bw/2, 200 + x2 := width/2 - 80 + x3 := width/2 - 40 + lines := fmt.Sprintf(``, x1, y, bw, bh) + lines += fmt.Sprintf(``, x2, 320, bh) + lines += fmt.Sprintf(``, x3, 420, x3-50, 500, x3+50, 500) + lines += fmt.Sprintf(``, width/2-80, 160, bh) + lines += `` + lines += `` + lines += `` + return fmt.Sprintf(`%s`, width, height, width, height, lines) +} + +func checklistSVG() string { + lines := "" + step := 56 + for y := 80; y < height-80; y += step { + lines += fmt.Sprintf(``, y) + lines += fmt.Sprintf(``, y+14, width-40, y+14) + } + return fmt.Sprintf(`%s`, width, height, width, height, lines) +} + +// BuiltinMethodsDirectory returns a Directory entry "Methods" with method documents as children. +func BuiltinMethodsDirectory() *viewmodel.Directory { + children := make([]viewmodel.Entry, 0, len(builtins)) + for _, b := range builtins { + children = append(children, &viewmodel.Document{ + ID: b.id, + Name: b.name, + DocumentType: "method", + LastModified: time.Time{}, + Size: 0, + }) + } + return &viewmodel.Directory{ + ID: "methods", + Name: "rm Methods", + Entries: children, + LastModified: time.Time{}, + IsFolder: true, + } +} + +// GetSVG returns the SVG content for a method ID, or empty string if not found. +func GetSVG(id string) string { + for _, b := range builtins { + if b.id == id { + return b.svg + } + } + return "" +} diff --git a/internal/ui/routes.go b/internal/ui/routes.go index d77b557d..85616f7a 100644 --- a/internal/ui/routes.go +++ b/internal/ui/routes.go @@ -86,6 +86,9 @@ func (app *ReactAppWrapper) RegisterRoutes(router *gin.Engine) { auth.GET("integrations/:intid/metadata/*path", app.getMetadataIntegration) auth.GET("integrations/:intid/download/*path", app.downloadThroughIntegration) + auth.GET("documents/:docid/template", app.getTemplate) + auth.GET("templates/:id", app.getBuiltinTemplate) + auth.GET("methods/:id", app.getBuiltinMethod) auth.GET("blobs/:blobid", app.getRawBlob) auth.GET("documents/:docid/blobs", app.getBlobTree) ss := auth.Group("screenshare") diff --git a/internal/ui/templates/templates.go b/internal/ui/templates/templates.go new file mode 100644 index 00000000..cadf45fb --- /dev/null +++ b/internal/ui/templates/templates.go @@ -0,0 +1,106 @@ +package templates + +import ( + "fmt" + "time" + + "github.com/ddvk/rmfakecloud/internal/ui/viewmodel" +) + +// reMarkable 2 nominal dimensions (points at 1404x1872) +const width = 1404 +const height = 1872 + +var builtins = []struct { + id string + name string + svg string +}{ + { + id: "blank", + name: "Blank", + svg: blankSVG(), + }, + { + id: "lined", + name: "Lined", + svg: linedSVG(), + }, + { + id: "grid", + name: "Grid", + svg: gridSVG(), + }, + { + id: "dotted", + name: "Dotted", + svg: dottedSVG(), + }, +} + +func blankSVG() string { + return fmt.Sprintf(``, width, height, width, height) +} + +func linedSVG() string { + lines := "" + step := 48 + for y := step; y < height; y += step { + lines += fmt.Sprintf(``, y, width, y) + } + return fmt.Sprintf(`%s`, width, height, width, height, lines) +} + +func gridSVG() string { + lines := "" + step := 36 + for x := step; x < width; x += step { + lines += fmt.Sprintf(``, x, x, height) + } + for y := step; y < height; y += step { + lines += fmt.Sprintf(``, y, width, y) + } + return fmt.Sprintf(`%s`, width, height, width, height, lines) +} + +func dottedSVG() string { + dots := "" + step := 24 + for y := step; y < height; y += step { + for x := step; x < width; x += step { + dots += fmt.Sprintf(``, x, y) + } + } + return fmt.Sprintf(`%s`, width, height, width, height, dots) +} + +// BuiltinTemplatesDirectory returns a Directory entry "Templates" with template documents as children. +func BuiltinTemplatesDirectory() *viewmodel.Directory { + children := make([]viewmodel.Entry, 0, len(builtins)) + for _, b := range builtins { + children = append(children, &viewmodel.Document{ + ID: b.id, + Name: b.name, + DocumentType: "template", + LastModified: time.Time{}, + Size: 0, + }) + } + return &viewmodel.Directory{ + ID: "templates", + Name: "Templates", + Entries: children, + LastModified: time.Time{}, + IsFolder: true, + } +} + +// GetSVG returns the SVG content for a template ID, or empty string if not found. +func GetSVG(id string) string { + for _, b := range builtins { + if b.id == id { + return b.svg + } + } + return "" +} diff --git a/internal/ui/viewmodel/models.go b/internal/ui/viewmodel/models.go index d58ed65f..748e5ce9 100644 --- a/internal/ui/viewmodel/models.go +++ b/internal/ui/viewmodel/models.go @@ -35,16 +35,48 @@ type ChangeEmailForm struct { type ErrorResponse struct { Error string `json:"error"` } + func NewErrorResponse(errormsg string) ErrorResponse { - return ErrorResponse { + return ErrorResponse{ Error: errormsg, } } +// RegisteredDeviceEntry is a safe JSON view of a paired tablet (no secrets). +type RegisteredDeviceEntry struct { + DeviceID string `json:"deviceId"` + DeviceDesc string `json:"deviceDesc"` + DeviceLink string `json:"deviceLink,omitempty"` + Make string `json:"make,omitempty"` + Model string `json:"model,omitempty"` + Year string `json:"year,omitempty"` + RegisteredAt string `json:"registeredAt,omitempty"` + LastSeen string `json:"lastSeen,omitempty"` +} + +// RegisteredDevicesResponse lists devices for the logged-in user. +type RegisteredDevicesResponse struct { + Devices []RegisteredDeviceEntry `json:"devices"` +} + +// ReissueDeviceRequest asks for a new device JWT without a pairing code (web session only). +type ReissueDeviceRequest struct { + DeviceID string `json:"deviceId" binding:"required"` + DeviceDesc string `json:"deviceDesc"` + DeviceLink string `json:"deviceLink,omitempty"` +} + +// ReissueDeviceResponse returns the raw device token for the tablet. +type ReissueDeviceResponse struct { + Token string `json:"token"` +} + // DocumentTree a tree of documents type DocumentTree struct { - Entries []Entry - Trash []Entry + Entries []Entry + Trash []Entry + Templates []Entry // [ Directory ] for frontend; optional + Methods []Entry // [ Directory ] for frontend; synced + builtin merged in backend } type InternalDoc struct { @@ -57,6 +89,9 @@ type InternalDoc struct { CurrentPage int Parent string Size int64 + HasWritings bool + Orientation string // from .content: "portrait", "landscape", or "" + Pinned bool // starred in metadata } func makeFolder(d *InternalDoc) (entry *Directory) { @@ -75,35 +110,103 @@ func makeDocument(d *InternalDoc) (entry Entry) { Name: d.Name, LastModified: d.LastModified, DocumentType: d.FileType, + Collection: d.Type, Size: d.Size, + HasWritings: d.HasWritings, + Orientation: d.Orientation, + Pinned: d.Pinned, } return } -// DocTreeFromHashTree from hash tree +// methodsSource is the reMarkable metadata source for rm Methods. +const methodsSource = "com.remarkable.methods" + +// templateType is the collection type for Templates (device/synced templates). +const templateType = common.EntryType("TemplateType") + +// fileTypeFromDoc returns document type by file extension, .content fileType (when size > 4), or "notebook". +func fileTypeFromDoc(d *models.HashDoc) string { + if t := d.PayloadTypeFromFiles(); t != "" { + return t + } + if d.PayloadType != "" { + return d.PayloadType + } + return "notebook" +} + +// DocTreeFromHashTree from hash tree. Templates and Methods are separated into their own sections. func DocTreeFromHashTree(tree *models.HashTree) *DocumentTree { docs := make([]*InternalDoc, 0) + templateDocs := make([]*InternalDoc, 0) + methodDocs := make([]*InternalDoc, 0) for _, d := range tree.Docs { if d.Deleted { continue } - lastModified, err := models.ToTime(d.LastModified) if err != nil { log.Warn("incorrect lastmodified for: ", d.DocumentName, " value: ", d.LastModified, " ", err) } - docs = append(docs, &InternalDoc{ + ft := fileTypeFromDoc(d) + internalDoc := &InternalDoc{ ID: d.EntryName, Parent: d.MetadataFile.Parent, Name: d.MetadataFile.DocumentName, Type: d.MetadataFile.CollectionType, LastModified: lastModified, - FileType: d.PayloadType, + FileType: ft, Size: d.Size, - }) + HasWritings: d.HasWritings(), + Pinned: d.MetadataFile.Pinned, + } + if d.MetadataFile.Source == methodsSource { + methodDocs = append(methodDocs, internalDoc) + continue + } + if d.MetadataFile.CollectionType == templateType { + templateDocs = append(templateDocs, internalDoc) + continue + } + docs = append(docs, internalDoc) } + dt := DocTreeFromRawMetadata(docs) + dt.Templates = templateEntriesToDirectory(templateDocs) + dt.Methods = methodEntriesToDirectory(methodDocs) + return dt +} - return DocTreeFromRawMetadata(docs) +// templateEntriesToDirectory returns a single Directory (as []Entry) for synced template documents. +func templateEntriesToDirectory(templateDocs []*InternalDoc) []Entry { + children := make([]Entry, 0, len(templateDocs)) + for _, d := range templateDocs { + children = append(children, makeDocument(d)) + } + dir := &Directory{ + ID: "templates", + Name: "Templates", + Entries: children, + LastModified: time.Time{}, + IsFolder: true, + } + return []Entry{dir} +} + +// methodEntriesToDirectory returns a single Directory (as []Entry) for method documents with type by extension. +func methodEntriesToDirectory(methodDocs []*InternalDoc) []Entry { + children := make([]Entry, 0, len(methodDocs)) + for _, d := range methodDocs { + children = append(children, makeDocument(d)) + } + dir := &Directory{ + ID: "methods", + Name: "rm Methods", + Entries: children, + LastModified: time.Time{}, + IsFolder: true, + } + return []Entry{dir} } // DocTreeFromRawMetadata from raw metadata @@ -176,8 +279,10 @@ func DocTreeFromRawMetadata(documents []*InternalDoc) *DocumentTree { } tree := DocumentTree{ - Entries: rootEntries, - Trash: trashEntries, + Entries: rootEntries, + Trash: trashEntries, + Templates: nil, + Methods: nil, } return &tree @@ -198,11 +303,15 @@ type Directory struct { // Document is a single document type Document struct { - ID string `json:"id"` - Name string `json:"name"` - DocumentType string `json:"type"` //notebook, pdf, epub - LastModified time.Time `json:"lastModified"` - Size int64 `json:"size"` + ID string `json:"id"` + Name string `json:"name"` + DocumentType string `json:"type"` // notebook, pdf, epub + Collection common.EntryType `json:"collectionType"` + LastModified time.Time `json:"lastModified"` + Size int64 `json:"size"` + HasWritings bool `json:"hasWritings"` + Orientation string `json:"orientation,omitempty"` // from .content: "portrait", "landscape", or empty if both/unspecified + Pinned bool `json:"pinned,omitempty"` } // DocumentList is a list of documents @@ -212,13 +321,18 @@ type DocumentList struct { // User user model type User struct { - ID string `json:"userid"` - Email string `json:"email"` - Name string `json:"name"` - NewPassword string `json:"newpassword,omitempty"` - IsAdmin bool `json:"isAdmin"` - CreatedAt time.Time - Integrations []string `json:"integrations,omitempty"` + ID string `json:"userid"` + Email string `json:"email"` + Name string `json:"name"` + NewPassword string `json:"newpassword,omitempty"` + IsAdmin bool `json:"isAdmin"` + CreatedAt time.Time + PasswordChangedAt time.Time + LastLoginAt time.Time + FileUsageBytes int64 + QuotaBytes *int64 `json:"quotaBytes,omitempty"` + Integrations []string `json:"integrations,omitempty"` + RegisteredDevices []RegisteredDeviceEntry `json:"registeredDevices,omitempty"` } // NewUser new user creation @@ -228,6 +342,11 @@ type NewUser struct { NewPassword string `json:"newpassword" binding:"required"` } +// SuRequest asks server to issue a web token for target user. +type SuRequest struct { + UserID string `json:"userid" binding:"required"` +} + // UpdateDoc with somethin type UpdateDoc struct { DocumentID string `json:"documentId" binding:"required"` diff --git a/ui/src/App.scss b/ui/src/App.scss index 577534fd..5531baa1 100644 --- a/ui/src/App.scss +++ b/ui/src/App.scss @@ -97,7 +97,7 @@ div[role="button"] > p { gap: 2em; } -canvas { +canvas:not(.rmrender) { margin: auto; width: auto !important; height: auto !important; @@ -274,3 +274,13 @@ main h2 { .flex-spacer { flex: 1; } + +div.rmrender-wrapper { + display: flex; + justify-content: center; +} + +div.rmrender-wrapper canvas { + max-width: 50%; + margin: auto; +} diff --git a/ui/src/common/constants.js b/ui/src/common/constants.js index 2a7d5a98..747443ca 100644 --- a/ui/src/common/constants.js +++ b/ui/src/common/constants.js @@ -1,5 +1,9 @@ const constants = { - ROOT_URL : "/ui/api" + ROOT_URL : "/ui/api", + // Optional: set VITE_ADOBE_PDF_CLIENT_ID for "Original PDF" (no drawings) viewer + ADOBE_CLIENT_ID: typeof import.meta !== "undefined" && import.meta.env?.VITE_ADOBE_PDF_CLIENT_ID + ? import.meta.env.VITE_ADOBE_PDF_CLIENT_ID + : "", } export default constants \ No newline at end of file diff --git a/ui/src/pages/Documents/FileList.jsx b/ui/src/pages/Documents/FileList.jsx index 07f3aeb7..6d02e843 100644 --- a/ui/src/pages/Documents/FileList.jsx +++ b/ui/src/pages/Documents/FileList.jsx @@ -1,4 +1,4 @@ -import { useMemo } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { Stack } from "react-bootstrap"; import { useReactTable, @@ -20,11 +20,63 @@ function formatBytes(bytes) { return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } +function displayName(data) { + const name = data?.name || ""; + return data?.pinned ? `${name} ★` : name; +} + export default function FileListViewer({ listStyle, files, onSelect, counter, selectedIds = [], onSelectItem }) { const onClickItem = (file) => { onSelect(file); } + const [contextMenu, setContextMenu] = useState(null); // { x, y, file } + const contextMenuRef = useRef(null); + + useEffect(() => { + if (!contextMenu) return; + const onDown = (e) => { + // Close if click outside the menu. + if (contextMenuRef.current && !contextMenuRef.current.contains(e.target)) { + setContextMenu(null); + } + }; + const onKey = (e) => { + if (e.key === "Escape") setContextMenu(null); + }; + window.addEventListener("mousedown", onDown); + window.addEventListener("keydown", onKey); + return () => { + window.removeEventListener("mousedown", onDown); + window.removeEventListener("keydown", onKey); + }; + }, [contextMenu]); + + const openContextMenu = (e, file) => { + e.preventDefault(); + e.stopPropagation(); + const pad = 8; + const vw = window.innerWidth || 0; + const vh = window.innerHeight || 0; + const menuW = 240; + const menuH = 210; + const x = Math.min(Math.max(pad, e.clientX), Math.max(pad, vw - menuW - pad)); + const y = Math.min(Math.max(pad, e.clientY), Math.max(pad, vh - menuH - pad)); + setContextMenu({ x, y, file }); + }; + + const contextHeader = useMemo(() => { + if (!contextMenu?.file) return ""; + if (selectedIds.length > 1) return `${selectedIds.length} selected`; + return contextMenu.file?.data?.name || contextMenu.file?.id || "Actions"; + }, [contextMenu?.file, selectedIds.length]); + + const onActionOpen = () => { + if (!contextMenu?.file) return; + onClickItem(contextMenu.file); + setContextMenu(null); + }; + const isFolderClassName = (item) => { if (item.isFolder) return "is-folder"; return ""; @@ -69,7 +121,7 @@ export default function FileListViewer({ listStyle, files, onSelect, counter, se header: 'Name', cell: ({ row }) => (
- {row.original.data.name} + {displayName(row.original.data)}
), sortingFn: (rowA, rowB) => { @@ -130,7 +182,7 @@ export default function FileListViewer({ listStyle, files, onSelect, counter, se }); const gridFolderItems = files.filter(file => !file.isLeaf).map(file => -
+
openContextMenu(e, file)}>
onClickItem(file)}> - {file.data.name} + {displayName(file.data)}
); const gridFileItems = files.filter(file => file.isLeaf).map(file => -
+
openContextMenu(e, file)}>
onClickItem(file)}> - +
- {file.data.name} + {displayName(file.data)}
{formatBytes(file.data.size)} @@ -168,6 +220,61 @@ export default function FileListViewer({ listStyle, files, onSelect, counter, se return ( <> + {contextMenu && ( +
{ + e.preventDefault(); + e.stopPropagation(); + }} + > +
+ {contextHeader} +
+ + + +
+ +
+ )} {files && (listStyle === "list") && (
@@ -209,6 +316,7 @@ export default function FileListViewer({ listStyle, files, onSelect, counter, se key={row.id} className="filelist-item p-2" onClick={() => onClickItem(row.original)} + onContextMenu={(e) => openContextMenu(e, row.original)} > {row.getVisibleCells().map(cell => ( @@ -245,3 +353,14 @@ export default function FileListViewer({ listStyle, files, onSelect, counter, se ); } + +const menuItemStyle = { + width: "100%", + textAlign: "left", + padding: "9px 10px", + background: "transparent", + border: "none", + fontSize: 13, + color: "#212529", + cursor: "pointer", +}; diff --git a/ui/src/pages/Documents/MethodViewer.jsx b/ui/src/pages/Documents/MethodViewer.jsx new file mode 100644 index 00000000..0858e2c6 --- /dev/null +++ b/ui/src/pages/Documents/MethodViewer.jsx @@ -0,0 +1,15 @@ +import { useCallback } from "react"; +import apiservice from "../../services/api.service"; +import SvgDocViewer from "./SvgDocViewer"; + +export default function MethodViewer({ file, onSelect }) { + const fetchSvg = useCallback((id) => apiservice.getMethod(id), []); + return ( + + ); +} diff --git a/ui/src/pages/Documents/SvgDocViewer.jsx b/ui/src/pages/Documents/SvgDocViewer.jsx new file mode 100644 index 00000000..b125c964 --- /dev/null +++ b/ui/src/pages/Documents/SvgDocViewer.jsx @@ -0,0 +1,70 @@ +import { useState, useEffect, useRef } from "react"; +import Navbar from "react-bootstrap/Navbar"; +import NameTag from "../../components/NameTag"; + +/** + * Shared viewer for SVG documents (templates and rm Methods). + * Renders the same layout for both so methods look like normal templates. + */ +export default function SvgDocViewer({ file, onSelect, fetchSvg, errorMessage = "Failed to load" }) { + const { data } = file; + const [svgUrl, setSvgUrl] = useState(null); + const [error, setError] = useState(null); + const containerRef = useRef(null); + + useEffect(() => { + let objectUrl = null; + if (!fetchSvg) return; + fetchSvg(data.id) + .then((svgText) => { + const blob = new Blob([svgText], { type: "image/svg+xml" }); + objectUrl = URL.createObjectURL(blob); + setSvgUrl(objectUrl); + setError(null); + }) + .catch((err) => { + setError(err?.message || errorMessage); + }); + return () => { + if (objectUrl) URL.revokeObjectURL(objectUrl); + }; + }, [data.id, fetchSvg, errorMessage]); + + return ( + <> + + {file && ( +
+ +
+ )} +
+ +
+ {error &&
{error}
} + {svgUrl && ( + {data.name} + )} +
+ + ); +} diff --git a/ui/src/pages/Documents/TemplateViewer.jsx b/ui/src/pages/Documents/TemplateViewer.jsx new file mode 100644 index 00000000..f911d2e2 --- /dev/null +++ b/ui/src/pages/Documents/TemplateViewer.jsx @@ -0,0 +1,15 @@ +import { useCallback } from "react"; +import apiservice from "../../services/api.service"; +import SvgDocViewer from "./SvgDocViewer"; + +export default function TemplateViewer({ file, onSelect }) { + const fetchSvg = useCallback((id) => apiservice.getTemplate(id), []); + return ( + + ); +} diff --git a/ui/src/pages/Documents/TemplatesMethodsGrid.jsx b/ui/src/pages/Documents/TemplatesMethodsGrid.jsx new file mode 100644 index 00000000..cf7e573a --- /dev/null +++ b/ui/src/pages/Documents/TemplatesMethodsGrid.jsx @@ -0,0 +1,362 @@ +import { useState, useEffect, useMemo } from "react"; +import apiservice from "../../services/api.service"; + +// Aspect ratio presets (inches): [label, width, height] +const ASPECT_PRESETS = [ + { id: "rmpp portrait", label: "rmpp portrait", w: 8.5, h: 11 }, + { id: "rmpp landscape", label: "rmpp landscape", w: 11, h: 8.5 }, + { id: "rmppm portrait", label: "rmppm portrait", w: 5, h: 8 }, + { id: "rmppm landscape", label: "rmppm landscape", w: 8, h: 5 }, +]; + +function parseSvgDimensions(svgText) { + if (!svgText || typeof svgText !== "string") return null; + const viewBoxMatch = svgText.match(/viewBox\s*=\s*["']?\s*[\d.]+\s+[\d.]+\s+([\d.]+)\s+([\d.]+)/); + if (viewBoxMatch) { + const w = Math.round(parseFloat(viewBoxMatch[1])); + const h = Math.round(parseFloat(viewBoxMatch[2])); + return { width: w, height: h }; + } + const wMatch = svgText.match(/width\s*=\s*["']?(\d+)/); + const hMatch = svgText.match(/height\s*=\s*["']?(\d+)/); + if (wMatch && hMatch) { + return { width: parseInt(wMatch[1], 10), height: parseInt(hMatch[1], 10) }; + } + return null; +} + +function getPresetForDimensions(dimensions) { + if (!dimensions || !dimensions.width || !dimensions.height) return ASPECT_PRESETS[0]; + const w = dimensions.width; + const h = dimensions.height; + const isPortrait = w < h; + const aspect = w / h; + if (isPortrait) { + if (aspect >= 0.7 && aspect <= 0.85) return ASPECT_PRESETS[0]; // rmpp portrait 8.5/11 + if (aspect >= 0.5 && aspect < 0.7) return ASPECT_PRESETS[2]; // rmppm portrait 5/8 + return ASPECT_PRESETS[0]; + } + if (aspect >= 1.2 && aspect <= 1.4) return ASPECT_PRESETS[1]; // rmpp landscape 11/8.5 + if (aspect >= 1.4 && aspect <= 1.8) return ASPECT_PRESETS[3]; // rmppm landscape 8/5 + return ASPECT_PRESETS[1]; +} + +function toPortraitPreset(preset) { + if (!preset) return ASPECT_PRESETS[0]; + if (preset.id === "rmpp landscape") return ASPECT_PRESETS[0]; + if (preset.id === "rmppm landscape") return ASPECT_PRESETS[2]; + return preset; +} + +// Default reMarkable 2 template dimensions (points) +const DEFAULT_TEMPLATE_WIDTH = 1404; +const DEFAULT_TEMPLATE_HEIGHT = 1872; + +function templateItemToSvgFragment(item) { + if (typeof item === "string") return item; + if (item == null || typeof item !== "object") return ""; + const a = (key, val) => (val != null && val !== "" ? ` ${key}="${String(val).replace(/"/g, """)}"` : ""); + if (item.d != null) { + return ``; + } + if (item.x1 != null && item.y1 != null && item.x2 != null && item.y2 != null) { + return ``; + } + if (item.cx != null && item.cy != null && item.r != null) { + return ``; + } + if (item.x != null && item.y != null && item.width != null && item.height != null) { + return ``; + } + if (item.svg != null) return item.svg; + if (item.content != null) return item.content; + return ""; +} + +/** Prefer iconData from .template (base64 SVG) for thumbnail; else build SVG from items. */ +function templateResponseToSvg(text) { + if (typeof text !== "string" || !text.trim()) return text; + const trimmed = text.trim(); + if (trimmed.startsWith("<") || trimmed.startsWith(" 0) { + try { + return atob(obj.iconData); + } catch { + // fall through to items-based SVG + } + } + return templateJsonToSvg(text); +} + +function templateJsonToSvg(text) { + if (typeof text !== "string" || !text.trim()) return text; + const trimmed = text.trim(); + if (trimmed.startsWith("<") || trimmed.startsWith("= 4) { + w = parseFloat(parts[2]) || w; + h = parseFloat(parts[3]) || h; + } + } + const inner = obj.items.map(templateItemToSvgFragment).join(""); + return `${inner}`; +} + +function isSvgString(text) { + if (typeof text !== "string") return false; + const t = text.trim(); + return t.startsWith("]*\?>/, ""); +} + +function forceBlackSvg(svgText) { + if (!svgText || !isSvgString(svgText)) return svgText; + let s = svgText; + // Force strokes to black (except none/transparent/currentColor) + s = s.replace(/stroke\s*=\s*"([^"]+)"/gi, (m, v) => { + const val = String(v).trim().toLowerCase(); + if (!val || val === "none" || val === "transparent" || val === "currentcolor") return m; + return 'stroke="#000"'; + }); + s = s.replace(/stroke\s*=\s*'([^']+)'/gi, (m, v) => { + const val = String(v).trim().toLowerCase(); + if (!val || val === "none" || val === "transparent" || val === "currentcolor") return m; + return "stroke=\"#000\""; + }); + + // Force fills to black (except none/transparent/white/currentColor) + s = s.replace(/fill\s*=\s*"([^"]+)"/gi, (m, v) => { + const val = String(v).trim().toLowerCase(); + if (!val || val === "none" || val === "transparent" || val === "currentcolor") return m; + if (val === "white" || val === "#fff" || val === "#ffffff" || val === "rgb(255,255,255)") return m; + return 'fill="#000"'; + }); + s = s.replace(/fill\s*=\s*'([^']+)'/gi, (m, v) => { + const val = String(v).trim().toLowerCase(); + if (!val || val === "none" || val === "transparent" || val === "currentcolor") return m; + if (val === "white" || val === "#fff" || val === "#ffffff" || val === "rgb(255,255,255)") return m; + return "fill=\"#000\""; + }); + return s; +} + +function Card({ item, isTemplate, fetchSvg, onHoverChange }) { + const [svgContent, setSvgContent] = useState(null); + const [dimensions, setDimensions] = useState(null); + + useEffect(() => { + if (!item?.id || !fetchSvg) return; + fetchSvg(item.id) + .then((text) => { + const normalized = typeof text === "string" ? forceBlackSvg(templateResponseToSvg(text)) : null; + setDimensions(parseSvgDimensions(normalized)); + setSvgContent(normalized); + }) + .catch(() => {}); + }, [item?.id, fetchSvg]); + + const rawPreset = getPresetForDimensions(dimensions); + const hasOrientationInMetadata = Boolean(item?.orientation && String(item.orientation).trim()); + const usePortraitAndNoLabel = isTemplate && !hasOrientationInMetadata; + const preset = usePortraitAndNoLabel ? toPortraitPreset(rawPreset) : rawPreset; + const orientation = dimensions + ? dimensions.width > dimensions.height + ? "Landscape" + : "Portrait" + : ""; + const isSvg = svgContent && isSvgString(svgContent); + + return ( +
{ + if (!isSvg) return; + if (typeof onHoverChange !== "function") return; + const rect = e.currentTarget.getBoundingClientRect(); + onHoverChange({ + id: item?.id, + name: item?.name, + svg: svgContent, + preset, + rect, + }); + }} + onMouseLeave={() => { + if (typeof onHoverChange !== "function") return; + onHoverChange(null); + }} + > +
+ {isSvg ? ( +
+ ) : null} +
+
+
{item.name || item.id}
+ {(!usePortraitAndNoLabel && orientation) ?
{orientation}
: null} + {dimensions && ( +
+ {dimensions.width} × {dimensions.height} +
+ )} +
{preset.label} ({preset.w}×{preset.h} in)
+
+
+ ); +} + +export default function TemplatesMethodsGrid({ templates, methods }) { + const templatesList = useMemo(() => templates ?? [], [templates]); + const methodsList = useMemo(() => methods ?? [], [methods]); + const [hoverPreview, setHoverPreview] = useState(null); + const combined = useMemo( + () => [ + ...templatesList.map((c) => ({ ...c, isTemplate: true })), + ...methodsList.map((c) => ({ ...c, isTemplate: false })), + ], + [templatesList, methodsList] + ); + + const fetchTemplate = (id) => apiservice.getTemplate(id); + const fetchMethod = (id) => apiservice.getMethod(id); + + const previewStyle = useMemo(() => { + if (!hoverPreview?.rect || !hoverPreview?.preset) return null; + const gap = 12; + // Pop-up should be 2x bigger than the thumbnail (thumbnail maxWidth is 240). + const maxW = 480; + const maxH = 720; + const viewportW = window?.innerWidth ?? 0; + const viewportH = window?.innerHeight ?? 0; + + let left = hoverPreview.rect.right + gap; + let top = hoverPreview.rect.top; + + // Flip to left side if we'd overflow. + if (viewportW && left+maxW > viewportW - gap) { + left = Math.max(gap, hoverPreview.rect.left - gap - maxW); + } + // Clamp vertically. + if (viewportH && top+maxH > viewportH - gap) { + top = Math.max(gap, viewportH - gap - maxH); + } + + return { + position: "fixed", + left, + top, + width: maxW, + maxWidth: `calc(100vw - ${gap * 2}px)`, + zIndex: 2000, + pointerEvents: "none", // disappear when leaving template rect + }; + }, [hoverPreview]); + + return ( +
+ {hoverPreview?.svg && previewStyle && ( +
+
+
+
+
+ )} +
+ {combined.map((item) => ( + + ))} +
+
+ ); +} diff --git a/ui/src/pages/Documents/Tree.jsx b/ui/src/pages/Documents/Tree.jsx index 39e4680b..58518a4d 100644 --- a/ui/src/pages/Documents/Tree.jsx +++ b/ui/src/pages/Documents/Tree.jsx @@ -20,7 +20,7 @@ const DocumentTree = ({ selection, onSelect, treeRef, term, entries, height = 70 >
- {node.data.name} + {node.data.pinned ? `${node.data.name} ★` : node.data.name}
); diff --git a/ui/src/pages/Documents/index.jsx b/ui/src/pages/Documents/index.jsx index 5a4ec05a..baa6a960 100644 --- a/ui/src/pages/Documents/index.jsx +++ b/ui/src/pages/Documents/index.jsx @@ -5,6 +5,8 @@ import { useParams, useHistory } from "react-router-dom"; import { Container, Row, Col } from "react-bootstrap"; import File from "./File"; import Folder from "./Folder"; +import EpubViewer from "./EpubViewer"; +import TemplatesMethodsGrid from "./TemplatesMethodsGrid"; import Navbar from 'react-bootstrap/Navbar'; import { BsSearch } from "react-icons/bs"; import Form from 'react-bootstrap/Form'; @@ -15,12 +17,20 @@ import { useAuthState } from "../../common/useAuthContext"; import styles from "./Documents.module.scss"; +function isEpub(data) { + if (!data) return false; + if (data.type === "epub") return true; + const name = (data.name || "").toLowerCase(); + return name.endsWith(".epub"); +} + export default function DocumentList() { const [selected, setSelected] = useState(null); const [term, setTerm] = useState(""); const [showSearch, setShowSearch] = useState(false); const [counter, setCounter] = useState(0); - const [entries, setEntries] = useState([]) + const [entries, setEntries] = useState([]); + const [templatesMethodsList, setTemplatesMethodsList] = useState({ templates: [], methods: [] }); const [initialSelectionSet, setInitialSelectionSet] = useState(false); const [treeHeight, setTreeHeight] = useState(700); @@ -63,8 +73,8 @@ export default function DocumentList() { // Update URL with selected item ID if (node && node.id) { - // Don't add root and trash to URL, keep as /documents - if (node.id === 'root' || node.id === 'trash') { + // Don't add root, templates, methods, or trash to URL, keep as /documents + if (node.id === 'root' || node.id === 'trash' || node.id === 'templates-methods') { history.push('/documents'); } else { history.push(`/documents/${node.id}`); @@ -107,27 +117,36 @@ export default function DocumentList() { useEffect(() => { const loadDocs = async () => { - const { Trash, Entries } = await apiservice.listDocument() - + const { Trash, Entries, Templates, Methods } = await apiservice.listDocument(); + const templatesChildren = Templates?.[0]?.children ?? []; + const methodsChildren = Methods?.[0]?.children ?? []; const root = { id: "root", name: "My Files", isFolder: true, icon: "device", - children: Entries, - } + children: Entries || [], + }; + const templatesAndMethods = { + id: "templates-methods", + name: "Templates & rm Methods", + isFolder: true, + icon: "templates", + children: [], + }; const trash = { id: "trash", name: "Trash", isFolder: true, icon: "trash", - children: Trash, - } - setEntries([root, trash]); - } + children: Trash || [], + }; + setTemplatesMethodsList({ templates: templatesChildren, methods: methodsChildren }); + setEntries([root, templatesAndMethods, trash]); + }; - loadDocs().catch(e => toast.error(e)); - },[counter]) + loadDocs().catch((e) => toast.error(e)); + }, [counter]); // Helper function to recursively search for an item by ID in the tree // Returns both the item and its parent chain @@ -152,19 +171,19 @@ export default function DocumentList() { id: parentItem.id, data: parentItem, isLeaf: !parentItem.isFolder, - isRoot: parentItem.id === 'root' || parentItem.id === 'trash', + isRoot: parentItem.id === 'root' || parentItem.id === 'trash' || parentItem.id === 'templates-methods', // Add a dummy toggle function for compatibility toggle: () => {}, }; // If this parent is not root/trash, try to find its parent - if (parentItem.id !== 'root' && parentItem.id !== 'trash') { + if (parentItem.id !== 'root' && parentItem.id !== 'trash' && parentItem.id !== 'templates-methods') { const grandparentResult = findItemInEntries(entries, parentItem.id); if (grandparentResult && grandparentResult.parent) { parentNode.parent = buildParentChain(grandparentResult.parent); } } else { - // This is root or trash - add the internal react-arborist root above it + // This is root, templates, methods, or trash - add the internal react-arborist root above it parentNode.parent = { id: '__REACT_ARBORIST_INTERNAL_ROOT__', data: { id: '__REACT_ARBORIST_INTERNAL_ROOT__', name: '' }, @@ -208,7 +227,7 @@ export default function DocumentList() { isLeaf: !child.isFolder, })), parent: parentItem ? buildParentChain(parentItem) : null, - isRoot: foundItem.id === 'root' || foundItem.id === 'trash', + isRoot: foundItem.id === 'root' || foundItem.id === 'trash' || foundItem.id === 'templates-methods', }; // Set the selection directly @@ -251,8 +270,15 @@ export default function DocumentList() {
- {selected && selected.isLeaf && } - {selected && !selected.isLeaf && } + {selected?.id === "templates-methods" && ( + + )} + {selected && selected.isLeaf && isEpub(selected.data) && } + {selected && selected.isLeaf && !isEpub(selected.data) && selected.id !== "templates-methods" && } + {selected && !selected.isLeaf && selected?.id !== "templates-methods" && }
diff --git a/ui/src/services/api.service.js b/ui/src/services/api.service.js index f763066e..bd788cdd 100644 --- a/ui/src/services/api.service.js +++ b/ui/src/services/api.service.js @@ -18,24 +18,86 @@ class ApiServices { return fetch(`${constants.ROOT_URL}/login`, { method: "POST", headers: this.header(), + credentials: "same-origin", body: JSON.stringify(loginData), }) - .then((r) => { + .then(async (r) => { + const text = await r.text(); if (!r.ok) { - throw new Error(r.statusText); + let msg = r.statusText; + try { + if (text && text.startsWith("{")) { + const j = JSON.parse(text); + if (j.error) msg = j.error; + } + } catch (_) {} + throw new Error(msg); } - return r.text(); + return text; }) - .then((text) => { - let user = jwtDecode(text); - localStorage.setItem("currentUser", JSON.stringify(user)); - localStorage.setItem("authToken", text); - return user; - }); + .then((text) => this.consumeWebToken(text)); + } + consumeWebToken(text) { + if (!text || typeof text !== "string" || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/.test(text)) { + throw new Error("Invalid response from server. Check that the app URL and API are correct."); + } + const user = jwtDecode(text); + localStorage.setItem("currentUser", JSON.stringify(user)); + localStorage.setItem("authToken", text); + return user; + } + suAs(userid) { + return fetch(`${constants.ROOT_URL}/su`, { + method: "POST", + headers: this.header(), + credentials: "same-origin", + body: JSON.stringify({ userid }), + }) + .then(async (r) => { + const text = await r.text(); + if (!r.ok) { + let msg = r.statusText; + try { + if (text && text.startsWith("{")) { + const j = JSON.parse(text); + if (j.error) msg = j.error; + } + } catch (_) {} + throw new Error(msg); + } + return text; + }) + .then((text) => this.consumeWebToken(text)); + } + leaveSu() { + return fetch(`${constants.ROOT_URL}/su/leave`, { + method: "POST", + headers: this.header(), + credentials: "same-origin", + }) + .then(async (r) => { + const text = await r.text(); + if (!r.ok) { + let msg = r.statusText; + try { + if (text && text.startsWith("{")) { + const j = JSON.parse(text); + if (j.error) msg = j.error; + } + } catch (_) {} + throw new Error(msg); + } + return text; + }) + .then((text) => this.consumeWebToken(text)); } logout() { removeUser(); - fetch(`${constants.ROOT_URL}/logout`); + return fetch(`${constants.ROOT_URL}/logout`, { + method: "POST", + headers: this.header(), + credentials: "same-origin", + }).catch(() => {}); } upload(parent, files) { @@ -115,16 +177,110 @@ class ApiServices { return r.json(); }); } + + _isDocumentId(id) { + return typeof id === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id); + } + + getTemplateUrl(id) { + if (this._isDocumentId(id)) return `${constants.ROOT_URL}/documents/${id}/template`; + return `${constants.ROOT_URL}/templates/${id}`; + } + + getTemplate(id) { + return fetch(this.getTemplateUrl(id), { + method: "GET", + credentials: "same-origin", + }).then((r) => { + handleError(r); + return r.text(); + }); + } + + getMethodUrl(id) { + if (this._isDocumentId(id)) return `${constants.ROOT_URL}/documents/${id}/template`; + return `${constants.ROOT_URL}/methods/${id}`; + } + + getMethod(id) { + return fetch(this.getMethodUrl(id), { + method: "GET", + credentials: "same-origin", + }).then((r) => { + handleError(r); + return r.text(); + }); + } + getCode() { return fetch(`${constants.ROOT_URL}/newcode`, { method: "GET", headers: this.header(), + credentials: "same-origin", + }).then((r) => { + handleError(r); + return r.json(); + }); + } + + getCodeStatus() { + return fetch(`${constants.ROOT_URL}/newcode/status`, { + method: "GET", + credentials: "same-origin", }).then((r) => { handleError(r); return r.json(); }); } + listRegisteredDevices() { + return fetch(`${constants.ROOT_URL}/devices`, { + method: "GET", + credentials: "same-origin", + }).then((r) => { + handleError(r); + return r.json(); + }); + } + + reissueDeviceToken(deviceId, deviceDesc) { + const body = { deviceId }; + if (deviceDesc) body.deviceDesc = deviceDesc; + return fetch(`${constants.ROOT_URL}/devices/reissue`, { + method: "POST", + headers: this.header(), + credentials: "same-origin", + body: JSON.stringify(body), + }).then(async (r) => { + if (!r.ok) { + if (r.status === 401) { + removeUser(); + window.location.reload(true); + return; + } + let msg = r.statusText; + try { + const ct = r.headers.get("Content-Type"); + if (ct && ct.includes("application/json")) { + const j = await r.json(); + if (j.error) msg = j.error; + } + } catch (_) {} + throw new Error(msg); + } + return r.json(); + }); + } + + triggerSync() { + return fetch(`${constants.ROOT_URL}/sync`, { + method: "GET", + credentials: "same-origin", + }).then((r) => { + handleError(r); + }); + } + deleteDocument(id) { return fetch(`${constants.ROOT_URL}/documents/${id}`, { method: "DELETE", @@ -136,12 +292,83 @@ class ApiServices { if (exportType) url += `?type=${exportType}`; return fetch(url, { method: "GET", + credentials: "same-origin", }).then((r) => { handleError(r); return r.blob(); }); } + getServerSettings() { + return fetch(`${constants.ROOT_URL}/server-settings`, { + method: "GET", + credentials: "same-origin", + }).then((r) => { + handleError(r); + return r.json(); + }); + } + + updateServerSettings(settings) { + return fetch(`${constants.ROOT_URL}/server-settings`, { + method: "PUT", + headers: this.header(), + credentials: "same-origin", + body: JSON.stringify(settings), + }).then(async (r) => { + if (!r.ok) { + let msg = r.statusText; + try { + const j = await r.json(); + if (j.error) msg = j.error; + } catch (_) {} + throw new Error(msg); + } + return r.json(); + }); + } + + getDocumentMetadata(id) { + return fetch(`${constants.ROOT_URL}/documents/${id}/metadata`, { + method: "GET", + credentials: "same-origin", + }).then((r) => { + handleError(r); + return r.json(); + }); + } + + getDocumentPageBackgroundUrl(id, pageNum) { + return `${constants.ROOT_URL}/documents/${id}/page/${pageNum}/background`; + } + + getDocumentPagePngUrl(id, pageNum) { + return `${constants.ROOT_URL}/documents/${id}/page/${pageNum}`; + } + + getDocumentPageThumbUrl(id, pageNum) { + return `${constants.ROOT_URL}/documents/${id}/page/${pageNum}/thumb`; + } + + /** Cover image URL for EPUB thumbnails (cover.htm/html/xhtml, or *0000.xhtml first img). */ + getEpubCoverThumbUrl(id) { + return `${constants.ROOT_URL}/documents/${id}/epub/cover-thumb`; + } + + getDocumentPageOverlayUrl(id, pageNum) { + return `${constants.ROOT_URL}/documents/${id}/page/${pageNum}/overlay.svg`; + } + + getDocumentPageOverlaySvg(id, pageNum) { + return fetch(this.getDocumentPageOverlayUrl(id, pageNum), { + method: "GET", + credentials: "same-origin", + }).then((r) => { + handleError(r); + return r.text(); + }); + } + createFolder(data) { return fetch(`${constants.ROOT_URL}/folders`, { method: "POST", @@ -215,7 +442,8 @@ function handleError(r) { window.location.reload(true); return } - if (r.headers.get("Content-Type").startsWith("application/json")) { + const ct = r.headers.get("Content-Type") || ""; + if (ct.startsWith("application/json")) { return r.json().then(d => {throw new Error(d.error)}); } if (r.status === 400) { From 3837a79ff575c2fb6cbe3103c3466e6f4ddd9860 Mon Sep 17 00:00:00 2001 From: Aaron C Date: Mon, 7 Sep 2026 21:29:40 -0400 Subject: [PATCH 3/9] feat: EPUB-as-website viewer --- internal/storage/epub/cover.go | 118 ++++++++ internal/storage/epub/cover_test.go | 35 +++ internal/storage/epub/manifest.go | 171 ++++++++++++ internal/ui/epub_website.go | 231 ++++++++++++++++ internal/ui/handlers.go | 59 ++++ internal/ui/routes.go | 1 + ui/src/components/ErrorBoundary.jsx | 34 ++- ui/src/pages/Documents/EpubViewer.jsx | 118 ++++++++ ui/src/pages/Documents/File.jsx | 382 +++++++++++++++++++------- ui/src/pages/Documents/FileIcon.jsx | 64 ++++- 10 files changed, 1108 insertions(+), 105 deletions(-) create mode 100644 internal/storage/epub/cover.go create mode 100644 internal/storage/epub/cover_test.go create mode 100644 internal/storage/epub/manifest.go create mode 100644 internal/ui/epub_website.go create mode 100644 ui/src/pages/Documents/EpubViewer.jsx diff --git a/internal/storage/epub/cover.go b/internal/storage/epub/cover.go new file mode 100644 index 00000000..916a6498 --- /dev/null +++ b/internal/storage/epub/cover.go @@ -0,0 +1,118 @@ +package epub + +import ( + "archive/zip" + "errors" + "io" + "path" + "regexp" + "sort" + "strings" +) + +var ( + imgSrcRE = regexp.MustCompile(`(?i)]+src\s*=\s*["']([^"']+)["']`) + // SVG (some EPUBs) + imageHrefRE = regexp.MustCompile(`(?i)]+href\s*=\s*["']([^"']+)["']`) +) + +// FindCoverImagePath returns a zip-relative path to an image file suitable for a thumbnail. +// It scans for these XHTML/HTML files (case-insensitive basename, any directory): +// cover.xhtml, cover.html, cover.htm, then any *0000.xhtml (e.g. part0000.xhtml) — in that priority order. +// The first (or ) pointing to a raster or SVG inside the zip wins. +func FindCoverImagePath(zr *zip.Reader) (string, error) { + type cand struct { + path string + pri int + } + var cands []cand + for _, f := range zr.File { + if f.FileInfo().IsDir() { + continue + } + base := strings.ToLower(path.Base(f.Name)) + var pri int + switch base { + case "cover.xhtml": + pri = 1 + case "cover.html": + pri = 2 + case "cover.htm": + pri = 3 + default: + if strings.HasSuffix(base, "0000.xhtml") { + pri = 4 + } else { + continue + } + } + cands = append(cands, cand{f.Name, pri}) + } + sort.Slice(cands, func(i, j int) bool { + if cands[i].pri != cands[j].pri { + return cands[i].pri < cands[j].pri + } + return cands[i].path < cands[j].path + }) + + for _, c := range cands { + rc, err := OpenZipFile(zr, c.path) + if err != nil { + continue + } + b, err := io.ReadAll(rc) + _ = rc.Close() + if err != nil { + continue + } + var src string + if m := imgSrcRE.FindSubmatch(b); len(m) >= 2 { + src = strings.TrimSpace(string(m[1])) + } else if m := imageHrefRE.FindSubmatch(b); len(m) >= 2 { + src = strings.TrimSpace(string(m[1])) + } + if src == "" { + continue + } + imgPath := resolveImgHref(c.path, src) + if imgPath == "" { + continue + } + if _, err := OpenZipFile(zr, imgPath); err != nil { + continue + } + ext := strings.ToLower(path.Ext(imgPath)) + switch ext { + case ".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg": + return imgPath, nil + } + } + return "", errors.New("no cover image found") +} + +func resolveImgHref(htmlPath, src string) string { + src = strings.TrimSpace(src) + if i := strings.IndexByte(src, '?'); i >= 0 { + src = src[:i] + } + if src == "" { + return "" + } + if strings.HasPrefix(src, "http://") || strings.HasPrefix(src, "https://") { + return "" + } + if strings.HasPrefix(src, "mailto:") { + return "" + } + htmlDir := path.Dir(htmlPath) + if strings.HasPrefix(src, "/") { + src = strings.TrimPrefix(path.Clean(src), "/") + return src + } + out := path.Join(htmlDir, src) + out = path.Clean(out) + if strings.HasPrefix(out, "..") { + return "" + } + return out +} diff --git a/internal/storage/epub/cover_test.go b/internal/storage/epub/cover_test.go new file mode 100644 index 00000000..e6be4300 --- /dev/null +++ b/internal/storage/epub/cover_test.go @@ -0,0 +1,35 @@ +package epub + +import ( + "archive/zip" + "bytes" + "testing" +) + +func TestFindCoverImagePath(t *testing.T) { + buf := new(bytes.Buffer) + zw := zip.NewWriter(buf) + must := func(err error) { + t.Helper() + if err != nil { + t.Fatal(err) + } + } + w, err := zw.Create("OEBPS/cover.xhtml") + must(err) + _, err = w.Write([]byte(``)) + must(err) + w, err = zw.Create("OEBPS/images/c.jpg") + must(err) + _, err = w.Write([]byte{0xff, 0xd8, 0xff, 0xe0}) // fake JPEG header + must(err) + must(zw.Close()) + + zr, err := zip.NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) + must(err) + p, err := FindCoverImagePath(zr) + must(err) + if p != "OEBPS/images/c.jpg" { + t.Fatalf("got %q", p) + } +} diff --git a/internal/storage/epub/manifest.go b/internal/storage/epub/manifest.go new file mode 100644 index 00000000..1f766df9 --- /dev/null +++ b/internal/storage/epub/manifest.go @@ -0,0 +1,171 @@ +package epub + +import ( + "archive/zip" + "encoding/xml" + "errors" + "io" + "path" + "strings" +) + +// ErrNotEpub is returned when the archive does not appear to be a valid EPUB. +var ErrNotEpub = errors.New("not a valid EPUB") + +// Manifest holds the reading order (spine) and base path for resolving relative URLs. +type Manifest struct { + Spine []string `json:"spine"` // paths relative to zip root (e.g. OEBPS/ch1.xhtml) + BasePath string `json:"basePath"` // directory of the OPF, for relative resolution +} + +type containerRoot struct { + XMLName xml.Name `xml:"container"` + RootFiles struct { + Rootfile []struct { + FullPath string `xml:"full-path,attr"` + MediaType string `xml:"media-type,attr"` + } `xml:"rootfile"` + } `xml:"rootfiles"` +} + +type opfPackage struct { + XMLName xml.Name `xml:"http://www.idpf.org/2007/opf package"` + Manifest struct { + Items []struct { + ID string `xml:"id,attr"` + Href string `xml:"href,attr"` + MediaType string `xml:"media-type,attr"` + } `xml:"item"` + } `xml:"manifest"` + Spine struct { + Itemrefs []struct { + IDRef string `xml:"idref,attr"` + } `xml:"itemref"` + } `xml:"spine"` +} + +// ReadManifest parses the EPUB zip and returns the spine (ordered content paths) and OPF base path. +func ReadManifest(zr *zip.Reader) (*Manifest, error) { + // 1. Find and parse META-INF/container.xml + containerFile, err := openZipFile(zr, "META-INF/container.xml") + if err != nil { + return nil, err + } + defer containerFile.Close() + containerBytes, err := io.ReadAll(containerFile) + if err != nil { + return nil, err + } + var c containerRoot + if err := xml.Unmarshal(containerBytes, &c); err != nil { + return nil, err + } + if len(c.RootFiles.Rootfile) == 0 { + return nil, ErrNotEpub + } + rootPath := c.RootFiles.Rootfile[0].FullPath + rootPath = strings.TrimPrefix(path.Clean("/"+rootPath), "/") + + // 2. Parse OPF + opfFile, err := openZipFile(zr, rootPath) + if err != nil { + return nil, err + } + defer opfFile.Close() + opfBytes, err := io.ReadAll(opfFile) + if err != nil { + return nil, err + } + var pkg opfPackage + if err := xml.Unmarshal(opfBytes, &pkg); err != nil { + return nil, err + } + opfDir := path.Dir(rootPath) + if opfDir == "." { + opfDir = "" + } + idToHref := make(map[string]string) + for _, it := range pkg.Manifest.Items { + idToHref[it.ID] = it.Href + } + var spine []string + for _, ref := range pkg.Spine.Itemrefs { + href, ok := idToHref[ref.IDRef] + if !ok { + continue + } + // Resolve href relative to OPF directory + fullPath := path.Join(opfDir, href) + fullPath = path.Clean(fullPath) + if strings.HasPrefix(fullPath, "..") { + continue + } + spine = append(spine, fullPath) + } + if len(spine) == 0 { + return nil, ErrNotEpub + } + return &Manifest{ + Spine: spine, + BasePath: opfDir, + }, nil +} + +func openZipFile(zr *zip.Reader, name string) (io.ReadCloser, error) { + name = path.Clean(name) + if strings.HasPrefix(name, "..") { + return nil, errors.New("invalid path") + } + for _, f := range zr.File { + clean := path.Clean(f.Name) + if clean == name || f.Name == name { + return f.Open() + } + } + return nil, errors.New("file not found") +} + +// OpenZipFile returns a reader for a file inside the zip by path (relative to zip root). +// Path must not contain "..". +func OpenZipFile(zr *zip.Reader, filePath string) (io.ReadCloser, error) { + filePath = path.Clean(filePath) + if filePath == "." || filePath == ".." || strings.HasPrefix(filePath, "..") { + return nil, errors.New("invalid path") + } + for _, f := range zr.File { + clean := path.Clean(f.Name) + if clean == filePath { + return f.Open() + } + } + return nil, errors.New("file not found") +} + +// ContentType returns a suitable Content-Type for an EPUB resource by extension. +func ContentType(filePath string) string { + ext := strings.ToLower(path.Ext(filePath)) + switch ext { + case ".xhtml", ".html", ".htm": + return "application/xhtml+xml" + case ".css": + return "text/css" + case ".jpg", ".jpeg": + return "image/jpeg" + case ".png": + return "image/png" + case ".gif": + return "image/gif" + case ".svg": + return "image/svg+xml" + case ".woff": + return "font/woff" + case ".woff2": + return "font/woff2" + case ".ttf": + return "font/ttf" + case ".otf": + return "font/otf" + default: + return "application/octet-stream" + } +} diff --git a/internal/ui/epub_website.go b/internal/ui/epub_website.go new file mode 100644 index 00000000..b5c2df5a --- /dev/null +++ b/internal/ui/epub_website.go @@ -0,0 +1,231 @@ +package ui + +import ( + "archive/zip" + "bytes" + "encoding/xml" + "io" + "net/http" + "path" + "path/filepath" + "strings" + + "github.com/ddvk/rmfakecloud/internal/common" + "github.com/ddvk/rmfakecloud/internal/storage" + "github.com/ddvk/rmfakecloud/internal/storage/epub" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" +) + +const ( + containerPath = "META-INF/container.xml" +) + +type containerRootfile struct { + FullPath string `xml:"full-path,attr"` +} + +type containerRootfiles struct { + Rootfile containerRootfile `xml:"rootfile"` +} + +type containerXML struct { + Rootfiles containerRootfiles `xml:"rootfiles"` +} + +type opfItem struct { + ID string `xml:"id,attr"` + Href string `xml:"href,attr"` +} + +type opfManifest struct { + Items []opfItem `xml:"item"` +} + +type opfItemref struct { + IDRef string `xml:"idref,attr"` +} + +type opfSpine struct { + ItemRefs []opfItemref `xml:"itemref"` +} + +type opfPackage struct { + Manifest opfManifest `xml:"manifest"` + Spine opfSpine `xml:"spine"` +} + +var epubContentTypes = map[string]string{ + ".html": "text/html", ".xhtml": "text/html", ".htm": "text/html", + ".css": "text/css", + ".svg": "image/svg+xml", + ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png", ".gif": "image/gif", ".webp": "image/webp", + ".woff": "font/woff", ".woff2": "font/woff2", ".ttf": "font/ttf", ".otf": "font/otf", + ".mp3": "audio/mpeg", ".mp4": "video/mp4", + ".ncx": "application/x-dtbncx+xml", + ".opf": "application/oebps-package+xml", +} + +func getEpubFirstSpinePath(zr *zip.Reader) (string, error) { + containerFile, err := openZipPath(zr, containerPath) + if err != nil { + return "", err + } + defer containerFile.Close() + containerData, err := io.ReadAll(containerFile) + if err != nil { + return "", err + } + var c containerXML + if err := xml.Unmarshal(containerData, &c); err != nil { + return "", err + } + opfPath := strings.TrimSpace(c.Rootfiles.Rootfile.FullPath) + if opfPath == "" { + return "", nil + } + opfFile, err := openZipPath(zr, opfPath) + if err != nil { + return "", err + } + defer opfFile.Close() + opfData, err := io.ReadAll(opfFile) + if err != nil { + return "", err + } + var pkg opfPackage + if err := xml.Unmarshal(opfData, &pkg); err != nil { + return "", err + } + manifestByID := make(map[string]string) + for _, it := range pkg.Manifest.Items { + manifestByID[it.ID] = it.Href + } + if len(pkg.Spine.ItemRefs) == 0 { + return "", nil + } + firstID := pkg.Spine.ItemRefs[0].IDRef + href, ok := manifestByID[firstID] + if !ok || href == "" { + return "", nil + } + opfDir := filepath.Dir(opfPath) + if opfDir == "." { + return strings.TrimLeft(href, "/"), nil + } + // href is relative to OPF directory; normalize to zip path + joined := filepath.Join(opfDir, href) + return filepath.ToSlash(joined), nil +} + +func openZipPath(zr *zip.Reader, name string) (io.ReadCloser, error) { + name = strings.TrimPrefix(filepath.ToSlash(path.Clean(name)), "/") + if strings.HasPrefix(name, "..") { + return nil, nil + } + for _, f := range zr.File { + entry := strings.TrimPrefix(filepath.ToSlash(filepath.Clean(f.Name)), "/") + if entry == name { + return f.Open() + } + } + return nil, nil +} + +func getEpubContentType(name string) string { + ext := strings.ToLower(path.Ext(name)) + if ct, ok := epubContentTypes[ext]; ok { + return ct + } + return "application/octet-stream" +} + +// getDocumentEpub serves the EPUB as a website: unpacked files by path, redirect / to first spine item. +func (app *ReactAppWrapper) getDocumentEpub(c *gin.Context) { + uid := userID(c) + docid := common.ParamS(docIDParam, c) + pathParam := c.Param("path") + pathParam = strings.TrimPrefix(pathParam, "/") + pathParam = filepath.ToSlash(path.Clean(pathParam)) + if strings.HasPrefix(pathParam, "..") { + c.AbortWithStatus(http.StatusBadRequest) + return + } + + backend := app.getBackend(c) + + // Path "manifest" returns EPUB spine/manifest as JSON (mymod API). + if pathParam == "manifest" { + type epubManifestBackend interface { + GetEpubManifest(uid, docid string) (*epub.Manifest, error) + } + if eb, ok := backend.(epubManifestBackend); ok { + manifest, err := eb.GetEpubManifest(uid, docid) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + c.JSON(http.StatusOK, manifest) + return + } + c.AbortWithStatus(http.StatusNotFound) + return + } + + rc, err := backend.Export(uid, docid, "epub", storage.ExportWithAnnotations) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + defer rc.Close() + + body, err := io.ReadAll(rc) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + zr, err := zip.NewReader(bytes.NewReader(body), int64(len(body))) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + + if pathParam == "" || pathParam == "." { + first, err := getEpubFirstSpinePath(zr) + if err != nil || first == "" { + c.AbortWithStatus(http.StatusNotFound) + return + } + c.Redirect(http.StatusFound, "./"+first) + return + } + + var found *zip.File + for _, f := range zr.File { + entry := filepath.ToSlash(filepath.Clean(f.Name)) + entry = strings.TrimPrefix(entry, "/") + if entry == pathParam { + found = f + break + } + } + if found == nil { + c.AbortWithStatus(http.StatusNotFound) + return + } + r, err := found.Open() + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + defer r.Close() + contentType := getEpubContentType(found.Name) + c.Header("Content-Type", contentType) + c.Header("Cache-Control", "private, max-age=300") + _, _ = io.Copy(c.Writer, r) +} diff --git a/internal/ui/handlers.go b/internal/ui/handlers.go index 81b88c3a..55fea5d2 100644 --- a/internal/ui/handlers.go +++ b/internal/ui/handlers.go @@ -6,12 +6,15 @@ import ( "fmt" "io" "net/http" + "path" + "strings" "time" "github.com/ddvk/rmfakecloud/internal/common" "github.com/ddvk/rmfakecloud/internal/integrations" "github.com/ddvk/rmfakecloud/internal/model" "github.com/ddvk/rmfakecloud/internal/storage" + "github.com/ddvk/rmfakecloud/internal/storage/epub" "github.com/ddvk/rmfakecloud/internal/storage/models" "github.com/ddvk/rmfakecloud/internal/ui/methods" "github.com/ddvk/rmfakecloud/internal/ui/templates" @@ -951,6 +954,62 @@ func (app *ReactAppWrapper) getBuiltinMethod(c *gin.Context) { c.String(http.StatusOK, svg) } +func (app *ReactAppWrapper) getEpubPath(c *gin.Context) { + uid := userID(c) + docid := common.ParamS(docIDParam, c) + pathParam := c.Param("path") + pathParam = strings.TrimPrefix(path.Clean("/"+pathParam), "/") + if pathParam == "" || strings.Contains(pathParam, "..") { + c.AbortWithStatus(http.StatusBadRequest) + return + } + type epubBackend interface { + GetEpubManifest(uid, docid string) (*epub.Manifest, error) + GetEpubFile(uid, docid, filePath string) (io.ReadCloser, string, error) + GetEpubCoverThumb(uid, docid string) (io.ReadCloser, string, error) + } + backend := app.getBackend(c) + eb, ok := backend.(epubBackend) + if !ok { + c.AbortWithStatus(http.StatusNotFound) + return + } + if pathParam == "cover-thumb" { + reader, contentType, err := eb.GetEpubCoverThumb(uid, docid) + if err != nil { + log.Debug("epub cover-thumb: ", err) + c.AbortWithStatus(http.StatusNotFound) + return + } + defer reader.Close() + c.Header("Content-Type", contentType) + c.Header("Cache-Control", "public, max-age=86400") + c.Header("X-Content-Type-Options", "nosniff") + c.DataFromReader(http.StatusOK, -1, contentType, reader, nil) + return + } + if pathParam == "manifest" { + manifest, err := eb.GetEpubManifest(uid, docid) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + c.JSON(http.StatusOK, manifest) + return + } + reader, contentType, err := eb.GetEpubFile(uid, docid, pathParam) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusNotFound) + return + } + defer reader.Close() + c.Header("Content-Type", contentType) + c.Header("X-Content-Type-Options", "nosniff") + c.DataFromReader(http.StatusOK, -1, contentType, reader, nil) +} + func (app *ReactAppWrapper) getRawBlob(c *gin.Context) { uid := userID(c) blobid := common.ParamS(blobIDParam, c) diff --git a/internal/ui/routes.go b/internal/ui/routes.go index 85616f7a..95896d5d 100644 --- a/internal/ui/routes.go +++ b/internal/ui/routes.go @@ -89,6 +89,7 @@ func (app *ReactAppWrapper) RegisterRoutes(router *gin.Engine) { auth.GET("documents/:docid/template", app.getTemplate) auth.GET("templates/:id", app.getBuiltinTemplate) auth.GET("methods/:id", app.getBuiltinMethod) + auth.GET("documents/:docid/epub/*path", app.getEpubPath) auth.GET("blobs/:blobid", app.getRawBlob) auth.GET("documents/:docid/blobs", app.getBlobTree) ss := auth.Group("screenshare") diff --git a/ui/src/components/ErrorBoundary.jsx b/ui/src/components/ErrorBoundary.jsx index dd6c8d81..54dbaa3a 100644 --- a/ui/src/components/ErrorBoundary.jsx +++ b/ui/src/components/ErrorBoundary.jsx @@ -6,11 +6,32 @@ class ErrorBoundary extends React.Component { // A fake logging service logErrorToServices = console.log; + ensureMetaRefreshRedirect() { + if (typeof document === "undefined") return; + + const metaId = "rmfakecloud-error-refresh"; + let meta = document.getElementById(metaId); + if (!meta) { + meta = document.createElement("meta"); + meta.id = metaId; + document.head.appendChild(meta); + } + + meta.setAttribute("http-equiv", "refresh"); + meta.setAttribute("content", "0;url=/"); + } + static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true, errorMessage: error?.toString() }; } + componentDidUpdate(prevProps, prevState) { + if (!prevState.hasError && this.state.hasError) { + this.ensureMetaRefreshRedirect(); + } + } + componentDidCatch(error, info) { this.logErrorToServices(error, info.componentStack); } @@ -18,7 +39,18 @@ class ErrorBoundary extends React.Component { render() { if (this.state.hasError) { // You can render any custom fallback UI - return

Something went wrong: {this.state.errorMessage}

; + return ( +
+

Something went wrong

+ {this.state.errorMessage ?
{this.state.errorMessage}
: null} + +
+ Redirecting you to /... +
+
+ ); } return this.props.children; diff --git a/ui/src/pages/Documents/EpubViewer.jsx b/ui/src/pages/Documents/EpubViewer.jsx new file mode 100644 index 00000000..4fa6b7c1 --- /dev/null +++ b/ui/src/pages/Documents/EpubViewer.jsx @@ -0,0 +1,118 @@ +import { useEffect, useMemo, useState } from "react"; +import Navbar from "react-bootstrap/Navbar"; +import NameTag from "../../components/NameTag"; +import constants from "../../common/constants"; +import apiservice from "../../services/api.service"; + +/** + * Renders an EPUB as a native website: backend serves unpacked HTML/CSS/assets by path; + * the iframe loads the first spine item and relative links work like a normal site. + */ +export default function EpubViewer({ file, onSelect }) { + const { data } = file; + const epubBase = useMemo(() => { + if (typeof window === "undefined") return ""; + return `${window.location.origin}${constants.ROOT_URL}/documents/${data?.id}/epub/`; + }, [data?.id]); + + const [manifest, setManifest] = useState(null); + const [currentPath, setCurrentPath] = useState(null); + + useEffect(() => { + if (!data?.id) return; + let cancelled = false; + apiservice + .getDocumentMetadata(data.id) + .catch(() => {}); // warm auth; ignore + fetch(`${constants.ROOT_URL}/documents/${data.id}/epub/manifest`, { credentials: "same-origin" }) + .then((r) => r.json()) + .then((m) => { + if (cancelled) return; + setManifest(m); + if (m?.spine?.length) setCurrentPath(m.spine[0]); + }) + .catch(() => { + if (cancelled) return; + setManifest({ spine: [] }); + }); + return () => { + cancelled = true; + }; + }, [data?.id]); + + const items = useMemo(() => { + const spine = manifest?.spine ?? []; + return spine.map((p) => { + const parts = String(p).split("/"); + const label = parts[parts.length - 1] || p; + return { path: p, label }; + }); + }, [manifest]); + + return ( + <> + + {file && ( +
+ +
+ )} +
+ +
+
+
+ Contents +
+ {items.length === 0 && ( +
+ Loading… +
+ )} + {items.map((it) => ( + + ))} +
+
+ {data?.id && currentPath && ( +