V bindings to QuickJS javascript engine. Run JS in V.
- Evaluate js (code, file, module, etc).
- Multi evaluate support.
- Callback function support.
- Set-Globals support.
- Set-Module support.
- Call V from JS.
- Call JS from V.
- Top-Level
awaitsupport. usingvjsx.type_module.
v install vjsxIf you already have a local QuickJS checkout, you can compile vjsx against the
source tree directly instead of the bundled prebuilt archives.
This is useful when:
- you are on an unsupported architecture such as
macOS arm64 - you want to use a newer QuickJS version
- you do not want to maintain extra prebuilt
.afiles inside this repo
Example:
VJS_QUICKJS_PATH=/Users/guweigang/Source/quickjs \
v -d build_quickjs run main.vNotes:
VJS_QUICKJS_PATHshould point to the QuickJS source root that containsquickjs.c,quickjs-libc.c,quickjs.h, andquickjs-libc.h.- In this mode
vjsxcompiles QuickJS C sources directly. - Without
-d build_quickjs,vjsxuses the bundled headers underlibs/include/together with the prebuilt archives inlibs/.
Create file main.v and copy-paste this code.
import vjsx
fn main() {
rt := vjsx.new_runtime()
ctx := rt.new_context()
value := ctx.eval('1 + 2') or { panic(err) }
ctx.end()
assert value.is_number() == true
assert value.is_string() == false
assert value.to_int() == 3
println(value)
// 3
// free
value.free()
ctx.free()
rt.free()
}v run main.vWith a local QuickJS checkout:
VJS_QUICKJS_PATH=/Users/guweigang/Source/quickjs \
v -d build_quickjs run main.vExplore examples
If you want the smallest file-based example, see
examples/run_file.v together with examples/js/foo.js.
You can also run JS files directly from the repository:
./vjsx ./tests/test.jsModule mode:
./vjsx --module ./examples/js/main.jsTypeScript entry files are also supported:
./vjsx ./tests/ts_basic.ts
./vjsx --module ./tests/ts_module_runtime.mtsTypeScript module graphs are also supported, including:
- relative
.ts/.mtsimports - nearest
tsconfig.json, includingextends compilerOptions.baseUrlandpaths- bare package imports resolved from local
node_modules - package
exportsroot and explicit subpath entries
Options:
--module,-m: run the file as an ES module
This is runtime transpilation backed by the bundled typescript.js, and the
same loader is now also available from the vjsx API through
ctx.install_typescript_runtime() and ctx.run_runtime_entry(...).
It is a good fit for standalone .ts scripts, .mts modules, and small local
module graphs. Project-wide features like full tsc diagnostics, references,
and broader Node compatibility are still out of scope for now.
The wrapper script will use VJS_QUICKJS_PATH when it is set. If it is not
set, it will try ../quickjs relative to the repository root as a local
convenience fallback.
Currently support linux/mac/win (x64).
in windows, requires
-cc gcc.
The runtime is now split into clearer layers:
ctx.install_runtime_globals(...): reusable globals likeBuffer, timers,URL, andURLPatternctx.install_node_compat(...): Node-like host features such asconsole,fs,path, andprocessweb.inject_browser_host(ctx, ...): browser-style host features underweb/, includingwindow, DOM bootstrap, and Web APIs
web.inject_browser_host(...) is now configurable, so you can expose only the
browser-facing modules you want, while still letting higher-level features like
fetch pull in their required Web API dependencies.
The legacy ctx.install_host(...) entrypoint still works as a compatibility
wrapper around install_node_compat(...).
Useful presets:
vjsx.runtime_globals_full()vjsx.runtime_globals_minimal()vjsx.node_compat_full(fs_roots, process_args)vjsx.node_compat_minimal(fs_roots, process_args)web.browser_host_full()web.browser_host_minimal()
Higher-level runtime entrypoints:
ctx.install_script_runtime(...)ctx.install_node_runtime(...)web.inject_browser_runtime(ctx)web.inject_browser_runtime_minimal(ctx)
CLI runtime profiles:
./vjsx --runtime node ..../vjsx --runtime script ..../vjsx --runtime browser --module ...
The CLI defaults to --runtime node for backwards compatibility.
browser is intentionally a pure browser-style host profile and currently
requires --module. The current CLI browser profile exposes browser-like
globals such as window, self, EventTarget, URL, timers, streams,
Blob, and FormData, while intentionally leaving out Node globals like
process, Buffer, and modules such as fs.
Example:
import vjsx
import herudi.vjsx.web
fn main() {
rt := vjsx.new_runtime()
ctx := rt.new_context()
ctx.install_script_runtime(
process_args: ['inline.js']
)
web.inject_browser_runtime_minimal(ctx)
}ctx.eval('const sum = (a, b) => a + b') or { panic(err) }
ctx.eval('const mul = (a, b) => a * b') or { panic(err) }
sum := ctx.eval('sum(${1}, ${2})') or { panic(err) }
mul := ctx.eval('mul(${1}, ${2})') or { panic(err) }
ctx.end()
println(sum)
// 3
println(mul)
// 2glob := ctx.js_global()
glob.set('foo', 'bar')
value := ctx.eval('foo') or { panic(err) }
ctx.end()
println(value)
// barmut mod := ctx.js_module('my-module')
mod.export('foo', 'foo')
mod.export('bar', 'bar')
mod.export_default(mod.to_object())
mod.create()
code := '
import mod, { foo, bar } from "my-module";
console.log(foo, bar);
console.log(mod);
'
ctx.eval(code, vjsx.type_module) or { panic(err) }
ctx.end()Inject Web API to vjsx.
import vjsx
import herudi.vjsx.web
fn main() {
rt := vjsx.new_runtime()
ctx := rt.new_context()
// inject all browser host features
web.inject_browser_host(ctx)
// or inject one by one
// web.console_api(ctx)
// web.encoding_api(ctx)
// more..
...
}- Console
- setTimeout, clearTimeout
- setInterval, clearInterval
- btoa, atob
- URL
- URLSearchParams
- URLPattern
- Encoding API
- Crypto API
- SubtleCrypto
- digest
- encrypt
- decrypt
- sign
- verify
- Streams API
- Event
- FormData
- Blob
- File
- Performance
- Navigator
- Fetch API
- More...