qjsqjscqjscalcstdosqjscQuickJS est un petit moteur JavaScript intégré qui prend en charge les spécifications ES2020, y compris les modules, les générateurs asynchrones et la procuration.
Il prend en charge éventuellement des extensions mathématiques telles que les grands entiers (Bigint), les grands numéros de points flottants (bigfloat) et la surcharge de l'opérateur.
Site officiel: https://bellard.org/quickjs/
Site chinois: https://github.com/quickjs-zh/
QuickJS QQ Groupe 1: 598609506 .
Wiki chinois: https://github.com/quickjs-zh/quickjs/wiki
Cliquez pour afficher le contenu spécifique du test de référence QuickJS
Fournit des makefiles qui peuvent être compilés sur Linux ou MacOS / X. La prise en charge préliminaire de Windows peut être obtenue par compilation croisée sur les hôtes Linux à l'aide de l'outil MINGW.
Si vous souhaitez sélectionner une option spécifique, modifiez le haut de Makefile et make .
Exécutez make install à l'aide de la racine pour installer des fichiers binaires et de prise en charge compilés sur /usr/local (cela n'est pas nécessaire pour utiliser QuickJS).
Remarque : Vous pouvez vous référer à la documentation chinoise QuickJS sur la compilation et l'installation sous Windows et la compilation et l'installation sous Linux.
qjs est un analyseur de ligne de commande (boucle de lecture-Eval).
./qjs examples/hello.js
qjsc est un compilateur de ligne de commande:
./qjsc -o hello examples/hello.js
./hello
Générez un fichier exécutable hello sans dépendances externes.
qjsbn et qjscbn sont les interprètes et compilateurs correspondants avec des extensions mathématiques:
./qjsbn examples/pi.js 1000
Afficher 1000 chiffres de Pi
./qjsbnc -o pi examples/pi.js
./pi 1000
Compiler et exécuter le programme PI.
qjsUtilisation: QJS [Options] [Fichiers]
Options:
-h
--help
Liste des options.
-e `EXPR`
--eval `EXPR`
Effectuer Expr.
-i
--interactive
Passez en mode interactif (ce n'est pas le mode par défaut lorsque le fichier est servi sur la ligne de commande).
-m
--module
Chargez le module ES6 (l'extension de fichier par défaut est .mjs).
Les options avancées incluent:
-d
--dump
Transférer les statistiques d'utilisation de la mémoire.
-q
--quit
Instanciez simplement l'interprète et la sortie.
qjscUtilisation: QJSC [Options] [Fichiers]
Options:
-c
Seul le code bytecode dans le fichier C est sorti et la valeur par défaut est de sortir le fichier exécutable.
-e
main() la sortie et le code bytecode Dans le fichier C, la valeur par défaut est le fichier exécutable de sortie.
-o output
Définissez le nom du fichier de sortie (default = out.c ou a.out).
-N cname
Définit le nom C des données générées.
-m
Compilez en tant que module JavaScript (par défaut est l'extension .mjs).
-M module_name[,cname]
Ajoutez le code d'initialisation pour les modules C externes. Consultez c_module .
-x
Outpilation d'échange d'octets (pour la compilation croisée uniquement).
-flto
Utilisez l'optimisation du temps de lien. La compilation est plus lente, mais les exécutables sont plus petits et plus rapides. Cette option est automatiquement définie lors de l'utilisation de l'option -fno-x .
-fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise]
Désactivez la fonction de langue sélectionnée pour générer des fichiers exécutables plus petits.
qjscalc L'application qjscalc est un superset de l'interprète de ligne de commande qjsbn qui implémente une calculatrice JavaScript avec des entiers arbitraires de grands entiers et des nombres de points flottants, des fractions, des nombres complexes, des polynômes et des matrices. Le code source est dans QJSCALC.JS. Plus de documents et versions Web sont disponibles sur http://numcalc.com.
Exécutez make test pour exécuter certains tests intégrés inclus dans l'archive QuickJS.
L'archive QuickJS contient le programme Test262 Runner.
Pour référence, le test complet de test262 est fourni dans l'archive QJS-Tests-yyyy-mm-dd.tar.xz. Il vous suffit de le décompresser dans le répertoire source QuickJS.
Alternativement, le test Test262 peut être installé:
git clone https://github.com/tc39/test262.git test262
cd test262
git checkout 94b1e80ab3440413df916cd56d29c5a2fa2ac451
patch -p1 < ../tests/test262.patch
cd ..
Le patch ajoute des fonctions harness spécifiques à l'implémentation et optimise les classes de caractères regexp inefficaces et les tests d'échappement d'attribut UNICODE (le test lui-même ne sera pas modifié, seule la fonction d'initialisation de chaîne lente est optimisée).
Le test peut fonctionner
make test2
Pour plus d'informations, exécutez ./run-test262 pour voir les options pour Test262 Runner. Le fichier de configuration test262.conf et test262bn.conf contiennent des options pour exécuter divers tests.
La spécification ES2019 2, qui comprend l'annexe B (compatibilité Web héritée) et les fonctionnalités liées à l'Unicode, est déjà essentiellement prise en charge. Les fonctionnalités suivantes ne sont pas encore prises en charge:
Les analyseurs JSON sont actuellement pris en charge par une plage plus large que la spécification.
ECMA402 (API international) n'est pas encore soutenue.
"use strip" ne conserve pas les informations de débogage (y compris le code source de fonction) pour enregistrer la mémoire. La directive "use strict" peut appliquer des scripts globaux ou des fonctions spécifiques.#! Au début du script sera ignorée. Les extensions de mathématiques sont disponibles dans la version qjsbn et sont entièrement compatibles avec jsbignum.pdf standard.
BigInt (grand entier) TC39 est déjà pris en charge.BigFloat Prise en charge: tout grand numéro de point flottant dans Cardinalité 2."use bigint" permet au mode BigInt, et BigInt est un entier par défaut."use math" permet le mode mathématique où les opérateurs de division et d'électricité sur des entiers produisent des fractions. Par défaut, les littéraux de points flottants sont la valeur par défaut et les entiers sont la valeur par défaut de BigInt.Le module ES6 prend en charge entièrement. Les règles de résolution des noms par défaut sont les suivantes:
. ou .. est le chemin par rapport au module actuel... n'a pas os std ..so et est un module natif en utilisant l'API QuickJS C. Par défaut, la bibliothèque standard est incluse dans l'interprète de ligne de commande. Il contient deux modules std et os et certains objets globaux.
scriptArgs
Fournissez des paramètres de ligne de commande. Le premier paramètre est le nom du script.
print(...args)
Imprime les paramètres séparés par des espaces et les nouvelles lignes de fin.
console.log(...args)
Identique à print ().
std Le module std fournit des emballages pour libc stdlib.h et stdio.h et certains autres services publics.
Exportation disponible:
exit(n)
Quittez le processus.
evalScript(str)
Exécutez la chaîne str Scripted (Global EVAL).
loadScript(filename)
Exécutez le script filename (Global EVAL).
Error(errno)
Constructeur std.Error . L'instance d'erreur contient les champs errno (code d'erreur) et message (résultat de std.Error.strerror(errno) ).
Le constructeur contient les champs suivants:
EINVAL
EIO
EACCES
EEXIST
ENOSPC
ENOSYS
EBUSY
ENOENT
EPERM
EPIPE
Les valeurs entières généralement mauvaises (les codes d'erreur supplémentaires peuvent être définis).
strerror(errno)
Renvoie la chaîne errno qui décrit l'erreur.
open(filename, flags)
Ouvrez un fichier (Wrapper de LiBC fopen() ). Jetez std.Error dans l'erreur d'E / S
tmpfile()
Ouvrez un fichier temporaire. Jetez std.Error dans l'erreur d'E / S.
puts(str)
Il est équivalent à std.out.puts(str) .
printf(fmt, ...args)
Équivalent à std.out.printf(fmt, ...args)
sprintf(fmt, ...args)
Équivalent au sprintf de LIBC ().
in
out
err
Enveloppez stdin , stdout , stderr du fichier LIBC.
SEEK_SET
SEEK_CUR
SEEK_END
Constantes de recherche ()
global
Références aux objets globaux.
gc()
Appelez manuellement l'algorithme de suppression de boucle. L'algorithme de suppression de boucle démarre automatiquement en cas de besoin, donc cette fonction est très utile lorsque des limites de mémoire ou des tests spécifiques.
getenv(name)
Renvoie le name de valeur de la variable d'environnement, ou undefined s'il est non défini.
Prototype de fichier:
close()
Fermez le fichier.
puts(str)
Utilisez le codage UTF-8 sur les chaînes de sortie.
printf(fmt, ...args)
Format printf, identique au format libc printf.
flush()
Actualiser le fichier tamponné.
seek(offset, whence)
À la recherche d'un emplacement de fichier spécifique (d'où std.SEEK_* ). Jetez std.Error dans l'erreur d'E / S.
tell()
Retourner à l'emplacement actuel du fichier.
eof()
Renvoie True si le fichier se termine.
fileno()
Renvoie la poignée du système d'exploitation associé.
read(buffer, position, length)
À partir de la position du fichier en position d'octet, lisez l'octet length vers le buffer ArrayBuffer ( fread wrapper de LIBC).
write(buffer, position, length)
Écrivez length dans le buffer ArrayBuffer en commençant par position de la position des octets dans le fichier ( fread Wrapper de LiBC).
getline()
Renvoie la ligne suivante dans le fichier, en supposant que c'est un codage UTF-8, à l'exclusion de la fin des lignes de fin.
getByte()
Renvoie l'octet suivant dans le fichier.
putByte(c)
Écrivez un octet dans le fichier.
os os fournit des fonctions spécifiques au système d'exploitation:
Si OK, la fonction OS renvoie généralement 0, ou le système d'exploitation renvoie un code d'erreur spécifique.
Fonctions d'exportation disponibles:
open(filename, flags, mode = 0o666)
Ouvrez un fichier. En cas d'erreur, renvoyez une poignée ou <0.
O_RDONLY
O_WRONLY
O_RDWR
O_APPEND
O_CREAT
O_EXCL
O_TRUNC
Posix Open Sign.
O_TEXT
(Spécifique à Windows). Ouvrez le fichier en mode texte. La valeur par défaut est le mode binaire.
close(fd)
Fermer la poignée du fichier fd .
seek(fd, offset, whence)
À la recherche de fichiers. Utilisez std.SEEK_* ou whence .
read(fd, buffer, offset, length)
À partir de la poignée de fichier fd avec le offset de position de l'octet, lisez l'octet length dans le buffer ArrayBuffer. Renvoie le nombre d'octets lus, et si une erreur se produit, il renvoie une valeur inférieure à 0.
write(fd, buffer, offset, length)
Écrivez l'octet length dans le buffer ArrayBuffer en commençant par le offset la poignée du fichier fd . Renvoie le nombre d'octets écrits et si une erreur se produit, une valeur inférieure à 0 est renvoyée.
isatty(fd)
fd est une poignée Tty (terminal) qui renvoie true .
ttyGetWinSize(fd)
Renvoie la taille Tty [width, height] ou null si indisponible.
ttySetRaw(fd)
Définissez Tty en mode d'origine.
remove(filename)
Supprimer le fichier. Retour 0 Si normal, retournez <0 si erreur
rename(oldname, newname)
Renommer le fichier. Retour 0 Si normal, retournez <0 si erreur
setReadHandler(fd, func)
Ajoutez le gestionnaire de lecture dans la poignée du fichier fd . fd appelle func à chaque fois qu'il y a des données à ajouter au processus. Prend en charge un seul gestionnaire de lecture pour chaque poignée de fichier. Utilisez func = null pour supprimer la poignée.
setWriteHandler(fd, func)
Ajoutez le gestionnaire d'écriture dans la poignée du fichier fd . fd appelle func chaque fois qu'il y a des données à écrire pour traiter. Utilisez `func = null pour supprimer la poignée.
signal(signal, func)
Appelez func lorsque signal se produit. Un seul gestionnaire est pris en charge par numéro de signal. Utilisez les signaux Ignores traités ou undefined défaut définis par null .
SIGINT
SIGABRT
SIGFPE
SIGILL
SIGSEGV
SIGTERM
Numéro de signal POSIX.
setTimeout(func, delay)
Appelez la fonction func après delay des millisecondes. Renvoie la poignée à la minuterie.
clearTimer(handle)
Annuler la minuterie.
platform
Renvoie la chaîne représentant la plate-forme: "linux" , "darwin" , "win32" ou "js" .
L'API C est simple et efficace. L'API C est définie dans l'en-tête quickjs.h .
JSRuntime représente l'exécution JavaScript correspondant au tas d'objet. Plusieurs temps d'exécution peuvent exister en même temps, mais ils ne peuvent pas échanger des objets. Dans un temps d'exécution donné, le multithreading n'est pas pris en charge.
JSContext représente un contexte JavaScript (ou domaine). Chaque JSContext a ses propres objets globaux et système. Il peut y avoir plusieurs jscontexts dans jsruntime, et ils peuvent partager des objets, similaires aux cadres avec la même source partageant des objets JavaScript dans un navigateur Web.
JSValue représente une valeur JavaScript, qui peut être un type primitif ou un objet. Utilisez des comptes de référence, il est donc important de copier explicitement ( JS_DupValue() , d'augmenter le nombre de références) ou de libérer ( JS_FreeValue() , de diminuer le nombre de références) jsvalues.
Utilisez JS_NewCFunction() pour créer des fonctions C. JS_SetPropertyFunctionList() est un moyen facile d'ajouter facilement les propriétés de fonction, de setter et de Getter à un objet donné.
Contrairement à d'autres moteurs JavaScript intégrés, QuickJS n'a pas de pile implicite, de sorte que la fonction C transmet ses paramètres comme paramètres C normaux. La règle générale est que les fonctions C prennent JSValue comme arguments (afin qu'ils n'aient pas besoin d'être libérés) et renvoient un JSValue nouvellement alloué (actif).
Exception: La plupart des fonctions C peuvent renvoyer une exception JavaScript. Il doit être explicitement testé et traité via le code C. Un JSValue spécifique, c'est-à-dire JS_EXCEPTION , indique qu'une exception s'est produite. L'objet d'exception réel est stocké dans JSContext et peut être récupéré à l'aide de JS_GetException() .
Utilisez JS_Eval() pour évaluer le code source de script ou de module.
Si le script ou le module a été compilé en bytecode à l'aide de qjsc , l'utilisation JS_EvalBinary() peut obtenir le même résultat. L'avantage est qu'il ne nécessite pas de compilation, il est donc plus rapide et plus petit, car si eval n'est pas requis, le compilateur peut être retiré de l'exécutable.
Remarque: Le format bytecode est associé à une version QuickJS spécifique. De plus, aucun contrôle de sécurité n'a été effectué avant l'exécution. Par conséquent, ByteCode ne doit pas être chargé à partir de sources non fiables. C'est pourquoi il n'y a pas d'option dans qjsc pour sortir des bytecode dans des fichiers binaires.
Les données opaques de C peuvent être jointes aux objets JavaScript. Le type de données C Opaque est déterminé par l'ID de classe de l'objet ( JSClassID ). Par conséquent, la première étape consiste à enregistrer un nouvel ID de classe et une classe JS ( JS_NewClassID() , JS_NewClass() ). Vous pouvez ensuite créer un objet de cette classe en utilisant JS_NewObjectClass() et utiliser JS_GetOpaque() / JS_SetOpaque() pour obtenir ou définir un pointeur opaque sur C.
Lorsque vous définissez une nouvelle classe JS, vous pouvez déclarer un destructeur qui est appelé lorsque l'objet est détruit. Une méthode gc_mark peut être fournie afin que l'algorithme de suppression de boucle puisse trouver d'autres objets référencés par l'objet. Il existe d'autres méthodes qui peuvent être utilisées pour définir un comportement d'objet hétérogène.
L'ID de classe est alloué à l'échelle mondiale (c'est-à-dire applicable à tous les temps d'exécution). JSClass est alloué dans chaque JSRuntime . JS_SetClassProto() est utilisé pour définir des prototypes pour une classe donnée dans un JSContext donné. JS_NewObjectClass() définit ce prototype dans l'objet créé.
Des exemples sont fournis dans JS_LIBC.C.
Modules ES6 natifs qui prennent en charge les liens dynamiques ou statiques. Consultez les exemples Test_Bjson et Bjson. La bibliothèque standard JS_LIBC.C est également un bon exemple de modules natifs.
Définissez les limites globales d'allocation de mémoire pour un jsruntime donné en utilisant JS_SetMemoryLimit() .
JS_NewRuntime2() peut fournir des fonctions d'allocation de mémoire personnalisées.
JS_SetMaxStackSize() peut être défini en utilisant la taille maximale de la pile système
Utilisez JS_SetInterruptHandler() pour configurer une fonction de rappel qui est appelée régulièrement lorsque le moteur exécute le code. Cette fonction de rappel peut être utilisée pour implémenter le délai d'exécution.
L'interpréteur de ligne de commande l'utilise pour implémenter le gestionnaire Ctrl-C .
Le compilateur génère un bytecode directement, sans représentations intermédiaires (comme les arbres d'analyse), il est donc très rapide. Plusieurs étapes d'optimisation sont effectuées sur le bytecode généré.
Bytecode basé sur la pile est sélectionné car il est simple et le code généré est compact.
Pour chaque fonction, la taille maximale de la pile est calculée au moment de la compilation, il n'y a donc pas besoin de tests de débordement de pile d'exécution.
Un tableau de numéro de ligne comprimé distinct est maintenu pour les informations de débogage.
L'accès aux variables de fermeture est optimisé et est presque aussi rapide que les variables locales.
eval directe en mode strict est optimisée.
qjsc Le compilateur qjsc génère le code source C à partir des fichiers JavaScript. Par défaut, le code source C est compilé à l'aide du compilateur système ( gcc ou clang ).
Le code source C généré contient le bytecode de la fonction ou du module compilé. Si un exécutable complet est requis, il contient également une fonction main() qui contient le code C nécessaire pour initialiser le moteur JavaScript et charger et exécuter des fonctions et des modules compilés.
Le code JavaScript peut être mélangé avec des modules C.
Pour générer des exécutables plus petits, des fonctionnalités JavaScript spécifiques, en particulier eval ou les expressions régulières, peuvent être désactivées. La suppression du code est liée à l'optimisation du temps de liaison dépendant du compilateur système.
qjsc fonctionne en compilant des scripts ou des modules, puis en les sérialisant en format binaire. Un sous-ensemble de ce format (à l'exclusion des fonctions ou des modules) peut être utilisé comme JSON binaire. Exemple test_bjson.js montre comment l'utiliser.
AVERTISSEMENT: le format JSON binaire peut changer sans préavis et ne doit pas être utilisé pour stocker des données persistantes. test_bjson.js n'est utilisé que pour tester les fonctions au format d'objet binaire.
Les cordes sont stockées sous forme de tableaux de caractères 8 bits ou 16 bits. Par conséquent, l'accès aléatoire aux caractères est toujours rapide.
L'API C fournit des fonctions pour convertir les chaînes JavaScript en chaînes codées C UTF-8. Le cas le plus courant est que les chaînes JavaScript ne contiennent que des chaînes ASCII et n'impliquent pas de copie.
Les formes d'objets (prototype d'objet, nom d'attribut et drapeau) sont partagées entre les objets pour enregistrer la mémoire.
Tableaux optimisés sans trous (sauf à la fin du tableau).
L'accès à TypedArray est optimisé.
Le nom de la propriété de l'objet et certaines chaînes sont stockés sous forme d'atomes (chaînes uniques) pour enregistrer la mémoire et permettre des comparaisons rapides. Les atomes sont représentés comme des entiers 32 bits. La moitié de la plage atomique est réservée à la valeur nominale immédiate entière de 0 à 2 ^ {31} -1.
Les nombres peuvent être représentés comme des entiers signés 32 bits ou des valeurs de points flottants IEEE-754 64 bits. La plupart des opérations ont des chemins rapides pour les cas entiers 32 bits.
Le nombre de références est utilisé pour libérer automatiquement et avec précision les objets. Lorsque la mémoire allouée devient trop grande, une opération de retrait de boucle séparée est effectuée. L'algorithme de suppression de boucle utilise uniquement le nombre de références et le contenu de l'objet, il n'est donc pas nécessaire de manipuler explicitement la racine de la collection des ordures dans le code C.
JSValue est une valeur JavaScript qui peut être un type primitif (tel que le nombre, la chaîne, etc.) ou un objet. Dans la version 32 bits, la boxe NAN est utilisée pour stocker des numéros de points flottants 64 bits. La représentation est optimisée pour tester efficacement les valeurs entières 32 bits et le nombre de références.
Dans le code 64 bits, la taille de JSValue est de 128 bits et n'est pas en boîte à l'aide de NAN. La raison en est que dans le code 64 bits, l'utilisation de la mémoire n'est pas si critique.
Dans les deux cas (32 bits ou 64 bits), JSValue s'adapte exactement à deux registres du CPU, il peut donc être renvoyé efficacement par les fonctions C.
Le moteur a été optimisé, donc les appels de fonction sont rapides. La pile système contient des paramètres JavaScript et des variables locales.
Un moteur d'expression régulière spécifique a été développé. Il est petit et efficace et prend en charge toutes les fonctionnalités ES2019, y compris les propriétés Unicode. En tant que compilateur JavaScript, il génère directement du bytecode sans arborescence d'analyse.
Utilisez un retour en arrière explicite de la pile afin qu'il n'y ait pas de récursivité sur la pile système. Les quantités simples sont spécialement optimisés pour éviter la récursivité.
La récursivité infinie d'un quantificateur avec des termes vides est évitée.
Le poids de la bibliothèque d'expression régulière complète est d'environ 15 kib (code x86), à l'exclusion de la bibliothèque Unicode.
Une bibliothèque Unicode spécifique est développée, donc elle ne dépend pas de grandes bibliothèques Unicode externes telles que les USI. Comprimez toutes les tables Unicode tout en maintenant des vitesses d'accès raisonnables.
La bibliothèque prend en charge la conversion de cas, la normalisation Unicode, les requêtes de script Unicode, les requêtes de catégorie générale Unicode et toutes les propriétés binaires Unicode.
La bibliothèque Unicode complète pèse environ 45 kib (code x86).
BigInt et BigFloat sont implémentés à l'aide de la bibliothèque Library libbf libbf Il dispose d'environ 60 kib (code x86) et fournit des opérations de points flottants IEEE 754 avec une précision arbitraire et des fonctions transcendantes avec un arrondissement précis.
QuickJS est libéré sous le protocole du MIT.
Sauf indication contraire, le droit d'auteur de Quickjs Source appartient à Fabrice Bellard et Charlie Gordon.
https://github.com/tc39/test262
https://tc39.github.io/ecma262/
Nous pensons que la spécification actuelle des appels de queue est trop complexe et présente des avantages réels limités.
https://bellard.org/libbf
Bibliothèque QuickJS-QUICKJS sous iOS
QuickJS - Bibliothèque Android QuickJS sous Android
Bibliothèque QuickJS de QuickJS-RS Rust
Bibliothèque QuickJSpp C ++ QuickJS
Bibliothèque QuickJS de Go-Quickjs Go
txiki.js Le petit temps d'exécution JavaScript construit avec Quickjs, Libuv et ❤️
QuickJS-Pascal QuickJS Freepascal / Delphi Régales