qjs通訳qjscコンパイラqjscalcアプリケーションstdモジュールosモジュールqjscコンパイラQuickJSは、モジュール、非同期ジェネレーター、プロキシなどのES2020仕様をサポートする小さく埋め込まれたJavaScriptエンジンです。
オプションでは、大型整数(BIGINT)、大きな浮動小数点数(BigFloat)、オペレーターの過負荷などの数学的拡張機能をサポートします。
公式サイト:https://bellard.org/quickjs/
中国のサイト:https://github.com/quickjs-zh/
QuickJS QQグループ1: 598609506 。
中国のwiki:https://github.com/quickjs-zh/quickjs/wiki
クリックしてQuickJSベンチマークテストの特定のコンテンツを表示します
LinuxまたはMacOS/Xにコンパイルできるメイクファイルを提供します。予備のWindowsサポートは、MINGWツールを使用してLinuxホストのクロスコンパイルで取得できます。
特定のオプションを選択する場合は、 Makefileの上部を編集してmakeします。
rootを使用してmake install実行して、コンパイルされたバイナリおよびサポートファイルを/usr/localにインストールします(これはquickjsを使用する必要はありません)。
注:Windowsの下でのコンピレーションとインストールに関するQuickJS中国のドキュメント、Linuxの下でのコンパイルとインストールを参照できます。
qjsは、コマンドラインパーサー(読み取りeval-printループ)です。
./qjs examples/hello.js
qjscはコマンドラインコンパイラです。
./qjsc -o hello examples/hello.js
./hello
外部依存関係なしでhello実行可能ファイルを生成します。
qjsbnとqjscbnは、数学的拡張機能を持つ対応する通訳者およびコンパイラーです。
./qjsbn examples/pi.js 1000
PIの1000桁を表示します
./qjsbnc -o pi examples/pi.js
./pi 1000
PIプログラムをコンパイルして実行します。
qjs通訳使用法:QJS [オプション] [ファイル]
オプション:
-h
--help
オプションのリスト。
-e `EXPR`
--eval `EXPR`
exprを実行します。
-i
--interactive
インタラクティブモードに移動します(コマンドラインでファイルが提供される場合、デフォルトモードではありません)。
-m
--module
ES6モジュールとしてロードします(デフォルトは.MJSファイル拡張子です)。
高度なオプションは次のとおりです。
-d
--dump
メモリ使用法統計を転送します。
-q
--quit
通訳をインスタンス化して終了します。
qjscコンパイラ使用法:QJSC [オプション] [ファイル]
オプション:
-c
Cファイルのバイトコードのみが出力され、デフォルトは実行可能ファイルを出力することです。
-e
main() cファイルの出力とバイトコードは、デフォルトは出力実行可能ファイルです。
-o output
出力ファイル名(default = out.cまたはa.out)を設定します。
-N cname
生成されたデータのC名を設定します。
-m
JavaScriptモジュールとしてコンパイルします(デフォルトは.MJS拡張機能です)。
-M module_name[,cname]
外部Cモジュールの初期化コードを追加します。 c_module例をご覧ください。
-x
バイトスワップ出力(相互コンパイルのみ)。
-flto
リンク時間の最適化を使用します。編集は遅くなりますが、実行可能ファイルは小さく、より速いです。このオプションは、オプション-fno-xを使用するときに自動的に設定されます。
-fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise]
選択した言語機能を無効にして、小さな実行可能ファイルを生成します。
qjscalcアプリケーションqjscalcアプリケーションは、任意の大きな整数と浮動小数点数、画分、複雑な数値、多項式、および行列を備えたJavaScript計算機を実装するqjsbnコマンドラインインタープリターのスーパーセットです。ソースコードはqjscalc.jsにあります。その他のドキュメントとWebバージョンは、http://numcalc.comで入手できます。
QuickJSアーカイブに含まれる組み込みテストを実行するためのmake test実行します。
QuickJSアーカイブには、test262ランナープログラムが含まれています。
参照のために、完全なtest262テストは、アーカイブqjs-tests-yyyyymm-dd.tar.xzで提供されています。 QuickJSソースディレクトリに解凍するだけです。
または、test262テストをインストールできます。
git clone https://github.com/tc39/test262.git test262
cd test262
git checkout 94b1e80ab3440413df916cd56d29c5a2fa2ac451
patch -p1 < ../tests/test262.patch
cd ..
このパッチは、実装固有のharness関数を追加し、非効率的なRegexp文字クラスとUnicode属性エスケープテストを最適化します(テスト自体は変更されず、遅い文字列初期化関数のみが最適化されます)。
テストは実行できます
make test2
詳細については、run ./run-test262実行して、test262ランナーのオプションを確認してください。構成ファイルtest262.confおよびtest262bn.confには、さまざまなテストを実行するオプションが含まれています。
Annex B(Legacy Web互換性)およびUnicode関連機能を含むES2019仕様2は、基本的にすでにサポートされています。 次の機能はまだサポートされていません。
JSONパーサーは現在、仕様よりも広い範囲でサポートされています。
ECMA402(国際API)はまだサポートされていません。
"use strip"メモリを保存するためにデバッグ情報(関数ソースコードを含む)を保持しません。 "use strict"指令は、グローバルスクリプトまたは特定の関数を適用できます。#! 数学拡張機能は、 qjsbnバージョンで利用でき、詳細についてはjsbignum.pdfをご覧ください。
BigInt (大整数)TC39はすでにサポートされています。BigFloatサポート:カーディナリティ2の大きな浮動小数点数。"use bigint"はBigIntモードを有効にし、 BigIntはデフォルトで整数です。"use math"命令により、整数の分割および電力オペレーターが分数を生成する数学モードが可能になります。デフォルトでは、フローティングポイントリテラルはデフォルト値であり、整数はBIGINTのデフォルト値です。ES6モジュールは完全にサポートしています。デフォルトの名前解決ルールは次のとおりです。
.または..は現在のモジュールに対するパスです。.または.. stdやosなどのシステムモジュールがありません。.soで終了し、QuickJS C APIを使用してネイティブモジュールです。デフォルトでは、標準ライブラリはコマンドラインインタープリターに含まれています。 2つのモジュールstdとos 、およびいくつかのグローバルオブジェクトが含まれています。
scriptArgs
コマンドラインパラメーターを提供します。最初のパラメーターはスクリプト名です。
print(...args)
スペースと後続のニューラインで区切られたパラメーターを印刷します。
console.log(...args)
print()と同じ。
stdモジュールstdモジュールは、LIBC STDLIB.HおよびSTDIO.Hおよびその他のユーティリティのラッパーを提供します。
利用可能なエクスポート:
exit(n)
プロセスを終了します。
evalScript(str)
文字列strスクリプト(グローバル評価)を実行します。
loadScript(filename)
filenameスクリプト(Global Eval)を実行します。
Error(errno)
std.Errorコンストラクター。 エラーインスタンスには、フィールドerrno (エラーコード)とmessage ( std.Error.strerror(errno)の結果)が含まれます。
コンストラクターには次のフィールドが含まれています。
EINVAL
EIO
EACCES
EEXIST
ENOSPC
ENOSYS
EBUSY
ENOENT
EPERM
EPIPE
一般的に間違った整数値(追加のエラーコードを定義できます)。
strerror(errno)
エラーを説明する文字列errnoを返します。
open(filename, flags)
ファイルを開きます(libcのラッパーfopen() )。 I/Oエラーでstd.Errorを投げます
tmpfile()
一時ファイルを開きます。 I/Oエラーでstd.Errorを投げます。
puts(str)
std.out.puts(str)に相当します。
printf(fmt, ...args)
std.out.printf(fmt, ...args)に相当
sprintf(fmt, ...args)
LIBCのsprintf()に相当します。
in
out
err
Lap stdin 、 stdout 、 stderr of libcファイル。
SEEK_SET
SEEK_CUR
SEEK_END
Seek()の定数
global
グローバルオブジェクトへの参照。
gc()
ループ削除アルゴリズムを手動で呼び出します。ループ除去アルゴリズムは、必要に応じて自動的に開始されるため、特定のメモリの制限またはテストでこの機能は非常に役立ちます。
getenv(name)
環境変数の値nameを返し、未定義の場合はundefinedない場合。
ファイルプロトタイプ:
close()
ファイルを閉じます。
puts(str)
UTF-8エンコードを使用して文字列を出力します。
printf(fmt, ...args)
libc printf形式と同じフォーマットprintf。
flush()
バッファーファイルを更新します。
seek(offset, whence)
特定のファイルの場所を探しています( std.SEEK_*から)。 I/Oエラーでstd.Errorを投げます。
tell()
現在のファイルの場所に戻ります。
eof()
ファイルが終了した場合はtrueを返します。
fileno()
関連するOSハンドルを返します。
read(buffer, position, length)
バイト位置のファイルpositionから、 lengthバイトをArrayBuffer buffer (LIBCのラッパーfread )まで読み取ります。
write(buffer, position, length)
ファイルへのバイト位置のposition (LIBCのラッパーfread )から始まるArrayBuffer bufferにlengthバイトを書きます。
getline()
Trailing Newlinesを除く、UTF-8エンコードであると仮定して、ファイルの次の行を返します。
getByte()
ファイル内の次のバイトを返します。
putByte(c)
ファイルにバイトを書き込みます。
osモジュールosモジュールは、オペレーティングシステム固有の機能を提供します。
OKの場合、OS関数は通常0を返し、OSは特定のエラーコードを返します。
利用可能なエクスポート機能:
open(filename, flags, mode = 0o666)
ファイルを開きます。エラーの場合、ハンドルまたは<0を返します。
O_RDONLY
O_WRONLY
O_RDWR
O_APPEND
O_CREAT
O_EXCL
O_TRUNC
Posixオープンサイン。
O_TEXT
(Windows固有)。テキストモードでファイルを開きます。デフォルトはバイナリモードです。
close(fd)
ファイルハンドルfdを閉じます。
seek(fd, offset, whence)
ファイルを探しています。 std.SEEK_*またはwhenceを使用してください。
read(fd, buffer, offset, length)
バイト位置offsetを備えたファイルハンドルfdから開始するには、 lengthバイトをArrayBuffer bufferまで読み取ります。読み取られたバイト数を返し、エラーが発生した場合、0未満の値を返します。
write(fd, buffer, offset, length)
ファイルハンドルfd offsetから始まるArrayBuffer bufferにlengthバイトを書き込みます。書かれたバイト数を返し、エラーが発生した場合、0未満の値が返されます。
isatty(fd)
fdはTTY(ターミナル)ハンドルであり、 trueを返します。
ttyGetWinSize(fd)
利用できない場合は、TTYサイズ[width, height]またはnullを返します。
ttySetRaw(fd)
TTYを元のモードで設定します。
remove(filename)
ファイルを削除します。通常の場合は0を返し、エラーの場合は<0を返します
rename(oldname, newname)
ファイルの名前を変更します。通常の場合は0を返し、エラーの場合は<0を返します
setReadHandler(fd, func)
読み取りハンドラーをファイルハンドルfdに追加します。 fd 、プロセスに追加されるデータがあるたびにfuncを呼び出します。ファイルハンドルごとに単一の読み取りハンドラーをサポートします。 func = nullを使用して、ハンドルを削除します。
setWriteHandler(fd, func)
ファイルハンドルfdに書き込みハンドラーを追加します。 fd 、ファイルハンドルの書き込みハンドラーをサポートするために、 funcを呼び出します。 `func = nullを使用して、ハンドルを削除します。
signal(signal, func)
signalが発生したらfuncを呼び出します。 信号番号ごとにサポートされているハンドラーは1つだけです。 nullによって設定されたデフォルトの処理済みまたはundefined無視信号を使用します。
SIGINT
SIGABRT
SIGFPE
SIGILL
SIGSEGV
SIGTERM
POSIX信号番号。
setTimeout(func, delay)
delayミリ秒後に関数funcを呼び出します。ハンドルをタイマーに返します。
clearTimer(handle)
タイマーをキャンセルします。
platform
プラットフォームを表す文字列を返します: "linux" 、 "darwin" 、 "win32"または"js" 。
C APIはシンプルで効果的です。 C APIはquickjs.hヘッダーで定義されています。
JSRuntime 、オブジェクトヒープに対応するJavaScriptランタイムを表します。複数のランタイムが同時に存在する可能性がありますが、オブジェクトを交換することはできません。特定のランタイム内では、マルチスレッドはサポートされていません。
JSContext 、JavaScriptコンテキスト(またはドメイン)を表します。各jScontextには、独自のグローバルおよびシステムオブジェクトがあります。 jsruntimeには複数のjScontextsがあり、WebブラウザーでJavaScriptオブジェクトを共有する同じソースを持つフレームワークと同様に、オブジェクトを共有できます。
JSValue 、原始タイプまたはオブジェクトであるJavaScript値を表します。参照カウントを使用するため、明示的にコピー( JS_DupValue() 、参照カウントの増加)またはリリース( JS_FreeValue() 、参照カウントを減少)jsvaluesをコピーすることが重要です。
JS_NewCFunction()を使用して、c関数を作成します。 JS_SetPropertyFunctionList() 、機能、セッター、およびゲッタープロパティを特定のオブジェクトに簡単に追加する簡単な方法です。
他の埋め込まれたJavaScriptエンジンとは異なり、QuickJSには暗黙的なスタックがないため、C関数は通常のCパラメーターとしてパラメーターを渡します。一般的なルールは、C関数がJSValue引数として取得し(解放する必要はない)、新しく割り当てられた(アクティブな) JSValueを返すことです。
例外:ほとんどのC関数は、JavaScript例外を返すことができます。 Cコードを介して明示的にテストおよび処理する必要があります。特定のJSValue 、つまりJS_EXCEPTION 、例外が発生したことを示しています。実際の例外オブジェクトはJSContextに保存され、 JS_GetException()を使用して取得できます。
JS_Eval()を使用して、スクリプトまたはモジュールソースコードを評価します。
スクリプトまたはモジュールがqjscを使用してByteCodeにコンパイルされている場合、 JS_EvalBinary()を使用すると同じ結果が得られます。利点は、コンピレーションを必要としないため、 evalが不要な場合、コンパイラを実行可能ファイルから削除できるため、サイズが高速で小さくなります。
注:ByteCode形式は、特定のQuickJSバージョンに関連付けられています。さらに、実行前にセキュリティチェックは実行されませんでした。したがって、bytecodeを信頼されていないソースからロードしないでください。これが、 qjscにバイナリファイルにバイテコードを出力するオプションがない理由です。
Cの不透明なデータは、JavaScriptオブジェクトに添付できます。 C不誤データのタイプは、オブジェクトのクラスID( JSClassID )によって決定されます。したがって、最初のステップは、新しいクラスIDとJSクラス( JS_NewClassID() 、 JS_NewClass() )を登録することです。その後、 JS_NewObjectClass()を使用してそのクラスのオブジェクトを作成し、 JS_GetOpaque() / JS_SetOpaque()を使用して、Cへの不透明なポインターを取得または設定できます。
新しいJSクラスを定義するとき、オブジェクトが破壊されたときに呼び出されるデストラクタを宣言できます。 gc_markメソッドを提供して、ループ除去アルゴリズムがオブジェクトによって参照される他のオブジェクトを見つけることができるようにすることができます。不均一なオブジェクトの動作を定義するために使用できる他の方法があります。
クラスIDはグローバルに割り当てられます(つまり、すべてのランタイムに適用可能)。 JSClassは各JSRuntimeに割り当てられています。 JS_SetClassProto()は、特定のJSContextの特定のクラスのプロトタイプを定義するために使用されます。 JS_NewObjectClass()このプロトタイプを作成したオブジェクトに設定します。
例はjs_libc.cで提供されています。
動的リンクまたは静的リンクをサポートするネイティブES6モジュール。 test_bjsonとbjson.oの例をご覧ください。標準ライブラリJS_LIBC.Cは、ネイティブモジュールの良い例でもあります。
JS_SetMemoryLimit()を使用して、特定のJSRUNTIMEのグローバルメモリ割り当て制限を設定します。
JS_NewRuntime2()カスタムメモリ割り当て関数を提供できます。
JS_SetMaxStackSize()最大システムスタックサイズを使用して設定できます
JS_SetInterruptHandler()を使用して、エンジンがコードを実行したときに定期的に呼び出されるコールバック関数を設定します。このコールバック関数は、実行タイムアウトを実装するために使用できます。
コマンドラインインタープリターは、それを使用してCtrl-Cハンドラーを実装します。
コンパイラは、中間表現(解析ツリーなど)なしで直接バイトコードを生成するため、非常に高速です。生成されたバイトコードでいくつかの最適化ステップが実行されます。
スタックベースのバイトコードが単純で、生成されたコードがコンパクトであるため、選択されます。
各関数について、最大スタックサイズはコンパイル時間で計算されるため、ランタイムスタックオーバーフローテストは必要ありません。
デバッグ情報のために、個別の圧縮行番号テーブルが維持されます。
閉鎖変数へのアクセスは最適化されており、ローカル変数とほぼ同じ高速です。
厳密なモードでの直接evalが最適化されています。
qjscコンパイラqjscコンパイラは、JavaScriptファイルからCソースコードを生成します。デフォルトでは、Cソースコードはシステムコンパイラ( gccまたはclang )を使用してコンパイルされます。
生成されたCソースコードには、コンパイルされた関数またはモジュールのバイトコードが含まれています。完全な実行可能ファイルが必要な場合、JavaScriptエンジンを初期化し、コンパイルされた機能とモジュールをロードして実行するために必要なCコードを含むmain()関数も含まれています。
JavaScriptコードはCモジュールと混合できます。
小さな実行可能ファイルを生成するには、特定のJavaScript機能、特にevalまたは正規表現を無効にすることができます。コード削除は、システムコンパイラ依存のリンク時間最適化にリンクされています。
qjsc 、スクリプトまたはモジュールをコンパイルし、バイナリ形式にシリアル化することで機能します。この形式のサブセット(関数またはモジュールを除く)は、バイナリJSONとして使用できます。サンプルtest_bjson.js 、それを使用する方法を示しています。
警告:バイナリJSON形式は予告なく変更される場合があり、永続的なデータを保存するために使用しないでください。 test_bjson.js例は、バイナリオブジェクト形式の関数のテストにのみ使用されます。
文字列は、8ビットまたは16ビット文字アレイとして保存されます。したがって、文字へのランダムアクセスは常に高速です。
C APIは、JavaScript文字列をC UTF-8エンコード文字列に変換する機能を提供します。最も一般的なケースは、JavaScript文字列にASCII文字列のみが含まれており、コピーが含まれないことです。
オブジェクトシェイプ(オブジェクトプロトタイプ、属性名、フラグ)は、メモリを保存するためにオブジェクト間で共有されます。
穴のない最適化された配列(配列の終わりを除く)。
TypedArrayアクセスが最適化されています。
オブジェクトプロパティ名といくつかの文字列は、メモリを保存し、迅速な比較を可能にするために、原子(一意の文字列)として保存されます。原子は32ビット整数として表されます。原子範囲の半分は、0〜2^{31} -1の即時整数額面用に予約されています。
数字は、32ビットの署名整数または64ビットIEEE-754フローティングポイント値として表すことができます。ほとんどの操作には、32ビットの整数ケースの高速パスがあります。
参照カウントは、オブジェクトを自動的かつ正確にリリースするために使用されます。割り当てられたメモリが大きくなりすぎると、個別のループ除去操作が実行されます。ループ除去アルゴリズムは、参照カウントとオブジェクトコンテンツのみを使用するため、Cコードのガベージコレクションルートを明示的に操作する必要はありません。
jsvalueは、原始的なタイプ(数、文字列など)またはオブジェクトになる可能性のあるJavaScript値です。 32ビットバージョンでは、NANボクシングを使用して64ビットの浮動小数点数を保存します。表現は、32ビット整数と参照カウント値を効率的にテストするために最適化されています。
64ビットコードでは、JSValueのサイズは128ビットで、NANを使用して箱入りはありません。その理由は、64ビットコードでは、メモリの使用がそれほど重要ではないためです。
どちらの場合も(32ビットまたは64ビット)、JSValueは正確に2つのCPUレジスタに適合するため、C関数によって効率的に返すことができます。
エンジンが最適化されているため、関数呼び出しは高速です。システムスタックには、JavaScriptパラメーターとローカル変数が含まれています。
特定の正規表現エンジンが開発されました。小さく効率的で、Unicodeプロパティを含むすべてのES2019機能をサポートしています。 JavaScriptコンパイラとして、解析ツリーなしでBytecodeを直接生成します。
システムスタックに再帰がないように、明示的なスタックバックトラッキングを使用します。単純な量子イカイザーは、再帰を避けるために特別に最適化されています。
空の用語での量子化器からの無限の再帰は回避されます。
完全な正規表現ライブラリの重みは、Unicodeライブラリを除く約15 KIB(x86コード)です。
特定のUnicodeライブラリが開発されているため、ICUなどの外部の大きなユニコードライブラリに依存しません。合理的なアクセス速度を維持しながら、すべてのユニコードテーブルを圧縮します。
ライブラリは、ケース変換、ユニコード正規化、ユニコードスクリプトクエリ、ユニコード一般カテゴリクエリ、およびすべてのユニコードバイナリプロパティをサポートしています。
完全なUnicodeライブラリの重量は約45キブ(x86コード)です。
BigintとBigFloatは、 libbfライブラリlibbfライブラリを使用して実装されています。 約60のKIB(x86コード)があり、IEEE 754フローティングポイント操作を任意の精度と正確な丸めで超越的な関数を提供します。
QuickJSはMITプロトコルでリリースされます。
特に明記しない限り、QuickJSソースの著作権はFabrice BellardとCharlie Gordonに属します。
https://github.com/tc39/test262
https://tc39.github.io/ecma262/
現在のテールコール仕様は複雑すぎて、実際の利点が限られていると考えています。
https://bellard.org/libbf
iOSの下のquickjs-quickjsライブラリ
QuickJS -Android QuickJSライブラリのAndroid
QuickJS-RS RustのQuickJSライブラリ
QuickJSPP C ++ QuickJSライブラリ
Go-Quickjs GoのQuickJSライブラリ
txiki.js QuickJS、Libuv、および❤️で構築された小さなJavaScriptランタイム
QuickJS-Pascal QuickJS Freepascal / Delphi Bindings