mirror of
https://github.com/bellard/quickjs.git
synced 2024-11-24 14:48:12 +08:00
2020-03-16 release
This commit is contained in:
parent
0e8fffd4de
commit
383e2b06c8
11
Changelog
11
Changelog
@ -1,3 +1,14 @@
|
||||
2020-03-16:
|
||||
|
||||
- reworked error handling in std and os libraries: suppressed I/O
|
||||
exceptions in std FILE functions and return a positive errno value
|
||||
when it is explicit
|
||||
- output exception messages to stderr
|
||||
- added std.loadFile(), std.strerror(), std.FILE.prototype.tello()
|
||||
- added JS_GetRuntimeOpaque(), JS_SetRuntimeOpaque(), JS_NewUint32()
|
||||
- updated to Unicode 13.0.0
|
||||
- misc bug fixes
|
||||
|
||||
2020-01-19:
|
||||
|
||||
- keep CONFIG_BIGNUM in the makefile
|
||||
|
5
TODO
5
TODO
@ -73,5 +73,6 @@ REPL:
|
||||
Test262o: 0/11262 errors, 463 excluded
|
||||
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
||||
|
||||
Test262: 17/69942 errors, 855 excluded, 581 skipped
|
||||
test262 commit: 28b4fcca4b1b1d278dfe0cc0e69c7d9d59b31aab
|
||||
Test262: 22/70040 errors, 860 excluded, 581 skipped
|
||||
test262 commit: 25c9e334d301944537215caba1d7f44319f3e0da
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ -->
|
||||
<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Javascript Bignum Extensions</title>
|
||||
|
||||
<meta name="description" content="Javascript Bignum Extensions">
|
||||
@ -10,6 +9,7 @@
|
||||
<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">
|
||||
<!--
|
||||
@ -121,7 +121,7 @@ changes were done in order to simplify the implementation.
|
||||
<ul>
|
||||
<li> <code>with operators from</code> is not supported. Operator overloading is always enabled.
|
||||
|
||||
</li><li> The dispatch is not based on a static <code>[[OperatorSet]]</code> field in all instances. Instead, a dynamic lookup the of the <code>Symbol.operatorSet</code> property is done. This property is typically added in the prototype of each object.
|
||||
</li><li> The dispatch is not based on a static <code>[[OperatorSet]]</code> field in all instances. Instead, a dynamic lookup of the <code>Symbol.operatorSet</code> property is done. This property is typically added in the prototype of each object.
|
||||
|
||||
</li><li> <code>Operators.create(...dictionaries)</code> is used to create a new OperatorSet object. The <code>Operators</code> function is supported as an helper to be closer to the TC39 proposal.
|
||||
|
||||
@ -194,7 +194,7 @@ raised if <em>a < 0</em>.
|
||||
<h3 class="section">4.1 Introduction</h3>
|
||||
|
||||
<p>This extension adds the <code>BigFloat</code> primitive type. The
|
||||
<code>BigFloat</code> type represents floating point numbers are in base 2
|
||||
<code>BigFloat</code> type represents floating point numbers in base 2
|
||||
with the IEEE 754 semantics. A floating
|
||||
point number is represented as a sign, mantissa and exponent. The
|
||||
special values <code>NaN</code>, <code>+/-Infinity</code>, <code>+0</code> and <code>-0</code>
|
||||
@ -216,15 +216,13 @@ point environment is used.
|
||||
<code>RNDN</code> (“round to nearest with ties to even”)<a name="DOCF1" href="#FOOT1"><sup>1</sup></a>. The status flags of the global environment cannot be
|
||||
read<a name="DOCF2" href="#FOOT2"><sup>2</sup></a>. The precision of the global environment is
|
||||
<code>BigFloatEnv.prec</code>. The number of exponent bits of the global
|
||||
environment is <code>BigFloatEnv.expBits</code>. If <code>BigFloatEnv.expBits</code> is
|
||||
strictly smaller than the maximum allowed number of exponent bits
|
||||
(<code>BigFloatEnv.expBitsMax</code>), then the global environment subnormal
|
||||
flag is set to <code>true</code>. Otherwise it is set to <code>false</code>;
|
||||
environment is <code>BigFloatEnv.expBits</code>. The global environment
|
||||
subnormal flag is set to <code>true</code>.
|
||||
</p>
|
||||
<p>For example, <code>prec = 53</code> and <code> expBits = 11</code> give exactly
|
||||
the same precision as the IEEE 754 64 bit floating point. The
|
||||
<p>For example, <code>prec = 53</code> and <code> expBits = 11</code> exactly give
|
||||
the same precision as the IEEE 754 64 bit floating point format. The
|
||||
default precision is <code>prec = 113</code> and <code> expBits = 15</code> (IEEE
|
||||
754 128 bit floating point).
|
||||
754 128 bit floating point format).
|
||||
</p>
|
||||
<p>The global floating point environment can only be modified temporarily
|
||||
when calling a function (see <code>BigFloatEnv.setPrec</code>). Hence a
|
||||
@ -433,9 +431,8 @@ environment. The initial value is <code>113</code>.
|
||||
</dd>
|
||||
<dt><code>expBits</code></dt>
|
||||
<dd><p>Getter. Return the exponent size in bits of the global floating point
|
||||
environment assuming an IEEE 754 representation. If <code>expBits <
|
||||
expBitsMax</code>, then subnormal numbers are supported. The initial value
|
||||
is <code>15</code>.
|
||||
environment assuming an IEEE 754 representation. The initial value is
|
||||
<code>15</code>.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>setPrec(f, p[, e])</code></dt>
|
||||
@ -608,7 +605,7 @@ Number value.
|
||||
|
||||
<p>It returns <code>0m</code> if no parameter is provided. Otherwise the first
|
||||
parameter is converted to a bigdecimal by using ToString(). Hence
|
||||
Number value are not converted to their exact numerical value as
|
||||
Number values are not converted to their exact numerical value as
|
||||
BigDecimal.
|
||||
</p>
|
||||
<a name="Properties-of-the-BigDecimal-object"></a>
|
||||
@ -702,12 +699,12 @@ always represented as BigFloat.
|
||||
|
||||
</li><li> The logical xor operator is still available with the <code>^^</code> operator.
|
||||
|
||||
</li><li> The integer division operator can be overloaded by modifying the corresponding operator in <code>BigInt.prototype.[[OperatorSet]]</code>.
|
||||
|
||||
</li><li> The integer power operator with a non zero negative exponent can be overloaded by modifying the corresponding operator in <code>BigInt.prototype.[[OperatorSet]]</code>.
|
||||
|
||||
</li><li> The modulo operator (<code>%</code>) returns the Euclidian remainder (always positive) instead of the truncated remainder.
|
||||
|
||||
</li><li> The integer division operator can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
|
||||
|
||||
</li><li> The integer power operator with a non zero negative exponent can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
|
||||
|
||||
</li></ul>
|
||||
|
||||
<div class="footnote">
|
||||
|
BIN
doc/jsbignum.pdf
BIN
doc/jsbignum.pdf
Binary file not shown.
@ -57,7 +57,7 @@ More precisely, the following modifications were made:
|
||||
|
||||
@item @code{with operators from} is not supported. Operator overloading is always enabled.
|
||||
|
||||
@item The dispatch is not based on a static @code{[[OperatorSet]]} field in all instances. Instead, a dynamic lookup the of the @code{Symbol.operatorSet} property is done. This property is typically added in the prototype of each object.
|
||||
@item The dispatch is not based on a static @code{[[OperatorSet]]} field in all instances. Instead, a dynamic lookup of the @code{Symbol.operatorSet} property is done. This property is typically added in the prototype of each object.
|
||||
|
||||
@item @code{Operators.create(...dictionaries)} is used to create a new OperatorSet object. The @code{Operators} function is supported as an helper to be closer to the TC39 proposal.
|
||||
|
||||
@ -119,7 +119,7 @@ Return the number of trailing zeros in the two's complement binary representatio
|
||||
@section Introduction
|
||||
|
||||
This extension adds the @code{BigFloat} primitive type. The
|
||||
@code{BigFloat} type represents floating point numbers are in base 2
|
||||
@code{BigFloat} type represents floating point numbers in base 2
|
||||
with the IEEE 754 semantics. A floating
|
||||
point number is represented as a sign, mantissa and exponent. The
|
||||
special values @code{NaN}, @code{+/-Infinity}, @code{+0} and @code{-0}
|
||||
@ -143,15 +143,13 @@ explicit.}. The status flags of the global environment cannot be
|
||||
read@footnote{The rationale is to avoid side effects for the built-in
|
||||
operators.}. The precision of the global environment is
|
||||
@code{BigFloatEnv.prec}. The number of exponent bits of the global
|
||||
environment is @code{BigFloatEnv.expBits}. If @code{BigFloatEnv.expBits} is
|
||||
strictly smaller than the maximum allowed number of exponent bits
|
||||
(@code{BigFloatEnv.expBitsMax}), then the global environment subnormal
|
||||
flag is set to @code{true}. Otherwise it is set to @code{false};
|
||||
environment is @code{BigFloatEnv.expBits}. The global environment
|
||||
subnormal flag is set to @code{true}.
|
||||
|
||||
For example, @code{prec = 53} and @code{ expBits = 11} give exactly
|
||||
the same precision as the IEEE 754 64 bit floating point. The
|
||||
For example, @code{prec = 53} and @code{ expBits = 11} exactly give
|
||||
the same precision as the IEEE 754 64 bit floating point format. The
|
||||
default precision is @code{prec = 113} and @code{ expBits = 15} (IEEE
|
||||
754 128 bit floating point).
|
||||
754 128 bit floating point format).
|
||||
|
||||
The global floating point environment can only be modified temporarily
|
||||
when calling a function (see @code{BigFloatEnv.setPrec}). Hence a
|
||||
@ -345,9 +343,8 @@ environment. The initial value is @code{113}.
|
||||
|
||||
@item expBits
|
||||
Getter. Return the exponent size in bits of the global floating point
|
||||
environment assuming an IEEE 754 representation. If @code{expBits <
|
||||
expBitsMax}, then subnormal numbers are supported. The initial value
|
||||
is @code{15}.
|
||||
environment assuming an IEEE 754 representation. The initial value is
|
||||
@code{15}.
|
||||
|
||||
@item setPrec(f, p[, e])
|
||||
Set the precision of the global floating point environment to @code{p}
|
||||
@ -492,7 +489,7 @@ BigDecimal literals are decimal floating point numbers with a trailing
|
||||
|
||||
It returns @code{0m} if no parameter is provided. Otherwise the first
|
||||
parameter is converted to a bigdecimal by using ToString(). Hence
|
||||
Number value are not converted to their exact numerical value as
|
||||
Number values are not converted to their exact numerical value as
|
||||
BigDecimal.
|
||||
|
||||
@subsection Properties of the @code{BigDecimal} object
|
||||
@ -581,12 +578,12 @@ The following changes are made to the Javascript semantics:
|
||||
|
||||
@item The logical xor operator is still available with the @code{^^} operator.
|
||||
|
||||
@item The integer division operator can be overloaded by modifying the corresponding operator in @code{BigInt.prototype.[[OperatorSet]]}.
|
||||
|
||||
@item The integer power operator with a non zero negative exponent can be overloaded by modifying the corresponding operator in @code{BigInt.prototype.[[OperatorSet]]}.
|
||||
|
||||
@item The modulo operator (@code{%}) returns the Euclidian remainder (always positive) instead of the truncated remainder.
|
||||
|
||||
@item The integer division operator can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
|
||||
|
||||
@item The integer power operator with a non zero negative exponent can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
|
||||
|
||||
@end itemize
|
||||
|
||||
@bye
|
||||
|
135
doc/quickjs.html
135
doc/quickjs.html
@ -1,8 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ -->
|
||||
<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>QuickJS Javascript Engine</title>
|
||||
|
||||
<meta name="description" content="QuickJS Javascript Engine">
|
||||
@ -10,6 +9,7 @@
|
||||
<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">
|
||||
<!--
|
||||
@ -519,50 +519,39 @@ optional properties:
|
||||
<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.
|
||||
<dt><code>loadFile(filename)</code></dt>
|
||||
<dd><p>Load the file <code>filename</code> and return it as a string assuming UTF-8
|
||||
encoding. Return <code>null</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.
|
||||
<dt><code>open(filename, flags, errorObj = undefined)</code></dt>
|
||||
<dd><p>Open a file (wrapper to the libc <code>fopen()</code>). Return the FILE
|
||||
object or <code>null</code> in case of I/O error. If <code>errorObj</code> is not
|
||||
undefined, set its <code>errno</code> property to the error code or to 0 if
|
||||
no error occured.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>fdopen(fd, flags)</code></dt>
|
||||
<dt><code>popen(command, flags, errorObj = undefined)</code></dt>
|
||||
<dd><p>Open a process by creating a pipe (wrapper to the libc
|
||||
<code>popen()</code>). Return the FILE
|
||||
object or <code>null</code> in case of I/O error. If <code>errorObj</code> is not
|
||||
undefined, set its <code>errno</code> property to the error code or to 0 if
|
||||
no error occured.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>fdopen(fd, flags, errorObj = undefined)</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.
|
||||
<code>fdopen()</code>). Return the FILE
|
||||
object or <code>null</code> in case of I/O error. If <code>errorObj</code> is not
|
||||
undefined, set its <code>errno</code> property to the error code or to 0 if
|
||||
no error occured.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>tmpfile()</code></dt>
|
||||
<dd><p>Open a temporary file. Throws <code>std.Error</code> in case of I/O error.
|
||||
<dt><code>tmpfile(errorObj = undefined)</code></dt>
|
||||
<dd><p>Open a temporary file. Return the FILE
|
||||
object or <code>null</code> in case of I/O error. If <code>errorObj</code> is not
|
||||
undefined, set its <code>errno</code> property to the error code or to 0 if
|
||||
no error occured.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>puts(str)</code></dt>
|
||||
@ -589,6 +578,29 @@ optional properties:
|
||||
<dd><p>Constants for seek().
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>Error</code></dt>
|
||||
<dd>
|
||||
<p>Enumeration object containing the integer value of common errors
|
||||
(additional error codes may be defined):
|
||||
</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>
|
||||
</dl>
|
||||
|
||||
</dd>
|
||||
<dt><code>strerror(errno)</code></dt>
|
||||
<dd><p>Return a string that describes the error <code>errno</code>.
|
||||
</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
|
||||
@ -614,12 +626,14 @@ optional properties:
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>full</code></dt>
|
||||
<dd><p>Boolean (default = false). If true, return the an object contains
|
||||
<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.
|
||||
(status code). <code>response</code> is <code>null</code> is case of protocol or
|
||||
network error. If <code>full</code> is false, only the response is
|
||||
returned if the status is between 200 and 299. Otherwise <code>null</code>
|
||||
is returned.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
@ -631,7 +645,7 @@ optional properties:
|
||||
</p>
|
||||
<dl compact="compact">
|
||||
<dt><code>close()</code></dt>
|
||||
<dd><p>Close the file.
|
||||
<dd><p>Close the file. Return 0 if OK or <code>-errno</code> in case of I/O error.
|
||||
</p></dd>
|
||||
<dt><code>puts(str)</code></dt>
|
||||
<dd><p>Outputs the string with the UTF-8 encoding.
|
||||
@ -643,17 +657,27 @@ optional properties:
|
||||
<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.
|
||||
<dd><p>Seek to a give file position (whence is
|
||||
<code>std.SEEK_*</code>). <code>offset</code> can be a number or a bigint. Return
|
||||
0 if OK or <code>-errno</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>tello()</code></dt>
|
||||
<dd><p>Return the current file position as a bigint.
|
||||
</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>error()</code></dt>
|
||||
<dd><p>Return true if there was an error.
|
||||
</p></dd>
|
||||
<dt><code>clearerr()</code></dt>
|
||||
<dd><p>Clear the error indication.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>read(buffer, position, length)</code></dt>
|
||||
@ -727,7 +751,9 @@ error 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>.
|
||||
<dd><p>Seek in the file. Use <code>std.SEEK_*</code> for
|
||||
<code>whence</code>. <code>offset</code> is either a number or a bigint. If
|
||||
<code>offset</code> is a bigint, a bigint is returned too.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>read(fd, buffer, offset, length)</code></dt>
|
||||
@ -755,11 +781,11 @@ Return the number of written bytes or < 0 if error.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>remove(filename)</code></dt>
|
||||
<dd><p>Remove a file. Return 0 if OK or < 0 if error.
|
||||
<dd><p>Remove a file. Return 0 if OK or <code>-errno</code>.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>rename(oldname, newname)</code></dt>
|
||||
<dd><p>Rename a file. Return 0 if OK or < 0 if error.
|
||||
<dd><p>Rename a file. Return 0 if OK or <code>-errno</code>.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>realpath(path)</code></dt>
|
||||
@ -773,11 +799,11 @@ and <code>err</code> the error code.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>chdir(path)</code></dt>
|
||||
<dd><p>Change the current directory. Return the error code.
|
||||
<dd><p>Change the current directory. Return 0 if OK or <code>-errno</code>.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>mkdir(path, mode = 0o777)</code></dt>
|
||||
<dd><p>Create a directory at <code>path</code>. Return the error code.
|
||||
<dd><p>Create a directory at <code>path</code>. Return 0 if OK or <code>-errno</code>.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>stat(path)</code></dt>
|
||||
@ -809,11 +835,11 @@ itself.
|
||||
</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.
|
||||
times are specified in milliseconds since 1970. Return 0 if OK or <code>-errno</code>.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>symlink(target, linkpath)</code></dt>
|
||||
<dd><p>Create a link at <code>linkpath</code> containing the string <code>target</code>.
|
||||
<dd><p>Create a link at <code>linkpath</code> containing the string <code>target</code>. Return 0 if OK or <code>-errno</code>.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>readlink(path)</code></dt>
|
||||
@ -896,7 +922,8 @@ object containing optional parameters:
|
||||
|
||||
</dd>
|
||||
<dt><code>waitpid(pid, options)</code></dt>
|
||||
<dd><p><code>waitpid</code> Unix system call. Return the array <code>[ret, status]</code>.
|
||||
<dd><p><code>waitpid</code> Unix system call. Return the array <code>[ret,
|
||||
status]</code>. <code>ret</code> contains <code>-errno</code> in case of error.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>WNOHANG</code></dt>
|
||||
|
BIN
doc/quickjs.pdf
BIN
doc/quickjs.pdf
Binary file not shown.
118
doc/quickjs.texi
118
doc/quickjs.texi
@ -373,44 +373,35 @@ optional properties:
|
||||
@item loadScript(filename)
|
||||
Evaluate the file @code{filename} as a script (global eval).
|
||||
|
||||
@item Error(errno)
|
||||
@item loadFile(filename)
|
||||
Load the file @code{filename} and return it as a string assuming UTF-8
|
||||
encoding. Return @code{null} in case of I/O error.
|
||||
|
||||
@code{std.Error} constructor. Error instances contain the field
|
||||
@code{errno} (error code) and @code{message} (result of
|
||||
@code{std.Error.strerror(errno)}).
|
||||
@item open(filename, flags, errorObj = undefined)
|
||||
Open a file (wrapper to the libc @code{fopen()}). Return the FILE
|
||||
object or @code{null} in case of I/O error. If @code{errorObj} is not
|
||||
undefined, set its @code{errno} property to the error code or to 0 if
|
||||
no error occured.
|
||||
|
||||
The constructor contains the following fields:
|
||||
@item popen(command, flags, errorObj = undefined)
|
||||
Open a process by creating a pipe (wrapper to the libc
|
||||
@code{popen()}). Return the FILE
|
||||
object or @code{null} in case of I/O error. If @code{errorObj} is not
|
||||
undefined, set its @code{errno} property to the error code or to 0 if
|
||||
no error occured.
|
||||
|
||||
@table @code
|
||||
@item EINVAL
|
||||
@item EIO
|
||||
@item EACCES
|
||||
@item EEXIST
|
||||
@item ENOSPC
|
||||
@item ENOSYS
|
||||
@item EBUSY
|
||||
@item ENOENT
|
||||
@item EPERM
|
||||
@item EPIPE
|
||||
Integer value of common errors (additional error codes may be defined).
|
||||
@item strerror(errno)
|
||||
Return a string that describes the error @code{errno}.
|
||||
@end table
|
||||
|
||||
@item open(filename, flags)
|
||||
Open a file (wrapper to the libc @code{fopen()}). Throws
|
||||
@code{std.Error} in case of I/O error.
|
||||
|
||||
@item popen(command, flags)
|
||||
Open a process by creating a pipe (wrapper to the libc @code{popen()}). Throws
|
||||
@code{std.Error} in case of I/O error.
|
||||
|
||||
@item fdopen(fd, flags)
|
||||
@item fdopen(fd, flags, errorObj = undefined)
|
||||
Open a file from a file handle (wrapper to the libc
|
||||
@code{fdopen()}). Throws @code{std.Error} in case of I/O error.
|
||||
@code{fdopen()}). Return the FILE
|
||||
object or @code{null} in case of I/O error. If @code{errorObj} is not
|
||||
undefined, set its @code{errno} property to the error code or to 0 if
|
||||
no error occured.
|
||||
|
||||
@item tmpfile()
|
||||
Open a temporary file. Throws @code{std.Error} in case of I/O error.
|
||||
@item tmpfile(errorObj = undefined)
|
||||
Open a temporary file. Return the FILE
|
||||
object or @code{null} in case of I/O error. If @code{errorObj} is not
|
||||
undefined, set its @code{errno} property to the error code or to 0 if
|
||||
no error occured.
|
||||
|
||||
@item puts(str)
|
||||
Equivalent to @code{std.out.puts(str)}.
|
||||
@ -431,6 +422,27 @@ Wrappers to the libc file @code{stdin}, @code{stdout}, @code{stderr}.
|
||||
@item SEEK_END
|
||||
Constants for seek().
|
||||
|
||||
@item Error
|
||||
|
||||
Enumeration object containing the integer value of common errors
|
||||
(additional error codes may be defined):
|
||||
|
||||
@table @code
|
||||
@item EINVAL
|
||||
@item EIO
|
||||
@item EACCES
|
||||
@item EEXIST
|
||||
@item ENOSPC
|
||||
@item ENOSYS
|
||||
@item EBUSY
|
||||
@item ENOENT
|
||||
@item EPERM
|
||||
@item EPIPE
|
||||
@end table
|
||||
|
||||
@item strerror(errno)
|
||||
Return a string that describes the error @code{errno}.
|
||||
|
||||
@item gc()
|
||||
Manually invoke the cycle removal algorithm. The cycle removal
|
||||
algorithm is automatically started when needed, so this function is
|
||||
@ -453,12 +465,14 @@ optional properties:
|
||||
to be UTF-8 encoded.
|
||||
|
||||
@item full
|
||||
|
||||
Boolean (default = false). If true, return the an object contains
|
||||
the properties @code{response} (response content),
|
||||
@code{responseHeaders} (headers separated by CRLF), @code{status}
|
||||
(status code). If @code{full} is false, only the response is
|
||||
returned if the status is between 200 and 299. Otherwise an
|
||||
@code{std.Error} exception is raised.
|
||||
(status code). @code{response} is @code{null} is case of protocol or
|
||||
network error. If @code{full} is false, only the response is
|
||||
returned if the status is between 200 and 299. Otherwise @code{null}
|
||||
is returned.
|
||||
|
||||
@end table
|
||||
|
||||
@ -468,7 +482,7 @@ FILE prototype:
|
||||
|
||||
@table @code
|
||||
@item close()
|
||||
Close the file.
|
||||
Close the file. Return 0 if OK or @code{-errno} in case of I/O error.
|
||||
@item puts(str)
|
||||
Outputs the string with the UTF-8 encoding.
|
||||
@item printf(fmt, ...args)
|
||||
@ -476,14 +490,21 @@ Formatted printf, same formats as the libc printf.
|
||||
@item flush()
|
||||
Flush the buffered file.
|
||||
@item seek(offset, whence)
|
||||
Seek to a give file position (whence is @code{std.SEEK_*}). Throws a
|
||||
@code{std.Error} in case of I/O error.
|
||||
Seek to a give file position (whence is
|
||||
@code{std.SEEK_*}). @code{offset} can be a number or a bigint. Return
|
||||
0 if OK or @code{-errno} in case of I/O error.
|
||||
@item tell()
|
||||
Return the current file position.
|
||||
@item tello()
|
||||
Return the current file position as a bigint.
|
||||
@item eof()
|
||||
Return true if end of file.
|
||||
@item fileno()
|
||||
Return the associated OS handle.
|
||||
@item error()
|
||||
Return true if there was an error.
|
||||
@item clearerr()
|
||||
Clear the error indication.
|
||||
|
||||
@item read(buffer, position, length)
|
||||
Read @code{length} bytes from the file to the ArrayBuffer @code{buffer} at byte
|
||||
@ -545,7 +566,9 @@ POSIX open flags.
|
||||
Close the file handle @code{fd}.
|
||||
|
||||
@item seek(fd, offset, whence)
|
||||
Seek in the file. Use @code{std.SEEK_*} for @code{whence}.
|
||||
Seek in the file. Use @code{std.SEEK_*} for
|
||||
@code{whence}. @code{offset} is either a number or a bigint. If
|
||||
@code{offset} is a bigint, a bigint is returned too.
|
||||
|
||||
@item read(fd, buffer, offset, length)
|
||||
Read @code{length} bytes from the file handle @code{fd} to the
|
||||
@ -567,10 +590,10 @@ Return the TTY size as @code{[width, height]} or @code{null} if not available.
|
||||
Set the TTY in raw mode.
|
||||
|
||||
@item remove(filename)
|
||||
Remove a file. Return 0 if OK or < 0 if error.
|
||||
Remove a file. Return 0 if OK or @code{-errno}.
|
||||
|
||||
@item rename(oldname, newname)
|
||||
Rename a file. Return 0 if OK or < 0 if error.
|
||||
Rename a file. Return 0 if OK or @code{-errno}.
|
||||
|
||||
@item realpath(path)
|
||||
Return @code{[str, err]} where @code{str} is the canonicalized absolute
|
||||
@ -581,10 +604,10 @@ Return @code{[str, err]} where @code{str} is the current working directory
|
||||
and @code{err} the error code.
|
||||
|
||||
@item chdir(path)
|
||||
Change the current directory. Return the error code.
|
||||
Change the current directory. Return 0 if OK or @code{-errno}.
|
||||
|
||||
@item mkdir(path, mode = 0o777)
|
||||
Create a directory at @code{path}. Return the error code.
|
||||
Create a directory at @code{path}. Return 0 if OK or @code{-errno}.
|
||||
|
||||
@item stat(path)
|
||||
@item lstat(path)
|
||||
@ -613,10 +636,10 @@ Constants to interpret the @code{mode} property returned by
|
||||
|
||||
@item utimes(path, atime, mtime)
|
||||
Change the access and modification times of the file @code{path}. The
|
||||
times are specified in milliseconds since 1970.
|
||||
times are specified in milliseconds since 1970. Return 0 if OK or @code{-errno}.
|
||||
|
||||
@item symlink(target, linkpath)
|
||||
Create a link at @code{linkpath} containing the string @code{target}.
|
||||
Create a link at @code{linkpath} containing the string @code{target}. Return 0 if OK or @code{-errno}.
|
||||
|
||||
@item readlink(path)
|
||||
Return @code{[str, err]} where @code{str} is the link target and @code{err}
|
||||
@ -685,7 +708,8 @@ object containing optional parameters:
|
||||
@end table
|
||||
|
||||
@item waitpid(pid, options)
|
||||
@code{waitpid} Unix system call. Return the array @code{[ret, status]}.
|
||||
@code{waitpid} Unix system call. Return the array @code{[ret,
|
||||
status]}. @code{ret} contains @code{-errno} in case of error.
|
||||
|
||||
@item WNOHANG
|
||||
Constant for the @code{options} argument of @code{waitpid}.
|
||||
|
47
libbf.c
47
libbf.c
@ -2526,19 +2526,18 @@ fail:
|
||||
return BF_ST_MEM_ERROR;
|
||||
}
|
||||
|
||||
/* The rounding mode is always BF_RNDZ. Return BF_ST_OVERFLOW if there
|
||||
/* The rounding mode is always BF_RNDZ. Return BF_ST_INVALID_OP if there
|
||||
is an overflow and 0 otherwise. */
|
||||
int bf_get_int32(int *pres, const bf_t *a, int flags)
|
||||
{
|
||||
uint32_t v;
|
||||
int ret;
|
||||
if (a->expn >= BF_EXP_INF) {
|
||||
ret = 0;
|
||||
ret = BF_ST_INVALID_OP;
|
||||
if (flags & BF_GET_INT_MOD) {
|
||||
v = 0;
|
||||
} else if (a->expn == BF_EXP_INF) {
|
||||
v = (uint32_t)INT32_MAX + a->sign;
|
||||
/* XXX: return overflow ? */
|
||||
} else {
|
||||
v = INT32_MAX;
|
||||
}
|
||||
@ -2551,7 +2550,7 @@ int bf_get_int32(int *pres, const bf_t *a, int flags)
|
||||
v = -v;
|
||||
ret = 0;
|
||||
} else if (!(flags & BF_GET_INT_MOD)) {
|
||||
ret = BF_ST_OVERFLOW;
|
||||
ret = BF_ST_INVALID_OP;
|
||||
if (a->sign) {
|
||||
v = (uint32_t)INT32_MAX + 1;
|
||||
if (a->expn == 32 &&
|
||||
@ -2571,14 +2570,14 @@ int bf_get_int32(int *pres, const bf_t *a, int flags)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The rounding mode is always BF_RNDZ. Return BF_ST_OVERFLOW if there
|
||||
/* The rounding mode is always BF_RNDZ. Return BF_ST_INVALID_OP if there
|
||||
is an overflow and 0 otherwise. */
|
||||
int bf_get_int64(int64_t *pres, const bf_t *a, int flags)
|
||||
{
|
||||
uint64_t v;
|
||||
int ret;
|
||||
if (a->expn >= BF_EXP_INF) {
|
||||
ret = 0;
|
||||
ret = BF_ST_INVALID_OP;
|
||||
if (flags & BF_GET_INT_MOD) {
|
||||
v = 0;
|
||||
} else if (a->expn == BF_EXP_INF) {
|
||||
@ -2603,7 +2602,7 @@ int bf_get_int64(int64_t *pres, const bf_t *a, int flags)
|
||||
v = -v;
|
||||
ret = 0;
|
||||
} else if (!(flags & BF_GET_INT_MOD)) {
|
||||
ret = BF_ST_OVERFLOW;
|
||||
ret = BF_ST_INVALID_OP;
|
||||
if (a->sign) {
|
||||
uint64_t v1;
|
||||
v = (uint64_t)INT64_MAX + 1;
|
||||
@ -2632,6 +2631,40 @@ int bf_get_int64(int64_t *pres, const bf_t *a, int flags)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The rounding mode is always BF_RNDZ. Return BF_ST_INVALID_OP if there
|
||||
is an overflow and 0 otherwise. */
|
||||
int bf_get_uint64(uint64_t *pres, const bf_t *a)
|
||||
{
|
||||
uint64_t v;
|
||||
int ret;
|
||||
if (a->expn == BF_EXP_NAN) {
|
||||
goto overflow;
|
||||
} else if (a->expn <= 0) {
|
||||
v = 0;
|
||||
ret = 0;
|
||||
} else if (a->sign) {
|
||||
v = 0;
|
||||
ret = BF_ST_INVALID_OP;
|
||||
} else if (a->expn <= 64) {
|
||||
#if LIMB_BITS == 32
|
||||
if (a->expn <= 32)
|
||||
v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
|
||||
else
|
||||
v = (((uint64_t)a->tab[a->len - 1] << 32) |
|
||||
get_limbz(a, a->len - 2)) >> (64 - a->expn);
|
||||
#else
|
||||
v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
|
||||
#endif
|
||||
ret = 0;
|
||||
} else {
|
||||
overflow:
|
||||
v = UINT64_MAX;
|
||||
ret = BF_ST_INVALID_OP;
|
||||
}
|
||||
*pres = v;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* base conversion from radix */
|
||||
|
||||
static const uint8_t digits_per_limb_table[BF_RADIX_MAX - 1] = {
|
||||
|
1
libbf.h
1
libbf.h
@ -376,6 +376,7 @@ char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
|
||||
#define BF_GET_INT_MOD (1 << 0)
|
||||
int bf_get_int32(int *pres, const bf_t *a, int flags);
|
||||
int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
|
||||
int bf_get_uint64(uint64_t *pres, const bf_t *a);
|
||||
|
||||
/* the following functions are exported for testing only. */
|
||||
void mp_print_str(const char *str, const limb_t *tab, limb_t n);
|
||||
|
92
libregexp.c
92
libregexp.c
@ -434,8 +434,9 @@ static int __attribute__((format(printf, 2, 3))) re_parse_error(REParseState *s,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return -1 in case of overflow */
|
||||
static int parse_digits(const uint8_t **pp)
|
||||
/* If allow_overflow is false, return -1 in case of
|
||||
overflow. Otherwise return INT32_MAX. */
|
||||
static int parse_digits(const uint8_t **pp, BOOL allow_overflow)
|
||||
{
|
||||
const uint8_t *p;
|
||||
uint64_t v;
|
||||
@ -448,8 +449,12 @@ static int parse_digits(const uint8_t **pp)
|
||||
if (c < '0' || c > '9')
|
||||
break;
|
||||
v = v * 10 + c - '0';
|
||||
if (v >= INT32_MAX)
|
||||
return -1;
|
||||
if (v >= INT32_MAX) {
|
||||
if (allow_overflow)
|
||||
v = INT32_MAX;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
*pp = p;
|
||||
@ -1225,14 +1230,27 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
|
||||
re_emit_op(s, REOP_prev);
|
||||
break;
|
||||
case '{':
|
||||
/* As an extension (see ES6 annex B), we accept '{' not
|
||||
followed by digits as a normal atom */
|
||||
if (!is_digit(p[1])) {
|
||||
if (s->is_utf16)
|
||||
goto invalid_quant_count;
|
||||
if (s->is_utf16) {
|
||||
return re_parse_error(s, "syntax error");
|
||||
} else if (!is_digit(p[1])) {
|
||||
/* Annex B: we accept '{' not followed by digits as a
|
||||
normal atom */
|
||||
goto parse_class_atom;
|
||||
} else {
|
||||
const uint8_t *p1 = p + 1;
|
||||
/* Annex B: error if it is like a repetition count */
|
||||
parse_digits(&p1, TRUE);
|
||||
if (*p1 == ',') {
|
||||
p1++;
|
||||
if (is_digit(*p1)) {
|
||||
parse_digits(&p1, TRUE);
|
||||
}
|
||||
}
|
||||
if (*p1 != '}') {
|
||||
goto parse_class_atom;
|
||||
}
|
||||
}
|
||||
/* fall tru */
|
||||
/* fall thru */
|
||||
case '*':
|
||||
case '+':
|
||||
case '?':
|
||||
@ -1387,7 +1405,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
|
||||
{
|
||||
const uint8_t *q = ++p;
|
||||
|
||||
c = parse_digits(&p);
|
||||
c = parse_digits(&p, FALSE);
|
||||
if (c < 0 || (c >= s->capture_count && c >= re_count_captures(s))) {
|
||||
if (!s->is_utf16) {
|
||||
/* Annex B.1.4: accept legacy octal */
|
||||
@ -1484,32 +1502,38 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
|
||||
quant_max = 1;
|
||||
goto quantifier;
|
||||
case '{':
|
||||
/* As an extension (see ES6 annex B), we accept '{' not
|
||||
followed by digits as a normal atom */
|
||||
if (!is_digit(p[1])) {
|
||||
if (s->is_utf16)
|
||||
goto invalid_quant_count;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
quant_min = parse_digits(&p);
|
||||
if (quant_min < 0) {
|
||||
invalid_quant_count:
|
||||
return re_parse_error(s, "invalid repetition count");
|
||||
}
|
||||
quant_max = quant_min;
|
||||
if (*p == ',') {
|
||||
p++;
|
||||
if (is_digit(*p)) {
|
||||
quant_max = parse_digits(&p);
|
||||
if (quant_max < 0 || quant_max < quant_min)
|
||||
{
|
||||
const uint8_t *p1 = p;
|
||||
/* As an extension (see ES6 annex B), we accept '{' not
|
||||
followed by digits as a normal atom */
|
||||
if (!is_digit(p[1])) {
|
||||
if (s->is_utf16)
|
||||
goto invalid_quant_count;
|
||||
} else {
|
||||
quant_max = INT32_MAX; /* infinity */
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
quant_min = parse_digits(&p, TRUE);
|
||||
quant_max = quant_min;
|
||||
if (*p == ',') {
|
||||
p++;
|
||||
if (is_digit(*p)) {
|
||||
quant_max = parse_digits(&p, TRUE);
|
||||
if (quant_max < quant_min) {
|
||||
invalid_quant_count:
|
||||
return re_parse_error(s, "invalid repetition count");
|
||||
}
|
||||
} else {
|
||||
quant_max = INT32_MAX; /* infinity */
|
||||
}
|
||||
}
|
||||
if (*p != '}' && !s->is_utf16) {
|
||||
/* Annex B: normal atom if invalid '{' syntax */
|
||||
p = p1;
|
||||
break;
|
||||
}
|
||||
if (re_parse_expect(s, &p, '}'))
|
||||
return -1;
|
||||
}
|
||||
if (re_parse_expect(s, &p, '}'))
|
||||
return -1;
|
||||
quantifier:
|
||||
greedy = TRUE;
|
||||
if (*p == '?') {
|
||||
|
3183
libunicode-table.h
3183
libunicode-table.h
File diff suppressed because it is too large
Load Diff
392
quickjs-libc.c
392
quickjs-libc.c
@ -224,17 +224,15 @@ static JSValue js_printf_internal(JSContext *ctx,
|
||||
case 'X':
|
||||
if (i >= argc)
|
||||
goto missing;
|
||||
if (JS_ToInt64Ext(ctx, &int64_arg, argv[i++]))
|
||||
goto fail;
|
||||
if (modsize > 0) {
|
||||
if (JS_ToInt64(ctx, &int64_arg, argv[i++]))
|
||||
goto fail;
|
||||
q[1] = q[-1];
|
||||
q[-1] = q[0] = 'l';
|
||||
q[2] = '\0';
|
||||
dbuf_printf_fun(&dbuf, fmtbuf, (long long)int64_arg);
|
||||
} else {
|
||||
if (JS_ToInt32(ctx, &int32_arg, argv[i++]))
|
||||
goto fail;
|
||||
dbuf_printf_fun(&dbuf, fmtbuf, int32_arg);
|
||||
dbuf_printf_fun(&dbuf, fmtbuf, (int)int64_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -369,6 +367,27 @@ static JSValue js_loadScript(JSContext *ctx, JSValueConst this_val,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* load a file as a UTF-8 encoded string */
|
||||
static JSValue js_std_loadFile(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
uint8_t *buf;
|
||||
const char *filename;
|
||||
JSValue ret;
|
||||
size_t buf_len;
|
||||
|
||||
filename = JS_ToCString(ctx, argv[0]);
|
||||
if (!filename)
|
||||
return JS_EXCEPTION;
|
||||
buf = js_load_file(ctx, &buf_len, filename);
|
||||
JS_FreeCString(ctx, filename);
|
||||
if (!buf)
|
||||
return JS_NULL;
|
||||
ret = JS_NewStringLen(ctx, (char *)buf, buf_len);
|
||||
js_free(ctx, buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef JSModuleDef *(JSInitModuleFunc)(JSContext *ctx,
|
||||
const char *module_name);
|
||||
|
||||
@ -633,30 +652,14 @@ static void js_std_file_finalizer(JSRuntime *rt, JSValue val)
|
||||
}
|
||||
}
|
||||
|
||||
static JSValue js_new_std_error(JSContext *ctx, int err)
|
||||
static ssize_t js_get_errno(ssize_t ret)
|
||||
{
|
||||
JSValue obj;
|
||||
/* XXX: could add a specific Error prototype */
|
||||
obj = JS_NewError(ctx);
|
||||
JS_DefinePropertyValueStr(ctx, obj, "message",
|
||||
JS_NewString(ctx, strerror(err)),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, obj, "errno",
|
||||
JS_NewInt32(ctx, err),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
return obj;
|
||||
if (ret == -1)
|
||||
ret = -errno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue js_std_error_constructor(JSContext *ctx, JSValueConst new_target,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
int err;
|
||||
if (JS_ToInt32(ctx, &err, argv[0]))
|
||||
return JS_EXCEPTION;
|
||||
return js_new_std_error(ctx, err);
|
||||
}
|
||||
|
||||
static JSValue js_std_error_strerror(JSContext *ctx, JSValueConst this_val,
|
||||
static JSValue js_std_strerror(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
int err;
|
||||
@ -665,15 +668,6 @@ static JSValue js_std_error_strerror(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_NewString(ctx, strerror(err));
|
||||
}
|
||||
|
||||
static JSValue js_std_throw_errno(JSContext *ctx, int err)
|
||||
{
|
||||
JSValue obj;
|
||||
obj = js_new_std_error(ctx, err);
|
||||
if (JS_IsException(obj))
|
||||
obj = JS_NULL;
|
||||
return JS_Throw(ctx, obj);
|
||||
}
|
||||
|
||||
static JSValue js_new_std_file(JSContext *ctx, FILE *f,
|
||||
BOOL close_in_finalizer,
|
||||
BOOL is_popen)
|
||||
@ -695,11 +689,19 @@ static JSValue js_new_std_file(JSContext *ctx, FILE *f,
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void js_set_error_object(JSContext *ctx, JSValue obj, int err)
|
||||
{
|
||||
if (!JS_IsUndefined(obj)) {
|
||||
JS_SetPropertyStr(ctx, obj, "errno", JS_NewInt32(ctx, err));
|
||||
}
|
||||
}
|
||||
|
||||
static JSValue js_std_open(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
const char *filename, *mode = NULL;
|
||||
FILE *f;
|
||||
int err;
|
||||
|
||||
filename = JS_ToCString(ctx, argv[0]);
|
||||
if (!filename)
|
||||
@ -708,15 +710,21 @@ static JSValue js_std_open(JSContext *ctx, JSValueConst this_val,
|
||||
if (!mode)
|
||||
goto fail;
|
||||
if (mode[strspn(mode, "rwa+b")] != '\0') {
|
||||
js_std_throw_errno(ctx, EINVAL);
|
||||
JS_ThrowTypeError(ctx, "invalid file mode");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
f = fopen(filename, mode);
|
||||
if (!f)
|
||||
err = errno;
|
||||
else
|
||||
err = 0;
|
||||
if (argc >= 3)
|
||||
js_set_error_object(ctx, argv[2], err);
|
||||
JS_FreeCString(ctx, filename);
|
||||
JS_FreeCString(ctx, mode);
|
||||
if (!f)
|
||||
return js_std_throw_errno(ctx, errno);
|
||||
return JS_NULL;
|
||||
return js_new_std_file(ctx, f, TRUE, FALSE);
|
||||
fail:
|
||||
JS_FreeCString(ctx, filename);
|
||||
@ -729,6 +737,7 @@ static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val,
|
||||
{
|
||||
const char *filename, *mode = NULL;
|
||||
FILE *f;
|
||||
int err;
|
||||
|
||||
filename = JS_ToCString(ctx, argv[0]);
|
||||
if (!filename)
|
||||
@ -737,15 +746,21 @@ static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val,
|
||||
if (!mode)
|
||||
goto fail;
|
||||
if (mode[strspn(mode, "rw")] != '\0') {
|
||||
js_std_throw_errno(ctx, EINVAL);
|
||||
JS_ThrowTypeError(ctx, "invalid file mode");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
f = popen(filename, mode);
|
||||
if (!f)
|
||||
err = errno;
|
||||
else
|
||||
err = 0;
|
||||
if (argc >= 3)
|
||||
js_set_error_object(ctx, argv[2], err);
|
||||
JS_FreeCString(ctx, filename);
|
||||
JS_FreeCString(ctx, mode);
|
||||
if (!f)
|
||||
return js_std_throw_errno(ctx, errno);
|
||||
return JS_NULL;
|
||||
return js_new_std_file(ctx, f, TRUE, TRUE);
|
||||
fail:
|
||||
JS_FreeCString(ctx, filename);
|
||||
@ -758,7 +773,7 @@ static JSValue js_std_fdopen(JSContext *ctx, JSValueConst this_val,
|
||||
{
|
||||
const char *mode;
|
||||
FILE *f;
|
||||
int fd;
|
||||
int fd, err;
|
||||
|
||||
if (JS_ToInt32(ctx, &fd, argv[0]))
|
||||
return JS_EXCEPTION;
|
||||
@ -766,14 +781,20 @@ static JSValue js_std_fdopen(JSContext *ctx, JSValueConst this_val,
|
||||
if (!mode)
|
||||
goto fail;
|
||||
if (mode[strspn(mode, "rwa+")] != '\0') {
|
||||
js_std_throw_errno(ctx, EINVAL);
|
||||
JS_ThrowTypeError(ctx, "invalid file mode");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
f = fdopen(fd, mode);
|
||||
if (!f)
|
||||
err = errno;
|
||||
else
|
||||
err = 0;
|
||||
if (argc >= 3)
|
||||
js_set_error_object(ctx, argv[2], err);
|
||||
JS_FreeCString(ctx, mode);
|
||||
if (!f)
|
||||
return js_std_throw_errno(ctx, errno);
|
||||
return JS_NULL;
|
||||
return js_new_std_file(ctx, f, TRUE, FALSE);
|
||||
fail:
|
||||
JS_FreeCString(ctx, mode);
|
||||
@ -785,8 +806,10 @@ static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val,
|
||||
{
|
||||
FILE *f;
|
||||
f = tmpfile();
|
||||
if (argc >= 1)
|
||||
js_set_error_object(ctx, argv[0], f ? 0 : errno);
|
||||
if (!f)
|
||||
return js_std_throw_errno(ctx, errno);
|
||||
return JS_NULL;
|
||||
return js_new_std_file(ctx, f, TRUE, FALSE);
|
||||
}
|
||||
|
||||
@ -808,7 +831,7 @@ static FILE *js_std_file_get(JSContext *ctx, JSValueConst obj)
|
||||
if (!s)
|
||||
return NULL;
|
||||
if (!s->f) {
|
||||
js_std_throw_errno(ctx, EBADF);
|
||||
JS_ThrowTypeError(ctx, "invalid file handle");
|
||||
return NULL;
|
||||
}
|
||||
return s->f;
|
||||
@ -843,17 +866,17 @@ static JSValue js_std_file_close(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
JSSTDFile *s = JS_GetOpaque2(ctx, this_val, js_std_file_class_id);
|
||||
int err;
|
||||
if (!s)
|
||||
return JS_EXCEPTION;
|
||||
if (!s->f)
|
||||
return js_std_throw_errno(ctx, EBADF);
|
||||
/* XXX: could return exit code */
|
||||
return JS_ThrowTypeError(ctx, "invalid file handle");
|
||||
if (s->is_popen)
|
||||
pclose(s->f);
|
||||
err = js_get_errno(pclose(s->f));
|
||||
else
|
||||
fclose(s->f);
|
||||
err = js_get_errno(fclose(s->f));
|
||||
s->f = NULL;
|
||||
return JS_UNDEFINED;
|
||||
return JS_NewInt32(ctx, err);
|
||||
}
|
||||
|
||||
static JSValue js_std_file_printf(JSContext *ctx, JSValueConst this_val,
|
||||
@ -876,7 +899,7 @@ static JSValue js_std_file_flush(JSContext *ctx, JSValueConst this_val,
|
||||
}
|
||||
|
||||
static JSValue js_std_file_tell(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
int argc, JSValueConst *argv, int is_bigint)
|
||||
{
|
||||
FILE *f = js_std_file_get(ctx, this_val);
|
||||
int64_t pos;
|
||||
@ -887,7 +910,10 @@ static JSValue js_std_file_tell(JSContext *ctx, JSValueConst this_val,
|
||||
#else
|
||||
pos = ftell(f);
|
||||
#endif
|
||||
return JS_NewInt64(ctx, pos);
|
||||
if (is_bigint)
|
||||
return JS_NewBigInt64(ctx, pos);
|
||||
else
|
||||
return JS_NewInt64(ctx, pos);
|
||||
}
|
||||
|
||||
static JSValue js_std_file_seek(JSContext *ctx, JSValueConst this_val,
|
||||
@ -898,7 +924,7 @@ static JSValue js_std_file_seek(JSContext *ctx, JSValueConst this_val,
|
||||
int whence, ret;
|
||||
if (!f)
|
||||
return JS_EXCEPTION;
|
||||
if (JS_ToInt64(ctx, &pos, argv[0]))
|
||||
if (JS_ToInt64Ext(ctx, &pos, argv[0]))
|
||||
return JS_EXCEPTION;
|
||||
if (JS_ToInt32(ctx, &whence, argv[1]))
|
||||
return JS_EXCEPTION;
|
||||
@ -908,8 +934,8 @@ static JSValue js_std_file_seek(JSContext *ctx, JSValueConst this_val,
|
||||
ret = fseek(f, pos, whence);
|
||||
#endif
|
||||
if (ret < 0)
|
||||
return js_std_throw_errno(ctx, EBADF);
|
||||
return JS_UNDEFINED;
|
||||
ret = -errno;
|
||||
return JS_NewInt32(ctx, ret);
|
||||
}
|
||||
|
||||
static JSValue js_std_file_eof(JSContext *ctx, JSValueConst this_val,
|
||||
@ -921,6 +947,25 @@ static JSValue js_std_file_eof(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_NewBool(ctx, feof(f));
|
||||
}
|
||||
|
||||
static JSValue js_std_file_error(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
FILE *f = js_std_file_get(ctx, this_val);
|
||||
if (!f)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewBool(ctx, ferror(f));
|
||||
}
|
||||
|
||||
static JSValue js_std_file_clearerr(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
FILE *f = js_std_file_get(ctx, this_val);
|
||||
if (!f)
|
||||
return JS_EXCEPTION;
|
||||
clearerr(f);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_std_file_fileno(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
@ -1151,7 +1196,7 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val,
|
||||
f = popen((char *)cmd_buf.buf, "r");
|
||||
dbuf_free(&cmd_buf);
|
||||
if (!f) {
|
||||
return js_std_throw_errno(ctx, errno);
|
||||
return JS_ThrowTypeError(ctx, "could not start curl");
|
||||
}
|
||||
|
||||
js_std_dbuf_init(ctx, data_buf);
|
||||
@ -1162,20 +1207,21 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val,
|
||||
goto fail;
|
||||
|
||||
/* get the HTTP status */
|
||||
if (http_get_header_line(f, buf, URL_GET_BUF_SIZE, NULL) < 0)
|
||||
if (http_get_header_line(f, buf, URL_GET_BUF_SIZE, NULL) < 0) {
|
||||
status = 0;
|
||||
goto bad_header;
|
||||
}
|
||||
status = http_get_status(buf);
|
||||
if (!full_flag && !(status >= 200 && status <= 299)) {
|
||||
js_std_throw_errno(ctx, ENOENT);
|
||||
goto fail;
|
||||
goto bad_header;
|
||||
}
|
||||
|
||||
/* wait until there is an empty line */
|
||||
for(;;) {
|
||||
if (http_get_header_line(f, buf, URL_GET_BUF_SIZE, header_buf) < 0) {
|
||||
bad_header:
|
||||
js_std_throw_errno(ctx, EINVAL);
|
||||
goto fail;
|
||||
response = JS_NULL;
|
||||
goto done;
|
||||
}
|
||||
if (!strcmp(buf, "\r\n"))
|
||||
break;
|
||||
@ -1191,11 +1237,6 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val,
|
||||
break;
|
||||
dbuf_put(data_buf, (uint8_t *)buf, len);
|
||||
}
|
||||
js_free(ctx, buf);
|
||||
buf = NULL;
|
||||
pclose(f);
|
||||
f = NULL;
|
||||
|
||||
if (dbuf_error(data_buf))
|
||||
goto fail;
|
||||
if (binary_flag) {
|
||||
@ -1204,10 +1245,15 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val,
|
||||
} else {
|
||||
response = JS_NewStringLen(ctx, (char *)data_buf->buf, data_buf->size);
|
||||
}
|
||||
dbuf_free(data_buf);
|
||||
data_buf = NULL;
|
||||
if (JS_IsException(response))
|
||||
goto fail;
|
||||
done:
|
||||
js_free(ctx, buf);
|
||||
buf = NULL;
|
||||
pclose(f);
|
||||
f = NULL;
|
||||
dbuf_free(data_buf);
|
||||
data_buf = NULL;
|
||||
|
||||
if (full_flag) {
|
||||
ret_obj = JS_NewObject(ctx);
|
||||
@ -1216,13 +1262,15 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val,
|
||||
JS_DefinePropertyValueStr(ctx, ret_obj, "response",
|
||||
response,
|
||||
JS_PROP_C_W_E);
|
||||
JS_DefinePropertyValueStr(ctx, ret_obj, "responseHeaders",
|
||||
JS_NewStringLen(ctx, (char *)header_buf->buf,
|
||||
header_buf->size),
|
||||
JS_PROP_C_W_E);
|
||||
JS_DefinePropertyValueStr(ctx, ret_obj, "status",
|
||||
JS_NewInt32(ctx, status),
|
||||
JS_PROP_C_W_E);
|
||||
if (!JS_IsNull(response)) {
|
||||
JS_DefinePropertyValueStr(ctx, ret_obj, "responseHeaders",
|
||||
JS_NewStringLen(ctx, (char *)header_buf->buf,
|
||||
header_buf->size),
|
||||
JS_PROP_C_W_E);
|
||||
JS_DefinePropertyValueStr(ctx, ret_obj, "status",
|
||||
JS_NewInt32(ctx, status),
|
||||
JS_PROP_C_W_E);
|
||||
}
|
||||
} else {
|
||||
ret_obj = response;
|
||||
}
|
||||
@ -1245,31 +1293,7 @@ static JSClassDef js_std_file_class = {
|
||||
.finalizer = js_std_file_finalizer,
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_std_funcs[] = {
|
||||
JS_CFUNC_DEF("exit", 1, js_std_exit ),
|
||||
JS_CFUNC_DEF("gc", 0, js_std_gc ),
|
||||
JS_CFUNC_DEF("evalScript", 1, js_evalScript ),
|
||||
JS_CFUNC_DEF("loadScript", 1, js_loadScript ),
|
||||
JS_CFUNC_DEF("getenv", 1, js_std_getenv ),
|
||||
JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ),
|
||||
|
||||
/* FILE I/O */
|
||||
JS_CFUNC_DEF("open", 2, js_std_open ),
|
||||
JS_CFUNC_DEF("popen", 2, js_std_popen ),
|
||||
JS_CFUNC_DEF("fdopen", 2, js_std_fdopen ),
|
||||
JS_CFUNC_DEF("tmpfile", 0, js_std_tmpfile ),
|
||||
JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 0 ),
|
||||
JS_CFUNC_DEF("printf", 1, js_std_printf ),
|
||||
JS_CFUNC_DEF("sprintf", 1, js_std_sprintf ),
|
||||
JS_PROP_INT32_DEF("SEEK_SET", SEEK_SET, JS_PROP_CONFIGURABLE ),
|
||||
JS_PROP_INT32_DEF("SEEK_CUR", SEEK_CUR, JS_PROP_CONFIGURABLE ),
|
||||
JS_PROP_INT32_DEF("SEEK_END", SEEK_END, JS_PROP_CONFIGURABLE ),
|
||||
|
||||
/* setenv, ... */
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_std_error_funcs[] = {
|
||||
JS_CFUNC_DEF("strerror", 1, js_std_error_strerror ),
|
||||
static const JSCFunctionListEntry js_std_error_props[] = {
|
||||
/* various errno values */
|
||||
#define DEF(x) JS_PROP_INT32_DEF(#x, x, JS_PROP_CONFIGURABLE )
|
||||
DEF(EINVAL),
|
||||
@ -1286,27 +1310,55 @@ static const JSCFunctionListEntry js_std_error_funcs[] = {
|
||||
#undef DEF
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_std_funcs[] = {
|
||||
JS_CFUNC_DEF("exit", 1, js_std_exit ),
|
||||
JS_CFUNC_DEF("gc", 0, js_std_gc ),
|
||||
JS_CFUNC_DEF("evalScript", 1, js_evalScript ),
|
||||
JS_CFUNC_DEF("loadScript", 1, js_loadScript ),
|
||||
JS_CFUNC_DEF("getenv", 1, js_std_getenv ),
|
||||
JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ),
|
||||
JS_CFUNC_DEF("loadFile", 1, js_std_loadFile ),
|
||||
JS_CFUNC_DEF("strerror", 1, js_std_strerror ),
|
||||
|
||||
/* FILE I/O */
|
||||
JS_CFUNC_DEF("open", 2, js_std_open ),
|
||||
JS_CFUNC_DEF("popen", 2, js_std_popen ),
|
||||
JS_CFUNC_DEF("fdopen", 2, js_std_fdopen ),
|
||||
JS_CFUNC_DEF("tmpfile", 0, js_std_tmpfile ),
|
||||
JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 0 ),
|
||||
JS_CFUNC_DEF("printf", 1, js_std_printf ),
|
||||
JS_CFUNC_DEF("sprintf", 1, js_std_sprintf ),
|
||||
JS_PROP_INT32_DEF("SEEK_SET", SEEK_SET, JS_PROP_CONFIGURABLE ),
|
||||
JS_PROP_INT32_DEF("SEEK_CUR", SEEK_CUR, JS_PROP_CONFIGURABLE ),
|
||||
JS_PROP_INT32_DEF("SEEK_END", SEEK_END, JS_PROP_CONFIGURABLE ),
|
||||
JS_OBJECT_DEF("Error", js_std_error_props, countof(js_std_error_props), JS_PROP_CONFIGURABLE),
|
||||
/* setenv, ... */
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_std_file_proto_funcs[] = {
|
||||
JS_CFUNC_DEF("close", 0, js_std_file_close ),
|
||||
JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 1 ),
|
||||
JS_CFUNC_DEF("printf", 1, js_std_file_printf ),
|
||||
JS_CFUNC_DEF("flush", 0, js_std_file_flush ),
|
||||
JS_CFUNC_DEF("tell", 0, js_std_file_tell ),
|
||||
JS_CFUNC_MAGIC_DEF("tell", 0, js_std_file_tell, 0 ),
|
||||
JS_CFUNC_MAGIC_DEF("tello", 0, js_std_file_tell, 1 ),
|
||||
JS_CFUNC_DEF("seek", 2, js_std_file_seek ),
|
||||
JS_CFUNC_DEF("eof", 0, js_std_file_eof ),
|
||||
JS_CFUNC_DEF("fileno", 0, js_std_file_fileno ),
|
||||
JS_CFUNC_DEF("error", 0, js_std_file_error ),
|
||||
JS_CFUNC_DEF("clearerr", 0, js_std_file_clearerr ),
|
||||
JS_CFUNC_MAGIC_DEF("read", 3, js_std_file_read_write, 0 ),
|
||||
JS_CFUNC_MAGIC_DEF("write", 3, js_std_file_read_write, 1 ),
|
||||
JS_CFUNC_DEF("getline", 0, js_std_file_getline ),
|
||||
JS_CFUNC_DEF("readAsString", 0, js_std_file_readAsString ),
|
||||
JS_CFUNC_DEF("getByte", 0, js_std_file_getByte ),
|
||||
JS_CFUNC_DEF("putByte", 1, js_std_file_putByte ),
|
||||
/* setvbuf, ferror, clearerr, ... */
|
||||
/* setvbuf, ... */
|
||||
};
|
||||
|
||||
static int js_std_init(JSContext *ctx, JSModuleDef *m)
|
||||
{
|
||||
JSValue proto, obj;
|
||||
JSValue proto;
|
||||
|
||||
/* FILE class */
|
||||
/* the class ID is created once */
|
||||
@ -1323,13 +1375,6 @@ static int js_std_init(JSContext *ctx, JSModuleDef *m)
|
||||
JS_SetModuleExport(ctx, m, "in", js_new_std_file(ctx, stdin, FALSE, FALSE));
|
||||
JS_SetModuleExport(ctx, m, "out", js_new_std_file(ctx, stdout, FALSE, FALSE));
|
||||
JS_SetModuleExport(ctx, m, "err", js_new_std_file(ctx, stderr, FALSE, FALSE));
|
||||
|
||||
obj = JS_NewCFunction2(ctx, js_std_error_constructor,
|
||||
"Error", 1, JS_CFUNC_constructor, 0);
|
||||
JS_SetPropertyFunctionList(ctx, obj, js_std_error_funcs,
|
||||
countof(js_std_error_funcs));
|
||||
JS_SetModuleExport(ctx, m, "Error", obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1343,20 +1388,12 @@ JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name)
|
||||
JS_AddModuleExport(ctx, m, "in");
|
||||
JS_AddModuleExport(ctx, m, "out");
|
||||
JS_AddModuleExport(ctx, m, "err");
|
||||
JS_AddModuleExport(ctx, m, "Error");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
/* 'os' object */
|
||||
|
||||
static JSValue js_os_return(JSContext *ctx, ssize_t ret)
|
||||
{
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
return JS_NewInt64(ctx, ret);
|
||||
}
|
||||
|
||||
static JSValue js_os_open(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
@ -1382,9 +1419,9 @@ static JSValue js_os_open(JSContext *ctx, JSValueConst this_val,
|
||||
if (!(flags & O_TEXT))
|
||||
flags |= O_BINARY;
|
||||
#endif
|
||||
ret = open(filename, flags, mode);
|
||||
ret = js_get_errno(open(filename, flags, mode));
|
||||
JS_FreeCString(ctx, filename);
|
||||
return js_os_return(ctx, ret);
|
||||
return JS_NewInt32(ctx, ret);
|
||||
}
|
||||
|
||||
static JSValue js_os_close(JSContext *ctx, JSValueConst this_val,
|
||||
@ -1393,24 +1430,31 @@ static JSValue js_os_close(JSContext *ctx, JSValueConst this_val,
|
||||
int fd, ret;
|
||||
if (JS_ToInt32(ctx, &fd, argv[0]))
|
||||
return JS_EXCEPTION;
|
||||
ret = close(fd);
|
||||
return js_os_return(ctx, ret);
|
||||
ret = js_get_errno(close(fd));
|
||||
return JS_NewInt32(ctx, ret);
|
||||
}
|
||||
|
||||
static JSValue js_os_seek(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
int fd, whence, ret;
|
||||
int64_t pos;
|
||||
int fd, whence;
|
||||
int64_t pos, ret;
|
||||
BOOL is_bigint;
|
||||
|
||||
if (JS_ToInt32(ctx, &fd, argv[0]))
|
||||
return JS_EXCEPTION;
|
||||
if (JS_ToInt64(ctx, &pos, argv[1]))
|
||||
is_bigint = JS_IsBigInt(ctx, argv[1]);
|
||||
if (JS_ToInt64Ext(ctx, &pos, argv[1]))
|
||||
return JS_EXCEPTION;
|
||||
if (JS_ToInt32(ctx, &whence, argv[2]))
|
||||
return JS_EXCEPTION;
|
||||
ret = lseek(fd, pos, whence);
|
||||
return js_os_return(ctx, ret);
|
||||
if (ret == -1)
|
||||
ret = -errno;
|
||||
if (is_bigint)
|
||||
return JS_NewBigInt64(ctx, ret);
|
||||
else
|
||||
return JS_NewInt64(ctx, ret);
|
||||
}
|
||||
|
||||
static JSValue js_os_read_write(JSContext *ctx, JSValueConst this_val,
|
||||
@ -1434,10 +1478,10 @@ static JSValue js_os_read_write(JSContext *ctx, JSValueConst this_val,
|
||||
if (pos + len > size)
|
||||
return JS_ThrowRangeError(ctx, "read/write array buffer overflow");
|
||||
if (magic)
|
||||
ret = write(fd, buf + pos, len);
|
||||
ret = js_get_errno(write(fd, buf + pos, len));
|
||||
else
|
||||
ret = read(fd, buf + pos, len);
|
||||
return js_os_return(ctx, ret);
|
||||
ret = js_get_errno(read(fd, buf + pos, len));
|
||||
return JS_NewInt64(ctx, ret);
|
||||
}
|
||||
|
||||
static JSValue js_os_isatty(JSContext *ctx, JSValueConst this_val,
|
||||
@ -1555,9 +1599,9 @@ static JSValue js_os_remove(JSContext *ctx, JSValueConst this_val,
|
||||
filename = JS_ToCString(ctx, argv[0]);
|
||||
if (!filename)
|
||||
return JS_EXCEPTION;
|
||||
ret = remove(filename);
|
||||
ret = js_get_errno(remove(filename));
|
||||
JS_FreeCString(ctx, filename);
|
||||
return js_os_return(ctx, ret);
|
||||
return JS_NewInt32(ctx, ret);
|
||||
}
|
||||
|
||||
static JSValue js_os_rename(JSContext *ctx, JSValueConst this_val,
|
||||
@ -1574,10 +1618,10 @@ static JSValue js_os_rename(JSContext *ctx, JSValueConst this_val,
|
||||
JS_FreeCString(ctx, oldpath);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
ret = rename(oldpath, newpath);
|
||||
ret = js_get_errno(rename(oldpath, newpath));
|
||||
JS_FreeCString(ctx, oldpath);
|
||||
JS_FreeCString(ctx, newpath);
|
||||
return js_os_return(ctx, ret);
|
||||
return JS_NewInt32(ctx, ret);
|
||||
}
|
||||
|
||||
static JSOSRWHandler *find_rh(int fd)
|
||||
@ -2018,7 +2062,7 @@ static JSValue js_os_getcwd(JSContext *ctx, JSValueConst this_val,
|
||||
|
||||
if (!getcwd(buf, sizeof(buf))) {
|
||||
buf[0] = '\0';
|
||||
err = -errno;
|
||||
err = errno;
|
||||
} else {
|
||||
err = 0;
|
||||
}
|
||||
@ -2036,9 +2080,9 @@ static JSValue js_os_chdir(JSContext *ctx, JSValueConst this_val,
|
||||
target = JS_ToCString(ctx, argv[0]);
|
||||
if (!target)
|
||||
return JS_EXCEPTION;
|
||||
err = chdir(target);
|
||||
err = js_get_errno(chdir(target));
|
||||
JS_FreeCString(ctx, target);
|
||||
return js_os_return(ctx, err);
|
||||
return JS_NewInt32(ctx, err);
|
||||
}
|
||||
|
||||
/* return [path, errorcode] */
|
||||
@ -2056,7 +2100,7 @@ static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val,
|
||||
JS_FreeCString(ctx, path);
|
||||
if (!res) {
|
||||
buf[0] = '\0';
|
||||
err = -errno;
|
||||
err = errno;
|
||||
} else {
|
||||
err = 0;
|
||||
}
|
||||
@ -2078,9 +2122,9 @@ static JSValue js_os_mkdir(JSContext *ctx, JSValueConst this_val,
|
||||
path = JS_ToCString(ctx, argv[0]);
|
||||
if (!path)
|
||||
return JS_EXCEPTION;
|
||||
ret = mkdir(path, mode);
|
||||
ret = js_get_errno(mkdir(path, mode));
|
||||
JS_FreeCString(ctx, path);
|
||||
return js_os_return(ctx, ret);
|
||||
return JS_NewInt32(ctx, ret);
|
||||
}
|
||||
|
||||
static int64_t timespec_to_ms(const struct timespec *tv)
|
||||
@ -2106,7 +2150,7 @@ static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val,
|
||||
res = stat(path, &st);
|
||||
JS_FreeCString(ctx, path);
|
||||
if (res < 0) {
|
||||
err = -errno;
|
||||
err = errno;
|
||||
obj = JS_NULL;
|
||||
} else {
|
||||
err = 0;
|
||||
@ -2179,10 +2223,10 @@ static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val,
|
||||
JS_FreeCString(ctx, target);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
err = symlink(target, linkpath);
|
||||
err = js_get_errno(symlink(target, linkpath));
|
||||
JS_FreeCString(ctx, target);
|
||||
JS_FreeCString(ctx, linkpath);
|
||||
return js_os_return(ctx, err);
|
||||
return JS_NewInt32(ctx, err);
|
||||
}
|
||||
|
||||
/* return [path, errorcode] */
|
||||
@ -2198,14 +2242,14 @@ static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val,
|
||||
if (!path)
|
||||
return JS_EXCEPTION;
|
||||
res = readlink(path, buf, sizeof(buf) - 1);
|
||||
JS_FreeCString(ctx, path);
|
||||
if (res < 0) {
|
||||
buf[0] = '\0';
|
||||
err = -errno;
|
||||
err = errno;
|
||||
} else {
|
||||
buf[res] = '\0';
|
||||
err = 0;
|
||||
}
|
||||
JS_FreeCString(ctx, path);
|
||||
return make_string_error(ctx, buf, err);
|
||||
}
|
||||
|
||||
@ -2229,18 +2273,19 @@ static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
f = opendir(path);
|
||||
if (!f)
|
||||
err = errno;
|
||||
else
|
||||
err = 0;
|
||||
JS_FreeCString(ctx, path);
|
||||
err = 0;
|
||||
if (!f) {
|
||||
err = -errno;
|
||||
if (!f)
|
||||
goto done;
|
||||
}
|
||||
len = 0;
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
d = readdir(f);
|
||||
if (!d) {
|
||||
err = -errno;
|
||||
err = errno;
|
||||
break;
|
||||
}
|
||||
JS_DefinePropertyValueUint32(ctx, obj, len++,
|
||||
@ -2275,9 +2320,9 @@ static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_EXCEPTION;
|
||||
ms_to_timeval(×[0], atime);
|
||||
ms_to_timeval(×[1], mtime);
|
||||
ret = utimes(path, times);
|
||||
ret = js_get_errno(utimes(path, times));
|
||||
JS_FreeCString(ctx, path);
|
||||
return js_os_return(ctx, ret);
|
||||
return JS_NewInt32(ctx, ret);
|
||||
}
|
||||
|
||||
/* exec(args[, options]) -> exitcode */
|
||||
@ -2486,8 +2531,8 @@ static JSValue js_os_kill(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_EXCEPTION;
|
||||
if (JS_ToInt32(ctx, &sig, argv[1]))
|
||||
return JS_EXCEPTION;
|
||||
ret = kill(pid, sig);
|
||||
return js_os_return(ctx, ret);
|
||||
ret = js_get_errno(kill(pid, sig));
|
||||
return JS_NewInt32(ctx, ret);
|
||||
}
|
||||
|
||||
/* sleep(delay_ms) */
|
||||
@ -2502,8 +2547,8 @@ static JSValue js_os_sleep(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_EXCEPTION;
|
||||
ts.tv_sec = delay / 1000;
|
||||
ts.tv_nsec = (delay % 1000) * 1000000;
|
||||
ret = nanosleep(&ts, NULL);
|
||||
return js_os_return(ctx, ret);
|
||||
ret = js_get_errno(nanosleep(&ts, NULL));
|
||||
return JS_NewInt32(ctx, ret);
|
||||
}
|
||||
|
||||
/* dup(fd) */
|
||||
@ -2514,8 +2559,8 @@ static JSValue js_os_dup(JSContext *ctx, JSValueConst this_val,
|
||||
|
||||
if (JS_ToInt32(ctx, &fd, argv[0]))
|
||||
return JS_EXCEPTION;
|
||||
ret = dup(fd);
|
||||
return js_os_return(ctx, ret);
|
||||
ret = js_get_errno(dup(fd));
|
||||
return JS_NewInt32(ctx, ret);
|
||||
}
|
||||
|
||||
/* dup2(fd) */
|
||||
@ -2528,8 +2573,8 @@ static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_EXCEPTION;
|
||||
if (JS_ToInt32(ctx, &fd2, argv[1]))
|
||||
return JS_EXCEPTION;
|
||||
ret = dup2(fd, fd2);
|
||||
return js_os_return(ctx, ret);
|
||||
ret = js_get_errno(dup2(fd, fd2));
|
||||
return JS_NewInt32(ctx, ret);
|
||||
}
|
||||
|
||||
#endif /* !_WIN32 */
|
||||
@ -2725,23 +2770,30 @@ void js_std_free_handlers(JSRuntime *rt)
|
||||
}
|
||||
}
|
||||
|
||||
static void js_std_dump_error1(JSContext *ctx, JSValueConst exception_val,
|
||||
BOOL is_throw)
|
||||
static void js_dump_obj(JSContext *ctx, FILE *f, JSValueConst val)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
str = JS_ToCString(ctx, val);
|
||||
if (str) {
|
||||
fprintf(f, "%s\n", str);
|
||||
JS_FreeCString(ctx, str);
|
||||
} else {
|
||||
fprintf(f, "[exception]\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void js_std_dump_error1(JSContext *ctx, JSValueConst exception_val)
|
||||
{
|
||||
JSValue val;
|
||||
const char *stack;
|
||||
BOOL is_error;
|
||||
|
||||
is_error = JS_IsError(ctx, exception_val);
|
||||
if (is_throw && !is_error)
|
||||
printf("Throw: ");
|
||||
js_print(ctx, JS_NULL, 1, (JSValueConst *)&exception_val);
|
||||
js_dump_obj(ctx, stderr, exception_val);
|
||||
if (is_error) {
|
||||
val = JS_GetPropertyStr(ctx, exception_val, "stack");
|
||||
if (!JS_IsUndefined(val)) {
|
||||
stack = JS_ToCString(ctx, val);
|
||||
printf("%s\n", stack);
|
||||
JS_FreeCString(ctx, stack);
|
||||
js_dump_obj(ctx, stderr, val);
|
||||
}
|
||||
JS_FreeValue(ctx, val);
|
||||
}
|
||||
@ -2752,7 +2804,7 @@ void js_std_dump_error(JSContext *ctx)
|
||||
JSValue exception_val;
|
||||
|
||||
exception_val = JS_GetException(ctx);
|
||||
js_std_dump_error1(ctx, exception_val, TRUE);
|
||||
js_std_dump_error1(ctx, exception_val);
|
||||
JS_FreeValue(ctx, exception_val);
|
||||
}
|
||||
|
||||
@ -2761,8 +2813,8 @@ void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise,
|
||||
BOOL is_handled, void *opaque)
|
||||
{
|
||||
if (!is_handled) {
|
||||
printf("Possibly unhandled promise rejection: ");
|
||||
js_std_dump_error1(ctx, reason, FALSE);
|
||||
fprintf(stderr, "Possibly unhandled promise rejection: ");
|
||||
js_std_dump_error1(ctx, reason);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,6 @@ DEF( eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */
|
||||
DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */
|
||||
DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
|
||||
bytecode string */
|
||||
DEF( get_super_ctor, 1, 1, 1, none)
|
||||
DEF( get_super, 1, 1, 1, none)
|
||||
DEF( import, 1, 1, 1, none) /* dynamic module import */
|
||||
|
||||
|
204
quickjs.c
204
quickjs.c
@ -284,6 +284,7 @@ struct JSRuntime {
|
||||
JSNumericOperations bigdecimal_ops;
|
||||
uint32_t operator_count;
|
||||
#endif
|
||||
void *user_opaque;
|
||||
};
|
||||
|
||||
struct JSClass {
|
||||
@ -1537,6 +1538,16 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *JS_GetRuntimeOpaque(JSRuntime *rt)
|
||||
{
|
||||
return rt->user_opaque;
|
||||
}
|
||||
|
||||
void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque)
|
||||
{
|
||||
rt->user_opaque = opaque;
|
||||
}
|
||||
|
||||
/* default memory allocation functions with memory limitation */
|
||||
static inline size_t js_def_malloc_usable_size(void *ptr)
|
||||
{
|
||||
@ -2198,26 +2209,6 @@ static inline BOOL is_math_mode(JSContext *ctx)
|
||||
}
|
||||
#endif
|
||||
|
||||
JSValue JS_NewInt64(JSContext *ctx, int64_t v)
|
||||
{
|
||||
if (v == (int32_t)v) {
|
||||
return JS_NewInt32(ctx, v);
|
||||
} else {
|
||||
return __JS_NewFloat64(ctx, (double)v);
|
||||
}
|
||||
}
|
||||
|
||||
static force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val)
|
||||
{
|
||||
JSValue v;
|
||||
if (val <= 0x7fffffff) {
|
||||
v = JS_MKVAL(JS_TAG_INT, val);
|
||||
} else {
|
||||
v = __JS_NewFloat64(ctx, val);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/* JSAtom support */
|
||||
|
||||
#define JS_ATOM_TAG_INT (1U << 31)
|
||||
@ -9794,6 +9785,8 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
|
||||
if (*p == '.' && (p > p_start || to_digit((uint8_t)p[1]) < radix)) {
|
||||
is_float = TRUE;
|
||||
p++;
|
||||
if (*p == sep)
|
||||
goto fail;
|
||||
while (to_digit((uint8_t)*p) < radix ||
|
||||
(*p == sep && to_digit((uint8_t)p[1]) < radix))
|
||||
p++;
|
||||
@ -10129,7 +10122,6 @@ static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
|
||||
ret = JS_NewInt32(ctx, 0);
|
||||
} else {
|
||||
/* convert -0 to +0 */
|
||||
/* XXX: should not be done here ? */
|
||||
d = trunc(d) + 0.0;
|
||||
ret = JS_NewFloat64(ctx, d);
|
||||
}
|
||||
@ -10385,6 +10377,14 @@ int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val)
|
||||
return JS_ToInt64Free(ctx, pres, JS_DupValue(ctx, val));
|
||||
}
|
||||
|
||||
int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val)
|
||||
{
|
||||
if (JS_IsBigInt(ctx, val))
|
||||
return JS_ToBigInt64(ctx, pres, val);
|
||||
else
|
||||
return JS_ToInt64(ctx, pres, val);
|
||||
}
|
||||
|
||||
/* return (<0, 0) in case of exception */
|
||||
static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val)
|
||||
{
|
||||
@ -11840,7 +11840,8 @@ static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val)
|
||||
}
|
||||
|
||||
/* must be kept in sync with JSOverloadableOperatorEnum */
|
||||
static const char *js_overloadable_operator_names[JS_OVOP_COUNT] = {
|
||||
/* XXX: use atoms ? */
|
||||
static const char js_overloadable_operator_names[JS_OVOP_COUNT][4] = {
|
||||
"+",
|
||||
"-",
|
||||
"*",
|
||||
@ -12894,7 +12895,7 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
|
||||
handle_bigint:
|
||||
if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))
|
||||
goto exception;
|
||||
} else if (tag1 == JS_TAG_FLOAT64 || tag2 == JS_TAG_FLOAT64) {
|
||||
} else {
|
||||
double dr;
|
||||
/* float64 result */
|
||||
if (JS_ToFloat64Free(ctx, &d1, op1)) {
|
||||
@ -13031,7 +13032,11 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
|
||||
} else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
|
||||
if (ctx->rt->bigfloat_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
|
||||
goto exception;
|
||||
} else if (tag1 == JS_TAG_FLOAT64 || tag2 == JS_TAG_FLOAT64) {
|
||||
} else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
|
||||
handle_bigint:
|
||||
if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
|
||||
goto exception;
|
||||
} else {
|
||||
double d1, d2;
|
||||
/* float64 result */
|
||||
if (JS_ToFloat64Free(ctx, &d1, op1)) {
|
||||
@ -13040,10 +13045,9 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
|
||||
}
|
||||
if (JS_ToFloat64Free(ctx, &d2, op2))
|
||||
goto exception;
|
||||
if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2))
|
||||
goto handle_bigint;
|
||||
sp[-2] = __JS_NewFloat64(ctx, d1 + d2);
|
||||
} else {
|
||||
if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
|
||||
goto exception;
|
||||
}
|
||||
return 0;
|
||||
exception:
|
||||
@ -13642,6 +13646,28 @@ static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp)
|
||||
|
||||
#else /* !CONFIG_BIGNUM */
|
||||
|
||||
static JSValue JS_ThrowUnsupportedBigint(JSContext *ctx)
|
||||
{
|
||||
return JS_ThrowTypeError(ctx, "bigint is not supported");
|
||||
}
|
||||
|
||||
JSValue JS_NewBigInt64(JSContext *ctx, int64_t v)
|
||||
{
|
||||
return JS_ThrowUnsupportedBigint(ctx);
|
||||
}
|
||||
|
||||
JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)
|
||||
{
|
||||
return JS_ThrowUnsupportedBigint(ctx);
|
||||
}
|
||||
|
||||
int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val)
|
||||
{
|
||||
JS_ThrowUnsupportedBigint(ctx);
|
||||
*pres = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
|
||||
JSValue *sp,
|
||||
OPCodeEnum op)
|
||||
@ -16280,22 +16306,6 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
|
||||
}
|
||||
BREAK;
|
||||
|
||||
CASE(OP_get_super_ctor):
|
||||
{
|
||||
JSValue proto;
|
||||
proto = JS_DupValue(ctx, JS_GetPrototype(ctx, sp[-1]));
|
||||
if (JS_IsException(proto))
|
||||
goto exception;
|
||||
if (!JS_IsConstructor(ctx, proto)) {
|
||||
JS_FreeValue(ctx, proto);
|
||||
JS_ThrowTypeError(ctx, "not a constructor");
|
||||
goto exception;
|
||||
}
|
||||
JS_FreeValue(ctx, sp[-1]);
|
||||
sp[-1] = proto;
|
||||
}
|
||||
BREAK;
|
||||
|
||||
CASE(OP_get_super):
|
||||
{
|
||||
JSValue proto;
|
||||
@ -23821,7 +23831,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
|
||||
emit_atom(s, JS_ATOM_this_active_func);
|
||||
emit_u16(s, 0);
|
||||
|
||||
emit_op(s, OP_get_super_ctor);
|
||||
emit_op(s, OP_get_super);
|
||||
|
||||
emit_op(s, OP_scope_get_var);
|
||||
emit_atom(s, JS_ATOM_new_target);
|
||||
@ -31993,10 +32003,10 @@ static __exception int js_parse_function_decl2(JSParseState *s,
|
||||
js_parse_expect(s, ')');
|
||||
goto fail;
|
||||
}
|
||||
if (s->token.val == ',') {
|
||||
if (next_token(s))
|
||||
goto fail;
|
||||
}
|
||||
if (s->token.val == ')')
|
||||
break;
|
||||
if (js_parse_expect(s, ','))
|
||||
goto fail;
|
||||
}
|
||||
if ((func_type == JS_PARSE_FUNC_GETTER && fd->arg_count != 0) ||
|
||||
(func_type == JS_PARSE_FUNC_SETTER && fd->arg_count != 1)) {
|
||||
@ -34381,6 +34391,10 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
|
||||
case JS_DEF_PROP_DOUBLE:
|
||||
val = __JS_NewFloat64(ctx, e->u.f64);
|
||||
break;
|
||||
case JS_DEF_OBJECT:
|
||||
val = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@ -37357,7 +37371,8 @@ static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target,
|
||||
JS_ThrowTypeError(ctx, "Array too long");
|
||||
goto fail;
|
||||
}
|
||||
if (JS_SetPropertyInt64(ctx, target, targetIndex, element) < 0)
|
||||
if (JS_DefinePropertyValueInt64(ctx, target, targetIndex, element,
|
||||
JS_PROP_C_W_E | JS_PROP_THROW) < 0)
|
||||
return -1;
|
||||
targetIndex++;
|
||||
}
|
||||
@ -37754,7 +37769,6 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = {
|
||||
JS_CFUNC_DEF("copyWithin", 2, js_array_copyWithin ),
|
||||
JS_CFUNC_MAGIC_DEF("flatMap", 1, js_array_flatten, 1 ),
|
||||
JS_CFUNC_MAGIC_DEF("flat", 0, js_array_flatten, 0 ),
|
||||
JS_CFUNC_MAGIC_DEF("flatten", 0, js_array_flatten, 0 ),
|
||||
JS_CFUNC_MAGIC_DEF("values", 0, js_create_array_iterator, JS_ITERATOR_KIND_VALUE ),
|
||||
JS_ALIAS_DEF("[Symbol.iterator]", "values" ),
|
||||
JS_CFUNC_MAGIC_DEF("keys", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY ),
|
||||
@ -39918,14 +39932,36 @@ static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val,
|
||||
if (JS_ToFloat64(ctx, &b, argv[1]))
|
||||
return JS_EXCEPTION;
|
||||
r = hypot(a, b);
|
||||
} else {
|
||||
} else if (argc == 0) {
|
||||
r = 0;
|
||||
} else {
|
||||
double *tab, a_max;
|
||||
tab = js_malloc(ctx, sizeof(tab[0]) * argc);
|
||||
if (!tab)
|
||||
return JS_EXCEPTION;
|
||||
/* avoid overflow by taking the maximum */
|
||||
a_max = 0;
|
||||
for(i = 0; i < argc; i++) {
|
||||
if (JS_ToFloat64(ctx, &a, argv[i]))
|
||||
if (JS_ToFloat64(ctx, &a, argv[i])) {
|
||||
js_free(ctx, tab);
|
||||
return JS_EXCEPTION;
|
||||
r += a;
|
||||
}
|
||||
a = fabs(a);
|
||||
tab[i] = a;
|
||||
if (a > a_max)
|
||||
a_max = a;
|
||||
}
|
||||
r = sqrt(r);
|
||||
if (a_max == 0 || !isfinite(a_max)) {
|
||||
r = a_max;
|
||||
} else {
|
||||
r = 0;
|
||||
for(i = 0; i < argc; i++) {
|
||||
a = tab[i] / a_max;
|
||||
r += a * a;
|
||||
}
|
||||
r = a_max * sqrt(r);
|
||||
}
|
||||
js_free(ctx, tab);
|
||||
}
|
||||
return JS_NewFloat64(ctx, r);
|
||||
}
|
||||
@ -45234,10 +45270,10 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va
|
||||
}
|
||||
JS_FreeValue(ctx, ret);
|
||||
if (magic == 0) {
|
||||
then_func = JS_NewCFunctionData(ctx, js_promise_finally_value_thunk, 1,
|
||||
then_func = JS_NewCFunctionData(ctx, js_promise_finally_value_thunk, 0,
|
||||
0, 1, argv);
|
||||
} else {
|
||||
then_func = JS_NewCFunctionData(ctx, js_promise_finally_thrower, 1,
|
||||
then_func = JS_NewCFunctionData(ctx, js_promise_finally_thrower, 0,
|
||||
0, 1, argv);
|
||||
}
|
||||
if (JS_IsException(then_func)) {
|
||||
@ -50037,7 +50073,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv, int special)
|
||||
{
|
||||
JSObject *p;
|
||||
int len, tag, is_int, is_big, k, stop, inc, res = -1;
|
||||
int len, tag, is_int, is_bigint, k, stop, inc, res = -1;
|
||||
int64_t v64;
|
||||
double d;
|
||||
float f;
|
||||
@ -50080,7 +50116,11 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
|
||||
inc = 1;
|
||||
}
|
||||
|
||||
is_big = 0;
|
||||
if (validate_typed_array(ctx, this_val))
|
||||
goto exception;
|
||||
p = JS_VALUE_GET_OBJ(this_val);
|
||||
|
||||
is_bigint = 0;
|
||||
is_int = 0; /* avoid warning */
|
||||
v64 = 0; /* avoid warning */
|
||||
tag = JS_VALUE_GET_NORM_TAG(argv[0]);
|
||||
@ -50095,10 +50135,20 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
|
||||
is_int = (v64 == d);
|
||||
} else
|
||||
#ifdef CONFIG_BIGNUM
|
||||
if (tag == JS_TAG_BIG_INT || tag == JS_TAG_BIG_FLOAT) {
|
||||
/* will a generic loop for bigint and bigfloat */
|
||||
/* XXX: should use the generic loop in math_mode? */
|
||||
is_big = 1;
|
||||
if (tag == JS_TAG_BIG_INT) {
|
||||
JSBigFloat *p1 = JS_VALUE_GET_PTR(argv[0]);
|
||||
|
||||
if (p->class_id == JS_CLASS_BIG_INT64_ARRAY) {
|
||||
if (bf_get_int64(&v64, &p1->num, 0) != 0)
|
||||
goto done;
|
||||
} else if (p->class_id == JS_CLASS_BIG_UINT64_ARRAY) {
|
||||
if (bf_get_uint64((uint64_t *)&v64, &p1->num) != 0)
|
||||
goto done;
|
||||
} else {
|
||||
goto done;
|
||||
}
|
||||
d = 0;
|
||||
is_bigint = 1;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@ -50172,7 +50222,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
|
||||
}
|
||||
break;
|
||||
case JS_CLASS_FLOAT32_ARRAY:
|
||||
if (is_big)
|
||||
if (is_bigint)
|
||||
break;
|
||||
if (isnan(d)) {
|
||||
const float *pv = p->u.array.u.float_ptr;
|
||||
@ -50196,7 +50246,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
|
||||
}
|
||||
break;
|
||||
case JS_CLASS_FLOAT64_ARRAY:
|
||||
if (is_big)
|
||||
if (is_bigint)
|
||||
break;
|
||||
if (isnan(d)) {
|
||||
const double *pv = p->u.array.u.double_ptr;
|
||||
@ -50221,20 +50271,22 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
|
||||
break;
|
||||
#ifdef CONFIG_BIGNUM
|
||||
case JS_CLASS_BIG_INT64_ARRAY:
|
||||
if (is_bigint || (is_math_mode(ctx) && is_int &&
|
||||
v64 >= -MAX_SAFE_INTEGER &&
|
||||
v64 <= MAX_SAFE_INTEGER)) {
|
||||
goto scan64;
|
||||
}
|
||||
break;
|
||||
case JS_CLASS_BIG_UINT64_ARRAY:
|
||||
if (is_big || is_strict_mode(ctx)) {
|
||||
/* generic loop for bignums, argv[0] is a bignum != NaN */
|
||||
/* XXX: optimize with explicit values */
|
||||
if (is_bigint || (is_math_mode(ctx) && is_int &&
|
||||
v64 >= 0 && v64 <= MAX_SAFE_INTEGER)) {
|
||||
const uint64_t *pv;
|
||||
uint64_t v;
|
||||
scan64:
|
||||
pv = p->u.array.u.uint64_ptr;
|
||||
v = v64;
|
||||
for (; k != stop; k += inc) {
|
||||
JSValue v = JS_GetPropertyUint32(ctx, this_val, k);
|
||||
int ret;
|
||||
if (JS_IsException(v))
|
||||
goto exception;
|
||||
ret = js_same_value_zero(ctx, v, argv[0]);
|
||||
JS_FreeValue(ctx, v);
|
||||
if (ret) {
|
||||
if (ret < 0)
|
||||
goto exception;
|
||||
if (pv[k] == v) {
|
||||
res = k;
|
||||
break;
|
||||
}
|
||||
|
28
quickjs.h
28
quickjs.h
@ -335,6 +335,8 @@ void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
|
||||
void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
|
||||
JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque);
|
||||
void JS_FreeRuntime(JSRuntime *rt);
|
||||
void *JS_GetRuntimeOpaque(JSRuntime *rt);
|
||||
void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque);
|
||||
typedef void JS_MarkFunc(JSRuntime *rt, JSGCObjectHeader *gp);
|
||||
void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
|
||||
void JS_RunGC(JSRuntime *rt);
|
||||
@ -508,7 +510,28 @@ static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val)
|
||||
return JS_MKVAL(JS_TAG_CATCH_OFFSET, val);
|
||||
}
|
||||
|
||||
JSValue JS_NewInt64(JSContext *ctx, int64_t v);
|
||||
static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val)
|
||||
{
|
||||
JSValue v;
|
||||
if (val == (int32_t)val) {
|
||||
v = JS_NewInt32(ctx, val);
|
||||
} else {
|
||||
v = __JS_NewFloat64(ctx, val);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val)
|
||||
{
|
||||
JSValue v;
|
||||
if (val <= 0x7fffffff) {
|
||||
v = JS_NewInt32(ctx, val);
|
||||
} else {
|
||||
v = __JS_NewFloat64(ctx, val);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
JSValue JS_NewBigInt64(JSContext *ctx, int64_t v);
|
||||
JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v);
|
||||
|
||||
@ -657,7 +680,10 @@ static int inline JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
|
||||
int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val);
|
||||
int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val);
|
||||
int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val);
|
||||
/* return an exception if 'val' is a Number */
|
||||
int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val);
|
||||
/* same as JS_ToInt64() but allow BigInt */
|
||||
int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val);
|
||||
|
||||
JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1);
|
||||
JSValue JS_NewString(JSContext *ctx, const char *str);
|
||||
|
21
release.sh
21
release.sh
@ -50,21 +50,30 @@ fi
|
||||
|
||||
if [ "$binary" = "yes" ] ; then
|
||||
|
||||
make -j4 qjs run-test262
|
||||
make -j4 CONFIG_M32=y qjs32 run-test262-32
|
||||
strip qjs run-test262 qjs32 run-test262-32
|
||||
|
||||
d="quickjs-linux-x86_64-${version}"
|
||||
name="quickjs-linux-x86_64-${version}"
|
||||
outdir="/tmp/${d}"
|
||||
|
||||
rm -rf $outdir
|
||||
mkdir -p $outdir
|
||||
|
||||
files="qjs run-test262"
|
||||
cp qjs run-test262 $outdir
|
||||
|
||||
make -j4 $files
|
||||
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
|
||||
|
||||
strip $files
|
||||
cp $files $outdir
|
||||
d="quickjs-linux-i686-${version}"
|
||||
outdir="/tmp/${d}"
|
||||
|
||||
( cd /tmp/$d && rm -f ../${name}.zip && zip -r ../${name}.zip . )
|
||||
rm -rf $outdir
|
||||
mkdir -p $outdir
|
||||
|
||||
cp qjs32 $outdir/qjs
|
||||
cp run-test262-32 $outdir/run-test262
|
||||
|
||||
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
|
||||
|
||||
fi
|
||||
|
||||
|
@ -385,8 +385,11 @@ static JSValue js_print(JSContext *ctx, JSValueConst this_val,
|
||||
str = JS_ToCString(ctx, argv[i]);
|
||||
if (!str)
|
||||
return JS_EXCEPTION;
|
||||
if (!strcmp(str, "Test262:AsyncTestComplete"))
|
||||
if (!strcmp(str, "Test262:AsyncTestComplete")) {
|
||||
async_done++;
|
||||
} else if (strstart(str, "Test262:AsyncTestFailure", NULL)) {
|
||||
async_done = 2; /* force an error */
|
||||
}
|
||||
fputs(str, outfile);
|
||||
JS_FreeCString(ctx, str);
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ destructuring-binding
|
||||
dynamic-import
|
||||
export-star-as-namespace-from-module
|
||||
FinalizationGroup=skip
|
||||
FinalizationRegistry=skip
|
||||
Float32Array
|
||||
Float64Array
|
||||
for-in-order
|
||||
|
@ -1,17 +1,22 @@
|
||||
test262/test/language/expressions/arrow-function/eval-var-scope-syntax-err.js:47: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/language/expressions/async-arrow-function/eval-var-scope-syntax-err.js:49: TypeError: $DONE() not called
|
||||
test262/test/language/expressions/async-function/named-eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called
|
||||
test262/test/language/expressions/async-function/nameless-eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called
|
||||
test262/test/language/expressions/async-generator/eval-var-scope-syntax-err.js:28: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/language/expressions/async-generator/named-eval-var-scope-syntax-err.js:28: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/language/expressions/class/super-evaluation-order.js:26: Test262Error: via ArgumentListEvaluation Expected SameValue(«0», «123») to be true
|
||||
test262/test/language/expressions/class/super-evaluation-order.js:26: strict mode: Test262Error: via ArgumentListEvaluation Expected SameValue(«0», «123») to be true
|
||||
test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: TypeError: $DONE() not called
|
||||
test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: strict mode: TypeError: $DONE() not called
|
||||
test262/test/language/expressions/function/eval-var-scope-syntax-err.js:48: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/language/expressions/generators/eval-var-scope-syntax-err.js:49: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/language/expressions/object/method-definition/async-gen-meth-eval-var-scope-syntax-err.js:32: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/language/expressions/object/method-definition/async-meth-eval-var-scope-syntax-err.js:36: TypeError: $DONE() not called
|
||||
test262/test/language/expressions/object/method-definition/gen-meth-eval-var-scope-syntax-err.js:54: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/language/expressions/object/method-definition/meth-eval-var-scope-syntax-err.js:50: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:21: TypeError: value has no property
|
||||
test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:15: strict mode: TypeError: value has no property
|
||||
test262/test/language/statements/async-function/eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called
|
||||
test262/test/language/statements/async-generator/eval-var-scope-syntax-err.js:28: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/language/statements/for-await-of/async-gen-decl-dstr-array-elem-iter-rtrn-close-null.js:81: TypeError: $DONE() not called
|
||||
test262/test/language/statements/for-await-of/async-gen-decl-dstr-array-elem-iter-rtrn-close-null.js:81: strict mode: TypeError: $DONE() not called
|
||||
test262/test/language/statements/function/eval-var-scope-syntax-err.js:49: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/language/statements/generators/eval-var-scope-syntax-err.js:49: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
|
@ -917,11 +917,9 @@ function load_result(filename)
|
||||
var f, str, res;
|
||||
if (typeof std === "undefined")
|
||||
return null;
|
||||
try {
|
||||
f = std.open(filename, "r");
|
||||
} catch(e) {
|
||||
f = std.open(filename, "r");
|
||||
if (!f)
|
||||
return null;
|
||||
}
|
||||
str = f.readAsString();
|
||||
res = JSON.parse(str);
|
||||
f.close();
|
||||
|
@ -501,6 +501,10 @@ function test_regexp()
|
||||
a = eval("/\0a/");
|
||||
assert(a.toString(), "/\0a/");
|
||||
assert(a.exec("\0a")[0], "\0a");
|
||||
|
||||
assert(/{1a}/.toString(), "/{1a}/");
|
||||
a = /a{1+/.exec("a{11");
|
||||
assert(a, ["a{11"] );
|
||||
}
|
||||
|
||||
function test_symbol()
|
||||
|
@ -106,6 +106,9 @@ function test_popen()
|
||||
f.puts(content);
|
||||
f.close();
|
||||
|
||||
/* test loadFile */
|
||||
assert(std.loadFile(fname), content);
|
||||
|
||||
/* execute the 'cat' shell command */
|
||||
f = std.popen("cat " + fname, "r");
|
||||
str = f.readAsString();
|
||||
@ -142,13 +145,19 @@ function test_os()
|
||||
buf[i] = i;
|
||||
assert(os.write(fd, buf.buffer, 0, buf.length) === buf.length);
|
||||
|
||||
assert(os.seek(fd, 0, os.SEEK_SET) === 0);
|
||||
assert(os.seek(fd, 0, std.SEEK_SET) === 0);
|
||||
buf2 = new Uint8Array(buf.length);
|
||||
assert(os.read(fd, buf2.buffer, 0, buf2.length) === buf2.length);
|
||||
|
||||
for(i = 0; i < buf.length; i++)
|
||||
assert(buf[i] == buf2[i]);
|
||||
|
||||
if (typeof BigInt !== "undefined") {
|
||||
assert(os.seek(fd, BigInt(6), std.SEEK_SET), BigInt(6));
|
||||
assert(os.read(fd, buf2.buffer, 0, 1) === 1);
|
||||
assert(buf[6] == buf2[0]);
|
||||
}
|
||||
|
||||
assert(os.close(fd) === 0);
|
||||
|
||||
[files, err] = os.readdir(fdir);
|
||||
|
@ -1,8 +1,8 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
url="ftp://ftp.unicode.org/Public/12.1.0/ucd"
|
||||
emoji_url="ftp://ftp.unicode.org/Public/emoji/12.0/emoji-data.txt"
|
||||
url="ftp://ftp.unicode.org/Public/13.0.0/ucd"
|
||||
emoji_url="${url}/emoji/emoji-data.txt"
|
||||
|
||||
files="CaseFolding.txt DerivedNormalizationProps.txt PropList.txt \
|
||||
SpecialCasing.txt CompositionExclusions.txt ScriptExtensions.txt \
|
||||
@ -11,9 +11,9 @@ PropertyValueAliases.txt"
|
||||
|
||||
mkdir -p unicode
|
||||
|
||||
for f in $files; do
|
||||
g="${url}/${f}"
|
||||
wget $g -O unicode/$f
|
||||
done
|
||||
#for f in $files; do
|
||||
# g="${url}/${f}"
|
||||
# wget $g -O unicode/$f
|
||||
#done
|
||||
|
||||
wget $emoji_url -O unicode/emoji-data.txt
|
||||
|
@ -66,6 +66,7 @@ DEF(Caucasian_Albanian, "Aghb")
|
||||
DEF(Chakma, "Cakm")
|
||||
DEF(Cham, "Cham")
|
||||
DEF(Cherokee, "Cher")
|
||||
DEF(Chorasmian, "Chrs")
|
||||
DEF(Common, "Zyyy")
|
||||
DEF(Coptic, "Copt,Qaac")
|
||||
DEF(Cuneiform, "Xsux")
|
||||
@ -73,6 +74,7 @@ DEF(Cypriot, "Cprt")
|
||||
DEF(Cyrillic, "Cyrl")
|
||||
DEF(Deseret, "Dsrt")
|
||||
DEF(Devanagari, "Deva")
|
||||
DEF(Dives_Akuru, "Diak")
|
||||
DEF(Dogra, "Dogr")
|
||||
DEF(Duployan, "Dupl")
|
||||
DEF(Egyptian_Hieroglyphs, "Egyp")
|
||||
@ -106,6 +108,7 @@ DEF(Kayah_Li, "Kali")
|
||||
DEF(Kharoshthi, "Khar")
|
||||
DEF(Khmer, "Khmr")
|
||||
DEF(Khojki, "Khoj")
|
||||
DEF(Khitan_Small_Script, "Kits")
|
||||
DEF(Khudawadi, "Sind")
|
||||
DEF(Lao, "Laoo")
|
||||
DEF(Latin, "Latn")
|
||||
@ -193,6 +196,7 @@ DEF(Ugaritic, "Ugar")
|
||||
DEF(Vai, "Vaii")
|
||||
DEF(Wancho, "Wcho")
|
||||
DEF(Warang_Citi, "Wara")
|
||||
DEF(Yezidi, "Yezi")
|
||||
DEF(Yi, "Yiii")
|
||||
DEF(Zanabazar_Square, "Zanb")
|
||||
#endif
|
||||
@ -244,11 +248,11 @@ DEF(Variation_Selector, "VS")
|
||||
DEF(White_Space, "space")
|
||||
DEF(Bidi_Mirrored, "Bidi_M")
|
||||
DEF(Emoji, "")
|
||||
DEF(Emoji_Component, "")
|
||||
DEF(Emoji_Modifier, "")
|
||||
DEF(Emoji_Modifier_Base, "")
|
||||
DEF(Emoji_Presentation, "")
|
||||
DEF(Extended_Pictographic, "")
|
||||
DEF(Emoji_Component, "EComp")
|
||||
DEF(Emoji_Modifier, "EMod")
|
||||
DEF(Emoji_Modifier_Base, "EBase")
|
||||
DEF(Emoji_Presentation, "EPres")
|
||||
DEF(Extended_Pictographic, "ExtPict")
|
||||
DEF(Default_Ignorable_Code_Point, "DI")
|
||||
DEF(ID_Start, "IDS")
|
||||
DEF(Case_Ignorable, "CI")
|
||||
|
Loading…
Reference in New Issue
Block a user