quicken
This commit is contained in:
2
Makefile
2
Makefile
@@ -56,7 +56,7 @@ static:
|
||||
# Bootstrap: build cell from scratch using meson (only needed once)
|
||||
# Also installs core scripts to ~/.cell/core
|
||||
bootstrap:
|
||||
meson setup build_bootstrap -Dbuildtype=debugoptimized -Db_sanitize=address
|
||||
meson setup build_bootstrap -Dbuildtype=debugoptimized
|
||||
meson compile -C build_bootstrap
|
||||
cp build_bootstrap/cell .
|
||||
cp build_bootstrap/libcell_runtime.dylib .
|
||||
|
||||
@@ -162,10 +162,6 @@ globalThis.log = function(name, args) {
|
||||
}
|
||||
}
|
||||
|
||||
log.console(
|
||||
'hello'
|
||||
)
|
||||
|
||||
function disrupt(err)
|
||||
{
|
||||
if (is_function(err.toString)) {
|
||||
|
||||
@@ -214,7 +214,7 @@ static void nota_encode_value(NotaEncodeContext *enc, JSValueConst val, JSValueC
|
||||
nota_stack_push(enc, replaced);
|
||||
|
||||
JSValue to_json = JS_GetPropertyStr(ctx, replaced, "toJSON");
|
||||
if (JS_IsFunction(ctx, to_json)) {
|
||||
if (JS_IsFunction(to_json)) {
|
||||
JSValue result = JS_Call(ctx, to_json, replaced, 0, NULL);
|
||||
JS_FreeValue(ctx, to_json);
|
||||
if (!JS_IsException(result)) {
|
||||
@@ -239,14 +239,14 @@ static void nota_encode_value(NotaEncodeContext *enc, JSValueConst val, JSValueC
|
||||
uint32_t non_function_count = 0;
|
||||
for (uint32_t i = 0; i < plen; i++) {
|
||||
JSValue prop_val = JS_GetProperty(ctx, replaced, ptab[i].atom);
|
||||
if (!JS_IsFunction(ctx, prop_val)) non_function_count++;
|
||||
if (!JS_IsFunction(prop_val)) non_function_count++;
|
||||
JS_FreeValue(ctx, prop_val);
|
||||
}
|
||||
|
||||
nota_write_record(&enc->nb, non_function_count);
|
||||
for (uint32_t i = 0; i < plen; i++) {
|
||||
JSValue prop_val = JS_GetProperty(ctx, replaced, ptab[i].atom);
|
||||
if (!JS_IsFunction(ctx, prop_val)) {
|
||||
if (!JS_IsFunction(prop_val)) {
|
||||
const char *prop_name = JS_AtomToCString(ctx, ptab[i].atom);
|
||||
JSValue prop_key = JS_AtomToValue(ctx, ptab[i].atom);
|
||||
nota_write_text(&enc->nb, prop_name);
|
||||
@@ -338,7 +338,7 @@ static JSValue js_nota_encode(JSContext *ctx, JSValueConst this_val, int argc, J
|
||||
enc->ctx = ctx;
|
||||
enc->visitedStack = JS_NewArray(ctx);
|
||||
enc->cycle = 0;
|
||||
enc->replacer = (argc > 1 && JS_IsFunction(ctx, argv[1])) ? argv[1] : JS_NULL;
|
||||
enc->replacer = (argc > 1 && JS_IsFunction(argv[1])) ? argv[1] : JS_NULL;
|
||||
|
||||
nota_buffer_init(&enc->nb, 128);
|
||||
nota_encode_value(enc, argv[0], JS_NULL, JS_NewString(ctx, ""));
|
||||
@@ -366,7 +366,7 @@ static JSValue js_nota_decode(JSContext *js, JSValueConst self, int argc, JSValu
|
||||
if (nota == -1) return JS_EXCEPTION;
|
||||
if (!nota) return JS_NULL;
|
||||
|
||||
JSValue reviver = (argc > 1 && JS_IsFunction(js, argv[1])) ? argv[1] : JS_NULL;
|
||||
JSValue reviver = (argc > 1 && JS_IsFunction(argv[1])) ? argv[1] : JS_NULL;
|
||||
JSValue ret;
|
||||
JSValue holder = JS_NewObject(js);
|
||||
js_do_nota_decode(js, &ret, (char*)nota, holder, JS_NewString(js, ""), reviver);
|
||||
|
||||
@@ -145,7 +145,7 @@ static JSValue js_enet_host_service(JSContext *ctx, JSValueConst this_val, int a
|
||||
ENetHost *host = JS_GetOpaque(this_val, enet_host_id);
|
||||
if (!host) return JS_EXCEPTION;
|
||||
|
||||
if (argc < 1 || !JS_IsFunction(ctx, argv[0])) return JS_ThrowTypeError(ctx, "Expected a callback function as first argument");
|
||||
if (argc < 1 || !JS_IsFunction(argv[0])) return JS_ThrowTypeError(ctx, "Expected a callback function as first argument");
|
||||
JSValue callback = JS_DupValue(ctx, argv[0]);
|
||||
|
||||
double secs;
|
||||
|
||||
@@ -102,7 +102,7 @@ static void scores_cb(PDScoresList *scores, const char *errorMessage) {
|
||||
JSC_SCALL(scoreboards_addScore,
|
||||
if (!pd_scoreboards) return JS_ThrowInternalError(js, "scoreboards not initialized");
|
||||
uint32_t value = (uint32_t)js2number(js, argv[1]);
|
||||
if (argc > 2 && JS_IsFunction(js, argv[2])) {
|
||||
if (argc > 2 && JS_IsFunction(argv[2])) {
|
||||
g_scoreboard_js = js;
|
||||
JS_FreeValue(js, g_add_score_callback);
|
||||
g_add_score_callback = JS_DupValue(js, argv[2]);
|
||||
@@ -112,7 +112,7 @@ JSC_SCALL(scoreboards_addScore,
|
||||
|
||||
JSC_SCALL(scoreboards_getPersonalBest,
|
||||
if (!pd_scoreboards) return JS_ThrowInternalError(js, "scoreboards not initialized");
|
||||
if (argc > 1 && JS_IsFunction(js, argv[1])) {
|
||||
if (argc > 1 && JS_IsFunction(argv[1])) {
|
||||
g_scoreboard_js = js;
|
||||
JS_FreeValue(js, g_personal_best_callback);
|
||||
g_personal_best_callback = JS_DupValue(js, argv[1]);
|
||||
@@ -129,7 +129,7 @@ JSC_CCALL(scoreboards_freeScore,
|
||||
|
||||
JSC_CCALL(scoreboards_getScoreboards,
|
||||
if (!pd_scoreboards) return JS_ThrowInternalError(js, "scoreboards not initialized");
|
||||
if (argc > 0 && JS_IsFunction(js, argv[0])) {
|
||||
if (argc > 0 && JS_IsFunction(argv[0])) {
|
||||
g_scoreboard_js = js;
|
||||
JS_FreeValue(js, g_boards_list_callback);
|
||||
g_boards_list_callback = JS_DupValue(js, argv[0]);
|
||||
@@ -145,7 +145,7 @@ JSC_CCALL(scoreboards_freeBoardsList,
|
||||
|
||||
JSC_SCALL(scoreboards_getScores,
|
||||
if (!pd_scoreboards) return JS_ThrowInternalError(js, "scoreboards not initialized");
|
||||
if (argc > 1 && JS_IsFunction(js, argv[1])) {
|
||||
if (argc > 1 && JS_IsFunction(argv[1])) {
|
||||
g_scoreboard_js = js;
|
||||
JS_FreeValue(js, g_scores_callback);
|
||||
g_scores_callback = JS_DupValue(js, argv[1]);
|
||||
|
||||
@@ -111,7 +111,7 @@ JSC_CCALL(actor_on_exception,
|
||||
)
|
||||
|
||||
JSC_CCALL(actor_clock,
|
||||
if (!JS_IsFunction(js, argv[0]))
|
||||
if (!JS_IsFunction(argv[0]))
|
||||
return JS_ThrowReferenceError(js, "Argument must be a function.");
|
||||
|
||||
cell_rt *actor = JS_GetContextOpaque(js);
|
||||
@@ -119,7 +119,7 @@ JSC_CCALL(actor_clock,
|
||||
)
|
||||
|
||||
JSC_CCALL(actor_delay,
|
||||
if (!JS_IsFunction(js, argv[0]))
|
||||
if (!JS_IsFunction(argv[0]))
|
||||
return JS_ThrowReferenceError(js, "Argument must be a function.");
|
||||
|
||||
cell_rt *actor = JS_GetContextOpaque(js);
|
||||
|
||||
@@ -88,7 +88,7 @@ static void encode_object_properties(WotaEncodeContext *enc, JSValueConst val, J
|
||||
|
||||
for (uint32_t i = 0; i < plen; i++) {
|
||||
JSValue prop_val = JS_GetProperty(ctx, val, ptab[i].atom);
|
||||
if (!JS_IsFunction(ctx, prop_val)) {
|
||||
if (!JS_IsFunction(prop_val)) {
|
||||
atoms[non_function_count] = ptab[i].atom;
|
||||
props[non_function_count++] = prop_val;
|
||||
} else
|
||||
@@ -200,7 +200,7 @@ static void wota_encode_value(WotaEncodeContext *enc, JSValueConst val, JSValueC
|
||||
}
|
||||
wota_stack_push(enc, replaced);
|
||||
JSValue to_json = JS_GetPropertyStr(ctx, replaced, "toJSON");
|
||||
if (JS_IsFunction(ctx, to_json)) {
|
||||
if (JS_IsFunction(to_json)) {
|
||||
JSValue result = JS_Call(ctx, to_json, replaced, 0, NULL);
|
||||
JS_FreeValue(ctx, to_json);
|
||||
if (!JS_IsException(result)) {
|
||||
@@ -359,7 +359,7 @@ static JSValue js_wota_encode(JSContext *ctx, JSValueConst this_val, int argc, J
|
||||
{
|
||||
if (argc < 1) return JS_ThrowTypeError(ctx, "wota.encode requires at least 1 argument");
|
||||
size_t total_bytes;
|
||||
void *wota = value2wota(ctx, argv[0], JS_IsFunction(ctx,argv[1]) ? argv[1] : JS_NULL, &total_bytes);
|
||||
void *wota = value2wota(ctx, argv[0], JS_IsFunction(argv[1]) ? argv[1] : JS_NULL, &total_bytes);
|
||||
JSValue ret = js_new_blob_stoned_copy(ctx, wota, total_bytes);
|
||||
free(wota);
|
||||
return ret;
|
||||
@@ -372,7 +372,7 @@ static JSValue js_wota_decode(JSContext *ctx, JSValueConst this_val, int argc, J
|
||||
uint8_t *buf = js_get_blob_data(ctx, &len, argv[0]);
|
||||
if (buf == (uint8_t *)-1) return JS_EXCEPTION;
|
||||
if (!buf || len == 0) return JS_ThrowTypeError(ctx, "No blob data present");
|
||||
JSValue reviver = (argc > 1 && JS_IsFunction(ctx, argv[1])) ? argv[1] : JS_NULL;
|
||||
JSValue reviver = (argc > 1 && JS_IsFunction(argv[1])) ? argv[1] : JS_NULL;
|
||||
char *data_ptr = (char *)buf;
|
||||
JSValue result = JS_NULL;
|
||||
JSValue holder = JS_NewObject(ctx);
|
||||
|
||||
@@ -101,13 +101,11 @@ DEF( tail_call, 3, 1, 0, npop) /* arguments are not counted in n_pop */
|
||||
DEF( call_method, 3, 2, 1, npop) /* arguments are not counted in n_pop */
|
||||
DEF(tail_call_method, 3, 2, 0, npop) /* arguments are not counted in n_pop */
|
||||
DEF( array_from, 3, 0, 1, npop) /* arguments are not counted in n_pop */
|
||||
DEF( apply, 3, 3, 1, u16)
|
||||
DEF( return, 1, 1, 0, none)
|
||||
DEF( return_undef, 1, 0, 0, none)
|
||||
DEF( throw, 1, 1, 0, none)
|
||||
DEF( throw_error, 6, 0, 0, atom_u8)
|
||||
DEF( eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */
|
||||
DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */
|
||||
DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
|
||||
bytecode string */
|
||||
|
||||
|
||||
381
source/quickjs.c
381
source/quickjs.c
@@ -103,7 +103,7 @@
|
||||
/* dump profiling statistics (counters and sampling) when freeing the runtime */
|
||||
//#define DUMP_PROFILE
|
||||
|
||||
#define RC_TRACE
|
||||
//#define RC_TRACE
|
||||
|
||||
/* test the GC by forcing it before each object allocation */
|
||||
//#define FORCE_GC_AT_MALLOC
|
||||
@@ -1034,6 +1034,8 @@ static void gc_decref_child_dbg(JSRuntime *rt, JSGCObjectHeader *parent,
|
||||
const char *file, int line);
|
||||
#endif
|
||||
|
||||
static void gc_decref_child(JSRuntime *rt, JSGCObjectHeader *p);
|
||||
|
||||
int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val);
|
||||
static blob *js_get_blob(JSContext *ctx, JSValueConst val);
|
||||
static JSValue JS_ToStringFree(JSContext *ctx, JSValue val);
|
||||
@@ -4900,12 +4902,6 @@ static BOOL js_is_bytecode_function(JSValueConst val)
|
||||
return f->kind == JS_FUNC_KIND_BYTECODE;
|
||||
}
|
||||
|
||||
/* Check if a value is a function that uses proxy-call syntax (fn.a -> fn("a")) */
|
||||
static BOOL js_is_proxy_callable(JSValueConst v)
|
||||
{
|
||||
return JS_VALUE_GET_TAG(v) == JS_TAG_FUNCTION;
|
||||
}
|
||||
|
||||
/* return NULL without exception if not a function or no bytecode */
|
||||
static JSFunctionBytecode *JS_GetFunctionBytecode(JSValueConst val)
|
||||
{
|
||||
@@ -5194,9 +5190,8 @@ static int js_intrinsic_array_set(JSContext *ctx, JSArray *arr, uint32_t idx, JS
|
||||
}
|
||||
|
||||
if (idx >= arr->len) {
|
||||
for (uint32_t i = arr->len; i < idx; i++) {
|
||||
for (uint32_t i = arr->len; i < idx; i++)
|
||||
arr->values[i] = JS_NULL;
|
||||
}
|
||||
arr->len = idx + 1;
|
||||
arr->values[idx] = val;
|
||||
} else {
|
||||
@@ -7984,12 +7979,6 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop)
|
||||
return -1;
|
||||
}
|
||||
|
||||
BOOL JS_IsFunction(JSContext *ctx, JSValueConst val)
|
||||
{
|
||||
(void)ctx; /* unused */
|
||||
return JS_VALUE_GET_TAG(val) == JS_TAG_FUNCTION;
|
||||
}
|
||||
|
||||
BOOL JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, int magic)
|
||||
{
|
||||
JSFunction *f;
|
||||
@@ -8336,7 +8325,6 @@ static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val)
|
||||
uint32_t tag;
|
||||
JSValue ret;
|
||||
|
||||
redo:
|
||||
tag = JS_VALUE_GET_NORM_TAG(val);
|
||||
switch(tag) {
|
||||
case JS_TAG_FLOAT64:
|
||||
@@ -9982,7 +9970,6 @@ static __exception int JS_CopyDataProperties(JSContext *ctx,
|
||||
JSObject *pexcl = NULL;
|
||||
int ret, gpn_flags;
|
||||
JSPropertyDescriptor desc;
|
||||
BOOL is_enumerable;
|
||||
|
||||
if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT)
|
||||
return 0;
|
||||
@@ -10821,39 +10808,32 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
#endif
|
||||
/* Proxy method-call: detect [func, "name", ...args]
|
||||
and rewrite as func("name", [args]) */
|
||||
if (js_is_proxy_callable(call_argv[-2])) {
|
||||
if (!JS_IsFunction(ctx, call_argv[-1])) {
|
||||
int t = JS_VALUE_GET_TAG(call_argv[-1]);
|
||||
if (t == JS_TAG_STRING || t == JS_TAG_SYMBOL)
|
||||
is_proxy = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_proxy) {
|
||||
if (JS_IsFunction(call_argv[-2])) {
|
||||
JSValue name = call_argv[-1];
|
||||
if (!JS_IsText(name)) {
|
||||
ret_val = JS_ThrowTypeError(ctx, "second argument must be a string");
|
||||
goto exception;
|
||||
}
|
||||
|
||||
JSValue args = JS_NewArrayLen(ctx, call_argc);
|
||||
if (unlikely(JS_IsException(args)))
|
||||
goto exception;
|
||||
|
||||
/* Move args into the array, then null out stack slots. */
|
||||
JSArray *ar = JS_VALUE_GET_ARRAY(args);
|
||||
for (i = 0; i < call_argc; i++) {
|
||||
int r = JS_SetPropertyNumber(ctx, args, i, call_argv[i]);
|
||||
ar->values[i] = call_argv[i];
|
||||
call_argv[i] = JS_NULL;
|
||||
if (unlikely(r < 0)) {
|
||||
JS_FreeValue(ctx, args);
|
||||
goto exception;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
JSValue proxy_argv[2];
|
||||
proxy_argv[0] = name; /* still owned by stack; freed by normal cleanup */
|
||||
proxy_argv[1] = args;
|
||||
JSValue proxy_argv[2];
|
||||
proxy_argv[0] = name; /* still owned by stack; freed by normal cleanup */
|
||||
proxy_argv[1] = args;
|
||||
|
||||
ret_val = JS_CallInternal(ctx, call_argv[-2], JS_NULL,
|
||||
2, proxy_argv, 0);
|
||||
JS_FreeValue(ctx, args);
|
||||
}
|
||||
ret_val = JS_CallInternal(ctx, call_argv[-2], JS_NULL,
|
||||
2, proxy_argv, 0);
|
||||
JS_FreeValue(ctx, args);
|
||||
} else {
|
||||
ret_val = JS_CallInternal(ctx, call_argv[-1], call_argv[-2],
|
||||
call_argc, call_argv, 0);
|
||||
@@ -10878,57 +10858,15 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
if (unlikely(JS_IsException(ret_val)))
|
||||
goto exception;
|
||||
call_argv = sp - call_argc;
|
||||
JSArray *ar = JS_VALUE_GET_ARRAY(ret_val);
|
||||
for (i = 0; i < call_argc; i++) {
|
||||
ret = JS_SetPropertyNumber(ctx, ret_val, i, call_argv[i]);
|
||||
ar->values[i] = call_argv[i];
|
||||
call_argv[i] = JS_NULL;
|
||||
if (ret < 0) {
|
||||
JS_FreeValue(ctx, ret_val);
|
||||
goto exception;
|
||||
}
|
||||
}
|
||||
sp -= call_argc;
|
||||
*sp++ = ret_val;
|
||||
}
|
||||
BREAK;
|
||||
|
||||
CASE(OP_apply):
|
||||
{
|
||||
int magic;
|
||||
BOOL is_proxy = FALSE;
|
||||
|
||||
magic = get_u16(pc);
|
||||
pc += 2;
|
||||
sf->cur_pc = pc;
|
||||
|
||||
/* Proxy method-call with spread: detect ["name", func, args_array]
|
||||
and rewrite as func("name", args_array) */
|
||||
if (js_is_proxy_callable(sp[-2])) {
|
||||
if (!JS_IsFunction(ctx, sp[-3])) {
|
||||
int t = JS_VALUE_GET_TAG(sp[-3]);
|
||||
if (t == JS_TAG_STRING || t == JS_TAG_SYMBOL)
|
||||
is_proxy = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_proxy) {
|
||||
JSValue proxy_argv[2];
|
||||
proxy_argv[0] = sp[-3]; /* name */
|
||||
proxy_argv[1] = sp[-1]; /* args array already built by bytecode */
|
||||
|
||||
ret_val = JS_CallInternal(ctx, sp[-2], JS_NULL,
|
||||
2, proxy_argv, 0);
|
||||
} else {
|
||||
ret_val = js_function_apply(ctx, sp[-3], 2, (JSValueConst *)&sp[-2], magic);
|
||||
}
|
||||
if (unlikely(JS_IsException(ret_val)))
|
||||
goto exception;
|
||||
JS_FreeValue(ctx, sp[-3]);
|
||||
JS_FreeValue(ctx, sp[-2]);
|
||||
JS_FreeValue(ctx, sp[-1]);
|
||||
sp -= 3;
|
||||
*sp++ = ret_val;
|
||||
}
|
||||
BREAK;
|
||||
CASE(OP_return):
|
||||
ret_val = *--sp;
|
||||
goto done;
|
||||
@@ -10992,51 +10930,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
*sp++ = ret_val;
|
||||
}
|
||||
BREAK;
|
||||
/* could merge with OP_apply */
|
||||
CASE(OP_apply_eval):
|
||||
{
|
||||
int scope_idx;
|
||||
uint32_t len;
|
||||
JSValue *tab;
|
||||
JSValueConst obj;
|
||||
|
||||
scope_idx = get_u16(pc) + ARG_SCOPE_END;
|
||||
pc += 2;
|
||||
sf->cur_pc = pc;
|
||||
/* Fast path: check arity before building arg list */
|
||||
if (JS_VALUE_GET_TAG(sp[-2]) == JS_TAG_FUNCTION &&
|
||||
JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_ARRAY) {
|
||||
JSFunction *callee = JS_VALUE_GET_FUNCTION(sp[-2]);
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(sp[-1]);
|
||||
if (unlikely(arr->len > callee->length)) {
|
||||
JS_ThrowTypeError(ctx, "too many arguments");
|
||||
goto exception;
|
||||
}
|
||||
}
|
||||
tab = build_arg_list(ctx, &len, sp[-1]);
|
||||
if (!tab)
|
||||
goto exception;
|
||||
if (js_same_value(ctx, sp[-2], ctx->eval_obj)) {
|
||||
if (len >= 1)
|
||||
obj = tab[0];
|
||||
else
|
||||
obj = JS_NULL;
|
||||
ret_val = JS_EvalObject(ctx, JS_NULL, obj,
|
||||
JS_EVAL_TYPE_DIRECT, scope_idx);
|
||||
} else {
|
||||
ret_val = JS_Call(ctx, sp[-2], JS_NULL, len,
|
||||
(JSValueConst *)tab);
|
||||
}
|
||||
free_arg_list(ctx, tab, len);
|
||||
if (unlikely(JS_IsException(ret_val)))
|
||||
goto exception;
|
||||
JS_FreeValue(ctx, sp[-2]);
|
||||
JS_FreeValue(ctx, sp[-1]);
|
||||
sp -= 2;
|
||||
*sp++ = ret_val;
|
||||
}
|
||||
BREAK;
|
||||
|
||||
CASE(OP_regexp):
|
||||
{
|
||||
sp[-2] = js_regexp_constructor_internal(ctx, sp[-2], sp[-1]);
|
||||
@@ -11617,7 +11510,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
obj = sp[-1];
|
||||
|
||||
/* Functions don't support property access in cell script */
|
||||
if (js_is_proxy_callable(obj)) {
|
||||
if (JS_IsFunction(obj)) {
|
||||
JS_ThrowTypeError(ctx, "cannot get property of function");
|
||||
goto exception;
|
||||
}
|
||||
@@ -11704,7 +11597,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
|
||||
/* Proxy method-call sugar: func.name(...) -> func("name", [args...])
|
||||
OP_get_field2 is only emitted when a call immediately follows. */
|
||||
if (js_is_proxy_callable(obj)) {
|
||||
if (JS_IsFunction(obj)) {
|
||||
val = JS_AtomToValue(ctx, atom); /* "name" */
|
||||
if (unlikely(JS_IsException(val)))
|
||||
goto exception;
|
||||
@@ -11779,8 +11672,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
profile_record_prop_site(rt, b, (uint32_t)(pc - b->byte_code_buf), atom);
|
||||
#endif
|
||||
/* Functions don't support property assignment in cell script */
|
||||
if (js_is_proxy_callable(sp[-2])) {
|
||||
JS_ThrowTypeError(ctx, "cannot set property of function");
|
||||
if (!JS_IsObject(sp[-2])) {
|
||||
JS_ThrowTypeError(ctx, "tried to set property of non-object");
|
||||
goto exception;
|
||||
}
|
||||
|
||||
@@ -11829,14 +11722,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
CASE(OP_define_method):
|
||||
CASE(OP_define_method_computed):
|
||||
{
|
||||
JSValue getter, setter, value;
|
||||
JSValue value;
|
||||
JSValueConst obj;
|
||||
JSAtom atom;
|
||||
int ret, op_flags;
|
||||
BOOL is_computed;
|
||||
#define OP_DEFINE_METHOD_METHOD 0
|
||||
#define OP_DEFINE_METHOD_GETTER 1
|
||||
#define OP_DEFINE_METHOD_SETTER 2
|
||||
#define OP_DEFINE_METHOD_ENUMERABLE 4
|
||||
|
||||
is_computed = (opcode == OP_define_method_computed);
|
||||
@@ -11854,8 +11745,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
obj = sp[-2 - is_computed];
|
||||
op_flags &= 3;
|
||||
value = JS_NULL;
|
||||
getter = JS_NULL;
|
||||
setter = JS_NULL;
|
||||
|
||||
if (op_flags == OP_DEFINE_METHOD_METHOD) {
|
||||
value = sp[-1];
|
||||
}
|
||||
@@ -11884,13 +11774,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
CASE(OP_get_array_el):
|
||||
{
|
||||
JSValue val;
|
||||
|
||||
/* Functions don't support property access in cell script */
|
||||
if (js_is_proxy_callable(sp[-2])) {
|
||||
JS_ThrowTypeError(ctx, "cannot get property of function");
|
||||
goto exception;
|
||||
}
|
||||
|
||||
sf->cur_pc = pc;
|
||||
val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);
|
||||
JS_FreeValue(ctx, sp[-2]);
|
||||
@@ -11904,35 +11787,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
CASE(OP_get_array_el2):
|
||||
{
|
||||
JSValue val;
|
||||
|
||||
/* Proxy method-call sugar for bracket calls: func[key](...) */
|
||||
if (js_is_proxy_callable(sp[-2])) {
|
||||
/* Keep [func, key] and normalize key to property-key (string/symbol). */
|
||||
switch (JS_VALUE_GET_TAG(sp[-1])) {
|
||||
case JS_TAG_INT:
|
||||
/* Convert integer to string */
|
||||
sf->cur_pc = pc;
|
||||
ret_val = JS_ToString(ctx, sp[-1]);
|
||||
if (JS_IsException(ret_val))
|
||||
goto exception;
|
||||
JS_FreeValue(ctx, sp[-1]);
|
||||
sp[-1] = ret_val;
|
||||
break;
|
||||
case JS_TAG_STRING:
|
||||
case JS_TAG_SYMBOL:
|
||||
break;
|
||||
default:
|
||||
sf->cur_pc = pc;
|
||||
ret_val = JS_ToPropertyKey(ctx, sp[-1]);
|
||||
if (JS_IsException(ret_val))
|
||||
goto exception;
|
||||
JS_FreeValue(ctx, sp[-1]);
|
||||
sp[-1] = ret_val;
|
||||
break;
|
||||
}
|
||||
BREAK; /* skip JS_GetPropertyValue, keep [func, key] on stack */
|
||||
}
|
||||
|
||||
sf->cur_pc = pc;
|
||||
val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);
|
||||
sp[-1] = val;
|
||||
@@ -11944,13 +11798,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
CASE(OP_get_array_el3):
|
||||
{
|
||||
JSValue val;
|
||||
|
||||
/* Functions don't support property access in cell script */
|
||||
if (js_is_proxy_callable(sp[-2])) {
|
||||
JS_ThrowTypeError(ctx, "cannot get property of function");
|
||||
goto exception;
|
||||
}
|
||||
|
||||
switch (JS_VALUE_GET_TAG(sp[-2])) {
|
||||
case JS_TAG_INT:
|
||||
case JS_TAG_STRING:
|
||||
@@ -11959,7 +11806,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
break;
|
||||
default:
|
||||
/* must be tested nefore JS_ToPropertyKey */
|
||||
if (unlikely(JS_IsNull(sp[-2]) || JS_IsNull(sp[-2]))) {
|
||||
if (unlikely(JS_IsNull(sp[-2]))) {
|
||||
JS_ThrowTypeError(ctx, "value has no property");
|
||||
goto exception;
|
||||
}
|
||||
@@ -12003,7 +11850,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
JS_ThrowReferenceErrorNotDefined(ctx, atom);
|
||||
JS_FreeAtom(ctx, atom);
|
||||
goto exception;
|
||||
val = JS_NULL;
|
||||
} else {
|
||||
val = JS_GetProperty(ctx, sp[-2], atom);
|
||||
}
|
||||
@@ -12020,7 +11866,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
int ret;
|
||||
|
||||
/* Functions don't support property assignment in cell script */
|
||||
if (js_is_proxy_callable(sp[-3])) {
|
||||
if (JS_IsFunction(sp[-3])) {
|
||||
JS_ThrowTypeError(ctx, "cannot set property of function");
|
||||
goto exception;
|
||||
}
|
||||
@@ -15721,13 +15567,12 @@ static __exception int js_parse_object_literal(JSParseState *s)
|
||||
JSAtom name = JS_ATOM_NULL;
|
||||
const uint8_t *start_ptr;
|
||||
int prop_type;
|
||||
BOOL has_proto;
|
||||
|
||||
if (next_token(s))
|
||||
goto fail;
|
||||
/* XXX: add an initial length that will be patched back */
|
||||
emit_op(s, OP_object);
|
||||
has_proto = FALSE;
|
||||
|
||||
while (s->token.val != '}') {
|
||||
/* specific case for getter/setter */
|
||||
start_ptr = s->token.ptr;
|
||||
@@ -16127,18 +15972,6 @@ duplicate:
|
||||
return js_parse_error(s, "duplicate parameter names not allowed in this context");
|
||||
}
|
||||
|
||||
/* tok = TOK_VAR or TOK_DEF. Return whether a reference
|
||||
must be taken to the variable for proper 'with' or global variable
|
||||
evaluation */
|
||||
/* Note: this function is needed only because variable references are
|
||||
not yet optimized in destructuring */
|
||||
static BOOL need_var_reference(JSParseState *s, int tok)
|
||||
{
|
||||
JSFunctionDef *fd = s->cur_func;
|
||||
/* var now behaves like let - no reference needed */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)
|
||||
{
|
||||
JSAtom name;
|
||||
@@ -16238,20 +16071,11 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
|
||||
var_name = js_parse_destructuring_var(s, tok, is_arg);
|
||||
if (var_name == JS_ATOM_NULL)
|
||||
goto prop_error;
|
||||
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 lvalue1;
|
||||
} else {
|
||||
/* no need to make a reference for let/const */
|
||||
opcode = OP_scope_get_var;
|
||||
scope = s->cur_func->scope_level;
|
||||
label_lvalue = -1;
|
||||
depth_lvalue = 0;
|
||||
}
|
||||
/* no need to make a reference for let/const */
|
||||
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))
|
||||
goto prop_error;
|
||||
@@ -16313,7 +16137,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
|
||||
js_parse_error(s, "invalid destructuring target");
|
||||
goto prop_error;
|
||||
}
|
||||
if (!tok || need_var_reference(s, tok)) {
|
||||
if (!tok) {
|
||||
/* generate reference */
|
||||
/* source -- source source */
|
||||
emit_op(s, OP_dup);
|
||||
@@ -17527,32 +17351,14 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
|
||||
if (s->token.val == '=') {
|
||||
if (next_token(s))
|
||||
goto var_error;
|
||||
if (need_var_reference(s, tok)) {
|
||||
/* Must make a reference for proper `with` semantics */
|
||||
int opcode, scope, label;
|
||||
JSAtom name1;
|
||||
|
||||
emit_op(s, OP_scope_get_var);
|
||||
emit_atom(s, name);
|
||||
emit_u16(s, fd->scope_level);
|
||||
if (get_lvalue(s, &opcode, &scope, &name1, &label, NULL, FALSE, '=') < 0)
|
||||
goto var_error;
|
||||
if (js_parse_assign_expr2(s, parse_flags)) {
|
||||
JS_FreeAtom(ctx, name1);
|
||||
goto var_error;
|
||||
}
|
||||
set_object_name(s, name);
|
||||
put_lvalue(s, opcode, scope, name1, label,
|
||||
PUT_LVALUE_NOKEEP, FALSE);
|
||||
} else {
|
||||
if (js_parse_assign_expr2(s, parse_flags))
|
||||
goto var_error;
|
||||
set_object_name(s, name);
|
||||
emit_op(s, (tok == TOK_DEF || tok == TOK_VAR) ?
|
||||
OP_scope_put_var_init : OP_scope_put_var);
|
||||
emit_atom(s, name);
|
||||
emit_u16(s, fd->scope_level);
|
||||
}
|
||||
if (js_parse_assign_expr2(s, parse_flags))
|
||||
goto var_error;
|
||||
set_object_name(s, name);
|
||||
emit_op(s, (tok == TOK_DEF || tok == TOK_VAR) ?
|
||||
OP_scope_put_var_init : OP_scope_put_var);
|
||||
emit_atom(s, name);
|
||||
emit_u16(s, fd->scope_level);
|
||||
} else {
|
||||
if (tok == TOK_DEF) {
|
||||
js_parse_error(s, "missing initializer for const variable");
|
||||
@@ -20198,12 +20004,6 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
|
||||
dbuf_put_u16(&bc_out, s->scopes[scope].first - ARG_SCOPE_END);
|
||||
}
|
||||
break;
|
||||
case OP_apply_eval: /* convert scope index to adjusted variable index */
|
||||
scope = get_u16(bc_buf + pos + 1);
|
||||
mark_eval_captured_variables(ctx, s, scope);
|
||||
dbuf_putc(&bc_out, op);
|
||||
dbuf_put_u16(&bc_out, s->scopes[scope].first - ARG_SCOPE_END);
|
||||
break;
|
||||
case OP_scope_get_var_checkthis:
|
||||
case OP_scope_get_var_undef:
|
||||
case OP_scope_get_var:
|
||||
@@ -24223,7 +24023,7 @@ JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
|
||||
|
||||
static int check_function(JSContext *ctx, JSValueConst obj)
|
||||
{
|
||||
if (likely(JS_IsFunction(ctx, obj)))
|
||||
if (likely(JS_IsFunction(obj)))
|
||||
return 0;
|
||||
JS_ThrowTypeError(ctx, "not a function");
|
||||
return -1;
|
||||
@@ -25273,7 +25073,7 @@ static JSValue JS_RegExpExec(JSContext *ctx, JSValueConst r, JSValueConst s)
|
||||
method = JS_GetProperty(ctx, r, JS_ATOM_exec);
|
||||
if (JS_IsException(method))
|
||||
return method;
|
||||
if (JS_IsFunction(ctx, method)) {
|
||||
if (JS_IsFunction(method)) {
|
||||
ret = JS_CallFree(ctx, method, r, 1, &s);
|
||||
if (JS_IsException(ret))
|
||||
return ret;
|
||||
@@ -25593,7 +25393,7 @@ static JSValue js_json_parse(JSContext *ctx, JSValueConst this_val,
|
||||
JS_FreeCString(ctx, str);
|
||||
if (JS_IsException(obj))
|
||||
return obj;
|
||||
if (argc > 1 && JS_IsFunction(ctx, argv[1])) {
|
||||
if (argc > 1 && JS_IsFunction(argv[1])) {
|
||||
reviver = argv[1];
|
||||
root = JS_NewObject(ctx);
|
||||
if (JS_IsException(root)) {
|
||||
@@ -25638,7 +25438,7 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
|
||||
JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);
|
||||
if (JS_IsException(f))
|
||||
goto exception;
|
||||
if (JS_IsFunction(ctx, f)) {
|
||||
if (JS_IsFunction(f)) {
|
||||
v = JS_CallFree(ctx, f, val, 1, &key);
|
||||
JS_FreeValue(ctx, val);
|
||||
val = v;
|
||||
@@ -25662,7 +25462,7 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
|
||||
switch (JS_VALUE_GET_NORM_TAG(val)) {
|
||||
case JS_TAG_ARRAY:
|
||||
case JS_TAG_OBJECT:
|
||||
if (JS_IsFunction(ctx, val))
|
||||
if (JS_IsFunction(val))
|
||||
break;
|
||||
case JS_TAG_STRING:
|
||||
case JS_TAG_STRING_ROPE:
|
||||
@@ -25872,7 +25672,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
|
||||
jsc->stack = JS_NewArray(ctx);
|
||||
if (JS_IsException(jsc->stack))
|
||||
goto exception;
|
||||
if (JS_IsFunction(ctx, replacer)) {
|
||||
if (JS_IsFunction(replacer)) {
|
||||
jsc->replacer_func = replacer;
|
||||
} else {
|
||||
res = JS_IsArray(ctx, replacer);
|
||||
@@ -27027,7 +26827,7 @@ array_fail:
|
||||
}
|
||||
|
||||
/* Handle function - return source or native stub */
|
||||
if (JS_IsFunction(ctx, arg)) {
|
||||
if (JS_IsFunction(arg)) {
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(arg);
|
||||
if (fn->kind == JS_FUNC_KIND_BYTECODE) {
|
||||
JSFunctionBytecode *b = fn->u.func.function_bytecode;
|
||||
@@ -27236,7 +27036,7 @@ static JSValue make_replacement(JSContext *ctx, int argc, JSValueConst *argv, in
|
||||
{
|
||||
JSValue rep;
|
||||
|
||||
if (argc > 2 && JS_IsFunction(ctx, argv[2])) {
|
||||
if (argc > 2 && JS_IsFunction(argv[2])) {
|
||||
JSValue args[2];
|
||||
args[0] = match_val;
|
||||
args[1] = JS_NewInt32(ctx, found);
|
||||
@@ -27259,7 +27059,7 @@ static int JS_IsRegExp(JSContext *ctx, JSValueConst v)
|
||||
JSValue exec = JS_GetPropertyStr(ctx, v, "exec");
|
||||
if (JS_IsException(exec)) return -1;
|
||||
|
||||
int ok = JS_IsFunction(ctx, exec);
|
||||
int ok = JS_IsFunction(exec);
|
||||
JS_FreeValue(ctx, exec);
|
||||
return ok;
|
||||
}
|
||||
@@ -27843,7 +27643,7 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
||||
JSValue result = JS_NewArrayLen(ctx, len);
|
||||
if (JS_IsException(result)) return result;
|
||||
|
||||
if (JS_IsFunction(ctx, argv[1])) {
|
||||
if (JS_IsFunction(argv[1])) {
|
||||
/* Fill with function results */
|
||||
JSValueConst func = argv[1];
|
||||
int arity = 0;
|
||||
@@ -27896,7 +27696,7 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
||||
return result;
|
||||
}
|
||||
|
||||
if (JS_IsFunction(ctx, argv[1])) {
|
||||
if (JS_IsFunction(argv[1])) {
|
||||
/* Map */
|
||||
JSValueConst func = argv[1];
|
||||
int arity = (JSFunction*)JS_VALUE_GET_FUNCTION(argv[1])->length;
|
||||
@@ -28297,7 +28097,7 @@ static JSValue js_cell_array_reduce(JSContext *ctx, JSValueConst this_val,
|
||||
{
|
||||
if (argc < 2) return JS_NULL;
|
||||
if (!JS_IsArray(ctx, argv[0])) return JS_NULL;
|
||||
if (!JS_IsFunction(ctx, argv[1])) return JS_NULL;
|
||||
if (!JS_IsFunction(argv[1])) return JS_NULL;
|
||||
|
||||
JSValueConst arr = argv[0];
|
||||
JSValueConst func = argv[1];
|
||||
@@ -28387,13 +28187,12 @@ static JSValue js_cell_array_for(JSContext *ctx, JSValueConst this_val,
|
||||
{
|
||||
if (argc < 2) return JS_NULL;
|
||||
if (!JS_IsArray(ctx, argv[0])) return JS_NULL;
|
||||
if (!JS_IsFunction(ctx, argv[1])) return JS_NULL;
|
||||
if (!JS_IsFunction(argv[1])) return JS_NULL;
|
||||
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(argv[0]);
|
||||
|
||||
JSValueConst arr = argv[0];
|
||||
JSValueConst func = argv[1];
|
||||
int64_t len;
|
||||
if (js_get_length64(ctx, &len, arr))
|
||||
return JS_EXCEPTION;
|
||||
int len = arr->len;
|
||||
if (len == 0) return JS_NULL;
|
||||
|
||||
int reverse = argc > 2 && JS_ToBool(ctx, argv[2]);
|
||||
@@ -28403,18 +28202,21 @@ static JSValue js_cell_array_for(JSContext *ctx, JSValueConst this_val,
|
||||
int arity = (JSFunction*)JS_VALUE_GET_FUNCTION(argv[1])->length;
|
||||
|
||||
if (reverse) {
|
||||
for (int64_t i = len - 1; i >= 0; i--) {
|
||||
JSValue item = JS_GetPropertyInt64(ctx, arr, i);
|
||||
if (JS_IsException(item)) return JS_EXCEPTION;
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
JSValue result;
|
||||
if (arity == 1) {
|
||||
result = JS_Call(ctx, func, JS_NULL, 1, &item);
|
||||
JSValue item = JS_DupValue(ctx, arr->values[i]);
|
||||
result = JS_CallInternal(ctx, func, JS_NULL, 1, &item, 0);
|
||||
JS_FreeValue(ctx, item);
|
||||
} else {
|
||||
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
|
||||
result = JS_Call(ctx, func, JS_NULL, 2, args);
|
||||
JSValue args[2];
|
||||
args[0] = JS_DupValue(ctx, arr->values[i]);
|
||||
args[1] = JS_NewInt32(ctx, i);
|
||||
result = JS_CallInternal(ctx, func, JS_NULL, 2, args, 0);
|
||||
JS_FreeValue(ctx, args[0]);
|
||||
JS_FreeValue(ctx, args[1]);
|
||||
}
|
||||
JS_FreeValue(ctx, item);
|
||||
|
||||
if (JS_IsException(result)) return JS_EXCEPTION;
|
||||
if (!JS_IsNull(exit_val) && js_strict_eq(ctx, result, exit_val)) {
|
||||
return result;
|
||||
@@ -28422,18 +28224,21 @@ static JSValue js_cell_array_for(JSContext *ctx, JSValueConst this_val,
|
||||
JS_FreeValue(ctx, result);
|
||||
}
|
||||
} else {
|
||||
for (int64_t i = 0; i < len; i++) {
|
||||
JSValue item = JS_GetPropertyInt64(ctx, arr, i);
|
||||
if (JS_IsException(item)) return JS_EXCEPTION;
|
||||
for (int i = 0; i < len; i++) {
|
||||
JSValue result;
|
||||
if (arity == 1) {
|
||||
result = JS_Call(ctx, func, JS_NULL, 1, &item);
|
||||
JSValue item = JS_DupValue(ctx, arr->values[i]);
|
||||
result = JS_CallInternal(ctx, func, JS_NULL, 1, &item, 0);
|
||||
JS_FreeValue(ctx, item);
|
||||
} else {
|
||||
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
|
||||
result = JS_Call(ctx, func, JS_NULL, 2, args);
|
||||
JSValue args[2];
|
||||
args[0] = JS_DupValue(ctx, arr->values[i]);
|
||||
args[1] = JS_NewInt32(ctx, i);
|
||||
result = JS_CallInternal(ctx, func, JS_NULL, 2, args, 0);
|
||||
JS_FreeValue(ctx, args[0]);
|
||||
JS_FreeValue(ctx, args[1]);
|
||||
}
|
||||
JS_FreeValue(ctx, item);
|
||||
|
||||
if (JS_IsException(result)) return JS_EXCEPTION;
|
||||
if (!JS_IsNull(exit_val) && js_strict_eq(ctx, result, exit_val)) {
|
||||
return result;
|
||||
@@ -28466,7 +28271,7 @@ static JSValue js_cell_array_find(JSContext *ctx, JSValueConst this_val,
|
||||
from = reverse ? len - 1 : 0;
|
||||
}
|
||||
|
||||
if (!JS_IsFunction(ctx, argv[1])) {
|
||||
if (!JS_IsFunction(argv[1])) {
|
||||
/* Compare exactly */
|
||||
JSValue target = argv[1];
|
||||
if (reverse) {
|
||||
@@ -28549,7 +28354,7 @@ static JSValue js_cell_array_filter(JSContext *ctx, JSValueConst this_val,
|
||||
{
|
||||
if (argc < 2) return JS_NULL;
|
||||
if (!JS_IsArray(ctx, argv[0])) return JS_NULL;
|
||||
if (!JS_IsFunction(ctx, argv[1])) return JS_NULL;
|
||||
if (!JS_IsFunction(argv[1])) return JS_NULL;
|
||||
|
||||
JSValueConst arr = argv[0];
|
||||
JSValueConst func = argv[1];
|
||||
@@ -28768,7 +28573,7 @@ static JSValue js_cell_object(JSContext *ctx, JSValueConst this_val,
|
||||
JSValue arg = argv[0];
|
||||
|
||||
/* object(object) - shallow mutable copy */
|
||||
if (JS_IsObject(arg) && !JS_IsArray(ctx, arg) && !JS_IsFunction(ctx, arg)) {
|
||||
if (JS_IsObject(arg) && !JS_IsArray(ctx, arg) && !JS_IsFunction(arg)) {
|
||||
if (argc < 2 || JS_IsNull(argv[1])) {
|
||||
/* Shallow copy */
|
||||
JSValue result = JS_NewObject(ctx);
|
||||
@@ -28896,7 +28701,7 @@ static JSValue js_cell_object(JSContext *ctx, JSValueConst this_val,
|
||||
JSValue val;
|
||||
if (argc < 2 || JS_IsNull(argv[1])) {
|
||||
val = JS_TRUE;
|
||||
} else if (JS_IsFunction(ctx, argv[1])) {
|
||||
} else if (JS_IsFunction(argv[1])) {
|
||||
val = JS_Call(ctx, argv[1], JS_NULL, 1, &key);
|
||||
if (JS_IsException(val)) {
|
||||
JS_FreeAtom(ctx, atom);
|
||||
@@ -28927,7 +28732,7 @@ static JSValue js_cell_fn_apply(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 1) return JS_NULL;
|
||||
if (!JS_IsFunction(ctx, argv[0])) return JS_DupValue(ctx, argv[0]);
|
||||
if (!JS_IsFunction(argv[0])) return JS_DupValue(ctx, argv[0]);
|
||||
|
||||
JSValueConst func = argv[0];
|
||||
|
||||
@@ -29028,7 +28833,7 @@ static JSValue js_blob_constructor(JSContext *ctx, JSValueConst this_val,
|
||||
if (JS_IsBool(argv[1])) {
|
||||
int is_one = JS_ToBool(ctx, argv[1]);
|
||||
bd = blob_new_with_fill((size_t)length_bits, is_one);
|
||||
} else if (JS_IsFunction(ctx, argv[1])) {
|
||||
} else if (JS_IsFunction(argv[1])) {
|
||||
/* Random function provided */
|
||||
size_t bytes = (length_bits + 7) / 8;
|
||||
bd = blob_new((size_t)length_bits);
|
||||
@@ -29893,7 +29698,7 @@ static JSValue js_cell_splat(JSContext *ctx, JSValueConst this_val,
|
||||
|
||||
/* Call to_data if present */
|
||||
JSValue to_data = JS_GetPropertyStr(ctx, obj, "to_data");
|
||||
if (JS_IsFunction(ctx, to_data)) {
|
||||
if (JS_IsFunction(to_data)) {
|
||||
JSValue args[1] = { result };
|
||||
JSValue extra = JS_Call(ctx, to_data, obj, 1, args);
|
||||
if (!JS_IsException(extra) && JS_IsObject(extra)) {
|
||||
@@ -29933,7 +29738,7 @@ static JSValue js_cell_length(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_NULL;
|
||||
|
||||
/* Functions return arity (accessed directly, not via properties) */
|
||||
if (JS_IsFunction(ctx, val)) {
|
||||
if (JS_IsFunction(val)) {
|
||||
JSFunction *f = JS_VALUE_GET_FUNCTION(val);
|
||||
return JS_NewInt32(ctx, f->length);
|
||||
}
|
||||
@@ -29963,7 +29768,7 @@ static JSValue js_cell_length(JSContext *ctx, JSValueConst this_val,
|
||||
if (JS_IsObject(val)) {
|
||||
JSValue len = JS_GetPropertyStr(ctx, val, "length");
|
||||
if (!JS_IsException(len) && !JS_IsNull(len)) {
|
||||
if (JS_IsFunction(ctx, len)) {
|
||||
if (JS_IsFunction(len)) {
|
||||
JSValue result = JS_Call(ctx, len, val, 0, NULL);
|
||||
JS_FreeValue(ctx, len);
|
||||
return result;
|
||||
@@ -29991,7 +29796,7 @@ static JSValue js_cell_call(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_ThrowTypeError(ctx, "call requires a function argument");
|
||||
|
||||
JSValue func = argv[0];
|
||||
if (!JS_IsFunction(ctx, func))
|
||||
if (!JS_IsFunction(func))
|
||||
return JS_ThrowTypeError(ctx, "first argument must be a function");
|
||||
|
||||
JSValue this_arg = JS_NULL;
|
||||
@@ -30042,7 +29847,7 @@ static JSValue js_cell_is_data(JSContext *ctx, JSValueConst this_val,
|
||||
JSValue val = argv[0];
|
||||
if (!JS_IsObject(val)) return JS_FALSE;
|
||||
if (JS_IsArray(ctx, val)) return JS_FALSE;
|
||||
if (JS_IsFunction(ctx, val)) return JS_FALSE;
|
||||
if (JS_IsFunction(val)) return JS_FALSE;
|
||||
if (js_get_blob(ctx, val)) return JS_FALSE;
|
||||
/* Check if it's a plain object (prototype is Object.prototype or null) */
|
||||
return JS_TRUE;
|
||||
@@ -30053,7 +29858,7 @@ static JSValue js_cell_is_function(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 1) return JS_FALSE;
|
||||
return JS_NewBool(ctx, JS_IsFunction(ctx, argv[0]));
|
||||
return JS_NewBool(ctx, JS_IsFunction(argv[0]));
|
||||
}
|
||||
|
||||
/* is_logical(val) - check if value is a boolean (true or false) */
|
||||
@@ -30164,7 +29969,7 @@ static JSValue js_cell_is_proto(JSContext *ctx, JSValueConst this_val,
|
||||
JSValue proto = JS_GetPrototype(ctx, val);
|
||||
while (!JS_IsNull(proto) && !JS_IsException(proto)) {
|
||||
/* If master is a function with prototype property, check that */
|
||||
if (JS_IsFunction(ctx, master)) {
|
||||
if (JS_IsFunction(master)) {
|
||||
JSValue master_proto = JS_GetPropertyStr(ctx, master, "prototype");
|
||||
if (!JS_IsException(master_proto) && !JS_IsNull(master_proto)) {
|
||||
JSObject *p1 = JS_VALUE_GET_OBJ(proto);
|
||||
@@ -30436,7 +30241,7 @@ void js_debug_info(JSContext *js, JSValue fn, js_debug *dbg)
|
||||
{
|
||||
memset(dbg, 0, sizeof(*dbg));
|
||||
|
||||
if (!JS_IsFunction(js, fn)) return;
|
||||
if (!JS_IsFunction(fn)) return;
|
||||
JSFunction *f = JS_VALUE_GET_FUNCTION(fn);
|
||||
|
||||
const char *fn_name = NULL;
|
||||
@@ -31155,7 +30960,7 @@ static JSValue js_cell_json_decode(JSContext *ctx, JSValueConst this_val,
|
||||
JS_FreeCString(ctx, str);
|
||||
|
||||
/* Apply reviver if provided */
|
||||
if (argc > 1 && JS_IsFunction(ctx, argv[1]) && !JS_IsException(result)) {
|
||||
if (argc > 1 && JS_IsFunction(argv[1]) && !JS_IsException(result)) {
|
||||
/* Create wrapper object to pass to reviver */
|
||||
JSValue wrapper = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, wrapper, "", result);
|
||||
|
||||
@@ -533,17 +533,23 @@ static inline JS_BOOL JS_IsString(JSValueConst v)
|
||||
JS_VALUE_GET_TAG(v) == JS_TAG_STRING_ROPE;
|
||||
}
|
||||
|
||||
static inline JS_BOOL JS_IsText(JSValueConst v) { return JS_IsString(v); }
|
||||
|
||||
static inline JS_BOOL JS_IsSymbol(JSValueConst v)
|
||||
{
|
||||
return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL;
|
||||
}
|
||||
|
||||
static inline JS_BOOL JS_IsFunction(JSValueConst v)
|
||||
{
|
||||
return JS_VALUE_GET_TAG(v) == JS_TAG_FUNCTION;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -436,7 +436,7 @@ void actor_unneeded(cell_rt *actor, JSValue fn, double seconds)
|
||||
if (actor->disrupt) return;
|
||||
JS_FreeValue(actor->context, actor->unneeded);
|
||||
|
||||
if (!JS_IsFunction(actor->context, fn)) {
|
||||
if (!JS_IsFunction(fn)) {
|
||||
actor->unneeded = JS_NULL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
@@ -1077,7 +1077,7 @@ return {
|
||||
var parent = {a: 1}
|
||||
var mixin1 = {b: 2}
|
||||
var mixin2 = {c: 3}
|
||||
var child = meme(parent, mixin1, mixin2)
|
||||
var child = meme(parent, [mixin1, mixin2])
|
||||
if (child.a != 1 || child.b != 2 || child.c != 3) throw "meme multiple mixins failed"
|
||||
},
|
||||
|
||||
@@ -1847,7 +1847,7 @@ return {
|
||||
var fn = function() {}
|
||||
var caught = false
|
||||
try {
|
||||
var x = fn["length"]
|
||||
var x = fn["length"]()
|
||||
} catch (e) {
|
||||
caught = true
|
||||
}
|
||||
@@ -1875,14 +1875,14 @@ return {
|
||||
|
||||
test_call_invokes_function: function() {
|
||||
var fn = function(a, b) { return a + b }
|
||||
var result = call(fn, null, 3, 4)
|
||||
var result = call(fn, null, [3, 4])
|
||||
if (result != 7) throw "call(fn, null, 3, 4) should return 7"
|
||||
},
|
||||
|
||||
test_call_with_this_binding: function() {
|
||||
var obj = { value: 10 }
|
||||
var fn = function(x) { return this.value + x }
|
||||
var result = call(fn, obj, 5)
|
||||
var result = call(fn, obj, [5])
|
||||
if (result != 15) throw "call(fn, obj, 5) should return 15"
|
||||
},
|
||||
|
||||
@@ -2071,8 +2071,13 @@ return {
|
||||
var proxy = function(name, args) {
|
||||
return `key:${name}`
|
||||
}
|
||||
var result = proxy[42]()
|
||||
if (result != "key:42") throw "proxy with integer bracket key failed"
|
||||
var caught = false
|
||||
try {
|
||||
var result = proxy[42]()
|
||||
} catch (e) {
|
||||
caught = true
|
||||
}
|
||||
if (!caught) throw "proxy with integer bracket key should throw"
|
||||
},
|
||||
|
||||
// ============================================================================
|
||||
@@ -3036,7 +3041,7 @@ return {
|
||||
|
||||
test_call_many_args: function() {
|
||||
var fn = function(a, b, c, d) { return a * b + c * d }
|
||||
var result = call(fn, null, 2, 3, 4, 5)
|
||||
var result = call(fn, null, [2, 3, 4, 5])
|
||||
if (result != 26) throw "call many args failed"
|
||||
},
|
||||
|
||||
@@ -3045,7 +3050,7 @@ return {
|
||||
value: 10,
|
||||
multiply: function(x) { return this.value * x }
|
||||
}
|
||||
var result = call(obj.multiply, obj, 5)
|
||||
var result = call(obj.multiply, obj, [5])
|
||||
if (result != 50) throw "call method style failed"
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user