The project hasn't received updates in ~4 years. This document groups the proposed improvements so they can be tracked, discussed, and later converted into individual GitHub issues.
Status legend: [ ] not started · [~] in progress · [x] done.
The block writes frameIbwpointer, frameimgBWsize, frameFeaturePoints
onto a JS-side arfset.frameMalloc object. Modern, more efficient options,
in order of preference:
-
Best: drop it entirely. Those same three fields are already returned through the embind
nftMarkervalue_object (pointer,imgBWsize,nftFeaturePointsinemscripten/bindings.cpp:46-55). JS can read them from the returned struct instead of from a side-channel global — eliminates a JS↔wasm crossing and removes hidden global state. -
If a JS-visible global is required: use
emscripten::val(pure C++, type-safe, no string parser):val::global("arfset")["frameMalloc"].set("frameIbwpointer", arc->imgBW);. -
Last resort:
EM_JS(void, set_frame_malloc, (...), { ... })— declarative, parsed once at build time instead of every call site. -
Pick approach (recommended: drop the EM_ASM and read from
nftMarker). -
Remove
EM_ASM_block. -
Update JS callers in
js/arfset.api.jsandsrc/ARFset.js.
Current design has two real problems:
-
It's called in a per-point loop from
readNFTMarker(emscripten/ARimageFsetDisplay.cpp:200-206), so each point pays a wasm→JS call. -
Each call adds a new
imageEvevent listener that is never removed. Loading a marker with N feature points leaks N listeners; loading a second marker doubles drawing work. -
Populate the already-declared
nftPointsvector inARimageFsetDisplay.cpp(the loop at lines 192–198 is commented out). -
Expose feature-set points the same way (new vector field).
-
Delete
writeFP/writeFSfromjs/jslibrary.jsand remove the--js-libraryflag if nothing else needs it. -
Have JS draw all points in a single pass after
imageEvfires.
-
loadNFTMarkerlogs an error ifar2ReadSurfaceSetreturns NULL but continues, then dereferences the NULL pointer (lines 109–128). -
exit(0)/exit(-1)on file errors (lines 148, 154) terminate the wasm runtime in the browser — return an error code instead. -
setup()mallocsimgBWwithwidth*height*4, butloadNFTMarkeroverwrites the pointer withsurfaceSet[...]->imgBW— the malloc'd buffer leaks (and so does the secondmallocbased on the uninitializednum_F_points_NFT). -
ARLOGi("...%d", arc->imgBW)and(int)arc->imgBWtruncate pointers — use%p/uintptr_t. - The
if (surfaceSetCount == PAGES_MAX) exit(-1);check at line 153 happens after the array is written (line 109+); reorder and return an error.
src/ARFset.js:144 and js/arfset.api.js:114 pass a Uint8ClampedArray
view to Module._free, which expects an integer pointer. The call is a
no-op at best and likely corrupts the heap if the cast happens to land on
a valid pointer.
- Remove the bogus
_freecall (the buffer is a view onto wasm memory managed by the C++ side; JS shouldn't free it).
The for (i,j) { id.data[j+0..2] = v; id.data[j+3] = 255 } loop in both
src/ARFset.js:131-137 and js/arfset.api.js:101-107 can be replaced by
writing a Uint32Array view of id.data with
(0xff000000 | v<<16 | v<<8 | v) — typically 3–5× faster.
- Refactor the gray→RGBA conversion loop using a
Uint32Arrayview.
axios 0.26.x has unpatched CVEs (CVE-2023-45857 / SSRF). The two
Utils.js methods just do
axios.get(url, { responseType: 'arraybuffer' }) — a one-line
fetch().then(r => r.arrayBuffer()) removes the dependency entirely.
- Replace both
fetchRemoteDataandfetchRemoteDataBlobwithfetch-based implementations. - Remove
axiosfrompackage.jsondependencies.
The legacy global-ARfset API in js/arfset.api.js is coupled to the
asm.js outputs: tools/makem.js:176 injects it via --pre-js into
arfset.debug.js and arfset.min.js only — the wasm and ES6-wasm
builds never include it. Modern browsers cover wasm, so we drop both
the legacy file and the asm.js targets in the same change. Only
example/example.html currently consumes it; that example is migrated
to the ES6 build (the existing example_es6.html is the template).
- Delete
js/arfset.api.js. - Delete
js/jslibrary.jsonce 1b removes itswriteFP/writeFScallbacks (the--js-libraryflag goes away with it). - Remove
compile_combineandcompile_combine_minjobs fromtools/makem.js, plus thePRE_FLAGSblock. - Migrate
example/example.htmlto the ES6 build (or replace it with the existingexample_es6.html). - Delete
build/arfset.min.jsandbuild/arfset.debug.js; stop generating them. - Continue to expose a
window.ARFsetglobal for legacy users via the webpack UMD bundle (dist/ARFset.jsalready does this) — no separate legacy entry point needed. - Note the removal in the README and bump to a major version since
this is a breaking change for anyone loading
arfset.min.js.
src/ARFset.js:249-251 hardcodes initial canvas dimensions. Make them
constructor options with sensible defaults.
- Accept
{ width, height }in theARFsetconstructor. - Update example HTML files accordingly.
- Add TypeScript declarations (
.d.ts) — or convertsrc/to TypeScript outright. - Add JSDoc on every public method.
- Decide on naming:
nftMarkerCount(field) vsmarkerNFTCount(local) are inconsistent.
package.json still pins webpack 5.70, Babel 7.17, axios 0.26 — all
~4 years old.
- Bump webpack, Babel, or replace webpack with Vite/Rollup/esbuild for an order-of-magnitude faster build.
- Drop
@babel/transform-runtimeif targeting modern browsers. - Refresh
package-lock.json.
The asm.js targets are dropped as part of 2d. This item covers the remaining cleanup.
-
TOTAL_MEMORYis deprecated — switch toINITIAL_MEMORY. Comment says64MBbut value is256MB; fix one or the other. -
var arguments = process.argvshadows the reservedarguments— replace withprocess.argv.slice(2)andfor…of. - Add a dedicated debug wasm target with
DEBUG_FLAGSapplied (currently they only affect the asm.js debug build, which is going away). - Bump the
WebARKitLibsubmodule (currently pinned 4 years back).
No tests exist today.
- Pick a runner — recommend Vitest for unit tests + Playwright for a browser-level smoke test that loads a known marker and asserts the canvas is non-empty.
- Add a
npm testscript. - Wire tests into CI (see 3d).
- Add a GitHub Actions workflow that:
- Checks out with submodules
- Sets up Emscripten via
mymindstorm/setup-emsdk - Runs
npm run buildandnpm run build-es6 - Runs the test suite from 3c
- Uploads build artifacts on tag pushes
- Add badges to README.
- Quick-start: install, build, run example.
- API reference table (which methods, what they return, what events they emit).
- Migration notes from the legacy
arfset.api.jsto the ES6ARFsetclass. - Architecture diagram of the C++ ↔ wasm ↔ JS boundary.
- Fix
package.jsoncontributors(currently contains a single empty string).
- 1b — fix the listener leak first; it affects every other change that touches drawing.
- 1a — drop the EM_ASM once JS reads from
nftMarkerdirectly. - 2a, 2b, 2c — small, isolated JS fixes; easy wins.
- 1c — native cleanup; pairs naturally with rebuilding wasm anyway.
- 2d — delete the legacy file and asm.js builds; major-version bump.
- 3a + 3b — toolchain refresh; gives us a clean base for tests.
- 3c + 3d — tests and CI so regressions get caught from here on.
- 2e, 2f, 3e — polish and docs.