Skip to content

Releases: OdinoCano/3va

v2.0.3

15 Jun 21:30

Choose a tag to compare

Full Changelog: v2.0.2...v2.0.3

Full Changelog: v2.0.2...v2.0.3

v2.0.2

15 Jun 14:19

Choose a tag to compare

Full Changelog: v2.0.0...v2.0.2

v2.0.0

11 Jun 05:35

Choose a tag to compare

Full Changelog: v1.0.0...v2.0.0

Full Changelog: v1.0.0...v2.0.0

Full Changelog: v1.0.0...v2.0.0

Full Changelog: v1.0.0...v2.0.0

Full Changelog: v1.0.0...v2.0.0

Full Changelog: v1.0.0...v2.0.0

Full Changelog: v2.0.1...v2.0.0

Full Changelog: v2.0.1...v2.0.0

Full Changelog: v2.0.1...v2.0.0

v2.0.1

15 Jun 21:29

Choose a tag to compare

Full Changelog: v1.0.0...v2.0.1

3va 1.0.0

04 Jun 19:59

Choose a tag to compare

[1.0.0] — 2026-06-04

Added

  • CDP Inspector (--inspect) — WebSocket Chrome DevTools Protocol server. debugger; statements are rewritten to __3va_debugger__() at source-load time. Pause is implemented via tokio::task::block_in_place + Condvar so the Tokio runtime remains responsive. Connect with chrome://inspect or any DAP-compatible IDE.
  • NAPI native module loading (--allow-ffi) — ~30 NAPI v8 functions exposed as unsafe extern "C". .node addons loaded via the standard require('./addon.node') path. Requires --allow-ffi permission.
  • WebAssembly (WASM) — WASI-preview1-compatible runtime via wasmtime. Supports .wasm and .wat files. Full permission integration (filesystem preopens, env vars scoped to granted capabilities).
  • Post-quantum TLS (__pqTlsConnect) — hybrid classical TLS + ML-KEM-768 key exchange. Returns { connId, pqSharedSecret }. Non-blocking: runs inside spawn_blocking. Requires --allow-net.
  • Post-quantum crypto JS APIrequire('crypto').pq.kem.{generateKeypair,encapsulate,decapsulate} (ML-KEM-768) and require('crypto').pq.dsa.{generateKeypair,sign,verify} (ML-DSA-65).
  • Fuzz targets in CI — 3 fuzz targets built on nightly; 30 s smoke run in GitHub Actions.
  • Doc-tests — public API surfaces of vvva_core, vvva_permissions, vvva_crypto, and vvva_js now have doc-tests.
  • SECURITY.md — explicit acceptance rationale for RUSTSEC-2023-0071 (Marvin Attack); documents "before 1.0" review requirement.
  • Process manager subcommandsstart, stop, restart, status, logs, delete for running scripts as managed background daemons.

Fixed

  • __pqTlsConnect was synchronous on the JS event loop (blocked all timers and I/O during TLS handshake). Now runs inside spawn_blocking and is registered as Async.
  • SemverRange silently rejected "latest", "1.x", ">=1.0.0 <2.0.0" forms — added dist-tag, x-range, and compound-range support.
  • Dependency resolver produced non-deterministic lockfiles (HashMap iteration order). Resolution stack is now sorted alphabetically.
  • Version conflict in the resolver was silent — now emits a structured tracing::warn!.
  • Content-Length header forwarded to JS did not reflect the 100 MiB internal cap.

Changed

  • rquickjs-core 0.6.2 vendored at vendor/rquickjs-core/ with a one-line fix for the never type fallback future-incompatibility lint (Rust Edition 2024).
  • All crate versions bumped to 1.0.0.

