rm autoinit
This commit is contained in:
234
source/quickjs.c
234
source/quickjs.c
@@ -399,10 +399,6 @@ typedef struct JSVarRef {
|
||||
};
|
||||
} JSVarRef;
|
||||
|
||||
typedef enum {
|
||||
JS_AUTOINIT_ID_PROP,
|
||||
} JSAutoInitIDEnum;
|
||||
|
||||
/* must be large enough to have a negligible runtime cost and small
|
||||
enough to call the interrupt callback often. */
|
||||
#define JS_INTERRUPT_COUNTER_INIT 10000
|
||||
@@ -699,13 +695,6 @@ typedef struct JSBoundFunction {
|
||||
JSValue argv[0];
|
||||
} JSBoundFunction;
|
||||
|
||||
/* Used by js_object_keys and related functions */
|
||||
typedef enum JSIteratorKindEnum {
|
||||
JS_ITERATOR_KIND_KEY,
|
||||
JS_ITERATOR_KIND_VALUE,
|
||||
JS_ITERATOR_KIND_KEY_AND_VALUE,
|
||||
} JSIteratorKindEnum;
|
||||
|
||||
typedef struct JSRegExp {
|
||||
JSString *pattern;
|
||||
JSString *bytecode; /* also contains the flags */
|
||||
@@ -719,13 +708,6 @@ typedef struct JSProperty {
|
||||
JSObject *setter; /* NULL if undefined */
|
||||
} getset;
|
||||
JSVarRef *var_ref; /* JS_PROP_VARREF */
|
||||
struct { /* JS_PROP_AUTOINIT */
|
||||
/* in order to use only 2 pointers, we compress the realm
|
||||
and the init function pointer */
|
||||
uintptr_t realm_and_id; /* realm and init_id (JS_AUTOINIT_ID_x)
|
||||
in the 2 low bits */
|
||||
void *opaque;
|
||||
} init;
|
||||
} u;
|
||||
} JSProperty;
|
||||
|
||||
@@ -4886,7 +4868,6 @@ static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
|
||||
p->u.cfunc.length = length;
|
||||
p->u.cfunc.cproto = cproto;
|
||||
p->u.cfunc.magic = magic;
|
||||
/* Note: is_constructor bit removed - constructors are called as regular functions */
|
||||
if (!name)
|
||||
name = "";
|
||||
name_atom = JS_NewAtom(ctx, name);
|
||||
@@ -4993,27 +4974,6 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
|
||||
return func_obj;
|
||||
}
|
||||
|
||||
static JSContext *js_autoinit_get_realm(JSProperty *pr)
|
||||
{
|
||||
return (JSContext *)(pr->u.init.realm_and_id & ~3);
|
||||
}
|
||||
|
||||
static JSAutoInitIDEnum js_autoinit_get_id(JSProperty *pr)
|
||||
{
|
||||
return pr->u.init.realm_and_id & 3;
|
||||
}
|
||||
|
||||
static void js_autoinit_free(JSRuntime *rt, JSProperty *pr)
|
||||
{
|
||||
JS_FreeContext(js_autoinit_get_realm(pr));
|
||||
}
|
||||
|
||||
static void js_autoinit_mark(JSRuntime *rt, JSProperty *pr,
|
||||
JS_MarkFunc *mark_func)
|
||||
{
|
||||
mark_func(rt, &js_autoinit_get_realm(pr)->header);
|
||||
}
|
||||
|
||||
static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags)
|
||||
{
|
||||
if (unlikely(prop_flags & JS_PROP_TMASK)) {
|
||||
@@ -5024,8 +4984,6 @@ static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags)
|
||||
JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));
|
||||
} else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
|
||||
free_var_ref(rt, pr->u.var_ref);
|
||||
} else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
|
||||
js_autoinit_free(rt, pr);
|
||||
}
|
||||
} else {
|
||||
JS_FreeValueRT(rt, pr->u.value);
|
||||
@@ -5417,8 +5375,6 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
|
||||
/* Note: the tag does not matter
|
||||
provided it is a GC object */
|
||||
mark_func(rt, &pr->u.var_ref->header);
|
||||
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
|
||||
js_autoinit_mark(rt, pr, mark_func);
|
||||
}
|
||||
} else {
|
||||
JS_MarkValue(rt, pr->u.value, mark_func);
|
||||
@@ -6632,39 +6588,6 @@ static JSValue JS_GetPrototypeFree(JSContext *ctx, JSValue obj)
|
||||
return obj1;
|
||||
}
|
||||
|
||||
/* return the value associated to the autoinit property or an exception */
|
||||
typedef JSValue JSAutoInitFunc(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);
|
||||
|
||||
static JSAutoInitFunc *js_autoinit_func_table[] = {
|
||||
JS_InstantiateFunctionListItem2, /* JS_AUTOINIT_ID_PROP */
|
||||
};
|
||||
|
||||
/* warning: 'prs' is reallocated after it */
|
||||
static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop,
|
||||
JSProperty *pr, JSShapeProperty *prs)
|
||||
{
|
||||
JSValue val;
|
||||
JSContext *realm;
|
||||
JSAutoInitFunc *func;
|
||||
JSAutoInitIDEnum id;
|
||||
|
||||
if (js_shape_prepare_update(ctx, p, &prs))
|
||||
return -1;
|
||||
|
||||
realm = js_autoinit_get_realm(pr);
|
||||
id = js_autoinit_get_id(pr);
|
||||
func = js_autoinit_func_table[id];
|
||||
/* 'func' shall not modify the object properties 'pr' */
|
||||
val = func(realm, p, prop, pr->u.init.opaque);
|
||||
js_autoinit_free(ctx->rt, pr);
|
||||
prs->flags &= ~JS_PROP_TMASK;
|
||||
pr->u.value = JS_NULL;
|
||||
if (JS_IsException(val))
|
||||
return -1;
|
||||
pr->u.value = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
||||
JSAtom prop, JSValueConst this_obj,
|
||||
BOOL throw_ref_error)
|
||||
@@ -6744,11 +6667,6 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
||||
if (unlikely(JS_IsUninitialized(val)))
|
||||
return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);
|
||||
return JS_DupValue(ctx, val);
|
||||
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
|
||||
/* Instantiate property and retry */
|
||||
if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
|
||||
return JS_EXCEPTION;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
return JS_DupValue(ctx, pr->u.value);
|
||||
@@ -6980,11 +6898,6 @@ retry:
|
||||
return -1;
|
||||
}
|
||||
desc->value = JS_DupValue(ctx, val);
|
||||
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
|
||||
/* Instantiate property and retry */
|
||||
if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
|
||||
return -1;
|
||||
goto retry;
|
||||
}
|
||||
} else {
|
||||
desc->value = JS_DupValue(ctx, pr->u.value);
|
||||
@@ -6996,8 +6909,6 @@ retry:
|
||||
JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);
|
||||
return -1;
|
||||
}
|
||||
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
|
||||
/* nothing to do: delay instantiation until actual value and/or attributes are read */
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
@@ -7507,13 +7418,6 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
||||
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
|
||||
set_value(ctx, pr->u.var_ref->pvalue, val);
|
||||
return TRUE;
|
||||
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
|
||||
/* Instantiate property and retry (potentially useless) */
|
||||
if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) {
|
||||
JS_FreeValue(ctx, val);
|
||||
return -1;
|
||||
}
|
||||
goto retry;
|
||||
} else {
|
||||
goto read_only_prop;
|
||||
}
|
||||
@@ -7530,11 +7434,6 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
||||
if (prs) {
|
||||
if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {
|
||||
return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags);
|
||||
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
|
||||
/* Instantiate property and retry (potentially useless) */
|
||||
if (JS_AutoInitProperty(ctx, p1, prop, pr, prs))
|
||||
return -1;
|
||||
goto retry2;
|
||||
} else if (!(prs->flags & JS_PROP_WRITABLE)) {
|
||||
goto read_only_prop;
|
||||
} else {
|
||||
@@ -7958,13 +7857,6 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
|
||||
return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable");
|
||||
}
|
||||
|
||||
if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
|
||||
/* Instantiate property and retry */
|
||||
if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
|
||||
return -1;
|
||||
goto redo_prop_update;
|
||||
}
|
||||
|
||||
if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE |
|
||||
JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {
|
||||
if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {
|
||||
@@ -8093,36 +7985,6 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
|
||||
return JS_CreateProperty(ctx, p, prop, val, getter, setter, flags);
|
||||
}
|
||||
|
||||
static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj,
|
||||
JSAtom prop, JSAutoInitIDEnum id,
|
||||
void *opaque, int flags)
|
||||
{
|
||||
JSObject *p;
|
||||
JSProperty *pr;
|
||||
|
||||
if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT)
|
||||
return FALSE;
|
||||
|
||||
p = JS_VALUE_GET_OBJ(this_obj);
|
||||
|
||||
if (find_own_property(&pr, p, prop)) {
|
||||
/* property already exists */
|
||||
abort();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Specialized CreateProperty */
|
||||
pr = add_property(ctx, p, prop, (flags & JS_PROP_C_W_E) | JS_PROP_AUTOINIT);
|
||||
if (unlikely(!pr))
|
||||
return -1;
|
||||
pr->u.init.realm_and_id = (uintptr_t)JS_DupContext(ctx);
|
||||
assert((pr->u.init.realm_and_id & 3) == 0);
|
||||
assert(id <= 3);
|
||||
pr->u.init.realm_and_id |= id;
|
||||
pr->u.init.opaque = opaque;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* shortcut to add or redefine a new property value */
|
||||
int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj,
|
||||
JSAtom prop, JSValue val, int flags)
|
||||
@@ -8270,7 +8132,6 @@ static int JS_CheckDefineGlobalVar(JSContext *ctx, JSAtom prop, int flags)
|
||||
|
||||
p = JS_VALUE_GET_OBJ(ctx->global_obj);
|
||||
prs = find_own_property1(p, prop);
|
||||
/* XXX: should handle JS_PROP_AUTOINIT */
|
||||
if (flags & DEFINE_GLOBAL_LEX_VAR) {
|
||||
if (prs && !(prs->flags & JS_PROP_CONFIGURABLE))
|
||||
goto fail_redeclaration;
|
||||
@@ -8386,7 +8247,6 @@ 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: should handle JS_PROP_AUTOINIT properties? */
|
||||
/* XXX: conformance: do these tests in
|
||||
OP_put_var_ref/OP_get_var_ref ? */
|
||||
if (unlikely(JS_IsUninitialized(pr->u.value))) {
|
||||
@@ -8446,7 +8306,6 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,
|
||||
p = JS_VALUE_GET_OBJ(ctx->global_var_obj);
|
||||
prs = find_own_property(&pr, p, prop);
|
||||
if (prs) {
|
||||
/* XXX: should handle JS_PROP_AUTOINIT properties? */
|
||||
if (flag != 1) {
|
||||
if (unlikely(JS_IsUninitialized(pr->u.value))) {
|
||||
JS_FreeValue(ctx, val);
|
||||
@@ -9792,17 +9651,6 @@ static void js_print_object(JSPrintValueState *s, JSObject *p)
|
||||
} else {
|
||||
js_print_value(s, *pr->u.var_ref->pvalue);
|
||||
}
|
||||
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
|
||||
if (s->options.raw_dump) {
|
||||
js_printf(s, "[autoinit %p %d %p]",
|
||||
(void *)js_autoinit_get_realm(pr),
|
||||
js_autoinit_get_id(pr),
|
||||
(void *)pr->u.init.opaque);
|
||||
} else {
|
||||
/* XXX: could autoinit but need to restart
|
||||
the iteration */
|
||||
js_printf(s, "[autoinit]");
|
||||
}
|
||||
} else {
|
||||
js_print_value(s, pr->u.value);
|
||||
}
|
||||
@@ -13956,8 +13804,6 @@ typedef enum JSParseFunctionEnum {
|
||||
JS_PARSE_FUNC_SETTER,
|
||||
JS_PARSE_FUNC_METHOD,
|
||||
JS_PARSE_FUNC_CLASS_STATIC_INIT,
|
||||
JS_PARSE_FUNC_CLASS_CONSTRUCTOR,
|
||||
JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR,
|
||||
} JSParseFunctionEnum;
|
||||
|
||||
typedef struct JSFunctionDef {
|
||||
@@ -25576,13 +25422,10 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
|
||||
}
|
||||
break;
|
||||
case JS_DEF_CFUNC:
|
||||
if (atom == JS_ATOM_Symbol_toPrimitive) {
|
||||
/* Symbol.toPrimitive functions are not writable */
|
||||
prop_flags = JS_PROP_CONFIGURABLE;
|
||||
}
|
||||
JS_DefineAutoInitProperty(ctx, obj, atom, JS_AUTOINIT_ID_PROP,
|
||||
(void *)e, prop_flags);
|
||||
return 0;
|
||||
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;
|
||||
case JS_DEF_CGETSET: /* XXX: use autoinit again ? */
|
||||
case JS_DEF_CGETSET_MAGIC:
|
||||
{
|
||||
@@ -25619,11 +25462,15 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
|
||||
case JS_DEF_PROP_UNDEFINED:
|
||||
val = JS_NULL;
|
||||
break;
|
||||
case JS_DEF_PROP_STRING:
|
||||
case JS_DEF_OBJECT:
|
||||
JS_DefineAutoInitProperty(ctx, obj, atom, JS_AUTOINIT_ID_PROP,
|
||||
(void *)e, prop_flags);
|
||||
return 0;
|
||||
case JS_DEF_PROP_STRING:
|
||||
val = JS_NewAtomString(ctx, e->u.str);
|
||||
break;
|
||||
|
||||
case JS_DEF_OBJECT:
|
||||
val = JS_NewObject(ctx);
|
||||
if (JS_IsException(val)) return -1;
|
||||
JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@@ -25673,7 +25520,7 @@ static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val)
|
||||
}
|
||||
|
||||
static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1,
|
||||
int flags, int kind)
|
||||
int flags)
|
||||
{
|
||||
JSValue obj, r, val, key, value;
|
||||
JSObject *p;
|
||||
@@ -25707,34 +25554,10 @@ static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1,
|
||||
if (!(desc.flags & JS_PROP_ENUMERABLE))
|
||||
continue;
|
||||
}
|
||||
switch(kind) {
|
||||
default:
|
||||
case JS_ITERATOR_KIND_KEY:
|
||||
val = JS_AtomToValue(ctx, atom);
|
||||
if (JS_IsException(val))
|
||||
goto exception;
|
||||
break;
|
||||
case JS_ITERATOR_KIND_VALUE:
|
||||
val = JS_GetProperty(ctx, obj, atom);
|
||||
if (JS_IsException(val))
|
||||
goto exception;
|
||||
break;
|
||||
case JS_ITERATOR_KIND_KEY_AND_VALUE:
|
||||
val = JS_NewArray(ctx);
|
||||
if (JS_IsException(val))
|
||||
goto exception;
|
||||
key = JS_AtomToValue(ctx, atom);
|
||||
if (JS_IsException(key))
|
||||
goto exception1;
|
||||
if (JS_CreateDataPropertyUint32(ctx, val, 0, key, JS_PROP_THROW) < 0)
|
||||
goto exception1;
|
||||
value = JS_GetProperty(ctx, obj, atom);
|
||||
if (JS_IsException(value))
|
||||
goto exception1;
|
||||
if (JS_CreateDataPropertyUint32(ctx, val, 1, value, JS_PROP_THROW) < 0)
|
||||
goto exception1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (JS_CreateDataPropertyUint32(ctx, r, j++, val, 0) < 0)
|
||||
goto exception;
|
||||
}
|
||||
@@ -25751,13 +25574,6 @@ done:
|
||||
return r;
|
||||
}
|
||||
|
||||
static JSValue js_object_keys(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv, int kind)
|
||||
{
|
||||
return JS_GetOwnPropertyNames2(ctx, argv[0],
|
||||
JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK, kind);
|
||||
}
|
||||
|
||||
static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv, int freeze_flag)
|
||||
{
|
||||
@@ -25853,25 +25669,10 @@ static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
|
||||
return JS_ToLengthFree(ctx, pres, len_val);
|
||||
}
|
||||
|
||||
static __exception int js_set_length64(JSContext *ctx, JSValueConst obj,
|
||||
int64_t len)
|
||||
{
|
||||
/* Intrinsic arrays have fixed length - cannot set */
|
||||
if (JS_VALUE_GET_TAG(obj) == JS_TAG_ARRAY) {
|
||||
JS_ThrowTypeError(ctx, "cannot change length of array");
|
||||
return -1;
|
||||
}
|
||||
return JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, len));
|
||||
}
|
||||
|
||||
int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres) {
|
||||
return js_get_length64(ctx, pres, obj);
|
||||
}
|
||||
|
||||
int JS_SetLength(JSContext *ctx, JSValueConst obj, int64_t len) {
|
||||
return js_set_length64(ctx, obj, len);
|
||||
}
|
||||
|
||||
static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
@@ -27292,7 +27093,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
|
||||
if (!JS_IsNull(jsc->property_list))
|
||||
tab = JS_DupValue(ctx, jsc->property_list);
|
||||
else
|
||||
tab = js_object_keys(ctx, JS_NULL, 1, (JSValueConst *)&val, JS_ITERATOR_KIND_KEY);
|
||||
tab = JS_GetOwnPropertyNames2(ctx, val, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK);
|
||||
if (JS_IsException(tab))
|
||||
goto exception;
|
||||
if (js_get_length64(ctx, &len, tab))
|
||||
@@ -29468,8 +29269,7 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
||||
if (JS_IsObject(arg) && !JS_IsArray(ctx, arg)) {
|
||||
/* Return object keys */
|
||||
return JS_GetOwnPropertyNames2(ctx, arg,
|
||||
JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK,
|
||||
JS_ITERATOR_KIND_KEY);
|
||||
JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK);
|
||||
}
|
||||
|
||||
/* array(text) - split into characters */
|
||||
|
||||
@@ -282,7 +282,6 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
|
||||
#define JS_PROP_NORMAL (0 << 4)
|
||||
#define JS_PROP_GETSET (1 << 4)
|
||||
#define JS_PROP_VARREF (2 << 4) /* used internally */
|
||||
#define JS_PROP_AUTOINIT (3 << 4) /* used internally */
|
||||
|
||||
/* flags for JS_DefineProperty */
|
||||
#define JS_PROP_HAS_SHIFT 8
|
||||
@@ -672,7 +671,6 @@ 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);
|
||||
int JS_SetLength(JSContext *ctx, JSValueConst obj, int64_t len);
|
||||
JSValue JS_ArrayPush(JSContext *ctx, JSValueConst obj, JSValueConst val);
|
||||
JSValue JS_ArrayPop(JSContext *ctx, JSValueConst obj);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user