Browse Source

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
pull/12/head
Horunabu Hofutenho 11 months ago
parent
commit
5c5fedb943
No known key found for this signature in database GPG Key ID: 7EB80FA93BC3054C
26 changed files with 2347 additions and 2015 deletions
  1. +11
    -0
      Changelog
  2. +3
    -2
      TODO
  3. +1
    -1
      VERSION
  4. +15
    -18
      doc/jsbignum.html
  5. BIN
      doc/jsbignum.pdf
  6. +13
    -16
      doc/jsbignum.texi
  7. +79
    -52
      doc/quickjs.html
  8. BIN
      doc/quickjs.pdf
  9. +74
    -50
      doc/quickjs.texi
  10. +40
    -7
      libbf.c
  11. +1
    -0
      libbf.h
  12. +58
    -34
      libregexp.c
  13. +1619
    -1564
      libunicode-table.h
  14. +220
    -168
      quickjs-libc.c
  15. +0
    -1
      quickjs-opcode.h
  16. +128
    -76
      quickjs.c
  17. +27
    -1
      quickjs.h
  18. +15
    -6
      release.sh
  19. +4
    -1
      run-test262.c
  20. +1
    -0
      test262.conf
  21. +7
    -2
      test262_errors.txt
  22. +2
    -4
      tests/microbench.js
  23. +4
    -0
      tests/test_builtin.js
  24. +10
    -1
      tests/test_std.js
  25. +6
    -6
      unicode_download.sh
  26. +9
    -5
      unicode_gen_def.h

+ 11
- 0
Changelog View File

@ -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

+ 3
- 2
TODO View File

@ -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
- 1
VERSION View File

@ -1 +1 @@
2020-01-19
2020-03-16

+ 15
- 18
doc/jsbignum.html View File

@ -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 a < 0.
<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> (&ldquo;round to nearest with ties to even&rdquo;)<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 113.
</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 &lt;
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,11 +699,11 @@ 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 modulo operator (<code>%</code>) returns the Euclidian remainder (always positive) instead of the truncated remainder.
</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 integer division operator can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
</li><li> The modulo operator (<code>%</code>) returns the Euclidian remainder (always positive) instead of the truncated remainder.
</li><li> The integer power operator with a non zero negative exponent can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
</li></ul>

BIN
doc/jsbignum.pdf View File


+ 13
- 16
doc/jsbignum.texi View File

@ -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,11 +578,11 @@ 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 modulo operator (@code{%}) returns the Euclidian remainder (always positive) instead of the truncated remainder.
@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 integer division operator can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
@item The modulo operator (@code{%}) returns the Euclidian remainder (always positive) instead of the truncated remainder.
@item The integer power operator with a non zero negative exponent can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
@end itemize

+ 79
- 52
doc/quickjs.html View File

@ -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>).
<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>
<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>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>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>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)</code></dt>
<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 &lt; 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 &lt; 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 err 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 View File


+ 74
- 50
doc/quickjs.texi View File

@ -373,44 +373,35 @@ optional properties:
@item loadScript(filename)
Evaluate the file @code{filename} as a script (global eval).
@item Error(errno)
@code{std.Error} constructor. Error instances contain the field
@code{errno} (error code) and @code{message} (result of
@code{std.Error.strerror(errno)}).
The constructor contains the following fields:
@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 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.
@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.
@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.
@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}.

+ 40
- 7
libbf.c View File

@ -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
- 0
libbf.h View File

@ -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);

+ 58
- 34
libregexp.c View File

@ -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 == '?') {

+ 1619
- 1564
libunicode-table.h
File diff suppressed because it is too large
View File


+ 220
- 168
quickjs-libc.c View File

@ -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;
}
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);
if (ret == -1)
ret = -errno;
return ret;
}
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,12 +689,20 @@ 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)
goto fail;
@ -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,7 +737,8 @@ 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)
goto fail;
@ -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,6 +1293,23 @@ static JSClassDef js_std_file_class = {
.finalizer = js_std_file_finalizer,
};
static const JSCFunctionListEntry js_std_error_props[] = {
/* various errno values */
#define DEF(x) JS_PROP_INT32_DEF(#x, x, JS_PROP_CONFIGURABLE )
DEF(EINVAL),
DEF(EIO),
DEF(EACCES),
DEF(EEXIST),
DEF(ENOSPC),
DEF(ENOSYS),
DEF(EBUSY),
DEF(ENOENT),
DEF(EPERM),
DEF(EPIPE),
DEF(EBADF),
#undef DEF
};
static const JSCFunctionListEntry js_std_funcs[] = {
JS_CFUNC_DEF("exit", 1, js_std_exit ),
JS_CFUNC_DEF("gc", 0, js_std_gc ),
@ -1252,7 +1317,9 @@ static const JSCFunctionListEntry js_std_funcs[] = {
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 ),
@ -1264,49 +1331,34 @@ static const JSCFunctionListEntry js_std_funcs[] = {
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_error_funcs[] = {
JS_CFUNC_DEF("strerror", 1, js_std_error_strerror ),
/* various errno values */
#define DEF(x) JS_PROP_INT32_DEF(#x, x, JS_PROP_CONFIGURABLE )
DEF(EINVAL),
DEF(EIO),
DEF(EACCES),
DEF(EEXIST),
DEF(ENOSPC),
DEF(ENOSYS),
DEF(EBUSY),
DEF(ENOENT),
DEF(EPERM),
DEF(EPIPE),
DEF(EBADF),
#undef DEF
};
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,