bindings for js/node/browser/deno etc
$ moon add mizchi/js{
"import": ["mizchi/js/core", "mizchi/js"]
}⚠️ Future Plans: Platform-specific APIs (Node.js, Browser, Deno) will be split into separate packages in the future. The core mizchi/js package will focus on JavaScript built-ins and Web Standard APIs.Note: Cloudflare Workers bindings have been moved to a separate package: @mizchi/cloudflare-mbt
| Platform | Documentation | Examples | Status |
|---|---|---|---|
| Core JavaScript | src/README.md | js_examples.mbt.md | 🧪 Tested |
| Browser | src/browser/README.md | browser_examples.mbt.md | 🧪 Tested |
| Node.js | src/node/README.md | node_examples.mbt.md | 🧪 Tested |
| Deno | src/deno/README.md | - | 🧪 Tested |
| React | src/npm/react/ | react_app/ | 🧪 Tested |
| Category | Package | Status | Note |
|---|---|---|---|
| Core FFI & Objects | |||
| Core FFI | mizchi/js/core | 🧪 Tested | get, set, call, etc. |
| Object | mizchi/js/builtins/object | 🧪 Tested | Object manipulation |
| Function | mizchi/js/builtins/function | 🧪 Tested | Function operations |
| Promise | mizchi/js/core | 🧪 Tested | Async/Promise API |
| Error | mizchi/js/builtins/error | 🧪 Tested | Error handling |
| JSON | mizchi/js/builtins/json | 🧪 Tested | JSON parse/stringify |
| Iterator | mizchi/js/builtins/iterator | 🧪 Tested | JS Iterator protocol |
| AsyncIterator | mizchi/js/builtins/iterator | 🧪 Tested | Async iteration |
| WeakMap/Set/Ref | mizchi/js/builtins/weak | 🧪 Tested | Weak references |
| Async Helpers | |||
| run_async | mizchi/js/core | 🧪 Tested | Async execution |
| suspend | mizchi/js/core | 🧪 Tested | Promise suspension |
| sleep | mizchi/js/core | 🧪 Tested | Delay execution |
| promisify | mizchi/js/core | 🧪 Tested | Callback → Promise |
| Category | Package | Status | Note |
|---|---|---|---|
| Global Functions | |||
| Global | mizchi/js/builtins/global | 🧪 Tested | globalThis, parseInt, parseFloat, setTimeout etc. |
| Core Types | |||
| Object | mizchi/js/builtins/object | 🧪 Tested | Object manipulation |
| Function | mizchi/js/builtins/function | 🧪 Tested | Function operations |
| Symbol | mizchi/js/builtins/symbol | 🧪 Tested | Symbol primitive |
| Error | mizchi/js/builtins/error | 🧪 Tested | Error types (TypeError, RangeError, etc.) |
| Primitives & Data | |||
| String | mizchi/js/builtins/string | 🧪 Tested | JsString (String methods) |
| Array | mizchi/js/builtins/array | 🧪 Tested | JsArray (Array methods) |
| BigInt | mizchi/js/builtins/bigint | 🧪 Tested | JsBigInt (arbitrary precision) |
| JSON | mizchi/js/builtins/json | 🧪 Tested | JSON parse/stringify |
| Date & Math | |||
| Date | mizchi/js/builtins/date | 🧪 Tested | Date/time operations |
| Math | mizchi/js/builtins/math | 🧪 Tested | Math operations |
| Collections | |||
| Map/Set | mizchi/js/builtins/collection | 🧪 Tested | JsMap, JsSet |
| WeakMap/Set/Ref | mizchi/js/builtins/weak | 🧪 Tested | WeakMap, WeakSet, WeakRef, FinalizationRegistry |
| Binary Data | |||
| ArrayBuffer | mizchi/js/builtins/arraybuffer | 🧪 Tested | Binary buffers |
| DataView | mizchi/js/builtins/arraybuffer | 🧪 Tested | Buffer views |
See mizchi/js/web for detailed Web APIs documentation
| Category | Package | Status | Note |
|---|---|---|---|
| Console | mizchi/js/web/console | 🧪 Tested | console.log, console.error, etc. |
| fetch | mizchi/js/web/http | 🧪 Tested | HTTP requests |
| Request | mizchi/js/web/http | 🧪 Tested | Request objects |
| Response | mizchi/js/web/http | 🧪 Tested | Response objects |
| Headers | mizchi/js/web/http | 🧪 Tested | HTTP headers |
| FormData | mizchi/js/web/http | 🧪 Tested | Form data |
| URL | mizchi/js/web/url | 🧪 Tested | URL parsing |
| URLSearchParams | mizchi/js/web/url | 🧪 Tested | Query strings |
| URLPattern | mizchi/js/web/url | 🧪 Tested | URL pattern matching |
| Blob | mizchi/js/web/blob | 🧪 Tested | Binary data |
| ReadableStream | mizchi/js/web/streams | 🧪 Tested | Stream reading |
| WritableStream | mizchi/js/web/streams | 🧪 Tested | Stream writing |
| TransformStream | mizchi/js/web/streams | 🧪 Tested | Stream transformation |
| CompressionStream | mizchi/js/web/streams | 🧪 Tested | GZIP/Deflate compression |
| DecompressionStream | mizchi/js/web/streams | 🧪 Tested | GZIP/Deflate decompression |
| TextEncoder | mizchi/js/web/encoding | 🧪 Tested | String to Uint8Array |
| TextDecoder | mizchi/js/web/encoding | 🧪 Tested | Uint8Array to String |
| Event | mizchi/js/web/event | 🧪 Tested | Event objects |
| CustomEvent | mizchi/js/web/event | 🧪 Tested | Custom events |
| MessageEvent | mizchi/js/web/event | 🧪 Tested | Message events |
| Crypto | mizchi/js/web/crypto | 🧪 Tested | Web Crypto API |
| WebSocket | mizchi/js/web/websocket | 🧪 Tested | WebSocket API |
| Worker | mizchi/js/web/worker | 🧪 Tested | Web Workers |
| MessageChannel | mizchi/js/web/message | 🧪 Tested | Message passing |
| MessagePort | mizchi/js/web/message | 🧪 Tested | Message ports |
| WebAssembly | mizchi/js/web/webassembly | 🤖 AI Generated | WASM integration |
| Performance | mizchi/js/web/performance | 🤖 AI Generated | Performance API |
| Platform | Package | Status | Documentation |
|---|---|---|---|
| Node.js | mizchi/js/node/* | 🧪 Tested | Node.js README |
| Browser API | mizchi/js/browser/* | 🧪 Tested | Browser README |
| Deno | mizchi/js/deno | 🧪 Tested | Deno README |
See src/npm/README.md for full npm package documentation
| Category | Packages | Status |
|---|---|---|
| UI Frameworks | React, React DOM, React Router, Preact, Ink | 🧪 Tested |
| Web Frameworks | Hono, better-auth | 🧪 Tested |
| AI / LLM | Vercel AI SDK, MCP SDK, Claude Code SDK | 🧪 Tested |
| Cloud Services | @aws-sdk/client-s3 (S3, R2, GCS, MinIO) | 🧪 Tested |
| Database | PGlite, DuckDB, Drizzle, pg | 🧪 Tested |
| Validation | Zod, AJV | 🧪 Tested |
| Build Tools | Terser, Vite, Unplugin, Lighthouse | 🧪 Tested |
| Utilities | date-fns, semver, chalk, dotenv, chokidar, yargs, debug | 🧪 Tested |
| Testing | Testing Library, Puppeteer, Playwright, Vitest, JSDOM, MSW | 🧪 Tested |
| Parsing | htmlparser2, js-yaml | 🧪 Tested |
| Other | simple-git, ignore, memfs, source-map, comlink | 🧪 Tested |
| Feature | Status | Note |
|---|---|---|
| eval() | ❌ Not Supported | Security and type safety concerns |
| new Function() | ❌ Not Supported | Security and type safety concerns |
// Create JavaScript objects
let obj = @js.from_entries([
("name", @js.any("Alice")),
("age", @js.any(30))
])
// Get property
let name = obj["name"]
// Set property
obj["age"] = @js.any(31)
// Call method
let result = obj._call("toString", [])
// Type casting
let age: Int = obj["age"].cast()moon add mizchi/js{
"import": ["mizchi/js"]
}// Create objects
let obj = @core.Object::new()
obj["name"] = "Alice" |> @js.any
obj["agen"] = 25 |> @js.any
// Get properties
let name: String = obj["name"].cast() // Returns @js.Any
let age: Int = obj["age"].cast() // Manual casting
// Call methods
let has_name: Bool = obj._call("hasOwnProperty", ["name"]).cast()
// Create from map
let obj2 = @js.from_map({ "x": @core.any(10), "y": @core.any(20) })// Using cast() method (recommended)
let value: Int = js_value.cast()
let str: String = js_value.cast()
// Using identity() for low-level FFI
let value: Int = @js.identity(js_value)
// Optional types
let nullable: Int? = @js.identity_option(js_value)// Create and use promises
let promise = @js.Promise::resolve(42)
promise.then_(fn(value) {
@console.log(value)
})
// Async/await
async fn example() -> Int {
let promise = @js.Promise::resolve(42)
let value = promise.wait()
value
}
// Run async code
@js.run_async(async fn() {
let value = some_promise.wait()
@console.log(value)
})// Sleep
async fn delayed() -> Unit {
@js.sleep(1000) // Sleep for 1 second
@console.log("Delayed!")
}
// Promisify callbacks
let async_fn = async fn(x: Int) -> String {
@js.sleep(100)
x.to_string()
}
let promise_fn = @js.promisify1(async_fn)
let promise = promise_fn(42) // Returns Promise[String]// Create arrays
let arr = @js.JsArray::new()
arr.push(1)
arr.push(2)
arr.push(3)
// Array operations
let length = arr.length()
let first = arr._get(0)
arr.set(1, 42)
// From MoonBit Array
let mbt_arr = [1, 2, 3]
let js_arr = @js.JsArray::from_array(mbt_arr)// Create errors
let err = @js.Error::new("Something went wrong")
// Throw errors (use in FFI functions marked with `raise`)
fn example() -> Int raise {
fail("Error message")
}
// Catch errors in async
async fn safe_operation() -> Unit {
try {
let result = risky_operation().wait()
@console.log(result)
} catch {
e => @console.error("Error: " + e.to_string())
}
}// Parse JSON
let json_str = "{\"name\":\"Alice\",\"age\":30}"
let obj = @js.JSON::parse(json_str)
// Stringify
let obj = @js.from_map({ "name": @core.any("Alice"), "age": @core.any(30) })
let json_str = @js.JSON::stringify(obj)
// With formatting
let pretty = @js.JSON::stringify_with_indent(obj, 2)// Nullish[T] handles both null and undefined
let nullish: @js.Nullish[Int] = @js.null()
match nullish.to_option() {
Some(value) => @console.log(value)
None => @console.log("null or undefined")
}
// Nullable[T] only handles null
let nullable: @js.Nullable[Int] = @js.Nullable::null()// JavaScript iterator
let iter = js_array.values()
loop {
let next = iter.next()
if next.done {
break
}
@console.log(next.value)
}
// Async iterator
async fn iterate_async(iter: @js.AsyncIterator) -> Unit {
loop {
let next = iter.next().wait()
if next.done {
break
}
@console.log(next.value)
}
}// @core.Any can hold any JavaScript value
let num : @core.Any = @core.any(42) // number
let str : @core.Any = @core.any("hello") // string
let obj : @core.Any = @core.Object::new() // object// Convert MoonBit values to JavaScript
let js_int = @core.any(42) // Int → @core.Any
let js_str = @core.any("hello") // String → @core.Any
let js_bool = @core.any(true) // Bool → @core.Any
let js_arr = @core.any([1, 2, 3]) // Array → @core.Any// Cast @core.Any to specific types (unsafe!)
let js_value : @core.Any = obj._get("count")
let count : Int = @js.identity(js_value)
// Common pattern: inline casting
let name : String = @js.identity(obj._get("name"))let count : Int = obj._get("count").cast()// These types implement JsImpl:
// - @core.Any, @js.Object, @js.JsArray, @js.Promise[T], etc.
// - MoonBit primitives: String, Int, Double, Bool, etc.
// - Array[T] where T : JsImpl
// JsImpl provides these methods:
trait JsImpl {
as_any(Self) -> Any // Convert to @core.Any
get(Self, key) -> Any // JS: self[key]
set(Self, key, val) -> Unit // JS: self[key] = val
call(Self, key, args) -> Any // JS: self[key](...args)
// ... and more
}// JavaScript: const name = obj.name
let name : String = @js.identity(obj._get("name"))
// Alternative using cast()
let age : Int = obj._get("age").cast()// Using from_map (recommended)
let obj = @js.from_map({
"name": @core.any("Alice"),
"age": @core.any(30)
})
// Manual construction
let obj = @core.Object::new()
obj.set("name", "Alice") // String implements JsImpl
obj.set("age", 30) // Int implements JsImpl// JavaScript null/undefined → MoonBit Option
let maybe_value : Int? = @js.identity_option(obj._get("optional_field"))
// MoonBit Option → JavaScript null
let js_value = @js.from_option(Some(42)) // → 42
let js_null = @js.from_option(None) // → null// No arguments: obj.method()
let result = obj.call0("method")
// With arguments: obj.method(arg1, arg2)
let result = obj._call("method", [arg1, arg2])
// With type casting
let str_result : String = obj.call0("toString").cast()| Function/Type | Purpose | Example |
|---|---|---|
| @core.Any | Universal JS value type | let v : @core.Any = ... |
| @core.any(x) | MoonBit → JS conversion | @core.any(42) |
| @js.identity(x) | Unsafe type cast | let n : Int = @js.identity(v) |
| .cast() | Same as identity (method) | v.cast() |
| JsImpl | Trait for JS-compatible types | fn foo(x : &JsImpl) |
| .as_any() | Convert to @core.Any | obj.as_any() |
| ._get(key) | Property access | obj._get("name") |
| .set(key, val) | Property assignment | obj.set("age", 30) |
// Define external FFI function
extern "js" fn ffi_my_custom_api(arg: @core.Any) -> @core.Any =
#|arg => {
#| // JavaScript code here
#| return arg.customMethod();
#|}
// Wrap it in a type-safe function
pub fn my_custom_api(value: String) -> String {
let result = ffi_my_custom_api(value)
result.cast()
}// Type rename: @js.Js → @core.Any
let value: @core.Any = obj._get("key")
// Method rename: to_js() → as_any()
let any = obj.as_any()
// Function rename: @js.js() → @core.any()
let converted = @core.any(value)
// Casting: unsafe_cast() → identity() or cast()
let typed: Int = value.cast()fn atob(encoded_data : String) -> String raisefn btoa(data : String) -> String raisefn decodeURIComponent(encoded_str : String) -> Stringlet p : Promise[Int] = from_async(async fn() {
let result = some_async_operation()
result
})fn parseFloat(string : String) -> Double?fn parseInt(string : String, radix? : Int) -> Int?fn queueMicrotask(callback : () -> Unit) -> Unitasync fn[T, E : Error] suspend(f : ((T) -> Unit, (E) -> Unit) -> Unit) -> T raise Elet result = throwable(() => undefined()._invoke([]))