simpler enumeration of property names

This commit is contained in:
2026-01-31 12:13:35 -06:00
parent 3a0ea31896
commit c5ccc66e51
4 changed files with 157 additions and 218 deletions

View File

@@ -228,34 +228,44 @@ static void nota_encode_value(NotaEncodeContext *enc, JSValueConst val, JSValueC
} }
JS_FreeValue(ctx, to_json); JS_FreeValue(ctx, to_json);
JSValue *keys; JSValue keys = JS_GetOwnPropertyNames(ctx, replaced);
uint32_t plen; if (JS_IsException(keys)) {
if (JS_GetOwnPropertyNames(ctx, &keys, &plen, replaced) < 0) {
nota_write_sym(&enc->nb, NOTA_NULL); nota_write_sym(&enc->nb, NOTA_NULL);
nota_stack_pop(enc); nota_stack_pop(enc);
break; break;
} }
int64_t plen64;
if (JS_GetLength(ctx, keys, &plen64) < 0) {
JS_FreeValue(ctx, keys);
nota_write_sym(&enc->nb, NOTA_NULL);
nota_stack_pop(enc);
break;
}
uint32_t plen = (uint32_t)plen64;
uint32_t non_function_count = 0; uint32_t non_function_count = 0;
for (uint32_t i = 0; i < plen; i++) { for (uint32_t i = 0; i < plen; i++) {
JSValue prop_val = JS_GetProperty(ctx, replaced, keys[i]); JSValue key = JS_GetPropertyUint32(ctx, keys, i);
JSValue prop_val = JS_GetProperty(ctx, replaced, key);
if (!JS_IsFunction(prop_val)) non_function_count++; if (!JS_IsFunction(prop_val)) non_function_count++;
JS_FreeValue(ctx, prop_val); JS_FreeValue(ctx, prop_val);
JS_FreeValue(ctx, key);
} }
nota_write_record(&enc->nb, non_function_count); nota_write_record(&enc->nb, non_function_count);
for (uint32_t i = 0; i < plen; i++) { for (uint32_t i = 0; i < plen; i++) {
JSValue prop_val = JS_GetProperty(ctx, replaced, keys[i]); JSValue key = JS_GetPropertyUint32(ctx, keys, i);
JSValue prop_val = JS_GetProperty(ctx, replaced, key);
if (!JS_IsFunction(prop_val)) { if (!JS_IsFunction(prop_val)) {
const char *prop_name = JS_ToCString(ctx, keys[i]); const char *prop_name = JS_ToCString(ctx, key);
nota_write_text(&enc->nb, prop_name ? prop_name : ""); nota_write_text(&enc->nb, prop_name ? prop_name : "");
nota_encode_value(enc, prop_val, replaced, keys[i]); nota_encode_value(enc, prop_val, replaced, key);
JS_FreeCString(ctx, prop_name); JS_FreeCString(ctx, prop_name);
} }
JS_FreeValue(ctx, prop_val); JS_FreeValue(ctx, prop_val);
JS_FreeValue(ctx, keys[i]); JS_FreeValue(ctx, key);
} }
js_free(ctx, keys); JS_FreeValue(ctx, keys);
nota_stack_pop(enc); nota_stack_pop(enc);
break; break;
} }

View File

