SkillAgentSearch skills...

Quickjs.rb

A CRuby wrapper to run QuickJS in Ruby

Install / Use

/learn @hmsk/Quickjs.rb
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

quickjs.rb

A Ruby wrapper for QuickJS to run JavaScript codes via Ruby with a smaller footprint.

Gem Version GitHub Actions Workflow Status

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 |

</details>

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

Otherwise, the MIT License, Copyright 2024 by Kengo Hamasaki.

Related Skills

View on GitHub
GitHub Stars38
CategoryDevelopment
Updated1d ago
Forks1

Languages

Ruby

Security Score

95/100

Audited on Apr 7, 2026

No findings