mirror of
https://github.com/bellard/quickjs.git
synced 2024-11-22 21:58:12 +08:00
2020-04-12 release
This commit is contained in:
parent
383e2b06c8
commit
1722758717
@ -1,3 +1,10 @@
|
|||||||
|
2020-04-12:
|
||||||
|
|
||||||
|
- added cross realm support
|
||||||
|
- added AggregateError and Promise.any
|
||||||
|
- added env, uid and gid options in os.exec()
|
||||||
|
- misc bug fixes
|
||||||
|
|
||||||
2020-03-16:
|
2020-03-16:
|
||||||
|
|
||||||
- reworked error handling in std and os libraries: suppressed I/O
|
- reworked error handling in std and os libraries: suppressed I/O
|
||||||
|
4
TODO
4
TODO
@ -73,6 +73,6 @@ REPL:
|
|||||||
Test262o: 0/11262 errors, 463 excluded
|
Test262o: 0/11262 errors, 463 excluded
|
||||||
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
||||||
|
|
||||||
Test262: 22/70040 errors, 860 excluded, 581 skipped
|
Test262: 28/70829 errors, 877 excluded, 425 skipped
|
||||||
test262 commit: 25c9e334d301944537215caba1d7f44319f3e0da
|
Test262 commit: 4a8e49b3ca7f9f74a4cafe6621ff9ba548ccc353
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ ul.no-bullet {list-style: none}
|
|||||||
<ul class="no-bullet">
|
<ul class="no-bullet">
|
||||||
<li><a name="toc-Language-support" href="#Language-support">3.1 Language support</a>
|
<li><a name="toc-Language-support" href="#Language-support">3.1 Language support</a>
|
||||||
<ul class="no-bullet">
|
<ul class="no-bullet">
|
||||||
<li><a name="toc-ES2019-support" href="#ES2019-support">3.1.1 ES2019 support</a></li>
|
<li><a name="toc-ES2020-support" href="#ES2020-support">3.1.1 ES2020 support</a></li>
|
||||||
<li><a name="toc-JSON" href="#JSON">3.1.2 JSON</a></li>
|
<li><a name="toc-JSON" href="#JSON">3.1.2 JSON</a></li>
|
||||||
<li><a name="toc-ECMA402" href="#ECMA402">3.1.3 ECMA402</a></li>
|
<li><a name="toc-ECMA402" href="#ECMA402">3.1.3 ECMA402</a></li>
|
||||||
<li><a name="toc-Extensions" href="#Extensions">3.1.4 Extensions</a></li>
|
<li><a name="toc-Extensions" href="#Extensions">3.1.4 Extensions</a></li>
|
||||||
@ -130,7 +130,7 @@ ul.no-bullet {list-style: none}
|
|||||||
<h2 class="chapter">1 Introduction</h2>
|
<h2 class="chapter">1 Introduction</h2>
|
||||||
|
|
||||||
<p>QuickJS is a small and embeddable Javascript engine. It supports the
|
<p>QuickJS is a small and embeddable Javascript engine. It supports the
|
||||||
upcoming ES2020 specification
|
ES2020 specification
|
||||||
<a name="DOCF1" href="#FOOT1"><sup>1</sup></a>
|
<a name="DOCF1" href="#FOOT1"><sup>1</sup></a>
|
||||||
including modules, asynchronous generators, proxies and BigInt.
|
including modules, asynchronous generators, proxies and BigInt.
|
||||||
</p>
|
</p>
|
||||||
@ -146,12 +146,12 @@ and operator overloading.
|
|||||||
|
|
||||||
</li><li> Fast interpreter with very low startup time: runs the 69000 tests of the ECMAScript Test Suite<a name="DOCF2" href="#FOOT2"><sup>2</sup></a> in about 95 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
|
</li><li> Fast interpreter with very low startup time: runs the 69000 tests of the ECMAScript Test Suite<a name="DOCF2" href="#FOOT2"><sup>2</sup></a> in about 95 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
|
||||||
|
|
||||||
</li><li> Almost complete ES2019 support including modules, asynchronous
|
</li><li> Almost complete ES2020 support including modules, asynchronous
|
||||||
generators and full Annex B support (legacy web compatibility). Many
|
generators and full Annex B support (legacy web compatibility). Many
|
||||||
features from the upcoming ES2020 specification
|
features from the upcoming ES2021 specification
|
||||||
<a name="DOCF3" href="#FOOT3"><sup>3</sup></a> are also supported.
|
<a name="DOCF3" href="#FOOT3"><sup>3</sup></a> are also supported.
|
||||||
|
|
||||||
</li><li> Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2019 features.
|
</li><li> Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2020 features.
|
||||||
|
|
||||||
</li><li> Compile Javascript sources to executables with no external dependency.
|
</li><li> Compile Javascript sources to executables with no external dependency.
|
||||||
|
|
||||||
@ -394,18 +394,16 @@ about 100 seconds).
|
|||||||
<a name="Language-support"></a>
|
<a name="Language-support"></a>
|
||||||
<h3 class="section">3.1 Language support</h3>
|
<h3 class="section">3.1 Language support</h3>
|
||||||
|
|
||||||
<a name="ES2019-support"></a>
|
<a name="ES2020-support"></a>
|
||||||
<h4 class="subsection">3.1.1 ES2019 support</h4>
|
<h4 class="subsection">3.1.1 ES2020 support</h4>
|
||||||
|
|
||||||
<p>The ES2019 specification is almost fully supported including the Annex
|
<p>The ES2020 specification is almost fully supported including the Annex
|
||||||
B (legacy web compatibility) and the Unicode related features.
|
B (legacy web compatibility) and the Unicode related features.
|
||||||
</p>
|
</p>
|
||||||
<p>The following features are not supported yet:
|
<p>The following features are not supported yet:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li> Realms (although the C API supports different runtimes and contexts)
|
<li> Tail calls<a name="DOCF6" href="#FOOT6"><sup>6</sup></a>
|
||||||
|
|
||||||
</li><li> Tail calls<a name="DOCF6" href="#FOOT6"><sup>6</sup></a>
|
|
||||||
|
|
||||||
</li></ul>
|
</li></ul>
|
||||||
|
|
||||||
@ -918,6 +916,20 @@ object containing optional parameters:
|
|||||||
<dd><p>If present, set the handle in the child for stdin, stdout or stderr.
|
<dd><p>If present, set the handle in the child for stdin, stdout or stderr.
|
||||||
</p>
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
|
<dt><code>env</code></dt>
|
||||||
|
<dd><p>Object. If present, set the process environment from the object
|
||||||
|
key-value pairs. Otherwise use the same environment as the current
|
||||||
|
process.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
<dt><code>uid</code></dt>
|
||||||
|
<dd><p>Integer. If present, the process uid with <code>setuid</code>.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
<dt><code>gid</code></dt>
|
||||||
|
<dd><p>Integer. If present, the process gid with <code>setgid</code>.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
@ -1266,7 +1278,7 @@ Bellard and Charlie Gordon.
|
|||||||
<h4 class="footnotes-heading">Footnotes</h4>
|
<h4 class="footnotes-heading">Footnotes</h4>
|
||||||
|
|
||||||
<h3><a name="FOOT1" href="#DOCF1">(1)</a></h3>
|
<h3><a name="FOOT1" href="#DOCF1">(1)</a></h3>
|
||||||
<p><a href="https://www.ecma-international.org/ecma-262/10.0">https://www.ecma-international.org/ecma-262/10.0</a></p>
|
<p><a href="https://tc39.es/ecma262/">https://tc39.es/ecma262/</a></p>
|
||||||
<h3><a name="FOOT2" href="#DOCF2">(2)</a></h3>
|
<h3><a name="FOOT2" href="#DOCF2">(2)</a></h3>
|
||||||
<p><a href="https://github.com/tc39/test262">https://github.com/tc39/test262</a></p>
|
<p><a href="https://github.com/tc39/test262">https://github.com/tc39/test262</a></p>
|
||||||
<h3><a name="FOOT3" href="#DOCF3">(3)</a></h3>
|
<h3><a name="FOOT3" href="#DOCF3">(3)</a></h3>
|
||||||
|
BIN
doc/quickjs.pdf
BIN
doc/quickjs.pdf
Binary file not shown.
@ -20,8 +20,8 @@
|
|||||||
@chapter Introduction
|
@chapter Introduction
|
||||||
|
|
||||||
QuickJS is a small and embeddable Javascript engine. It supports the
|
QuickJS is a small and embeddable Javascript engine. It supports the
|
||||||
upcoming ES2020 specification
|
ES2020 specification
|
||||||
@footnote{@url{https://www.ecma-international.org/ecma-262/10.0}}
|
@footnote{@url{https://tc39.es/ecma262/}}
|
||||||
including modules, asynchronous generators, proxies and BigInt.
|
including modules, asynchronous generators, proxies and BigInt.
|
||||||
|
|
||||||
It supports mathematical extensions such as big decimal float float
|
It supports mathematical extensions such as big decimal float float
|
||||||
@ -36,12 +36,12 @@ and operator overloading.
|
|||||||
|
|
||||||
@item Fast interpreter with very low startup time: runs the 69000 tests of the ECMAScript Test Suite@footnote{@url{https://github.com/tc39/test262}} in about 95 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
|
@item Fast interpreter with very low startup time: runs the 69000 tests of the ECMAScript Test Suite@footnote{@url{https://github.com/tc39/test262}} in about 95 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
|
||||||
|
|
||||||
@item Almost complete ES2019 support including modules, asynchronous
|
@item Almost complete ES2020 support including modules, asynchronous
|
||||||
generators and full Annex B support (legacy web compatibility). Many
|
generators and full Annex B support (legacy web compatibility). Many
|
||||||
features from the upcoming ES2020 specification
|
features from the upcoming ES2021 specification
|
||||||
@footnote{@url{https://tc39.github.io/ecma262/}} are also supported.
|
@footnote{@url{https://tc39.github.io/ecma262/}} are also supported.
|
||||||
|
|
||||||
@item Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2019 features.
|
@item Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2020 features.
|
||||||
|
|
||||||
@item Compile Javascript sources to executables with no external dependency.
|
@item Compile Javascript sources to executables with no external dependency.
|
||||||
|
|
||||||
@ -259,17 +259,15 @@ about 100 seconds).
|
|||||||
|
|
||||||
@section Language support
|
@section Language support
|
||||||
|
|
||||||
@subsection ES2019 support
|
@subsection ES2020 support
|
||||||
|
|
||||||
The ES2019 specification is almost fully supported including the Annex
|
The ES2020 specification is almost fully supported including the Annex
|
||||||
B (legacy web compatibility) and the Unicode related features.
|
B (legacy web compatibility) and the Unicode related features.
|
||||||
|
|
||||||
The following features are not supported yet:
|
The following features are not supported yet:
|
||||||
|
|
||||||
@itemize
|
@itemize
|
||||||
|
|
||||||
@item Realms (although the C API supports different runtimes and contexts)
|
|
||||||
|
|
||||||
@item Tail calls@footnote{We believe the current specification of tails calls is too complicated and presents limited practical interests.}
|
@item Tail calls@footnote{We believe the current specification of tails calls is too complicated and presents limited practical interests.}
|
||||||
|
|
||||||
@end itemize
|
@end itemize
|
||||||
@ -705,6 +703,17 @@ object containing optional parameters:
|
|||||||
@item stderr
|
@item stderr
|
||||||
If present, set the handle in the child for stdin, stdout or stderr.
|
If present, set the handle in the child for stdin, stdout or stderr.
|
||||||
|
|
||||||
|
@item env
|
||||||
|
Object. If present, set the process environment from the object
|
||||||
|
key-value pairs. Otherwise use the same environment as the current
|
||||||
|
process.
|
||||||
|
|
||||||
|
@item uid
|
||||||
|
Integer. If present, the process uid with @code{setuid}.
|
||||||
|
|
||||||
|
@item gid
|
||||||
|
Integer. If present, the process gid with @code{setgid}.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@item waitpid(pid, options)
|
@item waitpid(pid, options)
|
||||||
|
8
libbf.c
8
libbf.c
@ -1701,10 +1701,12 @@ static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
|
|||||||
memset(taba, 0, d * sizeof(limb_t));
|
memset(taba, 0, d * sizeof(limb_t));
|
||||||
memcpy(taba + d, a->tab, a->len * sizeof(limb_t));
|
memcpy(taba + d, a->tab, a->len * sizeof(limb_t));
|
||||||
if (bf_resize(r, n + 1))
|
if (bf_resize(r, n + 1))
|
||||||
|
goto fail1;
|
||||||
|
if (mp_divnorm(s, r->tab, taba, na, b->tab, nb)) {
|
||||||
|
fail1:
|
||||||
|
bf_free(s, taba);
|
||||||
goto fail;
|
goto fail;
|
||||||
if (mp_divnorm(s, r->tab, taba, na, b->tab, nb))
|
}
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* see if non zero remainder */
|
/* see if non zero remainder */
|
||||||
if (mp_scan_nz(taba, nb))
|
if (mp_scan_nz(taba, nb))
|
||||||
r->tab[0] |= 1;
|
r->tab[0] |= 1;
|
||||||
|
180
quickjs-libc.c
180
quickjs-libc.c
@ -239,6 +239,7 @@ static JSValue js_printf_internal(JSContext *ctx,
|
|||||||
case 's':
|
case 's':
|
||||||
if (i >= argc)
|
if (i >= argc)
|
||||||
goto missing;
|
goto missing;
|
||||||
|
/* XXX: handle strings containing null characters */
|
||||||
string_arg = JS_ToCString(ctx, argv[i++]);
|
string_arg = JS_ToCString(ctx, argv[i++]);
|
||||||
if (!string_arg)
|
if (!string_arg)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -843,6 +844,7 @@ static JSValue js_std_file_puts(JSContext *ctx, JSValueConst this_val,
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
int i;
|
int i;
|
||||||
const char *str;
|
const char *str;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
if (magic == 0) {
|
if (magic == 0) {
|
||||||
f = stdout;
|
f = stdout;
|
||||||
@ -853,10 +855,10 @@ static JSValue js_std_file_puts(JSContext *ctx, JSValueConst this_val,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < argc; i++) {
|
for(i = 0; i < argc; i++) {
|
||||||
str = JS_ToCString(ctx, argv[i]);
|
str = JS_ToCStringLen(ctx, &len, argv[i]);
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
fputs(str, f);
|
fwrite(str, 1, len, f);
|
||||||
JS_FreeCString(ctx, str);
|
JS_FreeCString(ctx, str);
|
||||||
}
|
}
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
@ -2325,6 +2327,121 @@ static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val,
|
|||||||
return JS_NewInt32(ctx, ret);
|
return JS_NewInt32(ctx, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char **build_envp(JSContext *ctx, JSValueConst obj)
|
||||||
|
{
|
||||||
|
uint32_t len, i;
|
||||||
|
JSPropertyEnum *tab;
|
||||||
|
char **envp, *pair;
|
||||||
|
const char *key, *str;
|
||||||
|
JSValue val;
|
||||||
|
size_t key_len, str_len;
|
||||||
|
|
||||||
|
if (JS_GetOwnPropertyNames(ctx, &tab, &len, obj,
|
||||||
|
JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY) < 0)
|
||||||
|
return NULL;
|
||||||
|
envp = js_mallocz(ctx, sizeof(envp[0]) * ((size_t)len + 1));
|
||||||
|
if (!envp)
|
||||||
|
goto fail;
|
||||||
|
for(i = 0; i < len; i++) {
|
||||||
|
val = JS_GetProperty(ctx, obj, tab[i].atom);
|
||||||
|
if (JS_IsException(val))
|
||||||
|
goto fail;
|
||||||
|
str = JS_ToCString(ctx, val);
|
||||||
|
JS_FreeValue(ctx, val);
|
||||||
|
if (!str)
|
||||||
|
goto fail;
|
||||||
|
key = JS_AtomToCString(ctx, tab[i].atom);
|
||||||
|
if (!key) {
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
key_len = strlen(key);
|
||||||
|
str_len = strlen(str);
|
||||||
|
pair = js_malloc(ctx, key_len + str_len + 2);
|
||||||
|
if (!pair) {
|
||||||
|
JS_FreeCString(ctx, key);
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
memcpy(pair, key, key_len);
|
||||||
|
pair[key_len] = '=';
|
||||||
|
memcpy(pair + key_len + 1, str, str_len);
|
||||||
|
pair[key_len + 1 + str_len] = '\0';
|
||||||
|
envp[i] = pair;
|
||||||
|
JS_FreeCString(ctx, key);
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
JS_FreeAtom(ctx, tab[i].atom);
|
||||||
|
js_free(ctx, tab);
|
||||||
|
return envp;
|
||||||
|
fail:
|
||||||
|
if (envp) {
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
js_free(ctx, envp[i]);
|
||||||
|
js_free(ctx, envp);
|
||||||
|
envp = NULL;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* execvpe is not available on non GNU systems */
|
||||||
|
static int my_execvpe(const char *filename, char **argv, char **envp)
|
||||||
|
{
|
||||||
|
char *path, *p, *p_next, *p1;
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
size_t filename_len, path_len;
|
||||||
|
BOOL eacces_error;
|
||||||
|
|
||||||
|
filename_len = strlen(filename);
|
||||||
|
if (filename_len == 0) {
|
||||||
|
errno = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strchr(filename, '/'))
|
||||||
|
return execve(filename, argv, envp);
|
||||||
|
|
||||||
|
path = getenv("PATH");
|
||||||
|
if (!path)
|
||||||
|
path = "/bin:/usr/bin";
|
||||||
|
eacces_error = FALSE;
|
||||||
|
p = path;
|
||||||
|
for(p = path; p != NULL; p = p_next) {
|
||||||
|
p1 = strchr(p, ':');
|
||||||
|
if (!p1) {
|
||||||
|
p_next = NULL;
|
||||||
|
path_len = strlen(p);
|
||||||
|
} else {
|
||||||
|
p_next = p1 + 1;
|
||||||
|
path_len = p1 - p;
|
||||||
|
}
|
||||||
|
/* path too long */
|
||||||
|
if ((path_len + 1 + filename_len + 1) > PATH_MAX)
|
||||||
|
continue;
|
||||||
|
memcpy(buf, p, path_len);
|
||||||
|
buf[path_len] = '/';
|
||||||
|
memcpy(buf + path_len + 1, filename, filename_len);
|
||||||
|
buf[path_len + 1 + filename_len] = '\0';
|
||||||
|
|
||||||
|
execve(buf, argv, envp);
|
||||||
|
|
||||||
|
switch(errno) {
|
||||||
|
case EACCES:
|
||||||
|
eacces_error = TRUE;
|
||||||
|
break;
|
||||||
|
case ENOENT:
|
||||||
|
case ENOTDIR:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (eacces_error)
|
||||||
|
errno = EACCES;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* exec(args[, options]) -> exitcode */
|
/* exec(args[, options]) -> exitcode */
|
||||||
static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
|
static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
|
||||||
int argc, JSValueConst *argv)
|
int argc, JSValueConst *argv)
|
||||||
@ -2332,11 +2449,13 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
|
|||||||
JSValueConst options, args = argv[0];
|
JSValueConst options, args = argv[0];
|
||||||
JSValue val, ret_val;
|
JSValue val, ret_val;
|
||||||
const char **exec_argv, *file = NULL, *str, *cwd = NULL;
|
const char **exec_argv, *file = NULL, *str, *cwd = NULL;
|
||||||
|
char **envp = environ;
|
||||||
uint32_t exec_argc, i;
|
uint32_t exec_argc, i;
|
||||||
int ret, pid, status;
|
int ret, pid, status;
|
||||||
BOOL block_flag = TRUE, use_path = TRUE;
|
BOOL block_flag = TRUE, use_path = TRUE;
|
||||||
static const char *std_name[3] = { "stdin", "stdout", "stderr" };
|
static const char *std_name[3] = { "stdin", "stdout", "stderr" };
|
||||||
int std_fds[3];
|
int std_fds[3];
|
||||||
|
uint32_t uid = -1, gid = -1;
|
||||||
|
|
||||||
val = JS_GetPropertyStr(ctx, args, "length");
|
val = JS_GetPropertyStr(ctx, args, "length");
|
||||||
if (JS_IsException(val))
|
if (JS_IsException(val))
|
||||||
@ -2410,6 +2529,36 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
|
|||||||
std_fds[i] = fd;
|
std_fds[i] = fd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val = JS_GetPropertyStr(ctx, options, "env");
|
||||||
|
if (JS_IsException(val))
|
||||||
|
goto exception;
|
||||||
|
if (!JS_IsUndefined(val)) {
|
||||||
|
envp = build_envp(ctx, val);
|
||||||
|
JS_FreeValue(ctx, val);
|
||||||
|
if (!envp)
|
||||||
|
goto exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = JS_GetPropertyStr(ctx, options, "uid");
|
||||||
|
if (JS_IsException(val))
|
||||||
|
goto exception;
|
||||||
|
if (!JS_IsUndefined(val)) {
|
||||||
|
ret = JS_ToUint32(ctx, &uid, val);
|
||||||
|
JS_FreeValue(ctx, val);
|
||||||
|
if (ret)
|
||||||
|
goto exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = JS_GetPropertyStr(ctx, options, "gid");
|
||||||
|
if (JS_IsException(val))
|
||||||
|
goto exception;
|
||||||
|
if (!JS_IsUndefined(val)) {
|
||||||
|
ret = JS_ToUint32(ctx, &gid, val);
|
||||||
|
JS_FreeValue(ctx, val);
|
||||||
|
if (ret)
|
||||||
|
goto exception;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
@ -2435,12 +2584,21 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
|
|||||||
if (chdir(cwd) < 0)
|
if (chdir(cwd) < 0)
|
||||||
_exit(127);
|
_exit(127);
|
||||||
}
|
}
|
||||||
|
if (uid != -1) {
|
||||||
|
if (setuid(uid) < 0)
|
||||||
|
_exit(127);
|
||||||
|
}
|
||||||
|
if (gid != -1) {
|
||||||
|
if (setgid(gid) < 0)
|
||||||
|
_exit(127);
|
||||||
|
}
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
file = exec_argv[0];
|
file = exec_argv[0];
|
||||||
if (use_path)
|
if (use_path)
|
||||||
ret = execvp(file, (char **)exec_argv);
|
ret = my_execvpe(file, (char **)exec_argv, envp);
|
||||||
else
|
else
|
||||||
ret = execv(file, (char **)exec_argv);
|
ret = execve(file, (char **)exec_argv, envp);
|
||||||
_exit(127);
|
_exit(127);
|
||||||
}
|
}
|
||||||
/* parent */
|
/* parent */
|
||||||
@ -2467,6 +2625,15 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
|
|||||||
for(i = 0; i < exec_argc; i++)
|
for(i = 0; i < exec_argc; i++)
|
||||||
JS_FreeCString(ctx, exec_argv[i]);
|
JS_FreeCString(ctx, exec_argv[i]);
|
||||||
js_free(ctx, exec_argv);
|
js_free(ctx, exec_argv);
|
||||||
|
if (envp != environ) {
|
||||||
|
char **p;
|
||||||
|
p = envp;
|
||||||
|
while (*p != NULL) {
|
||||||
|
js_free(ctx, *p);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
js_free(ctx, envp);
|
||||||
|
}
|
||||||
return ret_val;
|
return ret_val;
|
||||||
exception:
|
exception:
|
||||||
ret_val = JS_EXCEPTION;
|
ret_val = JS_EXCEPTION;
|
||||||
@ -2700,14 +2867,15 @@ static JSValue js_print(JSContext *ctx, JSValueConst this_val,
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const char *str;
|
const char *str;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
for(i = 0; i < argc; i++) {
|
for(i = 0; i < argc; i++) {
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
str = JS_ToCString(ctx, argv[i]);
|
str = JS_ToCStringLen(ctx, &len, argv[i]);
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
fputs(str, stdout);
|
fwrite(str, 1, len, stdout);
|
||||||
JS_FreeCString(ctx, str);
|
JS_FreeCString(ctx, str);
|
||||||
}
|
}
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
@ -333,6 +333,7 @@ JSRuntime *JS_NewRuntime(void);
|
|||||||
void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
|
void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
|
||||||
void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
|
void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
|
||||||
void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
|
void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
|
||||||
|
void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size);
|
||||||
JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque);
|
JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque);
|
||||||
void JS_FreeRuntime(JSRuntime *rt);
|
void JS_FreeRuntime(JSRuntime *rt);
|
||||||
void *JS_GetRuntimeOpaque(JSRuntime *rt);
|
void *JS_GetRuntimeOpaque(JSRuntime *rt);
|
||||||
@ -344,10 +345,10 @@ JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj);
|
|||||||
|
|
||||||
JSContext *JS_NewContext(JSRuntime *rt);
|
JSContext *JS_NewContext(JSRuntime *rt);
|
||||||
void JS_FreeContext(JSContext *s);
|
void JS_FreeContext(JSContext *s);
|
||||||
|
JSContext *JS_DupContext(JSContext *ctx);
|
||||||
void *JS_GetContextOpaque(JSContext *ctx);
|
void *JS_GetContextOpaque(JSContext *ctx);
|
||||||
void JS_SetContextOpaque(JSContext *ctx, void *opaque);
|
void JS_SetContextOpaque(JSContext *ctx, void *opaque);
|
||||||
JSRuntime *JS_GetRuntime(JSContext *ctx);
|
JSRuntime *JS_GetRuntime(JSContext *ctx);
|
||||||
void JS_SetMaxStackSize(JSContext *ctx, size_t stack_size);
|
|
||||||
void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj);
|
void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj);
|
||||||
JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id);
|
JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id);
|
||||||
|
|
||||||
@ -673,7 +674,7 @@ static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
|
|||||||
|
|
||||||
int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
|
int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
|
||||||
int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
|
int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
|
||||||
static int inline JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
|
static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
|
||||||
{
|
{
|
||||||
return JS_ToInt32(ctx, (int32_t*)pres, val);
|
return JS_ToInt32(ctx, (int32_t*)pres, val);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* ECMA Test 262 Runner for QuickJS
|
* ECMA Test 262 Runner for QuickJS
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
* Copyright (c) 2017-2020 Fabrice Bellard
|
||||||
* Copyright (c) 2017-2018 Charlie Gordon
|
* Copyright (c) 2017-2020 Charlie Gordon
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -41,8 +41,6 @@
|
|||||||
|
|
||||||
/* enable test262 thread support to test SharedArrayBuffer and Atomics */
|
/* enable test262 thread support to test SharedArrayBuffer and Atomics */
|
||||||
#define CONFIG_AGENT
|
#define CONFIG_AGENT
|
||||||
/* cross-realm tests (not supported yet) */
|
|
||||||
//#define CONFIG_REALM
|
|
||||||
|
|
||||||
#define CMD_NAME "run-test262"
|
#define CMD_NAME "run-test262"
|
||||||
|
|
||||||
@ -730,18 +728,20 @@ static JSValue js_new_agent(JSContext *ctx)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_REALM
|
|
||||||
static JSValue js_createRealm(JSContext *ctx, JSValue this_val,
|
static JSValue js_createRealm(JSContext *ctx, JSValue this_val,
|
||||||
int argc, JSValue *argv)
|
int argc, JSValue *argv)
|
||||||
{
|
{
|
||||||
JSContext *ctx1;
|
JSContext *ctx1;
|
||||||
/* XXX: the context is not freed, need a refcount */
|
JSValue ret;
|
||||||
|
|
||||||
ctx1 = JS_NewContext(JS_GetRuntime(ctx));
|
ctx1 = JS_NewContext(JS_GetRuntime(ctx));
|
||||||
if (!ctx1)
|
if (!ctx1)
|
||||||
return JS_ThrowOutOfMemory(ctx);
|
return JS_ThrowOutOfMemory(ctx);
|
||||||
return add_helpers1(ctx1);
|
ret = add_helpers1(ctx1);
|
||||||
|
/* ctx1 has a refcount so it stays alive */
|
||||||
|
JS_FreeContext(ctx1);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static JSValue add_helpers1(JSContext *ctx)
|
static JSValue add_helpers1(JSContext *ctx)
|
||||||
{
|
{
|
||||||
@ -770,12 +770,9 @@ static JSValue add_helpers1(JSContext *ctx)
|
|||||||
|
|
||||||
JS_SetPropertyStr(ctx, obj262, "global",
|
JS_SetPropertyStr(ctx, obj262, "global",
|
||||||
JS_DupValue(ctx, global_obj));
|
JS_DupValue(ctx, global_obj));
|
||||||
|
|
||||||
#ifdef CONFIG_REALM
|
|
||||||
JS_SetPropertyStr(ctx, obj262, "createRealm",
|
JS_SetPropertyStr(ctx, obj262, "createRealm",
|
||||||
JS_NewCFunction(ctx, js_createRealm,
|
JS_NewCFunction(ctx, js_createRealm,
|
||||||
"createRealm", 0));
|
"createRealm", 0));
|
||||||
#endif
|
|
||||||
|
|
||||||
JS_SetPropertyStr(ctx, global_obj, "$262", JS_DupValue(ctx, obj262));
|
JS_SetPropertyStr(ctx, global_obj, "$262", JS_DupValue(ctx, obj262));
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ testdir=test262/test
|
|||||||
# list the features that are included
|
# list the features that are included
|
||||||
# skipped features are tagged as such to avoid warnings
|
# skipped features are tagged as such to avoid warnings
|
||||||
|
|
||||||
AggregateError=skip
|
AggregateError
|
||||||
Array.prototype.flat
|
Array.prototype.flat
|
||||||
Array.prototype.flatMap
|
Array.prototype.flatMap
|
||||||
Array.prototype.flatten
|
Array.prototype.flatten
|
||||||
@ -70,7 +70,7 @@ class-static-methods-private
|
|||||||
coalesce-expression
|
coalesce-expression
|
||||||
computed-property-names
|
computed-property-names
|
||||||
const
|
const
|
||||||
cross-realm=skip
|
cross-realm
|
||||||
DataView
|
DataView
|
||||||
DataView.prototype.getFloat32
|
DataView.prototype.getFloat32
|
||||||
DataView.prototype.getFloat64
|
DataView.prototype.getFloat64
|
||||||
@ -102,6 +102,7 @@ Int8Array
|
|||||||
IsHTMLDDA=skip
|
IsHTMLDDA=skip
|
||||||
json-superset
|
json-superset
|
||||||
let
|
let
|
||||||
|
logical-assignment-operators=skip
|
||||||
Map
|
Map
|
||||||
new.target
|
new.target
|
||||||
numeric-separator-literal
|
numeric-separator-literal
|
||||||
@ -112,6 +113,7 @@ Object.is
|
|||||||
optional-catch-binding
|
optional-catch-binding
|
||||||
optional-chaining
|
optional-chaining
|
||||||
Promise.allSettled
|
Promise.allSettled
|
||||||
|
Promise.any
|
||||||
Promise.prototype.finally
|
Promise.prototype.finally
|
||||||
Proxy
|
Proxy
|
||||||
proxy-missing-checks
|
proxy-missing-checks
|
||||||
@ -179,5 +181,8 @@ test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js
|
|||||||
#test262/test/built-ins/RegExp/CharacterClassEscapes/
|
#test262/test/built-ins/RegExp/CharacterClassEscapes/
|
||||||
#test262/test/built-ins/RegExp/property-escapes/
|
#test262/test/built-ins/RegExp/property-escapes/
|
||||||
|
|
||||||
|
# invalid tests
|
||||||
|
test262/test/language/module-code/verify-dfs.js
|
||||||
|
|
||||||
[tests]
|
[tests]
|
||||||
# list test files or use config.testdir
|
# list test files or use config.testdir
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
|
test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: Test262Error: Expected a ReferenceError but got a ReferenceError
|
||||||
|
test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: strict mode: Test262Error: Expected a ReferenceError but got a ReferenceError
|
||||||
|
test262/test/built-ins/Proxy/ownKeys/trap-is-undefined-target-is-proxy.js:29: Test262Error: Expected [0, length, foo, Symbol()] and [Symbol(), length, foo, 0] to have the same contents.
|
||||||
|
test262/test/built-ins/Proxy/ownKeys/trap-is-undefined-target-is-proxy.js:29: strict mode: Test262Error: Expected [0, length, foo, Symbol()] and [Symbol(), length, foo, 0] to have the same contents.
|
||||||
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/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-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/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-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/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/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/elements/grammar-private-field-optional-chaining.js:26: SyntaxError: expecting field name
|
||||||
|
test262/test/language/expressions/class/elements/grammar-private-field-optional-chaining.js:26: strict mode: SyntaxError: expecting field name
|
||||||
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: 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/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/function/eval-var-scope-syntax-err.js:48: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||||
@ -16,7 +22,7 @@ test262/test/language/expressions/optional-chaining/optional-call-preserves-this
|
|||||||
test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:15: strict mode: 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-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/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/class/elements/grammar-private-field-optional-chaining.js:26: SyntaxError: expecting field name
|
||||||
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/class/elements/grammar-private-field-optional-chaining.js:26: strict mode: SyntaxError: expecting field name
|
||||||
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/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
|
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
|
||||||
|
@ -214,7 +214,11 @@ function test_os_exec()
|
|||||||
assert(ret, 1);
|
assert(ret, 1);
|
||||||
|
|
||||||
fds = os.pipe();
|
fds = os.pipe();
|
||||||
pid = os.exec(["echo", "hello"], { stdout: fds[1], block: false } );
|
pid = os.exec(["sh", "-c", "echo $FOO"], {
|
||||||
|
stdout: fds[1],
|
||||||
|
block: false,
|
||||||
|
env: { FOO: "hello" },
|
||||||
|
} );
|
||||||
assert(pid >= 0);
|
assert(pid >= 0);
|
||||||
os.close(fds[1]); /* close the write end (as it is only in the child) */
|
os.close(fds[1]); /* close the write end (as it is only in the child) */
|
||||||
f = std.fdopen(fds[0], "r");
|
f = std.fdopen(fds[0], "r");
|
||||||
|
Loading…
Reference in New Issue
Block a user