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("const isOne = (n) => 1 === n; func(1);") #=> true (TrueClass)
Quickjs.eval_code("const isOne = (n) => 1 === n; func(3);") #=> false (FalseClass)
# When code returns 'object' for `typeof`, the result is converted via JSON.stringify (JS) -> JSON.parse (Ruby)
Quickjs.eval_code("[1,2,3]") #=> [1, 2, 3] (Array)
Quickjs.eval_code("({ a: '1', b: 1 })") #=> { 'a' => '1', 'b' => 1 } (Hash)
Quickjs.eval_code("null") #=> nil
Quickjs.eval_code('const obj = {}; obj.missingKey;') # => :undefined (Quickjs::Value::Undefined)
Quickjs.eval_code("Number('whatever')") #=> :NaN (Quickjs::Value::NAN)
Resources
# 1GB memory limit
Quickjs.eval_code(code, { memory_limit: 1024 ** 3 })
# 1MB max stack size
Quickjs.eval_code(code, { max_stack_size: 1024 ** 2 })
Built-in modules
To enable std module and os module selectively.
# enable std module
Quickjs.eval_code(code, { features: [Quickjs::MODULE_STD] })
# enable os module
Quickjs.eval_code(code, { features: [Quickjs::MODULE_OS] })
# enable timeout features `setTimeout`, `clearTimeout` from os module specifically
Quickjs.eval_code(code, { features: [Quickjs::FEATURES_TIMEOUT] })
Quickjs::VM
: Maintain a consistent VM/runtime
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"
Resources
vm = Quickjs::VM.new(
memory_limit: 1024 ** 3,
max_stack_size: 1024 ** 2,
)
Built-in modules
To enable std module and os module selectively.
# enable std module
vm = Quickjs::VM.new(features: [::Quickjs::MODULE_STD])
# enable os module
vm = Quickjs::VM.new(features: [::Quickjs::MODULE_OS])
# enable timeout features `setTimeout`, `clearTimeout`
vm = Quickjs::VM.new(features: [::Quickjs::FEATURES_TIMEOUT])
VM timeout
# `eval_code` will be interrupted after 1 sec (default: 100 msec)
vm = Quickjs::VM.new(timeout_msec: 1_000)
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'
Quickjs::VM#logs
: 💾 Capture console logs
All logs by console.(log|info|debug|warn|error)
on VM are recorded and inspectable.
vm = Quickjs::VM.new
vm.eval_code('console.log("log me", null)')
vm.logs #=> Array of Quickjs::VM::Log
vm.logs.last.severity #=> :info
vm.logs.last.to_s #=> 'log me null'
vm,logs.last.raw #=> ['log me', nil]
License
Every file in ext/quickjsrb/quickjs
is licensed under the MIT License Copyright 2017-2021 by Fabrice Bellard and Charlie Goron.
For otherwise, the MIT License, Copyright 2024 by Kengo Hamasaki.