{"id":29129896,"url":"https://github.com/tapsterbot/burrito","last_synced_at":"2026-03-08T13:37:40.027Z","repository":{"id":300333761,"uuid":"1005901659","full_name":"tapsterbot/burrito","owner":"tapsterbot","description":"🌯👑 Nim wrapper for QuickJS ⚡🌯","archived":false,"fork":false,"pushed_at":"2025-06-26T04:54:38.000Z","size":276,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-30T02:14:49.514Z","etag":null,"topics":["js","nim","quickjs","repl"],"latest_commit_sha":null,"homepage":"https://tapsterbot.github.io/burrito/","language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tapsterbot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-21T03:49:35.000Z","updated_at":"2025-06-26T04:54:41.000Z","dependencies_parsed_at":"2025-06-21T05:29:17.008Z","dependency_job_id":"615c4af2-7a45-41b0-8d23-4b5ea8e9039e","html_url":"https://github.com/tapsterbot/burrito","commit_stats":null,"previous_names":["tapsterbot/burrito"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tapsterbot/burrito","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tapsterbot%2Fburrito","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tapsterbot%2Fburrito/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tapsterbot%2Fburrito/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tapsterbot%2Fburrito/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tapsterbot","download_url":"https://codeload.github.com/tapsterbot/burrito/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tapsterbot%2Fburrito/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262707958,"owners_count":23351525,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["js","nim","quickjs","repl"],"created_at":"2025-06-30T04:01:10.042Z","updated_at":"2026-03-08T13:37:39.961Z","avatar_url":"https://github.com/tapsterbot.png","language":"Nim","readme":"# Burrito 🌯\n\nA Nim wrapper for the [QuickJS JavaScript engine](https://github.com/bellard/quickjs).\n\n## Features\n\n- 🎯 **Embeddable REPL**: Drop a complete JavaScript REPL into your Nim app with just a few lines of code\n- 🎨 **Full-featured REPL**: Syntax highlighting, command history, multi-line editing - the complete QuickJS REPL experience\n- 📦 **Simple API**: Easy-to-use API for embedding JavaScript in Nim\n- 🔗 **Two-way Binding**: Run JavaScript from Nim and call Nim functions from JavaScript\n- 🔢 **Flexible Functions**: Support for functions with different numbers of arguments\n- 🔄 **Type Marshaling**: Comprehensive conversion between Nim and JavaScript data structures\n- 🚀 **Native Performance**: Native C function bridging with zero overhead\n- 📚 **Standard Modules**: Full support for QuickJS std and os modules\n\n## Installation\n\n### Prerequisites\n\n- Nim \u003e= 2.2.4\n- C compiler (gcc/clang)\n- Make\n- curl (for downloading QuickJS source)\n- tar (with xz support - available on most modern systems)\n- expect (optional, for running REPL tests)\n\n#### Linux (Ubuntu/Debian)\n```bash\nsudo apt update\nsudo apt install nim build-essential curl expect\n```\n\n#### Termux (Android)\n```bash\npkg update\npkg install nim build-essential curl expect\n```\n\n#### macOS\n```bash\nbrew install nim expect\n# Xcode Command Line Tools provide clang/make: xcode-select --install\n# curl and tar are pre-installed\n```\n\n#### Other platforms\n- Install Nim from [nim-lang.org/install.html](https://nim-lang.org/install.html)\n- Ensure you have a C compiler, make, curl, and expect (optional)\n\n### Install Steps\n\n1. **Clone the repository:**\n   ```bash\n   git clone https://github.com/tapsterbot/burrito.git\n   cd burrito\n   ```\n\n2. **Download and build QuickJS:**\n   ```bash\n   nimble get_quickjs\n   nimble build_quickjs\n   ```\n\n3. **Install the package:**\n   ```bash\n   nimble install\n   ```\n\n4. **Run examples:**\n   ```bash\n   nimble example\n   ```\n\n## Quick Start\n\n### Basic JavaScript Evaluation\n\n```nim\nimport burrito\n\n# Create a QuickJS instance\nvar js = newQuickJS()\ndefer: js.close()\n\n# Evaluate JavaScript code\necho js.eval(\"2 + 3\")                    # 5\necho js.eval(\"'Hello ' + 'World!'\")      # Hello World!\necho js.eval(\"Math.sqrt(16)\")            # 4\n```\n\n### Calling Nim Functions from JavaScript (Native C Bridging)\n\n```nim\nimport burrito\nimport std/times\n\n# Define Nim functions that work with JSValue directly\nproc getTime(ctx: ptr JSContext): JSValue =\n  let timeStr = now().format(\"yyyy-MM-dd HH:mm:ss\")\n  result = nimStringToJS(ctx, timeStr)\n\nproc getMessage(ctx: ptr JSContext): JSValue =\n  let msg = \"Hello from Nim! 🌯\"\n  result = nimStringToJS(ctx, msg)\n\nvar js = newQuickJS()\ndefer: js.close()\n\n# Register functions using native C bridging (no setup needed!)\njs.registerFunction(\"getTime\", getTime)\njs.registerFunction(\"getMessage\", getMessage)\n\n# Call Nim functions from JavaScript with native performance!\necho js.eval(\"getTime()\")     # \"2025-06-21 17:33:00\"\necho js.eval(\"getMessage()\")  # \"Hello from Nim! 🌯\"\n```\n\n### Advanced Function Registration\n\n```nim\nimport burrito\n\n# Different function signatures are supported\nproc square(ctx: ptr JSContext, arg: JSValue): JSValue =\n  let num = toNimFloat(ctx, arg)\n  nimFloatToJS(ctx, num * num)\n\nproc addNumbers(ctx: ptr JSContext, arg1, arg2: JSValue): JSValue =\n  let a = toNimFloat(ctx, arg1)\n  let b = toNimFloat(ctx, arg2)\n  nimFloatToJS(ctx, a + b)\n\nproc concatenate(ctx: ptr JSContext, args: seq[JSValue]): JSValue =\n  var result_str = \"\"\n  for arg in args:\n    result_str.add(toNimString(ctx, arg))\n  nimStringToJS(ctx, result_str)\n\nvar js = newQuickJS()\ndefer: js.close()\n\n# Register functions with different arities\njs.registerFunction(\"square\", square)           # 1 argument\njs.registerFunction(\"add\", addNumbers)          # 2 arguments\njs.registerFunction(\"concat\", concatenate)      # variadic arguments\n\necho js.eval(\"square(7)\")                       # 49\necho js.eval(\"add(5, 3)\")                       # 8\necho js.eval(\"concat('Hello', ' ', 'World!')\")  # Hello World!\n```\n\n## 🎯 Embedded JavaScript REPL\n\n**The killer feature**: Embed a complete JavaScript REPL into your Nim applications! Perfect for:\n- Interactive debugging and development tools\n- Live coding environments\n- Educational applications\n- Developer consoles in your apps\n- Interactive scripting interfaces\n\n### Drop-in REPL Example\n\n```nim\nimport burrito\n\nproc main() =\n  # Create QuickJS instance with full REPL support\n  var js = newQuickJS(QuickJSConfig(\n    enableStdHandlers: true,\n    includeStdLib: true,\n    includeOsLib: true\n  ))\n  defer: js.close()\n\n  # Add your custom functions to the REPL environment\n  proc greet(ctx: ptr JSContext, name: JSValue): JSValue =\n    let nameStr = toNimString(ctx, name)\n    nimStringToJS(ctx, \"Hello from Nim, \" \u0026 nameStr \u0026 \"!\")\n\n  js.registerFunction(\"greet\", greet)\n\n  # Load and start the interactive REPL\n  let replCode = readFile(\"quickjs/repl.js\")\n  discard js.evalModule(replCode, \"\u003crepl\u003e\")\n  js.runPendingJobs()\n\n  # REPL is now running! Users can:\n  # - Call your Nim functions: greet(\"Alice\")\n  # - Use std/os modules: std.printf(\"Hello %s\\n\", \"world\")\n  # - Get syntax highlighting and command history\n  # - Exit with Ctrl+D, Ctrl+C, or \\q\n  js.processStdLoop()\n\nwhen isMainModule:\n  main()\n```\n\n### Standalone REPL\n\nWant to try it right now? Burrito includes a standalone REPL:\n\n```bash\nnim c -r examples/repl.nim\n```\n\nThis gives you:\n- ✅ Full QuickJS REPL with syntax highlighting\n- ✅ Command history (arrow keys work)\n- ✅ Multi-line input support\n- ✅ Access to std and os modules\n- ✅ Clean exit with Ctrl+D\n\n### REPL in Your Application\n\nEmbedding the REPL into your own application is incredibly simple:\n\n```nim\n# In your application code\nproc startDebugREPL(myAppContext: MyAppType) =\n  var js = newQuickJS(configWithBothLibs())\n  defer: js.close()\n\n  # Expose your app's functionality to the REPL\n  proc getAppStatus(ctx: ptr JSContext): JSValue =\n    nimStringToJS(ctx, myAppContext.status)\n\n  js.registerFunction(\"getAppStatus\", getAppStatus)\n\n  # Start REPL for debugging/development\n  let replCode = readFile(\"quickjs/repl.js\")\n  discard js.evalModule(replCode, \"\u003cdebug-repl\u003e\")\n  js.runPendingJobs()\n  js.processStdLoop()\n```\n\n## Standard Library Modules (std/os)\n\nBurrito supports QuickJS's built-in `std` and `os` modules for file I/O, environment access, and system operations:\n\n### Basic std Module Usage\n\n```nim\nimport burrito\n\n# Enable std module\nvar js = newQuickJS(configWithStdLib())\ndefer: js.close()\n\n# Access environment variables and printf functionality\ndiscard js.evalModule(\"\"\"\n  import * as std from \"std\";\n\n  let shell = std.getenv(\"SHELL\") || \"unknown\";\n  std.out.printf(\"Current shell: %s\\n\", shell);\n\"\"\")\n```\n\n### Basic os Module Usage\n\n```nim\nimport burrito\n\n# Enable os module\nvar js = newQuickJS(configWithOsLib())\ndefer: js.close()\n\n# Get current directory and system info\ndiscard js.evalModule(\"\"\"\n  import * as os from \"os\";\n\n  let [cwd, err] = os.getcwd();\n  if (!err) {\n    console.log(\"Working directory:\", cwd);\n    console.log(\"Platform:\", os.platform);\n  }\n\"\"\")\n```\n\n### Using Both Modules\n\n```nim\nimport burrito\n\n# Enable both std and os modules\nvar js = newQuickJS(configWithBothLibs())\ndefer: js.close()\n\n# Combine functionality from both modules\ndiscard js.evalModule(\"\"\"\n  import * as std from \"std\";\n  import * as os from \"os\";\n\n  let [cwd] = os.getcwd();\n  let shell = std.getenv(\"SHELL\") || \"unknown\";\n\n  std.out.printf(\"Running %s in %s\\n\",\n                 shell.split('/').pop(),\n                 cwd.split('/').pop());\n\"\"\")\n```\n\n**Available configurations:**\n- `newQuickJS()` - Default (no modules)\n- `newQuickJS(configWithStdLib())` - std module only\n- `newQuickJS(configWithOsLib())` - os module only\n- `newQuickJS(configWithBothLibs())` - Both modules\n\n**Note:** ES6 modules correctly return `undefined` per specification. Use module side effects (like `printf`, `console.log`) or `export default` for return values.\n\n## Memory Management\n\nBurrito is memory-safe by design. All JavaScript values are automatically managed - just write your functions naturally:\n\n```nim\nproc processText(ctx: ptr JSContext, text: JSValue): JSValue =\n  let input = toNimString(ctx, text)\n  return nimStringToJS(ctx, input.toUpper())\n```\n\nMemory cleanup happens automatically when functions return. Property access and array helpers also handle their own cleanup.\n\n## Thread Safety\n\n**⚠️ IMPORTANT**: QuickJS instances are **NOT thread-safe**. You have two options:\n\n### Option 1: One Instance Per Thread (Recommended)\n```nim\n# Each thread should create its own QuickJS instance\nproc workerThread() {.thread.} =\n  var js = newQuickJS()  # Create instance in this thread\n  defer: js.close()\n  echo js.eval(\"2 + 2\")  # Safe - only this thread uses this instance\n```\n\n### Option 2: External Synchronization\nIf you must share an instance across threads, use locks:\n```nim\nimport std/locks\n\nvar\n  js = newQuickJS()\n  jsLock: Lock\n\ninitLock(jsLock)\n\nproc safeEval(code: string): string =\n  withLock jsLock:\n    return js.eval(code)  # Protected by lock\n```\n\n## API Reference\n\n### Types\n\n- `QuickJS`: Main wrapper object containing runtime and context (⚠️ NOT thread-safe)\n- `JSValue`: JavaScript value type (native QuickJS value)\n- `JSException`: Exception type for JavaScript errors\n- `NimFunction0*`: Function type with no arguments: `proc(ctx: ptr JSContext): JSValue`\n- `NimFunction1*`: Function type with one argument: `proc(ctx: ptr JSContext, arg: JSValue): JSValue`\n- `NimFunction2*`: Function type with two arguments: `proc(ctx: ptr JSContext, arg1, arg2: JSValue): JSValue`\n- `NimFunction3*`: Function type with three arguments: `proc(ctx: ptr JSContext, arg1, arg2, arg3: JSValue): JSValue`\n- `NimFunctionVariadic*`: Function type with variable arguments: `proc(ctx: ptr JSContext, args: seq[JSValue]): JSValue`\n\n### Core Functions\n\n#### `newQuickJS(config: QuickJSConfig = defaultConfig()): QuickJS`\nCreates a new QuickJS instance with runtime and context. **Not thread-safe** - use one instance per thread or external locking.\n\n**Configuration options:**\n- `defaultConfig()` - Basic QuickJS (no std/os modules)\n- `configWithStdLib()` - Enable std module\n- `configWithOsLib()` - Enable os module\n- `configWithBothLibs()` - Enable both std and os modules\n\n#### `close(js: var QuickJS)`\nProperly cleans up QuickJS instance (called automatically with `defer`).\n\n#### `eval(js: QuickJS, code: string, filename: string = \"\u003ceval\u003e\"): string`\nEvaluates JavaScript code and returns the result as a string.\n\n#### `evalModule(js: QuickJS, code: string, filename: string = \"\u003cmodule\u003e\"): string`\nEvaluates JavaScript code as an ES6 module (enables import/export syntax). Returns `undefined` per ES6 specification - use for side effects or `export default`.\n\n#### `evalWithGlobals(js: QuickJS, code: string, globals: Table[string, string]): string`\nEvaluates JavaScript code with global variables set from Nim.\n\n#### `setJSFunction(js: QuickJS, name: string, value: string)`\nSets a JavaScript function in the global scope from a string definition.\n\n#### `registerFunction(js: var QuickJS, name: string, nimFunc: NimFunction0|1|2|3|Variadic)`\nRegisters a Nim function to be callable from JavaScript using native C function bridging. The function type is automatically detected based on the signature. No setup required!\n\n#### `canUseStdLib(js: QuickJS): bool`\nCheck if std module is available in this QuickJS instance.\n\n#### `canUseOsLib(js: QuickJS): bool`\nCheck if os module is available in this QuickJS instance.\n\n#### `runPendingJobs(js: QuickJS)`\nExecute all pending JavaScript jobs (promises, async operations). This is needed after loading modules or running async code.\n\n#### `processStdLoop(js: QuickJS)`\nProcess the QuickJS standard event loop once. This handles timers, I/O, and other async operations. Only available when enableStdHandlers is true. For REPL usage, this runs the complete interactive loop until exit.\n\n### Value Conversion Helpers\n\n#### JavaScript to Nim\n- `toNimString(ctx: ptr JSContext, val: JSValueConst): string`\n- `toNimInt(ctx: ptr JSContext, val: JSValueConst): int32`\n- `toNimFloat(ctx: ptr JSContext, val: JSValueConst): float64`\n- `toNimBool(ctx: ptr JSContext, val: JSValueConst): bool`\n\n#### Nim to JavaScript\n- `nimStringToJS(ctx: ptr JSContext, str: string): JSValue`\n- `nimIntToJS(ctx: ptr JSContext, val: int32): JSValue`\n- `nimFloatToJS(ctx: ptr JSContext, val: float64): JSValue`\n- `nimBoolToJS(ctx: ptr JSContext, val: bool): JSValue`\n\n### Type Checking Functions\n\n- `isUndefined(ctx: ptr JSContext, val: JSValueConst): bool`\n- `isNull(ctx: ptr JSContext, val: JSValueConst): bool`\n- `isBool(ctx: ptr JSContext, val: JSValueConst): bool`\n- `isNumber(ctx: ptr JSContext, val: JSValueConst): bool`\n- `isString(ctx: ptr JSContext, val: JSValueConst): bool`\n- `isObject(ctx: ptr JSContext, val: JSValueConst): bool`\n- `isArray(ctx: ptr JSContext, val: JSValueConst): bool`\n- `isFunction(ctx: ptr JSContext, val: JSValueConst): bool`\n\n### Object and Array Manipulation\n\n#### Object Operations\n- `getProperty(ctx: ptr JSContext, obj: JSValueConst, key: string): JSValue`\n- `setProperty(ctx: ptr JSContext, obj: JSValueConst, key: string, value: JSValue): bool`\n\n#### Array Operations\n- `newArray(ctx: ptr JSContext): JSValue`\n- `getArrayElement(ctx: ptr JSContext, arr: JSValueConst, index: uint32): JSValue`\n- `setArrayElement(ctx: ptr JSContext, arr: JSValueConst, index: uint32, value: JSValue): bool`\n- `getArrayLength(ctx: ptr JSContext, arr: JSValueConst): uint32`\n\n### Auto-Memory Management Helpers\n\nThese functions automatically handle `JS_FreeValue` for you, making memory management effortless:\n\n#### Direct Value Access\n- `getPropertyValue[T](ctx: ptr JSContext, obj: JSValueConst, key: string, target: typedesc[T]): T`\n- `getArrayElementValue[T](ctx: ptr JSContext, arr: JSValueConst, index: uint32, target: typedesc[T]): T`\n- `setGlobalProperty[T](ctx: ptr JSContext, name: string, value: T): bool`\n- `getGlobalProperty[T](ctx: ptr JSContext, name: string, target: typedesc[T]): T`\n\n#### Scoped Access Templates\n- `withGlobalObject(ctx, globalVar, body)` - Auto-manage global object lifetime\n- `withProperty(ctx, obj, key, propVar, body)` - Auto-manage property lifetime\n- `withArrayElement(ctx, arr, index, elemVar, body)` - Auto-manage array element lifetime\n\n#### High-level Iteration\n- `iterateArray(ctx: ptr JSContext, arr: JSValueConst, callback)` - Iterate with auto memory management\n- `collectArray[T](ctx: ptr JSContext, arr: JSValueConst, target: typedesc[T]): seq[T]` - Collect to sequence\n\n**Complete Example:**\n```nim\nimport burrito\n\n# Create QuickJS instance\nvar js = newQuickJS()\ndefer: js.close()\n\n# Set up some test data in JavaScript\ndiscard js.eval(\"\"\"\n  userName = \"Alice\";\n  userAge = 30;\n  userScore = 95.5;\n  isActive = true;\n\"\"\")\n\n# Old way (manual memory management)\nlet globalObj = JS_GetGlobalObject(js.context)\nlet nameVal = getProperty(js.context, globalObj, \"userName\")\ndefer:\n  JS_FreeValue(js.context, globalObj)\n  JS_FreeValue(js.context, nameVal)\nlet name = toNimString(js.context, nameVal)\n\necho \"Old way result: \", name\n\n# New ways (automatic memory management + idiomatic syntax)\nlet name2 = js.context.getString(\"userName\")          # Type-specific method\nlet name3 = js.context.get(\"userName\", string)       # Generic method\njs.context[\"userName\"] = \"Bob\"                       # Idiomatic assignment\n\necho \"New way results: \", name2, \", \", name3\necho \"After assignment: \", js.context.getString(\"userName\")\n```\n\n### Idiomatic Syntax Helpers\n\nBurrito provides beautiful, Nim-like syntax for common operations:\n\n#### Global Property Access\n```nim\nimport burrito\n\n# Create QuickJS instance\nvar js = newQuickJS()\ndefer: js.close()\n\n# Set up test data\ndiscard js.eval(\"\"\"\n  userName = \"Alice\";\n  userAge = 30;\n  userScore = 95.5;\n  isActive = true;\n\"\"\")\n\nlet ctx = js.context\n\n# Type-specific methods (recommended)\nlet name = ctx.getString(\"userName\")\nlet age = ctx.getInt(\"userAge\")  \nlet score = ctx.getFloat(\"userScore\")\nlet active = ctx.getBool(\"isActive\")\n\necho \"Type-specific: \", name, \", \", age, \", \", score, \", \", active\n\n# Generic method with explicit type\nlet name1 = ctx.get(\"userName\", string)\nlet age1 = ctx.get(\"userAge\", int)\n\necho \"Generic explicit: \", name1, \", \", age1\n\n# Auto-detecting method with property access\nlet age2 = ctx.get(\"userAge\").int\nlet score2 = ctx.get(\"userScore\").float\nlet active2 = ctx.get(\"isActive\").bool\nlet name2 = ctx.get(\"userName\").string\n\necho \"Auto-detecting: \", name2, \", \", age2, \", \", score2, \", \", active2\n\n# Assignment (works with any type)\nctx[\"userName\"] = \"Bob\"\nctx[\"userAge\"] = 25\nctx.set(\"userScore\", 88.0)\n\necho \"After assignment: \", ctx.getString(\"userName\"), \", \", ctx.getInt(\"userAge\")\n```\n\n### Comprehensive Type Marshaling\n\nBurrito provides advanced type marshaling capabilities for seamless conversion between Nim data structures and JavaScript values.\n\n#### Sequence and Array Conversions\n- `seqToJS[T](ctx: ptr JSContext, s: seq[T]): JSValue` - Convert Nim sequence to JavaScript array\n  - Supports: `string`, `int`/`int32`, `float`/`float64`, `bool`, and complex types (via string representation)\n\n#### Table and Object Conversions\n- `tableToJS[K,V](ctx: ptr JSContext, t: Table[K,V]): JSValue` - Convert Nim Table to JavaScript object\n  - Key types: Any type convertible to string\n  - Value types: `string`, `int`/`int32`, `float`/`float64`, `bool`, and complex types (via string representation)\n\n#### Tuple Conversions\n- `nimTupleToJSArray[T](ctx: ptr JSContext, tup: T): JSValue` - Convert Nim tuple to JavaScript array\n  - Supported tuple types: `(string, int)`, `(string, string)`, `(int, int)`\n\n#### Custom Object Type Support\nCreate your own conversion functions for custom Nim object types:\n\n```nim\ntype\n  Person = object\n    name: string\n    age: int\n    email: string\n\nproc personToJS(ctx: ptr JSContext, person: Person): JSValue =\n  let obj = JS_NewObject(ctx)\n  discard setProperty(ctx, obj, \"name\", nimStringToJS(ctx, person.name))\n  discard setProperty(ctx, obj, \"age\", nimIntToJS(ctx, person.age.int32))\n  discard setProperty(ctx, obj, \"email\", nimStringToJS(ctx, person.email))\n  return obj\n\nproc jsToPerson(ctx: ptr JSContext, jsObj: JSValueConst): Person =\n  let nameVal = getProperty(ctx, jsObj, \"name\")\n  let ageVal = getProperty(ctx, jsObj, \"age\")\n  let emailVal = getProperty(ctx, jsObj, \"email\")\n  defer:\n    JS_FreeValue(ctx, nameVal)\n    JS_FreeValue(ctx, ageVal)\n    JS_FreeValue(ctx, emailVal)\n\n  result = Person(\n    name: toNimString(ctx, nameVal),\n    age: toNimInt(ctx, ageVal).int,\n    email: toNimString(ctx, emailVal)\n  )\n```\n\n#### Practical Type Marshaling Example\n\n```nim\nimport burrito\nimport std/tables\n\n# Create QuickJS instance\nvar js = newQuickJS()\ndefer: js.close()\n\n# Convert Nim data structures to JavaScript\nlet fruits = @[\"apple\", \"banana\", \"cherry\"]\nlet config = {\"host\": \"localhost\", \"port\": \"8080\"}.toTable()\nlet point = (x: 100, y: 200)\n\nlet ctx = js.context\n\n# Set them as global JavaScript variables using idiomatic syntax\nctx[\"fruits\"] = seqToJS(ctx, fruits)\nctx[\"config\"] = tableToJS(ctx, config)  \nctx[\"point\"] = nimTupleToJSArray(ctx, point)\n\n# Use them in JavaScript\necho \"Fruits length: \", js.eval(\"fruits.length\")                    # 3\necho \"Fruits joined: \", js.eval(\"fruits.join(', ')\")               # apple, banana, cherry\necho \"Config URL: \", js.eval(\"config.host + ':' + config.port\")    # localhost:8080\necho \"Point sum: \", js.eval(\"point[0] + point[1]\")                 # 300\n\n# Can also access them back from Nim\necho \"Back to Nim - first fruit: \", js.eval(\"fruits[0]\")           # apple\necho \"Back to Nim - config host: \", js.eval(\"config.host\")         # localhost\n```\n\n## Examples\n\nBurrito includes comprehensive examples showcasing all features from beginner-friendly to advanced:\n\n### 🎯 REPL Examples\n```bash\nnim c -r examples/repl.nim                      # 🌟 Standalone JavaScript REPL with full QuickJS features\nnim c -r examples/repl_with_nim_functions.nim   # 🎯 REPL with custom Nim functions exposed\n```\n\n### Core Examples\n```bash\nnim c -r examples/basic_example.nim             # Basic JavaScript evaluation\nnim c -r examples/call_nim_from_js.nim          # Call Nim functions from JavaScript\nnim c -r examples/advanced_native_bridging.nim  # Advanced native function bridging\n```\n\n### More Feature Examples\n```bash\nnim c -r examples/comprehensive_features.nim    # ALL features from high-level to low-level\nnim c -r examples/idiomatic_patterns.nim        # Beautiful idiomatic Nim syntax patterns\nnim c -r examples/module_example.nim            # Using ES6 modules with std/os module functionality\nnim c -r examples/type_system.nim               # Advanced type marshaling and safety\n```\n\nOr run all examples at once:\n```bash\nnimble examples\n```\n\n## Contributing\n\nPatches welcome!\n\n## License\n\nMIT License - see LICENSE file for details.\n\nQuickJS is licensed under the MIT license. See `quickjs/LICENSE` for QuickJS license details.\n\n## Related Projects\n\n- [QuickJS](https://github.com/bellard/quickjs) - The underlying JavaScript engine\n- [QuickJS Documentation](https://bellard.org/quickjs/) - Official QuickJS documentation\n\n---\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftapsterbot%2Fburrito","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftapsterbot%2Fburrito","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftapsterbot%2Fburrito/lists"}