diff --git a/qop.c b/qop.c index 788a559e..a1e6fe9a 100644 --- a/qop.c +++ b/qop.c @@ -450,10 +450,10 @@ static const JSCFunctionListEntry js_qop_writer_funcs[] = { static const JSCFunctionListEntry js_qop_funcs[] = { MIST_FUNC_DEF(qop, open, 1), MIST_FUNC_DEF(qop, write, 1), - JS_PROP_INT32_DEF("FLAG_NONE", QOP_FLAG_NONE, JS_PROP_ENUMERABLE), - JS_PROP_INT32_DEF("FLAG_COMPRESSED_ZSTD", QOP_FLAG_COMPRESSED_ZSTD, JS_PROP_ENUMERABLE), - JS_PROP_INT32_DEF("FLAG_COMPRESSED_DEFLATE", QOP_FLAG_COMPRESSED_DEFLATE, JS_PROP_ENUMERABLE), - JS_PROP_INT32_DEF("FLAG_ENCRYPTED", QOP_FLAG_ENCRYPTED, JS_PROP_ENUMERABLE), + JS_PROP_INT32_DEF("FLAG_NONE", QOP_FLAG_NONE, 0), + JS_PROP_INT32_DEF("FLAG_COMPRESSED_ZSTD", QOP_FLAG_COMPRESSED_ZSTD, 0), + JS_PROP_INT32_DEF("FLAG_COMPRESSED_DEFLATE", QOP_FLAG_COMPRESSED_DEFLATE, 0), + JS_PROP_INT32_DEF("FLAG_ENCRYPTED", QOP_FLAG_ENCRYPTED, 0), }; JSValue js_qop_use(JSContext *js) { diff --git a/source/cell.h b/source/cell.h index d580b540..4d8328f4 100644 --- a/source/cell.h +++ b/source/cell.h @@ -36,7 +36,7 @@ void cell_trace_sethook(cell_hook); // Macros to help with creating scripts #define MIST_CFUNC_DEF(name, length, func1, props) { name, props, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } -#define MIST_FUNC_DEF(TYPE, FN, LEN) MIST_CFUNC_DEF(#FN, LEN, js_##TYPE##_##FN, JS_PROP_C_W_E) +#define MIST_FUNC_DEF(TYPE, FN, LEN) MIST_CFUNC_DEF(#FN, LEN, js_##TYPE##_##FN, 0) #define PROTO_FUNC_DEF(TYPE, FN, LEN) MIST_CFUNC_DEF(#FN, LEN, js_##TYPE##_##FN, 0) #define JS_SETSIG JSContext *js, JSValue self, JSValue val diff --git a/source/quickjs-opcode.h b/source/quickjs-opcode.h index b63fb423..38550b8d 100644 --- a/source/quickjs-opcode.h +++ b/source/quickjs-opcode.h @@ -75,7 +75,6 @@ DEF( push_false, 1, 0, 1, none) DEF( push_true, 1, 0, 1, none) DEF( object, 1, 0, 1, none) DEF( special_object, 2, 0, 1, u8) /* only used at the start of a function */ -DEF( rest, 3, 0, 1, u16) /* only used at the start of a function */ DEF( drop, 1, 1, 0, none) /* a -> */ DEF( nip, 1, 2, 1, none) /* a b -> b */ diff --git a/source/quickjs.c b/source/quickjs.c index 8df8682c..bd9ca30b 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -74,7 +74,6 @@ #define CONFIG_STACK_CHECK #endif - /* dump object free */ //#define DUMP_FREE //#define DUMP_CLOSURE @@ -516,6 +515,7 @@ typedef struct JSArray { uint32_t len; /* current length */ uint32_t cap; /* allocated capacity */ JSValue *values; /* array of values */ + int stone; } JSArray; typedef struct JSRecord { @@ -718,10 +718,6 @@ struct JSShape { /* true if the shape is inserted in the shape hash table. If not, JSShape.hash is not valid */ uint8_t is_hashed; - /* If true, the shape may have small array index properties 'n' with 0 - <= n <= 2^31-1. If false, the shape is guaranteed not to have - small array index properties */ - uint8_t has_small_array_index; uint32_t hash; /* current hash value */ uint32_t prop_hash_mask; int prop_size; /* allocated properties */ @@ -739,7 +735,7 @@ struct JSObject { int __gc_ref_count; /* corresponds to header.ref_count */ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ - uint8_t extensible : 1; + uint8_t stone : 1; uint8_t free_mark : 1; /* only used when freeing objects with cycles */ uint8_t has_immutable_prototype : 1; /* cannot modify the prototype */ uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */ @@ -768,6 +764,14 @@ struct JSObject { } u; }; +/* Property descriptor (simplified - no getter/setter support) */ +typedef struct JSPropertyDescriptor { + int flags; + JSValue value; + JSValue getter; + JSValue setter; +} JSPropertyDescriptor; + enum { __JS_ATOM_NULL = JS_ATOM_NULL, #define DEF(name, str) JS_ATOM_ ## name, @@ -859,9 +863,8 @@ static void js_bound_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_regexp_finalizer(JSRuntime *rt, JSValue val); -#define HINT_STRING 0 -#define HINT_NONE 2 -#define HINT_FORCE_ORDINARY (1 << 4) // don't try Symbol.toPrimitive +int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val); + static JSValue JS_ToStringFree(JSContext *ctx, JSValue val); static int JS_ToBoolFree(JSContext *ctx, JSValue val); static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val); @@ -899,10 +902,6 @@ static JSValue js_cell_array_find(JSContext *ctx, JSValueConst this_val, static JSProperty *add_property(JSContext *ctx, JSObject *p, JSAtom prop, int prop_flags); JSValue JS_ThrowOutOfMemory(JSContext *ctx); -static int JS_CreateProperty(JSContext *ctx, JSObject *p, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, - int flags); static int js_string_memcmp(const JSString *p1, int pos1, const JSString *p2, int pos2, int len); static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx, @@ -915,11 +914,9 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref); static int js_string_compare(JSContext *ctx, const JSString *p1, const JSString *p2); static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val); -static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, - JSValue prop, JSValue val, int flags); +static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, JSValue prop, JSValue val); static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val); -static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, - JSObject *p, JSAtom prop); +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 void js_free_shape(JSRuntime *rt, JSShape *sh); @@ -1951,9 +1948,11 @@ void JS_UpdateStackTop(JSRuntime *rt) /* JSAtom support */ -#define JS_ATOM_TAG_INT (1U << 31) -#define JS_ATOM_MAX_INT (JS_ATOM_TAG_INT - 1) #define JS_ATOM_MAX ((1U << 30) - 1) +#define JS_ATOM_MAX_INT UINT32_MAX /* Max valid numeric property index */ + +static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type); +static JSString *js_alloc_string(JSContext *ctx, int max_len, int is_wide_char); /* return the max count from the hash size */ #define JS_ATOM_COUNT_RESIZE(n) ((n) * 2) @@ -1967,21 +1966,6 @@ static inline BOOL __JS_AtomIsConst(JSAtom v) #endif } -static inline BOOL __JS_AtomIsTaggedInt(JSAtom v) -{ - return (v & JS_ATOM_TAG_INT) != 0; -} - -static inline JSAtom __JS_AtomFromUInt32(uint32_t v) -{ - return v | JS_ATOM_TAG_INT; -} - -static inline uint32_t __JS_AtomToUInt32(JSAtom atom) -{ - return atom & ~JS_ATOM_TAG_INT; -} - static inline int is_num(int c) { return c >= '0' && c <= '9'; @@ -2022,6 +2006,22 @@ static inline BOOL is_num_string(uint32_t *pval, const JSString *p) } } +/* Create atom from int64 - always uses string representation */ +static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n) +{ + char buf[24]; + snprintf(buf, sizeof(buf), "%" PRId64, n); + return JS_NewAtom(ctx, buf); +} + +/* Create atom from uint32 - always uses string representation */ +JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n) +{ + char buf[12]; + snprintf(buf, sizeof(buf), "%u", n); + return JS_NewAtom(ctx, buf); +} + /* XXX: could use faster version ? */ static inline uint32_t hash_string8(const uint8_t *str, size_t len, uint32_t h) { @@ -2212,14 +2212,9 @@ JSAtom JS_DupAtom(JSContext *ctx, JSAtom v) static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v) { - JSRuntime *rt; - JSAtomStruct *p; - - rt = ctx->rt; - if (__JS_AtomIsTaggedInt(v)) - return JS_ATOM_KIND_STRING; - p = rt->atom_array[v]; - switch(p->atom_type) { + JSRuntime *rt = ctx->rt; + JSAtomStruct *p = rt->atom_array[v]; + switch (p->atom_type) { case JS_ATOM_TYPE_STRING: return JS_ATOM_KIND_STRING; case JS_ATOM_TYPE_SYMBOL: @@ -2557,8 +2552,6 @@ static JSValue js_get_object_key_symbol(JSContext *ctx, JSObject *key_obj) /* Check if a symbol atom is an object-key symbol (has obj_key payload) */ static BOOL js_atom_is_object_key_symbol(JSRuntime *rt, JSAtom atom) { - if (__JS_AtomIsTaggedInt(atom)) - return FALSE; if (atom >= (JSAtom)rt->atom_size) return FALSE; JSAtomStruct *ap = rt->atom_array[atom]; @@ -2572,14 +2565,7 @@ static BOOL js_atom_is_object_key_symbol(JSRuntime *rt, JSAtom atom) static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p) { JSRuntime *rt = ctx->rt; - uint32_t n; - if (is_num_string(&n, p)) { - if (n <= JS_ATOM_MAX_INT) { - js_free_string(rt, p); - return __JS_AtomFromUInt32(n); - } - } - /* XXX: should generate an exception */ + /* All atoms are now strings - no more tagged int optimization */ return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING); } @@ -2617,40 +2603,6 @@ JSAtom JS_NewAtom(JSContext *ctx, const char *str) return JS_NewAtomLen(ctx, str, strlen(str)); } -JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n) -{ - if (n <= JS_ATOM_MAX_INT) { - return __JS_AtomFromUInt32(n); - } else { - char buf[11]; - JSValue val; - size_t len; - len = u32toa(buf, n); - val = js_new_string8_len(ctx, buf, len); - if (JS_IsException(val)) - return JS_ATOM_NULL; - return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val), - JS_ATOM_TYPE_STRING); - } -} - -static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n) -{ - if ((uint64_t)n <= JS_ATOM_MAX_INT) { - return __JS_AtomFromUInt32((uint32_t)n); - } else { - char buf[24]; - JSValue val; - size_t len; - len = i64toa(buf, n); - val = js_new_string8_len(ctx, buf, len); - if (JS_IsException(val)) - return JS_ATOM_NULL; - return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val), - JS_ATOM_TYPE_STRING); - } -} - /* 'p' is freed */ static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type) { @@ -2668,45 +2620,41 @@ static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type) static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size, JSAtom atom) { - if (__JS_AtomIsTaggedInt(atom)) { - snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom)); + JSAtomStruct *p; + assert(atom < rt->atom_size); + if (atom == JS_ATOM_NULL) { + snprintf(buf, buf_size, ""); } else { - JSAtomStruct *p; - assert(atom < rt->atom_size); - if (atom == JS_ATOM_NULL) { - snprintf(buf, buf_size, ""); - } else { - int i, c; - char *q; - JSString *str; + int i, c; + char *q; + JSString *str; - q = buf; - p = rt->atom_array[atom]; - assert(!atom_is_free(p)); - str = p; - if (str) { - if (!str->is_wide_char) { - /* special case ASCII strings */ - c = 0; - for(i = 0; i < str->len; i++) { - c |= str->u.str8[i]; - } - if (c < 0x80) - return (const char *)str->u.str8; + q = buf; + p = rt->atom_array[atom]; + assert(!atom_is_free(p)); + str = p; + if (str) { + if (!str->is_wide_char) { + /* special case ASCII strings */ + c = 0; + for (i = 0; i < str->len; i++) { + c |= str->u.str8[i]; } - for(i = 0; i < str->len; i++) { - c = string_get(str, i); - if ((q - buf) >= buf_size - UTF8_CHAR_LEN_MAX) - break; - if (c < 128) { - *q++ = c; - } else { - q += unicode_to_utf8((uint8_t *)q, c); - } + if (c < 0x80) + return (const char *)str->u.str8; + } + for (i = 0; i < str->len; i++) { + c = string_get(str, i); + if ((q - buf) >= buf_size - UTF8_CHAR_LEN_MAX) + break; + if (c < 128) { + *q++ = c; + } else { + q += unicode_to_utf8((uint8_t *)q, c); } } - *q = '\0'; } + *q = '\0'; } return buf; } @@ -2720,26 +2668,21 @@ static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string) { char buf[ATOM_GET_STR_BUF_SIZE]; - if (__JS_AtomIsTaggedInt(atom)) { - size_t len = u32toa(buf, __JS_AtomToUInt32(atom)); - return js_new_string8_len(ctx, buf, len); - } else { - JSRuntime *rt = ctx->rt; - JSAtomStruct *p; - assert(atom < rt->atom_size); - p = rt->atom_array[atom]; - if (p->atom_type == JS_ATOM_TYPE_STRING) { - goto ret_string; - } else if (force_string) { - if (p->len == 0 && p->is_wide_char != 0) { - /* no description string */ - p = rt->atom_array[JS_ATOM_empty_string]; - } - ret_string: - return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); - } else { - return JS_DupValue(ctx, JS_MKPTR(JS_TAG_SYMBOL, p)); + JSRuntime *rt = ctx->rt; + JSAtomStruct *p; + assert(atom < rt->atom_size); + p = rt->atom_array[atom]; + if (p->atom_type == JS_ATOM_TYPE_STRING) { + goto ret_string; + } else if (force_string) { + if (p->len == 0 && p->is_wide_char != 0) { + /* no description string */ + p = rt->atom_array[JS_ATOM_empty_string]; } + ret_string: + return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); + } else { + return JS_DupValue(ctx, JS_MKPTR(JS_TAG_SYMBOL, p)); } } @@ -2753,98 +2696,6 @@ JSValue JS_AtomToString(JSContext *ctx, JSAtom atom) return __JS_AtomToValue(ctx, atom, TRUE); } -/* return TRUE if the atom is an array index (i.e. 0 <= index <= - 2^32-2 and return its value */ -static BOOL JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom) -{ - if (__JS_AtomIsTaggedInt(atom)) { - *pval = __JS_AtomToUInt32(atom); - return TRUE; - } else { - JSRuntime *rt = ctx->rt; - JSAtomStruct *p; - uint32_t val; - - assert(atom < rt->atom_size); - p = rt->atom_array[atom]; - if (p->atom_type == JS_ATOM_TYPE_STRING && - is_num_string(&val, p) && val != -1) { - *pval = val; - return TRUE; - } else { - *pval = 0; - return FALSE; - } - } -} - -/* This test must be fast if atom is not a numeric index (e.g. a - method name). Return JS_NULL if not a numeric - index. JS_EXCEPTION can also be returned. */ -static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom) -{ - JSRuntime *rt = ctx->rt; - JSAtomStruct *p1; - JSString *p; - int c, ret; - JSValue num, str; - - if (__JS_AtomIsTaggedInt(atom)) - return JS_NewInt32(ctx, __JS_AtomToUInt32(atom)); - assert(atom < rt->atom_size); - p1 = rt->atom_array[atom]; - if (p1->atom_type != JS_ATOM_TYPE_STRING) - return JS_NULL; - switch(atom) { - case JS_ATOM_minus_zero: - return __JS_NewFloat64(ctx, -0.0); - case JS_ATOM_Infinity: - return __JS_NewFloat64(ctx, INFINITY); - case JS_ATOM_minus_Infinity: - return __JS_NewFloat64(ctx, -INFINITY); - case JS_ATOM_NaN: - return __JS_NewFloat64(ctx, NAN); - default: - break; - } - p = p1; - if (p->len == 0) - return JS_NULL; - c = string_get(p, 0); - if (!is_num(c) && c != '-') - return JS_NULL; - /* this is ECMA CanonicalNumericIndexString primitive */ - num = JS_ToNumber(ctx, JS_MKPTR(JS_TAG_STRING, p)); - if (JS_IsException(num)) - return num; - str = JS_ToString(ctx, num); - if (JS_IsException(str)) { - JS_FreeValue(ctx, num); - return str; - } - ret = js_string_compare(ctx, p, JS_VALUE_GET_STRING(str)); - /* str removed - arg not owned */ - if (ret == 0) { - return num; - } else { - JS_FreeValue(ctx, num); - return JS_NULL; - } -} - -/* return -1 if exception or TRUE/FALSE */ -int JS_AtomIsNumericIndex(JSContext *ctx, JSAtom atom) -{ - JSValue num; - num = JS_AtomIsNumericIndex1(ctx, atom); - if (likely(JS_IsNull(num))) - return FALSE; - if (JS_IsException(num)) - return -1; - JS_FreeValue(ctx, num); - return TRUE; -} - void JS_FreeAtom(JSContext *ctx, JSAtom v) { if (!__JS_AtomIsConst(v)) @@ -2860,13 +2711,8 @@ void JS_FreeAtomRT(JSRuntime *rt, JSAtom v) /* return TRUE if 'v' is a symbol with a string description */ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v) { - JSRuntime *rt; - JSAtomStruct *p; - - rt = ctx->rt; - if (__JS_AtomIsTaggedInt(v)) - return FALSE; - p = rt->atom_array[v]; + JSRuntime *rt = ctx->rt; + JSAtomStruct *p = rt->atom_array[v]; return (p->atom_type == JS_ATOM_TYPE_SYMBOL && !(p->len == 0 && p->is_wide_char != 0)); } @@ -4296,7 +4142,6 @@ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, /* insert in the hash table */ sh->hash = shape_initial_hash(proto); sh->is_hashed = TRUE; - sh->has_small_array_index = FALSE; js_shape_hash_link(ctx->rt, sh); return sh; } @@ -4541,8 +4386,6 @@ static int add_shape_property(JSContext *ctx, JSShape **psh, pr = &prop[sh->prop_count++]; pr->atom = JS_DupAtom(ctx, atom); pr->flags = prop_flags; - sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom); - /* add in hash table */ hash_mask = sh->prop_hash_mask; h = atom & hash_mask; pr->hash_next = prop_hash_end(sh)[-h - 1]; @@ -4656,7 +4499,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas if (unlikely(!p)) goto fail; p->class_id = class_id; - p->extensible = TRUE; + p->stone = FALSE; p->free_mark = 0; p->has_immutable_prototype = 0; p->tmp_mark = 0; @@ -4769,11 +4612,8 @@ JSValue JS_NewObject(JSContext *ctx) static void js_function_set_properties(JSContext *ctx, JSValueConst func_obj, JSAtom name, int len) { - /* ES6 feature non compatible with ES5.1: length is configurable */ - JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, JS_NewInt32(ctx, len), - JS_PROP_CONFIGURABLE); - JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, - JS_AtomToString(ctx, name), JS_PROP_CONFIGURABLE); + JS_SetPropertyInternal(ctx, func_obj, JS_ATOM_length, JS_NewInt32(ctx, len)); + JS_SetPropertyInternal(ctx, func_obj, JS_ATOM_name, JS_AtomToString(ctx, name)); } static BOOL js_class_has_bytecode(JSClassID class_id) @@ -4828,8 +4668,7 @@ static int js_method_set_properties(JSContext *ctx, JSValueConst func_obj, name_str = js_get_function_name(ctx, name); if (JS_IsException(name_str)) return -1; - if (JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, name_str, - JS_PROP_CONFIGURABLE) < 0) + if (JS_SetPropertyInternal(ctx, func_obj, JS_ATOM_name, name_str) < 0) return -1; return 0; } @@ -6160,12 +5999,9 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj, if (JS_IsException(str)) return; /* Note: SpiderMonkey does that, could update once there is a standard */ - if (JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_fileName, str, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0 || - JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0 || - JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_columnNumber, JS_NewInt32(ctx, col_num), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0) { + if (JS_SetPropertyInternal(ctx, error_obj, JS_ATOM_fileName, str) < 0 || + JS_SetPropertyInternal(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num)) < 0 || + JS_SetPropertyInternal(ctx, error_obj, JS_ATOM_columnNumber, JS_NewInt32(ctx, col_num)) < 0) { return; } } @@ -6213,8 +6049,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj, else str = JS_NewString(ctx, (char *)dbuf.buf); dbuf_free(&dbuf); - JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_stack, str, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyInternal(ctx, error_obj, JS_ATOM_stack, str); } /* Note: it is important that no exception is returned by this function */ @@ -6249,9 +6084,8 @@ static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num, /* out of memory: throw JS_NULL to avoid recursing */ obj = JS_NULL; } else { - JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, - JS_NewString(ctx, buf), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyInternal(ctx, obj, JS_ATOM_message, + JS_NewString(ctx, buf)); if (add_backtrace) { build_backtrace(ctx, obj, NULL, 0, 0, 0); } @@ -6296,21 +6130,6 @@ JSValue __attribute__((format(printf, 2, 3))) JS_ThrowTypeError(JSContext *ctx, return val; } -static int __attribute__((format(printf, 3, 4))) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, const char *fmt, ...) -{ - va_list ap; - - if (flags & JS_PROP_THROW || - flags & JS_PROP_THROW_STRICT) { - va_start(ap, fmt); - JS_ThrowError(ctx, JS_TYPE_ERROR, fmt, ap); - va_end(ap); - return -1; - } else { - return FALSE; - } -} - /* never use it directly */ static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowTypeErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...) { @@ -6332,17 +6151,6 @@ static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowSyntaxErrorAtom(J #define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "") #define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "") -static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom) -{ - if (flags & JS_PROP_THROW || - flags & JS_PROP_THROW_STRICT) { - JS_ThrowTypeErrorAtom(ctx, "'%s' is read-only", atom); - return -1; - } else { - return FALSE; - } -} - JSValue __attribute__((format(printf, 2, 3))) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...) { JSValue val; @@ -6503,8 +6311,8 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, JS_ThrowTypeError(ctx, "prototype is immutable"); return -1; } - if (unlikely(!p->extensible)) { - JS_ThrowTypeError(ctx, "object is not extensible"); + if (unlikely(!p->stone)) { + JS_ThrowTypeError(ctx, "object is not stone"); return -1; } if (proto) { @@ -6563,6 +6371,7 @@ static JSValue JS_GetPrototypeFree(JSContext *ctx, JSValue obj) return obj1; } +/* This is for getting string or symbol based properties */ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, JSAtom prop, JSValueConst this_obj, BOOL throw_ref_error) @@ -6579,50 +6388,14 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, return JS_NULL; case JS_TAG_EXCEPTION: return JS_EXCEPTION; - case JS_TAG_ARRAY: - { - JSArray *arr = JS_VALUE_GET_ARRAY(obj); - /* Only integer indexed access is allowed on arrays */ - if (__JS_AtomIsTaggedInt(prop)) { - uint32_t idx = __JS_AtomToUInt32(prop); - if (idx < arr->len) { - return JS_DupValue(ctx, arr->values[idx]); - } - } - } - return JS_NULL; - case JS_TAG_STRING: - { - JSString *p1 = JS_VALUE_GET_STRING(obj); - /* Only indexed access via [] is allowed on strings */ - if (__JS_AtomIsTaggedInt(prop)) { - uint32_t idx = __JS_AtomToUInt32(prop); - if (idx < p1->len) { - return js_new_string_char(ctx, string_get(p1, idx)); - } - } - } - return JS_NULL; - case JS_TAG_STRING_ROPE: - { - JSStringRope *p1 = JS_VALUE_GET_STRING_ROPE(obj); - /* Only indexed access via [] is allowed on strings */ - if (__JS_AtomIsTaggedInt(prop)) { - uint32_t idx = __JS_AtomToUInt32(prop); - if (idx < p1->len) { - return js_new_string_char(ctx, string_rope_get(obj, idx)); - } - } - } - return JS_NULL; default: /* Primitives have no properties */ return JS_NULL; } - } else { - p = JS_VALUE_GET_OBJ(obj); } + p = JS_VALUE_GET_OBJ(obj); + for(;;) { prs = find_own_property(&pr, p, prop); if (prs) { @@ -6649,25 +6422,6 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, } } -static int num_keys_cmp(const void *p1, const void *p2, void *opaque) -{ - JSContext *ctx = opaque; - JSAtom atom1 = ((const JSPropertyEnum *)p1)->atom; - JSAtom atom2 = ((const JSPropertyEnum *)p2)->atom; - uint32_t v1, v2; - BOOL atom1_is_integer, atom2_is_integer; - - atom1_is_integer = JS_AtomIsArrayIndex(ctx, &v1, atom1); - atom2_is_integer = JS_AtomIsArrayIndex(ctx, &v2, atom2); - assert(atom1_is_integer && atom2_is_integer); - if (v1 < v2) - return -1; - else if (v1 == v2) - return 0; - else - return 1; -} - void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len) { uint32_t i; @@ -6679,7 +6433,10 @@ void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len) } /* return < 0 in case if exception, 0 if OK. ptab and its atoms must - be freed by the user. */ + be freed by the user. + Simplified: returns only string keys (text keys). All text keys are enumerable. + The 'flags' parameter is kept for compatibility but only JS_GPN_STRING_MASK + and JS_GPN_SYMBOL_MASK are used. */ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, JSPropertyEnum **ptab, uint32_t *plen, @@ -6690,111 +6447,64 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, JSShapeProperty *prs; JSPropertyEnum *tab_atom; JSAtom atom; - uint32_t num_keys_count, str_keys_count, sym_keys_count, atom_count; - uint32_t num_index, str_index, sym_index; - BOOL is_enumerable, num_sorted; - uint32_t num_key; + uint32_t str_keys_count, atom_count; JSAtomKindEnum kind; + BOOL want_strings = (flags & JS_GPN_STRING_MASK) != 0; + BOOL want_symbols = (flags & JS_GPN_SYMBOL_MASK) != 0; /* clear pointer for consistency in case of failure */ *ptab = NULL; *plen = 0; /* compute the number of returned properties */ - num_keys_count = 0; str_keys_count = 0; - sym_keys_count = 0; sh = p->shape; - for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { + for (i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { atom = prs->atom; if (atom != JS_ATOM_NULL) { - /* Skip object-key symbols (private access tokens, not enumerable) */ + /* Skip object-key symbols (private access tokens) */ if (js_atom_is_object_key_symbol(ctx->rt, atom)) continue; - is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0); kind = JS_AtomGetKind(ctx, atom); - if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) && - ((flags >> kind) & 1) != 0) { - /* need to raise an exception in case of the module - name space (implicit GetOwnProperty) */ - if (unlikely((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) && - (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY))) { - JSVarRef *var_ref = p->prop[i].u.var_ref; - if (unlikely(JS_IsUninitialized(*var_ref->pvalue))) { - JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); - return -1; - } - } - if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { - num_keys_count++; - } else if (kind == JS_ATOM_KIND_STRING) { - str_keys_count++; - } else { - sym_keys_count++; - } + if ((kind == JS_ATOM_KIND_STRING && want_strings) || + (kind == JS_ATOM_KIND_SYMBOL && want_symbols)) { + str_keys_count++; } } } - /* fill them */ - - atom_count = num_keys_count + str_keys_count; - if (atom_count < str_keys_count) - goto add_overflow; - atom_count += sym_keys_count; - if (atom_count < sym_keys_count) - goto add_overflow; + atom_count = str_keys_count; if (atom_count > INT32_MAX) { - add_overflow: JS_ThrowOutOfMemory(ctx); return -1; } - /* XXX: need generic way to test for js_malloc(ctx, a * b) overflow */ - + /* avoid allocating 0 bytes */ tab_atom = js_malloc(ctx, sizeof(tab_atom[0]) * max_int(atom_count, 1)); if (!tab_atom) { return -1; } - num_index = 0; - str_index = num_keys_count; - sym_index = str_index + str_keys_count; - - num_sorted = TRUE; + j = 0; sh = p->shape; - for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { + for (i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { atom = prs->atom; if (atom != JS_ATOM_NULL) { - /* Skip object-key symbols (private access tokens, not enumerable) */ + /* Skip object-key symbols (private access tokens) */ if (js_atom_is_object_key_symbol(ctx->rt, atom)) continue; - is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0); kind = JS_AtomGetKind(ctx, atom); - if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) && - ((flags >> kind) & 1) != 0) { - if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { - j = num_index++; - num_sorted = FALSE; - } else if (kind == JS_ATOM_KIND_STRING) { - j = str_index++; - } else { - j = sym_index++; - } + if ((kind == JS_ATOM_KIND_STRING && want_strings) || + (kind == JS_ATOM_KIND_SYMBOL && want_symbols)) { tab_atom[j].atom = JS_DupAtom(ctx, atom); - tab_atom[j].is_enumerable = is_enumerable; + tab_atom[j].is_enumerable = TRUE; /* all text keys are enumerable */ + j++; } } } - assert(num_index == num_keys_count); - assert(str_index == num_keys_count + str_keys_count); - assert(sym_index == atom_count); + assert((uint32_t)j == atom_count); - if (num_keys_count != 0 && !num_sorted) { - rqsort(tab_atom, num_keys_count, sizeof(tab_atom[0]), num_keys_cmp, - ctx); - } *ptab = tab_atom; *plen = atom_count; return 0; @@ -6803,28 +6513,6 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, uint32_t *plen, JSValueConst obj, int flags) { - /* Handle intrinsic arrays */ - if (JS_VALUE_GET_TAG(obj) == JS_TAG_ARRAY) { - JSArray *arr = JS_VALUE_GET_ARRAY(obj); - uint32_t i, len = arr->len; - JSPropertyEnum *tab; - - if (len == 0) { - *ptab = NULL; - *plen = 0; - return 0; - } - tab = js_malloc(ctx, sizeof(JSPropertyEnum) * len); - if (!tab) - return -1; - for (i = 0; i < len; i++) { - tab[i].atom = __JS_AtomFromUInt32(i); - tab[i].is_enumerable = TRUE; - } - *ptab = tab; - *plen = len; - return 0; - } if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) { JS_ThrowTypeErrorNotAnObject(ctx); return -1; @@ -6846,7 +6534,7 @@ retry: prs = find_own_property(&pr, p, prop); if (prs) { if (desc) { - desc->flags = prs->flags & JS_PROP_C_W_E; + desc->flags = prs->flags; desc->getter = JS_NULL; desc->setter = JS_NULL; desc->value = JS_NULL; @@ -6879,24 +6567,6 @@ retry: int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, JSValueConst obj, JSAtom prop) { - /* Handle intrinsic arrays */ - if (JS_VALUE_GET_TAG(obj) == JS_TAG_ARRAY) { - JSArray *arr = JS_VALUE_GET_ARRAY(obj); - uint32_t idx; - if (__JS_AtomIsTaggedInt(prop)) { - idx = __JS_AtomToUInt32(prop); - if (idx < arr->len) { - if (desc) { - desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE | JS_PROP_CONFIGURABLE; - desc->value = JS_DupValue(ctx, arr->values[idx]); - desc->getter = JS_NULL; - desc->setter = JS_NULL; - } - return TRUE; - } - } - return FALSE; - } if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) { JS_ThrowTypeErrorNotAnObject(ctx); return -1; @@ -6904,45 +6574,11 @@ int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, return JS_GetOwnPropertyInternal(ctx, desc, JS_VALUE_GET_OBJ(obj), prop); } -/* return -1 if exception (exotic object only) or TRUE/FALSE */ -int JS_IsExtensible(JSContext *ctx, JSValueConst obj) -{ - JSObject *p; - - if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) - return FALSE; - p = JS_VALUE_GET_OBJ(obj); - return p->extensible; -} - -/* return -1 if exception (exotic object only) or TRUE/FALSE */ -int JS_PreventExtensions(JSContext *ctx, JSValueConst obj) -{ - JSObject *p; - - if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) - return FALSE; - p = JS_VALUE_GET_OBJ(obj); - p->extensible = FALSE; - return TRUE; -} - /* return -1 if exception otherwise TRUE or FALSE */ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) { JSObject *p; int ret; - - /* Handle intrinsic arrays */ - if (JS_VALUE_GET_TAG(obj) == JS_TAG_ARRAY) { - JSArray *arr = JS_VALUE_GET_ARRAY(obj); - uint32_t idx; - if (__JS_AtomIsTaggedInt(prop)) { - idx = __JS_AtomToUInt32(prop); - return idx < arr->len; - } - return FALSE; - } if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) return FALSE; p = JS_VALUE_GET_OBJ(obj); @@ -6973,10 +6609,9 @@ JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val) JSAtom atom; uint32_t tag; tag = JS_VALUE_GET_TAG(val); - if (tag == JS_TAG_INT && - (uint32_t)JS_VALUE_GET_INT(val) <= JS_ATOM_MAX_INT) { - /* fast path for integer values */ - atom = __JS_AtomFromUInt32(JS_VALUE_GET_INT(val)); + if (tag == JS_TAG_INT) { + /* Convert integer to string atom */ + atom = JS_NewAtomUInt32(ctx, (uint32_t)JS_VALUE_GET_INT(val)); } else if (tag == JS_TAG_SYMBOL) { JSAtomStruct *p = JS_VALUE_GET_PTR(val); atom = JS_DupAtom(ctx, js_get_atom_index(ctx->rt, p)); @@ -7021,150 +6656,90 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj, return JS_NULL; } - if (this_tag == JS_TAG_ARRAY) { - JSArray *arr = JS_VALUE_GET_ARRAY(this_obj); - if (prop_tag == JS_TAG_INT) { - int idx = JS_VALUE_GET_INT(prop); - if (idx < 0 || (uint32_t)idx >= arr->len) { - return JS_NULL; - } - return JS_DupValue(ctx, arr->values[idx]); - } - - if (prop_tag == JS_TAG_FLOAT64) { - double d = JS_VALUE_GET_FLOAT64(prop); - uint32_t idx = (uint32_t)d; - if (d < 0 || d != (double)idx || idx >= arr->len) { - return JS_NULL; - } - return JS_DupValue(ctx, arr->values[idx]); - } - + if (prop_tag == JS_TAG_INT) { + int idx = JS_VALUE_GET_INT(prop); JS_FreeValue(ctx, prop); - return JS_ThrowTypeError(ctx, "array index must be a number"); + return JS_GetPropertyNumber(ctx, this_obj, idx); } - if (this_tag == JS_TAG_OBJECT) { - /* Records only accept string or object keys */ - if (prop_tag == JS_TAG_INT || prop_tag == JS_TAG_FLOAT64) { - JS_FreeValue(ctx, prop); - return JS_ThrowTypeError(ctx, "record index must be text or record"); - } - - if (prop_tag == JS_TAG_STRING || prop_tag == JS_TAG_STRING_ROPE) { - atom = JS_ValueToAtom(ctx, prop); - JS_FreeValue(ctx, prop); - ret = JS_GetProperty(ctx, this_obj, atom); - JS_FreeAtom(ctx, atom); - return ret; - } - - if (prop_tag == JS_TAG_OBJECT) { - /* Object key - handled via symbol lookup */ - atom = JS_ValueToAtom(ctx, prop); - JS_FreeValue(ctx, prop); - if (atom == JS_ATOM_NULL) - return JS_EXCEPTION; - ret = JS_GetProperty(ctx, this_obj, atom); - JS_FreeAtom(ctx, atom); - return ret; - } - + if (prop_tag == JS_TAG_FLOAT64) { + double d = JS_VALUE_GET_FLOAT64(prop); + uint32_t idx = (uint32_t)d; JS_FreeValue(ctx, prop); - return JS_ThrowTypeError(ctx, "record index must be text or record"); + if (d != (double)idx) + return JS_NULL; + return JS_GetPropertyNumber(ctx, this_obj, idx); } - if (this_tag == JS_TAG_STRING || this_tag == JS_TAG_STRING_ROPE) { - if (prop_tag == JS_TAG_INT) { - int idx = JS_VALUE_GET_INT(prop); - uint32_t len = js_string_get_length(this_obj); - if (idx < 0 || (uint32_t)idx >= len) { - return JS_NULL; - } - return js_sub_string(ctx, JS_VALUE_GET_STRING(this_obj), idx, idx + 1); - } - - if (prop_tag == JS_TAG_FLOAT64) { - double d = JS_VALUE_GET_FLOAT64(prop); - uint32_t idx = (uint32_t)d; - uint32_t len = js_string_get_length(this_obj); - if (d < 0 || d != (double)idx || idx >= len) { - return JS_NULL; - } - return js_sub_string(ctx, JS_VALUE_GET_STRING(this_obj), idx, idx + 1); - } - + if (prop_tag == JS_TAG_STRING || prop_tag == JS_TAG_STRING_ROPE) { + atom = JS_ValueToAtom(ctx, prop); JS_FreeValue(ctx, prop); - return JS_ThrowTypeError(ctx, "string index must be a number"); + ret = JS_GetProperty(ctx, this_obj, atom); + JS_FreeAtom(ctx, atom); + return ret; } + /* Unknown type -> null */ JS_FreeValue(ctx, prop); - return JS_ThrowTypeError(ctx, "cannot read property of this value: %d", this_tag); + return JS_ThrowInternalError(ctx, "attempted to access property on odd type"); +} + +JSValue JS_SetPropertyNumber(JSContext *js, JSValueConst obj, int idx, JSValue val) +{ + if (JS_VALUE_GET_TAG(obj) != JS_TAG_ARRAY) + return JS_ThrowInternalError(js, "cannot set with a number on a non array"); + + JSArray *a = JS_VALUE_GET_ARRAY(obj); + int len = a->len; + if (idx < 0 || idx >= len) { + return JS_ThrowInternalError(js, "index out of bounds"); + } + + if (a->stone) + return JS_ThrowInternalError(js, "cannot set on a stoned array"); + + a->values[idx] = JS_DupValue(js, val); +} + +JSValue JS_GetPropertyNumber(JSContext *js, JSValueConst obj, int idx) +{ + if (JS_VALUE_GET_TAG(obj) == JS_TAG_ARRAY) { + JSArray *a = JS_VALUE_GET_ARRAY(obj); + int len = a->len; + if (idx < 0 || idx >= len) { + return JS_NULL; + } + return JS_DupValue(js, a->values[idx]); + } + + if (JS_VALUE_GET_TAG(obj) == JS_TAG_STRING || JS_VALUE_GET_TAG(obj) == JS_TAG_STRING_ROPE) { + uint32_t len = js_string_get_length(obj); + if (idx < 0 || idx >= len) { + return JS_NULL; + } + return js_sub_string(js, JS_VALUE_GET_STRING(obj), idx, idx + 1); + } + + return JS_NULL; } JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx) { - return JS_GetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx)); -} - -/* Check if an object has a generalized numeric property. Return value: - -1 for exception, - TRUE if property exists, stored into *pval, - FALSE if proprty does not exist. - */ -static int JS_TryGetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, JSValue *pval) -{ - JSValue val = JS_NULL; - JSAtom prop; - int present; - - if (likely((uint64_t)idx <= JS_ATOM_MAX_INT)) { - /* fast path */ - present = JS_HasProperty(ctx, obj, __JS_AtomFromUInt32(idx)); - if (present > 0) { - val = JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx)); - if (unlikely(JS_IsException(val))) - present = -1; - } - } else { - prop = JS_NewAtomInt64(ctx, idx); - present = -1; - if (likely(prop != JS_ATOM_NULL)) { - present = JS_HasProperty(ctx, obj, prop); - if (present > 0) { - val = JS_GetProperty(ctx, obj, prop); - if (unlikely(JS_IsException(val))) - present = -1; - } - JS_FreeAtom(ctx, prop); - } - } - *pval = val; - return present; + return JS_GetPropertyNumber(ctx, this_obj, idx); } static JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx) { - JSAtom prop; - JSValue val; - - if ((uint64_t)idx <= INT32_MAX) { - /* fast path for fast arrays */ - return JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx)); - } - prop = JS_NewAtomInt64(ctx, idx); - if (prop == JS_ATOM_NULL) - return JS_EXCEPTION; - - val = JS_GetProperty(ctx, obj, prop); - JS_FreeAtom(ctx, prop); - return val; + return JS_GetPropertyNumber(ctx, obj, idx); } JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, const char *prop) { + if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT) + return JS_NULL; + JSAtom atom; JSValue ret; atom = JS_NewAtom(ctx, prop); @@ -7218,6 +6793,8 @@ static JSProperty *add_property(JSContext *ctx, return &p->prop[p->shape->prop_count - 1]; } +/* Simplified delete_property - no JS_PROP_CONFIGURABLE check. + Deletion fails only if object is stone. */ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) { JSShape *sh; @@ -7226,7 +6803,10 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) uint32_t lpr_idx; intptr_t h, h1; - redo: + /* Cannot delete from a stone object */ + if (p->stone) + return FALSE; + sh = p->shape; h1 = atom & sh->prop_hash_mask; h = prop_hash_end(sh)[-h1 - 1]; @@ -7236,9 +6816,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) while (h != 0) { pr = &prop[h - 1]; if (likely(pr->atom == atom)) { - /* found ! */ - if (!(pr->flags & JS_PROP_CONFIGURABLE)) - return FALSE; + /* found - delete it */ /* realloc the shape if needed */ if (lpr) lpr_idx = lpr - get_shape_prop(sh); @@ -7272,35 +6850,10 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) lpr = pr; h = pr->hash_next; } - /* not found */ + /* not found - success (nothing to delete) */ return TRUE; } -static int call_setter(JSContext *ctx, JSObject *setter, - JSValueConst this_obj, JSValue val, int flags) -{ - JSValue ret, func; - if (likely(setter)) { - func = JS_MKPTR(JS_TAG_OBJECT, setter); - /* Note: the field could be removed in the setter */ - func = JS_DupValue(ctx, func); - ret = JS_CallFree(ctx, func, this_obj, 1, (JSValueConst *)&val); - JS_FreeValue(ctx, val); - if (JS_IsException(ret)) - return -1; - JS_FreeValue(ctx, ret); - return TRUE; - } else { - JS_FreeValue(ctx, val); - if (flags & JS_PROP_THROW || - flags & JS_PROP_THROW_STRICT) { - JS_ThrowTypeError(ctx, "no setter for property"); - return -1; - } - return FALSE; - } -} - static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc) { JS_FreeValue(ctx, desc->getter); @@ -7308,157 +6861,72 @@ static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc) JS_FreeValue(ctx, desc->value); } -/* return -1 in case of exception or TRUE or FALSE. Warning: 'val' is - freed by the function. 'flags' is a bitmask of JS_PROP_NO_ADD, - JS_PROP_THROW or JS_PROP_THROW_STRICT. If JS_PROP_NO_ADD is set, - the new property is not added and an error is raised. 'this_obj' is - the receiver. If obj != this_obj, then obj must be an object - (Reflect.set case). */ -int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, - JSAtom prop, JSValue val, JSValueConst this_obj, int flags) +int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val) { - JSObject *p, *p1; + JSObject *p; JSShapeProperty *prs; JSProperty *pr; uint32_t tag; - JSPropertyDescriptor desc; - int ret; tag = JS_VALUE_GET_TAG(this_obj); - if (unlikely(tag != JS_TAG_OBJECT)) { - if (tag == JS_TAG_ARRAY) { - /* Arrays only accept integer index via JS_SetPropertyValue */ - JS_FreeValue(ctx, val); - if (__JS_AtomIsTaggedInt(prop)) { - uint32_t idx = __JS_AtomToUInt32(prop); - JSArray *arr = JS_VALUE_GET_ARRAY(this_obj); - if (idx < arr->len) { - /* This path shouldn't be used for arrays - use JS_SetPropertyValue */ - JS_ThrowTypeError(ctx, "use JS_SetPropertyValue for array element access"); - } else { - JS_ThrowRangeError(ctx, "array index out of bounds"); - } - } else { - JS_ThrowTypeError(ctx, "array index must be a number"); - } - return -1; - } - if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { - p = NULL; - p1 = JS_VALUE_GET_OBJ(obj); - goto prototype_lookup; - } else { - /* Primitives cannot have properties set */ - JS_FreeValue(ctx, val); - if (tag == JS_TAG_NULL) { - JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop); - } else { - JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' on a primitive", prop); - } - return -1; - } - } else { - p = JS_VALUE_GET_OBJ(this_obj); - p1 = JS_VALUE_GET_OBJ(obj); - if (unlikely(p != p1)) - goto retry2; - } - - /* fast path if obj == this_obj */ - retry: - prs = find_own_property(&pr, p1, prop); - if (prs) { - if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE | - JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) { - /* fast case */ - set_value(ctx, &pr->u.value, val); - return TRUE; - } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { - set_value(ctx, pr->u.var_ref->pvalue, val); - return TRUE; - } else { - goto read_only_prop; - } - } - - for(;;) { - p1 = p1->shape->proto; - prototype_lookup: - if (!p1) - break; - - retry2: - prs = find_own_property(&pr, p1, prop); - if (prs) { - if (!(prs->flags & JS_PROP_WRITABLE)) { - goto read_only_prop; - } else { - break; - } - } - } - - if (unlikely(flags & JS_PROP_NO_ADD)) { + if (tag != JS_TAG_OBJECT) { JS_FreeValue(ctx, val); - JS_ThrowReferenceErrorNotDefined(ctx, prop); + if (tag == JS_TAG_NULL) { + JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop); + } else { + JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' on a primitive", prop); + } return -1; } - if (unlikely(!p)) { - JS_FreeValue(ctx, val); - return JS_ThrowTypeErrorOrFalse(ctx, flags, "not an object"); - } + p = JS_VALUE_GET_OBJ(this_obj); - if (unlikely(!p->extensible)) { - JS_FreeValue(ctx, val); - return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible"); - } - - if (likely(p == JS_VALUE_GET_OBJ(obj))) { - pr = add_property(ctx, p, prop, JS_PROP_C_W_E); - if (unlikely(!pr)) { - JS_FreeValue(ctx, val); - return -1; - } - pr->u.value = val; + if (unlikely(p->stone)) { + /* If stone, can only update existing own properties */ + prs = find_own_property(&pr, p, prop); + if (!prs) { + JS_FreeValue(ctx, val); + JS_ThrowTypeError(ctx, "object is stone"); + return -1; + } + /* Handle VARREF for closures */ + if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { + set_value(ctx, pr->u.var_ref->pvalue, val); return TRUE; - } else { - /* generic case: modify the property in this_obj if it already exists */ - ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); - if (ret < 0) { - JS_FreeValue(ctx, val); - return ret; - } - if (ret) { - JS_FreeValue(ctx, desc.value); - if (!(desc.flags & JS_PROP_WRITABLE)) { - read_only_prop: - JS_FreeValue(ctx, val); - return JS_ThrowTypeErrorReadOnly(ctx, flags, prop); - } - ret = JS_DefineProperty(ctx, this_obj, prop, val, - JS_NULL, JS_NULL, - JS_PROP_HAS_VALUE); - JS_FreeValue(ctx, val); - return ret; - } else { - generic_create_prop: - ret = JS_CreateProperty(ctx, p, prop, val, JS_NULL, JS_NULL, - flags | - JS_PROP_HAS_VALUE | - JS_PROP_HAS_ENUMERABLE | - JS_PROP_HAS_WRITABLE | - JS_PROP_HAS_CONFIGURABLE | - JS_PROP_C_W_E); - JS_FreeValue(ctx, val); - return ret; } + set_value(ctx, &pr->u.value, val); + return TRUE; } + + /* Object is not stone - find or create property */ + prs = find_own_property(&pr, p, prop); + if (prs) { + /* Property exists - update it */ + if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { + set_value(ctx, pr->u.var_ref->pvalue, val); + return TRUE; + } + set_value(ctx, &pr->u.value, val); + return TRUE; + } + + /* Add new property */ + pr = add_property(ctx, p, prop, 0); + if (unlikely(!pr)) { + JS_FreeValue(ctx, val); + return -1; + } + pr->u.value = val; + return TRUE; } -/* flags can be JS_PROP_THROW or JS_PROP_THROW_STRICT */ -static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, - JSValue prop, JSValue val, int flags) +int JS_SetProperty(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValue val) +{ + return JS_SetPropertyInternal(ctx, this_obj, prop, val); +} + +static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, JSValue prop, JSValue val) { JSAtom atom; int ret; @@ -7522,7 +6990,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, JS_FreeValue(ctx, val); return -1; } - ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, flags); + ret = JS_SetPropertyInternal(ctx, this_obj, atom, val); JS_FreeAtom(ctx, atom); return ret; } @@ -7537,29 +7005,13 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx, JSValue val) { - return JS_SetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx), val, - JS_PROP_THROW); + JS_SetPropertyNumber(ctx, this_obj, idx, val); } int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, int64_t idx, JSValue val) { - JSAtom prop; - int res; - - if ((uint64_t)idx <= INT32_MAX) { - /* fast path for fast arrays */ - return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, - JS_PROP_THROW); - } - prop = JS_NewAtomInt64(ctx, idx); - if (prop == JS_ATOM_NULL) { - JS_FreeValue(ctx, val); - return -1; - } - res = JS_SetProperty(ctx, this_obj, prop, val); - JS_FreeAtom(ctx, prop); - return res; + JS_SetPropertyNumber(ctx, this_obj, idx, val); } int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, @@ -7572,7 +7024,7 @@ int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, JS_FreeValue(ctx, val); return -1; } - ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, JS_PROP_THROW); + ret = JS_SetPropertyInternal(ctx, this_obj, atom, val); JS_FreeAtom(ctx, atom); return ret; } @@ -7599,7 +7051,7 @@ int JS_SetPropertyKey(JSContext *ctx, JSValueConst this_obj, JSValueConst key, J JS_FreeValue(ctx, val); return -1; } - ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, JS_PROP_THROW); + ret = JS_SetPropertyInternal(ctx, this_obj, atom, val); JS_FreeAtom(ctx, atom); return ret; } @@ -7608,62 +7060,6 @@ int JS_SetPropertyKey(JSContext *ctx, JSValueConst this_obj, JSValueConst key, J it, otherwise def_flags is used) Note: makes assumption about the bit pattern of the flags */ -static int get_prop_flags(int flags, int def_flags) -{ - int mask; - mask = (flags >> JS_PROP_HAS_SHIFT) & JS_PROP_C_W_E; - return (flags & mask) | (def_flags & ~mask); -} - -static int JS_CreateProperty(JSContext *ctx, JSObject *p, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, - int flags) -{ - JSProperty *pr; - int ret, prop_flags; - - /* add a new property or modify an existing exotic one */ - if (!p->extensible) { - not_extensible: - return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible"); - } - - prop_flags = flags & JS_PROP_C_W_E; - - pr = add_property(ctx, p, prop, prop_flags); - if (unlikely(!pr)) - return -1; - if (flags & JS_PROP_HAS_VALUE) { - pr->u.value = JS_DupValue(ctx, val); - } else { - pr->u.value = JS_NULL; - } - return TRUE; -} - -/* return FALSE if not OK */ -static BOOL check_define_prop_flags(int prop_flags, int flags) -{ - if (!(prop_flags & JS_PROP_CONFIGURABLE)) { - if ((flags & (JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) == - (JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) { - return FALSE; - } - if ((flags & JS_PROP_HAS_ENUMERABLE) && - (flags & JS_PROP_ENUMERABLE) != (prop_flags & JS_PROP_ENUMERABLE)) - return FALSE; - if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE)) { - if (!(prop_flags & JS_PROP_WRITABLE)) { - /* not writable: cannot set the writable bit */ - if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == - (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) - return FALSE; - } - } - } - return TRUE; -} /* ensure that the shape can be safely modified */ static int js_shape_prepare_update(JSContext *ctx, JSObject *p, @@ -7693,209 +7089,6 @@ static int js_shape_prepare_update(JSContext *ctx, JSObject *p, return 0; } -static int js_update_property_flags(JSContext *ctx, JSObject *p, - JSShapeProperty **pprs, int flags) -{ - if (flags != (*pprs)->flags) { - if (js_shape_prepare_update(ctx, p, pprs)) - return -1; - (*pprs)->flags = flags; - } - return 0; -} - -/* allowed flags: - JS_PROP_CONFIGURABLE, JS_PROP_WRITABLE, JS_PROP_ENUMERABLE - JS_PROP_HAS_VALUE, - JS_PROP_HAS_CONFIGURABLE, JS_PROP_HAS_WRITABLE, JS_PROP_HAS_ENUMERABLE, - JS_PROP_THROW, JS_PROP_NO_EXOTIC. - If JS_PROP_THROW is set, return an exception instead of FALSE. - if JS_PROP_NO_EXOTIC is set, do not call the exotic - define_own_property callback. - return -1 (exception), FALSE or TRUE. -*/ -int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, int flags) -{ - JSObject *p; - JSShapeProperty *prs; - JSProperty *pr; - int mask, res; - - /* Handle intrinsic arrays - only numeric indices allowed */ - if (JS_VALUE_GET_TAG(this_obj) == JS_TAG_ARRAY) { - JSArray *arr = JS_VALUE_GET_ARRAY(this_obj); - uint32_t idx; - if (__JS_AtomIsTaggedInt(prop)) { - idx = __JS_AtomToUInt32(prop); - /* For array creation, we allow setting within allocated length */ - if (idx < arr->len) { - JS_FreeValueRT(ctx->rt, arr->values[idx]); - arr->values[idx] = JS_DupValue(ctx, val); - return 1; - } - /* Allow extending by exactly 1 (for push-like operations during construction) */ - if (idx == arr->len) { - if (js_intrinsic_array_push(ctx, arr, JS_DupValue(ctx, val)) < 0) - return -1; - return 1; - } - JS_ThrowRangeError(ctx, "array index %u out of bounds (length %u)", idx, arr->len); - return -1; - } - /* length property - intrinsic arrays have fixed length */ - if (prop == JS_ATOM_length) { - JS_ThrowTypeError(ctx, "cannot set length of intrinsic array"); - return -1; - } - JS_ThrowTypeError(ctx, "intrinsic arrays only support numeric indices"); - assert(0); - return -1; - } - - if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT) { - JS_ThrowTypeErrorNotAnObject(ctx); - return -1; - } - p = JS_VALUE_GET_OBJ(this_obj); - - redo_prop_update: - prs = find_own_property(&pr, p, prop); - if (prs) { - /* the range of the Array length property is always tested before */ - if ((prs->flags & JS_PROP_LENGTH) && (flags & JS_PROP_HAS_VALUE)) { - uint32_t array_length; - if (JS_ToArrayLengthFree(ctx, &array_length, - JS_DupValue(ctx, val), FALSE)) { - return -1; - } - /* this code relies on the fact that Uint32 are never allocated */ - val = (JSValueConst)JS_NewUint32(ctx, array_length); - /* prs may have been modified */ - prs = find_own_property(&pr, p, prop); - assert(prs != NULL); - } - /* property already exists */ - if (!check_define_prop_flags(prs->flags, flags)) { - not_configurable: - return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable"); - } - - if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE)) { - if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { - if (flags & JS_PROP_HAS_VALUE) { - /* update the reference */ - set_value(ctx, pr->u.var_ref->pvalue, - JS_DupValue(ctx, val)); - } - /* if writable is set to false, no longer a - reference (for mapped arguments) */ - if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) { - JSValue val1; - if (js_shape_prepare_update(ctx, p, &prs)) - return -1; - val1 = JS_DupValue(ctx, *pr->u.var_ref->pvalue); - free_var_ref(ctx->rt, pr->u.var_ref); - pr->u.value = val1; - prs->flags &= ~(JS_PROP_TMASK | JS_PROP_WRITABLE); - } - } else if (prs->flags & JS_PROP_LENGTH) { - /* Object-based arrays removed - length property not supported */ - JS_ThrowTypeError(ctx, "cannot set length property"); - return -1; - } else { - if (flags & JS_PROP_HAS_VALUE) { - JS_FreeValue(ctx, pr->u.value); - pr->u.value = JS_DupValue(ctx, val); - } - if (flags & JS_PROP_HAS_WRITABLE) { - if (js_update_property_flags(ctx, p, &prs, - (prs->flags & ~JS_PROP_WRITABLE) | - (flags & JS_PROP_WRITABLE))) - return -1; - } - } - } - mask = 0; - if (flags & JS_PROP_HAS_CONFIGURABLE) - mask |= JS_PROP_CONFIGURABLE; - if (flags & JS_PROP_HAS_ENUMERABLE) - mask |= JS_PROP_ENUMERABLE; - if (js_update_property_flags(ctx, p, &prs, - (prs->flags & ~mask) | (flags & mask))) - return -1; - return TRUE; - } - - return JS_CreateProperty(ctx, p, prop, val, getter, setter, flags); -} - -/* shortcut to add or redefine a new property value */ -int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValue val, int flags) -{ - int ret; - ret = JS_DefineProperty(ctx, this_obj, prop, val, JS_NULL, JS_NULL, - flags | JS_PROP_HAS_VALUE | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_ENUMERABLE); - JS_FreeValue(ctx, val); - return ret; -} - -int JS_DefinePropertyValueValue(JSContext *ctx, JSValueConst this_obj, - JSValue prop, JSValue val, int flags) -{ - JSAtom atom; - int ret; - atom = JS_ValueToAtom(ctx, prop); - JS_FreeValue(ctx, prop); - if (unlikely(atom == JS_ATOM_NULL)) { - JS_FreeValue(ctx, val); - return -1; - } - ret = JS_DefinePropertyValue(ctx, this_obj, atom, val, flags); - JS_FreeAtom(ctx, atom); - return ret; -} - -int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj, - uint32_t idx, JSValue val, int flags) -{ - return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewUint32(ctx, idx), - val, flags); -} - -int JS_DefinePropertyValueInt64(JSContext *ctx, JSValueConst this_obj, - int64_t idx, JSValue val, int flags) -{ - return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx), - val, flags); -} - -int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj, - const char *prop, JSValue val, int flags) -{ - JSAtom atom; - int ret; - atom = JS_NewAtom(ctx, prop); - if (atom == JS_ATOM_NULL) { - JS_FreeValue(ctx, val); - return -1; - } - ret = JS_DefinePropertyValue(ctx, this_obj, atom, val, flags); - JS_FreeAtom(ctx, atom); - return ret; -} - -static int JS_CreateDataPropertyUint32(JSContext *ctx, JSValueConst this_obj, - int64_t idx, JSValue val, int flags) -{ - return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx), - val, flags | JS_PROP_CONFIGURABLE | - JS_PROP_ENUMERABLE | JS_PROP_WRITABLE); -} - - /* return TRUE if 'obj' has a non empty 'name' string */ static BOOL js_object_has_name(JSContext *ctx, JSValueConst obj) { @@ -7916,20 +7109,18 @@ static BOOL js_object_has_name(JSContext *ctx, JSValueConst obj) return (p->len != 0); } -static int JS_DefineObjectName(JSContext *ctx, JSValueConst obj, - JSAtom name, int flags) +static int JS_DefineObjectName(JSContext *ctx, JSValueConst obj, JSAtom name) { if (name != JS_ATOM_NULL && JS_IsObject(obj) && !js_object_has_name(ctx, obj) - && JS_DefinePropertyValue(ctx, obj, JS_ATOM_name, JS_AtomToString(ctx, name), flags) < 0) { + && JS_SetPropertyInternal(ctx, obj, JS_ATOM_name, JS_AtomToString(ctx, name)) < 0) { return -1; } return 0; } -static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj, - JSValueConst str, int flags) +static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj, JSValueConst str) { if (JS_IsObject(obj) && !js_object_has_name(ctx, obj)) { @@ -7942,7 +7133,7 @@ static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj, JS_FreeAtom(ctx, prop); if (JS_IsException(name_str)) return -1; - if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_name, name_str, flags) < 0) + if (JS_SetPropertyInternal(ctx, obj, JS_ATOM_name, name_str) < 0) return -1; } return 0; @@ -7965,22 +7156,12 @@ static int JS_CheckDefineGlobalVar(JSContext *ctx, JSAtom prop, int flags) p = JS_VALUE_GET_OBJ(ctx->global_obj); prs = find_own_property1(p, prop); if (flags & DEFINE_GLOBAL_LEX_VAR) { - if (prs && !(prs->flags & JS_PROP_CONFIGURABLE)) + if (prs) goto fail_redeclaration; } else { - if (!prs && !p->extensible) - goto define_error; - if (flags & DEFINE_GLOBAL_FUNC_VAR) { - if (prs) { - if (!(prs->flags & JS_PROP_CONFIGURABLE) && - ((prs->flags & (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)) != - (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE))) { - define_error: - JS_ThrowTypeErrorAtom(ctx, "cannot define variable '%s'", - prop); - return -1; - } - } + if (!prs && p->stone) { + JS_ThrowTypeErrorAtom(ctx, "cannot define variable '%s'", prop); + return -1; } } /* check if there already is a lexical declaration */ @@ -7994,57 +7175,39 @@ static int JS_CheckDefineGlobalVar(JSContext *ctx, JSAtom prop, int flags) return 0; } -/* def_flags is (0, DEFINE_GLOBAL_LEX_VAR) | - JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE */ +/* Simplified: def_flags is (0, DEFINE_GLOBAL_LEX_VAR) */ static int JS_DefineGlobalVar(JSContext *ctx, JSAtom prop, int def_flags) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; JSValue val; - int flags; if (def_flags & DEFINE_GLOBAL_LEX_VAR) { p = JS_VALUE_GET_OBJ(ctx->global_var_obj); - flags = JS_PROP_ENUMERABLE | (def_flags & JS_PROP_WRITABLE) | - JS_PROP_CONFIGURABLE; val = JS_UNINITIALIZED; } else { p = JS_VALUE_GET_OBJ(ctx->global_obj); - flags = JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | - (def_flags & JS_PROP_CONFIGURABLE); val = JS_NULL; } prs = find_own_property1(p, prop); if (prs) return 0; - if (!p->extensible) + if (p->stone) return 0; - pr = add_property(ctx, p, prop, flags); + pr = add_property(ctx, p, prop, 0); if (unlikely(!pr)) return -1; pr->u.value = val; return 0; } -/* 'def_flags' is 0 or JS_PROP_CONFIGURABLE. */ +/* Simplified global function definition */ static int JS_DefineGlobalFunction(JSContext *ctx, JSAtom prop, JSValueConst func, int def_flags) { - - JSObject *p; - JSShapeProperty *prs; - int flags; - - p = JS_VALUE_GET_OBJ(ctx->global_obj); - prs = find_own_property1(p, prop); - flags = JS_PROP_HAS_VALUE | JS_PROP_THROW; - if (!prs || (prs->flags & JS_PROP_CONFIGURABLE)) { - flags |= JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | def_flags | - JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_ENUMERABLE; - } - if (JS_DefineProperty(ctx, ctx->global_obj, prop, func, - JS_NULL, JS_NULL, flags) < 0) + (void)def_flags; + if (JS_SetPropertyInternal(ctx, ctx->global_obj, prop, func) < 0) return -1; return 0; } @@ -8078,15 +7241,11 @@ static int JS_GetGlobalVarRef(JSContext *ctx, JSAtom prop, JSValue *sp) p = JS_VALUE_GET_OBJ(ctx->global_var_obj); prs = find_own_property(&pr, p, prop); if (prs) { - /* XXX: conformance: do these tests in - OP_put_var_ref/OP_get_var_ref ? */ + /* Check for uninitialized lexical variable */ if (unlikely(JS_IsUninitialized(pr->u.value))) { JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return -1; } - if (unlikely(!(prs->flags & JS_PROP_WRITABLE))) { - return JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, prop); - } sp[0] = JS_DupValue(ctx, ctx->global_var_obj); } else { int ret; @@ -8143,19 +7302,12 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return -1; } - if (unlikely(!(prs->flags & JS_PROP_WRITABLE))) { - JS_FreeValue(ctx, val); - return JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, prop); - } } set_value(ctx, &pr->u.value, val); return 0; } - /* XXX: add a fast path where the property exists and the object - is not exotic. Otherwise do as in OP_put_ref_value and remove - JS_PROP_NO_ADD which is no longer necessary */ - flags = JS_PROP_THROW_STRICT | JS_PROP_NO_ADD; - return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, ctx->global_obj, flags); + + return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val); } /* return -1, FALSE or TRUE */ @@ -8175,16 +7327,13 @@ static int JS_DeleteGlobalVar(JSContext *ctx, JSAtom prop) if (ret < 0) return -1; if (ret) { - return JS_DeleteProperty(ctx, ctx->global_obj, prop, 0); + return JS_DeleteProperty(ctx, ctx->global_obj, prop); } else { return TRUE; } } -/* return -1, FALSE or TRUE. return FALSE if not configurable or - invalid object. return -1 in case of exception. - flags can be 0, JS_PROP_THROW or JS_PROP_THROW_STRICT */ -int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags) +int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) { JSValue obj1; JSObject *p; @@ -8192,11 +7341,8 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags) /* Arrays do not support property deletion */ if (JS_VALUE_GET_TAG(obj) == JS_TAG_ARRAY) { - if (flags & (JS_PROP_THROW | JS_PROP_THROW_STRICT)) { - JS_ThrowTypeError(ctx, "cannot delete array element"); - return -1; - } - return FALSE; + JS_ThrowTypeError(ctx, "cannot delete array element"); + return -1; } obj1 = JS_ToObject(ctx, obj); @@ -8207,29 +7353,9 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags) JS_FreeValue(ctx, obj1); if (res != FALSE) return res; - if (flags & JS_PROP_THROW || - flags & JS_PROP_THROW_STRICT) { - JS_ThrowTypeError(ctx, "could not delete property"); - return -1; - } - return FALSE; -} -int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int flags) -{ - JSAtom prop; - int res; - - if ((uint64_t)idx <= JS_ATOM_MAX_INT) { - /* fast path for fast arrays */ - return JS_DeleteProperty(ctx, obj, __JS_AtomFromUInt32(idx), flags); - } - prop = JS_NewAtomInt64(ctx, idx); - if (prop == JS_ATOM_NULL) - return -1; - res = JS_DeleteProperty(ctx, obj, prop, flags); - JS_FreeAtom(ctx, prop); - return res; + JS_ThrowTypeError(ctx, "could not delete property"); + return -1; } BOOL JS_IsFunction(JSContext *ctx, JSValueConst val) @@ -9319,9 +8445,7 @@ static BOOL is_ascii_ident(const JSString *p) static void js_print_atom(JSPrintValueState *s, JSAtom atom) { int i; - if (__JS_AtomIsTaggedInt(atom)) { - js_printf(s, "%u", __JS_AtomToUInt32(atom)); - } else if (atom == JS_ATOM_NULL) { + if (atom == JS_ATOM_NULL) { js_puts(s, ""); } else { assert(atom < s->rt->atom_size); @@ -9452,10 +8576,6 @@ static void js_print_object(JSPrintValueState *s, JSObject *p) j = 0; for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { if (prs->atom != JS_ATOM_NULL) { - if (!(prs->flags & JS_PROP_ENUMERABLE) && - !s->options.show_hidden) { - continue; - } if (j < s->options.max_item_count) { pr = &p->prop[i]; js_print_comma(s, &comma_state); @@ -10229,7 +9349,7 @@ static __exception int js_operator_delete(JSContext *ctx, JSValue *sp) atom = JS_ValueToAtom(ctx, op2); if (unlikely(atom == JS_ATOM_NULL)) return -1; - ret = JS_DeleteProperty(ctx, op1, atom, JS_PROP_THROW_STRICT); + ret = JS_DeleteProperty(ctx, op1, atom); JS_FreeAtom(ctx, atom); if (unlikely(ret < 0)) return -1; @@ -10251,26 +9371,6 @@ static JSValue js_throw_type_error(JSContext *ctx, JSValueConst this_val, #define GLOBAL_VAR_OFFSET 0x40000000 #define ARGUMENT_VAR_OFFSET 0x20000000 -static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst *argv) -{ - JSValue val; - int i, ret; - - val = JS_NewArray(ctx); - if (JS_IsException(val)) - return val; - for (i = first; i < argc; i++) { - ret = JS_DefinePropertyValueUint32(ctx, val, i - first, - JS_DupValue(ctx, argv[i]), - JS_PROP_C_W_E); - if (ret < 0) { - JS_FreeValue(ctx, val); - return JS_EXCEPTION; - } - } - return val; -} - /* Access an Array's internal JSValue array if available */ static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj, JSValue **arrpp, uint32_t *countp) @@ -10329,10 +9429,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, 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)) @@ -10340,8 +9437,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, if (setprop) ret = JS_SetProperty(ctx, target, tab_atom[i].atom, val); else - ret = JS_DefinePropertyValue(ctx, target, tab_atom[i].atom, val, - JS_PROP_C_W_E); + ret = JS_SetPropertyInternal(ctx, target, tab_atom[i].atom, val); if (ret < 0) goto exception; } @@ -10555,18 +9651,6 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, ret_val = func.generic_magic(ctx, this_obj, argc, arg_buf, p->u.cfunc.magic); break; - case JS_CFUNC_getter: - ret_val = func.getter(ctx, this_obj); - break; - case JS_CFUNC_setter: - ret_val = func.setter(ctx, this_obj, arg_buf[0]); - break; - case JS_CFUNC_getter_magic: - ret_val = func.getter_magic(ctx, this_obj, p->u.cfunc.magic); - break; - case JS_CFUNC_setter_magic: - ret_val = func.setter_magic(ctx, this_obj, arg_buf[0], p->u.cfunc.magic); - break; case JS_CFUNC_f_f: { double d1; @@ -11157,16 +10241,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } } BREAK; - CASE(OP_rest): - { - int first = get_u16(pc); - pc += 2; - *sp++ = js_build_rest(ctx, first, argc, (JSValueConst *)argv); - if (unlikely(JS_IsException(sp[-1]))) - goto exception; - } - BREAK; - CASE(OP_drop): JS_FreeValue(ctx, sp[-1]); sp--; @@ -11382,9 +10456,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, goto exception; /* Move args into the array, then null out stack slots. */ - for(i = 0; i < call_argc; i++) { - int r = JS_DefinePropertyValue(ctx, args, __JS_AtomFromUInt32(i), call_argv[i], - JS_PROP_C_W_E | JS_PROP_THROW); + for (i = 0; i < call_argc; i++) { + JSAtom prop = JS_NewAtomUInt32(ctx, i); + int r = JS_SetPropertyInternal(ctx, args, prop, call_argv[i]); + JS_FreeAtom(ctx, prop); call_argv[i] = JS_NULL; if (unlikely(r < 0)) { JS_FreeValue(ctx, args); @@ -11425,9 +10500,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (unlikely(JS_IsException(ret_val))) goto exception; call_argv = sp - call_argc; - for(i = 0; i < call_argc; i++) { - ret = JS_DefinePropertyValue(ctx, ret_val, __JS_AtomFromUInt32(i), call_argv[i], - JS_PROP_C_W_E | JS_PROP_THROW); + for (i = 0; i < call_argc; i++) { + JSAtom prop = JS_NewAtomUInt32(ctx, i); + ret = JS_SetPropertyInternal(ctx, ret_val, prop, call_argv[i]); + JS_FreeAtom(ctx, prop); call_argv[i] = JS_NULL; if (ret < 0) { JS_FreeValue(ctx, ret_val); @@ -11499,9 +10575,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); type = pc[4]; pc += 5; - if (type == JS_THROW_VAR_RO) - JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, atom); - else if (type == JS_THROW_VAR_REDECL) JS_ThrowSyntaxErrorVarRedeclaration(ctx, atom); else @@ -11947,8 +11020,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (!var_ref) goto exception; } - pr = add_property(ctx, JS_VALUE_GET_OBJ(sp[-1]), atom, - JS_PROP_WRITABLE | JS_PROP_VARREF); + pr = add_property(ctx, JS_VALUE_GET_OBJ(sp[-1]), atom, JS_PROP_VARREF); if (!pr) { free_var_ref(rt, var_ref); goto exception; @@ -12326,8 +11398,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, goto exception; } - ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1], sp[-2], - JS_PROP_THROW_STRICT); + ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1]); JS_FreeValue(ctx, sp[-2]); sp -= 2; if (unlikely(ret < 0)) @@ -12342,8 +11413,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); pc += 4; - ret = JS_DefinePropertyValue(ctx, sp[-2], atom, sp[-1], - JS_PROP_C_W_E | JS_PROP_THROW); + ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1]); sp--; if (unlikely(ret < 0)) goto exception; @@ -12357,7 +11427,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); pc += 4; - ret = JS_DefineObjectName(ctx, sp[-1], atom, JS_PROP_CONFIGURABLE); + ret = JS_DefineObjectName(ctx, sp[-1], atom); if (unlikely(ret < 0)) goto exception; } @@ -12365,7 +11435,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_set_name_computed): { int ret; - ret = JS_DefineObjectNameComputed(ctx, sp[-1], sp[-2], JS_PROP_CONFIGURABLE); + ret = JS_DefineObjectNameComputed(ctx, sp[-1], sp[-2]); if (unlikely(ret < 0)) goto exception; } @@ -12389,7 +11459,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSValue getter, setter, value; JSValueConst obj; JSAtom atom; - int flags, ret, op_flags; + int ret, op_flags; BOOL is_computed; #define OP_DEFINE_METHOD_METHOD 0 #define OP_DEFINE_METHOD_GETTER 1 @@ -12409,22 +11479,16 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, op_flags = *pc++; obj = sp[-2 - is_computed]; - flags = JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE | - JS_PROP_HAS_ENUMERABLE | JS_PROP_THROW; - if (op_flags & OP_DEFINE_METHOD_ENUMERABLE) - flags |= JS_PROP_ENUMERABLE; op_flags &= 3; value = JS_NULL; getter = JS_NULL; setter = JS_NULL; if (op_flags == OP_DEFINE_METHOD_METHOD) { value = sp[-1]; - flags |= JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE; } - ret = js_method_set_properties(ctx, sp[-1], atom, flags, obj); + ret = js_method_set_properties(ctx, sp[-1], atom, 0, obj); if (ret >= 0) { - ret = JS_DefineProperty(ctx, obj, atom, value, - getter, setter, flags); + ret = JS_SetProperty(ctx, obj, atom, value); } JS_FreeValue(ctx, sp[-1]); if (is_computed) { @@ -12587,7 +11651,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } sf->cur_pc = pc; - ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT); + ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1]); JS_FreeValue(ctx, sp[-3]); sp -= 3; if (unlikely(ret < 0)) @@ -12618,7 +11682,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_FreeAtom(ctx, atom); goto exception; } - ret = JS_SetPropertyInternal(ctx, sp[-3], atom, sp[-1], sp[-3], JS_PROP_THROW_STRICT); + ret = JS_SetPropertyInternal(ctx, sp[-3], atom, sp[-1]); JS_FreeAtom(ctx, atom); JS_FreeValue(ctx, sp[-2]); JS_FreeValue(ctx, sp[-3]); @@ -12631,8 +11695,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_define_array_el): { int ret; - ret = JS_DefinePropertyValueValue(ctx, sp[-3], JS_DupValue(ctx, sp[-2]), sp[-1], - JS_PROP_C_W_E | JS_PROP_THROW); + ret = JS_SetPropertyValue(ctx, sp[-3], JS_DupValue(ctx, sp[-2]), sp[-1]); sp -= 1; if (unlikely(ret < 0)) goto exception; @@ -13485,7 +12548,6 @@ enum { TOK_LOR, TOK_POW, TOK_ARROW, - TOK_ELLIPSIS, TOK_DOUBLE_QUESTION_MARK, TOK_QUESTION_MARK_DOT, TOK_ERROR, @@ -13503,7 +12565,6 @@ enum { TOK_DEF, TOK_THIS, TOK_DELETE, - TOK_VOID, TOK_NEW, TOK_IN, TOK_DO, @@ -14567,9 +13628,8 @@ static __exception int next_token(JSParseState *s) break; case '.': if (p[1] == '.' && p[2] == '.') { - p += 3; - s->token.val = TOK_ELLIPSIS; - break; + js_parse_error(s, "ellipsis (...) is not supported"); + goto fail; } if (p[1] >= '0' && p[1] <= '9') { goto parse_number; @@ -15470,7 +14530,7 @@ static __exception int emit_push_const(JSParseState *s, JSValueConst val, /* warning: JS_NewAtomStr frees the string value */ JS_DupValue(s->ctx, val); atom = JS_NewAtomStr(s->ctx, JS_VALUE_GET_STRING(val)); - if (atom != JS_ATOM_NULL && !__JS_AtomIsTaggedInt(atom)) { + if (atom != JS_ATOM_NULL) { emit_op(s, OP_push_atom_value); emit_u32(s, atom); return 0; @@ -15872,23 +14932,6 @@ static void push_break_entry(JSFunctionDef *fd, BlockEnv *be, int drop_count); static void pop_break_entry(JSFunctionDef *fd); -/* Note: all the fields are already sealed except length */ -static int seal_template_obj(JSContext *ctx, JSValueConst obj) -{ - JSObject *p; - JSShapeProperty *prs; - - p = JS_VALUE_GET_OBJ(obj); - prs = find_own_property1(p, JS_ATOM_length); - if (prs) { - if (js_update_property_flags(ctx, p, &prs, - prs->flags & ~(JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE))) - return -1; - } - p->extensible = FALSE; - return 0; -} - static __exception int js_parse_template(JSParseState *s, int call, int *argc) { JSContext *ctx = s->ctx; @@ -15912,8 +14955,7 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) raw_array = JS_NewArray(ctx); if (JS_IsException(raw_array)) return -1; - if (JS_DefinePropertyValue(ctx, template_object, JS_ATOM_raw, - raw_array, JS_PROP_THROW) < 0) { + if (JS_SetPropertyInternal(ctx, template_object, JS_ATOM_raw, raw_array) < 0) { return -1; } } @@ -15923,9 +14965,8 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) const uint8_t *p = s->token.ptr + 1; cooked = s->token; if (call) { - if (JS_DefinePropertyValueUint32(ctx, raw_array, depth, - JS_DupValue(ctx, s->token.u.str.str), - JS_PROP_ENUMERABLE | JS_PROP_THROW) < 0) { + if (JS_SetPropertyUint32(ctx, raw_array, depth, + JS_DupValue(ctx, s->token.u.str.str)) < 0) { return -1; } /* re-parse the string with escape sequences but do not throw a @@ -15934,9 +14975,8 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) if (js_parse_string(s, '`', FALSE, p, &cooked, &p)) { cooked.u.str.str = JS_NULL; } - if (JS_DefinePropertyValueUint32(ctx, template_object, depth, - cooked.u.str.str, - JS_PROP_ENUMERABLE | JS_PROP_THROW) < 0) { + if (JS_SetPropertyUint32(ctx, template_object, depth, + cooked.u.str.str) < 0) { return -1; } } else { @@ -15984,9 +15024,6 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) done: if (call) { - /* Seal the objects */ - seal_template_obj(ctx, raw_array); - seal_template_obj(ctx, template_object); *argc = depth + 1; } else if (depth > 1) { /* Use template_concat opcode to concatenate all parts */ @@ -16119,8 +15156,7 @@ static BOOL is_regexp_allowed(int tok) } #define SKIP_HAS_SEMI (1 << 0) -#define SKIP_HAS_ELLIPSIS (1 << 1) -#define SKIP_HAS_ASSIGNMENT (1 << 2) +#define SKIP_HAS_ASSIGNMENT (1 << 1) static BOOL has_lf_in_range(const uint8_t *p1, const uint8_t *p2) { @@ -16199,11 +15235,6 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ bits |= SKIP_HAS_SEMI; } break; - case TOK_ELLIPSIS: - if (level == 2) { - bits |= SKIP_HAS_ELLIPSIS; - } - break; case '=': bits |= SKIP_HAS_ASSIGNMENT; break; @@ -16319,19 +15350,6 @@ static __exception int js_parse_object_literal(JSParseState *s) /* specific case for getter/setter */ start_ptr = s->token.ptr; - if (s->token.val == TOK_ELLIPSIS) { - if (next_token(s)) - return -1; - if (js_parse_assign_expr(s)) - return -1; - emit_op(s, OP_null); /* dummy excludeList */ - emit_op(s, OP_copy_data_properties); - emit_u8(s, 2 | (1 << 2) | (0 << 5)); - emit_op(s, OP_drop); /* pop excludeList */ - emit_op(s, OP_drop); /* pop src object */ - goto next; - } - prop_type = js_parse_property_name(s, &name, TRUE, TRUE); if (prop_type < 0) goto fail; @@ -16430,7 +15448,7 @@ static __exception int js_parse_array_literal(JSParseState *s) /* small regular arrays are created on the stack */ idx = 0; while (s->token.val != ']' && idx < 32) { - if (s->token.val == ',' || s->token.val == TOK_ELLIPSIS) + if (s->token.val == ',') break; if (js_parse_assign_expr(s)) return -1; @@ -16449,14 +15467,15 @@ static __exception int js_parse_array_literal(JSParseState *s) /* larger arrays and holes are handled with explicit indices */ need_length = FALSE; while (s->token.val != ']' && idx < 0x7fffffff) { - if (s->token.val == TOK_ELLIPSIS) - break; need_length = TRUE; if (s->token.val != ',') { + JSAtom atom; if (js_parse_assign_expr(s)) return -1; + atom = JS_NewAtomUInt32(s->ctx, idx); emit_op(s, OP_define_field); - emit_u32(s, __JS_AtomFromUInt32(idx)); + emit_atom(s, atom); + JS_FreeAtom(s->ctx, atom); need_length = FALSE; } idx++; @@ -16466,51 +15485,14 @@ static __exception int js_parse_array_literal(JSParseState *s) return -1; } } - if (s->token.val == ']') { - if (need_length) { - /* Set the length: Cannot use OP_define_field because - length is not configurable */ - emit_op(s, OP_dup); - emit_op(s, OP_push_i32); - emit_u32(s, idx); - emit_op(s, OP_put_field); - emit_atom(s, JS_ATOM_length); - } - goto done; - } - - /* huge arrays and spread elements require a dynamic index on the stack */ - emit_op(s, OP_push_i32); - emit_u32(s, idx); - - /* stack has array, index */ - while (s->token.val != ']') { - if (s->token.val == TOK_ELLIPSIS) { - return js_parse_error(s, "spread syntax in array literals is not supported"); - } else { - need_length = TRUE; - if (s->token.val != ',') { - if (js_parse_assign_expr(s)) - return -1; - /* a idx val */ - emit_op(s, OP_define_array_el); - need_length = FALSE; - } - emit_op(s, OP_inc); - } - if (s->token.val != ',') - break; - if (next_token(s)) - return -1; - } if (need_length) { - /* Set the length: cannot use OP_define_field because + /* Set the length: Cannot use OP_define_field because length is not configurable */ - emit_op(s, OP_dup1); /* array length - array array length */ + emit_op(s, OP_dup); + emit_op(s, OP_push_i32); + emit_u32(s, idx); emit_op(s, OP_put_field); emit_atom(s, JS_ATOM_length); - } else { - emit_op(s, OP_drop); /* array length - array */ } done: return js_parse_expect(s, ']'); @@ -16829,7 +15811,7 @@ fail: /* Return -1 if error, 0 if no initializer, 1 if an initializer is present at the top level. */ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, - int hasval, int has_ellipsis, + int hasval, BOOL allow_initializer, BOOL export_flag) { int label_parse, label_assign, label_done, label_lvalue, depth_lvalue; @@ -16838,12 +15820,6 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, int opcode, scope, tok1, skip_bits; BOOL has_initializer; - if (has_ellipsis < 0) { - /* pre-parse destructuration target for spread detection */ - js_parse_skip_parens_token(s, &skip_bits, FALSE); - has_ellipsis = skip_bits & SKIP_HAS_ELLIPSIS; - } - label_parse = new_label(s); label_assign = new_label(s); @@ -16867,54 +15843,8 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, return -1; /* throw an exception if the value cannot be converted to an object */ emit_op(s, OP_to_object); - if (has_ellipsis) { - /* add excludeList on stack just below src object */ - emit_op(s, OP_object); - emit_op(s, OP_swap); - } while (s->token.val != '}') { int prop_type; - if (s->token.val == TOK_ELLIPSIS) { - if (!has_ellipsis) { - JS_ThrowInternalError(s->ctx, "unexpected ellipsis token"); - return -1; - } - if (next_token(s)) - return -1; - if (tok) { - var_name = js_parse_destructuring_var(s, tok, is_arg); - if (var_name == JS_ATOM_NULL) - return -1; - if (need_var_reference(s, tok)) { - /* Must make a reference for proper `with` semantics */ - emit_op(s, OP_scope_get_var); - emit_atom(s, var_name); - emit_u16(s, s->cur_func->scope_level); - JS_FreeAtom(s->ctx, var_name); - goto lvalue0; - } else { - opcode = OP_scope_get_var; - scope = s->cur_func->scope_level; - label_lvalue = -1; - depth_lvalue = 0; - } - } else { - if (js_parse_left_hand_side_expr(s)) - return -1; - lvalue0: - if (get_lvalue(s, &opcode, &scope, &var_name, - &label_lvalue, &depth_lvalue, FALSE, '{')) - return -1; - } - if (s->token.val != '}') { - js_parse_error(s, "assignment rest property must be last"); - goto var_error; - } - emit_op(s, OP_object); /* target */ - emit_op(s, OP_copy_data_properties); - emit_u8(s, 0 | ((depth_lvalue + 1) << 2) | ((depth_lvalue + 2) << 5)); - goto set_val; - } prop_type = js_parse_property_name(s, &prop_name, FALSE, TRUE); if (prop_type < 0) return -1; @@ -16927,31 +15857,15 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, tok1 == '=' || tok1 == '}')) { if (prop_name == JS_ATOM_NULL) { /* computed property name on stack */ - if (has_ellipsis) { - /* define the property in excludeList */ - emit_op(s, OP_to_propkey); /* avoid calling ToString twice */ - emit_op(s, OP_perm3); /* TOS: src excludeList prop */ - emit_op(s, OP_null); /* TOS: src excludeList prop null */ - emit_op(s, OP_define_array_el); /* TOS: src excludeList prop */ - emit_op(s, OP_perm3); /* TOS: excludeList src prop */ - } /* get the computed property from the source object */ emit_op(s, OP_get_array_el2); } else { /* named property */ - if (has_ellipsis) { - /* define the property in excludeList */ - emit_op(s, OP_swap); /* TOS: src excludeList */ - emit_op(s, OP_null); /* TOS: src excludeList null */ - emit_op(s, OP_define_field); /* TOS: src excludeList */ - emit_atom(s, prop_name); - emit_op(s, OP_swap); /* TOS: excludeList src */ - } /* get the named property from the source object */ emit_op(s, OP_get_field2); emit_u32(s, prop_name); } - if (js_parse_destructuring_element(s, tok, is_arg, TRUE, -1, TRUE, export_flag) < 0) + if (js_parse_destructuring_element(s, tok, is_arg, TRUE, TRUE, export_flag) < 0) return -1; if (s->token.val == '}') break; @@ -16962,24 +15876,9 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, } if (prop_name == JS_ATOM_NULL) { emit_op(s, OP_to_propkey); - if (has_ellipsis) { - /* define the property in excludeList */ - emit_op(s, OP_perm3); - emit_op(s, OP_null); - emit_op(s, OP_define_array_el); - emit_op(s, OP_perm3); - } /* source prop -- source source prop */ emit_op(s, OP_dup1); } else { - if (has_ellipsis) { - /* define the property in excludeList */ - emit_op(s, OP_swap); - emit_op(s, OP_null); - emit_op(s, OP_define_field); - emit_atom(s, prop_name); - emit_op(s, OP_swap); - } /* source -- source source */ emit_op(s, OP_dup); } @@ -17062,14 +15961,6 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, js_parse_error(s, "invalid destructuring target"); goto prop_error; } - if (has_ellipsis) { - /* define the property in excludeList */ - emit_op(s, OP_swap); - emit_op(s, OP_null); - emit_op(s, OP_define_field); - emit_atom(s, prop_name); - emit_op(s, OP_swap); - } if (!tok || need_var_reference(s, tok)) { /* generate reference */ /* source -- source source */ @@ -17085,13 +15976,12 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, scope = s->cur_func->scope_level; label_lvalue = -1; depth_lvalue = 0; - + /* source -- source val */ emit_op(s, OP_get_field2); emit_u32(s, prop_name); } } - set_val: if (tok) { if (js_define_var(s, var_name, tok)) goto var_error; @@ -17124,9 +16014,6 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, } /* drop the source object */ emit_op(s, OP_drop); - if (has_ellipsis) { - emit_op(s, OP_drop); /* pop excludeList */ - } if (next_token(s)) return -1; } else if (s->token.val == '[') { @@ -17473,8 +16360,6 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) if (arg_count >= 65535) { return js_parse_error(s, "Too many call arguments"); } - if (s->token.val == TOK_ELLIPSIS) - return js_parse_error(s, "spread syntax in function calls is not supported"); if (js_parse_assign_expr(s)) return -1; arg_count++; @@ -17654,7 +16539,6 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) case '-': case '!': case '~': - case TOK_VOID: op_token_ptr = s->token.ptr; op = s->token.val; if (next_token(s)) @@ -17677,10 +16561,6 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) emit_source_pos(s, op_token_ptr); emit_op(s, OP_not); break; - case TOK_VOID: - emit_op(s, OP_drop); - emit_op(s, OP_null); - break; default: abort(); } @@ -18007,7 +16887,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) s->token.ptr); } else if ((s->token.val == '{' || s->token.val == '[') && js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') { - if (js_parse_destructuring_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE, FALSE) < 0) + if (js_parse_destructuring_element(s, 0, 0, FALSE, TRUE, FALSE) < 0) return -1; return 0; } @@ -18340,7 +17220,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, if ((s->token.val == '[' || s->token.val == '{') && js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') { emit_op(s, OP_null); - if (js_parse_destructuring_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE, export_flag) < 0) + if (js_parse_destructuring_element(s, tok, 0, TRUE, TRUE, export_flag) < 0) return -1; } else { return js_parse_error(s, "variable name expected"); @@ -18932,7 +17812,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) { if (s->token.val == '[' || s->token.val == '{') { /* catch variables behave like var (block scoped) */ - if (js_parse_destructuring_element(s, TOK_VAR, 0, TRUE, -1, TRUE, FALSE) < 0) + if (js_parse_destructuring_element(s, TOK_VAR, 0, TRUE, TRUE, FALSE) < 0) goto fail; } else { js_parse_error(s, "identifier expected"); @@ -20770,8 +19650,6 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy int flags; flags = 0; - if (s->eval_type != JS_EVAL_TYPE_GLOBAL) - flags |= JS_PROP_CONFIGURABLE; if (hf->cpool_idx >= 0 && !hf->is_lexical) { /* global function definitions need a specific handling */ dbuf_putc(bc, OP_fclosure); @@ -20785,8 +19663,6 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy } else { if (hf->is_lexical) { flags |= DEFINE_GLOBAL_LEX_VAR; - if (!hf->is_const) - flags |= JS_PROP_WRITABLE; } dbuf_putc(bc, OP_define_var); dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name)); @@ -23000,29 +21876,15 @@ static __exception int js_parse_function_decl2(JSParseState *s, while (s->token.val != ')') { JSAtom name; - BOOL rest = FALSE; int idx, has_initializer; - if (s->token.val == TOK_ELLIPSIS) { - if (func_type == JS_PARSE_FUNC_SETTER) - goto fail_accessor; - fd->has_simple_parameter_list = FALSE; - rest = TRUE; - if (next_token(s)) - goto fail; - } if (s->token.val == '[' || s->token.val == '{') { fd->has_simple_parameter_list = FALSE; - if (rest) { - emit_op(s, OP_rest); - emit_u16(s, fd->arg_count); - } else { - /* unnamed arg for destructuring */ - idx = add_arg(ctx, fd, JS_ATOM_NULL); - emit_op(s, OP_get_arg); - emit_u16(s, idx); - } - has_initializer = js_parse_destructuring_element(s, TOK_VAR, 1, TRUE, -1, TRUE, FALSE); + /* unnamed arg for destructuring */ + idx = add_arg(ctx, fd, JS_ATOM_NULL); + emit_op(s, OP_get_arg); + emit_u16(s, idx); + has_initializer = js_parse_destructuring_element(s, TOK_VAR, 1, TRUE, TRUE, FALSE); if (has_initializer < 0) goto fail; if (has_initializer) @@ -23041,26 +21903,12 @@ static __exception int js_parse_function_decl2(JSParseState *s, if (define_var(s, fd, name, JS_VAR_DEF_LET) < 0) goto fail; } - /* XXX: could avoid allocating an argument if rest is true */ idx = add_arg(ctx, fd, name); if (idx < 0) goto fail; if (next_token(s)) goto fail; - if (rest) { - emit_op(s, OP_rest); - emit_u16(s, idx); - if (fd->has_parameter_expressions) { - emit_op(s, OP_dup); - emit_op(s, OP_scope_put_var_init); - emit_atom(s, name); - emit_u16(s, fd->scope_level); - } - emit_op(s, OP_put_arg); - emit_u16(s, idx); - fd->has_simple_parameter_list = FALSE; - has_opt_arg = TRUE; - } else if (s->token.val == '=') { + if (s->token.val == '=') { int label; fd->has_simple_parameter_list = FALSE; @@ -23104,10 +21952,6 @@ static __exception int js_parse_function_decl2(JSParseState *s, js_parse_error(s, "missing formal parameter"); goto fail; } - if (rest && s->token.val != ')') { - js_parse_expect(s, ')'); - goto fail; - } if (s->token.val == ')') break; if (js_parse_expect(s, ',')) @@ -23762,7 +22606,7 @@ static int bc_atom_to_idx(BCWriterState *s, uint32_t *pres, JSAtom atom) { uint32_t v; - if (atom < s->first_atom || __JS_AtomIsTaggedInt(atom)) { + if (atom < s->first_atom) { *pres = atom; return 0; } @@ -23802,13 +22646,9 @@ static int bc_put_atom(BCWriterState *s, JSAtom atom) { uint32_t v; - if (__JS_AtomIsTaggedInt(atom)) { - v = (__JS_AtomToUInt32(atom) << 1) | 1; - } else { - if (bc_atom_to_idx(s, &v, atom)) - return -1; - v <<= 1; - } + if (bc_atom_to_idx(s, &v, atom)) + return -1; + v <<= 1; bc_put_leb128(s, v); return 0; } @@ -24024,7 +22864,7 @@ static int JS_WriteArray(BCWriterState *s, JSValueConst obj) int ret; BOOL is_template; - if (s->allow_bytecode && !p->extensible) { + if (s->allow_bytecode && p->stone) { /* not extensible array: we consider it is a template when we are saving bytecode */ bc_put_u8(s, BC_TAG_TEMPLATE_OBJECT); @@ -24077,8 +22917,7 @@ static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj) for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { atom = pr->atom; if (atom != JS_ATOM_NULL && - JS_AtomIsString(s->ctx, atom) && - (pr->flags & JS_PROP_ENUMERABLE)) { + JS_AtomIsString(s->ctx, atom)) { if (pr->flags & JS_PROP_TMASK) { JS_ThrowTypeError(s->ctx, "only value properties are supported"); goto fail; @@ -24466,9 +23305,7 @@ static int bc_idx_to_atom(BCReaderState *s, JSAtom *patom, uint32_t idx) { JSAtom atom; - if (__JS_AtomIsTaggedInt(idx)) { - atom = idx; - } else if (idx < s->first_atom) { + if (idx < s->first_atom) { atom = JS_DupAtom(s->ctx, idx); } else { idx -= s->first_atom; @@ -24490,8 +23327,9 @@ static int bc_get_atom(BCReaderState *s, JSAtom *patom) if (bc_get_leb128(s, &v)) return -1; if (v & 1) { - *patom = __JS_AtomFromUInt32(v >> 1); - return 0; + /* Old bytecode format with tagged int atoms - convert to string atom */ + *patom = JS_NewAtomUInt32(s->ctx, v >> 1); + return (*patom == JS_ATOM_NULL) ? -1 : 0; } else { return bc_idx_to_atom(s, patom, v >> 1); } @@ -24843,7 +23681,7 @@ static JSValue JS_ReadObjectTag(BCReaderState *s) JS_FreeAtom(ctx, atom); goto fail; } - ret = JS_DefinePropertyValue(ctx, obj, atom, val, JS_PROP_C_W_E); + ret = JS_SetPropertyInternal(ctx, obj, atom, val); JS_FreeAtom(ctx, atom); if (ret < 0) goto fail; @@ -25178,14 +24016,9 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj, abort(); } JS_FreeAtom(ctx, atom1); - if (atom == JS_ATOM_Symbol_toPrimitive) { - /* Symbol.toPrimitive functions are not writable */ - prop_flags = JS_PROP_CONFIGURABLE; } - } break; case JS_DEF_CFUNC: - if (atom == JS_ATOM_Symbol_toPrimitive) prop_flags = JS_PROP_CONFIGURABLE; val = JS_NewCFunction2(ctx, e->u.func.cfunc.generic, e->name, e->u.func.length, e->u.func.cproto, e->magic); break; @@ -25213,7 +24046,7 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj, default: abort(); } - JS_DefinePropertyValue(ctx, obj, atom, val, prop_flags); + JS_SetPropertyInternal(ctx, obj, atom, val); return 0; } @@ -25258,6 +24091,7 @@ static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val) return obj; } +// TODO: This needs to only return text atoms static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1, int flags) { @@ -25279,26 +24113,11 @@ static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1, goto exception; for(j = i = 0; i < len; i++) { JSAtom atom = atoms[i].atom; - if (flags & JS_GPN_ENUM_ONLY) { - JSPropertyDescriptor desc; - int res; - - /* Check if property is still enumerable */ - res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom); - if (res < 0) - goto exception; - if (!res) - continue; - js_free_desc(ctx, &desc); - if (!(desc.flags & JS_PROP_ENUMERABLE)) - continue; - } - val = JS_AtomToValue(ctx, atom); - if (JS_IsException(val)) - goto exception; - - if (JS_CreateDataPropertyUint32(ctx, r, j++, val, 0) < 0) + val = JS_AtomToValue(ctx, atom); + if (JS_IsException(val)) goto exception; + + JS_ArrayPush(ctx, r, val); } goto done; @@ -25313,57 +24132,6 @@ done: return r; } -static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int freeze_flag) -{ - JSValueConst obj = argv[0]; - JSObject *p; - JSPropertyEnum *props; - uint32_t len, i; - int flags, desc_flags, res; - - if (!JS_IsObject(obj)) - return JS_DupValue(ctx, obj); - - res = JS_PreventExtensions(ctx, obj); - if (res < 0) - return JS_EXCEPTION; - if (!res) { - return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false"); - } - - p = JS_VALUE_GET_OBJ(obj); - flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK; - if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, flags)) - return JS_EXCEPTION; - - for(i = 0; i < len; i++) { - JSPropertyDescriptor desc; - JSAtom prop = props[i].atom; - - desc_flags = JS_PROP_THROW | JS_PROP_HAS_CONFIGURABLE; - if (freeze_flag) { - res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); - if (res < 0) - goto exception; - if (res) { - if (desc.flags & JS_PROP_WRITABLE) - desc_flags |= JS_PROP_HAS_WRITABLE; - js_free_desc(ctx, &desc); - } - } - if (JS_DefineProperty(ctx, obj, prop, JS_NULL, - JS_NULL, JS_NULL, desc_flags) < 0) - goto exception; - } - JS_FreePropertyEnum(ctx, props, len); - return JS_DupValue(ctx, obj); - - exception: - JS_FreePropertyEnum(ctx, props, len); - return JS_EXCEPTION; -} - /* Function class */ static JSValue js_function_proto(JSContext *ctx, JSValueConst this_val, @@ -25500,8 +24268,7 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst this_val, msg = JS_ToString(ctx, message); if (unlikely(JS_IsException(msg))) goto exception; - JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, msg, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyInternal(ctx, obj, JS_ATOM_message, msg); } if (arg_index < argc) { @@ -25514,8 +24281,7 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst this_val, JSValue cause = JS_GetProperty(ctx, options, JS_ATOM_cause); if (JS_IsException(cause)) goto exception; - JS_DefinePropertyValue(ctx, obj, JS_ATOM_cause, cause, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyInternal(ctx, obj, JS_ATOM_cause, cause); } } } @@ -25536,7 +24302,7 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, error_list); goto exception; } - if (JS_DefinePropertyValueUint32(ctx, error_list, i, item, JS_PROP_C_W_E) < 0) { + if (JS_SetPropertyUint32(ctx, error_list, i, item) < 0) { JS_FreeValue(ctx, error_list); goto exception; } @@ -25546,8 +24312,7 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst this_val, if (JS_IsException(error_list)) goto exception; } - JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, error_list, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyInternal(ctx, obj, JS_ATOM_errors, error_list); } /* skip the Error() function in the backtrace */ @@ -25727,8 +24492,7 @@ static JSValue js_regexp_constructor_internal(JSContext *ctx, re = &p->u.regexp; re->pattern = JS_VALUE_GET_STRING(pattern); re->bytecode = JS_VALUE_GET_STRING(bc); - JS_DefinePropertyValue(ctx, obj, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0), - JS_PROP_WRITABLE); + JS_SetPropertyInternal(ctx, obj, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)); return obj; } @@ -25987,7 +24751,6 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, goto fail; } } else { - int prop_flags; if (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) { if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, JS_NewInt32(ctx, (capture[1] - str_buf) >> shift)) < 0) @@ -25996,7 +24759,6 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, obj = JS_NewArray(ctx); if (JS_IsException(obj)) goto fail; - prop_flags = JS_PROP_C_W_E | JS_PROP_THROW; group_name_ptr = lre_get_groupnames(re_bytecode); if (group_name_ptr) { groups = JS_NewObjectProto(ctx, JS_NULL); @@ -26037,29 +24799,25 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, val = JS_NewArray(ctx); if (JS_IsException(val)) goto fail; - if (JS_DefinePropertyValueUint32(ctx, val, 0, - JS_NewInt32(ctx, start), - prop_flags) < 0) { + if (JS_SetPropertyUint32(ctx, val, 0, + JS_NewInt32(ctx, start)) < 0) { JS_FreeValue(ctx, val); goto fail; } - if (JS_DefinePropertyValueUint32(ctx, val, 1, - JS_NewInt32(ctx, end), - prop_flags) < 0) { + if (JS_SetPropertyUint32(ctx, val, 1, JS_NewInt32(ctx, end)) < 0) { JS_FreeValue(ctx, val); goto fail; } } if (name && !JS_IsNull(indices_groups)) { val = JS_DupValue(ctx, val); - if (JS_DefinePropertyValueStr(ctx, indices_groups, - name, val, prop_flags) < 0) { + if (JS_SetPropertyStr(ctx, indices_groups, + name, val) < 0) { JS_FreeValue(ctx, val); goto fail; } } - if (JS_DefinePropertyValueUint32(ctx, indices, i, val, - prop_flags) < 0) { + if (JS_SetPropertyUint32(ctx, indices, i, val) < 0) { goto fail; } } @@ -26072,15 +24830,14 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, } if (name) { - if (JS_DefinePropertyValueStr(ctx, groups, name, - JS_DupValue(ctx, val), - prop_flags) < 0) { + if (JS_SetPropertyStr(ctx, groups, name, + JS_DupValue(ctx, val)) < 0) { JS_FreeValue(ctx, val); goto fail; } } - if (JS_DefinePropertyValueUint32(ctx, obj, i, val, prop_flags) < 0) + if (JS_SetPropertyUint32(ctx, obj, i, val) < 0) goto fail; } @@ -26264,9 +25021,8 @@ void JS_AddIntrinsicRegExp(JSContext *ctx) countof(js_regexp_proto_funcs)); obj = JS_NewCFunction2(ctx, js_regexp_constructor, "RegExp", 2, JS_CFUNC_generic, 0); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "RegExp", - JS_DupValue(ctx, obj), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "RegExp", + JS_DupValue(ctx, obj)); ctx->regexp_ctor = obj; } @@ -26320,8 +25076,7 @@ static JSValue json_parse_value(JSParseState *s) JS_FreeAtom(ctx, prop_name); goto fail; } - ret = JS_DefinePropertyValue(ctx, val, prop_name, - prop_val, JS_PROP_C_W_E); + ret = JS_SetPropertyInternal(ctx, val, prop_name, prop_val); JS_FreeAtom(ctx, prop_name); if (ret < 0) goto fail; @@ -26354,7 +25109,7 @@ static JSValue json_parse_value(JSParseState *s) el = json_parse_value(s); if (JS_IsException(el)) goto fail; - ret = JS_DefinePropertyValueUint32(ctx, val, idx, el, JS_PROP_C_W_E); + ret = JS_SetPropertyUint32(ctx, val, idx, el); if (ret < 0) goto fail; if (s->token.val != ',') @@ -26487,9 +25242,9 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, goto fail; } if (JS_IsNull(new_el)) { - ret = JS_DeleteProperty(ctx, val, prop, 0); + ret = JS_DeleteProperty(ctx, val, prop); } else { - ret = JS_DefinePropertyValue(ctx, val, prop, new_el, JS_PROP_C_W_E); + ret = JS_SetPropertyInternal(ctx, val, prop, new_el); } JS_FreeAtom(ctx, prop); if (ret < 0) @@ -26535,8 +25290,7 @@ static JSValue js_json_parse(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, obj); return JS_EXCEPTION; } - if (JS_DefinePropertyValue(ctx, root, JS_ATOM_empty_string, obj, - JS_PROP_C_W_E) < 0) { + if (JS_SetPropertyInternal(ctx, root, JS_ATOM_empty_string, obj) < 0) { JS_FreeValue(ctx, root); return JS_EXCEPTION; } @@ -26870,8 +25624,8 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, wrapper = JS_NewObject(ctx); if (JS_IsException(wrapper)) goto exception; - if (JS_DefinePropertyValue(ctx, wrapper, JS_ATOM_empty_string, - JS_DupValue(ctx, obj), JS_PROP_C_W_E) < 0) + if (JS_SetPropertyInternal(ctx, wrapper, JS_ATOM_empty_string, + JS_DupValue(ctx, obj)) < 0) goto exception; val = JS_DupValue(ctx, obj); @@ -26911,11 +25665,11 @@ static JSValue js_json_stringify(JSContext *ctx, JSValueConst this_val, static const JSCFunctionListEntry js_json_funcs[] = { JS_CFUNC_DEF("parse", 2, js_json_parse ), JS_CFUNC_DEF("stringify", 3, js_json_stringify ), - JS_PROP_STRING_DEF("[Symbol.toStringTag]", "JSON", JS_PROP_CONFIGURABLE ), + JS_PROP_STRING_DEF("[Symbol.toStringTag]", "JSON", 0 ), }; static const JSCFunctionListEntry js_json_obj[] = { - JS_OBJECT_DEF("JSON", js_json_funcs, countof(js_json_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), + JS_OBJECT_DEF("JSON", js_json_funcs, countof(js_json_funcs), 0 ), }; void JS_AddIntrinsicJSON(JSContext *ctx) @@ -28667,7 +27421,7 @@ static JSValue js_cell_text_extract(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } - JS_DefinePropertyValueUint32(ctx, arr, 0, match, JS_PROP_C_W_E); + JS_SetPropertyUint32(ctx, arr, 0, match); /* str removed - arg not owned */ return arr; @@ -30382,103 +29136,36 @@ int js_is_blob(JSContext *js, JSValue v) * stone() function - deep freeze with blob support * ============================================================================ */ -static JSValue js_cell_stone_deep(JSContext *ctx, JSValueConst obj) -{ - /* Handle blob specially */ - blob *bd = js_get_blob(ctx, obj); - if (bd) { - if (!bd->is_stone) - blob_make_stone(bd); - return JS_DupValue(ctx, obj); - } - - /* Handle non-objects (primitives are already immutable) */ - if (!JS_IsObject(obj)) - return JS_DupValue(ctx, obj); - - /* Get all property keys */ - JSPropertyEnum *tab; - uint32_t len; - if (JS_GetOwnPropertyNames(ctx, &tab, &len, obj, - JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK | JS_GPN_ENUM_ONLY) < 0) { - return JS_EXCEPTION; - } - - /* Recursively freeze all properties */ - for (uint32_t i = 0; i < len; i++) { - JSValue val = JS_GetProperty(ctx, obj, tab[i].atom); - if (JS_IsException(val)) { - for (uint32_t j = i; j < len; j++) - JS_FreeAtom(ctx, tab[j].atom); - js_free(ctx, tab); - return JS_EXCEPTION; - } - - if (JS_IsObject(val) || JS_IsFunction(ctx, val)) { - JSValue frozen = js_cell_stone_deep(ctx, val); - JS_FreeValue(ctx, val); - if (JS_IsException(frozen)) { - for (uint32_t j = i; j < len; j++) - JS_FreeAtom(ctx, tab[j].atom); - js_free(ctx, tab); - return JS_EXCEPTION; - } - JS_FreeValue(ctx, frozen); - } else { - JS_FreeValue(ctx, val); - } - - JS_FreeAtom(ctx, tab[i].atom); - } - js_free(ctx, tab); - - /* Freeze the object itself */ - JSValue args[1] = { JS_DupValue(ctx, obj) }; - JSValue result = js_object_seal(ctx, JS_NULL, 1, args, 1); /* freeze */ - JS_FreeValue(ctx, args[0]); - - if (JS_IsException(result)) - return result; - JS_FreeValue(ctx, result); - - return JS_DupValue(ctx, obj); -} - /* stone(object) - deep freeze an object */ static JSValue js_cell_stone(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { if (argc < 1) return JS_NULL; - return js_cell_stone_deep(ctx, argv[0]); -} - -/* stone.p(object) - check if object is frozen/stone */ -static JSValue js_cell_stone_p(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - if (argc < 1) - return JS_FALSE; JSValue obj = argv[0]; - /* Check blob */ blob *bd = js_get_blob(ctx, obj); - if (bd) - return JS_NewBool(ctx, bd->is_stone); + if (bd) { + bd->is_stone = true; + return JS_DupValue(ctx, obj); + } - /* Non-objects are immutable by nature */ - if (!JS_IsObject(obj)) - return JS_TRUE; + if (JS_IsObject(obj)) { + JSObject *p = JS_VALUE_GET_OBJ(obj); + p->stone = TRUE; + return JS_DupValue(ctx, obj); + } - /* Check if object is frozen */ - return JS_NewBool(ctx, JS_IsExtensible(ctx, obj) == 0); + if (JS_IsArray(ctx, obj)) { + JSArray *p = JS_VALUE_GET_ARRAY(obj); + p->stone = TRUE; + return JS_DupValue(ctx, obj); + } + + return JS_NULL; } -static const JSCFunctionListEntry js_cell_stone_funcs[] = { - JS_CFUNC_DEF("p", 1, js_cell_stone_p), -}; - /* ============================================================================ * reverse() function - reverse an array * ============================================================================ */ @@ -30971,20 +29658,28 @@ static JSValue js_cell_is_object(JSContext *ctx, JSValueConst this_val, static JSValue js_cell_is_stone(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - if (argc < 1) return JS_FALSE; - JSValue val = argv[0]; + if (argc < 1) + return JS_FALSE; + + JSValue obj = argv[0]; /* Check blob */ - blob *bd = js_get_blob(ctx, val); + blob *bd = js_get_blob(ctx, obj); if (bd) return JS_NewBool(ctx, bd->is_stone); - /* Primitives are always stone */ - if (!JS_IsObject(val)) - return JS_TRUE; + /* Non-objects are immutable by nature */ + if (JS_IsObject(obj)) { + JSObject *p = JS_VALUE_GET_OBJ(obj); + return JS_NewBool(ctx, p->stone); + } - /* Check frozen */ - return JS_NewBool(ctx, JS_IsExtensible(ctx, val) == 0); + if (JS_IsArray(ctx, obj)) { + JSArray *p = JS_VALUE_GET_ARRAY(obj); + return JS_NewBool(ctx, p->stone); + } + + return JS_NewBool(ctx, true); } /* is_text(val) */ @@ -31075,12 +29770,10 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx) 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); + JS_SetPropertyInternal(ctx, proto, JS_ATOM_name, + JS_NewAtomString(ctx, native_error_name[i])); + JS_SetPropertyInternal(ctx, proto, JS_ATOM_message, + JS_AtomToString(ctx, JS_ATOM_empty_string)); ctx->native_error_proto[i] = proto; } } @@ -31092,22 +29785,14 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) JSValue obj1; ctx->throw_type_error = JS_NewCFunction(ctx, js_throw_type_error, NULL, 0); - - /* add caller property to throw a TypeError */ - JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_caller, JS_NULL, - ctx->throw_type_error, ctx->throw_type_error, - JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE); - JS_FreeValue(ctx, js_object_seal(ctx, JS_NULL, 1, (JSValueConst *)&ctx->throw_type_error, 1)); - ctx->global_obj = JS_NewObject(ctx); ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL); /* Error */ obj1 = JS_NewCFunctionMagic(ctx, js_error_constructor, "Error", 1, JS_CFUNC_generic_magic, -1); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "Error", - JS_DupValue(ctx, obj1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "Error", + JS_DupValue(ctx, obj1)); JS_FreeValue(ctx, obj1); for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { @@ -31117,34 +29802,28 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) func_obj = JS_NewCFunctionMagic(ctx, js_error_constructor, native_error_name[i], n_args, JS_CFUNC_generic_magic, i); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, native_error_name[i], - JS_DupValue(ctx, func_obj), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, native_error_name[i], + JS_DupValue(ctx, func_obj)); JS_FreeValue(ctx, func_obj); } /* global properties */ - JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis, - JS_DupValue(ctx, ctx->global_obj), - JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); + JS_SetPropertyInternal(ctx, ctx->global_obj, JS_ATOM_globalThis, + JS_DupValue(ctx, ctx->global_obj)); /* Cell Script global functions: text, number, array, object, fn */ { JSValue text_func = JS_NewCFunction(ctx, js_cell_text, "text", 2); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "text", text_func, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "text", text_func); JSValue number_func = JS_NewCFunction(ctx, js_cell_number, "number", 2); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "number", number_func, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "number", number_func); JSValue array_func = JS_NewCFunction(ctx, js_cell_array, "array", 4); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "array", array_func, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "array", array_func); JSValue object_func = JS_NewCFunction(ctx, js_cell_object, "object", 2); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "object", object_func, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "object", object_func); /* Blob intrinsic type */ { @@ -31159,191 +29838,134 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) JSValue blob_ctor = JS_NewCFunction2(ctx, js_blob_constructor, "blob", 3, JS_CFUNC_generic, 0); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "blob", blob_ctor, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "blob", blob_ctor); } /* stone() function */ - JSValue stone_func = JS_NewCFunction(ctx, js_cell_stone, "stone", 1); - JS_SetPropertyFunctionList(ctx, stone_func, js_cell_stone_funcs, countof(js_cell_stone_funcs)); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "stone", stone_func, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "stone", JS_NewCFunction(ctx, js_cell_stone, "stone", 1)); /* length() function */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "length", - JS_NewCFunction(ctx, js_cell_length, "length", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "length", + JS_NewCFunction(ctx, js_cell_length, "length", 1)); /* call() function */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "call", - JS_NewCFunction(ctx, js_cell_call, "call", 3), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "call", + JS_NewCFunction(ctx, js_cell_call, "call", 3)); /* is_* type checking functions */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_array", - JS_NewCFunction(ctx, js_cell_is_array, "is_array", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_blob", - JS_NewCFunction(ctx, js_cell_is_blob, "is_blob", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_data", - JS_NewCFunction(ctx, js_cell_is_data, "is_data", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_function", - JS_NewCFunction(ctx, js_cell_is_function, "is_function", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_logical", - JS_NewCFunction(ctx, js_cell_is_logical, "is_logical", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_integer", - JS_NewCFunction(ctx, js_cell_is_integer, "is_integer", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_null", - JS_NewCFunction(ctx, js_cell_is_null, "is_null", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_number", - JS_NewCFunction(ctx, js_cell_is_number, "is_number", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_object", - JS_NewCFunction(ctx, js_cell_is_object, "is_object", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_stone", - JS_NewCFunction(ctx, js_cell_is_stone, "is_stone", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_text", - JS_NewCFunction(ctx, js_cell_is_text, "is_text", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_proto", - JS_NewCFunction(ctx, js_cell_is_proto, "is_proto", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_array", + JS_NewCFunction(ctx, js_cell_is_array, "is_array", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_blob", + JS_NewCFunction(ctx, js_cell_is_blob, "is_blob", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_data", + JS_NewCFunction(ctx, js_cell_is_data, "is_data", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_function", + JS_NewCFunction(ctx, js_cell_is_function, "is_function", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_logical", + JS_NewCFunction(ctx, js_cell_is_logical, "is_logical", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_integer", + JS_NewCFunction(ctx, js_cell_is_integer, "is_integer", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_null", + JS_NewCFunction(ctx, js_cell_is_null, "is_null", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_number", + JS_NewCFunction(ctx, js_cell_is_number, "is_number", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_object", + JS_NewCFunction(ctx, js_cell_is_object, "is_object", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_stone", + JS_NewCFunction(ctx, js_cell_is_stone, "is_stone", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_text", + JS_NewCFunction(ctx, js_cell_is_text, "is_text", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "is_proto", + JS_NewCFunction(ctx, js_cell_is_proto, "is_proto", 2)); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "apply", - JS_NewCFunction(ctx, js_cell_fn_apply, "apply", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "replace", - JS_NewCFunction(ctx, js_cell_text_replace, "replace", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "lower", - JS_NewCFunction(ctx, js_cell_text_lower, "lower", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "upper", - JS_NewCFunction(ctx, js_cell_text_upper, "upper", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "trim", - JS_NewCFunction(ctx, js_cell_text_trim, "trim", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "codepoint", - JS_NewCFunction(ctx, js_cell_text_codepoint, "codepoint", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "search", - JS_NewCFunction(ctx, js_cell_text_search, "search", 3), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "extract", - JS_NewCFunction(ctx, js_cell_text_extract, "extract", 3), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "reduce", - JS_NewCFunction(ctx, js_cell_array_reduce, "reduce", 4), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "arrfor", - JS_NewCFunction(ctx, js_cell_array_for, "for", 4), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "find", - JS_NewCFunction(ctx, js_cell_array_find, "find", 4), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "filter", - JS_NewCFunction(ctx, js_cell_array_filter, "filter", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "sort", - JS_NewCFunction(ctx, js_cell_array_sort, "sort", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "apply", + JS_NewCFunction(ctx, js_cell_fn_apply, "apply", 2)); + JS_SetPropertyStr(ctx, ctx->global_obj, "replace", + JS_NewCFunction(ctx, js_cell_text_replace, "replace", 2)); + JS_SetPropertyStr(ctx, ctx->global_obj, "lower", + JS_NewCFunction(ctx, js_cell_text_lower, "lower", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "upper", + JS_NewCFunction(ctx, js_cell_text_upper, "upper", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "trim", + JS_NewCFunction(ctx, js_cell_text_trim, "trim", 2)); + JS_SetPropertyStr(ctx, ctx->global_obj, "codepoint", + JS_NewCFunction(ctx, js_cell_text_codepoint, "codepoint", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "search", + JS_NewCFunction(ctx, js_cell_text_search, "search", 3)); + JS_SetPropertyStr(ctx, ctx->global_obj, "extract", + JS_NewCFunction(ctx, js_cell_text_extract, "extract", 3)); + JS_SetPropertyStr(ctx, ctx->global_obj, "reduce", + JS_NewCFunction(ctx, js_cell_array_reduce, "reduce", 4)); + JS_SetPropertyStr(ctx, ctx->global_obj, "arrfor", + JS_NewCFunction(ctx, js_cell_array_for, "for", 4)); + JS_SetPropertyStr(ctx, ctx->global_obj, "find", + JS_NewCFunction(ctx, js_cell_array_find, "find", 4)); + JS_SetPropertyStr(ctx, ctx->global_obj, "filter", + JS_NewCFunction(ctx, js_cell_array_filter, "filter", 2)); + JS_SetPropertyStr(ctx, ctx->global_obj, "sort", + JS_NewCFunction(ctx, js_cell_array_sort, "sort", 2)); /* Number utility functions as globals */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "whole", - JS_NewCFunction(ctx, js_cell_number_whole, "whole", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "fraction", - JS_NewCFunction(ctx, js_cell_number_fraction, "fraction", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "floor", - JS_NewCFunction(ctx, js_cell_number_floor, "floor", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "ceiling", - JS_NewCFunction(ctx, js_cell_number_ceiling, "ceiling", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "abs", - JS_NewCFunction(ctx, js_cell_number_abs, "abs", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "round", - JS_NewCFunction(ctx, js_cell_number_round, "round", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "sign", - JS_NewCFunction(ctx, js_cell_number_sign, "sign", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "trunc", - JS_NewCFunction(ctx, js_cell_number_trunc, "trunc", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "min", - JS_NewCFunction(ctx, js_cell_number_min, "min", 0), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "max", - JS_NewCFunction(ctx, js_cell_number_max, "max", 0), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "remainder", - JS_NewCFunction(ctx, js_cell_number_remainder, "remainder", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "character", - JS_NewCFunction(ctx, js_cell_character, "character", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "whole", + JS_NewCFunction(ctx, js_cell_number_whole, "whole", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "fraction", + JS_NewCFunction(ctx, js_cell_number_fraction, "fraction", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "floor", + JS_NewCFunction(ctx, js_cell_number_floor, "floor", 2)); + JS_SetPropertyStr(ctx, ctx->global_obj, "ceiling", + JS_NewCFunction(ctx, js_cell_number_ceiling, "ceiling", 2)); + JS_SetPropertyStr(ctx, ctx->global_obj, "abs", + JS_NewCFunction(ctx, js_cell_number_abs, "abs", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "round", + JS_NewCFunction(ctx, js_cell_number_round, "round", 2)); + JS_SetPropertyStr(ctx, ctx->global_obj, "sign", + JS_NewCFunction(ctx, js_cell_number_sign, "sign", 1)); + JS_SetPropertyStr(ctx, ctx->global_obj, "trunc", + JS_NewCFunction(ctx, js_cell_number_trunc, "trunc", 2)); + JS_SetPropertyStr(ctx, ctx->global_obj, "min", + JS_NewCFunction(ctx, js_cell_number_min, "min", 0)); + JS_SetPropertyStr(ctx, ctx->global_obj, "max", + JS_NewCFunction(ctx, js_cell_number_max, "max", 0)); + JS_SetPropertyStr(ctx, ctx->global_obj, "remainder", + JS_NewCFunction(ctx, js_cell_number_remainder, "remainder", 2)); + JS_SetPropertyStr(ctx, ctx->global_obj, "character", + JS_NewCFunction(ctx, js_cell_character, "character", 2)); /* modulo(dividend, divisor) - dividend - (divisor * floor(dividend / divisor)) */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "modulo", - JS_NewCFunction(ctx, js_cell_modulo, "modulo", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "modulo", + JS_NewCFunction(ctx, js_cell_modulo, "modulo", 2)); /* neg(number) - negate a number */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "neg", - JS_NewCFunction(ctx, js_cell_neg, "neg", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "neg", + JS_NewCFunction(ctx, js_cell_neg, "neg", 1)); /* not(boolean) - logical not */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "not", - JS_NewCFunction(ctx, js_cell_not, "not", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "not", + JS_NewCFunction(ctx, js_cell_not, "not", 1)); /* reverse() - reverse an array */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "reverse", - JS_NewCFunction(ctx, js_cell_reverse, "reverse", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "reverse", + JS_NewCFunction(ctx, js_cell_reverse, "reverse", 1)); /* proto() - get prototype of an object */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "proto", - JS_NewCFunction(ctx, js_cell_proto, "proto", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "proto", + JS_NewCFunction(ctx, js_cell_proto, "proto", 1)); /* splat() - flatten object with prototype chain */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "splat", - JS_NewCFunction(ctx, js_cell_splat, "splat", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - - /* splat() - flatten object with prototype chain */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "meme", - JS_NewCFunction(ctx, js_cell_meme, "meme", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "splat", + JS_NewCFunction(ctx, js_cell_splat, "splat", 1)); /* pi - mathematical constant */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "pi", - JS_NewFloat64(ctx, 3.14159265358979323846264338327950288419716939937510), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "pi", + JS_NewFloat64(ctx, 3.14159265358979323846264338327950288419716939937510)); /* push() - add element to end of array */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "push", - JS_NewCFunction(ctx, js_cell_push, "push", 2), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "push", + JS_NewCFunction(ctx, js_cell_push, "push", 2)); /* pop() - remove and return last element of array */ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "pop", - JS_NewCFunction(ctx, js_cell_pop, "pop", 1), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, ctx->global_obj, "pop", + JS_NewCFunction(ctx, js_cell_pop, "pop", 1)); } } @@ -32048,9 +30670,8 @@ static JSValue js_cell_json_decode(JSContext *ctx, JSValueConst this_val, int tag = JS_VALUE_GET_TAG(argv[0]); if (tag != JS_TAG_STRING && tag != JS_TAG_STRING_ROPE) { JSValue err = JS_NewError(ctx); - JS_DefinePropertyValueStr(ctx, err, "message", - JS_NewString(ctx, "couldn't parse text: not a string"), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyStr(ctx, err, "message", + JS_NewString(ctx, "couldn't parse text: not a string")); return JS_Throw(ctx, err); } @@ -32066,7 +30687,7 @@ static JSValue js_cell_json_decode(JSContext *ctx, JSValueConst this_val, if (argc > 1 && JS_IsFunction(ctx, argv[1]) && !JS_IsException(result)) { /* Create wrapper object to pass to reviver */ JSValue wrapper = JS_NewObject(ctx); - JS_DefinePropertyValueStr(ctx, wrapper, "", result, JS_PROP_C_W_E); + JS_SetPropertyStr(ctx, wrapper, "", result); JSValue holder = wrapper; JSAtom key = JS_NewAtom(ctx, ""); @@ -32422,3 +31043,4 @@ JSContext *JS_GetContext(JSRuntime *rt) { return rt->js; } + diff --git a/source/quickjs.h b/source/quickjs.h index 7a9bacc9..f48ad195 100644 --- a/source/quickjs.h +++ b/source/quickjs.h @@ -272,32 +272,12 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) #define JS_EXCEPTION JS_MKVAL(JS_TAG_EXCEPTION, 0) #define JS_UNINITIALIZED JS_MKVAL(JS_TAG_UNINITIALIZED, 0) -/* flags for object properties */ -#define JS_PROP_CONFIGURABLE (1 << 0) -#define JS_PROP_WRITABLE (1 << 1) -#define JS_PROP_ENUMERABLE (1 << 2) -#define JS_PROP_C_W_E (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_ENUMERABLE) -#define JS_PROP_LENGTH (1 << 3) /* used internally in Arrays */ -#define JS_PROP_TMASK (3 << 4) /* mask for NORMAL, GETSET, VARREF, AUTOINIT */ +/* flags for object properties - simplified model: + - No per-property writable/configurable (use stone() for immutability) + - Text keys are enumerable, object keys are not */ +#define JS_PROP_TMASK (3 << 4) /* mask for NORMAL, VARREF */ #define JS_PROP_NORMAL (0 << 4) -#define JS_PROP_VARREF (2 << 4) /* used internally */ - -/* flags for JS_DefineProperty */ -#define JS_PROP_HAS_SHIFT 8 -#define JS_PROP_HAS_CONFIGURABLE (1 << 8) -#define JS_PROP_HAS_WRITABLE (1 << 9) -#define JS_PROP_HAS_ENUMERABLE (1 << 10) -#define JS_PROP_HAS_VALUE (1 << 13) - -/* throw an exception if false would be returned - (JS_DefineProperty/JS_SetProperty) */ -#define JS_PROP_THROW (1 << 14) -/* throw an exception if false would be returned in strict mode - (JS_SetProperty) */ -#define JS_PROP_THROW_STRICT (1 << 15) - -#define JS_PROP_NO_ADD (1 << 16) /* internal use */ -#define JS_PROP_NO_EXOTIC (1 << 17) /* internal use */ +#define JS_PROP_VARREF (2 << 4) /* used internally for closures */ #ifndef JS_DEFAULT_STACK_SIZE #define JS_DEFAULT_STACK_SIZE (1024 * 1024) @@ -370,12 +350,9 @@ JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id); JSContext *JS_NewContextRaw(JSRuntime *rt); void JS_AddIntrinsicBaseObjects(JSContext *ctx); void JS_AddIntrinsicEval(JSContext *ctx); -void 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); JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); @@ -439,13 +416,6 @@ typedef struct JSPropertyEnum { JSAtom atom; } JSPropertyEnum; -typedef struct JSPropertyDescriptor { - int flags; - JSValue value; - JSValue getter; - JSValue setter; -} JSPropertyDescriptor; - typedef void JSClassFinalizer(JSRuntime *rt, JSValue val); typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); @@ -569,6 +539,11 @@ static inline JS_BOOL JS_IsObject(JSValueConst v) { return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT; } +int JS_IsArray(JSContext *ctx, JSValueConst val); +JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val); + +// Fundamental +int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres); JSValue JS_Throw(JSContext *ctx, JSValue obj); void JS_SetUncatchableException(JSContext *ctx, JS_BOOL flag); @@ -662,12 +637,8 @@ JSValue JS_NewObjectClass(JSContext *ctx, int class_id); JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto); JSValue JS_NewObject(JSContext *ctx); -JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val); - JSValue JS_NewArray(JSContext *ctx); JSValue JS_NewArrayLen(JSContext *ctx, uint32_t len); -int JS_IsArray(JSContext *ctx, JSValueConst val); -int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres); JSValue JS_ArrayPush(JSContext *ctx, JSValueConst obj, JSValueConst val); JSValue JS_ArrayPop(JSContext *ctx, JSValueConst obj); @@ -679,51 +650,35 @@ static js_force_inline JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_ { return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, 0); } -JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, - const char *prop); -JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, - uint32_t idx); -int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, - JSAtom prop, JSValue val, JSValueConst this_obj, - int flags); -static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValue val) -{ - return JS_SetPropertyInternal(ctx, this_obj, prop, val, this_obj, JS_PROP_THROW); -} -int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj, - uint32_t idx, JSValue val); -int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, - int64_t idx, JSValue val); -int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, - const char *prop, JSValue val); - -/* Property access with JSValue key (supports object keys via symbols) */ +// For records +JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, const char *prop); +int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, const char *prop, JSValue val); +int JS_SetProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val); JSValue JS_GetPropertyKey(JSContext *ctx, JSValueConst this_obj, JSValueConst key); int JS_SetPropertyKey(JSContext *ctx, JSValueConst this_obj, JSValueConst key, JSValue val); +// Must be an array +JSValue JS_GetPropertyNumber(JSContext *ctx, JSValueConst this_obj, int idx); +JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx); +int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx, JSValue val); +int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, int64_t idx, JSValue val); + int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop); -int JS_IsExtensible(JSContext *ctx, JSValueConst obj); -int JS_PreventExtensions(JSContext *ctx, JSValueConst obj); -int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags); -int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val); +int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop); JSValue JS_GetPrototype(JSContext *ctx, JSValueConst val); +/* Get Own Property Names flags */ #define JS_GPN_STRING_MASK (1 << 0) #define JS_GPN_SYMBOL_MASK (1 << 1) #define JS_GPN_PRIVATE_MASK (1 << 2) -/* only include the enumerable properties */ #define JS_GPN_ENUM_ONLY (1 << 4) -/* set theJSPropertyEnum.is_enumerable field */ #define JS_GPN_SET_ENUM (1 << 5) int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, uint32_t *plen, JSValueConst obj, int flags); void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len); -int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, - JSValueConst obj, JSAtom prop); JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv); @@ -737,15 +692,6 @@ JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, const char *filename, int eval_flags); JSValue JS_GetGlobalObject(JSContext *ctx); -int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, int flags); -int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValue val, int flags); -int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj, - uint32_t idx, JSValue val, int flags); -int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj, - const char *prop, JSValue val, int flags); void JS_SetOpaque(JSValue obj, void *opaque); void *JS_GetOpaque(JSValueConst obj, JSClassID class_id); void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id); @@ -797,11 +743,6 @@ typedef enum JSCFunctionEnum { JS_CFUNC_generic_magic, JS_CFUNC_f_f, JS_CFUNC_f_f_f, - JS_CFUNC_getter, - JS_CFUNC_setter, - JS_CFUNC_getter_magic, - JS_CFUNC_setter_magic, - JS_CFUNC_iterator_next, } JSCFunctionEnum; typedef union JSCFunctionType { @@ -809,12 +750,6 @@ typedef union JSCFunctionType { JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); double (*f_f)(double); double (*f_f_f)(double, double); - JSValue (*getter)(JSContext *ctx, JSValueConst this_val); - JSValue (*setter)(JSContext *ctx, JSValueConst this_val, JSValueConst val); - JSValue (*getter_magic)(JSContext *ctx, JSValueConst this_val, int magic); - JSValue (*setter_magic)(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic); - JSValue (*iterator_next)(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int *pdone, int magic); } JSCFunctionType; JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, @@ -875,10 +810,10 @@ typedef struct JSCFunctionListEntry { #define JS_DEF_ALIAS 9 /* 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 } } } } -#define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } } -#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } } -#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } } +#define JS_CFUNC_DEF(name, length, func1) { name, 0, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } +#define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, 0, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } } +#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, 0, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } } +#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, 0, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } } #define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, .u = { .str = cstr } } #define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, .u = { .i32 = val } } #define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, .u = { .i64 = val } } diff --git a/wildstar.c b/wildstar.c index 616c6319..c813e139 100644 --- a/wildstar.c +++ b/wildstar.c @@ -18,14 +18,14 @@ JSC_CCALL(wildstar_match, static const JSCFunctionListEntry js_wildstar_funcs[] = { MIST_FUNC_DEF(wildstar, match, 3), - JS_PROP_INT32_DEF("WM_MATCH", WM_MATCH, JS_PROP_CONFIGURABLE), - JS_PROP_INT32_DEF("WM_NOMATCH", WM_NOMATCH, JS_PROP_CONFIGURABLE), - JS_PROP_INT32_DEF("WM_NOESCAPE", WM_NOESCAPE, JS_PROP_CONFIGURABLE), - JS_PROP_INT32_DEF("WM_PATHNAME", WM_PATHNAME, JS_PROP_CONFIGURABLE), - JS_PROP_INT32_DEF("WM_PERIOD", WM_PERIOD, JS_PROP_CONFIGURABLE), - JS_PROP_INT32_DEF("WM_LEADING_DIR", WM_LEADING_DIR, JS_PROP_CONFIGURABLE), - JS_PROP_INT32_DEF("WM_CASEFOLD", WM_CASEFOLD, JS_PROP_CONFIGURABLE), - JS_PROP_INT32_DEF("WM_WILDSTAR", WM_WILDSTAR, JS_PROP_CONFIGURABLE), + JS_PROP_INT32_DEF("WM_MATCH", WM_MATCH, 0), + JS_PROP_INT32_DEF("WM_NOMATCH", WM_NOMATCH, 0), + JS_PROP_INT32_DEF("WM_NOESCAPE", WM_NOESCAPE, 0), + JS_PROP_INT32_DEF("WM_PATHNAME", WM_PATHNAME, 0), + JS_PROP_INT32_DEF("WM_PERIOD", WM_PERIOD, 0), + JS_PROP_INT32_DEF("WM_LEADING_DIR", WM_LEADING_DIR, 0), + JS_PROP_INT32_DEF("WM_CASEFOLD", WM_CASEFOLD, 0), + JS_PROP_INT32_DEF("WM_WILDSTAR", WM_WILDSTAR, 0), }; JSValue js_wildstar_use(JSContext *js) {