Quickjs.rb
A CRuby wrapper to run QuickJS in Ruby
Install / Use
/learn @hmsk/Quickjs.rbREADME
quickjs.rb
A Ruby wrapper for QuickJS to run JavaScript codes via Ruby with a smaller footprint.
Installation
gem install quickjs
gem 'quickjs'
Usage
Quickjs.eval_code: Evaluate JavaScript code instantly
require 'quickjs'
Quickjs.eval_code('const fn = (n, pow) => n ** pow; fn(2,8);') # => 256
Quickjs.eval_code('const fn = (name) => `Hi, ${name}!`; fn("Itadori");') # => "Hi, Itadori!"
Quickjs.eval_code("[1,2,3]") #=> [1, 2, 3]
Quickjs.eval_code("({ a: '1', b: 1 })") #=> { 'a' => '1', 'b' => 1 }
<details>
<summary>Options</summary>
Resources
Quickjs.eval_code(code,
memory_limit: 1024 ** 3, # 1GB memory limit
max_stack_size: 1024 ** 2, # 1MB max stack size
)
Timeout
# eval_code will be interrupted after 1 sec (default: 100 msec)
Quickjs.eval_code(code, timeout_msec: 1_000)
Features
Quickjs.eval_code(code, features: [::Quickjs::MODULE_STD, ::Quickjs::POLYFILL_FILE])
| Constant | Description |
|---|---|
| MODULE_STD | QuickJS std module |
| MODULE_OS | QuickJS os module |
| FEATURE_TIMEOUT | setTimeout / setInterval managed by CRuby |
| POLYFILL_INTL | Intl API (DateTimeFormat, NumberFormat, PluralRules, Locale) |
| POLYFILL_FILE | W3C File API (Blob and File) |
| POLYFILL_ENCODING | Encoding API (TextEncoder and TextDecoder) |
| POLYFILL_URL | URL API (URL and URLSearchParams) |
| POLYFILL_CRYPTO | Web Crypto API (crypto.getRandomValues, crypto.randomUUID, crypto.subtle); combine with POLYFILL_ENCODING for string↔buffer conversion |
Quickjs::VM: Maintain a consistent VM/runtime
Accepts the same options as Quickjs.eval_code.
vm = Quickjs::VM.new
vm.eval_code('const a = { b: "c" };')
vm.eval_code('a.b;') #=> "c"
vm.eval_code('a.b = "d";')
vm.eval_code('a.b;') #=> "d"
Quickjs::VM#call: ⚡ Call a JS function directly with Ruby arguments
vm = Quickjs::VM.new
vm.eval_code('function add(a, b) { return a + b; }')
vm.call('add', 1, 2) #=> 3
vm.call(:add, 1, 2) #=> 3 (Symbol also works)
# Nested functions — preserves `this` binding
vm.eval_code('const counter = { n: 0, inc() { return ++this.n; } }')
vm.call('counter.inc') #=> 1
vm.call('counter.inc') #=> 2
# Keys with special characters via bracket notation
vm.eval_code("const obj = {}; obj['my-fn'] = x => x * 2;")
vm.call('obj["my-fn"]', 21) #=> 42
# Async functions are automatically awaited
vm.eval_code('async function fetchVal() { return 42; }')
vm.call('fetchVal') #=> 42
Quickjs::VM#import: 🔌 Import ESM from a source code
vm = Quickjs::VM.new
# Equivalent to `import { default: aliasedDefault, member: member } from './exports.esm.js';`
vm.import({ default: 'aliasedDefault', member: 'member' }, from: File.read('exports.esm.js'))
vm.eval_code("aliasedDefault()") #=> Exported `default` of the ESM is called
vm.eval_code("member()") #=> Exported `member` of the ESM is called
# import { member, defaultMember } from './exports.esm.js';
vm.import(['member', 'defaultMember'], from: File.read('exports.esm.js'))
# import DefaultExport from './exports.esm.js';
vm.import('DefaultExport', from: File.read('exports.esm.js'))
# import * as all from './exports.esm.js';
vm.import('* as all', from: File.read('exports.esm.js'))
Quickjs::VM#define_function: 💎 Define a global function for JS by Ruby
vm = Quickjs::VM.new
vm.define_function("greetingTo") do |arg1|
['Hello!', arg1].join(' ')
end
vm.eval_code("greetingTo('Rick')") #=> 'Hello! Rick'
A Ruby exception raised inside the block is catchable in JS as an Error, and propagates back to Ruby as the original exception type if uncaught in JS.
vm.define_function("fail") { raise IOError, "something went wrong" }
vm.eval_code('try { fail() } catch (e) { e.message }') #=> "something went wrong"
vm.eval_code("fail()") #=> raise IOError transparently
With POLYFILL_FILE enabled, a Ruby ::File returned from the block becomes a JS File-compatible proxy. Passing it back to Ruby from JS returns the original ::File object.
vm = Quickjs::VM.new(features: [::Quickjs::POLYFILL_FILE])
vm.define_function(:get_file) { File.open('report.pdf') }
vm.eval_code("get_file().name") #=> "report.pdf"
vm.eval_code("get_file().size") #=> Integer (byte size)
vm.eval_code("await get_file().text()") #=> file content as String
Quickjs::VM#on_log: 📡 Handle console logs in real time
Register a block to be called for each console.(log|info|debug|warn|error) call.
vm = Quickjs::VM.new
vm.on_log { |log| puts "#{log.severity}: #{log.to_s}" }
vm.eval_code('console.log("hello", 42)')
# => prints: info: hello 42
# log.severity #=> :info / :verbose / :warning / :error
# log.to_s #=> space-joined string of all arguments
# log.raw #=> Array of raw Ruby values
Value Conversion
| JavaScript | | Ruby | Note |
|---|:---:|---|---|
| number (integer / float) | ↔ | Integer / Float | |
| string | ↔ | String | |
| true / false | ↔ | true / false | |
| null | ↔ | nil | |
| Array | ↔ | Array | via JSON |
| Object | ↔ | Hash | via JSON |
| undefined | → | Quickjs::Value::UNDEFINED | |
| NaN | → | Quickjs::Value::NAN | |
| Blob | → | Quickjs::Blob — .size, .type, .content | requires POLYFILL_FILE |
| File | → | Quickjs::File — .name, .last_modified + Blob attrs | requires POLYFILL_FILE |
| File proxy | ← | ::File | requires POLYFILL_FILE; applies to define_function return values |
License
ext/quickjsrb/quickjsext/quickjsrb/vendor/polyfill-intl-en.min.js(bundled and minified frompolyfills/)- MIT License Copyright (c) 2023 FormatJS
- MIT License Copyright (c) 2025 Michael Mclaughlin
Otherwise, the MIT License, Copyright 2024 by Kengo Hamasaki.
Related Skills
node-connect
351.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
110.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
351.8kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
351.8kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
