qjsqjscqjscalcstdosqjscO QuickJS é um mecanismo JavaScript pequeno e incorporável que suporta especificações do ES2020, incluindo módulos, geradores assíncronos e proxy.
Opcionalmente, ele suporta extensões matemáticas, como números inteiros grandes (bigint), grandes números de ponto flutuante (bigfloat) e sobrecarga do operador.
Site oficial: https://bellard.org/quickjs/
Site chinês: https://github.com/quickjs-zh/
Quickjs QQ Group 1: 598609506 .
Wiki chinês: https://github.com/quickjs-zh/quickjs/wiki
Clique para ver o conteúdo específico do teste de benchmark QuickJS
Fornece fingidas que podem ser compiladas no Linux ou MacOS/X. O suporte preliminar do Windows pode ser obtido por compilação cruzada em hosts Linux usando a ferramenta Mingw.
Se você deseja selecionar uma opção específica, edite a parte superior Makefile e execute make .
Execute make install usando o root para instalar arquivos binários e de suporte compilados em /usr/local (isso não é obrigado a usar o QuickJS).
NOTA : Você pode consultar a documentação chinesa do QuickJS sobre compilação e instalação no Windows e compilação e instalação no Linux.
qjs é um analisador de linha de comando (loop de leitura-EVal-Print).
./qjs examples/hello.js
qjsc é um compilador de linha de comando:
./qjsc -o hello examples/hello.js
./hello
Gere um arquivo executável hello sem dependências externas.
qjsbn e qjscbn são os intérpretes e compiladores correspondentes com extensões matemáticas:
./qjsbn examples/pi.js 1000
Exibir 1000 dígitos de Pi
./qjsbnc -o pi examples/pi.js
./pi 1000
Compilar e executar o programa PI.
qjsUso: QJS [Opções] [Arquivos]
Opções:
-h
--help
Lista de opções.
-e `EXPR`
--eval `EXPR`
Execute expr.
-i
--interactive
Vá para o modo interativo (não é o modo padrão quando o arquivo é servido na linha de comando).
-m
--module
Carregar como módulo ES6 (o padrão é .MJS Extensão de arquivo).
As opções avançadas incluem:
-d
--dump
Transferir estatísticas de uso da memória.
-q
--quit
Apenas instancie o intérprete e a saída.
qjscUso: QJSC [Opções] [arquivos]
Opções:
-c
Somente o bytecode no arquivo C é em saída e o padrão é produzir o arquivo executável.
-e
main() a saída e bytecode no arquivo C, o padrão é o arquivo executável de saída.
-o output
Defina o nome do arquivo de saída (padrão = out.c ou A.out).
-N cname
Define o nome C dos dados gerados.
-m
Compilar como um módulo JavaScript (o padrão é a extensão .MJS).
-M module_name[,cname]
Adicione o código de inicialização para módulos C externos. Confira c_module .
-x
Saída de troca de bytes (apenas para compilação cruzada).
-flto
Use otimização do tempo do link. A compilação é mais lenta, mas os executáveis são menores e mais rápidos. Esta opção é definida automaticamente ao usar a opção -fno-x .
-fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise]
Desative o recurso de idioma selecionado para gerar arquivos executáveis menores.
qjscalc O aplicativo qjscalc é um superconjunto do intérprete da linha de comando qjsbn que implementa uma calculadora JavaScript com números inteiros grandes arbitrários e números de ponto flutuante, frações, números complexos, polinômios e matrizes. O código -fonte está em qjscalc.js. Mais documentação e versões da Web estão disponíveis em http://numcalc.com.
Executar make test para executar alguns testes internos incluídos no arquivo Quickjs.
O arquivo QuickJS contém o programa Test262 Runner.
Para referência, o teste Test262 completo é fornecido no arquivo QJS-tests-yyyy-mm-dd.tar.xz. Você só precisa descompactá -lo no diretório de origem do QuickJS.
Como alternativa, o teste Test262 pode ser instalado:
git clone https://github.com/tc39/test262.git test262
cd test262
git checkout 94b1e80ab3440413df916cd56d29c5a2fa2ac451
patch -p1 < ../tests/test262.patch
cd ..
O patch adiciona funções harness específicas da implementação e otimiza as classes de caracteres REGEXP ineficientes e os testes de escape de atributos do Unicode (o próprio teste não será modificado, apenas a função de inicialização da string lenta é otimizada).
O teste pode ser executado
make test2
Para obter mais informações, execute ./run-test262 para ver as opções para o Test262 Runner. O arquivo de configuração test262.conf e test262bn.conf contêm opções para executar vários testes.
Especificação ES2019 2, que inclui os recursos do Anexo B (Compatibilidade da Web Legacy) e Recursos relacionados ao Unicode, já são basicamente suportados. Os seguintes recursos ainda não foram suportados:
Atualmente, os analisadores JSON são suportados por um alcance mais amplo que a especificação.
A ECMA402 (API internacional) ainda não foi apoiada.
"use strip" não retém informações de depuração (incluindo o código -fonte da função) para salvar a memória. A diretiva "use strict" pode aplicar scripts globais ou funções específicas.#! No início do script será ignorada. As extensões de matemática estão disponíveis na versão qjsbn e são totalmente compatíveis com jsbignum.pdf JavaScript padrão.
BigInt (INTEGER GRANDE) TC39 já é suportado.BigFloat suporta: qualquer grande número de ponto flutuante na cardinalidade 2."use bigint" permite o modo BIGINT, e BigInt é um número inteiro por padrão."use math" permite o modo matemático onde os operadores de divisão e energia em números inteiros produzem frações. Por padrão, os literais de ponto flutuante são o valor padrão e os números inteiros são o valor padrão do BIGINT.O módulo ES6 suporta totalmente. As regras de resolução de nomes padrão são as seguintes:
. ou .. é o caminho em relação ao módulo atual... nome os módulo não tem std ..so e é um módulo nativo usando a API Quickjs C. Por padrão, a biblioteca padrão está incluída no intérprete da linha de comando. Ele contém dois módulos std e os e alguns objetos globais.
scriptArgs
Forneça parâmetros da linha de comando. O primeiro parâmetro é o nome do script.
print(...args)
Parâmetros de impressão separados por espaços e novas linhas de direita.
console.log(...args)
O mesmo que print ().
std O módulo std fornece invólucros para libc stdlib.h e stdio.h e alguns outros utilitários.
Exportação disponível:
exit(n)
Saia do processo.
evalScript(str)
Execute o string str script (Global Eval).
loadScript(filename)
Execute o script filename (Global Eval).
Error(errno)
Construtor std.Error . A instância de erro contém os campos errno (código de erro) e message (resultado de std.Error.strerror(errno) ).
O construtor contém os seguintes campos:
EINVAL
EIO
EACCES
EEXIST
ENOSPC
ENOSYS
EBUSY
ENOENT
EPERM
EPIPE
Valores inteiros comumente errados (códigos de erro adicionais podem ser definidos).
strerror(errno)
Retorna a string errno que descreve o erro.
open(filename, flags)
Abra um arquivo (wrapper da libc fopen() ). Jogue std.Error no erro de E/S
tmpfile()
Abra um arquivo temporário. Jogue std.Error no erro de E/S.
puts(str)
É equivalente a std.out.puts(str) .
printf(fmt, ...args)
Equivalente a std.out.printf(fmt, ...args)
sprintf(fmt, ...args)
Equivalente ao sprintf () da libc ().
in
out
err
Wrap stdin , stdout , stderr do arquivo libc.
SEEK_SET
SEEK_CUR
SEEK_END
Constantes de Seek ()
global
Referências a objetos globais.
gc()
Chame manualmente o algoritmo de exclusão de loop. O algoritmo de remoção de loop inicia automaticamente quando necessário; portanto, esse recurso é muito útil quando limites ou testes específicos de memória.
getenv(name)
Retorna o name do valor da variável de ambiente, ou undefined se indefinido.
Protótipo de arquivo:
close()
Feche o arquivo.
puts(str)
Use a codificação do UTF-8 para sair de saída.
printf(fmt, ...args)
Formato printf, o mesmo que o formato Libc Printf.
flush()
Atualize o arquivo em buffer.
seek(offset, whence)
Procurando um local de arquivo específico (de onde std.SEEK_* ). Jogue std.Error no erro de E/S.
tell()
Retorne ao local atual do arquivo.
eof()
Retorne true se o arquivo terminar.
fileno()
Retorna o identificador do sistema operacional associado.
read(buffer, position, length)
Da position do arquivo na posição de byte, leia o byte length para o buffer do ArrayBuffer (o invólucro do LIBC fread ).
write(buffer, position, length)
Escreva length no buffer do ArrayBuffer, começando com position da posição de byte no arquivo (Wrapper fread da libc).
getline()
Retorna a próxima linha no arquivo, supondo que seja a codificação UTF-8, excluindo as linhas de novo.
getByte()
Retorna o próximo byte no arquivo.
putByte(c)
Escreva um byte no arquivo.
os os fornece funções específicas do sistema operacional:
Se ok, a função do sistema operacional geralmente retorna 0, ou o sistema operacional retorna um código de erro específico.
Funções de exportação disponíveis:
open(filename, flags, mode = 0o666)
Abra um arquivo. Se erro, retorne um identificador ou <0.
O_RDONLY
O_WRONLY
O_RDWR
O_APPEND
O_CREAT
O_EXCL
O_TRUNC
Posix Sign Open.
O_TEXT
(Específico do Windows). Abra o arquivo no modo de texto. O padrão é o modo binário.
close(fd)
Feche o identificador de arquivo fd .
seek(fd, offset, whence)
Procurando arquivos. Use std.SEEK_* ou whence .
read(fd, buffer, offset, length)
Começando do identificador de arquivo fd com o offset da posição de bytes, leia o byte length para o buffer do ArrayBuffer. Retorna o número de bytes lido e, se ocorrer um erro, ele retorna um valor menor que 0.
write(fd, buffer, offset, length)
Escreva o byte length no buffer do ArrayBuffer, começando com o offset identificador de arquivo fd . Retorna o número de bytes escritos e, se ocorrer um erro, um valor menor que 0 será retornado.
isatty(fd)
fd é um identificador de TTY (terminal) que retorna true .
ttyGetWinSize(fd)
Retorna o tamanho do TTY [width, height] ou null se indisponível.
ttySetRaw(fd)
Defina o TTY no modo original.
remove(filename)
Exclua o arquivo. Retornar 0 Se normal, retorne <0 se o erro
rename(oldname, newname)
Renomeie o arquivo. Retornar 0 Se normal, retorne <0 se o erro
setReadHandler(fd, func)
Adicione o manipulador de leitura ao identificador de arquivo fd . fd chama func toda vez que há dados a serem adicionados para processar. Suporta um único manipulador de leitura para cada identificador de arquivo. Use func = null para excluir a alça.
setWriteHandler(fd, func)
Adicione o manipulador de gravação ao identificador de arquivo fd . fd chama func toda vez que há dados a serem gravados para processar. Use `func = nulo para excluir a alça.
signal(signal, func)
Chame func quando signal ocorrer. Apenas um manipulador é suportado por número do sinal. Use os sinais ignorados processados ou undefined padrão definidos pelo null .
SIGINT
SIGABRT
SIGFPE
SIGILL
SIGSEGV
SIGTERM
Número do sinal POSIX.
setTimeout(func, delay)
Chame a função func após delay milissegundos. Retorna a alça para o cronômetro.
clearTimer(handle)
Cancele o temporizador.
platform
Retorna a sequência que representa a plataforma: "linux" , "darwin" , "win32" ou "js" .
A API C é simples e eficaz. A API C é definida no cabeçalho quickjs.h .
JSRuntime representa o tempo de execução do JavaScript correspondente à pilha do objeto. Vários tempos de execução podem existir ao mesmo tempo, mas eles não podem trocar objetos. Dentro de um determinado tempo de execução, o multithreading não é suportado.
JSContext representa um contexto de JavaScript (ou domínio). Cada JScontext possui seus próprios objetos globais e de sistema. Pode haver vários JSContexts no JSruntime, e eles podem compartilhar objetos, semelhantes às estruturas com os mesmos objetos JavaScript compartilhando em um navegador da Web.
JSValue representa um valor JavaScript, que pode ser um tipo primitivo ou um objeto. Use contagens de referência, por isso é importante copiar explicitamente ( JS_DupValue() , aumentar a contagem de referência) ou liberação ( JS_FreeValue() , diminuir a contagem de referência).
Use JS_NewCFunction() para criar funções C. JS_SetPropertyFunctionList() é uma maneira fácil de adicionar facilmente propriedades de função, setter e getter a um determinado objeto.
Ao contrário de outros motores JavaScript incorporados, o QuickJS não possui uma pilha implícita; portanto, a função C passa seus parâmetros como parâmetros C normais. A regra geral é que as funções C tomam JSValue como argumentos (para que eles não precisem ser libertados) e retornem um JSValue recém -alocado (ativo).
Exceção: a maioria das funções C pode retornar uma exceção de JavaScript. Deve ser explicitamente testado e processado através do código C. Um JSValue específico, ou seja, JS_EXCEPTION , indica que ocorreu uma exceção. O objeto de exceção real é armazenado no JSContext e pode ser recuperado usando JS_GetException() .
Use JS_Eval() para avaliar o script ou o código -fonte do módulo.
Se o script ou módulo tiver sido compilado no bytecode usando qjsc , o uso de JS_EvalBinary() poderá obter o mesmo resultado. A vantagem é que ele não requer compilação, por isso é mais rápido e menor em tamanho, porque se eval for necessário, o compilador poderá ser removido do executável.
Nota: O formato ByteCode está associado a uma versão do QuickJS específico. Além disso, nenhuma verificação de segurança foi realizada antes da execução. Portanto, o bytecode não deve ser carregado de fontes não confiáveis. É por isso que não há opção no qjsc para produzir bytecode para arquivos binários.
Os dados opacos de C podem ser anexados aos objetos JavaScript. O tipo de dados de C opa é determinado pelo ID da classe do objeto ( JSClassID ). Portanto, a primeira etapa é registrar uma nova classe de classe e classe JS ( JS_NewClassID() , JS_NewClass() ). Você pode criar um objeto dessa classe usando JS_NewObjectClass() e usar JS_GetOpaque() / JS_SetOpaque() para obter ou definir um ponteiro opaco para C.
Ao definir uma nova classe JS, você pode declarar um destruidor chamado quando o objeto é destruído. Um método gc_mark pode ser fornecido para que o algoritmo de remoção de loop possa encontrar outros objetos referenciados pelo objeto. Existem outros métodos que podem ser usados para definir o comportamento heterogêneo do objeto.
O ID da classe é alocado globalmente (ou seja, aplicável a todos os horários de execução). O JSClass é alocado em cada JSRuntime . JS_SetClassProto() é usado para definir protótipos para uma determinada classe em um determinado JSContext . JS_NewObjectClass() define esse protótipo no objeto criado.
Exemplos são fornecidos em js_libc.c.
Módulos ES6 nativos que suportam links dinâmicos ou estáticos. Confira os exemplos test_bjson e bjson.so. A biblioteca padrão js_libc.c também é um bom exemplo de módulos nativos.
Defina os limites globais de alocação de memória para um determinado JSruntime usando JS_SetMemoryLimit() .
JS_NewRuntime2() pode fornecer funções de alocação de memória personalizadas.
JS_SetMaxStackSize() pode ser definido usando o tamanho máximo da pilha do sistema
Use JS_SetInterruptHandler() para configurar uma função de retorno de chamada que é chamada regularmente quando o mecanismo executar o código. Essa função de retorno de chamada pode ser usada para implementar o tempo limite da execução.
O intérprete da linha de comando o usa para implementar o manipulador Ctrl-C .
O compilador gera diretamente o bytecode, sem representações intermediárias (como árvores de análise), por isso é muito rápido. Várias etapas de otimização são executadas no bytecode gerado.
O bytecode baseado em pilha é selecionado porque é simples e o código gerado é compacto.
Para cada função, o tamanho máximo da pilha é calculado no tempo de compilação, portanto, não há necessidade de testes de transbordamento de pilha de tempo de execução.
Uma tabela de número de linha compactada separada é mantida para depurar informações.
O acesso às variáveis de fechamento é otimizado e é quase tão rápido quanto as variáveis locais.
eval direta no modo rigoroso é otimizado.
qjsc O compilador qjsc gera código -fonte C a partir de arquivos JavaScript. Por padrão, o código -fonte C é compilado usando o compilador do sistema ( gcc ou clang ).
O código -fonte C gerado contém o bytecode da função ou módulo compilado. Se for necessário um executável completo, ele também contém uma função main() que contém o código C necessário para inicializar o mecanismo JavaScript e a carga e executar funções e módulos compilados.
O código JavaScript pode ser misturado com módulos C.
Para gerar executáveis menores, os recursos específicos do JavaScript, especialmente eval ou regulares, podem ser desativados. A remoção do código está vinculada à otimização do tempo dependente do compilador do sistema.
qjsc funciona compilando scripts ou módulos e, em seguida, serializando -os em formato binário. Um subconjunto desse formato (excluindo funções ou módulos) pode ser usado como JSON binário. Amostra test_bjson.js mostra como usá -lo.
Aviso: o formato JSON binário pode mudar sem aviso prévio e não deve ser usado para armazenar dados persistentes. test_bjson.js é usado apenas para testar funções no formato de objeto binário.
As cordas são armazenadas como matrizes de caracteres de 8 ou 16 bits. Portanto, o acesso aleatório aos caracteres é sempre rápido.
A API C fornece funções para converter strings JavaScript em seqüências codificadas C UTF-8. O caso mais comum é que as seqüências de javascript contêm apenas seqüências de cordas ASCII e não envolvem cópia.
As formas de objeto (protótipo de objeto, nome do atributo e sinalizador) são compartilhadas entre os objetos para salvar a memória.
Matrizes otimizadas sem orifícios (exceto no final da matriz).
O acesso typeDArray é otimizado.
O nome da propriedade do objeto e algumas seqüências são armazenadas como átomos (strings exclusivos) para salvar a memória e permitir comparações rápidas. Os átomos são representados como números inteiros de 32 bits. Metade da faixa atômica é reservada para o valor face inteiro imediato de 0 a 2^{31} -1.
Os números podem ser representados como números inteiros assinados de 32 bits ou valores de ponto flutuante IEEE-754 IEEE-754. A maioria das operações possui caminhos rápidos para casos inteiros de 32 bits.
A contagem de referência é usada para liberar automaticamente e com precisão objetos. Quando a memória alocada se torna muito grande, uma operação de remoção de loop separada é realizada. O algoritmo de remoção de loop usa apenas contagens de referência e conteúdo de objeto; portanto, não há necessidade de manipular explicitamente a raiz de coleta de lixo no código C.
O JSValue é um valor JavaScript que pode ser um tipo primitivo (como número, string, etc.) ou um objeto. Na versão de 32 bits, o Nan Boxing é usado para armazenar números de ponto flutuante de 64 bits. A representação é otimizada para testar com eficiência os valores inteiros de 32 bits e contagem de referência.
No código de 64 bits, o tamanho do JSValue é de 128 bits e não é embalado usando a NAN. O motivo é que, em código de 64 bits, o uso da memória não é tão crítico.
Nos dois casos (32 bits ou 64 bits), o JSValue se encaixa exatamente em dois registros da CPU, para que possa ser retornado eficientemente por funções C.
O motor foi otimizado, portanto as chamadas de função são rápidas. A pilha do sistema contém parâmetros JavaScript e variáveis locais.
Um mecanismo de expressão regular específico foi desenvolvido. É pequeno e eficiente e suporta todos os recursos do ES2019, incluindo propriedades Unicode. Como um compilador JavaScript, ele gera diretamente bytecode sem uma árvore de análise.
Use o tracktrack explícito da pilha para que não haja recursão na pilha do sistema. Quantizadores simples são especialmente otimizados para evitar a recursão.
A recursão infinita de um quantizador com termos vazios é evitada.
O peso da biblioteca de expressão regular completa é de aproximadamente 15 kib (código x86), excluindo a biblioteca Unicode.
Uma biblioteca unicode específica é desenvolvida, portanto, não depende de bibliotecas de unicode grandes externas, como as UTIs. Compressa todas as tabelas Unicode, mantendo velocidades de acesso razoáveis.
A biblioteca suporta conversão de casos, normalização unicode, consultas de script Unicode, consultas de categoria geral Unicode e todas as propriedades binárias Unicode.
A biblioteca Unicode completa pesa aproximadamente 45 kib (código x86).
BIGINT e BIGFLOAT são implementados usando a biblioteca libbf libbf Library. Possui cerca de 60 kib (código x86) e fornece operações de ponto flutuante IEEE 754 com precisão arbitrária e funções transcendentes com arredondamento preciso.
O QuickJS é lançado sob o protocolo MIT.
Salvo indicação em contrário, os direitos autorais da Fonte Quickjs pertencem a Fabrice Bellard e Charlie Gordon.
https://github.com/tc39/test262
https://tc39.github.io/ecma262/
Acreditamos que a especificação atual da chamada de cauda é muito complexa e tem benefícios reais limitados.
https://bellard.org/libbf
Biblioteca Quickjs-Quickjs sob iOS
Quickjs - Biblioteca Android Quickjs sob Android
biblioteca Quickjs-Rs Rust's Rust
Biblioteca Quickjspp C ++ QuickJS
Biblioteca Quickjs da Go-Quickjs Go
txiki.js o minúsculo tempo de execução do JavaScript construído com QuickJs, Libuv e ❤️
Quickjs-Pascal Quickjs FreePasCal / Delphi Bindings