@@ -76,26 +76,34 @@ static void wota_encode_value(WotaEncodeContext *enc, JSValueConst val, JSValueC
static void encode_object_properties(WotaEncodeContext *enc, JSValueConst val, JSValueConst holder) static void encode_object_properties(WotaEncodeContext *enc, JSValueConst val, JSValueConst holder)
{ {
JSContext *ctx = enc->ctx; JSContext *ctx = enc->ctx;
JSValue *keys; JSValue keys = JS_GetOwnPropertyNames(ctx, val);
uint32_t plen; if (JS_IsException(keys)) {
if (JS_GetOwnPropertyNames(ctx, &keys, &plen, val) < 0) {
wota_write_sym(&enc->wb, WOTA_NULL); wota_write_sym(&enc->wb, WOTA_NULL);
return; return;
} }
int64_t plen64;
if (JS_GetLength(ctx, keys, &plen64) < 0) {
JS_FreeValue(ctx, keys);
wota_write_sym(&enc->wb, WOTA_NULL);
return;
}
uint32_t plen = (uint32_t)plen64;
uint32_t non_function_count = 0; uint32_t non_function_count = 0;
JSValue props[plen]; JSValue props[plen];
JSValue kept_keys[plen]; JSValue kept_keys[plen];
for (uint32_t i = 0; i < plen; i++) { for (uint32_t i = 0; i < plen; i++) {
JSValue prop_val = JS_GetProperty(ctx, val, keys[i]); JSValue key = JS_GetPropertyUint32(ctx, keys, i);
JSValue prop_val = JS_GetProperty(ctx, val, key);
if (!JS_IsFunction(prop_val)) { if (!JS_IsFunction(prop_val)) {
kept_keys[non_function_count] = keys[i]; kept_keys[non_function_count] = key;
props[non_function_count++] = prop_val; props[non_function_count++] = prop_val;
} else { } else {
JS_FreeValue(ctx, prop_val); JS_FreeValue(ctx, prop_val);
JS_FreeValue(ctx, keys[i]); JS_FreeValue(ctx, key);
} }
} }
JS_FreeValue(ctx, keys);
wota_write_record(&enc->wb, non_function_count); wota_write_record(&enc->wb, non_function_count);
for (uint32_t i = 0; i < non_function_count; i++) { for (uint32_t i = 0; i < non_function_count; i++) {
size_t klen; size_t klen;
@@ -107,8 +115,6 @@ static void encode_object_properties(WotaEncodeContext *enc, JSValueConst val, J
JS_FreeValue(ctx, prop_val); JS_FreeValue(ctx, prop_val);
JS_FreeValue(ctx, kept_keys[i]); JS_FreeValue(ctx, kept_keys[i]);
} }
js_free(ctx, keys);
} }
static void wota_encode_value(WotaEncodeContext *enc, JSValueConst val, JSValueConst holder, JSValue key) static void wota_encode_value(WotaEncodeContext *enc, JSValueConst val, JSValueConst holder, JSValue key)

View File

@@ -208,39 +208,6 @@ static inline const char *JS_KeyGetStr (JSContext *ctx, char *buf,
return buf; return buf;
} }
/* Legacy JSPropertyEnum type (replaced by JSValue array) */
typedef struct JSPropertyEnum {
JSValue atom; /* property key as JSValue */
int is_enumerable;
} JSPropertyEnum;
/* GPN flags (no longer used - property enumeration uses JSValue keys) */
#define JS_GPN_ENUM_ONLY 0
#define JS_GPN_STRING_MASK 0
/* Stub: JS_GetOwnPropertyNamesInternal - legacy property enumeration */
static inline int JS_GetOwnPropertyNamesInternal (JSContext *ctx,
JSPropertyEnum **ptab,
uint32_t *plen, void *obj,
int flags) {
(void)ctx;
(void)ptab;
(void)plen;
(void)obj;
(void)flags;
*ptab = NULL;
*plen = 0;
return 0;
}
/* Stub: JS_FreePropertyEnum - legacy property enumeration cleanup */
static inline void JS_FreePropertyEnum (JSContext *ctx, JSPropertyEnum *tab,
uint32_t len) {
(void)ctx;
(void)tab;
(void)len;
}
/* JS_Invoke - invoke method on object using JSValue key */ /* JS_Invoke - invoke method on object using JSValue key */
static JSValue JS_Invoke (JSContext *ctx, JSValue this_val, JSValue method, static JSValue JS_Invoke (JSContext *ctx, JSValue this_val, JSValue method,
int argc, JSValue *argv); int argc, JSValue *argv);
@@ -287,8 +254,6 @@ typedef enum JSErrorEnum {
typedef struct JSString JSString; typedef struct JSString JSString;
/* JSRecord is now an alias for JSRecord - defined later after JSRecord */ /* JSRecord is now an alias for JSRecord - defined later after JSRecord */
/* JSPropertyEnum removed - property keys are now JSValue strings directly */
/* Forward declaration for bytecode freeing */ /* Forward declaration for bytecode freeing */
struct JSFunctionBytecode; struct JSFunctionBytecode;
static void free_function_bytecode (JSRuntime *rt, static void free_function_bytecode (JSRuntime *rt,
@@ -5272,63 +5237,35 @@ JSValue JS_GetProperty (JSContext *ctx, JSValue obj, JSValue prop) {
return rec_get (ctx, rec, prop); return rec_get (ctx, rec, prop);
} }
/* Forward declaration for js_get_record_keys */ /* Get own property names from an object.
static int js_get_record_keys (JSContext *ctx, JSValue **ptab, uint32_t *plen, Returns a JSValue array of text keys. */
JSRecord *rec); JSValue JS_GetOwnPropertyNames (JSContext *ctx, JSValue obj) {
JSRecord *rec;
uint32_t mask, count, i;
JSValue arr;
/* Internal helper: get property keys for legacy JSRecord (now just records) */ if (JS_VALUE_GET_TAG (obj) != JS_TAG_OBJECT) {
static int __exception js_get_object_keys (JSContext *ctx, JSValue **ptab, JS_ThrowTypeErrorNotAnObject (ctx);
uint32_t *plen, JSRecord *p) { return JS_EXCEPTION;
/* Objects are now records */
JSRecord *rec = (JSRecord *)p;
return js_get_record_keys (ctx, ptab, plen, rec);
}
/* Get own property names from a JSRecord.
Returns JSValue string keys directly (text values), not record-as-key. */
static int js_get_record_keys (JSContext *ctx, JSValue **ptab, uint32_t *plen,
JSRecord *rec) {
uint32_t mask = (uint32_t)objhdr_cap56 (rec->mist_hdr);
uint32_t count = 0;
uint32_t i, j;
JSValue *tab;
/* Count string keys (skip empty/tombstone and non-string keys) */
for (i = 1; i <= mask; i++) {
JSValue k = rec->tab[i].key;
if (!rec_key_is_empty (k) && !rec_key_is_tomb (k) && JS_IsString (k))
count++;
} }
/* Allocate array */ rec = (JSRecord *)JS_VALUE_GET_OBJ (obj);
tab = js_malloc (ctx, sizeof (tab[0]) * max_int (count, 1)); arr = JS_NewArray (ctx);
if (!tab) return -1; if (JS_IsException (arr)) return JS_EXCEPTION;
/* Fill array with JSValue string keys */ mask = (uint32_t)objhdr_cap56 (rec->mist_hdr);
j = 0; count = 0;
/* Add string keys to array */
for (i = 1; i <= mask; i++) { for (i = 1; i <= mask; i++) {
JSValue k = rec->tab[i].key; JSValue k = rec->tab[i].key;
if (!rec_key_is_empty (k) && !rec_key_is_tomb (k) && JS_IsString (k)) { if (!rec_key_is_empty (k) && !rec_key_is_tomb (k) && JS_IsString (k)) {
tab[j] = JS_DupValue (ctx, k); JS_SetPropertyUint32 (ctx, arr, count, JS_DupValue (ctx, k));
j++; count++;
} }
} }
*ptab = tab; return arr;
*plen = count;
return 0;
}
int JS_GetOwnPropertyNames (JSContext *ctx, JSValue **ptab, uint32_t *plen,
JSValue obj) {
if (JS_VALUE_GET_TAG (obj) != JS_TAG_OBJECT) {
JS_ThrowTypeErrorNotAnObject (ctx);
return -1;
}
/* All objects are now records */
JSRecord *rec = (JSRecord *)JS_VALUE_GET_OBJ (obj);
return js_get_record_keys (ctx, ptab, plen, rec);
} }
/* Return -1 if exception, /* Return -1 if exception,
@@ -7693,50 +7630,53 @@ static BOOL js_get_fast_array (JSContext *ctx, JSValue obj, JSValue **arrpp,
static __exception int JS_CopyDataProperties (JSContext *ctx, JSValue target, static __exception int JS_CopyDataProperties (JSContext *ctx, JSValue target,
JSValue source, JSValue excluded, JSValue source, JSValue excluded,
BOOL setprop) { BOOL setprop) {
JSValue *keys; JSValue keys, key, val;
JSValue val;
uint32_t i, key_count; uint32_t i, key_count;
int ret; int ret;
if (JS_VALUE_GET_TAG (source) != JS_TAG_OBJECT) return 0; if (JS_VALUE_GET_TAG (source) != JS_TAG_OBJECT) return 0;
/* Get all string keys from source */ /* Get all string keys from source */
if (JS_GetOwnPropertyNames (ctx, &keys, &key_count, source)) return -1; keys = JS_GetOwnPropertyNames (ctx, source);
if (JS_IsException (keys)) return -1;
if (js_get_length32 (ctx, &key_count, keys)) {
JS_FreeValue (ctx, keys);
return -1;
}
for (i = 0; i < key_count; i++) { for (i = 0; i < key_count; i++) {
key = JS_GetPropertyUint32 (ctx, keys, i);
if (JS_IsException (key)) goto exception;
/* Check if key is excluded */ /* Check if key is excluded */
if (JS_VALUE_GET_TAG (excluded) == JS_TAG_OBJECT) { if (JS_VALUE_GET_TAG (excluded) == JS_TAG_OBJECT) {
/* Check if key exists in excluded object */ /* Check if key exists in excluded object */
JSValue test = JS_GetProperty (ctx, excluded, keys[i]); JSValue test = JS_GetProperty (ctx, excluded, key);
if (!JS_IsNull (test) && !JS_IsException (test)) { if (!JS_IsNull (test) && !JS_IsException (test)) {
JS_FreeValue (ctx, test); JS_FreeValue (ctx, test);
JS_FreeValue (ctx, key);
continue; continue;
} }
JS_FreeValue (ctx, test); JS_FreeValue (ctx, test);
} }
/* Get property value from source */ /* Get property value from source */
val = JS_GetProperty (ctx, source, keys[i]); val = JS_GetProperty (ctx, source, key);
if (JS_IsException (val)) goto exception; if (JS_IsException (val)) {
JS_FreeValue (ctx, key);
goto exception;
}
/* Set property on target */ /* Set property on target */
if (setprop) ret = JS_SetProperty (ctx, target, key, val);
ret = JS_SetProperty (ctx, target, JS_DupValue (ctx, keys[i]), val);
else
ret = JS_SetProperty (ctx, target, JS_DupValue (ctx, keys[i]), val);
if (ret < 0) goto exception; if (ret < 0) goto exception;
} }
/* Free keys array */ JS_FreeValue (ctx, keys);
for (i = 0; i < key_count; i++)
JS_FreeValue (ctx, keys[i]);
js_free (ctx, keys);
return 0; return 0;
exception: exception:
for (i = 0; i < key_count; i++) JS_FreeValue (ctx, keys);
JS_FreeValue (ctx, keys[i]);
js_free (ctx, keys);
return -1; return -1;
} }
@@ -20770,42 +20710,6 @@ static JSValue JS_ToObjectFree (JSContext *ctx, JSValue val) {
return obj; return obj;
} }
// TODO: This needs to only return text atoms
static JSValue JS_GetOwnPropertyNames2 (JSContext *ctx, JSValue obj1,
int flags) {
JSValue obj, r, val, key, value;
JSRecord *p;
JSPropertyEnum *atoms;
uint32_t len, i, j;
r = JS_NULL;
val = JS_NULL;
obj = JS_ToObject (ctx, obj1);
if (JS_IsException (obj)) return JS_EXCEPTION;
p = JS_VALUE_GET_OBJ (obj);
if (JS_GetOwnPropertyNamesInternal (ctx, &atoms, &len, p,
flags & ~JS_GPN_ENUM_ONLY))
goto exception;
r = JS_NewArray (ctx);
if (JS_IsException (r)) goto exception;
for (j = i = 0; i < len; i++) {
val = JS_DupValue (ctx, atoms[i].atom);
if (JS_IsException (val)) goto exception;
JS_ArrayPush (ctx, r, val);
}
goto done;
exception1:
JS_FreeValue (ctx, val);
exception:
JS_FreeValue (ctx, r);
r = JS_EXCEPTION;
done:
JS_FreePropertyEnum (ctx, atoms, len);
JS_FreeValue (ctx, obj);
return r;
}
/* Function class */ /* Function class */
static JSValue js_function_proto (JSContext *ctx, JSValue this_val, int argc, static JSValue js_function_proto (JSContext *ctx, JSValue this_val, int argc,
@@ -22082,8 +21986,7 @@ static int js_json_to_str (JSContext *ctx, JSONStringifyContext *jsc,
if (!JS_IsNull (jsc->property_list)) if (!JS_IsNull (jsc->property_list))
tab = JS_DupValue (ctx, jsc->property_list); tab = JS_DupValue (ctx, jsc->property_list);
else else
tab = JS_GetOwnPropertyNames2 (ctx, val, tab = JS_GetOwnPropertyNames (ctx, val);
JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK);
if (JS_IsException (tab)) goto exception; if (JS_IsException (tab)) goto exception;
if (js_get_length64 (ctx, &len, tab)) goto exception; if (js_get_length64 (ctx, &len, tab)) goto exception;
string_buffer_putc8 (jsc->b, '{'); string_buffer_putc8 (jsc->b, '{');
@@ -24277,8 +24180,7 @@ static JSValue js_cell_array (JSContext *ctx, JSValue this_val, int argc,
/* array(object) - keys */ /* array(object) - keys */
if (JS_IsObject (arg) && !JS_IsArray (ctx, arg)) { if (JS_IsObject (arg) && !JS_IsArray (ctx, arg)) {
/* Return object keys */ /* Return object keys */
return JS_GetOwnPropertyNames2 (ctx, arg, return JS_GetOwnPropertyNames (ctx, arg);
JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK);
} }
/* array(text) - split into characters */ /* array(text) - split into characters */
@@ -25040,27 +24942,30 @@ static JSValue js_cell_object (JSContext *ctx, JSValue this_val, int argc,
JSValue result = JS_NewObject (ctx); JSValue result = JS_NewObject (ctx);
if (JS_IsException (result)) return result; if (JS_IsException (result)) return result;
JSValue *keys; JSValue keys = JS_GetOwnPropertyNames (ctx, arg);
if (JS_IsException (keys)) {
JS_FreeValue (ctx, result);
return JS_EXCEPTION;
}
uint32_t len; uint32_t len;
if (JS_GetOwnPropertyNames (ctx, &keys, &len, arg)) { if (js_get_length32 (ctx, &len, keys)) {
JS_FreeValue (ctx, keys);
JS_FreeValue (ctx, result); JS_FreeValue (ctx, result);
return JS_EXCEPTION; return JS_EXCEPTION;
} }
for (uint32_t i = 0; i < len; i++) { for (uint32_t i = 0; i < len; i++) {
JSValue val = JS_GetProperty (ctx, arg, keys[i]); JSValue key = JS_GetPropertyUint32 (ctx, keys, i);
JSValue val = JS_GetProperty (ctx, arg, key);
if (JS_IsException (val)) { if (JS_IsException (val)) {
for (uint32_t j = 0; j < len; j++) JS_FreeValue (ctx, key);
JS_FreeValue (ctx, keys[j]); JS_FreeValue (ctx, keys);
js_free (ctx, keys);
JS_FreeValue (ctx, result); JS_FreeValue (ctx, result);
return JS_EXCEPTION; return JS_EXCEPTION;
} }
JS_SetProperty (ctx, result, keys[i], val); JS_SetProperty (ctx, result, key, val);
} }
for (uint32_t i = 0; i < len; i++) JS_FreeValue (ctx, keys);
JS_FreeValue (ctx, keys[i]);
js_free (ctx, keys);
return result; return result;
} }
@@ -25070,46 +24975,53 @@ static JSValue js_cell_object (JSContext *ctx, JSValue this_val, int argc,
if (JS_IsException (result)) return result; if (JS_IsException (result)) return result;
/* Copy from first object */ /* Copy from first object */
JSValue *keys; JSValue keys = JS_GetOwnPropertyNames (ctx, arg);
if (JS_IsException (keys)) {
JS_FreeValue (ctx, result);
return JS_EXCEPTION;
}
uint32_t len; uint32_t len;
if (JS_GetOwnPropertyNames (ctx, &keys, &len, arg)) { if (js_get_length32 (ctx, &len, keys)) {
JS_FreeValue (ctx, keys);
JS_FreeValue (ctx, result); JS_FreeValue (ctx, result);
return JS_EXCEPTION; return JS_EXCEPTION;
} }
for (uint32_t i = 0; i < len; i++) { for (uint32_t i = 0; i < len; i++) {
JSValue val = JS_GetProperty (ctx, arg, keys[i]); JSValue key = JS_GetPropertyUint32 (ctx, keys, i);
JSValue val = JS_GetProperty (ctx, arg, key);
if (JS_IsException (val)) { if (JS_IsException (val)) {
for (uint32_t j = 0; j < len; j++) JS_FreeValue (ctx, key);
JS_FreeValue (ctx, keys[j]); JS_FreeValue (ctx, keys);
js_free (ctx, keys);
JS_FreeValue (ctx, result); JS_FreeValue (ctx, result);
return JS_EXCEPTION; return JS_EXCEPTION;
} }
JS_SetProperty (ctx, result, keys[i], val); JS_SetProperty (ctx, result, key, val);
} }
for (uint32_t i = 0; i < len; i++) JS_FreeValue (ctx, keys);
JS_FreeValue (ctx, keys[i]);
js_free (ctx, keys);
/* Copy from second object */ /* Copy from second object */
if (JS_GetOwnPropertyNames (ctx, &keys, &len, argv[1])) { keys = JS_GetOwnPropertyNames (ctx, argv[1]);
if (JS_IsException (keys)) {
JS_FreeValue (ctx, result);
return JS_EXCEPTION;
}
if (js_get_length32 (ctx, &len, keys)) {
JS_FreeValue (ctx, keys);
JS_FreeValue (ctx, result); JS_FreeValue (ctx, result);
return JS_EXCEPTION; return JS_EXCEPTION;
} }
for (uint32_t i = 0; i < len; i++) { for (uint32_t i = 0; i < len; i++) {
JSValue val = JS_GetProperty (ctx, argv[1], keys[i]); JSValue key = JS_GetPropertyUint32 (ctx, keys, i);
JSValue val = JS_GetProperty (ctx, argv[1], key);
if (JS_IsException (val)) { if (JS_IsException (val)) {
for (uint32_t j = 0; j < len; j++) JS_FreeValue (ctx, key);
JS_FreeValue (ctx, keys[j]); JS_FreeValue (ctx, keys);
js_free (ctx, keys);
JS_FreeValue (ctx, result); JS_FreeValue (ctx, result);
return JS_EXCEPTION; return JS_EXCEPTION;
} }
JS_SetProperty (ctx, result, keys[i], val); JS_SetProperty (ctx, result, key, val);
} }
for (uint32_t i = 0; i < len; i++) JS_FreeValue (ctx, keys);
JS_FreeValue (ctx, keys[i]);
js_free (ctx, keys);
return result; return result;
} }
@@ -25982,25 +25894,29 @@ static JSValue js_cell_meme (JSContext *ctx, JSValue this_val, int argc,
do { \ do { \
if (!JS_IsObject (mix) || JS_IsNull (mix) || JS_IsArray (ctx, mix)) \ if (!JS_IsObject (mix) || JS_IsNull (mix) || JS_IsArray (ctx, mix)) \
break; \ break; \
JSValue *tab; \ JSValue _keys = JS_GetOwnPropertyNames (ctx, mix); \
uint32_t len; \ if (JS_IsException (_keys)) { \
if (JS_GetOwnPropertyNames (ctx, &tab, &len, mix) < 0) { \
JS_FreeValue (ctx, result); \ JS_FreeValue (ctx, result); \
return JS_EXCEPTION; \ return JS_EXCEPTION; \
} \ } \
for (uint32_t j = 0; j < len; j++) { \ uint32_t _len; \
JSValue val = JS_GetProperty (ctx, mix, tab[j]); \ if (js_get_length32 (ctx, &_len, _keys)) { \
JS_FreeValue (ctx, _keys); \
JS_FreeValue (ctx, result); \
return JS_EXCEPTION; \
} \
for (uint32_t j = 0; j < _len; j++) { \
JSValue _key = JS_GetPropertyUint32 (ctx, _keys, j); \
JSValue val = JS_GetProperty (ctx, mix, _key); \
if (JS_IsException (val)) { \ if (JS_IsException (val)) { \
for (uint32_t k = j; k < len; k++) \ JS_FreeValue (ctx, _key); \
JS_FreeValue (ctx, tab[k]); \ JS_FreeValue (ctx, _keys); \
js_free (ctx, tab); \
JS_FreeValue (ctx, result); \ JS_FreeValue (ctx, result); \
return JS_EXCEPTION; \ return JS_EXCEPTION; \
} \ } \
JS_SetProperty (ctx, result, tab[j], val); \ JS_SetProperty (ctx, result, _key, val); \
JS_FreeValue (ctx, tab[j]); \
} \ } \
js_free (ctx, tab); \ JS_FreeValue (ctx, _keys); \
} while (0) } while (0)
/* Process all arguments starting from argv[1] as mixins */ /* Process all arguments starting from argv[1] as mixins */
@@ -26054,23 +25970,27 @@ static JSValue js_cell_splat (JSContext *ctx, JSValue this_val, int argc,
/* Walk prototype chain and collect text keys */ /* Walk prototype chain and collect text keys */
while (!JS_IsNull (current)) { while (!JS_IsNull (current)) {
JSValue *keys; JSValue keys = JS_GetOwnPropertyNames (ctx, current);
if (JS_IsException (keys)) {
JS_FreeValue (ctx, current);
JS_FreeValue (ctx, result);
return JS_EXCEPTION;
}
uint32_t len; uint32_t len;
if (js_get_length32 (ctx, &len, keys)) {
if (JS_GetOwnPropertyNames (ctx, &keys, &len, current) < 0) { JS_FreeValue (ctx, keys);
JS_FreeValue (ctx, current); JS_FreeValue (ctx, current);
JS_FreeValue (ctx, result); JS_FreeValue (ctx, result);
return JS_EXCEPTION; return JS_EXCEPTION;
} }
for (uint32_t i = 0; i < len; i++) { for (uint32_t i = 0; i < len; i++) {
JSValue key = keys[i]; JSValue key = JS_GetPropertyUint32 (ctx, keys, i);
/* Check if property not already in result */ /* Check if property not already in result */
int has = JS_HasProperty (ctx, result, key); int has = JS_HasProperty (ctx, result, key);
if (has < 0) { if (has < 0) {
for (uint32_t j = i; j < len; j++) JS_FreeValue (ctx, key);
JS_FreeValue (ctx, keys[j]); JS_FreeValue (ctx, keys);
js_free (ctx, keys);
JS_FreeValue (ctx, current); JS_FreeValue (ctx, current);
JS_FreeValue (ctx, result); JS_FreeValue (ctx, result);
return JS_EXCEPTION; return JS_EXCEPTION;
@@ -26078,9 +25998,8 @@ static JSValue js_cell_splat (JSContext *ctx, JSValue this_val, int argc,
if (!has) { if (!has) {
JSValue val = JS_GetProperty (ctx, current, key); JSValue val = JS_GetProperty (ctx, current, key);
if (JS_IsException (val)) { if (JS_IsException (val)) {
for (uint32_t j = i; j < len; j++) JS_FreeValue (ctx, key);
JS_FreeValue (ctx, keys[j]); JS_FreeValue (ctx, keys);
js_free (ctx, keys);
JS_FreeValue (ctx, current); JS_FreeValue (ctx, current);
JS_FreeValue (ctx, result); JS_FreeValue (ctx, result);
return JS_EXCEPTION; return JS_EXCEPTION;
@@ -26091,12 +26010,14 @@ static JSValue js_cell_splat (JSContext *ctx, JSValue this_val, int argc,
|| tag == JS_TAG_STRING_IMM || tag == JS_TAG_BOOL) { || tag == JS_TAG_STRING_IMM || tag == JS_TAG_BOOL) {
JS_SetProperty (ctx, result, key, val); JS_SetProperty (ctx, result, key, val);
} else { } else {
JS_FreeValue (ctx, key);
JS_FreeValue (ctx, val); JS_FreeValue (ctx, val);
} }
} else {
JS_FreeValue (ctx, key);
} }
JS_FreeValue (ctx, keys[i]);
} }
js_free (ctx, keys); JS_FreeValue (ctx, keys);
JSValue next = JS_GetPrototype (ctx, current); JSValue next = JS_GetPrototype (ctx, current);
JS_FreeValue (ctx, current); JS_FreeValue (ctx, current);
@@ -26109,15 +26030,17 @@ static JSValue js_cell_splat (JSContext *ctx, JSValue this_val, int argc,
JSValue args[1] = { result }; JSValue args[1] = { result };
JSValue extra = JS_Call (ctx, to_data, obj, 1, args); JSValue extra = JS_Call (ctx, to_data, obj, 1, args);
if (!JS_IsException (extra) && JS_IsObject (extra)) { if (!JS_IsException (extra) && JS_IsObject (extra)) {
JSValue *keys2; JSValue keys2 = JS_GetOwnPropertyNames (ctx, extra);
uint32_t len; if (!JS_IsException (keys2)) {
if (JS_GetOwnPropertyNames (ctx, &keys2, &len, extra) >= 0) { uint32_t len;
for (uint32_t i = 0; i < len; i++) { if (!js_get_length32 (ctx, &len, keys2)) {
JSValue val = JS_GetProperty (ctx, extra, keys2[i]); for (uint32_t i = 0; i < len; i++) {
JS_SetProperty (ctx, result, keys2[i], val); JSValue key = JS_GetPropertyUint32 (ctx, keys2, i);
JS_FreeValue (ctx, keys2[i]); JSValue val = JS_GetProperty (ctx, extra, key);
JS_SetProperty (ctx, result, key, val);
}
} }
js_free (ctx, keys2); JS_FreeValue (ctx, keys2);
} }
} }
JS_FreeValue (ctx, extra); JS_FreeValue (ctx, extra);

View File

@@ -707,8 +707,8 @@ JSValue JS_GetPropertyUint32 (JSContext *ctx, JSValue this_obj, uint32_t idx);
int JS_SetPropertyUint32 (JSContext *ctx, JSValue this_obj, uint32_t idx, JSValue val); int JS_SetPropertyUint32 (JSContext *ctx, JSValue this_obj, uint32_t idx, JSValue val);
int JS_SetPropertyInt64 (JSContext *ctx, JSValue this_obj, int64_t idx, JSValue val); int JS_SetPropertyInt64 (JSContext *ctx, JSValue this_obj, int64_t idx, JSValue val);
/* Get property keys as array of JSValue strings */ /* Get property keys as array of text */
int JS_GetOwnPropertyNames (JSContext *ctx, JSValue **tab, uint32_t *plen, JSValue obj); JSValue JS_GetOwnPropertyNames (JSContext *ctx, JSValue obj);
JSValue JS_Call (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv); JSValue JS_Call (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv);
/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */ /* 'input' must be zero terminated i.e. input[input_len] = '\0'. */