scriptc : compiler TypeScript en exécutables natifs sans moteur JavaScript
Compilateur TypeScript vers natif. Pas d'annotations, pas de dialecte, le même TypeScript que vous exécutez sur Node, vérifié par le véritable compilateur TypeScript et compilé en natif.
En bref
- De quoi s’agit-il ?
- Un aperçu basé sur les sources de vercel-labs/scriptc, ses trois niveaux de compilation, ses mécanismes de correction, ses chiffres de performance et son flux de développement.
- À qui s’adresse-t-il ?
- scriptc est un projet actif avec 2 891 étoiles et 66 forks. Le README documente ses tests et son cache de construction mais ne divulgue pas les utilisateurs en production, les audits de sécurité ou les environnements de référence autres que les mesures Apple M-series décrites.
- Puis-je l’utiliser commercialement ?
- Oui. Apache-2.0 est une licence permissive : vous pouvez utiliser, modifier et vendre un logiciel qui en dépend, à condition de conserver les mentions de droit d’auteur et de licence.
- Est-il encore maintenu ?
- Oui. Les derniers commits datent d’il y a 1 jour.
- En quel langage est-il écrit ?
- Principalement TypeScript, d’après les statistiques de langage de GitHub.
Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 14 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.
ANALYSE OPEN SOURCE APPROFONDIE
TypeScript zéro runtime
scriptc compile TypeScript en exécutables natifs sans Node.js, V8 ni aucun moteur JavaScript dans le binaire. Le README montre une fonction de Fibonacci qui s'exécute via `scriptc run fib.ts` et produit un binaire autonome d'environ 178 Ko avec un démarrage d'environ 2 ms. L'installation se fait avec `npm install -g scriptc` ; clang (préinstallé avec les outils de ligne de commande Xcode) est requis. macOS arm64 est la plateforme principale, tandis que les binaires Linux et Windows sont construits par compilation croisée et vérifiés par des voies de tests différentiels séparées.
Mesurer ce qui peut être compilé
scriptc analyse un programme constructeur par constructeur pour décider ce qui peut être compilé en code natif. La commande `coverage` rapporte les instructions analysées, combien sont compilées statiquement, et les bloqueurs avec des codes d'erreur comme SC1090 et SC2020. Le README décrit trois niveaux explicites : code compilé statiquement (natif, sans moteur), code exécuté dynamiquement via le drapeau `--dynamic` avec un moteur quickjs-ng intégré (environ 620 Ko), et code rejeté avec une erreur spécifique et généralement un indice de réécriture. Rien n'est mal compilé silencieusement.
La surface statique
Le niveau statique couvre les fonctionnalités du langage et de la bibliothèque standard que les programmes réels utilisent : classes avec héritage simple et dispatch dynamique, fermetures, génériques (monomorphisés), unions discriminées, async/await sur fibres à pile complète, exceptions, déstructuration, spread, getters/setters, itérateurs, littéraux de gabarit et expressions régulières. La bibliothèque standard inclut des chaînes UTF-16 exactes, des tableaux/Map/Set avec ordre JS exact, JSON avec conversions validées à l'exécution, Math, tableaux typés et Buffer, et hiérarchies d'erreurs. La couverture de l'API Node inclut fs, path, process, child_process, os, crypto, url, zlib, minuteurs et la pile serveur (net, http, https, tls, dgram, dns, fs.watch, readline). `fetch` et le sous-ensemble web WHATWG fonctionnent sur la même pile net/TLS native. Avec `--dynamic`, les dépendances npm sont résolues avec l'algorithme de Node, vérifiées par rapport à leurs .d.ts et leur JS est intégré au binaire au moment de la construction.
Mécanismes de correction
Chaque modification exécute deux mécanismes de contrôle. Les tests différentiels exécutent chaque programme du corpus (plus de 800 tests) sous Node et en binaire natif, exigeant que stdout, stderr et codes de sortie correspondent octet pour octet. Le formatage des nombres est exact JS, vérifié par fuzzing contre Node sur un million de doubles. Les serveurs sont testés avec des pilotes clients en direct contre les deux implémentations. Une voie de sécurité mémoire réexécute le corpus sous AddressSanitizer avec un audit de comptage de références ; les fuites et use-after-free sont des échecs de construction. Les quelques dizaines de divergences délibérées avec Node, principalement autour des internals de synchronisation et des propriétés d'objets d'erreur, sont documentées et numérotées.
Chiffres de performance et cache de construction
Mesuré sur Apple M-series contre Node, Go, Rust et Zig (sortie octet identique), scriptc montre un démarrage d'environ 2,4 ms (Node environ 47 ms), une taille de binaire statique de 170-200 Ko (ou environ 3 Mo avec --dynamic et dépendances intégrées), et une RSS mémoire typique de 1 à 4 Mo (Node 67-116 Mo). Les performances d'exécution sont décrites comme compétitives avec les langages système sur la plupart des charges de travail, avec l'inférence d'entiers et l'analyse de possession sur la feuille de route. Les constructions utilisent un cache adressé par contenu qui restaure les exécutables ou bibliothèques inchangés après des sondes légères de chaîne d'outils. Les identités de cache incluent les octets d'en-tête système résolus, les identités de linker/assembleur et les entrées de lien implicites exactes. Chaque artefact mis en cache est vérifié par somme de contrôle. `SCRIPTC_NO_CACHE=1` désactive le cache, et `SCRIPTC_CACHE_DIR` choisit la racine du cache.
Échappatoires
scriptc fournit quatre échappatoires. `comptime(() => ...)` exécute TypeScript au moment de la construction dans une VM isolée et intègre le résultat comme littéral dans le binaire. FFI natif (`--ffi`) lie des déclarations TypeScript uniquement de signature à des appels directs ABI C et lie des archives, objets et bibliothèques système déclarés dans le manifeste. Le drapeau `--dynamic` intègre le moteur pour les dépendances npm et le code `any` ; `coverage --dynamic` rapporte exactement quelles instructions s'exécutent où. Les conversions vérifiées font que `JSON.parse(...) as Config` insère une validation à l'exécution qui lance une erreur attrapable nommant le chemin fautif.
Architecture et développement
Le pipeline est TypeScript → analyse/typecheck tsc → abaissement en IR typé → code C → clang → exécutable natif. Le paquet compilateur gère le frontend, l'IR et les backends ; le paquet runtime est un runtime C avec des valeurs à comptage de références, des fibres à pile complète et une boucle d'événements ; la CLI fournit `build`, `run` et `coverage`. Le développement utilise pnpm : `pnpm install && pnpm build`, puis `pnpm test` pour le corpus différentiel et les instantanés de diagnostic, ou `SCRIPTC_SAN=1 pnpm test` pour l'audit ASan + RC. Les tests sandbox s'exécutent sur Vercel Sandboxes, avec une porte Pro+ rapide et une porte Hobby avec parallélisme réduit. Chaque fonctionnalité est livrée avec des tests différentiels ; les deux voies vertes sont la barre de fusion. Le projet est sous licence Apache-2.0 ; la licence accorde des licences de droit d'auteur et de brevet perpétuelles, mondiales, non exclusives, gratuites et sans redevance, mais le README ne spécifie pas de garantie ou de conditions de support.
Conclusion éditoriale
scriptc est un projet actif avec 2 891 étoiles et 66 forks. Le README documente ses tests et son cache de construction mais ne divulgue pas les utilisateurs en production, les audits de sécurité ou les environnements de référence autres que les mesures Apple M-series décrites.
Notes de la communauté