2021-03-27 release

This commit is contained in:
bellard 2021-03-27 11:17:31 +01:00
parent 204682fb87
commit b5e62895c6
19 changed files with 585 additions and 268 deletions

View File

@ -1,3 +1,10 @@
2021-03-27:
- faster Array.prototype.push and Array.prototype.unshift
- added JS_UpdateStackTop()
- fixed Windows console
- misc bug fixes
2020-11-08:
- improved function parameter initializers

22
LICENSE Normal file
View File

@ -0,0 +1,22 @@
QuickJS Javascript Engine
Copyright (c) 2017-2021 Fabrice Bellard
Copyright (c) 2017-2021 Charlie Gordon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,8 +1,8 @@
#
# QuickJS Javascript Engine
#
# Copyright (c) 2017-2020 Fabrice Bellard
# Copyright (c) 2017-2020 Charlie Gordon
# Copyright (c) 2017-2021 Fabrice Bellard
# Copyright (c) 2017-2021 Charlie Gordon
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@ -179,6 +179,7 @@ LIBS=-lm
ifndef CONFIG_WIN32
LIBS+=-ldl -lpthread
endif
LIBS+=$(EXTRA_LIBS)
$(OBJDIR):
mkdir -p $(OBJDIR) $(OBJDIR)/examples $(OBJDIR)/tests

4
TODO
View File

@ -66,5 +66,5 @@ Optimization ideas:
Test262o: 0/11262 errors, 463 excluded
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
Result: 51/75119 errors, 899 excluded, 570 skipped
Test262 commit: 1c33fdb0ca60fb9d7392403be769ed0d26209132
Result: 35/75280 errors, 909 excluded, 585 skipped
Test262 commit: 31126581e7290f9233c29cefd93f66c6ac78f1c9

View File

@ -1 +1 @@
2020-11-08
2021-03-27

View File

@ -896,10 +896,11 @@ set the C opaque point with
@code{JS_GetOpaque()}/@code{JS_SetOpaque()}.
When defining a new JS class, it is possible to declare a finalizer
which is called when the object is destroyed. A @code{gc_mark} method
can be provided so that the cycle removal algorithm can find the other
objects referenced by this object. Other methods are available to
define exotic object behaviors.
which is called when the object is destroyed. The finalizer should be
used to release C resources. It is invalid to execute JS code from
it. A @code{gc_mark} method can be provided so that the cycle removal
algorithm can find the other objects referenced by this object. Other
methods are available to define exotic object behaviors.
The Class ID are globally allocated (i.e. for all runtimes). The
JSClass are allocated per @code{JSRuntime}. @code{JS_SetClassProto()}

View File

