qjsqjscqjscalcstd STDosqjscQuickJS es un motor JavaScript pequeño e integrable que admite especificaciones de ES2020, incluidos módulos, generadores asíncronos y proxy.
Opcionalmente, admite extensiones matemáticas, como enteros grandes (Bigint), grandes números de puntos flotantes (bigfloat) y sobrecarga del operador.
Sitio oficial: https://bellard.org/quickjs/
Sitio chino: https://github.com/quickjs-zh/
QuickJS QQ Group 1: 598609506 .
Wiki chino: https://github.com/quickjs-zh/quickjs/wiki
Haga clic para ver el contenido específico de la prueba de referencia QuickJS
Proporciona makefiles que se pueden compilar en Linux o MacOS/X. El soporte preliminar de Windows se puede obtener mediante compilación cruzada en hosts de Linux utilizando la herramienta MINGW.
Si desea seleccionar una opción específica, edite la parte superior de Makefile y ejecute make .
Ejecute make install usando Root para instalar archivos binarios y de soporte compilados a /usr/local (esto no es necesario para usar QuickJS).
Nota : Puede consultar la documentación china de QuickJS sobre la compilación e instalación en Windows y la compilación e instalación en Linux.
qjs es un analizador de línea de comandos (lee-Eval-Pread Loop).
./qjs examples/hello.js
qjsc es un compilador de línea de comandos:
./qjsc -o hello examples/hello.js
./hello
Genere un archivo ejecutable hello sin dependencias externas.
qjsbn y qjscbn son los intérpretes y compiladores correspondientes con extensiones matemáticas:
./qjsbn examples/pi.js 1000
Muestra 1000 dígitos de PI
./qjsbnc -o pi examples/pi.js
./pi 1000
Compilar y ejecutar el programa PI.
qjsUso: QJS [Opciones] [Archivos]
Opciones:
-h
--help
Lista de opciones.
-e `EXPR`
--eval `EXPR`
Realizar expr.
-i
--interactive
Vaya al modo interactivo (no es el modo predeterminado cuando el archivo se sirve en la línea de comando).
-m
--module
Cargar como módulo ES6 (predeterminado es la extensión del archivo .mjs).
Las opciones avanzadas incluyen:
-d
--dump
Transferir estadísticas de uso de la memoria.
-q
--quit
Simplemente instanciar el intérprete y la salida.
qjscUso: QJSC [Opciones] [Archivos]
Opciones:
-c
Solo se emite el ByTecode en el archivo C, y el valor predeterminado es generar el archivo ejecutable.
-e
main() la salida y el bytecode En el archivo C, el predeterminado es el archivo ejecutable de salida.
-o output
Establezca el nombre del archivo de salida (default = out.c o A.out).
-N cname
Establece el nombre C de los datos generados.
-m
Compilar como un módulo JavaScript (el valor predeterminado es la extensión .mjs).
-M module_name[,cname]
Agregue el código de inicialización para módulos C externos. Consulte c_module .
-x
Salida de intercambio de bytes (solo para compilación cruzada).
-flto
Use la optimización del tiempo de enlace. La compilación es más lenta, pero los ejecutables son más pequeños y más rápidos. Esta opción se establece automáticamente cuando se usa la opción -fno-x .
-fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise]
Deshabilite la función de idioma seleccionado para generar archivos ejecutables más pequeños.
qjscalc La aplicación qjscalc es un superconjunto del intérprete de la línea de comandos qjsbn que implementa una calculadora de JavaScript con enteros gruesos arbitrarios y números de puntos flotantes, fracciones, números complejos, polinomios y matrices. El código fuente está en QJScalc.js. Hay más documentación y versiones web disponibles en http://numcalc.com.
Ejecutar make test para ejecutar algunas pruebas incorporadas incluidas en el archivo QuickJS.
El archivo QuickJS contiene el programa Test262 Runner.
Como referencia, la prueba Test262 completa se proporciona en el archivo QJS-Tests-Yyyy-MM-DD.tar.xz. Solo necesita descomponerlo en el directorio de origen QuickJS.
Alternativamente, se puede instalar la prueba TEST262:
git clone https://github.com/tc39/test262.git test262
cd test262
git checkout 94b1e80ab3440413df916cd56d29c5a2fa2ac451
patch -p1 < ../tests/test262.patch
cd ..
El parche agrega funciones harness específicas de implementación y optimiza las clases ineficientes de caracteres regexp y las pruebas de escape de atributos Unicode (la prueba en sí no se modificará, solo la función de inicialización de cadena lenta está optimizada).
La prueba puede ejecutarse
make test2
Para obtener más información, ejecute ./run-test262 para ver las opciones para el corredor Test262. El archivo de configuración test262.conf y test262bn.conf contienen opciones para ejecutar varias pruebas.
La especificación ES2019 2, que incluye el anexo B (compatibilidad web heredada) y las características relacionadas con unicode, ya es compatible básicamente. Las siguientes características aún no son compatibles:
Los analizadores JSON son actualmente compatibles con un rango más amplio que la especificación.
ECMA402 (API internacional) aún no es compatible.
"use strip" no retiene la información de depuración (incluido el código fuente de la función) para guardar la memoria. La directiva "use strict" puede aplicar scripts globales o funciones específicas.#! Al comienzo del guión será ignorado. Las extensiones de matemáticas están disponibles en la versión qjsbn y son completamente compatibles jsbignum.pdf JavaScript estándar.
BigInt (Integer grande) TC39 ya es compatible.BigFloat Supports: cualquier número de punto flotante grande en Cardinality 2."use bigint" habilita el modo Bigint, y BigInt es un entero de forma predeterminada."use math" permite el modo matemático donde los operadores de división y energía en enteros producen fracciones. Por defecto, los literales de puntos flotantes son el valor predeterminado y los enteros son el valor predeterminado de BigInt.El módulo ES6 es completamente admitente. Las reglas de resolución de nombre predeterminadas son las siguientes:
. .. es la ruta relativa al módulo actual... módulo no os std ..so y es un módulo nativo que usa la API QuickJS C. Por defecto, la biblioteca estándar se incluye en el intérprete de la línea de comandos. Contiene dos módulos std y os y algunos objetos globales.
scriptArgs
Proporcionar parámetros de línea de comandos. El primer parámetro es el nombre del script.
print(...args)
Imprime parámetros separados por espacios y siguientes nuevas líneas.
console.log(...args)
Igual que print ().
std STD El módulo std proporciona envoltorios para libc stdlib.h y stdio.h y algunas otras utilidades.
Exportación disponible:
exit(n)
Salir del proceso.
evalScript(str)
Ejecute la cadena str Scripted (Global Eval).
loadScript(filename)
Ejecute el script filename (evaluación global).
Error(errno)
Constructor std.Error . La instancia de error contiene los campos errno (código de error) y message (resultado de std.Error.strerror(errno) ).
El constructor contiene los siguientes campos:
EINVAL
EIO
EACCES
EEXIST
ENOSPC
ENOSYS
EBUSY
ENOENT
EPERM
EPIPE
Valores enteros comúnmente incorrectos (se pueden definir códigos de error adicionales).
strerror(errno)
Devuelve la cadena errno que describe el error.
open(filename, flags)
Abra un archivo (Wrapper fopen() ). Arrojar std.Error en error de E/S
tmpfile()
Abra un archivo temporal. Tire std.Error en error de E/S.
puts(str)
Es equivalente a std.out.puts(str) .
printf(fmt, ...args)
Equivalente a std.out.printf(fmt, ...args)
sprintf(fmt, ...args)
Equivalente al sprintf () de libc.
in
out
err
Envolver stdin , stdout , stderr del archivo libc.
SEEK_SET
SEEK_CUR
SEEK_END
constantes de búsqueda ()
global
Referencias a objetos globales.
gc()
Llame manualmente al algoritmo de deleción del bucle. El algoritmo de eliminación de bucle se inicia automáticamente cuando sea necesario, por lo que esta característica es muy útil cuando la memoria específica limita o las pruebas.
getenv(name)
Devuelve el name de valor de la variable de entorno o undefined si no define.
Prototipo de archivo:
close()
Cierre el archivo.
puts(str)
Use la codificación UTF-8 a las cadenas de salida.
printf(fmt, ...args)
Formato printf, lo mismo que el formato de printf libc.
flush()
Actualice el archivo buffado.
seek(offset, whence)
Buscando una ubicación de archivo específica (desde donde std.SEEK_* ). Tire std.Error en error de E/S.
tell()
Regrese a la ubicación del archivo actual.
eof()
Devuelve verdadero si el archivo termina.
fileno()
Devuelve el mango OS asociado.
read(buffer, position, length)
Desde la position del archivo en la posición del byte, lea el byte length al buffer ArrayBuffer (el fread de libc).
write(buffer, position, length)
Escriba length en el buffer ArrayBuffer que comienza con position de la posición de byte al archivo (Wrapper fread ).
getline()
Devuelve la siguiente línea en el archivo, suponiendo que sea la codificación UTF-8, excluyendo las líneas nuevas.
getByte()
Devuelve el siguiente byte en el archivo.
putByte(c)
Escribe un byte al archivo.
os os operativo proporciona funciones específicas del sistema operativo:
Si está bien, la función del sistema operativo generalmente devuelve 0, o el sistema operativo devuelve un código de error específico.
Funciones de exportación disponibles:
open(filename, flags, mode = 0o666)
Abra un archivo. Si es un error, devuelve un mango o <0.
O_RDONLY
O_WRONLY
O_RDWR
O_APPEND
O_CREAT
O_EXCL
O_TRUNC
POSIX Open Sign.
O_TEXT
(Windows específico). Abra el archivo en modo de texto. El valor predeterminado es el modo binario.
close(fd)
Cerrar el manejo del archivo fd .
seek(fd, offset, whence)
Buscando archivos. Use std.SEEK_* o whence .
read(fd, buffer, offset, length)
Comenzando desde el archivo de manejo fd con el offset la posición del byte, lea el byte length al buffer ArrayBuffer. Devuelve el número de bytes que leen, y si se produce un error, devuelve un valor inferior a 0.
write(fd, buffer, offset, length)
Escriba el byte length en el buffer de ArrayBuffer que comienza con la posición de la posición de byte offset mango del archivo fd . Devuelve el número de bytes escritos, y si se produce un error, se devuelve un valor inferior a 0.
isatty(fd)
fd es un mango TTY (terminal) que devuelve true .
ttyGetWinSize(fd)
Devuelve el tamaño TTY [width, height] o null si no está disponible.
ttySetRaw(fd)
Establezca TTY en modo original.
remove(filename)
Eliminar el archivo. Devolver 0 si es normal, return <0 si error
rename(oldname, newname)
Cambiar el nombre del archivo. Devolver 0 si es normal, return <0 si error
setReadHandler(fd, func)
Agregue el controlador de lectura al manejo del archivo fd . fd llama func cada vez que se pueden agregar datos al proceso. Admite un solo controlador de lectura para cada mango de archivo. Use func = null para eliminar el mango.
setWriteHandler(fd, func)
Agregue el controlador de escritura al mango del archivo fd . fd llama func cada vez que hay datos que se pueden escribir para procesar. Use `func = null para eliminar el mango.
signal(signal, func)
Llame func cuando se produce signal . Solo se admite un controlador por número de señal. Use las señales de ignoración procesadas o undefined predeterminadas establecidas por null .
SIGINT
SIGABRT
SIGFPE
SIGILL
SIGSEGV
SIGTERM
Número de señal POSIX.
setTimeout(func, delay)
Llame a la función func después de los milisegundos delay . Devuelve el mango al temporizador.
clearTimer(handle)
Cancelar el temporizador.
platform
Devuelve la cadena que representa la plataforma: "linux" , "darwin" , "win32" o "js" .
La API C es simple y efectiva. La API C se define en el encabezado quickjs.h .
JSRuntime representa el tiempo de ejecución de JavaScript correspondiente al montón de objeto. Múltiples tiempos de ejecución pueden existir al mismo tiempo, pero no pueden intercambiar objetos. Dentro de un tiempo de ejecución dado, Multithreading no es compatible.
JSContext representa un contexto de JavaScript (o dominio). Cada jscontext tiene sus propios objetos globales y de sistema. Puede haber múltiples JSContexts en JSRuntime, y pueden compartir objetos, similares a los marcos con la misma fuente que comparte objetos JavaScript en un navegador web.
JSValue representa un valor de JavaScript, que puede ser un tipo primitivo o un objeto. Use recuentos de referencia, por lo que es importante copiar explícitamente ( JS_DupValue() , aumentar el recuento de referencias) o la liberación ( JS_FreeValue() , disminuir el recuento de referencias) JSValues.
Use JS_NewCFunction() para crear funciones C. JS_SetPropertyFunctionList() es una manera fácil de agregar fácilmente las propiedades de función, setter y getter a un objeto dado.
A diferencia de otros motores JavaScript integrados, QuickJS no tiene una pila implícita, por lo que la función C pasa sus parámetros como parámetros C normales. La regla general es que las funciones C toman JSValue como argumentos (por lo que no necesitan ser liberados) y devuelven un JSValue recién asignado (activo).
Excepción: la mayoría de las funciones C pueden devolver una excepción de JavaScript. Debe probarse y procesarse explícitamente a través del código C. Un JSValue específico, es decir, JS_EXCEPTION , indica que se ha producido una excepción. El objeto de excepción real se almacena en JSContext y se puede recuperar usando JS_GetException() .
Use JS_Eval() para evaluar el código fuente de script o módulo.
Si el script o el módulo se ha compilado en bytecode usando qjsc , entonces usar JS_EvalBinary() puede lograr el mismo resultado. La ventaja es que no requiere compilación, por lo que es más rápido y menor en tamaño, porque si no se requiere eval , el compilador se puede eliminar del ejecutable.
Nota: El formato de Bytecode está asociado con una versión específica de QuickJS. Además, no se realizaron comprobaciones de seguridad antes de la ejecución. Por lo tanto, el bytecode no debe cargarse de fuentes no confiables. Es por eso que no hay una opción en qjsc para emitir bytecode a archivos binarios.
Los datos opacos de C se pueden conectar a los objetos JavaScript. El tipo de datos C opacos está determinado por la ID de clase del objeto ( JSClassID ). Por lo tanto, el primer paso es registrar una nueva ID de clase y clase JS ( JS_NewClassID() , JS_NewClass() ). Luego puede crear un objeto de esa clase usando JS_NewObjectClass() y usar JS_GetOpaque() / JS_SetOpaque() para obtener o configurar un puntero opaco en C.
Al definir una nueva clase JS, puedes declarar un destructor que se llama cuando el objeto se destruye. Se puede proporcionar un método gc_mark para que el algoritmo de eliminación de bucle pueda encontrar otros objetos a los que se hace referencia el objeto. Existen otros métodos que se pueden usar para definir el comportamiento de los objetos heterogéneos.
La ID de clase se asigna a nivel mundial (es decir, aplicable a todos los tiempos de ejecución). JSClass se asigna en cada JSRuntime . JS_SetClassProto() se usa para definir prototipos para una clase dada en un JSContext dado. JS_NewObjectClass() establece este prototipo en el objeto creado.
Se proporcionan ejemplos en js_libc.c.
Módulos ES6 nativos que admiten enlaces dinámicos o estáticos. Echa un vistazo a los ejemplos test_bjson y bjson. La biblioteca estándar js_libc.c también es un buen ejemplo de módulos nativos.
Establezca límites de asignación de memoria global para un JSRuntime dado usando JS_SetMemoryLimit() .
JS_NewRuntime2() puede proporcionar funciones de asignación de memoria personalizadas.
JS_SetMaxStackSize() se puede establecer utilizando el tamaño máximo de la pila del sistema
Use JS_SetInterruptHandler() para configurar una función de devolución de llamada que se llama regularmente cuando el motor ejecuta el código. Esta función de devolución de llamada se puede usar para implementar el tiempo de espera de ejecución.
El intérprete de la línea de comandos lo usa para implementar el controlador Ctrl-C .
El compilador genera bytecode directamente, sin representaciones intermedias (como árboles de análisis), por lo que es muy rápido. Se realizan varios pasos de optimización en el bytecode generado.
Bytecode basado en pila se selecciona porque es simple y el código generado es compacto.
Para cada función, el tamaño máximo de la pila se calcula en el tiempo de compilación, por lo que no es necesario que las pruebas de desbordamiento de pila de tiempo de ejecución.
Se mantiene una tabla de número de fila comprimida separada para la información de depuración.
El acceso a las variables de cierre está optimizado y es casi tan rápido como las variables locales.
eval directa en modo estricto está optimizado.
qjsc El compilador qjsc genera código fuente C a partir de archivos JavaScript. Por defecto, el código fuente C se compila utilizando el compilador del sistema ( gcc o clang ).
El código fuente C generado contiene el código de bytes de la función o módulo compilado. Si se requiere un ejecutable completo, también contiene una función main() que contiene el código C necesario para inicializar el motor JavaScript y cargar y ejecutar funciones y módulos compilados.
El código JavaScript se puede mezclar con módulos C.
Para generar ejecutables más pequeños, se pueden deshabilitar características específicas de JavaScript, especialmente eval o expresiones regulares. La eliminación del código está vinculada a la optimización del tiempo de enlace dependiente del compilador del sistema.
qjsc funciona compilando scripts o módulos y luego serializándolos en formato binario. Un subconjunto de este formato (excluyendo funciones o módulos) puede usarse como JSON binario. La muestra test_bjson.js muestra cómo usarlo.
Advertencia: el formato JSON binario puede cambiar sin previo aviso y no debe usarse para almacenar datos persistentes. test_bjson.js solo se usa para probar funciones en formato de objeto binario.
Las cadenas se almacenan como matrices de personajes de 8 o 16 bits. Por lo tanto, el acceso aleatorio a los personajes siempre es rápido.
La API C proporciona funciones para convertir las cadenas JavaScript en cadenas codificadas C UTF-8. El caso más común es que las cadenas JavaScript contienen solo cadenas ASCII y no implican copiar.
Las formas de objeto (prototipo de objeto, nombre del atributo y indicador) se comparten entre los objetos para guardar la memoria.
Matrices optimizadas sin agujeros (excepto al final de la matriz).
TypedArray Access está optimizado.
El nombre de la propiedad del objeto y algunas cadenas se almacenan como átomos (cadenas únicas) para guardar la memoria y permitir comparaciones rápidas. Los átomos se representan como enteros de 32 bits. La mitad del rango atómico está reservado para el valor nominal entero inmediato de 0 a 2^{31} -1.
Los números pueden representarse como enteros firmados de 32 bits o valores de punto flotante IEEE-754 de 64 bits. La mayoría de las operaciones tienen rutas rápidas para casos enteros de 32 bits.
El recuento de referencias se usa para liberar objetos de forma automática y precisa. Cuando la memoria asignada se vuelve demasiado grande, se realiza una operación de eliminación de bucle separada. El algoritmo de eliminación de bucle utiliza solo recuentos de referencia y contenido de objetos, por lo que no es necesario manipular explícitamente la raíz de recolección de basura en el código C.
JSValue es un valor de JavaScript que puede ser un tipo primitivo (como número, cadena, etc.) o un objeto. En la versión de 32 bits, el boxeo NAN se usa para almacenar números de puntos flotantes de 64 bits. La representación está optimizada para probar eficientemente el entero de 32 bits y los valores de conteo de referencia.
En el código de 64 bits, el tamaño de JSValue es de 128 bits y no está en caja usando NAN. La razón es que en el código de 64 bits, el uso de la memoria no es tan crítico.
En ambos casos (32 bits o 64 bits), JSValue se ajusta exactamente a dos registros de CPU, por lo que puede ser devuelto de manera eficiente mediante funciones C.
El motor ha sido optimizado, por lo que las llamadas de función son rápidas. La pila del sistema contiene parámetros de JavaScript y variables locales.
Se desarrolló un motor de expresión regular específico. Es pequeño y eficiente y admite todas las características de ES2019, incluidas las propiedades de Unicode. Como compilador de JavaScript, genera directamente bytecode sin un árbol de análisis.
Use el retroceso explícito de la pila para que no haya recursión en la pila del sistema. Los cuantizadores simples están especialmente optimizados para evitar la recursión.
Se evita la recursión infinita de un cuantizador con términos vacíos.
El peso de la biblioteca de expresión regular completa es de aproximadamente 15 KIB (código x86), excluyendo la biblioteca Unicode.
Se desarrolla una biblioteca unicode específica, por lo que no depende de bibliotecas unicode grandes externos como las UCI. Comprima todas las tablas Unicode mientras mantiene velocidades de acceso razonables.
La biblioteca admite la conversión de casos, la normalización unicode, consultas de script Unicode, consultas de categoría general Unicode y todas las propiedades binarias unicode.
La biblioteca Unicode completa pesa aproximadamente 45 kib (código x86).
Bigint y BigFloat se implementan utilizando la biblioteca libbf libbf . Tiene alrededor de 60 KIB (código X86) y proporciona operaciones de punto flotante IEEE 754 con precisión arbitraria y funciones trascendentes con redondeo preciso.
QuickJS se libera bajo el protocolo MIT.
A menos que se indique lo contrario, los derechos de autor de QuickJS Source pertenecen a Fabrice Bellard y Charlie Gordon.
https://github.com/tc39/test262
https://tc39.github.io/ecma262/
Creemos que la especificación actual de llamadas de cola es demasiado compleja y tiene beneficios reales limitados.
https://bellard.org/libbf
Biblioteca QuickJS-Quickjs bajo iOS
QuickJS - Biblioteca Android QuickJS en Android
Biblioteca QuickJS de QuickJS-RS Rusts
Biblioteca QuickJSPP C ++ QuickJS
Biblioteca QuickJS de Go-Quickjs GO
txiki.js El pequeño tiempo de ejecución de JavaScript construido con QuickJS, Libuv y ❤️
Quickjs-Pascal Quickjs Freepascal / Delphi Bindings