This is an automated email from the ASF dual-hosted git repository. vatamane pushed a commit to branch update-quickjs-5 in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit f9a52f3a2e9e60d71de00ba91079e2136532de44 Author: Nick Vatamaniuc <[email protected]> AuthorDate: Wed Oct 15 22:03:03 2025 -0400 Update QuickJS: faster context creation and faster dbuf * Faster context creation and exception checks in JS_NewContext https://github.com/bellard/quickjs/commit/42eb2795f0daec0adddb0392823a27a64b676169 * Faster and safer dbuf functions https://github.com/bellard/quickjs/commit/0d4cd2d0517fc6675320829d38fa9c06a415f720 * Fixed argument evaluation order in Date constructor and Date.UTC() https://github.com/bellard/quickjs/commit/7fb994c45d884769efee1b6d87fee9f60e246075 * Stricter year parsing in Date https://github.com/bellard/quickjs/commit/2161640067cd2e2a0127d41eddcb5903d43e8aa2 --- .../patches/01-spidermonkey-185-mode.patch | 6 +- src/couch_quickjs/patches/02-test262-errors.patch | 14 +- src/couch_quickjs/quickjs/Makefile | 2 +- src/couch_quickjs/quickjs/cutils.c | 52 +- src/couch_quickjs/quickjs/cutils.h | 46 +- src/couch_quickjs/quickjs/libregexp.c | 4 +- src/couch_quickjs/quickjs/libunicode.c | 2 +- src/couch_quickjs/quickjs/quickjs-atom.h | 1 + src/couch_quickjs/quickjs/quickjs.c | 1428 +++++++++++--------- src/couch_quickjs/quickjs/quickjs.h | 30 +- src/couch_quickjs/quickjs/test262_errors.txt | 15 +- 11 files changed, 867 insertions(+), 733 deletions(-) diff --git a/src/couch_quickjs/patches/01-spidermonkey-185-mode.patch b/src/couch_quickjs/patches/01-spidermonkey-185-mode.patch index cbb77897c..1af4c4f50 100644 --- a/src/couch_quickjs/patches/01-spidermonkey-185-mode.patch +++ b/src/couch_quickjs/patches/01-spidermonkey-185-mode.patch @@ -1,6 +1,6 @@ ---- quickjs-master/quickjs.c 2025-10-08 08:16:51 -+++ quickjs/quickjs.c 2025-10-08 17:43:48 -@@ -30951,10 +30951,24 @@ +--- quickjs-master/quickjs.c 2025-10-13 08:51:37 ++++ quickjs/quickjs.c 2025-10-15 21:57:44 +@@ -30997,10 +30997,24 @@ if (s->token.val == TOK_FUNCTION || (token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, TRUE) == TOK_FUNCTION)) { diff --git a/src/couch_quickjs/patches/02-test262-errors.patch b/src/couch_quickjs/patches/02-test262-errors.patch index 41ff848ab..c73d088cf 100644 --- a/src/couch_quickjs/patches/02-test262-errors.patch +++ b/src/couch_quickjs/patches/02-test262-errors.patch @@ -1,11 +1,11 @@ ---- quickjs-master/test262_errors.txt 2025-10-08 08:16:51 -+++ quickjs/test262_errors.txt 2025-10-08 17:43:48 -@@ -6,6 +6,8 @@ - test262/test/annexB/language/expressions/assignmenttargettype/callexpression.js:33: SyntaxError: invalid assignment left-hand side +--- quickjs-master/test262_errors.txt 2025-10-13 08:51:37 ++++ quickjs/test262_errors.txt 2025-10-15 22:00:27 +@@ -7,6 +7,8 @@ test262/test/annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js:20: SyntaxError: invalid assignment left-hand side test262/test/language/identifier-resolution/assign-to-global-undefined.js:20: strict mode: expected error + test262/test/language/module-code/top-level-await/rejection-order.js:20: TypeError: $DONE() not called +test262/test/language/statements/expression/S12.4_A1.js:15: unexpected error type: Test262: This statement should not be evaluated. +test262/test/language/statements/expression/S12.4_A1.js:15: strict mode: unexpected error type: Test262: This statement should not be evaluated. - test262/test/staging/sm/Date/UTC-convert-all-arguments.js:13: Test262Error: index 1: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true - test262/test/staging/sm/Date/UTC-convert-all-arguments.js:13: strict mode: Test262Error: index 1: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true - test262/test/staging/sm/Date/constructor-convert-all-arguments.js:13: Test262Error: index undefined: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true + test262/test/staging/sm/Function/arguments-parameter-shadowing.js:14: Test262Error: Expected SameValue(«true», «false») to be true + test262/test/staging/sm/Function/constructor-binding.js:11: Test262Error: Expected SameValue(«"function"», «"undefined"») to be true + test262/test/staging/sm/Function/constructor-binding.js:11: strict mode: Test262Error: Expected SameValue(«"function"», «"undefined"») to be true diff --git a/src/couch_quickjs/quickjs/Makefile b/src/couch_quickjs/quickjs/Makefile index 0ddb759f3..ba64923d2 100644 --- a/src/couch_quickjs/quickjs/Makefile +++ b/src/couch_quickjs/quickjs/Makefile @@ -55,7 +55,7 @@ PREFIX?=/usr/local #CONFIG_UBSAN=y # TEST262 bootstrap config: commit id and shallow "since" parameter -TEST262_COMMIT?=06dfddc4ebd21c39e1ce44f3e13b56b0dfda28e3 +TEST262_COMMIT?=42303c7c2bcf1c1edb9e5375c291c6fbc8a261ab TEST262_SINCE?=2025-09-01 OBJDIR=.obj diff --git a/src/couch_quickjs/quickjs/cutils.c b/src/couch_quickjs/quickjs/cutils.c index c038cf44c..52ff1649b 100644 --- a/src/couch_quickjs/quickjs/cutils.c +++ b/src/couch_quickjs/quickjs/cutils.c @@ -100,15 +100,20 @@ void dbuf_init(DynBuf *s) dbuf_init2(s, NULL, NULL); } -/* return < 0 if error */ -int dbuf_realloc(DynBuf *s, size_t new_size) +/* Try to allocate 'len' more bytes. return < 0 if error */ +int dbuf_claim(DynBuf *s, size_t len) { - size_t size; + size_t new_size, size; uint8_t *new_buf; + new_size = s->size + len; + if (new_size < len) + return -1; /* overflow case */ if (new_size > s->allocated_size) { if (s->error) return -1; - size = s->allocated_size * 3 / 2; + size = s->allocated_size + (s->allocated_size / 2); + if (size < s->allocated_size) + return -1; /* overflow case */ if (size > new_size) new_size = size; new_buf = s->realloc_func(s->opaque, s->buf, new_size); @@ -122,22 +127,10 @@ int dbuf_realloc(DynBuf *s, size_t new_size) return 0; } -int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len) -{ - size_t end; - end = offset + len; - if (dbuf_realloc(s, end)) - return -1; - memcpy(s->buf + offset, data, len); - if (end > s->size) - s->size = end; - return 0; -} - int dbuf_put(DynBuf *s, const uint8_t *data, size_t len) { - if (unlikely((s->size + len) > s->allocated_size)) { - if (dbuf_realloc(s, s->size + len)) + if (unlikely((s->allocated_size - s->size) < len)) { + if (dbuf_claim(s, len)) return -1; } memcpy_no_ub(s->buf + s->size, data, len); @@ -147,8 +140,8 @@ int dbuf_put(DynBuf *s, const uint8_t *data, size_t len) int dbuf_put_self(DynBuf *s, size_t offset, size_t len) { - if (unlikely((s->size + len) > s->allocated_size)) { - if (dbuf_realloc(s, s->size + len)) + if (unlikely((s->allocated_size - s->size) < len)) { + if (dbuf_claim(s, len)) return -1; } memcpy(s->buf + s->size, s->buf + offset, len); @@ -156,11 +149,26 @@ int dbuf_put_self(DynBuf *s, size_t offset, size_t len) return 0; } -int dbuf_putc(DynBuf *s, uint8_t c) +int __dbuf_putc(DynBuf *s, uint8_t c) { return dbuf_put(s, &c, 1); } +int __dbuf_put_u16(DynBuf *s, uint16_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 2); +} + +int __dbuf_put_u32(DynBuf *s, uint32_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 4); +} + +int __dbuf_put_u64(DynBuf *s, uint64_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 8); +} + int dbuf_putstr(DynBuf *s, const char *str) { return dbuf_put(s, (const uint8_t *)str, strlen(str)); @@ -182,7 +190,7 @@ int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, /* fast case */ return dbuf_put(s, (uint8_t *)buf, len); } else { - if (dbuf_realloc(s, s->size + len + 1)) + if (dbuf_claim(s, len + 1)) return -1; va_start(ap, fmt); vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size, diff --git a/src/couch_quickjs/quickjs/cutils.h b/src/couch_quickjs/quickjs/cutils.h index 9fcb7a607..094a8f124 100644 --- a/src/couch_quickjs/quickjs/cutils.h +++ b/src/couch_quickjs/quickjs/cutils.h @@ -264,24 +264,58 @@ typedef struct DynBuf { void dbuf_init(DynBuf *s); void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func); -int dbuf_realloc(DynBuf *s, size_t new_size); -int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len); +int dbuf_claim(DynBuf *s, size_t len); int dbuf_put(DynBuf *s, const uint8_t *data, size_t len); int dbuf_put_self(DynBuf *s, size_t offset, size_t len); -int dbuf_putc(DynBuf *s, uint8_t c); int dbuf_putstr(DynBuf *s, const char *str); +int __dbuf_putc(DynBuf *s, uint8_t c); +int __dbuf_put_u16(DynBuf *s, uint16_t val); +int __dbuf_put_u32(DynBuf *s, uint32_t val); +int __dbuf_put_u64(DynBuf *s, uint64_t val); + +static inline int dbuf_putc(DynBuf *s, uint8_t val) +{ + if (unlikely((s->allocated_size - s->size) < 1)) { + return __dbuf_putc(s, val); + } else { + s->buf[s->size++] = val; + return 0; + } +} + static inline int dbuf_put_u16(DynBuf *s, uint16_t val) { - return dbuf_put(s, (uint8_t *)&val, 2); + if (unlikely((s->allocated_size - s->size) < 2)) { + return __dbuf_put_u16(s, val); + } else { + put_u16(s->buf + s->size, val); + s->size += 2; + return 0; + } } + static inline int dbuf_put_u32(DynBuf *s, uint32_t val) { - return dbuf_put(s, (uint8_t *)&val, 4); + if (unlikely((s->allocated_size - s->size) < 4)) { + return __dbuf_put_u32(s, val); + } else { + put_u32(s->buf + s->size, val); + s->size += 4; + return 0; + } } + static inline int dbuf_put_u64(DynBuf *s, uint64_t val) { - return dbuf_put(s, (uint8_t *)&val, 8); + if (unlikely((s->allocated_size - s->size) < 8)) { + return __dbuf_put_u64(s, val); + } else { + put_u64(s->buf + s->size, val); + s->size += 8; + return 0; + } } + int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, const char *fmt, ...); void dbuf_free(DynBuf *s); diff --git a/src/couch_quickjs/quickjs/libregexp.c b/src/couch_quickjs/quickjs/libregexp.c index 0cf9a1261..118d950eb 100644 --- a/src/couch_quickjs/quickjs/libregexp.c +++ b/src/couch_quickjs/quickjs/libregexp.c @@ -117,7 +117,7 @@ static inline int is_digit(int c) { /* insert 'len' bytes at position 'pos'. Return < 0 if error. */ static int dbuf_insert(DynBuf *s, int pos, int len) { - if (dbuf_realloc(s, s->size + len)) + if (dbuf_claim(s, len)) return -1; memmove(s->buf + pos + len, s->buf + pos, s->size - pos); s->size += len; @@ -2340,7 +2340,7 @@ static int re_parse_alternative(REParseState *s, BOOL is_backward_dir) speed is not really critical here) */ end = s->byte_code.size; term_size = end - term_start; - if (dbuf_realloc(&s->byte_code, end + term_size)) + if (dbuf_claim(&s->byte_code, term_size)) return -1; memmove(s->byte_code.buf + start + term_size, s->byte_code.buf + start, diff --git a/src/couch_quickjs/quickjs/libunicode.c b/src/couch_quickjs/quickjs/libunicode.c index 3791523d6..0c510ccb1 100644 --- a/src/couch_quickjs/quickjs/libunicode.c +++ b/src/couch_quickjs/quickjs/libunicode.c @@ -1179,7 +1179,7 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, is_compat = n_type >> 1; dbuf_init2(dbuf, opaque, realloc_func); - if (dbuf_realloc(dbuf, sizeof(int) * src_len)) + if (dbuf_claim(dbuf, sizeof(int) * src_len)) goto fail; /* common case: latin1 is unaffected by NFC */ diff --git a/src/couch_quickjs/quickjs/quickjs-atom.h b/src/couch_quickjs/quickjs/quickjs-atom.h index b598ec655..23c2ed07a 100644 --- a/src/couch_quickjs/quickjs/quickjs-atom.h +++ b/src/couch_quickjs/quickjs/quickjs-atom.h @@ -256,6 +256,7 @@ DEF(SyntaxError, "SyntaxError") DEF(TypeError, "TypeError") DEF(URIError, "URIError") DEF(InternalError, "InternalError") +DEF(AggregateError, "AggregateError") /* private symbols */ DEF(Private_brand, "<brand>") /* symbols */ diff --git a/src/couch_quickjs/quickjs/quickjs.c b/src/couch_quickjs/quickjs/quickjs.c index 3c2236975..22a3ecedf 100644 --- a/src/couch_quickjs/quickjs/quickjs.c +++ b/src/couch_quickjs/quickjs/quickjs.c @@ -897,7 +897,6 @@ typedef struct JSProperty { #define JS_PROP_INITIAL_SIZE 2 #define JS_PROP_INITIAL_HASH_SIZE 4 /* must be a power of two */ -#define JS_ARRAY_INITIAL_SIZE 2 typedef struct JSShapeProperty { uint32_t hash_next : 26; /* 0 if last in list */ @@ -1273,7 +1272,7 @@ static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val); static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, JSObject *p, JSAtom prop); static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc); -static void JS_AddIntrinsicBasicObjects(JSContext *ctx); +static int JS_AddIntrinsicBasicObjects(JSContext *ctx); static void js_free_shape(JSRuntime *rt, JSShape *sh); static void js_free_shape_null(JSRuntime *rt, JSShape *sh); static int js_shape_prepare_update(JSContext *ctx, JSObject *p, @@ -2162,7 +2161,10 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) ctx->promise_ctor = JS_NULL; init_list_head(&ctx->loaded_modules); - JS_AddIntrinsicBasicObjects(ctx); + if (JS_AddIntrinsicBasicObjects(ctx)) { + JS_FreeContext(ctx); + return NULL; + } return ctx; } @@ -2174,17 +2176,20 @@ JSContext *JS_NewContext(JSRuntime *rt) if (!ctx) return NULL; - JS_AddIntrinsicBaseObjects(ctx); - JS_AddIntrinsicDate(ctx); - JS_AddIntrinsicEval(ctx); - JS_AddIntrinsicStringNormalize(ctx); - JS_AddIntrinsicRegExp(ctx); - JS_AddIntrinsicJSON(ctx); - JS_AddIntrinsicProxy(ctx); - JS_AddIntrinsicMapSet(ctx); - JS_AddIntrinsicTypedArrays(ctx); - JS_AddIntrinsicPromise(ctx); - JS_AddIntrinsicWeakRef(ctx); + if (JS_AddIntrinsicBaseObjects(ctx) || + JS_AddIntrinsicDate(ctx) || + JS_AddIntrinsicEval(ctx) || + JS_AddIntrinsicStringNormalize(ctx) || + JS_AddIntrinsicRegExp(ctx) || + JS_AddIntrinsicJSON(ctx) || + JS_AddIntrinsicProxy(ctx) || + JS_AddIntrinsicMapSet(ctx) || + JS_AddIntrinsicTypedArrays(ctx) || + JS_AddIntrinsicPromise(ctx) || + JS_AddIntrinsicWeakRef(ctx)) { + JS_FreeContext(ctx); + return NULL; + } return ctx; } @@ -2608,7 +2613,7 @@ static int JS_InitAtoms(JSRuntime *rt) rt->atom_count = 0; rt->atom_size = 0; rt->atom_free_index = 0; - if (JS_ResizeAtomHash(rt, 256)) /* there are at least 195 predefined atoms */ + if (JS_ResizeAtomHash(rt, 512)) /* there are at least 504 predefined atoms */ return -1; p = js_atom_init; @@ -2753,9 +2758,9 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) /* alloc new with size progression 3/2: 4 6 9 13 19 28 42 63 94 141 211 316 474 711 1066 1599 2398 3597 5395 8092 - preallocating space for predefined atoms (at least 195). + preallocating space for predefined atoms (at least 504). */ - new_size = max_int(211, rt->atom_size * 3 / 2); + new_size = max_int(711, rt->atom_size * 3 / 2); if (new_size > JS_ATOM_MAX) goto fail; /* XXX: should use realloc2 to use slack space */ @@ -4738,19 +4743,14 @@ static void js_shape_hash_unlink(JSRuntime *rt, JSShape *sh) rt->shape_hash_count--; } -/* create a new empty shape with prototype 'proto' */ -static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, - int hash_size, int prop_size) +/* create a new empty shape with prototype 'proto'. It is not hashed */ +static inline JSShape *js_new_shape_nohash(JSContext *ctx, JSObject *proto, + int hash_size, int prop_size) { JSRuntime *rt = ctx->rt; void *sh_alloc; JSShape *sh; - /* resize the shape hash table if necessary */ - if (2 * (rt->shape_hash_count + 1) > rt->shape_hash_size) { - resize_shape_hash(rt, rt->shape_hash_bits + 1); - } - sh_alloc = js_malloc(ctx, get_shape_size(hash_size, prop_size)); if (!sh_alloc) return NULL; @@ -4766,7 +4766,26 @@ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, sh->prop_size = prop_size; sh->prop_count = 0; sh->deleted_prop_count = 0; + sh->is_hashed = FALSE; + return sh; +} + +/* create a new empty shape with prototype 'proto' */ +static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, + int hash_size, int prop_size) +{ + JSRuntime *rt = ctx->rt; + JSShape *sh; + + /* resize the shape hash table if necessary */ + if (2 * (rt->shape_hash_count + 1) > rt->shape_hash_size) { + resize_shape_hash(rt, rt->shape_hash_bits + 1); + } + sh = js_new_shape_nohash(ctx, proto, hash_size, prop_size); + if (!sh) + return NULL; + /* insert in the hash table */ sh->hash = shape_initial_hash(proto); sh->is_hashed = TRUE; @@ -5247,6 +5266,29 @@ JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val, return JS_NewObjectFromShape(ctx, sh, class_id); } +/* WARNING: the shape is not hashed. It is used for objects where + factorizing the shape is not relevant (prototypes, constructors) */ +static JSValue JS_NewObjectProtoClassAlloc(JSContext *ctx, JSValueConst proto_val, + JSClassID class_id, int n_alloc_props) +{ + JSShape *sh; + JSObject *proto; + int hash_size, hash_bits; + + if (n_alloc_props <= JS_PROP_INITIAL_SIZE) { + n_alloc_props = JS_PROP_INITIAL_SIZE; + hash_size = JS_PROP_INITIAL_HASH_SIZE; + } else { + hash_bits = 32 - clz32(n_alloc_props - 1); /* ceil(log2(radix)) */ + hash_size = 1 << hash_bits; + } + proto = get_proto_obj(proto_val); + sh = js_new_shape_nohash(ctx, proto, hash_size, n_alloc_props); + if (!sh) + return JS_EXCEPTION; + return JS_NewObjectFromShape(ctx, sh, class_id); +} + #if 0 static JSValue JS_GetObjectData(JSContext *ctx, JSValueConst obj) { @@ -5410,13 +5452,17 @@ static int js_method_set_properties(JSContext *ctx, JSValueConst func_obj, static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, const char *name, int length, JSCFunctionEnum cproto, int magic, - JSValueConst proto_val) + JSValueConst proto_val, int n_fields) { JSValue func_obj; JSObject *p; JSAtom name_atom; - func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION); + if (n_fields > 0) { + func_obj = JS_NewObjectProtoClassAlloc(ctx, proto_val, JS_CLASS_C_FUNCTION, n_fields); + } else { + func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION); + } if (JS_IsException(func_obj)) return func_obj; p = JS_VALUE_GET_OBJ(func_obj); @@ -5447,7 +5493,7 @@ JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, int length, JSCFunctionEnum cproto, int magic) { return JS_NewCFunction3(ctx, func, name, length, cproto, magic, - ctx->function_proto); + ctx->function_proto, 0); } typedef struct JSCFunctionDataRecord { @@ -22789,7 +22835,7 @@ static void emit_op(JSParseState *s, uint8_t val) static void emit_atom(JSParseState *s, JSAtom name) { DynBuf *bc = &s->cur_func->byte_code; - if (dbuf_realloc(bc, bc->size + 4)) + if (dbuf_claim(bc, 4)) return; /* not enough memory : don't duplicate the atom */ put_u32(bc->buf + bc->size, JS_DupAtom(s->ctx, name)); bc->size += 4; @@ -27705,7 +27751,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, int chunk_size = pos_expr - pos_next; int offset = bc->size - pos_next; int i; - dbuf_realloc(bc, bc->size + chunk_size); + dbuf_claim(bc, chunk_size); dbuf_put(bc, bc->buf + pos_next, chunk_size); memset(bc->buf + pos_next, OP_nop, chunk_size); /* `next` part ends with a goto */ @@ -28111,7 +28157,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, int chunk_size = pos_body - pos_cont; int offset = bc->size - pos_cont; int i; - dbuf_realloc(bc, bc->size + chunk_size); + dbuf_claim(bc, chunk_size); dbuf_put(bc, bc->buf + pos_cont, chunk_size); memset(bc->buf + pos_cont, OP_nop, chunk_size); /* increment part ends with a goto */ @@ -37065,7 +37111,7 @@ static int JS_WriteObjectAtoms(BCWriterState *s) /* XXX: could just append dbuf1 data, but it uses more memory if dbuf1 is larger than dbuf */ atoms_size = s->dbuf.size; - if (dbuf_realloc(&dbuf1, dbuf1.size + atoms_size)) + if (dbuf_claim(&dbuf1, atoms_size)) goto fail; memmove(dbuf1.buf + atoms_size, dbuf1.buf, dbuf1.size); memcpy(dbuf1.buf, s->dbuf.buf, atoms_size); @@ -38319,11 +38365,25 @@ static JSAtom find_atom(JSContext *ctx, const char *name) return atom; } +static JSValue JS_NewObjectProtoList(JSContext *ctx, JSValueConst proto, + const JSCFunctionListEntry *fields, int n_fields) +{ + JSValue obj; + obj = JS_NewObjectProtoClassAlloc(ctx, proto, JS_CLASS_OBJECT, n_fields); + if (JS_IsException(obj)) + return obj; + if (JS_SetPropertyFunctionList(ctx, obj, fields, n_fields)) { + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; + } + return obj; +} + static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque) { const JSCFunctionListEntry *e = opaque; - JSValue val; + JSValue val, proto; switch(e->def_type) { case JS_DEF_CFUNC: @@ -38334,8 +38394,13 @@ static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p, val = JS_NewAtomString(ctx, e->u.str); break; case JS_DEF_OBJECT: - val = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len); + /* XXX: could add a flag */ + if (atom == JS_ATOM_Symbol_unscopables) + proto = JS_NULL; + else + proto = ctx->class_proto[JS_CLASS_OBJECT]; + val = JS_NewObjectProtoList(ctx, proto, + e->u.prop_list.tab, e->u.prop_list.len); break; default: abort(); @@ -38424,6 +38489,12 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj, case JS_DEF_PROP_UNDEFINED: val = JS_UNDEFINED; break; + case JS_DEF_PROP_ATOM: + val = JS_AtomToValue(ctx, e->u.i32); + break; + case JS_DEF_PROP_BOOL: + val = JS_NewBool(ctx, e->u.i32); + break; case JS_DEF_PROP_STRING: case JS_DEF_OBJECT: JS_DefineAutoInitProperty(ctx, obj, atom, JS_AUTOINIT_ID_PROP, @@ -38491,8 +38562,8 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, val = __JS_NewFloat64(ctx, e->u.f64); break; case JS_DEF_OBJECT: - val = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len); + val = JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_OBJECT], + e->u.prop_list.tab, e->u.prop_list.len); break; default: abort(); @@ -38504,57 +38575,107 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, } /* Note: 'func_obj' is not necessarily a constructor */ -static void JS_SetConstructor2(JSContext *ctx, - JSValueConst func_obj, - JSValueConst proto, - int proto_flags, int ctor_flags) -{ - JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype, - JS_DupValue(ctx, proto), proto_flags); - JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor, - JS_DupValue(ctx, func_obj), - ctor_flags); +static int JS_SetConstructor2(JSContext *ctx, + JSValueConst func_obj, + JSValueConst proto, + int proto_flags, int ctor_flags) +{ + if (JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype, + JS_DupValue(ctx, proto), proto_flags) < 0) + return -1; + if (JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor, + JS_DupValue(ctx, func_obj), + ctor_flags) < 0) + return -1; set_cycle_flag(ctx, func_obj); set_cycle_flag(ctx, proto); + return 0; } -void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, - JSValueConst proto) +/* return 0 if OK, -1 if exception */ +int JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, + JSValueConst proto) { - JS_SetConstructor2(ctx, func_obj, proto, - 0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + return JS_SetConstructor2(ctx, func_obj, proto, + 0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } -static void JS_NewGlobalCConstructor2(JSContext *ctx, - JSValue func_obj, - const char *name, - JSValueConst proto) -{ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, name, - JS_DupValue(ctx, func_obj), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_SetConstructor(ctx, func_obj, proto); - JS_FreeValue(ctx, func_obj); -} +#define JS_NEW_CTOR_NO_GLOBAL (1 << 0) /* don't create a global binding */ +#define JS_NEW_CTOR_PROTO_CLASS (1 << 1) /* the prototype class is 'class_id' instead of JS_CLASS_OBJECT */ +#define JS_NEW_CTOR_PROTO_EXIST (1 << 2) /* the prototype is already defined */ +#define JS_NEW_CTOR_READONLY (1 << 3) /* read-only constructor field */ -static JSValueConst JS_NewGlobalCConstructor(JSContext *ctx, const char *name, - JSCFunction *func, int length, - JSValueConst proto) +/* Return the constructor and. Define it as a global variable unless + JS_NEW_CTOR_NO_GLOBAL is set. The new class inherit from + parent_ctor if it is not JS_UNDEFINED. if class_id is != -1, + class_proto[class_id] is set. */ +static JSValue JS_NewCConstructor(JSContext *ctx, int class_id, const char *name, + JSCFunction *func, int length, JSCFunctionEnum cproto, int magic, + JSValueConst parent_ctor, + const JSCFunctionListEntry *ctor_fields, int n_ctor_fields, + const JSCFunctionListEntry *proto_fields, int n_proto_fields, + int flags) { - JSValue func_obj; - func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor_or_func, 0); - JS_NewGlobalCConstructor2(ctx, func_obj, name, proto); - return func_obj; -} + JSValue ctor = JS_UNDEFINED, proto, parent_proto; + int proto_class_id, proto_flags, ctor_flags; -static JSValueConst JS_NewGlobalCConstructorOnly(JSContext *ctx, const char *name, - JSCFunction *func, int length, - JSValueConst proto) -{ - JSValue func_obj; - func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor, 0); - JS_NewGlobalCConstructor2(ctx, func_obj, name, proto); - return func_obj; + proto_flags = 0; + if (flags & JS_NEW_CTOR_READONLY) { + ctor_flags = JS_PROP_CONFIGURABLE; + } else { + ctor_flags = JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE; + } + + if (JS_IsUndefined(parent_ctor)) { + parent_proto = JS_DupValue(ctx, ctx->class_proto[JS_CLASS_OBJECT]); + parent_ctor = ctx->function_proto; + } else { + parent_proto = JS_GetProperty(ctx, parent_ctor, JS_ATOM_prototype); + if (JS_IsException(parent_proto)) + return JS_EXCEPTION; + } + + if (flags & JS_NEW_CTOR_PROTO_EXIST) { + proto = JS_DupValue(ctx, ctx->class_proto[class_id]); + } else { + if (flags & JS_NEW_CTOR_PROTO_CLASS) + proto_class_id = class_id; + else + proto_class_id = JS_CLASS_OBJECT; + /* one additional field: constructor */ + proto = JS_NewObjectProtoClassAlloc(ctx, parent_proto, proto_class_id, + n_proto_fields + 1); + if (JS_IsException(proto)) + goto fail; + if (class_id >= 0) + ctx->class_proto[class_id] = JS_DupValue(ctx, proto); + } + if (JS_SetPropertyFunctionList(ctx, proto, proto_fields, n_proto_fields)) + goto fail; + + /* additional fields: name, length, prototype */ + ctor = JS_NewCFunction3(ctx, func, name, length, cproto, magic, parent_ctor, + n_ctor_fields + 3); + if (JS_IsException(ctor)) + goto fail; + if (JS_SetPropertyFunctionList(ctx, ctor, ctor_fields, n_ctor_fields)) + goto fail; + if (!(flags & JS_NEW_CTOR_NO_GLOBAL)) { + if (JS_DefinePropertyValueStr(ctx, ctx->global_obj, name, + JS_DupValue(ctx, ctor), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0) + goto fail; + } + JS_SetConstructor2(ctx, ctor, proto, proto_flags, ctor_flags); + + JS_FreeValue(ctx, proto); + JS_FreeValue(ctx, parent_proto); + return ctor; + fail: + JS_FreeValue(ctx, proto); + JS_FreeValue(ctx, parent_proto); + JS_FreeValue(ctx, ctor); + return JS_EXCEPTION; } static JSValue js_global_eval(JSContext *ctx, JSValueConst this_val, @@ -39506,107 +39627,12 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -#if 0 -/* Note: corresponds to ECMA spec: CreateDataPropertyOrThrow() */ -static JSValue js_object___setOwnProperty(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int ret; - ret = JS_DefinePropertyValueValue(ctx, argv[0], JS_DupValue(ctx, argv[1]), - JS_DupValue(ctx, argv[2]), - JS_PROP_C_W_E | JS_PROP_THROW); - if (ret < 0) - return JS_EXCEPTION; - else - return JS_NewBool(ctx, ret); -} - -static JSValue js_object___toObject(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_ToObject(ctx, argv[0]); -} - -static JSValue js_object___toPrimitive(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int hint = HINT_NONE; - - if (JS_VALUE_GET_TAG(argv[1]) == JS_TAG_INT) - hint = JS_VALUE_GET_INT(argv[1]); - - return JS_ToPrimitive(ctx, argv[0], hint); -} -#endif - -/* return an empty string if not an object */ -static JSValue js_object___getClass(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSAtom atom; - JSObject *p; - uint32_t tag; - int class_id; - - tag = JS_VALUE_GET_NORM_TAG(argv[0]); - if (tag == JS_TAG_OBJECT) { - p = JS_VALUE_GET_OBJ(argv[0]); - class_id = p->class_id; - if (class_id == JS_CLASS_PROXY && JS_IsFunction(ctx, argv[0])) - class_id = JS_CLASS_BYTECODE_FUNCTION; - atom = ctx->rt->class_array[class_id].class_name; - } else { - atom = JS_ATOM_empty_string; - } - return JS_AtomToString(ctx, atom); -} - static JSValue js_object_is(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { return JS_NewBool(ctx, js_same_value(ctx, argv[0], argv[1])); } -#if 0 -static JSValue js_object___getObjectData(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_GetObjectData(ctx, argv[0]); -} - -static JSValue js_object___setObjectData(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - if (JS_SetObjectData(ctx, argv[0], JS_DupValue(ctx, argv[1]))) - return JS_EXCEPTION; - return JS_DupValue(ctx, argv[1]); -} - -static JSValue js_object___toPropertyKey(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_ToPropertyKey(ctx, argv[0]); -} - -static JSValue js_object___isObject(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_NewBool(ctx, JS_IsObject(argv[0])); -} - -static JSValue js_object___isSameValueZero(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_NewBool(ctx, js_same_value_zero(ctx, argv[0], argv[1])); -} - -static JSValue js_object___isConstructor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_NewBool(ctx, JS_IsConstructor(ctx, argv[0])); -} -#endif - static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj, JSValueConst defaultConstructor) { @@ -39636,14 +39662,6 @@ static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj, return species; } -#if 0 -static JSValue js_object___speciesConstructor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_SpeciesConstructor(ctx, argv[0], argv[1]); -} -#endif - static JSValue js_object_get___proto__(JSContext *ctx, JSValueConst this_val) { JSValue val, ret; @@ -39807,17 +39825,6 @@ static const JSCFunctionListEntry js_object_funcs[] = { JS_CFUNC_MAGIC_DEF("freeze", 1, js_object_seal, 1 ), JS_CFUNC_MAGIC_DEF("isSealed", 1, js_object_isSealed, 0 ), JS_CFUNC_MAGIC_DEF("isFrozen", 1, js_object_isSealed, 1 ), - JS_CFUNC_DEF("__getClass", 1, js_object___getClass ), - //JS_CFUNC_DEF("__isObject", 1, js_object___isObject ), - //JS_CFUNC_DEF("__isConstructor", 1, js_object___isConstructor ), - //JS_CFUNC_DEF("__toObject", 1, js_object___toObject ), - //JS_CFUNC_DEF("__setOwnProperty", 3, js_object___setOwnProperty ), - //JS_CFUNC_DEF("__toPrimitive", 2, js_object___toPrimitive ), - //JS_CFUNC_DEF("__toPropertyKey", 1, js_object___toPropertyKey ), - //JS_CFUNC_DEF("__speciesConstructor", 2, js_object___speciesConstructor ), - //JS_CFUNC_DEF("__isSameValueZero", 2, js_object___isSameValueZero ), - //JS_CFUNC_DEF("__getObjectData", 1, js_object___getObjectData ), - //JS_CFUNC_DEF("__setObjectData", 2, js_object___setObjectData ), JS_CFUNC_DEF("fromEntries", 1, js_object_fromEntries ), JS_CFUNC_DEF("hasOwn", 2, js_object_hasOwn ), }; @@ -40334,6 +40341,25 @@ static const JSCFunctionListEntry js_error_proto_funcs[] = { JS_PROP_STRING_DEF("message", "", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), }; +/* 2 entries for each native error class */ +/* Note: we use an atom to avoid the autoinit definition which does + not work in get_prop_string() */ +static const JSCFunctionListEntry js_native_error_proto_funcs[] = { +#define DEF(name) \ + JS_PROP_ATOM_DEF("name", name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),\ + JS_PROP_STRING_DEF("message", "", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), + + DEF(JS_ATOM_EvalError) + DEF(JS_ATOM_RangeError) + DEF(JS_ATOM_ReferenceError) + DEF(JS_ATOM_SyntaxError) + DEF(JS_ATOM_TypeError) + DEF(JS_ATOM_URIError) + DEF(JS_ATOM_InternalError) + DEF(JS_ATOM_AggregateError) +#undef DEF +}; + static JSValue js_error_isError(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -43213,6 +43239,25 @@ static const JSCFunctionListEntry js_iterator_helper_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Iterator Helper", JS_PROP_CONFIGURABLE ), }; +static const JSCFunctionListEntry js_array_unscopables_funcs[] = { + JS_PROP_BOOL_DEF("at", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("copyWithin", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("entries", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("fill", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("find", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("findIndex", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("findLast", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("findLastIndex", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("flat", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("flatMap", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("includes", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("keys", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("toReversed", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("toSorted", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("toSpliced", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("values", TRUE, JS_PROP_C_W_E), +}; + static const JSCFunctionListEntry js_array_proto_funcs[] = { JS_CFUNC_DEF("at", 1, js_array_at ), JS_CFUNC_DEF("with", 2, js_array_with ), @@ -43253,6 +43298,7 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = { JS_ALIAS_DEF("[Symbol.iterator]", "values" ), JS_CFUNC_MAGIC_DEF("keys", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY ), JS_CFUNC_MAGIC_DEF("entries", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY_AND_VALUE ), + JS_OBJECT_DEF("[Symbol.unscopables]", js_array_unscopables_funcs, countof(js_array_unscopables_funcs), JS_PROP_CONFIGURABLE ), }; static const JSCFunctionListEntry js_array_iterator_proto_funcs[] = { @@ -45396,10 +45442,10 @@ static const JSCFunctionListEntry js_string_proto_normalize[] = { JS_CFUNC_DEF("localeCompare", 1, js_string_localeCompare ), }; -void JS_AddIntrinsicStringNormalize(JSContext *ctx) +int JS_AddIntrinsicStringNormalize(JSContext *ctx) { - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_normalize, - countof(js_string_proto_normalize)); + return JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_normalize, + countof(js_string_proto_normalize)); } /* Math */ @@ -47626,25 +47672,29 @@ void JS_AddIntrinsicRegExpCompiler(JSContext *ctx) ctx->compile_regexp = js_compile_regexp; } -void JS_AddIntrinsicRegExp(JSContext *ctx) +int JS_AddIntrinsicRegExp(JSContext *ctx) { - JSValueConst obj; + JSValue obj; JS_AddIntrinsicRegExpCompiler(ctx); - ctx->class_proto[JS_CLASS_REGEXP] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP], js_regexp_proto_funcs, - countof(js_regexp_proto_funcs)); - obj = JS_NewGlobalCConstructor(ctx, "RegExp", js_regexp_constructor, 2, - ctx->class_proto[JS_CLASS_REGEXP]); - ctx->regexp_ctor = JS_DupValue(ctx, obj); - JS_SetPropertyFunctionList(ctx, obj, js_regexp_funcs, countof(js_regexp_funcs)); - + obj = JS_NewCConstructor(ctx, JS_CLASS_REGEXP, "RegExp", + js_regexp_constructor, 2, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_regexp_funcs, countof(js_regexp_funcs), + js_regexp_proto_funcs, countof(js_regexp_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + ctx->regexp_ctor = obj; + ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR] = - JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR], - js_regexp_string_iterator_proto_funcs, - countof(js_regexp_string_iterator_proto_funcs)); + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_regexp_string_iterator_proto_funcs, + countof(js_regexp_string_iterator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR])) + return -1; + return 0; } /* JSON */ @@ -48395,10 +48445,10 @@ static const JSCFunctionListEntry js_json_obj[] = { JS_OBJECT_DEF("JSON", js_json_funcs, countof(js_json_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), }; -void JS_AddIntrinsicJSON(JSContext *ctx) +int JS_AddIntrinsicJSON(JSContext *ctx) { /* add JSON as autoinit object */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_json_obj, countof(js_json_obj)); + return JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_json_obj, countof(js_json_obj)); } /* Reflect */ @@ -49525,25 +49575,36 @@ static const JSClassShortDef js_proxy_class_def[] = { { JS_ATOM_Object, js_proxy_finalizer, js_proxy_mark }, /* JS_CLASS_PROXY */ }; -void JS_AddIntrinsicProxy(JSContext *ctx) +int JS_AddIntrinsicProxy(JSContext *ctx) { JSRuntime *rt = ctx->rt; JSValue obj1; if (!JS_IsRegisteredClass(rt, JS_CLASS_PROXY)) { - init_class_range(rt, js_proxy_class_def, JS_CLASS_PROXY, - countof(js_proxy_class_def)); + if (init_class_range(rt, js_proxy_class_def, JS_CLASS_PROXY, + countof(js_proxy_class_def))) + return -1; rt->class_array[JS_CLASS_PROXY].exotic = &js_proxy_exotic_methods; rt->class_array[JS_CLASS_PROXY].call = js_proxy_call; } - obj1 = JS_NewCFunction2(ctx, js_proxy_constructor, "Proxy", 2, - JS_CFUNC_constructor, 0); + /* additional fields: name, length */ + obj1 = JS_NewCFunction3(ctx, js_proxy_constructor, "Proxy", 2, + JS_CFUNC_constructor, 0, + ctx->function_proto, countof(js_proxy_funcs) + 2); + if (JS_IsException(obj1)) + return -1; JS_SetConstructorBit(ctx, obj1, TRUE); - JS_SetPropertyFunctionList(ctx, obj1, js_proxy_funcs, - countof(js_proxy_funcs)); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "Proxy", - obj1, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + if (JS_SetPropertyFunctionList(ctx, obj1, js_proxy_funcs, + countof(js_proxy_funcs))) + goto fail; + if (JS_DefinePropertyValueStr(ctx, ctx->global_obj, "Proxy", + obj1, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0) + goto fail; + return 0; + fail: + JS_FreeValue(ctx, obj1); + return -1; } /* Symbol */ @@ -49655,6 +49716,19 @@ static JSValue js_symbol_keyFor(JSContext *ctx, JSValueConst this_val, static const JSCFunctionListEntry js_symbol_funcs[] = { JS_CFUNC_DEF("for", 1, js_symbol_for ), JS_CFUNC_DEF("keyFor", 1, js_symbol_keyFor ), + JS_PROP_ATOM_DEF("toPrimitive", JS_ATOM_Symbol_toPrimitive, 0), + JS_PROP_ATOM_DEF("iterator", JS_ATOM_Symbol_iterator, 0), + JS_PROP_ATOM_DEF("match", JS_ATOM_Symbol_match, 0), + JS_PROP_ATOM_DEF("matchAll", JS_ATOM_Symbol_matchAll, 0), + JS_PROP_ATOM_DEF("replace", JS_ATOM_Symbol_replace, 0), + JS_PROP_ATOM_DEF("search", JS_ATOM_Symbol_search, 0), + JS_PROP_ATOM_DEF("split", JS_ATOM_Symbol_split, 0), + JS_PROP_ATOM_DEF("toStringTag", JS_ATOM_Symbol_toStringTag, 0), + JS_PROP_ATOM_DEF("isConcatSpreadable", JS_ATOM_Symbol_isConcatSpreadable, 0), + JS_PROP_ATOM_DEF("hasInstance", JS_ATOM_Symbol_hasInstance, 0), + JS_PROP_ATOM_DEF("species", JS_ATOM_Symbol_species, 0), + JS_PROP_ATOM_DEF("unscopables", JS_ATOM_Symbol_unscopables, 0), + JS_PROP_ATOM_DEF("asyncIterator", JS_ATOM_Symbol_asyncIterator, 0), }; /* Set/Map/WeakSet/WeakMap */ @@ -51254,35 +51328,37 @@ static const uint8_t js_map_proto_funcs_count[6] = { countof(js_set_iterator_proto_funcs), }; -void JS_AddIntrinsicMapSet(JSContext *ctx) +int JS_AddIntrinsicMapSet(JSContext *ctx) { int i; JSValue obj1; char buf[ATOM_GET_STR_BUF_SIZE]; for(i = 0; i < 4; i++) { + JSCFunctionType ft; const char *name = JS_AtomGetStr(ctx, buf, sizeof(buf), JS_ATOM_Map + i); - ctx->class_proto[JS_CLASS_MAP + i] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_MAP + i], - js_map_proto_funcs_ptr[i], - js_map_proto_funcs_count[i]); - obj1 = JS_NewCFunctionMagic(ctx, js_map_constructor, name, 0, - JS_CFUNC_constructor_magic, i); - if (i < 2) { - JS_SetPropertyFunctionList(ctx, obj1, js_map_funcs, - countof(js_map_funcs)); - } - JS_NewGlobalCConstructor2(ctx, obj1, name, ctx->class_proto[JS_CLASS_MAP + i]); + ft.constructor_magic = js_map_constructor; + obj1 = JS_NewCConstructor(ctx, JS_CLASS_MAP + i, name, + ft.generic, 0, JS_CFUNC_constructor_magic, i, + JS_UNDEFINED, + js_map_funcs, i < 2 ? countof(js_map_funcs) : 0, + js_map_proto_funcs_ptr[i], js_map_proto_funcs_count[i], + 0); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); } for(i = 0; i < 2; i++) { ctx->class_proto[JS_CLASS_MAP_ITERATOR + i] = - JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_MAP_ITERATOR + i], - js_map_proto_funcs_ptr[i + 4], - js_map_proto_funcs_count[i + 4]); + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_map_proto_funcs_ptr[i + 4], + js_map_proto_funcs_count[i + 4]); + if (JS_IsException(ctx->class_proto[JS_CLASS_MAP_ITERATOR + i])) + return -1; } + return 0; } /* Generator */ @@ -52601,15 +52677,16 @@ static JSClassShortDef const js_async_class_def[] = { { JS_ATOM_AsyncGenerator, js_async_generator_finalizer, js_async_generator_mark }, /* JS_CLASS_ASYNC_GENERATOR */ }; -void JS_AddIntrinsicPromise(JSContext *ctx) +int JS_AddIntrinsicPromise(JSContext *ctx) { JSRuntime *rt = ctx->rt; JSValue obj1; JSCFunctionType ft; if (!JS_IsRegisteredClass(rt, JS_CLASS_PROMISE)) { - init_class_range(rt, js_async_class_def, JS_CLASS_PROMISE, - countof(js_async_class_def)); + if (init_class_range(rt, js_async_class_def, JS_CLASS_PROMISE, + countof(js_async_class_def))) + return -1; rt->class_array[JS_CLASS_PROMISE_RESOLVE_FUNCTION].call = js_promise_resolve_function_call; rt->class_array[JS_CLASS_PROMISE_REJECT_FUNCTION].call = js_promise_resolve_function_call; rt->class_array[JS_CLASS_ASYNC_FUNCTION].call = js_async_function_call; @@ -52619,74 +52696,67 @@ void JS_AddIntrinsicPromise(JSContext *ctx) } /* Promise */ - ctx->class_proto[JS_CLASS_PROMISE] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_PROMISE], - js_promise_proto_funcs, - countof(js_promise_proto_funcs)); - obj1 = JS_NewCFunction2(ctx, js_promise_constructor, "Promise", 1, - JS_CFUNC_constructor, 0); - ctx->promise_ctor = JS_DupValue(ctx, obj1); - JS_SetPropertyFunctionList(ctx, obj1, - js_promise_funcs, - countof(js_promise_funcs)); - JS_NewGlobalCConstructor2(ctx, obj1, "Promise", - ctx->class_proto[JS_CLASS_PROMISE]); - + obj1 = JS_NewCConstructor(ctx, JS_CLASS_PROMISE, "Promise", + js_promise_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + js_promise_funcs, countof(js_promise_funcs), + js_promise_proto_funcs, countof(js_promise_proto_funcs), + 0); + if (JS_IsException(obj1)) + return -1; + ctx->promise_ctor = obj1; + /* AsyncFunction */ - ctx->class_proto[JS_CLASS_ASYNC_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto); ft.generic_magic = js_function_constructor; - obj1 = JS_NewCFunction3(ctx, ft.generic, - "AsyncFunction", 1, - JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC, - ctx->function_ctor); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_ASYNC_FUNCTION], - js_async_function_proto_funcs, - countof(js_async_function_proto_funcs)); - JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_ASYNC_FUNCTION], - 0, JS_PROP_CONFIGURABLE); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_ASYNC_FUNCTION, "AsyncFunction", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC, + ctx->function_ctor, + NULL, 0, + js_async_function_proto_funcs, countof(js_async_function_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL | JS_NEW_CTOR_READONLY); + if (JS_IsException(obj1)) + return -1; JS_FreeValue(ctx, obj1); - + /* AsyncIteratorPrototype */ - ctx->async_iterator_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->async_iterator_proto, - js_async_iterator_proto_funcs, - countof(js_async_iterator_proto_funcs)); + ctx->async_iterator_proto = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_OBJECT], + js_async_iterator_proto_funcs, + countof(js_async_iterator_proto_funcs)); + if (JS_IsException(ctx->async_iterator_proto)) + return -1; /* AsyncFromSyncIteratorPrototype */ ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR] = - JS_NewObjectProto(ctx, ctx->async_iterator_proto); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR], - js_async_from_sync_iterator_proto_funcs, - countof(js_async_from_sync_iterator_proto_funcs)); - + JS_NewObjectProtoList(ctx, ctx->async_iterator_proto, + js_async_from_sync_iterator_proto_funcs, + countof(js_async_from_sync_iterator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR])) + return -1; + /* AsyncGeneratorPrototype */ ctx->class_proto[JS_CLASS_ASYNC_GENERATOR] = - JS_NewObjectProto(ctx, ctx->async_iterator_proto); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR], - js_async_generator_proto_funcs, - countof(js_async_generator_proto_funcs)); + JS_NewObjectProtoList(ctx, ctx->async_iterator_proto, + js_async_generator_proto_funcs, + countof(js_async_generator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ASYNC_GENERATOR])) + return -1; /* AsyncGeneratorFunction */ - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION] = - JS_NewObjectProto(ctx, ctx->function_proto); ft.generic_magic = js_function_constructor; - obj1 = JS_NewCFunction3(ctx, ft.generic, - "AsyncGeneratorFunction", 1, - JS_CFUNC_constructor_or_func_magic, - JS_FUNC_ASYNC_GENERATOR, - ctx->function_ctor); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], - js_async_generator_function_proto_funcs, - countof(js_async_generator_function_proto_funcs)); - JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR], - JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE); - JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], - 0, JS_PROP_CONFIGURABLE); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_ASYNC_GENERATOR_FUNCTION, "AsyncGeneratorFunction", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC_GENERATOR, + ctx->function_ctor, + NULL, 0, + js_async_generator_function_proto_funcs, countof(js_async_generator_function_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL | JS_NEW_CTOR_READONLY); + if (JS_IsException(obj1)) + return -1; JS_FreeValue(ctx, obj1); + + return JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], + ctx->class_proto[JS_CLASS_ASYNC_GENERATOR], + JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE); } /* URI handling */ @@ -52981,6 +53051,7 @@ static const JSCFunctionListEntry js_global_funcs[] = { JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ), JS_PROP_UNDEFINED_DEF("undefined", 0 ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "global", JS_PROP_CONFIGURABLE ), + JS_CFUNC_DEF("eval", 1, js_global_eval ), }; /* Date */ @@ -53179,6 +53250,21 @@ static double set_date_fields(double fields[minimum_length(7)], int is_local) { return time_clip(tv); } +static double set_date_fields_checked(double fields[minimum_length(7)], int is_local) +{ + int i; + double a; + for(i = 0; i < 7; i++) { + a = fields[i]; + if (!isfinite(a)) + return NAN; + fields[i] = trunc(a); + if (i == 0 && fields[0] >= 0 && fields[0] < 100) + fields[0] += 1900; + } + return set_date_fields(fields, is_local); +} + static JSValue get_date_field(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { @@ -53364,7 +53450,7 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target, // Date(y, mon, d, h, m, s, ms) JSValue rv; int i, n; - double a, val; + double val; if (JS_IsUndefined(new_target)) { /* invoked as function */ @@ -53402,15 +53488,10 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target, if (n > 7) n = 7; for(i = 0; i < n; i++) { - if (JS_ToFloat64(ctx, &a, argv[i])) + if (JS_ToFloat64(ctx, &fields[i], argv[i])) return JS_EXCEPTION; - if (!isfinite(a)) - break; - fields[i] = trunc(a); - if (i == 0 && fields[0] >= 0 && fields[0] < 100) - fields[0] += 1900; } - val = (i == n) ? set_date_fields(fields, 1) : NAN; + val = set_date_fields_checked(fields, 1); } has_val: #if 0 @@ -53440,7 +53521,6 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val, // UTC(y, mon, d, h, m, s, ms) double fields[] = { 0, 0, 1, 0, 0, 0, 0 }; int i, n; - double a; n = argc; if (n == 0) @@ -53448,15 +53528,10 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val, if (n > 7) n = 7; for(i = 0; i < n; i++) { - if (JS_ToFloat64(ctx, &a, argv[i])) + if (JS_ToFloat64(ctx, &fields[i], argv[i])) return JS_EXCEPTION; - if (!isfinite(a)) - return JS_NAN; - fields[i] = trunc(a); - if (i == 0 && fields[0] >= 0 && fields[0] < 100) - fields[0] += 1900; } - return JS_NewFloat64(ctx, set_date_fields(fields, 0)); + return JS_NewFloat64(ctx, set_date_fields_checked(fields, 0)); } /* Date string parsing */ @@ -53778,11 +53853,11 @@ static BOOL js_date_parse_otherstring(const uint8_t *sp, *is_local = FALSE; } } else { - if (p - p_start > 2) { + if (p - p_start > 2 && !has_year) { fields[0] = val; has_year = TRUE; } else - if (val < 1 || val > 31) { + if ((val < 1 || val > 31) && !has_year) { fields[0] = val + (val < 100) * 1900 + (val < 50) * 100; has_year = TRUE; } else { @@ -54121,24 +54196,29 @@ JSValue JS_NewDate(JSContext *ctx, double epoch_ms) return obj; } -void JS_AddIntrinsicDate(JSContext *ctx) +int JS_AddIntrinsicDate(JSContext *ctx) { - JSValueConst obj; + JSValue obj; /* Date */ - ctx->class_proto[JS_CLASS_DATE] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_DATE], js_date_proto_funcs, - countof(js_date_proto_funcs)); - obj = JS_NewGlobalCConstructor(ctx, "Date", js_date_constructor, 7, - ctx->class_proto[JS_CLASS_DATE]); - JS_SetPropertyFunctionList(ctx, obj, js_date_funcs, countof(js_date_funcs)); + obj = JS_NewCConstructor(ctx, JS_CLASS_DATE, "Date", + js_date_constructor, 7, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_date_funcs, countof(js_date_funcs), + js_date_proto_funcs, countof(js_date_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); + return 0; } /* eval */ -void JS_AddIntrinsicEval(JSContext *ctx) +int JS_AddIntrinsicEval(JSContext *ctx) { ctx->eval_internal = __JS_EvalInternal; + return 0; } /* BigInt */ @@ -54322,333 +54402,330 @@ static const JSCFunctionListEntry js_bigint_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "BigInt", JS_PROP_CONFIGURABLE ), }; -static void JS_AddIntrinsicBigInt(JSContext *ctx) +static int JS_AddIntrinsicBigInt(JSContext *ctx) { - JSValueConst obj1; + JSValue obj1; - ctx->class_proto[JS_CLASS_BIG_INT] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_INT], - js_bigint_proto_funcs, - countof(js_bigint_proto_funcs)); - obj1 = JS_NewGlobalCConstructor(ctx, "BigInt", js_bigint_constructor, 1, - ctx->class_proto[JS_CLASS_BIG_INT]); - JS_SetPropertyFunctionList(ctx, obj1, js_bigint_funcs, - countof(js_bigint_funcs)); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_BIG_INT, "BigInt", + js_bigint_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_bigint_funcs, countof(js_bigint_funcs), + js_bigint_proto_funcs, countof(js_bigint_proto_funcs), + 0); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + return 0; } -static const char * const native_error_name[JS_NATIVE_ERROR_COUNT] = { - "EvalError", "RangeError", "ReferenceError", - "SyntaxError", "TypeError", "URIError", - "InternalError", "AggregateError", -}; - /* Minimum amount of objects to be able to compile code and display - error messages. No JSAtom should be allocated by this function. */ -static void JS_AddIntrinsicBasicObjects(JSContext *ctx) + error messages. */ +static int JS_AddIntrinsicBasicObjects(JSContext *ctx) { - JSValue proto; + JSValue obj; + JSCFunctionType ft; int i; - ctx->class_proto[JS_CLASS_OBJECT] = JS_NewObjectProto(ctx, JS_NULL); + /* warning: ordering is tricky */ + ctx->class_proto[JS_CLASS_OBJECT] = + JS_NewObjectProtoClassAlloc(ctx, JS_NULL, JS_CLASS_OBJECT, + countof(js_object_proto_funcs) + 1); + if (JS_IsException(ctx->class_proto[JS_CLASS_OBJECT])) + return -1; JS_SetImmutablePrototype(ctx, ctx->class_proto[JS_CLASS_OBJECT]); - + + /* 2 more properties: caller and arguments */ ctx->function_proto = JS_NewCFunction3(ctx, js_function_proto, "", 0, JS_CFUNC_generic, 0, - ctx->class_proto[JS_CLASS_OBJECT]); + ctx->class_proto[JS_CLASS_OBJECT], + countof(js_function_proto_funcs) + 3 + 2); + if (JS_IsException(ctx->function_proto)) + return -1; ctx->class_proto[JS_CLASS_BYTECODE_FUNCTION] = JS_DupValue(ctx, ctx->function_proto); - ctx->class_proto[JS_CLASS_ERROR] = JS_NewObject(ctx); -#if 0 - /* these are auto-initialized from js_error_proto_funcs, - but delaying might be a problem */ - JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ERROR], JS_ATOM_name, - JS_AtomToString(ctx, JS_ATOM_Error), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ERROR], JS_ATOM_message, - JS_AtomToString(ctx, JS_ATOM_empty_string), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); -#endif - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ERROR], - js_error_proto_funcs, - countof(js_error_proto_funcs)); + + ctx->global_obj = JS_NewObjectProtoClassAlloc(ctx, ctx->class_proto[JS_CLASS_OBJECT], + JS_CLASS_OBJECT, 64); + if (JS_IsException(ctx->global_obj)) + return -1; + ctx->global_var_obj = JS_NewObjectProtoClassAlloc(ctx, JS_NULL, + JS_CLASS_OBJECT, 16); + if (JS_IsException(ctx->global_var_obj)) + return -1; + + /* Error */ + ft.generic_magic = js_error_constructor; + obj = JS_NewCConstructor(ctx, JS_CLASS_ERROR, "Error", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, -1, + JS_UNDEFINED, + js_error_funcs, countof(js_error_funcs), + js_error_proto_funcs, countof(js_error_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { - proto = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ERROR]); - JS_DefinePropertyValue(ctx, proto, JS_ATOM_name, - JS_NewAtomString(ctx, native_error_name[i]), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValue(ctx, proto, JS_ATOM_message, - JS_AtomToString(ctx, JS_ATOM_empty_string), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - ctx->native_error_proto[i] = proto; + JSValue func_obj; + const JSCFunctionListEntry *funcs; + int n_args; + char buf[ATOM_GET_STR_BUF_SIZE]; + const char *name = JS_AtomGetStr(ctx, buf, sizeof(buf), + JS_ATOM_EvalError + i); + n_args = 1 + (i == JS_AGGREGATE_ERROR); + funcs = js_native_error_proto_funcs + 2 * i; + func_obj = JS_NewCConstructor(ctx, -1, name, + ft.generic, n_args, JS_CFUNC_constructor_or_func_magic, i, + obj, + NULL, 0, + funcs, 2, + 0); + if (JS_IsException(func_obj)) { + JS_FreeValue(ctx, obj); + return -1; + } + ctx->native_error_proto[i] = JS_GetProperty(ctx, func_obj, JS_ATOM_prototype); + JS_FreeValue(ctx, func_obj); + if (JS_IsException(ctx->native_error_proto[i])) { + JS_FreeValue(ctx, obj); + return -1; + } } + JS_FreeValue(ctx, obj); - /* the array prototype is an array */ - ctx->class_proto[JS_CLASS_ARRAY] = - JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_ARRAY); + /* Array */ + obj = JS_NewCConstructor(ctx, JS_CLASS_ARRAY, "Array", + js_array_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_array_funcs, countof(js_array_funcs), + js_array_proto_funcs, countof(js_array_proto_funcs), + JS_NEW_CTOR_PROTO_CLASS); + if (JS_IsException(obj)) + return -1; + ctx->array_ctor = obj; ctx->array_shape = js_new_shape2(ctx, get_proto_obj(ctx->class_proto[JS_CLASS_ARRAY]), JS_PROP_INITIAL_HASH_SIZE, 1); - add_shape_property(ctx, &ctx->array_shape, NULL, - JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH); + if (!ctx->array_shape) + return -1; + if (add_shape_property(ctx, &ctx->array_shape, NULL, + JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH)) + return -1; ctx->std_array_prototype = TRUE; - /* XXX: could test it on first context creation to ensure that no - new atoms are created in JS_AddIntrinsicBasicObjects(). It is - necessary to avoid useless renumbering of atoms after - JS_EvalBinary() if it is done just after - JS_AddIntrinsicBasicObjects(). */ - // assert(ctx->rt->atom_count == JS_ATOM_END); + return 0; } -void JS_AddIntrinsicBaseObjects(JSContext *ctx) +int JS_AddIntrinsicBaseObjects(JSContext *ctx) { - int i; - JSValueConst obj, number_obj; - JSValue obj1; + JSValue obj1, obj2; JSCFunctionType ft; ctx->throw_type_error = JS_NewCFunction(ctx, js_throw_type_error, NULL, 0); - + if (JS_IsException(ctx->throw_type_error)) + return -1; /* add caller and arguments properties to throw a TypeError */ - JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_caller, JS_UNDEFINED, - ctx->throw_type_error, ctx->throw_type_error, - JS_PROP_HAS_GET | JS_PROP_HAS_SET | - JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE); - JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_arguments, JS_UNDEFINED, - ctx->throw_type_error, ctx->throw_type_error, - JS_PROP_HAS_GET | JS_PROP_HAS_SET | - JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE); + if (JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_caller, JS_UNDEFINED, + ctx->throw_type_error, ctx->throw_type_error, + JS_PROP_HAS_GET | JS_PROP_HAS_SET | + JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE) < 0) + return -1; + if (JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_arguments, JS_UNDEFINED, + ctx->throw_type_error, ctx->throw_type_error, + JS_PROP_HAS_GET | JS_PROP_HAS_SET | + JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE) < 0) + return -1; JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, (JSValueConst *)&ctx->throw_type_error, 1)); - ctx->global_obj = JS_NewObject(ctx); - ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL); - /* Object */ - obj = JS_NewGlobalCConstructor(ctx, "Object", js_object_constructor, 1, - ctx->class_proto[JS_CLASS_OBJECT]); - JS_SetPropertyFunctionList(ctx, obj, js_object_funcs, countof(js_object_funcs)); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_OBJECT], - js_object_proto_funcs, countof(js_object_proto_funcs)); - + obj1 = JS_NewCConstructor(ctx, JS_CLASS_OBJECT, "Object", + js_object_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_object_funcs, countof(js_object_funcs), + js_object_proto_funcs, countof(js_object_proto_funcs), + JS_NEW_CTOR_PROTO_EXIST); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + /* Function */ - JS_SetPropertyFunctionList(ctx, ctx->function_proto, js_function_proto_funcs, countof(js_function_proto_funcs)); - ctx->function_ctor = JS_NewCFunctionMagic(ctx, js_function_constructor, - "Function", 1, JS_CFUNC_constructor_or_func_magic, - JS_FUNC_NORMAL); - JS_NewGlobalCConstructor2(ctx, JS_DupValue(ctx, ctx->function_ctor), "Function", - ctx->function_proto); - - /* Error */ - obj1 = JS_NewCFunctionMagic(ctx, js_error_constructor, - "Error", 1, JS_CFUNC_constructor_or_func_magic, -1); - JS_NewGlobalCConstructor2(ctx, obj1, - "Error", ctx->class_proto[JS_CLASS_ERROR]); - JS_SetPropertyFunctionList(ctx, obj1, js_error_funcs, countof(js_error_funcs)); - - /* Used to squelch a -Wcast-function-type warning. */ - ft.generic_magic = js_error_constructor; - for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { - JSValue func_obj; - int n_args; - n_args = 1 + (i == JS_AGGREGATE_ERROR); - func_obj = JS_NewCFunction3(ctx, ft.generic, - native_error_name[i], n_args, - JS_CFUNC_constructor_or_func_magic, i, obj1); - JS_NewGlobalCConstructor2(ctx, func_obj, native_error_name[i], - ctx->native_error_proto[i]); - } + ft.generic_magic = js_function_constructor; + obj1 = JS_NewCConstructor(ctx, JS_CLASS_BYTECODE_FUNCTION, "Function", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_NORMAL, + JS_UNDEFINED, + NULL, 0, + js_function_proto_funcs, countof(js_function_proto_funcs), + JS_NEW_CTOR_PROTO_EXIST); + if (JS_IsException(obj1)) + return -1; + ctx->function_ctor = obj1; /* Iterator */ - ctx->class_proto[JS_CLASS_ITERATOR] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], - js_iterator_proto_funcs, - countof(js_iterator_proto_funcs)); - obj = JS_NewGlobalCConstructor(ctx, "Iterator", js_iterator_constructor, 0, - ctx->class_proto[JS_CLASS_ITERATOR]); + obj2 = JS_NewCConstructor(ctx, JS_CLASS_ITERATOR, "Iterator", + js_iterator_constructor, 0, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_iterator_funcs, countof(js_iterator_funcs), + js_iterator_proto_funcs, countof(js_iterator_proto_funcs), + 0); + if (JS_IsException(obj2)) + return -1; // quirk: Iterator.prototype.constructor is an accessor property // TODO(bnoordhuis) mildly inefficient because JS_NewGlobalCConstructor // first creates a .constructor value property that we then replace with // an accessor obj1 = JS_NewCFunctionData(ctx, js_iterator_constructor_getset, - 0, 0, 1, (JSValueConst *)&obj); - JS_DefineProperty(ctx, ctx->class_proto[JS_CLASS_ITERATOR], - JS_ATOM_constructor, JS_UNDEFINED, - obj1, obj1, - JS_PROP_HAS_GET | JS_PROP_HAS_SET | JS_PROP_CONFIGURABLE); + 0, 0, 1, (JSValueConst *)&obj2); + if (JS_IsException(obj1)) { + JS_FreeValue(ctx, obj2); + return -1; + } + if (JS_DefineProperty(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + JS_ATOM_constructor, JS_UNDEFINED, + obj1, obj1, + JS_PROP_HAS_GET | JS_PROP_HAS_SET | JS_PROP_CONFIGURABLE) < 0) { + JS_FreeValue(ctx, obj2); + JS_FreeValue(ctx, obj1); + return -1; + } JS_FreeValue(ctx, obj1); + ctx->iterator_ctor = obj2; - ctx->iterator_ctor = JS_DupValue(ctx, obj); - JS_SetPropertyFunctionList(ctx, obj, - js_iterator_funcs, - countof(js_iterator_funcs)); - - ctx->class_proto[JS_CLASS_ITERATOR_HELPER] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_HELPER], - js_iterator_helper_proto_funcs, - countof(js_iterator_helper_proto_funcs)); - - ctx->class_proto[JS_CLASS_ITERATOR_WRAP] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_WRAP], - js_iterator_wrap_proto_funcs, - countof(js_iterator_wrap_proto_funcs)); - - /* Array */ - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY], - js_array_proto_funcs, - countof(js_array_proto_funcs)); - - obj = JS_NewGlobalCConstructor(ctx, "Array", js_array_constructor, 1, - ctx->class_proto[JS_CLASS_ARRAY]); - ctx->array_ctor = JS_DupValue(ctx, obj); - JS_SetPropertyFunctionList(ctx, obj, js_array_funcs, - countof(js_array_funcs)); - - /* XXX: create auto_initializer */ - { - /* initialize Array.prototype[Symbol.unscopables] */ - static const char unscopables[] = - "at" "\0" - "copyWithin" "\0" - "entries" "\0" - "fill" "\0" - "find" "\0" - "findIndex" "\0" - "findLast" "\0" - "findLastIndex" "\0" - "flat" "\0" - "flatMap" "\0" - "includes" "\0" - "keys" "\0" - "toReversed" "\0" - "toSorted" "\0" - "toSpliced" "\0" - "values" "\0"; - const char *p = unscopables; - obj1 = JS_NewObjectProto(ctx, JS_NULL); - for(p = unscopables; *p; p += strlen(p) + 1) { - JS_DefinePropertyValueStr(ctx, obj1, p, JS_TRUE, JS_PROP_C_W_E); - } - JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ARRAY], - JS_ATOM_Symbol_unscopables, obj1, - JS_PROP_CONFIGURABLE); - } + ctx->class_proto[JS_CLASS_ITERATOR_HELPER] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_iterator_helper_proto_funcs, + countof(js_iterator_helper_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ITERATOR_HELPER])) + return -1; + + ctx->class_proto[JS_CLASS_ITERATOR_WRAP] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_iterator_wrap_proto_funcs, + countof(js_iterator_wrap_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ITERATOR_WRAP])) + return -1; /* needed to initialize arguments[Symbol.iterator] */ ctx->array_proto_values = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_values); + if (JS_IsException(ctx->array_proto_values)) + return -1; ctx->class_proto[JS_CLASS_ARRAY_ITERATOR] = - JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY_ITERATOR], - js_array_iterator_proto_funcs, - countof(js_array_iterator_proto_funcs)); + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_array_iterator_proto_funcs, + countof(js_array_iterator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ARRAY_ITERATOR])) + return -1; /* parseFloat and parseInteger must be defined before Number because of the Number.parseFloat and Number.parseInteger aliases */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs, - countof(js_global_funcs)); + if (JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs, + countof(js_global_funcs))) + return -1; /* Number */ - ctx->class_proto[JS_CLASS_NUMBER] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_NUMBER); - JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_NUMBER], JS_NewInt32(ctx, 0)); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_NUMBER], - js_number_proto_funcs, - countof(js_number_proto_funcs)); - number_obj = JS_NewGlobalCConstructor(ctx, "Number", js_number_constructor, 1, - ctx->class_proto[JS_CLASS_NUMBER]); - JS_SetPropertyFunctionList(ctx, number_obj, js_number_funcs, countof(js_number_funcs)); - + obj1 = JS_NewCConstructor(ctx, JS_CLASS_NUMBER, "Number", + js_number_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_number_funcs, countof(js_number_funcs), + js_number_proto_funcs, countof(js_number_proto_funcs), + JS_NEW_CTOR_PROTO_CLASS); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + if (JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_NUMBER], JS_NewInt32(ctx, 0))) + return -1; + /* Boolean */ - ctx->class_proto[JS_CLASS_BOOLEAN] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_BOOLEAN); - JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], JS_NewBool(ctx, FALSE)); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], js_boolean_proto_funcs, - countof(js_boolean_proto_funcs)); - JS_NewGlobalCConstructor(ctx, "Boolean", js_boolean_constructor, 1, - ctx->class_proto[JS_CLASS_BOOLEAN]); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_BOOLEAN, "Boolean", + js_boolean_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + NULL, 0, + js_boolean_proto_funcs, countof(js_boolean_proto_funcs), + JS_NEW_CTOR_PROTO_CLASS); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + if (JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], JS_NewBool(ctx, FALSE))) + return -1; /* String */ - ctx->class_proto[JS_CLASS_STRING] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_STRING); - JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_STRING], JS_AtomToString(ctx, JS_ATOM_empty_string)); - obj = JS_NewGlobalCConstructor(ctx, "String", js_string_constructor, 1, - ctx->class_proto[JS_CLASS_STRING]); - JS_SetPropertyFunctionList(ctx, obj, js_string_funcs, - countof(js_string_funcs)); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_funcs, - countof(js_string_proto_funcs)); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_STRING, "String", + js_string_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_string_funcs, countof(js_string_funcs), + js_string_proto_funcs, countof(js_string_proto_funcs), + JS_NEW_CTOR_PROTO_CLASS); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + if (JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_STRING], JS_AtomToString(ctx, JS_ATOM_empty_string))) + return -1; ctx->class_proto[JS_CLASS_STRING_ITERATOR] = - JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING_ITERATOR], - js_string_iterator_proto_funcs, - countof(js_string_iterator_proto_funcs)); + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_string_iterator_proto_funcs, + countof(js_string_iterator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_STRING_ITERATOR])) + return -1; /* Math: create as autoinit object */ js_random_init(ctx); - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_math_obj, countof(js_math_obj)); + if (JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_math_obj, countof(js_math_obj))) + return -1; /* ES6 Reflect: create as autoinit object */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_reflect_obj, countof(js_reflect_obj)); + if (JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_reflect_obj, countof(js_reflect_obj))) + return -1; /* ES6 Symbol */ - ctx->class_proto[JS_CLASS_SYMBOL] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_SYMBOL], js_symbol_proto_funcs, - countof(js_symbol_proto_funcs)); - obj = JS_NewGlobalCConstructor(ctx, "Symbol", js_symbol_constructor, 0, - ctx->class_proto[JS_CLASS_SYMBOL]); - JS_SetPropertyFunctionList(ctx, obj, js_symbol_funcs, - countof(js_symbol_funcs)); - for(i = JS_ATOM_Symbol_toPrimitive; i < JS_ATOM_END; i++) { - char buf[ATOM_GET_STR_BUF_SIZE]; - const char *str, *p; - str = JS_AtomGetStr(ctx, buf, sizeof(buf), i); - /* skip "Symbol." */ - p = strchr(str, '.'); - if (p) - str = p + 1; - JS_DefinePropertyValueStr(ctx, obj, str, JS_AtomToValue(ctx, i), 0); - } - + obj1 = JS_NewCConstructor(ctx, JS_CLASS_SYMBOL, "Symbol", + js_symbol_constructor, 0, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_symbol_funcs, countof(js_symbol_funcs), + js_symbol_proto_funcs, countof(js_symbol_proto_funcs), + 0); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + /* ES6 Generator */ ctx->class_proto[JS_CLASS_GENERATOR] = - JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_GENERATOR], - js_generator_proto_funcs, - countof(js_generator_proto_funcs)); + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_generator_proto_funcs, + countof(js_generator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_GENERATOR])) + return -1; - ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto); ft.generic_magic = js_function_constructor; - obj1 = JS_NewCFunction3(ctx, ft.generic, - "GeneratorFunction", 1, - JS_CFUNC_constructor_or_func_magic, JS_FUNC_GENERATOR, - ctx->function_ctor); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], - js_generator_function_proto_funcs, - countof(js_generator_function_proto_funcs)); - JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], - ctx->class_proto[JS_CLASS_GENERATOR], - JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE); - JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], - 0, JS_PROP_CONFIGURABLE); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_GENERATOR_FUNCTION, "GeneratorFunction", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_GENERATOR, + ctx->function_ctor, + NULL, 0, + js_generator_function_proto_funcs, + countof(js_generator_function_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL | JS_NEW_CTOR_READONLY); + if (JS_IsException(obj1)) + return -1; JS_FreeValue(ctx, obj1); - + if (JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], + ctx->class_proto[JS_CLASS_GENERATOR], + JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE)) + return -1; + /* global properties */ - ctx->eval_obj = JS_NewCFunction(ctx, js_global_eval, "eval", 1); - JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_eval, - JS_DupValue(ctx, ctx->eval_obj), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - - JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis, - JS_DupValue(ctx, ctx->global_obj), - JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); + ctx->eval_obj = JS_GetProperty(ctx, ctx->global_obj, JS_ATOM_eval); + if (JS_IsException(ctx->eval_obj)) + return -1; + + if (JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis, + JS_DupValue(ctx, ctx->global_obj), + JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE) < 0) + return -1; /* BigInt */ - JS_AddIntrinsicBigInt(ctx); + if (JS_AddIntrinsicBigInt(ctx)) + return -1; + return 0; } /* Typed Arrays */ @@ -56871,9 +56948,6 @@ static const JSCFunctionListEntry js_typed_array_base_funcs[] = { JS_CFUNC_DEF("from", 1, js_typed_array_from ), JS_CFUNC_DEF("of", 0, js_typed_array_of ), JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), - //JS_CFUNC_DEF("__getLength", 2, js_typed_array___getLength ), - //JS_CFUNC_DEF("__create", 2, js_typed_array___create ), - //JS_CFUNC_DEF("__speciesCreate", 2, js_typed_array___speciesCreate ), }; static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = { @@ -56916,6 +56990,13 @@ static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = { //JS_ALIAS_BASE_DEF("toString", "toString", 2 /* Array.prototype. */), @@@ }; +static const JSCFunctionListEntry js_typed_array_funcs[] = { + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 1, 0), + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 2, 0), + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 4, 0), + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 8, 0), +}; + static JSValue js_typed_array_base_constructor(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -58092,100 +58173,106 @@ static const JSCFunctionListEntry js_atomics_obj[] = { JS_OBJECT_DEF("Atomics", js_atomics_funcs, countof(js_atomics_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), }; -void JS_AddIntrinsicAtomics(JSContext *ctx) +static int JS_AddIntrinsicAtomics(JSContext *ctx) { /* add Atomics as autoinit object */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_atomics_obj, countof(js_atomics_obj)); + return JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_atomics_obj, countof(js_atomics_obj)); } #endif /* CONFIG_ATOMICS */ -void JS_AddIntrinsicTypedArrays(JSContext *ctx) +int JS_AddIntrinsicTypedArrays(JSContext *ctx) { - JSValue typed_array_base_proto, typed_array_base_func; - JSValueConst array_buffer_func, shared_array_buffer_func; - int i; + JSValue typed_array_base_func, typed_array_base_proto, obj; + int i, ret; - ctx->class_proto[JS_CLASS_ARRAY_BUFFER] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY_BUFFER], - js_array_buffer_proto_funcs, - countof(js_array_buffer_proto_funcs)); - - array_buffer_func = JS_NewGlobalCConstructorOnly(ctx, "ArrayBuffer", - js_array_buffer_constructor, 1, - ctx->class_proto[JS_CLASS_ARRAY_BUFFER]); - JS_SetPropertyFunctionList(ctx, array_buffer_func, - js_array_buffer_funcs, - countof(js_array_buffer_funcs)); - - ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER], - js_shared_array_buffer_proto_funcs, - countof(js_shared_array_buffer_proto_funcs)); - - shared_array_buffer_func = JS_NewGlobalCConstructorOnly(ctx, "SharedArrayBuffer", - js_shared_array_buffer_constructor, 1, - ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER]); - JS_SetPropertyFunctionList(ctx, shared_array_buffer_func, - js_shared_array_buffer_funcs, - countof(js_shared_array_buffer_funcs)); - - typed_array_base_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, typed_array_base_proto, - js_typed_array_base_proto_funcs, - countof(js_typed_array_base_proto_funcs)); + obj = JS_NewCConstructor(ctx, JS_CLASS_ARRAY_BUFFER, "ArrayBuffer", + js_array_buffer_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + js_array_buffer_funcs, countof(js_array_buffer_funcs), + js_array_buffer_proto_funcs, countof(js_array_buffer_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); - /* TypedArray.prototype.toString must be the same object as Array.prototype.toString */ - JSValue obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_toString); - /* XXX: should use alias method in JSCFunctionListEntry */ //@@@ - JS_DefinePropertyValue(ctx, typed_array_base_proto, JS_ATOM_toString, obj, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + obj = JS_NewCConstructor(ctx, JS_CLASS_SHARED_ARRAY_BUFFER, "SharedArrayBuffer", + js_shared_array_buffer_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + js_shared_array_buffer_funcs, countof(js_shared_array_buffer_funcs), + js_shared_array_buffer_proto_funcs, countof(js_shared_array_buffer_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); - typed_array_base_func = JS_NewCFunction2(ctx, js_typed_array_base_constructor, - "TypedArray", 0, JS_CFUNC_constructor_or_func, 0); - JS_SetPropertyFunctionList(ctx, typed_array_base_func, - js_typed_array_base_funcs, - countof(js_typed_array_base_funcs)); - JS_SetConstructor(ctx, typed_array_base_func, typed_array_base_proto); + typed_array_base_func = + JS_NewCConstructor(ctx, -1, "TypedArray", + js_typed_array_base_constructor, 0, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_typed_array_base_funcs, countof(js_typed_array_base_funcs), + js_typed_array_base_proto_funcs, countof(js_typed_array_base_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL); + if (JS_IsException(typed_array_base_func)) + return -1; + + /* TypedArray.prototype.toString must be the same object as Array.prototype.toString */ + obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_toString); + if (JS_IsException(obj)) + goto fail; + /* XXX: should use alias method in JSCFunctionListEntry */ //@@@ + typed_array_base_proto = JS_GetProperty(ctx, typed_array_base_func, JS_ATOM_prototype); + if (JS_IsException(typed_array_base_proto)) + goto fail; + ret = JS_DefinePropertyValue(ctx, typed_array_base_proto, JS_ATOM_toString, obj, + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_FreeValue(ctx, typed_array_base_proto); + if (ret < 0) + goto fail; + /* Used to squelch a -Wcast-function-type warning. */ JSCFunctionType ft = { .generic_magic = js_typed_array_constructor }; for(i = JS_CLASS_UINT8C_ARRAY; i < JS_CLASS_UINT8C_ARRAY + JS_TYPED_ARRAY_COUNT; i++) { - JSValue func_obj; char buf[ATOM_GET_STR_BUF_SIZE]; const char *name; - - ctx->class_proto[i] = JS_NewObjectProto(ctx, typed_array_base_proto); - JS_DefinePropertyValueStr(ctx, ctx->class_proto[i], - "BYTES_PER_ELEMENT", - JS_NewInt32(ctx, 1 << typed_array_size_log2(i)), - 0); + const JSCFunctionListEntry *bpe; + name = JS_AtomGetStr(ctx, buf, sizeof(buf), JS_ATOM_Uint8ClampedArray + i - JS_CLASS_UINT8C_ARRAY); - func_obj = JS_NewCFunction3(ctx, ft.generic, - name, 3, JS_CFUNC_constructor_magic, i, - typed_array_base_func); - JS_NewGlobalCConstructor2(ctx, func_obj, name, ctx->class_proto[i]); - JS_DefinePropertyValueStr(ctx, func_obj, - "BYTES_PER_ELEMENT", - JS_NewInt32(ctx, 1 << typed_array_size_log2(i)), - 0); + bpe = js_typed_array_funcs + typed_array_size_log2(i); + obj = JS_NewCConstructor(ctx, i, name, + ft.generic, 3, JS_CFUNC_constructor_magic, i, + typed_array_base_func, + bpe, 1, + bpe, 1, + 0); + if (JS_IsException(obj)) { + fail: + JS_FreeValue(ctx, typed_array_base_func); + return -1; + } + JS_FreeValue(ctx, obj); } - JS_FreeValue(ctx, typed_array_base_proto); JS_FreeValue(ctx, typed_array_base_func); /* DataView */ - ctx->class_proto[JS_CLASS_DATAVIEW] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_DATAVIEW], - js_dataview_proto_funcs, - countof(js_dataview_proto_funcs)); - JS_NewGlobalCConstructorOnly(ctx, "DataView", - js_dataview_constructor, 1, - ctx->class_proto[JS_CLASS_DATAVIEW]); + obj = JS_NewCConstructor(ctx, JS_CLASS_DATAVIEW, "DataView", + js_dataview_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + NULL, 0, + js_dataview_proto_funcs, countof(js_dataview_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); + /* Atomics */ #ifdef CONFIG_ATOMICS - JS_AddIntrinsicAtomics(ctx); + if (JS_AddIntrinsicAtomics(ctx)) + return -1; #endif + return 0; } /* WeakRef */ @@ -58440,29 +58527,42 @@ static const JSClassShortDef js_finrec_class_def[] = { { JS_ATOM_FinalizationRegistry, js_finrec_finalizer, js_finrec_mark }, /* JS_CLASS_FINALIZATION_REGISTRY */ }; -void JS_AddIntrinsicWeakRef(JSContext *ctx) +int JS_AddIntrinsicWeakRef(JSContext *ctx) { JSRuntime *rt = ctx->rt; - + JSValue obj; + /* WeakRef */ if (!JS_IsRegisteredClass(rt, JS_CLASS_WEAK_REF)) { - init_class_range(rt, js_weakref_class_def, JS_CLASS_WEAK_REF, - countof(js_weakref_class_def)); + if (init_class_range(rt, js_weakref_class_def, JS_CLASS_WEAK_REF, + countof(js_weakref_class_def))) + return -1; } - ctx->class_proto[JS_CLASS_WEAK_REF] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_WEAK_REF], - js_weakref_proto_funcs, - countof(js_weakref_proto_funcs)); - JS_NewGlobalCConstructor(ctx, "WeakRef", js_weakref_constructor, 1, ctx->class_proto[JS_CLASS_WEAK_REF]); + obj = JS_NewCConstructor(ctx, JS_CLASS_WEAK_REF, "WeakRef", + js_weakref_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + NULL, 0, + js_weakref_proto_funcs, countof(js_weakref_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); /* FinalizationRegistry */ if (!JS_IsRegisteredClass(rt, JS_CLASS_FINALIZATION_REGISTRY)) { - init_class_range(rt, js_finrec_class_def, JS_CLASS_FINALIZATION_REGISTRY, - countof(js_finrec_class_def)); - } - ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY], - js_finrec_proto_funcs, - countof(js_finrec_proto_funcs)); - JS_NewGlobalCConstructor(ctx, "FinalizationRegistry", js_finrec_constructor, 1, ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY]); + if (init_class_range(rt, js_finrec_class_def, JS_CLASS_FINALIZATION_REGISTRY, + countof(js_finrec_class_def))) + return -1; + } + + obj = JS_NewCConstructor(ctx, JS_CLASS_FINALIZATION_REGISTRY, "FinalizationRegistry", + js_finrec_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + NULL, 0, + js_finrec_proto_funcs, countof(js_finrec_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); + return 0; } diff --git a/src/couch_quickjs/quickjs/quickjs.h b/src/couch_quickjs/quickjs/quickjs.h index cad3652fb..92cc000d0 100644 --- a/src/couch_quickjs/quickjs/quickjs.h +++ b/src/couch_quickjs/quickjs/quickjs.h @@ -394,18 +394,18 @@ JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id); /* the following functions are used to select the intrinsic object to save memory */ JSContext *JS_NewContextRaw(JSRuntime *rt); -void JS_AddIntrinsicBaseObjects(JSContext *ctx); -void JS_AddIntrinsicDate(JSContext *ctx); -void JS_AddIntrinsicEval(JSContext *ctx); -void JS_AddIntrinsicStringNormalize(JSContext *ctx); +int JS_AddIntrinsicBaseObjects(JSContext *ctx); +int JS_AddIntrinsicDate(JSContext *ctx); +int JS_AddIntrinsicEval(JSContext *ctx); +int JS_AddIntrinsicStringNormalize(JSContext *ctx); void JS_AddIntrinsicRegExpCompiler(JSContext *ctx); -void JS_AddIntrinsicRegExp(JSContext *ctx); -void JS_AddIntrinsicJSON(JSContext *ctx); -void JS_AddIntrinsicProxy(JSContext *ctx); -void JS_AddIntrinsicMapSet(JSContext *ctx); -void JS_AddIntrinsicTypedArrays(JSContext *ctx); -void JS_AddIntrinsicPromise(JSContext *ctx); -void JS_AddIntrinsicWeakRef(JSContext *ctx); +int JS_AddIntrinsicRegExp(JSContext *ctx); +int JS_AddIntrinsicJSON(JSContext *ctx); +int JS_AddIntrinsicProxy(JSContext *ctx); +int JS_AddIntrinsicMapSet(JSContext *ctx); +int JS_AddIntrinsicTypedArrays(JSContext *ctx); +int JS_AddIntrinsicPromise(JSContext *ctx); +int JS_AddIntrinsicWeakRef(JSContext *ctx); JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); @@ -1052,8 +1052,8 @@ static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *fun JSCFunctionType ft = { .generic_magic = func }; return JS_NewCFunction2(ctx, ft.generic, name, length, cproto, magic); } -void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, - JSValueConst proto); +int JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, + JSValueConst proto); /* C property definition */ @@ -1097,6 +1097,8 @@ typedef struct JSCFunctionListEntry { #define JS_DEF_PROP_UNDEFINED 7 #define JS_DEF_OBJECT 8 #define JS_DEF_ALIAS 9 +#define JS_DEF_PROP_ATOM 10 +#define JS_DEF_PROP_BOOL 11 /* Note: c++ does not like nested designators */ #define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } @@ -1110,6 +1112,8 @@ typedef struct JSCFunctionListEntry { #define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, .u = { .i64 = val } } #define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, .u = { .f64 = val } } #define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, .u = { .i32 = 0 } } +#define JS_PROP_ATOM_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_ATOM, 0, .u = { .i32 = val } } +#define JS_PROP_BOOL_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_BOOL, 0, .u = { .i32 = val } } #define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, .u = { .prop_list = { tab, len } } } #define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, -1 } } } #define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, base } } } diff --git a/src/couch_quickjs/quickjs/test262_errors.txt b/src/couch_quickjs/quickjs/test262_errors.txt index 56ac50680..31bb92940 100644 --- a/src/couch_quickjs/quickjs/test262_errors.txt +++ b/src/couch_quickjs/quickjs/test262_errors.txt @@ -6,14 +6,9 @@ test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in- test262/test/annexB/language/expressions/assignmenttargettype/callexpression.js:33: SyntaxError: invalid assignment left-hand side test262/test/annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js:20: SyntaxError: invalid assignment left-hand side test262/test/language/identifier-resolution/assign-to-global-undefined.js:20: strict mode: expected error +test262/test/language/module-code/top-level-await/rejection-order.js:20: TypeError: $DONE() not called test262/test/language/statements/expression/S12.4_A1.js:15: unexpected error type: Test262: This statement should not be evaluated. test262/test/language/statements/expression/S12.4_A1.js:15: strict mode: unexpected error type: Test262: This statement should not be evaluated. -test262/test/staging/sm/Date/UTC-convert-all-arguments.js:13: Test262Error: index 1: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true -test262/test/staging/sm/Date/UTC-convert-all-arguments.js:13: strict mode: Test262Error: index 1: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true -test262/test/staging/sm/Date/constructor-convert-all-arguments.js:13: Test262Error: index undefined: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true -test262/test/staging/sm/Date/constructor-convert-all-arguments.js:13: strict mode: Test262Error: index undefined: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true -test262/test/staging/sm/Date/two-digit-years.js:26: Test262Error: Expected SameValue(«915177600000», «NaN») to be true -test262/test/staging/sm/Date/two-digit-years.js:26: strict mode: Test262Error: Expected SameValue(«915177600000», «NaN») to be true test262/test/staging/sm/Function/arguments-parameter-shadowing.js:14: Test262Error: Expected SameValue(«true», «false») to be true test262/test/staging/sm/Function/constructor-binding.js:11: Test262Error: Expected SameValue(«"function"», «"undefined"») to be true test262/test/staging/sm/Function/constructor-binding.js:11: strict mode: Test262Error: Expected SameValue(«"function"», «"undefined"») to be true @@ -22,14 +17,6 @@ test262/test/staging/sm/Function/function-name-for.js:13: Test262Error: Expected test262/test/staging/sm/Function/implicit-this-in-parameter-expression.js:12: Test262Error: Expected SameValue(«[object Object]», «undefined») to be true test262/test/staging/sm/Function/invalid-parameter-list.js:13: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all test262/test/staging/sm/Function/invalid-parameter-list.js:13: strict mode: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all -test262/test/staging/sm/Math/acosh-exact.js:15: ReferenceError: 'ONE_MINUS_EPSILON' is not defined -test262/test/staging/sm/Math/acosh-exact.js:15: strict mode: ReferenceError: 'ONE_MINUS_EPSILON' is not defined -test262/test/staging/sm/Math/atanh-exact.js:15: ReferenceError: 'ONE_PLUS_EPSILON' is not defined -test262/test/staging/sm/Math/atanh-exact.js:15: strict mode: ReferenceError: 'ONE_PLUS_EPSILON' is not defined -test262/test/staging/sm/Math/log1p-exact.js:18: ReferenceError: 'ONE_PLUS_EPSILON' is not defined -test262/test/staging/sm/Math/log1p-exact.js:18: strict mode: ReferenceError: 'ONE_PLUS_EPSILON' is not defined -test262/test/staging/sm/Math/trunc.js:29: ReferenceError: 'ONE_MINUS_EPSILON' is not defined -test262/test/staging/sm/Math/trunc.js:29: strict mode: ReferenceError: 'ONE_MINUS_EPSILON' is not defined test262/test/staging/sm/RegExp/constructor-ordering-2.js:12: Test262Error: Expected SameValue(«false», «true») to be true test262/test/staging/sm/RegExp/constructor-ordering-2.js:12: strict mode: Test262Error: Expected SameValue(«false», «true») to be true test262/test/staging/sm/RegExp/regress-613820-1.js:12: Test262Error: Actual [aaa, aa, a] and expected [aa, a, a] should have the same contents.
