quickjs/doc/quickjs.html

1255 lines
45 KiB
HTML
Raw Normal View History

2020-09-07 00:53:08 +08:00
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->
<head>
<title>QuickJS Javascript Engine</title>
<meta name="description" content="QuickJS Javascript Engine">
<meta name="keywords" content="QuickJS Javascript Engine">
<meta name="resource-type" content="document">
<meta name="distribution" content="global">
<meta name="Generator" content="makeinfo">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="#SEC_Contents" rel="contents" title="Table of Contents">
<style type="text/css">
<!--
a.summary-letter {text-decoration: none}
blockquote.indentedblock {margin-right: 0em}
blockquote.smallindentedblock {margin-right: 0em; font-size: smaller}
blockquote.smallquotation {font-size: smaller}
div.display {margin-left: 3.2em}
div.example {margin-left: 3.2em}
div.lisp {margin-left: 3.2em}
div.smalldisplay {margin-left: 3.2em}
div.smallexample {margin-left: 3.2em}
div.smalllisp {margin-left: 3.2em}
kbd {font-style: oblique}
pre.display {font-family: inherit}
pre.format {font-family: inherit}
pre.menu-comment {font-family: serif}
pre.menu-preformatted {font-family: serif}
pre.smalldisplay {font-family: inherit; font-size: smaller}
pre.smallexample {font-size: smaller}
pre.smallformat {font-family: inherit; font-size: smaller}
pre.smalllisp {font-size: smaller}
span.nolinebreak {white-space: nowrap}
span.roman {font-family: initial; font-weight: normal}
span.sansserif {font-family: sans-serif; font-weight: normal}
ul.no-bullet {list-style: none}
-->
</style>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body lang="en">
<h1 class="settitle" align="center">QuickJS Javascript Engine</h1>
<a name="SEC_Contents"></a>
<h2 class="contents-heading">Table of Contents</h2>
<div class="contents">
<ul class="no-bullet">
<li><a name="toc-Introduction" href="#Introduction">1 Introduction</a>
<ul class="no-bullet">
<li><a name="toc-Main-Features" href="#Main-Features">1.1 Main Features</a></li>
</ul></li>
<li><a name="toc-Usage" href="#Usage">2 Usage</a>
<ul class="no-bullet">
<li><a name="toc-Installation" href="#Installation">2.1 Installation</a></li>
<li><a name="toc-Quick-start" href="#Quick-start">2.2 Quick start</a></li>
<li><a name="toc-Command-line-options" href="#Command-line-options">2.3 Command line options</a>
<ul class="no-bullet">
<li><a name="toc-qjs-interpreter" href="#qjs-interpreter">2.3.1 <code>qjs</code> interpreter</a></li>
<li><a name="toc-qjsc-compiler" href="#qjsc-compiler">2.3.2 <code>qjsc</code> compiler</a></li>
</ul></li>
<li><a name="toc-qjscalc-application" href="#qjscalc-application">2.4 <code>qjscalc</code> application</a></li>
<li><a name="toc-Built_002din-tests" href="#Built_002din-tests">2.5 Built-in tests</a></li>
<li><a name="toc-Test262-_0028ECMAScript-Test-Suite_0029" href="#Test262-_0028ECMAScript-Test-Suite_0029">2.6 Test262 (ECMAScript Test Suite)</a></li>
</ul></li>
<li><a name="toc-Specifications" href="#Specifications">3 Specifications</a>
<ul class="no-bullet">
<li><a name="toc-Language-support" href="#Language-support">3.1 Language support</a>
<ul class="no-bullet">
<li><a name="toc-ES2019-support" href="#ES2019-support">3.1.1 ES2019 support</a></li>
<li><a name="toc-JSON" href="#JSON">3.1.2 JSON</a></li>
<li><a name="toc-ECMA402" href="#ECMA402">3.1.3 ECMA402</a></li>
<li><a name="toc-Extensions" href="#Extensions">3.1.4 Extensions</a></li>
<li><a name="toc-Mathematical-extensions" href="#Mathematical-extensions">3.1.5 Mathematical extensions</a></li>
</ul></li>
<li><a name="toc-Modules" href="#Modules">3.2 Modules</a></li>
<li><a name="toc-Standard-library" href="#Standard-library">3.3 Standard library</a>
<ul class="no-bullet">
<li><a name="toc-Global-objects" href="#Global-objects">3.3.1 Global objects</a></li>
<li><a name="toc-std-module" href="#std-module">3.3.2 <code>std</code> module</a></li>
<li><a name="toc-os-module" href="#os-module">3.3.3 <code>os</code> module</a></li>
</ul></li>
<li><a name="toc-QuickJS-C-API" href="#QuickJS-C-API">3.4 QuickJS C API</a>
<ul class="no-bullet">
<li><a name="toc-Runtime-and-contexts" href="#Runtime-and-contexts">3.4.1 Runtime and contexts</a></li>
<li><a name="toc-JSValue" href="#JSValue">3.4.2 JSValue</a></li>
<li><a name="toc-C-functions" href="#C-functions">3.4.3 C functions</a></li>
<li><a name="toc-Exceptions" href="#Exceptions">3.4.4 Exceptions</a></li>
<li><a name="toc-Script-evaluation" href="#Script-evaluation">3.4.5 Script evaluation</a></li>
<li><a name="toc-JS-Classes" href="#JS-Classes">3.4.6 JS Classes</a></li>
<li><a name="toc-C-Modules" href="#C-Modules">3.4.7 C Modules</a></li>
<li><a name="toc-Memory-handling" href="#Memory-handling">3.4.8 Memory handling</a></li>
<li><a name="toc-Execution-timeout-and-interrupts" href="#Execution-timeout-and-interrupts">3.4.9 Execution timeout and interrupts</a></li>
</ul></li>
</ul></li>
<li><a name="toc-Internals" href="#Internals">4 Internals</a>
<ul class="no-bullet">
<li><a name="toc-Bytecode" href="#Bytecode">4.1 Bytecode</a></li>
<li><a name="toc-Executable-generation" href="#Executable-generation">4.2 Executable generation</a>
<ul class="no-bullet">
<li><a name="toc-qjsc-compiler-1" href="#qjsc-compiler-1">4.2.1 <code>qjsc</code> compiler</a></li>
<li><a name="toc-Binary-JSON" href="#Binary-JSON">4.2.2 Binary JSON</a></li>
</ul></li>
<li><a name="toc-Runtime" href="#Runtime">4.3 Runtime</a>
<ul class="no-bullet">
<li><a name="toc-Strings" href="#Strings">4.3.1 Strings</a></li>
<li><a name="toc-Objects" href="#Objects">4.3.2 Objects</a></li>
<li><a name="toc-Atoms" href="#Atoms">4.3.3 Atoms</a></li>
<li><a name="toc-Numbers" href="#Numbers">4.3.4 Numbers</a></li>
<li><a name="toc-Garbage-collection" href="#Garbage-collection">4.3.5 Garbage collection</a></li>
<li><a name="toc-JSValue-1" href="#JSValue-1">4.3.6 JSValue</a></li>
<li><a name="toc-Function-call" href="#Function-call">4.3.7 Function call</a></li>
</ul></li>
<li><a name="toc-RegExp" href="#RegExp">4.4 RegExp</a></li>
<li><a name="toc-Unicode" href="#Unicode">4.5 Unicode</a></li>
<li><a name="toc-BigInt_002c-BigFloat_002c-BigDecimal" href="#BigInt_002c-BigFloat_002c-BigDecimal">4.6 BigInt, BigFloat, BigDecimal</a></li>
</ul></li>
<li><a name="toc-License" href="#License">5 License</a></li>
</ul>
</div>
<a name="Introduction"></a>
<h2 class="chapter">1 Introduction</h2>
<p>QuickJS is a small and embeddable Javascript engine. It supports the
upcoming ES2020 specification
<a name="DOCF1" href="#FOOT1"><sup>1</sup></a>
including modules, asynchronous generators, proxies and BigInt.
</p>
<p>It supports mathematical extensions such as big decimal float float
numbers (BigDecimal), big binary floating point numbers (BigFloat),
and operator overloading.
</p>
<a name="Main-Features"></a>
<h3 class="section">1.1 Main Features</h3>
<ul>
<li> Small and easily embeddable: just a few C files, no external dependency, 210 KiB of x86 code for a simple &ldquo;hello world&rdquo; program.
</li><li> Fast interpreter with very low startup time: runs the 69000 tests of the ECMAScript Test Suite<a name="DOCF2" href="#FOOT2"><sup>2</sup></a> in about 95 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
</li><li> Almost complete ES2019 support including modules, asynchronous
generators and full Annex B support (legacy web compatibility). Many
features from the upcoming ES2020 specification
<a name="DOCF3" href="#FOOT3"><sup>3</sup></a> are also supported.
</li><li> Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2019 features.
</li><li> Compile Javascript sources to executables with no external dependency.
</li><li> Garbage collection using reference counting (to reduce memory usage and have deterministic behavior) with cycle removal.
</li><li> Mathematical extensions: BigDecimal, BigFloat, operator overloading, bigint mode, math mode.
</li><li> Command line interpreter with contextual colorization and completion implemented in Javascript.
</li><li> Small built-in standard library with C library wrappers.
</li></ul>
<a name="Usage"></a>
<h2 class="chapter">2 Usage</h2>
<a name="Installation"></a>
<h3 class="section">2.1 Installation</h3>
<p>A Makefile is provided to compile the engine on Linux or MacOS/X. A
preliminary Windows support is available thru cross compilation on a
Linux host with the MingGW tools.
</p>
<p>Edit the top of the <code>Makefile</code> if you wish to select specific
options then run <code>make</code>.
</p>
<p>You can type <code>make install</code> as root if you wish to install the binaries and support files to
<code>/usr/local</code> (this is not necessary to use QuickJS).
</p>
<a name="Quick-start"></a>
<h3 class="section">2.2 Quick start</h3>
<p><code>qjs</code> is the command line interpreter (Read-Eval-Print Loop). You can pass
Javascript files and/or expressions as arguments to execute them:
</p>
<div class="example">
<pre class="example">./qjs examples/hello.js
</pre></div>
<p><code>qjsc</code> is the command line compiler:
</p>
<div class="example">
<pre class="example">./qjsc -o hello examples/hello.js
./hello
</pre></div>
<p>generates a <code>hello</code> executable with no external dependency.
</p>
<a name="Command-line-options"></a>
<h3 class="section">2.3 Command line options</h3>
<a name="qjs-interpreter"></a>
<h4 class="subsection">2.3.1 <code>qjs</code> interpreter</h4>
<pre class="verbatim">usage: qjs [options] [files]
</pre>
<p>Options are:
</p><dl compact="compact">
<dt><code>-h</code></dt>
<dt><code>--help</code></dt>
<dd><p>List options.
</p>
</dd>
<dt><code>-e <code>EXPR</code></code></dt>
<dt><code>--eval <code>EXPR</code></code></dt>
<dd><p>Evaluate EXPR.
</p>
</dd>
<dt><code>-i</code></dt>
<dt><code>--interactive</code></dt>
<dd><p>Go to interactive mode (it is not the default when files are provided on the command line).
</p>
</dd>
<dt><code>-m</code></dt>
<dt><code>--module</code></dt>
<dd><p>Load as ES6 module (default=autodetect). A module is autodetected if
the filename extension is <code>.mjs</code> or if the first keyword of the
source is <code>import</code>.
</p>
</dd>
<dt><code>--script</code></dt>
<dd><p>Load as ES6 script (default=autodetect).
</p>
</dd>
<dt><code>--bignum</code></dt>
<dd><p>Enable the bignum extensions: BigDecimal object, BigFloat object and
the <code>&quot;use bigint&quot;</code> and <code>&quot;use math&quot;</code> directives.
</p>
</dd>
</dl>
<p>Advanced options are:
</p>
<dl compact="compact">
<dt><code>--std</code></dt>
<dd><p>Make the <code>std</code> and <code>os</code> modules available to the loaded
script even if it is not a module.
</p>
</dd>
<dt><code>-d</code></dt>
<dt><code>--dump</code></dt>
<dd><p>Dump the memory usage stats.
</p>
</dd>
<dt><code>-q</code></dt>
<dt><code>--quit</code></dt>
<dd><p>just instantiate the interpreter and quit.
</p>
</dd>
</dl>
<a name="qjsc-compiler"></a>
<h4 class="subsection">2.3.2 <code>qjsc</code> compiler</h4>
<pre class="verbatim">usage: qjsc [options] [files]
</pre>
<p>Options are:
</p><dl compact="compact">
<dt><code>-c</code></dt>
<dd><p>Only output bytecode in a C file. The default is to output an executable file.
</p></dd>
<dt><code>-e</code></dt>
<dd><p>Output <code>main()</code> and bytecode in a C file. The default is to output an
executable file.
</p></dd>
<dt><code>-o output</code></dt>
<dd><p>Set the output filename (default = <samp>out.c</samp> or <samp>a.out</samp>).
</p>
</dd>
<dt><code>-N cname</code></dt>
<dd><p>Set the C name of the generated data.
</p>
</dd>
<dt><code>-m</code></dt>
<dd><p>Compile as Javascript module (default=autodetect).
</p>
</dd>
<dt><code>-M module_name[,cname]</code></dt>
<dd><p>Add initialization code for an external C module. See the
<code>c_module</code> example.
</p>
</dd>
<dt><code>-x</code></dt>
<dd><p>Byte swapped output (only used for cross compilation).
</p>
</dd>
<dt><code>-flto</code></dt>
<dd><p>Use link time optimization. The compilation is slower but the
executable is smaller and faster. This option is automatically set
when the <code>-fno-x</code> options are used.
</p>
</dd>
<dt><code>-fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise|bigint]</code></dt>
<dd><p>Disable selected language features to produce a smaller executable file.
</p>
</dd>
<dt><code>-fbignum</code></dt>
<dd><p>Enable the bignum extensions: BigDecimal object, BigFloat object and
the <code>&quot;use bigint&quot;</code> and <code>&quot;use math&quot;</code> directives.
</p>
</dd>
</dl>
<a name="qjscalc-application"></a>
<h3 class="section">2.4 <code>qjscalc</code> application</h3>
<p>The <code>qjscalc</code> application is a superset of the <code>qjs</code>
command line interpreter implementing a Javascript calculator with
arbitrarily large integer and floating point numbers, fractions,
complex numbers, polynomials and matrices. The source code is in
<samp>qjscalc.js</samp>. More documentation and a web version are available at
<a href="http://numcalc.com">http://numcalc.com</a>.
</p>
<a name="Built_002din-tests"></a>
<h3 class="section">2.5 Built-in tests</h3>
<p>Run <code>make test</code> to run the few built-in tests included in the
QuickJS archive.
</p>
<a name="Test262-_0028ECMAScript-Test-Suite_0029"></a>
<h3 class="section">2.6 Test262 (ECMAScript Test Suite)</h3>
<p>A test262 runner is included in the QuickJS archive. The test262 tests
can be installed in the QuickJS source directory with:
</p>
<div class="example">
<pre class="example">git clone https://github.com/tc39/test262.git test262
cd test262
patch -p1 &lt; ../tests/test262.patch
cd ..
</pre></div>
<p>The patch adds the implementation specific <code>harness</code> functions
and optimizes the inefficient RegExp character classes and Unicode
property escapes tests (the tests themselves are not modified, only a
slow string initialization function is optimized).
</p>
<p>The tests can be run with
</p><div class="example">
<pre class="example">make test2
</pre></div>
<p>The configuration files <code>test262.conf</code>
(resp. <code>test262o.conf</code> for the old ES5.1 tests<a name="DOCF4" href="#FOOT4"><sup>4</sup></a>))
contain the options to run the various tests. Tests can be excluded
based on features or filename.
</p>
<p>The file <code>test262_errors.txt</code> contains the current list of
errors. The runner displays a message when a new error appears or when
an existing error is corrected or modified. Use the <code>-u</code> option
to update the current list of errors (or <code>make test2-update</code>).
</p>
<p>The file <code>test262_report.txt</code> contains the logs of all the
tests. It is useful to have a clearer analysis of a particular
error. In case of crash, the last line corresponds to the failing
test.
</p>
<p>Use the syntax <code>./run-test262 -c test262.conf -f filename.js</code> to
run a single test. Use the syntax <code>./run-test262 -c test262.conf
N</code> to start testing at test number <code>N</code>.
</p>
<p>For more information, run <code>./run-test262</code> to see the command line
options of the test262 runner.
</p>
<p><code>run-test262</code> accepts the <code>-N</code> option to be invoked from
<code>test262-harness</code><a name="DOCF5" href="#FOOT5"><sup>5</sup></a>
thru <code>eshost</code>. Unless you want to compare QuickJS with other
engines under the same conditions, we do not recommend to run the
tests this way as it is much slower (typically half an hour instead of
about 100 seconds).
</p>
<a name="Specifications"></a>
<h2 class="chapter">3 Specifications</h2>
<a name="Language-support"></a>
<h3 class="section">3.1 Language support</h3>
<a name="ES2019-support"></a>
<h4 class="subsection">3.1.1 ES2019 support</h4>
<p>The ES2019 specification is almost fully supported including the Annex
B (legacy web compatibility) and the Unicode related features.
</p>
<p>The following features are not supported yet:
</p>
<ul>
<li> Realms (although the C API supports different runtimes and contexts)
</li><li> Tail calls<a name="DOCF6" href="#FOOT6"><sup>6</sup></a>
</li></ul>
<a name="JSON"></a>
<h4 class="subsection">3.1.2 JSON</h4>
<p>The JSON parser is currently more tolerant than the specification.
</p>
<a name="ECMA402"></a>
<h4 class="subsection">3.1.3 ECMA402</h4>
<p>ECMA402 (Internationalization API) is not supported.
</p>
<a name="Extensions"></a>
<h4 class="subsection">3.1.4 Extensions</h4>
<ul>
<li> The directive <code>&quot;use strip&quot;</code> indicates that the debug information (including the source code of the functions) should not be retained to save memory. As <code>&quot;use strict&quot;</code>, the directive can be global to a script or local to a function.
</li><li> The first line of a script beginning with <code>#!</code> is ignored.
</li></ul>
<a name="Mathematical-extensions"></a>
<h4 class="subsection">3.1.5 Mathematical extensions</h4>
<p>The mathematical extensions are fully backward compatible with
standard Javascript. See <code>jsbignum.pdf</code> for more information.
</p>
<ul>
<li> <code>BigDecimal</code> support: arbitrary large floating point numbers in base 10.
</li><li> <code>BigFloat</code> support: arbitrary large floating point numbers in base 2.
</li><li> Operator overloading.
</li><li> The directive <code>&quot;use bigint&quot;</code> enables the bigint mode where integers are <code>BigInt</code> by default.
</li><li> The directive <code>&quot;use math&quot;</code> enables the math mode where the division and power operators on integers produce fractions. Floating point literals are <code>BigFloat</code> by default and integers are <code>BigInt</code> by default.
</li></ul>
<a name="Modules"></a>
<h3 class="section">3.2 Modules</h3>
<p>ES6 modules are fully supported. The default name resolution is the
following:
</p>
<ul>
<li> Module names with a leading <code>.</code> or <code>..</code> are relative
to the current module path.
</li><li> Module names without a leading <code>.</code> or <code>..</code> are system
modules, such as <code>std</code> or <code>os</code>.
</li><li> Module names ending with <code>.so</code> are native modules using the
QuickJS C API.
</li></ul>
<a name="Standard-library"></a>
<h3 class="section">3.3 Standard library</h3>
<p>The standard library is included by default in the command line
interpreter. It contains the two modules <code>std</code> and <code>os</code> and
a few global objects.
</p>
<a name="Global-objects"></a>
<h4 class="subsection">3.3.1 Global objects</h4>
<dl compact="compact">
<dt><code>scriptArgs</code></dt>
<dd><p>Provides the command line arguments. The first argument is the script name.
</p></dd>
<dt><code>print(...args)</code></dt>
<dd><p>Print the arguments separated by spaces and a trailing newline.
</p></dd>
<dt><code>console.log(...args)</code></dt>
<dd><p>Same as print().
</p>
</dd>
</dl>
<a name="std-module"></a>
<h4 class="subsection">3.3.2 <code>std</code> module</h4>
<p>The <code>std</code> module provides wrappers to the libc <samp>stdlib.h</samp>
and <samp>stdio.h</samp> and a few other utilities.
</p>
<p>Available exports:
</p>
<dl compact="compact">
<dt><code>exit(n)</code></dt>
<dd><p>Exit the process.
</p>
</dd>
<dt><code>evalScript(str, options = undefined)</code></dt>
<dd><p>Evaluate the string <code>str</code> as a script (global
eval). <code>options</code> is an optional object containing the following
optional properties:
</p>
<dl compact="compact">
<dt><code>backtrace_barrier</code></dt>
<dd><p>Boolean (default = false). If true, error backtraces do not list the
stack frames below the evalScript.
</p></dd>
</dl>
</dd>
<dt><code>loadScript(filename)</code></dt>
<dd><p>Evaluate the file <code>filename</code> as a script (global eval).
</p>
</dd>
<dt><code>Error(errno)</code></dt>
<dd>
<p><code>std.Error</code> constructor. Error instances contain the field
<code>errno</code> (error code) and <code>message</code> (result of
<code>std.Error.strerror(errno)</code>).
</p>
<p>The constructor contains the following fields:
</p>
<dl compact="compact">
<dt><code>EINVAL</code></dt>
<dt><code>EIO</code></dt>
<dt><code>EACCES</code></dt>
<dt><code>EEXIST</code></dt>
<dt><code>ENOSPC</code></dt>
<dt><code>ENOSYS</code></dt>
<dt><code>EBUSY</code></dt>
<dt><code>ENOENT</code></dt>
<dt><code>EPERM</code></dt>
<dt><code>EPIPE</code></dt>
<dd><p>Integer value of common errors (additional error codes may be defined).
</p></dd>
<dt><code>strerror(errno)</code></dt>
<dd><p>Return a string that describes the error <code>errno</code>.
</p></dd>
</dl>
</dd>
<dt><code>open(filename, flags)</code></dt>
<dd><p>Open a file (wrapper to the libc <code>fopen()</code>). Throws
<code>std.Error</code> in case of I/O error.
</p>
</dd>
<dt><code>popen(command, flags)</code></dt>
<dd><p>Open a process by creating a pipe (wrapper to the libc <code>popen()</code>). Throws
<code>std.Error</code> in case of I/O error.
</p>
</dd>
<dt><code>fdopen(fd, flags)</code></dt>
<dd><p>Open a file from a file handle (wrapper to the libc
<code>fdopen()</code>). Throws <code>std.Error</code> in case of I/O error.
</p>
</dd>
<dt><code>tmpfile()</code></dt>
<dd><p>Open a temporary file. Throws <code>std.Error</code> in case of I/O error.
</p>
</dd>
<dt><code>puts(str)</code></dt>
<dd><p>Equivalent to <code>std.out.puts(str)</code>.
</p>
</dd>
<dt><code>printf(fmt, ...args)</code></dt>
<dd><p>Equivalent to <code>std.out.printf(fmt, ...args)</code>
</p>
</dd>
<dt><code>sprintf(fmt, ...args)</code></dt>
<dd><p>Equivalent to the libc sprintf().
</p>
</dd>
<dt><code>in</code></dt>
<dt><code>out</code></dt>
<dt><code>err</code></dt>
<dd><p>Wrappers to the libc file <code>stdin</code>, <code>stdout</code>, <code>stderr</code>.
</p>
</dd>
<dt><code>SEEK_SET</code></dt>
<dt><code>SEEK_CUR</code></dt>
<dt><code>SEEK_END</code></dt>
<dd><p>Constants for seek().
</p>
</dd>
<dt><code>gc()</code></dt>
<dd><p>Manually invoke the cycle removal algorithm. The cycle removal
algorithm is automatically started when needed, so this function is
useful in case of specific memory constraints or for testing.
</p>
</dd>
<dt><code>getenv(name)</code></dt>
<dd><p>Return the value of the environment variable <code>name</code> or
<code>undefined</code> if it is not defined.
</p>
</dd>
<dt><code>urlGet(url, options = undefined)</code></dt>
<dd>
<p>Download <code>url</code> using the <samp>curl</samp> command line
utility. <code>options</code> is an optional object containing the following
optional properties:
</p>
<dl compact="compact">
<dt><code>binary</code></dt>
<dd><p>Boolean (default = false). If true, the response is an ArrayBuffer
instead of a string. When a string is returned, the data is assumed
to be UTF-8 encoded.
</p>
</dd>
<dt><code>full</code></dt>
<dd><p>Boolean (default = false). If true, return the an object contains
the properties <code>response</code> (response content),
<code>responseHeaders</code> (headers separated by CRLF), <code>status</code>
(status code). If <code>full</code> is false, only the response is
returned if the status is between 200 and 299. Otherwise an
<code>std.Error</code> exception is raised.
</p>
</dd>
</dl>
</dd>
</dl>
<p>FILE prototype:
</p>
<dl compact="compact">
<dt><code>close()</code></dt>
<dd><p>Close the file.
</p></dd>
<dt><code>puts(str)</code></dt>
<dd><p>Outputs the string with the UTF-8 encoding.
</p></dd>
<dt><code>printf(fmt, ...args)</code></dt>
<dd><p>Formatted printf, same formats as the libc printf.
</p></dd>
<dt><code>flush()</code></dt>
<dd><p>Flush the buffered file.
</p></dd>
<dt><code>seek(offset, whence)</code></dt>
<dd><p>Seek to a give file position (whence is <code>std.SEEK_*</code>). Throws a
<code>std.Error</code> in case of I/O error.
</p></dd>
<dt><code>tell()</code></dt>
<dd><p>Return the current file position.
</p></dd>
<dt><code>eof()</code></dt>
<dd><p>Return true if end of file.
</p></dd>
<dt><code>fileno()</code></dt>
<dd><p>Return the associated OS handle.
</p>
</dd>
<dt><code>read(buffer, position, length)</code></dt>
<dd><p>Read <code>length</code> bytes from the file to the ArrayBuffer <code>buffer</code> at byte
position <code>position</code> (wrapper to the libc <code>fread</code>).
</p>
</dd>
<dt><code>write(buffer, position, length)</code></dt>
<dd><p>Write <code>length</code> bytes to the file from the ArrayBuffer <code>buffer</code> at byte
position <code>position</code> (wrapper to the libc <code>fread</code>).
</p>
</dd>
<dt><code>getline()</code></dt>
<dd><p>Return the next line from the file, assuming UTF-8 encoding, excluding
the trailing line feed.
</p>
</dd>
<dt><code>readAsString(max_size = undefined)</code></dt>
<dd><p>Read <code>max_size</code> bytes from the file and return them as a string
assuming UTF-8 encoding. If <code>max_size</code> is not present, the file
is read up its end.
</p>
</dd>
<dt><code>getByte()</code></dt>
<dd><p>Return the next byte from the file. Return -1 if the end of file is reached.
</p>
</dd>
<dt><code>putByte(c)</code></dt>
<dd><p>Write one byte to the file.
</p></dd>
</dl>
<a name="os-module"></a>
<h4 class="subsection">3.3.3 <code>os</code> module</h4>
<p>The <code>os</code> module provides Operating System specific functions:
</p>
<ul>
<li> low level file access
</li><li> signals
</li><li> timers
</li><li> asynchronous I/O
</li></ul>
<p>The OS functions usually return 0 if OK or an OS specific negative
error code.
</p>
<p>Available exports:
</p>
<dl compact="compact">
<dt><code>open(filename, flags, mode = 0o666)</code></dt>
<dd><p>Open a file. Return a handle or &lt; 0 if error.
</p>
</dd>
<dt><code>O_RDONLY</code></dt>
<dt><code>O_WRONLY</code></dt>
<dt><code>O_RDWR</code></dt>
<dt><code>O_APPEND</code></dt>
<dt><code>O_CREAT</code></dt>
<dt><code>O_EXCL</code></dt>
<dt><code>O_TRUNC</code></dt>
<dd><p>POSIX open flags.
</p>
</dd>
<dt><code>O_TEXT</code></dt>
<dd><p>(Windows specific). Open the file in text mode. The default is binary mode.
</p>
</dd>
<dt><code>close(fd)</code></dt>
<dd><p>Close the file handle <code>fd</code>.
</p>
</dd>
<dt><code>seek(fd, offset, whence)</code></dt>
<dd><p>Seek in the file. Use <code>std.SEEK_*</code> for <code>whence</code>.
</p>
</dd>
<dt><code>read(fd, buffer, offset, length)</code></dt>
<dd><p>Read <code>length</code> bytes from the file handle <code>fd</code> to the
ArrayBuffer <code>buffer</code> at byte position <code>offset</code>.
Return the number of read bytes or &lt; 0 if error.
</p>
</dd>
<dt><code>write(fd, buffer, offset, length)</code></dt>
<dd><p>Write <code>length</code> bytes to the file handle <code>fd</code> from the
ArrayBuffer <code>buffer</code> at byte position <code>offset</code>.
Return the number of written bytes or &lt; 0 if error.
</p>
</dd>
<dt><code>isatty(fd)</code></dt>
<dd><p>Return <code>true</code> is <code>fd</code> is a TTY (terminal) handle.
</p>
</dd>
<dt><code>ttyGetWinSize(fd)</code></dt>
<dd><p>Return the TTY size as <code>[width, height]</code> or <code>null</code> if not available.
</p>
</dd>
<dt><code>ttySetRaw(fd)</code></dt>
<dd><p>Set the TTY in raw mode.
</p>
</dd>
<dt><code>remove(filename)</code></dt>
<dd><p>Remove a file. Return 0 if OK or &lt; 0 if error.
</p>
</dd>
<dt><code>rename(oldname, newname)</code></dt>
<dd><p>Rename a file. Return 0 if OK or &lt; 0 if error.
</p>
</dd>
<dt><code>realpath(path)</code></dt>
<dd><p>Return <code>[str, err]</code> where <code>str</code> is the canonicalized absolute
pathname of <code>path</code> and <code>err</code> the error code.
</p>
</dd>
<dt><code>getcwd()</code></dt>
<dd><p>Return <code>[str, err]</code> where <code>str</code> is the current working directory
and <code>err</code> the error code.
</p>
</dd>
<dt><code>mkdir(path, mode = 0o777)</code></dt>
<dd><p>Create a directory at <code>path</code>. Return the error code.
</p>
</dd>
<dt><code>stat(path)</code></dt>
<dt><code>lstat(path)</code></dt>
<dd>
<p>Return <code>[obj, err]</code> where <code>obj</code> is an object containing the
file status of <code>path</code>. <code>err</code> is the error code. The
following fields are defined in <code>obj</code>: dev, ino, mode, nlink,
uid, gid, rdev, size, blocks, atime, mtime, ctime. The times are
specified in milliseconds since 1970. <code>lstat()</code> is the same as
<code>stat()</code> excepts that it returns information about the link
itself.
</p>
</dd>
<dt><code>S_IFMT</code></dt>
<dt><code>S_IFIFO</code></dt>
<dt><code>S_IFCHR</code></dt>
<dt><code>S_IFDIR</code></dt>
<dt><code>S_IFBLK</code></dt>
<dt><code>S_IFREG</code></dt>
<dt><code>S_IFSOCK</code></dt>
<dt><code>S_IFLNK</code></dt>
<dt><code>S_ISGID</code></dt>
<dt><code>S_ISUID</code></dt>
<dd><p>Constants to interpret the <code>mode</code> property returned by
<code>stat()</code>. They have the same value as in the C system header
<samp>sys/stat.h</samp>.
</p>
</dd>
<dt><code>utimes(path, atime, mtime)</code></dt>
<dd><p>Change the access and modification times of the file <code>path</code>. The
times are specified in milliseconds since 1970.
</p>
</dd>
<dt><code>symlink(target, linkpath)</code></dt>
<dd><p>Create a link at <code>linkpath</code> containing the string <code>target</code>.
</p>
</dd>
<dt><code>readlink(path)</code></dt>
<dd><p>Return <code>[str, err]</code> where <code>str</code> is the link target and <code>err</code>
the error code.
</p>
</dd>
<dt><code>readdir(path)</code></dt>
<dd><p>Return <code>[array, err]</code> where <code>array</code> is an array of strings
containing the filenames of the directory <code>path</code>. <code>err</code> is
the error code.
</p>
</dd>
<dt><code>setReadHandler(fd, func)</code></dt>
<dd><p>Add a read handler to the file handle <code>fd</code>. <code>func</code> is called
each time there is data pending for <code>fd</code>. A single read handler
per file handle is supported. Use <code>func = null</code> to remove the
handler.
</p>
</dd>
<dt><code>setWriteHandler(fd, func)</code></dt>
<dd><p>Add a write handler to the file handle <code>fd</code>. <code>func</code> is
called each time data can be written to <code>fd</code>. A single write
handler per file handle is supported. Use <code>func = null</code> to remove
the handler.
</p>
</dd>
<dt><code>signal(signal, func)</code></dt>
<dd><p>Call the function <code>func</code> when the signal <code>signal</code>
happens. Only a single handler per signal number is supported. Use
<code>null</code> to set the default handler or <code>undefined</code> to ignore
the signal.
</p>
</dd>
<dt><code>SIGINT</code></dt>
<dt><code>SIGABRT</code></dt>
<dt><code>SIGFPE</code></dt>
<dt><code>SIGILL</code></dt>
<dt><code>SIGSEGV</code></dt>
<dt><code>SIGTERM</code></dt>
<dd><p>POSIX signal numbers.
</p>
</dd>
<dt><code>kill(pid, sig)</code></dt>
<dd><p>Send the signal <code>sig</code> to the process <code>pid</code>.
</p>
</dd>
<dt><code>exec(args[, options])</code></dt>
<dd><p>Execute a process with the arguments <code>args</code>. <code>options</code> is an
object containing optional parameters:
</p>
<dl compact="compact">
<dt><code>block</code></dt>
<dd><p>Boolean (default = true). If true, wait until the process is
terminated. In this case, <code>exec</code> return the exit code if positive
or the negated signal number if the process was interrupted by a
signal. If false, do not block and return the process id of the child.
</p>
</dd>
<dt><code>usePath</code></dt>
<dd><p>Boolean (default = true). If true, the file is searched in the
<code>PATH</code> environment variable.
</p>
</dd>
<dt><code>file</code></dt>
<dd><p>String (default = <code>args[0]</code>). Set the file to be executed.
</p>
</dd>
<dt><code>cwd</code></dt>
<dd><p>String. If present, set the working directory of the new process.
</p>
</dd>
<dt><code>stdin</code></dt>
<dt><code>stdout</code></dt>
<dt><code>stderr</code></dt>
<dd><p>If present, set the handle in the child for stdin, stdout or stderr.
</p>
</dd>
</dl>
</dd>
<dt><code>waitpid(pid, options)</code></dt>
<dd><p><code>waitpid</code> Unix system call. Return the array <code>[ret, status]</code>.
</p>
</dd>
<dt><code>WNOHANG</code></dt>
<dd><p>Constant for the <code>options</code> argument of <code>waitpid</code>.
</p>
</dd>
<dt><code>dup(fd)</code></dt>
<dd><p><code>dup</code> Unix system call.
</p>
</dd>
<dt><code>dup2(oldfd, newfd)</code></dt>
<dd><p><code>dup2</code> Unix system call.
</p>
</dd>
<dt><code>pipe()</code></dt>
<dd><p><code>pipe</code> Unix system call. Return two handles as <code>[read_fd,
write_fd]</code> or null in case of error.
</p>
</dd>
<dt><code>sleep(delay_ms)</code></dt>
<dd><p>Sleep during <code>delay_ms</code> milliseconds.
</p>
</dd>
<dt><code>setTimeout(func, delay)</code></dt>
<dd><p>Call the function <code>func</code> after <code>delay</code> ms. Return a handle
to the timer.
</p>
</dd>
<dt><code>clearTimeout(handle)</code></dt>
<dd><p>Cancel a timer.
</p>
</dd>
<dt><code>platform</code></dt>
<dd><p>Return a string representing the platform: <code>&quot;linux&quot;</code>, <code>&quot;darwin&quot;</code>,
<code>&quot;win32&quot;</code> or <code>&quot;js&quot;</code>.
</p>
</dd>
</dl>
<a name="QuickJS-C-API"></a>
<h3 class="section">3.4 QuickJS C API</h3>
<p>The C API was designed to be simple and efficient. The C API is
defined in the header <code>quickjs.h</code>.
</p>
<a name="Runtime-and-contexts"></a>
<h4 class="subsection">3.4.1 Runtime and contexts</h4>
<p><code>JSRuntime</code> represents a Javascript runtime corresponding to an
object heap. Several runtimes can exist at the same time but they
cannot exchange objects. Inside a given runtime, no multi-threading is
supported.
</p>
<p><code>JSContext</code> represents a Javascript context (or Realm). Each
JSContext has its own global objects and system objects. There can be
several JSContexts per JSRuntime and they can share objects, similar
to frames of the same origin sharing Javascript objects in a
web browser.
</p>
<a name="JSValue"></a>
<h4 class="subsection">3.4.2 JSValue</h4>
<p><code>JSValue</code> represents a Javascript value which can be a primitive
type or an object. Reference counting is used, so it is important to
explicitly duplicate (<code>JS_DupValue()</code>, increment the reference
count) or free (<code>JS_FreeValue()</code>, decrement the reference count)
JSValues.
</p>
<a name="C-functions"></a>
<h4 class="subsection">3.4.3 C functions</h4>
<p>C functions can be created with
<code>JS_NewCFunction()</code>. <code>JS_SetPropertyFunctionList()</code> is a
shortcut to easily add functions, setters and getters properties to a
given object.
</p>
<p>Unlike other embedded Javascript engines, there is no implicit stack,
so C functions get their parameters as normal C parameters. As a
general rule, C functions take constant <code>JSValue</code>s as parameters
(so they don&rsquo;t need to free them) and return a newly allocated (=live)
<code>JSValue</code>.
</p>
<a name="Exceptions"></a>
<h4 class="subsection">3.4.4 Exceptions</h4>
<p>Exceptions: most C functions can return a Javascript exception. It
must be explicitly tested and handled by the C code. The specific
<code>JSValue</code> <code>JS_EXCEPTION</code> indicates that an exception
occurred. The actual exception object is stored in the
<code>JSContext</code> and can be retrieved with <code>JS_GetException()</code>.
</p>
<a name="Script-evaluation"></a>
<h4 class="subsection">3.4.5 Script evaluation</h4>
<p>Use <code>JS_Eval()</code> to evaluate a script or module source.
</p>
<p>If the script or module was compiled to bytecode with <code>qjsc</code>, it
can be evaluated by calling <code>js_std_eval_binary()</code>. The advantage
is that no compilation is needed so it is faster and smaller because
the compiler can be removed from the executable if no <code>eval</code> is
required.
</p>
<p>Note: the bytecode format is linked to a given QuickJS
version. Moreover, no security check is done before its
execution. Hence the bytecode should not be loaded from untrusted
sources. That&rsquo;s why there is no option to output the bytecode to a
binary file in <code>qjsc</code>.
</p>
<a name="JS-Classes"></a>
<h4 class="subsection">3.4.6 JS Classes</h4>
<p>C opaque data can be attached to a Javascript object. The type of the
C opaque data is determined with the class ID (<code>JSClassID</code>) of
the object. Hence the first step is to register a new class ID and JS
class (<code>JS_NewClassID()</code>, <code>JS_NewClass()</code>). Then you can
create objects of this class with <code>JS_NewObjectClass()</code> and get or
set the C opaque point with
<code>JS_GetOpaque()</code>/<code>JS_SetOpaque()</code>.
</p>
<p>When defining a new JS class, it is possible to declare a finalizer
which is called when the object is destroyed. A <code>gc_mark</code> method
can be provided so that the cycle removal algorithm can find the other
objects referenced by this object. Other methods are available to
define exotic object behaviors.
</p>
<p>The Class ID are globally allocated (i.e. for all runtimes). The
JSClass are allocated per <code>JSRuntime</code>. <code>JS_SetClassProto()</code>
is used to define a prototype for a given class in a given
JSContext. <code>JS_NewObjectClass()</code> sets this prototype in the
created object.
</p>
<p>Examples are available in <samp>quickjs-libc.c</samp>.
</p>
<a name="C-Modules"></a>
<h4 class="subsection">3.4.7 C Modules</h4>
<p>Native ES6 modules are supported and can be dynamically or statically
linked. Look at the <samp>test_bjson</samp> and <samp>bjson.so</samp>
examples. The standard library <samp>quickjs-libc.c</samp> is also a good example
of a native module.
</p>
<a name="Memory-handling"></a>
<h4 class="subsection">3.4.8 Memory handling</h4>
<p>Use <code>JS_SetMemoryLimit()</code> to set a global memory allocation limit
to a given JSRuntime.
</p>
<p>Custom memory allocation functions can be provided with
<code>JS_NewRuntime2()</code>.
</p>
<p>The maximum system stack size can be set with <code>JS_SetMaxStackSize()</code>.
</p>
<a name="Execution-timeout-and-interrupts"></a>
<h4 class="subsection">3.4.9 Execution timeout and interrupts</h4>
<p>Use <code>JS_SetInterruptHandler()</code> to set a callback which is
regularly called by the engine when it is executing code. This
callback can be used to implement an execution timeout.
</p>
<p>It is used by the command line interpreter to implement a
<code>Ctrl-C</code> handler.
</p>
<a name="Internals"></a>
<h2 class="chapter">4 Internals</h2>
<a name="Bytecode"></a>
<h3 class="section">4.1 Bytecode</h3>
<p>The compiler generates bytecode directly with no intermediate
representation such as a parse tree, hence it is very fast. Several
optimizations passes are done over the generated bytecode.
</p>
<p>A stack-based bytecode was chosen because it is simple and generates
compact code.
</p>
<p>For each function, the maximum stack size is computed at compile time so that
no runtime stack overflow tests are needed.
</p>
<p>A separate compressed line number table is maintained for the debug
information.
</p>
<p>Access to closure variables is optimized and is almost as fast as local
variables.
</p>
<p>Direct <code>eval</code> in strict mode is optimized.
</p>
<a name="Executable-generation"></a>
<h3 class="section">4.2 Executable generation</h3>
<a name="qjsc-compiler-1"></a>
<h4 class="subsection">4.2.1 <code>qjsc</code> compiler</h4>
<p>The <code>qjsc</code> compiler generates C sources from Javascript files. By
default the C sources are compiled with the system compiler
(<code>gcc</code> or <code>clang</code>).
</p>
<p>The generated C source contains the bytecode of the compiled functions
or modules. If a full complete executable is needed, it also
contains a <code>main()</code> function with the necessary C code to initialize the
Javascript engine and to load and execute the compiled functions and
modules.
</p>
<p>Javascript code can be mixed with C modules.
</p>
<p>In order to have smaller executables, specific Javascript features can
be disabled, in particular <code>eval</code> or the regular expressions. The
code removal relies on the Link Time Optimization of the system
compiler.
</p>
<a name="Binary-JSON"></a>
<h4 class="subsection">4.2.2 Binary JSON</h4>
<p><code>qjsc</code> works by compiling scripts or modules and then serializing
them to a binary format. A subset of this format (without functions or
modules) can be used as binary JSON. The example <samp>test_bjson.js</samp>
shows how to use it.
</p>
<p>Warning: the binary JSON format may change without notice, so it
should not be used to store persistent data. The <samp>test_bjson.js</samp>
example is only used to test the binary object format functions.
</p>
<a name="Runtime"></a>
<h3 class="section">4.3 Runtime</h3>
<a name="Strings"></a>
<h4 class="subsection">4.3.1 Strings</h4>
<p>Strings are stored either as an 8 bit or a 16 bit array of
characters. Hence random access to characters is always fast.
</p>
<p>The C API provides functions to convert Javascript Strings to C UTF-8 encoded
strings. The most common case where the Javascript string contains
only ASCII characters involves no copying.
</p>
<a name="Objects"></a>
<h4 class="subsection">4.3.2 Objects</h4>
<p>The object shapes (object prototype, property names and flags) are shared
between objects to save memory.
</p>
<p>Arrays with no holes (except at the end of the array) are optimized.
</p>
<p>TypedArray accesses are optimized.
</p>
<a name="Atoms"></a>
<h4 class="subsection">4.3.3 Atoms</h4>
<p>Object property names and some strings are stored as Atoms (unique
strings) to save memory and allow fast comparison. Atoms are
represented as a 32 bit integer. Half of the atom range is reserved for
immediate integer literals from <em>0</em> to <em>2^{31}-1</em>.
</p>
<a name="Numbers"></a>
<h4 class="subsection">4.3.4 Numbers</h4>
<p>Numbers are represented either as 32-bit signed integers or 64-bit IEEE-754
floating point values. Most operations have fast paths for the 32-bit
integer case.
</p>
<a name="Garbage-collection"></a>
<h4 class="subsection">4.3.5 Garbage collection</h4>
<p>Reference counting is used to free objects automatically and
deterministically. A separate cycle removal pass is done when the allocated
memory becomes too large. The cycle removal algorithm only uses the
reference counts and the object content, so no explicit garbage
collection roots need to be manipulated in the C code.
</p>
<a name="JSValue-1"></a>
<h4 class="subsection">4.3.6 JSValue</h4>
<p>It is a Javascript value which can be a primitive type (such as
Number, String, ...) or an Object. NaN boxing is used in the 32-bit version
to store 64-bit floating point numbers. The representation is
optimized so that 32-bit integers and reference counted values can be
efficiently tested.
</p>
<p>In 64-bit code, JSValue are 128-bit large and no NaN boxing is used. The
rationale is that in 64-bit code memory usage is less critical.
</p>
<p>In both cases (32 or 64 bits), JSValue exactly fits two CPU registers,
so it can be efficiently returned by C functions.
</p>
<a name="Function-call"></a>
<h4 class="subsection">4.3.7 Function call</h4>
<p>The engine is optimized so that function calls are fast. The system
stack holds the Javascript parameters and local variables.
</p>
<a name="RegExp"></a>
<h3 class="section">4.4 RegExp</h3>
<p>A specific regular expression engine was developed. It is both small
and efficient and supports all the ES2020 features including the
Unicode properties. As the Javascript compiler, it directly generates
bytecode without a parse tree.
</p>
<p>Backtracking with an explicit stack is used so that there is no
recursion on the system stack. Simple quantifiers are specifically
optimized to avoid recursions.
</p>
<p>Infinite recursions coming from quantifiers with empty terms are
avoided.
</p>
<p>The full regexp library weights about 15 KiB (x86 code), excluding the
Unicode library.
</p>
<a name="Unicode"></a>
<h3 class="section">4.5 Unicode</h3>
<p>A specific Unicode library was developed so that there is no
dependency on an external large Unicode library such as ICU. All the
Unicode tables are compressed while keeping a reasonable access
speed.
</p>
<p>The library supports case conversion, Unicode normalization, Unicode
script queries, Unicode general category queries and all Unicode
binary properties.
</p>
<p>The full Unicode library weights about 45 KiB (x86 code).
</p>
<a name="BigInt_002c-BigFloat_002c-BigDecimal"></a>
<h3 class="section">4.6 BigInt, BigFloat, BigDecimal</h3>
<p>BigInt, BigFloat and BigDecimal are implemented with the <code>libbf</code>
library<a name="DOCF7" href="#FOOT7"><sup>7</sup></a>. It weights about 90
KiB (x86 code) and provides arbitrary precision IEEE 754 floating
point operations and transcendental functions with exact rounding.
</p>
<a name="License"></a>
<h2 class="chapter">5 License</h2>
<p>QuickJS is released under the MIT license.
</p>
<p>Unless otherwise specified, the QuickJS sources are copyright Fabrice
Bellard and Charlie Gordon.
</p>
<div class="footnote">
<hr>
<h4 class="footnotes-heading">Footnotes</h4>
<h3><a name="FOOT1" href="#DOCF1">(1)</a></h3>
<p><a href="https://www.ecma-international.org/ecma-262/10.0">https://www.ecma-international.org/ecma-262/10.0</a></p>
<h3><a name="FOOT2" href="#DOCF2">(2)</a></h3>
<p><a href="https://github.com/tc39/test262">https://github.com/tc39/test262</a></p>
<h3><a name="FOOT3" href="#DOCF3">(3)</a></h3>
<p><a href="https://tc39.github.io/ecma262/">https://tc39.github.io/ecma262/</a></p>
<h3><a name="FOOT4" href="#DOCF4">(4)</a></h3>
<p>The old
ES5.1 tests can be extracted with <code>git clone --single-branch
--branch es5-tests https://github.com/tc39/test262.git test262o</code></p>
<h3><a name="FOOT5" href="#DOCF5">(5)</a></h3>
<p><a href="https://github.com/bterlson/test262-harness">https://github.com/bterlson/test262-harness</a></p>
<h3><a name="FOOT6" href="#DOCF6">(6)</a></h3>
<p>We believe the current specification of tails calls is too complicated and presents limited practical interests.</p>
<h3><a name="FOOT7" href="#DOCF7">(7)</a></h3>
<p><a href="https://bellard.org/libbf">https://bellard.org/libbf</a></p>
</div>
<hr>
</body>
</html>