GEOS WebAssembly Bindings
geos-wasm provides a high-performance WebAssembly (WASM) build of GEOS, a robust C/C++ port of the Java Topology Suite (JTS), enabling advanced planar geometry operations directly within JavaScript environments. Currently at version 3.1.1, this library allows developers to leverage a battle-tested geospatial engine without relying on native system dependencies, making it suitable for both browser-based applications and server-side contexts like Node.js, Bun, or Deno. Built using Emscripten, geos-wasm translates GEOS's extensive C/C++ core into an efficient WebAssembly module. Its key differentiator is bringing the full power and precision of GEOS's algorithms—such as buffering, intersection, union, and area calculation—to JavaScript with a minimal setup, abstracting away the complexities of the underlying C/C++ memory management through its WASM interface. While no fixed release cadence is stated, updates typically align with upstream GEOS advancements and community-driven requirements, ensuring access to the latest topological functionalities.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'GEOSWKTReader_create')
cause The `initGeosJs()` function, which initializes the WebAssembly module and returns the GEOS object, was not awaited or has not yet resolved before its methods were accessed.fixEnsure `const geos = await initGeosJs();` is called and successfully resolves within an `async` context before attempting to access any `geos` methods. -
Memory leak detected in performance profiler / Application consumes increasing amounts of RAM over time.
cause GEOS objects (geometries, readers) or manually allocated memory pointers (`_malloc`) are not being explicitly freed or destroyed after use, leading to unmanaged memory growth within the WebAssembly module.fixThoroughly review your code to ensure all GEOS objects are destroyed (`geos.GEOSGeom_destroy()`, `geos.GEOSWKTReader_destroy()`) and all manually allocated pointers are freed (`geos.Module._free()`, `geos.GEOSFree()`) once they are no longer needed. -
SyntaxError: Cannot use import statement outside a module
cause You are attempting to use ESM `import` syntax in a CommonJS environment (e.g., a `.js` file without `"type": "module"` in `package.json`, or a `.cjs` file in Node.js).fixConfigure your Node.js project for ESM by adding `"type": "module"` to your `package.json`, or rename your file to `.mjs`. If you must use CommonJS, consider dynamic `import()`: `const { default: initGeosJs } = await import('geos-wasm');`
Warnings
- gotcha geos-wasm requires explicit manual memory management using functions like `geos.Module._malloc()`, `geos.Module._free()`, `geos.GEOSGeom_destroy()`, and `geos.GEOSWKTReader_destroy()`. Failing to free allocated pointers and destroy GEOS objects will lead to memory leaks, which is highly atypical for JavaScript development.
- gotcha Interaction with GEOS functions often involves passing and receiving raw memory pointers, requiring a C-like programming paradigm not common in JavaScript. Developers must understand how to allocate memory, write data to pointers, and read values from them using `geos.Module` utilities.
- gotcha The `initGeosJs()` function is asynchronous and returns a Promise. All GEOS operations must be performed only after this Promise has successfully resolved to the GEOS object, otherwise `TypeError`s will occur due to attempts to access properties of an undefined or unresolved object.
Install
-
npm install geos-wasm -
yarn add geos-wasm -
pnpm add geos-wasm
Imports
- initGeosJs
const initGeosJs = require('geos-wasm');import initGeosJs from 'geos-wasm';
- GEOS functions (e.g., GEOSWKTReader_create)
const geos = await initGeosJs(); const reader = geos.GEOSWKTReader_create();
- GEOS Type
import type { GEOS } from 'geos-wasm';
Quickstart
import initGeosJs from 'geos-wasm';
async function runGeosExample() {
// Initialize the GEOS WebAssembly module. This returns a promise.
const geos = await initGeosJs();
// Use the GEOS object to call GEOS functions.
// Example: Get the area of a polygon defined by WKT.
// 1. Create a WKT reader.
const reader = geos.GEOSWKTReader_create();
const wkt = 'POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))';
// 2. Allocate memory for the WKT string and write it.
const size = wkt.length + 1;
const wktPtr = geos.Module._malloc(size);
geos.Module.stringToUTF8(wkt, wktPtr, size);
// 3. Read the WKT string into a GEOS geometry, which returns a pointer to the geometry.
const geomPtr = geos.GEOSWKTReader_read(reader, wktPtr);
// 4. Allocate memory for the result (area) and calculate it.
const areaPtr = geos.Module._malloc(8); // 8 bytes for a double
geos.GEOSArea(geomPtr, areaPtr);
// 5. Read the calculated area from the pointer into a JavaScript number.
const area = geos.Module.getValue(areaPtr, 'double');
console.log('Calculated area:', area); // Expected output: Calculated area: 1
// 6. Crucially, free all allocated GEOS objects and memory pointers.
geos.GEOSWKTReader_destroy(reader);
geos.GEOSGeom_destroy(geomPtr);
geos.GEOSFree(areaPtr); // GEOSFree for values allocated by GEOS
geos.Module._free(wktPtr); // Module._free for values allocated by Emscripten's malloc
}
// Run the example and catch any potential errors.
runGeosExample().catch(console.error);