@ -1,7 +1,7 @@
/*
* Tiny arbitrary precision floating point library
*
* Copyright (c) 2017-2020 Fabrice Bellard
* Copyright (c) 2017-2021 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@ -1,7 +1,7 @@
/*
* Tiny arbitrary precision floating point library
*
* Copyright (c) 2017-2020 Fabrice Bellard
* Copyright (c) 2017-2021 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

12
qjs.c
View File

@ -1,8 +1,8 @@
/*
* QuickJS stand alone interpreter
*
* Copyright (c) 2017-2020 Fabrice Bellard
* Copyright (c) 2017-2020 Charlie Gordon
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -156,7 +156,13 @@ static inline size_t js_trace_malloc_usable_size(void *ptr)
#endif
}
static void __attribute__((format(printf, 2, 3)))
static void
#ifdef _WIN32
/* mingw printf is used */
__attribute__((format(gnu_printf, 2, 3)))
#else
__attribute__((format(printf, 2, 3)))
#endif
js_trace_malloc_printf(JSMallocState *s, const char *fmt, ...)
{
va_list ap;

2
qjsc.c
View File

@ -1,7 +1,7 @@
/*
* QuickJS command line compiler
*
* Copyright (c) 2018-2020 Fabrice Bellard
* Copyright (c) 2018-2021 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@ -2299,8 +2299,13 @@ var Integer, Float, Fraction, Complex, Mod, Polynomial, PolyMod, RationalFunctio
function array_div(a, b) {
return array_mul(a, b.inverse());
}
function array_scalar_div(a, b) {
return a * b.inverse();
function array_element_wise_inverse(a) {
var r, i, n;
n = a.length;
r = [];
for(i = 0; i < n; i++)
r[i] = a[i].inverse();
return r;
}
function array_eq(a, b) {
var n, i;
@ -2337,14 +2342,14 @@ var Integer, Float, Fraction, Complex, Mod, Polynomial, PolyMod, RationalFunctio
right: [Number, BigInt, Float, Fraction, Complex, Mod,
Polynomial, PolyMod, RationalFunction, Series],
"*": array_scalar_mul,
"/": array_scalar_div,
"/"(a, b) { return a * b.inverse(); },
"**": generic_pow, /* XXX: only for integer */
},
{
left: [Number, BigInt, Float, Fraction, Complex, Mod,
Polynomial, PolyMod, RationalFunction, Series],
"*"(a, b) { return array_scalar_mul(b, a); },
"/"(a, b) { return array_scalar_div(b, a); },
"/"(a, b) { return a * array_element_wise_inverse(b); },
});
add_props(Array.prototype, {

View File

@ -1,8 +1,8 @@
/*
* QuickJS C library
*
* Copyright (c) 2017-2020 Fabrice Bellard
* Copyright (c) 2017-2020 Charlie Gordon
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -1663,7 +1663,7 @@ static JSValue js_os_isatty(JSContext *ctx, JSValueConst this_val,
int fd;
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
return JS_NewBool(ctx, isatty(fd) == 1);
return JS_NewBool(ctx, (isatty(fd) != 0));
}
#if defined(_WIN32)
@ -1689,6 +1689,10 @@ static JSValue js_os_ttyGetWinSize(JSContext *ctx, JSValueConst this_val,
return obj;
}
/* Windows 10 built-in VT100 emulation */
#define __ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#define __ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@ -1698,8 +1702,12 @@ static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val,
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
handle = (HANDLE)_get_osfhandle(fd);
SetConsoleMode(handle, ENABLE_WINDOW_INPUT);
SetConsoleMode(handle, ENABLE_WINDOW_INPUT | __ENABLE_VIRTUAL_TERMINAL_INPUT);
_setmode(fd, _O_BINARY);
if (fd == 0) {
handle = (HANDLE)_get_osfhandle(1); /* corresponding output */
SetConsoleMode(handle, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | __ENABLE_VIRTUAL_TERMINAL_PROCESSING);
}
return JS_UNDEFINED;
}
#else
@ -1772,7 +1780,19 @@ static JSValue js_os_remove(JSContext *ctx, JSValueConst this_val,
filename = JS_ToCString(ctx, argv[0]);
if (!filename)
return JS_EXCEPTION;
ret = js_get_errno(remove(filename));
#if defined(_WIN32)
{
struct stat st;
if (stat(filename, &st) == 0 && S_ISDIR(st.st_mode)) {
ret = rmdir(filename);
} else {
ret = unlink(filename);
}
}
#else
ret = remove(filename);
#endif
ret = js_get_errno(ret);
JS_FreeCString(ctx, filename);
return JS_NewInt32(ctx, ret);
}
@ -2588,7 +2608,47 @@ static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val,
return JS_NewInt32(ctx, ret);
}
#if !defined(_WIN32)
/* sleep(delay_ms) */
static JSValue js_os_sleep(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
int64_t delay;
int ret;
if (JS_ToInt64(ctx, &delay, argv[0]))
return JS_EXCEPTION;
if (delay < 0)
delay = 0;
#if defined(_WIN32)
{
if (delay > INT32_MAX)
delay = INT32_MAX;
Sleep(delay);
ret = 0;
}
#else
{
struct timespec ts;
ts.tv_sec = delay / 1000;
ts.tv_nsec = (delay % 1000) * 1000000;
ret = js_get_errno(nanosleep(&ts, NULL));
}
#endif
return JS_NewInt32(ctx, ret);
}
#if defined(_WIN32)
static char *realpath(const char *path, char *buf)
{
if (!_fullpath(buf, path, PATH_MAX)) {
errno = ENOENT;
return NULL;
} else {
return buf;
}
}
#endif
/* return [path, errorcode] */
static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val,
@ -2612,6 +2672,7 @@ static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val,
return make_string_error(ctx, buf, err);
}
#if !defined(_WIN32)
static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@ -3031,22 +3092,6 @@ static JSValue js_os_kill(JSContext *ctx, JSValueConst this_val,
return JS_NewInt32(ctx, ret);
}
/* sleep(delay_ms) */
static JSValue js_os_sleep(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
int64_t delay;
struct timespec ts;
int ret;
if (JS_ToInt64(ctx, &delay, argv[0]))
return JS_EXCEPTION;
ts.tv_sec = delay / 1000;
ts.tv_nsec = (delay % 1000) * 1000000;
ret = js_get_errno(nanosleep(&ts, NULL));
return JS_NewInt32(ctx, ret);
}
/* dup(fd) */
static JSValue js_os_dup(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
@ -3598,9 +3643,10 @@ static const JSCFunctionListEntry js_os_funcs[] = {
#endif
JS_CFUNC_MAGIC_DEF("stat", 1, js_os_stat, 0 ),
JS_CFUNC_DEF("utimes", 3, js_os_utimes ),
JS_CFUNC_DEF("sleep", 1, js_os_sleep ),
JS_CFUNC_DEF("realpath", 1, js_os_realpath ),
#if !defined(_WIN32)
JS_CFUNC_MAGIC_DEF("lstat", 1, js_os_stat, 1 ),
JS_CFUNC_DEF("realpath", 1, js_os_realpath ),
JS_CFUNC_DEF("symlink", 2, js_os_symlink ),
JS_CFUNC_DEF("readlink", 1, js_os_readlink ),
JS_CFUNC_DEF("exec", 1, js_os_exec ),
@ -3608,7 +3654,6 @@ static const JSCFunctionListEntry js_os_funcs[] = {
OS_FLAG(WNOHANG),
JS_CFUNC_DEF("pipe", 0, js_os_pipe ),
JS_CFUNC_DEF("kill", 2, js_os_kill ),
JS_CFUNC_DEF("sleep", 1, js_os_sleep ),
JS_CFUNC_DEF("dup", 1, js_os_dup ),
JS_CFUNC_DEF("dup2", 2, js_os_dup2 ),
#endif

570
quickjs.c
View File

@ -1,8 +1,8 @@
/*
* QuickJS Javascript Engine
*
* Copyright (c) 2017-2020 Fabrice Bellard
* Copyright (c) 2017-2020 Charlie Gordon
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -36,6 +36,8 @@
#include <malloc/malloc.h>
#elif defined(__linux__)
#include <malloc.h>
#elif defined(__FreeBSD__)
#include <malloc_np.h>
#endif
#include "cutils.h"
@ -265,8 +267,9 @@ struct JSRuntime {
struct list_head string_list; /* list of JSString.link */
#endif
/* stack limitation */
const uint8_t *stack_top;
size_t stack_size; /* in bytes */
uintptr_t stack_size; /* in bytes, 0 if no limit */
uintptr_t stack_top;
uintptr_t stack_limit; /* lower stack limit */
JSValue current_exception;
/* true if inside an out of memory error, to avoid recursing */
@ -1569,9 +1572,9 @@ static void set_dummy_numeric_ops(JSNumericOperations *ops)
#if !defined(CONFIG_STACK_CHECK)
/* no stack limitation */
static inline uint8_t *js_get_stack_pointer(void)
static inline uintptr_t js_get_stack_pointer(void)
{
return NULL;
return 0;
}
static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
@ -1580,16 +1583,16 @@ static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
}
#else
/* Note: OS and CPU dependent */
static inline uint8_t *js_get_stack_pointer(void)
static inline uintptr_t js_get_stack_pointer(void)
{
return __builtin_frame_address(0);
return (uintptr_t)__builtin_frame_address(0);
}
static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
{
size_t size;
size = rt->stack_top - js_get_stack_pointer();
return unlikely((size + alloca_size) > rt->stack_size);
uintptr_t sp;
sp = js_get_stack_pointer() - alloca_size;
return unlikely(sp < rt->stack_limit);
}
#endif
@ -1649,8 +1652,9 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
if (init_shape_hash(rt))
goto fail;
rt->stack_top = js_get_stack_pointer();
rt->stack_size = JS_DEFAULT_STACK_SIZE;
JS_UpdateStackTop(rt);
rt->current_exception = JS_NULL;
return rt;
@ -2338,9 +2342,25 @@ JSRuntime *JS_GetRuntime(JSContext *ctx)
return ctx->rt;
}
static void update_stack_limit(JSRuntime *rt)
{
if (rt->stack_size == 0) {
rt->stack_limit = 0; /* no limit */
} else {
rt->stack_limit = rt->stack_top - rt->stack_size;
}
}
void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size)
{
rt->stack_size = stack_size;
update_stack_limit(rt);
}
void JS_UpdateStackTop(JSRuntime *rt)
{
rt->stack_top = js_get_stack_pointer();
update_stack_limit(rt);
}
static inline BOOL is_strict_mode(JSContext *ctx)
@ -3377,6 +3397,8 @@ static int JS_NewClass1(JSRuntime *rt, JSClassID class_id,
JSClass *cl, *new_class_array;
struct list_head *el;
if (class_id >= (1 << 16))
return -1;
if (class_id < rt->class_count &&
rt->class_array[class_id].class_id != 0)
return -1;
@ -8231,6 +8253,23 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val,
return TRUE;
}
/* return -1 if exception */
static int expand_fast_array(JSContext *ctx, JSObject *p, uint32_t new_len)
{
uint32_t new_size;
size_t slack;
JSValue *new_array_prop;
/* XXX: potential arithmetic overflow */
new_size = max_int(new_len, p->u.array.u1.size * 3 / 2);
new_array_prop = js_realloc2(ctx, p->u.array.u.values, sizeof(JSValue) * new_size, &slack);
if (!new_array_prop)
return -1;
new_size += slack / sizeof(*new_array_prop);
p->u.array.u.values = new_array_prop;
p->u.array.u1.size = new_size;
return 0;
}
/* Preconditions: 'p' must be of class JS_CLASS_ARRAY, p->fast_array =
TRUE and p->extensible = TRUE */
static int add_fast_array_element(JSContext *ctx, JSObject *p,
@ -8253,19 +8292,10 @@ static int add_fast_array_element(JSContext *ctx, JSObject *p,
}
}
if (unlikely(new_len > p->u.array.u1.size)) {
uint32_t new_size;
size_t slack;
JSValue *new_array_prop;
/* XXX: potential arithmetic overflow */
new_size = max_int(new_len, p->u.array.u1.size * 3 / 2);
new_array_prop = js_realloc2(ctx, p->u.array.u.values, sizeof(JSValue) * new_size, &slack);
if (!new_array_prop) {
if (expand_fast_array(ctx, p, new_len)) {
JS_FreeValue(ctx, val);
return -1;
}
new_size += slack / sizeof(*new_array_prop);
p->u.array.u.values = new_array_prop;
p->u.array.u1.size = new_size;
}
p->u.array.u.values[new_len - 1] = val;
p->u.array.count = new_len;
@ -8279,22 +8309,24 @@ static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc)
JS_FreeValue(ctx, desc->value);
}
/* generic (and slower) version of JS_SetProperty() for Reflect.set() */
/* generic (and slower) version of JS_SetProperty() for
* Reflect.set(). 'obj' must be an object. */
static int JS_SetPropertyGeneric(JSContext *ctx,
JSObject *p, JSAtom prop,
JSValueConst obj, JSAtom prop,
JSValue val, JSValueConst this_obj,
int flags)
{
int ret;
JSPropertyDescriptor desc;
JSValue obj1;
JSObject *p;
while (p != NULL) {
obj1 = JS_DupValue(ctx, obj);
for(;;) {
p = JS_VALUE_GET_OBJ(obj1);
if (p->is_exotic) {
const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
if (em && em->set_property) {
JSValue obj1;
/* set_property can free the prototype */
obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
ret = em->set_property(ctx, obj1, prop,
val, this_obj, flags);
JS_FreeValue(ctx, obj1);
@ -8304,8 +8336,11 @@ static int JS_SetPropertyGeneric(JSContext *ctx,
}
ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);
if (ret < 0)
if (ret < 0) {
JS_FreeValue(ctx, obj1);
JS_FreeValue(ctx, val);
return ret;
}
if (ret) {
if (desc.flags & JS_PROP_GETSET) {
JSObject *setter;
@ -8316,27 +8351,38 @@ static int JS_SetPropertyGeneric(JSContext *ctx,
ret = call_setter(ctx, setter, this_obj, val, flags);
JS_FreeValue(ctx, desc.getter);
JS_FreeValue(ctx, desc.setter);
JS_FreeValue(ctx, obj1);
return ret;
} else {
JS_FreeValue(ctx, desc.value);
if (!(desc.flags & JS_PROP_WRITABLE)) {
JS_FreeValue(ctx, obj1);
goto read_only_error;
}
}
break;
}
p = p->shape->proto;
/* Note: at this point 'obj1' cannot be a proxy. XXX: may have
to check recursion */
obj1 = JS_GetPrototypeFree(ctx, obj1);
if (JS_IsNull(obj1))
break;
}
JS_FreeValue(ctx, obj1);
if (!JS_IsObject(this_obj))
if (!JS_IsObject(this_obj)) {
JS_FreeValue(ctx, val);
return JS_ThrowTypeErrorOrFalse(ctx, flags, "receiver is not an object");
}
p = JS_VALUE_GET_OBJ(this_obj);
/* modify the property in this_obj if it already exists */
ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);
if (ret < 0)
if (ret < 0) {
JS_FreeValue(ctx, val);
return ret;
}
if (ret) {
if (desc.flags & JS_PROP_GETSET) {
JS_FreeValue(ctx, desc.getter);
@ -15022,10 +15068,10 @@ static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst *
static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
{
JSObject *p, *p1;
JSObject *p;
JSPropertyEnum *tab_atom;
int i;
JSValue enum_obj;
JSValue enum_obj, obj1;
JSForInIterator *it;
uint32_t tag, tab_atom_count;
@ -15054,20 +15100,34 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED)
return enum_obj;
p = JS_VALUE_GET_OBJ(obj);
/* fast path: assume no enumerable properties in the prototype chain */
p1 = p->shape->proto;
while (p1 != NULL) {
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p1,
JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY))
obj1 = JS_DupValue(ctx, obj);
for(;;) {
obj1 = JS_GetPrototypeFree(ctx, obj1);
if (JS_IsNull(obj1))
break;
if (JS_IsException(obj1))
goto fail;
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
JS_VALUE_GET_OBJ(obj1),
JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) {
JS_FreeValue(ctx, obj1);
goto fail;
}
js_free_prop_enum(ctx, tab_atom, tab_atom_count);
if (tab_atom_count != 0) {
JS_FreeValue(ctx, obj1);
goto slow_path;
}
p1 = p1->shape->proto;
/* must check for timeout to avoid infinite loop */
if (js_poll_interrupts(ctx)) {
JS_FreeValue(ctx, obj1);
goto fail;
}
}
p = JS_VALUE_GET_OBJ(obj);
if (p->fast_array) {
JSShape *sh;
JSShapeProperty *prs;
@ -15095,17 +15155,30 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
slow_path:
/* non enumerable properties hide the enumerables ones in the
prototype chain */
while (p != NULL) {
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,
JS_GPN_STRING_MASK | JS_GPN_SET_ENUM))
obj1 = JS_DupValue(ctx, obj);
for(;;) {
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
JS_VALUE_GET_OBJ(obj1),
JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
JS_FreeValue(ctx, obj1);
goto fail;
}
for(i = 0; i < tab_atom_count; i++) {
JS_DefinePropertyValue(ctx, enum_obj, tab_atom[i].atom, JS_NULL,
(tab_atom[i].is_enumerable ?
JS_PROP_ENUMERABLE : 0));
}
js_free_prop_enum(ctx, tab_atom, tab_atom_count);
p = p->shape->proto;
obj1 = JS_GetPrototypeFree(ctx, obj1);
if (JS_IsNull(obj1))
break;
if (JS_IsException(obj1))
goto fail;
/* must check for timeout to avoid infinite loop */
if (js_poll_interrupts(ctx)) {
JS_FreeValue(ctx, obj1);
goto fail;
}
}
return enum_obj;
@ -15572,7 +15645,9 @@ static __exception int JS_CopyDataProperties(JSContext *ctx,
uint32_t i, tab_atom_count;
JSObject *p;
JSObject *pexcl = NULL;
int ret = 0, flags;
int ret, gpn_flags;
JSPropertyDescriptor desc;
BOOL is_enumerable;
if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT)
return 0;
@ -15581,37 +15656,57 @@ static __exception int JS_CopyDataProperties(JSContext *ctx,
pexcl = JS_VALUE_GET_OBJ(excluded);
p = JS_VALUE_GET_OBJ(source);
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,
JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK |
JS_GPN_ENUM_ONLY))
return -1;
flags = JS_PROP_C_W_E;
gpn_flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK | JS_GPN_ENUM_ONLY;
if (p->is_exotic) {
const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
/* cannot use JS_GPN_ENUM_ONLY with e.g. proxies because it
introduces a visible change */
if (em && em->get_own_property_names) {
gpn_flags &= ~JS_GPN_ENUM_ONLY;
}
}
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,
gpn_flags))
return -1;
for (i = 0; i < tab_atom_count; i++) {
if (pexcl) {
ret = JS_GetOwnPropertyInternal(ctx, NULL, pexcl, tab_atom[i].atom);
if (ret) {
if (ret < 0)
break;
ret = 0;
goto exception;
continue;
}
}
ret = -1;
if (!(gpn_flags & JS_GPN_ENUM_ONLY)) {
/* test if the property is enumerable */
ret = JS_GetOwnPropertyInternal(ctx, &desc, p, tab_atom[i].atom);
if (ret < 0)
goto exception;
if (!ret)
continue;
is_enumerable = (desc.flags & JS_PROP_ENUMERABLE) != 0;
js_free_desc(ctx, &desc);
if (!is_enumerable)
continue;
}
val = JS_GetProperty(ctx, source, tab_atom[i].atom);
if (JS_IsException(val))
break;
goto exception;
if (setprop)
ret = JS_SetProperty(ctx, target, tab_atom[i].atom, val);
else
ret = JS_DefinePropertyValue(ctx, target, tab_atom[i].atom, val, flags);
ret = JS_DefinePropertyValue(ctx, target, tab_atom[i].atom, val,
JS_PROP_C_W_E);
if (ret < 0)
break;
ret = 0;
goto exception;
}
js_free_prop_enum(ctx, tab_atom, tab_atom_count);
return ret;
return 0;
exception:
js_free_prop_enum(ctx, tab_atom, tab_atom_count);
return -1;
}
/* only valid inside C functions */
@ -16654,7 +16749,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK;
CASE(OP_check_ctor):
if (JS_IsUndefined(new_target)) {
JS_ThrowTypeError(caller_ctx, "class constructors must be invoked with 'new'");
JS_ThrowTypeError(ctx, "class constructors must be invoked with 'new'");
goto exception;
}
BREAK;
@ -17770,8 +17865,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
atom = JS_ValueToAtom(ctx, sp[-2]);
if (unlikely(atom == JS_ATOM_NULL))
goto exception;
ret = JS_SetPropertyGeneric(ctx, JS_VALUE_GET_OBJ(sp[-3]),
atom, sp[-1], sp[-4],
ret = JS_SetPropertyGeneric(ctx, sp[-3], atom, sp[-1], sp[-4],
JS_PROP_THROW_STRICT);
JS_FreeAtom(ctx, atom);
JS_FreeValue(ctx, sp[-4]);
@ -22678,7 +22772,7 @@ static __exception int js_parse_left_hand_side_expr(JSParseState *s)
return js_parse_postfix_expr(s, PF_POSTFIX_CALL);
}
/* XXX: is there is nicer solution ? */
/* XXX: could generate specific bytecode */
static __exception int js_parse_class_default_ctor(JSParseState *s,
BOOL has_super,
JSFunctionDef **pfd)
@ -22691,7 +22785,8 @@ static __exception int js_parse_class_default_ctor(JSParseState *s,
js_parse_get_pos(s, &pos);
if (has_super) {
str = "(...a){super(...a);}";
/* spec change: no argument evaluation */
str = "(){super(...arguments);}";
func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR;
} else {
str = "(){}";
@ -34227,6 +34322,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
bc_put_leb128(s, b->cpool_count);
bc_put_leb128(s, b->byte_code_len);
if (b->vardefs) {
/* XXX: this field is redundant */
bc_put_leb128(s, b->arg_count + b->var_count);
for(i = 0; i < b->arg_count + b->var_count; i++) {
JSVarDef *vd = &b->vardefs[i];
@ -35196,6 +35292,16 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
memcpy(b, &bc, offsetof(JSFunctionBytecode, debug));
b->header.ref_count = 1;
if (local_count != 0) {
b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
}
if (b->closure_var_count != 0) {
b->closure_var = (void *)((uint8_t*)b + closure_var_offset);
}
if (b->cpool_count != 0) {
b->cpool = (void *)((uint8_t*)b + cpool_offset);
}
add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b);
@ -35211,7 +35317,6 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
if (local_count != 0) {
bc_read_trace(s, "vars {\n");
b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
for(i = 0; i < local_count; i++) {
JSVarDef *vd = &b->vardefs[i];
if (bc_get_atom(s, &vd->var_name))
@ -35236,7 +35341,6 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
}
if (b->closure_var_count != 0) {
bc_read_trace(s, "closure vars {\n");
b->closure_var = (void *)((uint8_t*)b + closure_var_offset);
for(i = 0; i < b->closure_var_count; i++) {
JSClosureVar *cv = &b->closure_var[i];
int var_idx;
@ -35288,7 +35392,6 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
}
if (b->cpool_count != 0) {
bc_read_trace(s, "cpool {\n");
b->cpool = (void *)((uint8_t*)b + cpool_offset);
for(i = 0; i < b->cpool_count; i++) {
JSValue val;
val = JS_ReadObjectRec(s);
@ -37493,6 +37596,10 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
}
if (js_get_length32(ctx, &len, array_arg))
return NULL;
if (len > JS_MAX_LOCAL_VARS) {
JS_ThrowInternalError(ctx, "too many arguments");
return NULL;
}
/* avoid allocating 0 bytes */
tab = js_mallocz(ctx, sizeof(tab[0]) * max_uint32(1, len));
if (!tab)
@ -38293,9 +38400,16 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val,
n = 0;
for(k = 0; k < len; k++) {
present = JS_TryGetPropertyInt64(ctx, obj, k, &val);
if (present < 0)
goto exception;
if (special & special_TA) {
val = JS_GetPropertyInt64(ctx, obj, k);
if (JS_IsException(val))
goto exception;
present = TRUE;
} else {
present = JS_TryGetPropertyInt64(ctx, obj, k, &val);
if (present < 0)
goto exception;
}
if (present) {
index_val = JS_NewInt64(ctx, k);
if (JS_IsException(index_val))
@ -38413,18 +38527,32 @@ static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val,
}
k1 = (special & special_reduceRight) ? len - k - 1 : k;
k++;
present = JS_TryGetPropertyInt64(ctx, obj, k1, &acc);
if (present < 0)
goto exception;
if (present)
if (special & special_TA) {
acc = JS_GetPropertyInt64(ctx, obj, k1);
if (JS_IsException(acc))
goto exception;
break;
} else {
present = JS_TryGetPropertyInt64(ctx, obj, k1, &acc);
if (present < 0)
goto exception;
if (present)
break;
}
}
}
for (; k < len; k++) {
k1 = (special & special_reduceRight) ? len - k - 1 : k;
present = JS_TryGetPropertyInt64(ctx, obj, k1, &val);
if (present < 0)
goto exception;
if (special & special_TA) {
val = JS_GetPropertyInt64(ctx, obj, k1);
if (JS_IsException(val))
goto exception;
present = TRUE;
} else {
present = JS_TryGetPropertyInt64(ctx, obj, k1, &val);
if (present < 0)
goto exception;
}
if (present) {
index_val = JS_NewInt64(ctx, k1);
if (JS_IsException(index_val))
@ -38829,27 +38957,64 @@ static JSValue js_array_push(JSContext *ctx, JSValueConst this_val,
int64_t len, from, newLen;
obj = JS_ToObject(ctx, this_val);
if (js_get_length64(ctx, &len, obj))
goto exception;
newLen = len + argc;
if (newLen > MAX_SAFE_INTEGER) {
JS_ThrowTypeError(ctx, "Array loo long");
goto exception;
}
from = len;
if (unshift && argc > 0) {
if (JS_CopySubArray(ctx, obj, argc, 0, len, -1))
goto exception;
from = 0;
}
for(i = 0; i < argc; i++) {
if (JS_SetPropertyInt64(ctx, obj, from + i,
JS_DupValue(ctx, argv[i])) < 0)
goto exception;
}
if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0)
goto exception;
if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(obj);
if (p->class_id != JS_CLASS_ARRAY ||
!p->fast_array || !p->extensible)
goto generic_case;
/* length must be writable */
if (unlikely(!(get_shape_prop(p->shape)->flags & JS_PROP_WRITABLE)))
goto generic_case;
/* check the length */
if (unlikely(JS_VALUE_GET_TAG(p->prop[0].u.value) != JS_TAG_INT))
goto generic_case;
len = JS_VALUE_GET_INT(p->prop[0].u.value);
/* we don't support holes */
if (unlikely(len != p->u.array.count))
goto generic_case;
newLen = len + argc;
if (unlikely(newLen > INT32_MAX))
goto generic_case;
if (newLen > p->u.array.u1.size) {
if (expand_fast_array(ctx, p, newLen))
goto exception;
}
if (unshift && argc > 0) {
memmove(p->u.array.u.values + argc, p->u.array.u.values,
len * sizeof(p->u.array.u.values[0]));
from = 0;
} else {
from = len;
}
for(i = 0; i < argc; i++) {
p->u.array.u.values[from + i] = JS_DupValue(ctx, argv[i]);
}
p->u.array.count = newLen;
p->prop[0].u.value = JS_NewInt32(ctx, newLen);
} else {
generic_case:
if (js_get_length64(ctx, &len, obj))
goto exception;
newLen = len + argc;
if (newLen > MAX_SAFE_INTEGER) {
JS_ThrowTypeError(ctx, "Array loo long");
goto exception;
}
from = len;
if (unshift && argc > 0) {
if (JS_CopySubArray(ctx, obj, argc, 0, len, -1))
goto exception;
from = 0;
}
for(i = 0; i < argc; i++) {
if (JS_SetPropertyInt64(ctx, obj, from + i,
JS_DupValue(ctx, argv[i])) < 0)
goto exception;
}
if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0)
goto exception;
}
JS_FreeValue(ctx, obj);
return JS_NewInt64(ctx, newLen);
@ -39079,6 +39244,11 @@ static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target,
int64_t sourceIndex, elementLen;
int present, is_array;
if (js_check_stack_overflow(ctx->rt, 0)) {
JS_ThrowStackOverflow(ctx);
return -1;
}
for (sourceIndex = 0; sourceIndex < sourceLen; sourceIndex++) {
present = JS_TryGetPropertyInt64(ctx, source, sourceIndex, &element);
if (present < 0)
@ -41816,7 +41986,7 @@ static JSValue js___date_clock(JSContext *ctx, JSValueConst this_val,
}
/* OS dependent. d = argv[0] is in ms from 1970. Return the difference
between local time and UTC time 'd' in minutes */
between UTC time and local time 'd' in minutes */
static int getTimezoneOffset(int64_t time) {
#if defined(_WIN32)
/* XXX: TODO */
@ -44165,7 +44335,7 @@ static JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val,
atom = JS_ValueToAtom(ctx, prop);
if (unlikely(atom == JS_ATOM_NULL))
return JS_EXCEPTION;
ret = JS_SetPropertyGeneric(ctx, JS_VALUE_GET_OBJ(obj), atom,
ret = JS_SetPropertyGeneric(ctx, obj, atom,
JS_DupValue(ctx, val), receiver, 0);
JS_FreeAtom(ctx, atom);
if (ret < 0)
@ -44513,7 +44683,7 @@ static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom,
if (!s)
return -1;
if (JS_IsUndefined(method)) {
return JS_SetPropertyGeneric(ctx, JS_VALUE_GET_OBJ(s->target), atom,
return JS_SetPropertyGeneric(ctx, s->target, atom,
JS_DupValue(ctx, value), receiver,
flags);
}
@ -48134,24 +48304,22 @@ static void string_skip_non_spaces(JSString *sp, int *pp) {
*pp += 1;
}
/* parse a numeric field */
static int string_get_field(JSString *sp, int *pp, int64_t *pval) {
/* parse a numeric field with an optional sign if accept_sign is TRUE */
static int string_get_digits(JSString *sp, int *pp, int64_t *pval) {
int64_t v = 0;
int c, p = *pp;
int c, p = *pp, p_start;
/* skip non digits, should only skip spaces? */
while (p < sp->len) {
c = string_get(sp, p);
if (c >= '0' && c <= '9')
break;
p++;
}
if (p >= sp->len)
return -1;
p_start = p;
while (p < sp->len) {
c = string_get(sp, p);
if (!(c >= '0' && c <= '9'))
break;
if (!(c >= '0' && c <= '9')) {
if (p == p_start)
return -1;
else
break;
}
v = v * 10 + c - '0';
p++;
}
@ -48160,8 +48328,25 @@ static int string_get_field(JSString *sp, int *pp, int64_t *pval) {
return 0;
}
static int string_get_signed_digits(JSString *sp, int *pp, int64_t *pval) {
int res, sgn, p = *pp;
if (p >= sp->len)
return -1;
sgn = string_get(sp, p);
if (sgn == '-' || sgn == '+')
p++;
res = string_get_digits(sp, &p, pval);
if (res == 0 && sgn == '-')
*pval = -*pval;
*pp = p;
return res;
}
/* parse a fixed width numeric field */
static int string_get_digits(JSString *sp, int *pp, int n, int64_t *pval) {
static int string_get_fixed_width_digits(JSString *sp, int *pp, int n, int64_t *pval) {
int64_t v = 0;
int i, c, p = *pp;
@ -48179,23 +48364,32 @@ static int string_get_digits(JSString *sp, int *pp, int n, int64_t *pval) {
return 0;
}
/* parse a signed numeric field */
static int string_get_signed_field(JSString *sp, int *pp, int64_t *pval) {
int sgn, res;
if (*pp >= sp->len)
static int string_get_milliseconds(JSString *sp, int *pp, int64_t *pval) {
/* parse milliseconds as a fractional part, round to nearest */
/* XXX: the spec does not indicate which rounding should be used */
int mul = 1000, ms = 0, p = *pp, c, p_start;
if (p >= sp->len)
return -1;
sgn = string_get(sp, *pp);
if (sgn == '-' || sgn == '+')
*pp += 1;
res = string_get_field(sp, pp, pval);
if (res == 0 && sgn == '-')
*pval = -*pval;
return res;
p_start = p;
while (p < sp->len) {
c = string_get(sp, p);
if (!(c >= '0' && c <= '9')) {
if (p == p_start)
return -1;
else
break;
}
if (mul == 1 && c >= '5')
ms += 1;
ms += (c - '0') * (mul /= 10);
p++;
}
*pval = ms;
*pp = p;
return 0;
}
static int find_abbrev(JSString *sp, int p, const char *list, int count) {
int n, i;
@ -48234,7 +48428,7 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
double fields1[7];
int64_t tz, hh, mm;
double d;
int p, i, c, sgn;
int p, i, c, sgn, l;
JSString *sp;
BOOL is_local;
@ -48249,50 +48443,74 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
if (p < sp->len && (((c = string_get(sp, p)) >= '0' && c <= '9') || c == '+' || c == '-')) {
/* ISO format */
/* year field can be negative */
/* XXX: could be stricter */
if (string_get_signed_field(sp, &p, &fields[0]))
if (string_get_signed_digits(sp, &p, &fields[0]))
goto done;
is_local = TRUE;
for (i = 1; i < 6; i++) {
if (string_get_field(sp, &p, &fields[i]))
for (i = 1; i < 7; i++) {
if (p >= sp->len)
break;
switch(i) {
case 1:
case 2:
c = '-';
break;
case 3:
c = 'T';
break;
case 4:
case 5:
c = ':';
break;
case 6:
c = '.';
break;
}
if (i <= 3) {
/* no time: UTC by default */
is_local = FALSE;
} else if (i == 6 && p < sp->len && string_get(sp, p) == '.') {
/* parse milliseconds as a fractional part, round to nearest */
/* XXX: the spec does not indicate which rounding should be used */
int mul = 1000, ms = 0;
while (++p < sp->len) {
int c = string_get(sp, p);
if (!(c >= '0' && c <= '9'))
break;
if (mul == 1 && c >= '5')
ms += 1;
ms += (c - '0') * (mul /= 10);
}
fields[6] = ms;
if (string_get(sp, p) != c)
break;
p++;
if (i == 6) {
if (string_get_milliseconds(sp, &p, &fields[i]))
goto done;
} else {
if (string_get_digits(sp, &p, &fields[i]))
goto done;
}
}
/* no time: UTC by default */
is_local = (i > 3);
fields[1] -= 1;
/* parse the time zone offset if present: [+-]HH:mm */
/* parse the time zone offset if present: [+-]HH:mm or [+-]HHmm */
tz = 0;
if (p < sp->len) {
sgn = string_get(sp, p);
if (sgn == '+' || sgn == '-') {
if (string_get_field(sp, &p, &hh))
p++;
l = sp->len - p;
if (l != 4 && l != 5)
goto done;
if (string_get_field(sp, &p, &mm))
if (string_get_fixed_width_digits(sp, &p, 2, &hh))
goto done;
if (l == 5) {
if (string_get(sp, p) != ':')
goto done;
p++;
}
if (string_get_fixed_width_digits(sp, &p, 2, &mm))
goto done;
tz = hh * 60 + mm;
if (sgn == '-')
tz = -tz;
is_local = FALSE;
} else if (sgn == 'Z') {
p++;
is_local = FALSE;
} else {
goto done;
}
/* error if extraneous characters */
if (p != sp->len)
goto done;
}
} else {
/* toString or toUTCString format */
@ -48304,7 +48522,7 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
c = string_get(sp, p);
if (c >= '0' && c <= '9') {
/* day of month first */
if (string_get_field(sp, &p, &fields[2]))
if (string_get_digits(sp, &p, &fields[2]))
goto done;
if (string_get_month(sp, &p, &fields[1]))
goto done;
@ -48312,16 +48530,26 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
/* month first */
if (string_get_month(sp, &p, &fields[1]))
goto done;
if (string_get_field(sp, &p, &fields[2]))
string_skip_spaces(sp, &p);
if (string_get_digits(sp, &p, &fields[2]))
goto done;
}
/* year */
string_skip_spaces(sp, &p);
if (string_get_signed_field(sp, &p, &fields[0]))
if (string_get_signed_digits(sp, &p, &fields[0]))
goto done;
/* hour, min, seconds */
string_skip_spaces(sp, &p);
for(i = 0; i < 3; i++) {
if (string_get_field(sp, &p, &fields[3 + i]))
if (i == 1 || i == 2) {
if (p >= sp->len)
goto done;
if (string_get(sp, p) != ':')
goto done;
p++;
}
if (string_get_digits(sp, &p, &fields[3 + i]))
goto done;
}
// XXX: parse optional milliseconds?
@ -48333,9 +48561,9 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
sgn = string_get(sp, p);
if (sgn == '+' || sgn == '-') {
p++;
if (string_get_digits(sp, &p, 2, &hh))
if (string_get_fixed_width_digits(sp, &p, 2, &hh))
goto done;
if (string_get_digits(sp, &p, 2, &mm))
if (string_get_fixed_width_digits(sp, &p, 2, &mm))
goto done;
tz = hh * 60 + mm;
if (sgn == '-')
@ -51886,9 +52114,15 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
inc = 1;
}
if (validate_typed_array(ctx, this_val))
goto exception;
p = JS_VALUE_GET_OBJ(this_val);
/* if the array was detached, no need to go further (but no
exception is raised) */
if (typed_array_is_detached(ctx, p)) {
/* "includes" scans all the properties, so "undefined" can match */
if (special == special_includes && JS_IsUndefined(argv[0]) && len > 0)
res = 0;
goto done;
}
is_bigint = 0;
is_int = 0; /* avoid warning */
@ -51925,7 +52159,6 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
goto done;
}
p = JS_VALUE_GET_OBJ(this_val);
switch (p->class_id) {
case JS_CLASS_INT8_ARRAY:
if (is_int && (int8_t)v64 == v64)
@ -52114,13 +52347,16 @@ static JSValue js_typed_array_join(JSContext *ctx, JSValueConst this_val,
}
}
el = JS_GetPropertyUint32(ctx, this_val, i);
if (JS_IsException(el))
goto fail;
if (toLocaleString) {
el = JS_ToLocaleStringFree(ctx, el);
/* Can return undefined for example if the typed array is detached */
if (!JS_IsNull(el) && !JS_IsUndefined(el)) {
if (JS_IsException(el))
goto fail;
if (toLocaleString) {
el = JS_ToLocaleStringFree(ctx, el);
}
if (string_buffer_concat_value_free(b, el))
goto fail;
}
if (string_buffer_concat_value_free(b, el))
goto fail;
}
JS_FreeValue(ctx, sep);
return string_buffer_end(b);

View File

@ -1,8 +1,8 @@
/*
* QuickJS Javascript Engine
*
* Copyright (c) 2017-2020 Fabrice Bellard
* Copyright (c) 2017-2020 Charlie Gordon
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -333,7 +333,11 @@ JSRuntime *JS_NewRuntime(void);
void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
/* use 0 to disable maximum stack size check */
void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size);
/* should be called when changing thread to update the stack top value
used to check stack overflow. */
void JS_UpdateStackTop(JSRuntime *rt);
JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque);
void JS_FreeRuntime(JSRuntime *rt);
void *JS_GetRuntimeOpaque(JSRuntime *rt);

View File

@ -131,7 +131,8 @@ outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir $outdir/doc $outdir/tests $outdir/examples
cp Makefile VERSION TODO Changelog readme.txt release.sh unicode_download.sh \
cp Makefile VERSION TODO Changelog readme.txt LICENSE \
release.sh unicode_download.sh \
qjs.c qjsc.c qjscalc.js repl.js \
quickjs.c quickjs.h quickjs-atom.h \
quickjs-libc.c quickjs-libc.h quickjs-opcode.h \

View File

@ -1,8 +1,8 @@
/*
* ECMA Test 262 Runner for QuickJS
*
* Copyright (c) 2017-2020 Fabrice Bellard
* Copyright (c) 2017-2020 Charlie Gordon
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@ -51,10 +51,10 @@ testdir=test262/test
AggregateError
align-detached-buffer-semantics-with-web-reality
arbitrary-module-namespace-names=skip
Array.prototype.at=skip
Array.prototype.flat
Array.prototype.flatMap
Array.prototype.flatten
Array.prototype.item=skip
Array.prototype.values
ArrayBuffer
arrow-function
@ -141,7 +141,7 @@ string-trimming
String.fromCodePoint
String.prototype.endsWith
String.prototype.includes
String.prototype.item=skip
String.prototype.at=skip
String.prototype.matchAll
String.prototype.replaceAll
String.prototype.trimEnd
@ -166,7 +166,7 @@ tail-call-optimization=skip
template
top-level-await=skip
TypedArray
TypedArray.prototype.item=skip
TypedArray.prototype.at=skip
u180e
Uint16Array
Uint32Array

View File

@ -2,50 +2,34 @@ test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-r
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/RegExp/named-groups/non-unicode-property-names-valid.js:46: SyntaxError: invalid group name
test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js:46: strict mode: SyntaxError: invalid group name
test262/test/built-ins/TypedArray/prototype/every/BigInt/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/every/BigInt/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/every/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/every/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/filter/BigInt/callbackfn-detachbuffer.js:20: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/filter/BigInt/callbackfn-detachbuffer.js:20: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/filter/callbackfn-detachbuffer.js:20: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/filter/callbackfn-detachbuffer.js:20: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/findIndex/BigInt/predicate-may-detach-buffer.js:36: Test262Error: throws a TypeError getting a value from the detached buffer Expected a TypeError to be thrown but no exception was thrown at all (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/findIndex/BigInt/predicate-may-detach-buffer.js:36: strict mode: Test262Error: throws a TypeError getting a value from the detached buffer Expected a TypeError to be thrown but no exception was thrown at all (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/forEach/BigInt/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/forEach/BigInt/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/forEach/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/forEach/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/map/BigInt/callbackfn-detachbuffer.js:20: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/map/BigInt/callbackfn-detachbuffer.js:20: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/map/callbackfn-detachbuffer.js:20: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/map/callbackfn-detachbuffer.js:20: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/reduce/BigInt/callbackfn-detachbuffer.js:29: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/reduce/BigInt/callbackfn-detachbuffer.js:29: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/reduce/callbackfn-detachbuffer.js:29: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/reduce/callbackfn-detachbuffer.js:29: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/reduceRight/BigInt/callbackfn-detachbuffer.js:29: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/reduceRight/BigInt/callbackfn-detachbuffer.js:29: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/reduceRight/callbackfn-detachbuffer.js:29: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/reduceRight/callbackfn-detachbuffer.js:29: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/some/BigInt/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/some/BigInt/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArray/prototype/some/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArray/prototype/some/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/detached-buffer.js:37: Test262Error: (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/detached-buffer.js:37: strict mode: Test262Error: (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/detached-buffer.js:38: Test262Error: (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/detached-buffer.js:38: strict mode: Test262Error: (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/GetOwnProperty/BigInt/index-prop-desc.js:21: Test262Error: Expected SameValue(«43», «42») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/GetOwnProperty/BigInt/index-prop-desc.js:21: strict mode: Test262Error: Expected SameValue(«43», «42») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/GetOwnProperty/index-prop-desc.js:22: Test262Error: Expected SameValue(«43», «42») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/GetOwnProperty/index-prop-desc.js:22: strict mode: Test262Error: Expected SameValue(«43», «42») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer-realm.js:36: strict mode: TypeError: out-of-bound numeric index (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/detached-buffer.js:46: Test262Error: (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/detached-buffer.js:46: strict mode: Test262Error: (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/detached-buffer.js:47: Test262Error: (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/detached-buffer.js:47: strict mode: Test262Error: (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer-realm.js:37: strict mode: TypeError: out-of-bound numeric index (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer.js:34: TypeError: cannot convert bigint to number (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer.js:32: strict mode: TypeError: out-of-bound numeric index (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/detached-buffer-realm.js:36: strict mode: TypeError: out-of-bound numeric index (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-minus-zero.js:20: Test262Error: Reflect.set("new TA([42n])", "-0", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-minus-zero.js:20: strict mode: Test262Error: Reflect.set("new TA([42n])", "-0", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-not-integer.js:21: Test262Error: Reflect.set("new TA([42n])", "1.1", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-not-integer.js:21: strict mode: Test262Error: Reflect.set("new TA([42n])", "1.1", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-out-of-bounds.js:27: Test262Error: Reflect.set("new TA([42n])", "-1", 1n) must return false Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-out-of-bounds.js:27: strict mode: Test262Error: Reflect.set("new TA([42n])", "-1", 1n) must return false Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/tonumber-value-detached-buffer.js:24: Test262Error: Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/tonumber-value-detached-buffer.js:24: strict mode: Test262Error: Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/detached-buffer-realm.js:37: strict mode: TypeError: out-of-bound numeric index (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/detached-buffer.js:32: strict mode: TypeError: out-of-bound numeric index (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-minus-zero.js:22: Test262Error: Reflect.set(sample, "-0", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-minus-zero.js:22: strict mode: Test262Error: Reflect.set(sample, "-0", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-not-integer.js:22: Test262Error: Reflect.set(sample, "1.1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-not-integer.js:22: strict mode: Test262Error: Reflect.set(sample, "1.1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds.js:22: Test262Error: Reflect.set(sample, "-1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds.js:22: strict mode: Test262Error: Reflect.set(sample, "-1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/tonumber-value-detached-buffer.js:39: Test262Error: Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
test262/test/built-ins/TypedArrayConstructors/internals/Set/tonumber-value-detached-buffer.js:39: strict mode: Test262Error: Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
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/optional-chaining/optional-call-preserves-this.js:21: TypeError: cannot read property 'c' of undefined
test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:15: strict mode: TypeError: cannot read property '_b' of undefined
test262/test/language/statements/for-of/head-lhs-async-invalid.js:14: unexpected error type: Test262: This statement should not be evaluated.
test262/test/language/statements/for-of/head-lhs-async-invalid.js:14: strict mode: unexpected error type: Test262: This statement should not be evaluated.

View File

@ -399,7 +399,7 @@ function test_eval()
function test_typed_array()
{
var buffer, a, i;
var buffer, a, i, str;
a = new Uint8Array(4);
assert(a.length, 4);
@ -439,7 +439,12 @@ function test_typed_array()
a = new Uint8Array(buffer);
assert(a.toString(), "0,0,255,255,0,0,0,0,0,0,128,63,255,255,255,255");
str = a.toString();
/* test little and big endian cases */
if (str !== "0,0,255,255,0,0,0,0,0,0,128,63,255,255,255,255" &&
str !== "0,0,255,255,0,0,0,0,63,128,0,0,255,255,255,255") {
assert(false);
}
assert(a.buffer, buffer);