Added

  • Expo / React Native package support (crates/js/src/builtins/modules.rs, crates/js/src/transpiler.rs):
    Real Expo npm packages (expo-modules-core, expo-constants, expo-asset, expo-font, expo-file-system) load and execute without errors. 45/45 tests pass in test-projects/expo-test/.

    ESM→CJS converter fixes:

    • Circular dependency guardmodule.exports pre-cached before eval; circular requires get the partial exports object instead of re-executing the module (matches Node.js behavior, eliminates stack overflows).
    • export default X chained assignment — was setting .default on the OLD module.exports object due to JS LHS-ref evaluation order. Now uses two statements: module.exports = X + deferred module.exports.default = module.exports.
    • Destructuring exportsexport const { a, b } = X and export const [a, b] = X now correctly emit individual module.exports.a = a entries.
    • Uninitialised var exportexport var X; is now deferred so TypeScript enum IIFEs can fill the value before module.exports.X is set.
    • Empty export markerexport {} (OXC emits this to tag a file as ESM) is now a no-op; previously surfaced as "unsupported keyword: export".
    • Dynamic import() — inline import(specifier) expressions are rewritten to __importAsync(specifier) which wraps synchronous require() in a resolved Promise.
    • Deferred exports — all deferred assignments wrapped in try{}catch{} to tolerate read-only properties defined by Object.defineProperty.

    Platform-aware extension resolution:

    • resolve_file_path probes .web.js, .web.tsx, .web.ts, .web.mjs before the generic .js, .tsx, .ts variants. Expo .web.* files are the correct choice in a server/CLI context (they avoid native bridge imports).
    • Index file probing follows the same order (index.web.ts before index.ts).

    TypeScript transpiler:

    • SemanticBuilder::with_enum_eval(true) added — prevents OXC panic when transforming TypeScript const enum declarations.

    New React Native / Expo polyfills:

    • react-native pre-cached in __requireCache with Platform, NativeModules, TurboModuleRegistry, PixelRatio, Dimensions, StyleSheet, Animated, and all major component stubs.
    • @react-native/assets-registry pre-cached with registerAsset / getAssetByID.
    • NativeModules proxy changed to return undefined for unregistered module names (previously returned a truthy function-proxy, causing JSON.parse(function(){}) errors in expo-constants).
    • expo-modules-core polyfill extended with NativeModule, SharedObject, SharedRef (extendable base classes), registerWebModule, Platform, uuid.
    • requireOptionalNativeModule returns null — correct for a web/server environment where optional native modules are absent.
    • process.env.EXPO_OS = 'web' — Expo packages branch on this to select server-safe code paths.
  • CPU sampling profiler (--prof) (crates/js/src/profiler.rs):

    • 3va run app.ts --prof — collects samples every --prof-interval ms (default 10) via setInterval + new Error().stack; writes V8-compatible .cpuprofile JSON.
    • --flamegraph=<path> — also emits an Inferno-style SVG flamegraph using the inferno crate.
    • 3va prof <file> subcommand — post-hoc analysis: prints top-N hot functions by self% or re-generates a flamegraph from an existing .cpuprofile.
    • console.profile(label) / console.profileEnd(label) — JS-side region markers, active when --prof is passed.
    • JsEngine::new_with_profiler(perms, interval_ms) / JsEngine::take_profiler() — public Rust API.
    • 7 unit tests: stack parser, location parser, folded-stacks aggregation, .cpuprofile JSON validity, analyze_cpuprofile, JS bootstrap interval embedding.
  • Buffer como subclase real de Uint8Array (builtins/buffer.rs):
    Reescrito usando el patrón prototype swap: el constructor devuelve un Uint8Array real con Buffer.prototype en su cadena. Esto garantiza:

    • buf instanceof Uint8Arraytrue
    • buf[0] → valor de byte correcto (proxy nativo de TypedArray)
    • [...buf] spread, buf.set(), Array.from(buf) — todos funcionan como nativos
    • DataView, Float32Array y otras vistas sobre buf.buffer funcionan sin conversión
    • Compatibles con ws, msgpackr, protobufjs y cualquier librería que accede a bytes directamente
      Todos los métodos (readUInt32BE, writeFloatLE, BigUInt64, slice, subarray, etc.) actualizados para operar sobre this directamente.
  • crypto.createSign/createVerify — RSA PKCS1v15 y ECDSA reales (builtins/crypto.rs):
    Implementación nativa vía crates Rust. Soporta:

    • RSA PKCS#1 v1.5: algoritmos RSA-SHA256, RSA-SHA384, RSA-SHA512, SHA256, SHA1
    • ECDSA P-256: SHA256 con clave P-256
    • ECDSA P-384: SHA384 con clave P-384
    • Salida en formato DER (compatible con jsonwebtoken, passport-jwt, jose)
    • Acepta DER y P1363 (raw r‖s) en verificación
    const sig = crypto.createSign('RSA-SHA256').update(data).sign(privateKey);
    crypto.createVerify('RSA-SHA256').update(data).verify(publicKey, sig); // → true
  • crypto.createPrivateKey/createPublicKey/createSecretKey (builtins/crypto.rs):
    Importa claves PEM existentes en objetos KeyObject compatibles con Node.js.

    • .type'private', 'public', o 'secret'
    • .asymmetricKeyType'rsa' o 'ec'
    • .export() → PEM string o Uint8Array (con format: 'der')
      Desbloquea: jsonwebtoken con claves externas, passport-jwt, @panva/jose.
  • crypto.sign/crypto.verify (one-shot, Node.js 15+) (builtins/crypto.rs):

    const sig = crypto.sign('SHA256', data, privateKey);
    crypto.verify('SHA256', data, publicKey, sig); // → boolean
  • crypto.createHash('md5') (builtins/crypto.rs):
    MD5 ahora soportado vía crate md-5 0.10 (algoritmo RustCrypto). Para fingerprinting de contenido,
    ETags, compatibilidad legacy. No recomendado para seguridad.

  • crypto.getCiphers()/getHashes()/getCurves() (builtins/crypto.rs):
    Nuevas funciones de enumeración que devuelven los algoritmos soportados.

  • crypto.generateKeyPair / generateKeyPairSync — RSA y EC nativos (builtins/crypto.rs):
    Generación de pares de claves asimétricas vía Rust (rsa 0.9, p256 0.13, p384 0.13).

    • crypto.generateKeyPairSync('rsa', { modulusLength: 2048 }){ publicKey, privateKey } con .export() que devuelve PEM PKCS#8/SPKI.
    • crypto.generateKeyPair('rsa', opts, callback) — versión async con spawn_blocking.
    • Curvas EC soportadas: P-256 (prime256v1), P-384 (secp384r1).
    • Claves RSA-PSS: misma implementación que RSA estándar.
      Desbloquea: JWT RS256/ES256/ES384 con jsonwebtoken, passport-jwt, node-jose.
  • crypto.webcrypto (builtins/crypto.rs):
    Añadido crypto.webcrypto = { subtle } como alias al crypto.subtle existente.
    Requerido por Hono, edge runtimes, y cualquier código que accede a WebCrypto vía require('crypto').webcrypto.

  • crypto.scryptSync — implementación real con scrypt (builtins/crypto.rs):
    Sustituye la aproximación anterior (PBKDF2 como fallback) por __cryptoScryptSync, que llama
    directamente a la implementación nativa scrypt::scrypt. N...

Read more