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)
|
# Bootstrap: build cell from scratch using meson (only needed once)
|
||||||
# Also installs core scripts to ~/.cell/core
|
# Also installs core scripts to ~/.cell/core
|
||||||
bootstrap:
|
bootstrap:
|
||||||
meson setup build_bootstrap -Dbuildtype=debugoptimized -Db_sanitize=address
|
meson setup build_bootstrap -Dbuildtype=debugoptimized
|
||||||
meson compile -C build_bootstrap
|
meson compile -C build_bootstrap
|
||||||
cp build_bootstrap/cell .
|
cp build_bootstrap/cell .
|
||||||
cp build_bootstrap/libcell_runtime.dylib .
|
cp build_bootstrap/libcell_runtime.dylib .
|
||||||
|
|||||||
@@ -162,10 +162,6 @@ globalThis.log = function(name, args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.console(
|
|
||||||
'hello'
|
|
||||||
)
|
|
||||||
|
|
||||||
function disrupt(err)
|
function disrupt(err)
|
||||||
{
|
{
|
||||||
if (is_function(err.toString)) {
|
if (is_function(err.toString)) {
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ static void nota_encode_value(NotaEncodeContext *enc, JSValueConst val, JSValueC
|
|||||||
nota_stack_push(enc, replaced);
|
nota_stack_push(enc, replaced);
|
||||||
|
|
||||||
JSValue to_json = JS_GetPropertyStr(ctx, replaced, "toJSON");
|
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);
|
JSValue result = JS_Call(ctx, to_json, replaced, 0, NULL);
|
||||||
JS_FreeValue(ctx, to_json);
|
JS_FreeValue(ctx, to_json);
|
||||||
if (!JS_IsException(result)) {
|
if (!JS_IsException(result)) {
|
||||||
@@ -239,14 +239,14 @@ static void nota_encode_value(NotaEncodeContext *enc, JSValueConst val, JSValueC
|
|||||||
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, ptab[i].atom);
|
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);
|
JS_FreeValue(ctx, prop_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
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, ptab[i].atom);
|
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);
|
const char *prop_name = JS_AtomToCString(ctx, ptab[i].atom);
|
||||||
JSValue prop_key = JS_AtomToValue(ctx, ptab[i].atom);
|
JSValue prop_key = JS_AtomToValue(ctx, ptab[i].atom);
|
||||||
nota_write_text(&enc->nb, prop_name);
|
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->ctx = ctx;
|
||||||
enc->visitedStack = JS_NewArray(ctx);
|
enc->visitedStack = JS_NewArray(ctx);
|
||||||
enc->cycle = 0;
|
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_buffer_init(&enc->nb, 128);
|
||||||
nota_encode_value(enc, argv[0], JS_NULL, JS_NewString(ctx, ""));
|
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 == -1) return JS_EXCEPTION;
|
||||||
if (!nota) return JS_NULL;
|
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 ret;
|
||||||
JSValue holder = JS_NewObject(js);
|
JSValue holder = JS_NewObject(js);
|
||||||
js_do_nota_decode(js, &ret, (char*)nota, holder, JS_NewString(js, ""), reviver);
|
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);
|
ENetHost *host = JS_GetOpaque(this_val, enet_host_id);
|
||||||
if (!host) return JS_EXCEPTION;
|
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]);
|
JSValue callback = JS_DupValue(ctx, argv[0]);
|
||||||
|
|
||||||
double secs;
|
double secs;
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ static void scores_cb(PDScoresList *scores, const char *errorMessage) {
|
|||||||
JSC_SCALL(scoreboards_addScore,
|
JSC_SCALL(scoreboards_addScore,
|
||||||
if (!pd_scoreboards) return JS_ThrowInternalError(js, "scoreboards not initialized");
|
if (!pd_scoreboards) return JS_ThrowInternalError(js, "scoreboards not initialized");
|
||||||
uint32_t value = (uint32_t)js2number(js, argv[1]);
|
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;
|
g_scoreboard_js = js;
|
||||||
JS_FreeValue(js, g_add_score_callback);
|
JS_FreeValue(js, g_add_score_callback);
|
||||||
g_add_score_callback = JS_DupValue(js, argv[2]);
|
g_add_score_callback = JS_DupValue(js, argv[2]);
|
||||||
@@ -112,7 +112,7 @@ JSC_SCALL(scoreboards_addScore,
|
|||||||
|
|
||||||
JSC_SCALL(scoreboards_getPersonalBest,
|
JSC_SCALL(scoreboards_getPersonalBest,
|
||||||
if (!pd_scoreboards) return JS_ThrowInternalError(js, "scoreboards not initialized");
|
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;
|
g_scoreboard_js = js;
|
||||||
JS_FreeValue(js, g_personal_best_callback);
|
JS_FreeValue(js, g_personal_best_callback);
|
||||||
g_personal_best_callback = JS_DupValue(js, argv[1]);
|
g_personal_best_callback = JS_DupValue(js, argv[1]);
|
||||||
@@ -129,7 +129,7 @@ JSC_CCALL(scoreboards_freeScore,
|
|||||||
|
|
||||||
JSC_CCALL(scoreboards_getScoreboards,
|
JSC_CCALL(scoreboards_getScoreboards,
|
||||||
if (!pd_scoreboards) return JS_ThrowInternalError(js, "scoreboards not initialized");
|
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;
|
g_scoreboard_js = js;
|
||||||
JS_FreeValue(js, g_boards_list_callback);
|
JS_FreeValue(js, g_boards_list_callback);
|
||||||
g_boards_list_callback = JS_DupValue(js, argv[0]);
|
g_boards_list_callback = JS_DupValue(js, argv[0]);
|
||||||
@@ -145,7 +145,7 @@ JSC_CCALL(scoreboards_freeBoardsList,
|
|||||||
|
|
||||||
JSC_SCALL(scoreboards_getScores,
|
JSC_SCALL(scoreboards_getScores,
|
||||||
if (!pd_scoreboards) return JS_ThrowInternalError(js, "scoreboards not initialized");
|
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;
|
g_scoreboard_js = js;
|
||||||
JS_FreeValue(js, g_scores_callback);
|
JS_FreeValue(js, g_scores_callback);
|
||||||
g_scores_callback = JS_DupValue(js, argv[1]);
|
g_scores_callback = JS_DupValue(js, argv[1]);
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ JSC_CCALL(actor_on_exception,
|
|||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(actor_clock,
|
JSC_CCALL(actor_clock,
|
||||||
if (!JS_IsFunction(js, argv[0]))
|
if (!JS_IsFunction(argv[0]))
|
||||||
return JS_ThrowReferenceError(js, "Argument must be a function.");
|
return JS_ThrowReferenceError(js, "Argument must be a function.");
|
||||||
|
|
||||||
cell_rt *actor = JS_GetContextOpaque(js);
|
cell_rt *actor = JS_GetContextOpaque(js);
|
||||||
@@ -119,7 +119,7 @@ JSC_CCALL(actor_clock,
|
|||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(actor_delay,
|
JSC_CCALL(actor_delay,
|
||||||
if (!JS_IsFunction(js, argv[0]))
|
if (!JS_IsFunction(argv[0]))
|
||||||
return JS_ThrowReferenceError(js, "Argument must be a function.");
|
return JS_ThrowReferenceError(js, "Argument must be a function.");
|
||||||
|
|
||||||
cell_rt *actor = JS_GetContextOpaque(js);
|
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++) {
|
for (uint32_t i = 0; i < plen; i++) {
|
||||||
JSValue prop_val = JS_GetProperty(ctx, val, ptab[i].atom);
|
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;
|
atoms[non_function_count] = ptab[i].atom;
|
||||||
props[non_function_count++] = prop_val;
|
props[non_function_count++] = prop_val;
|
||||||
} else
|
} else
|
||||||
@@ -200,7 +200,7 @@ static void wota_encode_value(WotaEncodeContext *enc, JSValueConst val, JSValueC
|
|||||||
}
|
}
|
||||||
wota_stack_push(enc, replaced);
|
wota_stack_push(enc, replaced);
|
||||||
JSValue to_json = JS_GetPropertyStr(ctx, replaced, "toJSON");
|
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);
|
JSValue result = JS_Call(ctx, to_json, replaced, 0, NULL);
|
||||||
JS_FreeValue(ctx, to_json);
|
JS_FreeValue(ctx, to_json);
|
||||||
if (!JS_IsException(result)) {
|
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");
|
if (argc < 1) return JS_ThrowTypeError(ctx, "wota.encode requires at least 1 argument");
|
||||||
size_t total_bytes;
|
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);
|
JSValue ret = js_new_blob_stoned_copy(ctx, wota, total_bytes);
|
||||||
free(wota);
|
free(wota);
|
||||||
return ret;
|
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]);
|
uint8_t *buf = js_get_blob_data(ctx, &len, argv[0]);
|
||||||
if (buf == (uint8_t *)-1) return JS_EXCEPTION;
|
if (buf == (uint8_t *)-1) return JS_EXCEPTION;
|
||||||
if (!buf || len == 0) return JS_ThrowTypeError(ctx, "No blob data present");
|
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;
|
char *data_ptr = (char *)buf;
|
||||||
JSValue result = JS_NULL;
|
JSValue result = JS_NULL;
|
||||||
JSValue holder = JS_NewObject(ctx);
|
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( 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(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( 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, 1, 1, 0, none)
|
||||||
DEF( return_undef, 1, 0, 0, none)
|
DEF( return_undef, 1, 0, 0, none)
|
||||||
DEF( throw, 1, 1, 0, none)
|
DEF( throw, 1, 1, 0, none)
|
||||||
DEF( throw_error, 6, 0, 0, atom_u8)
|
DEF( throw_error, 6, 0, 0, atom_u8)
|
||||||
DEF( eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */
|
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
|
DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
|
||||||
bytecode string */
|
bytecode string */
|
||||||
|
|
||||||
|
|||||||
381
source/quickjs.c
381
source/quickjs.c
@@ -103,7 +103,7 @@
|
|||||||
/* dump profiling statistics (counters and sampling) when freeing the runtime */
|
/* dump profiling statistics (counters and sampling) when freeing the runtime */
|
||||||
//#define DUMP_PROFILE
|
//#define DUMP_PROFILE
|
||||||
|
|
||||||
#define RC_TRACE
|
//#define RC_TRACE
|
||||||
|
|
||||||
/* test the GC by forcing it before each object allocation */
|
/* test the GC by forcing it before each object allocation */
|
||||||
//#define FORCE_GC_AT_MALLOC
|
//#define FORCE_GC_AT_MALLOC
|
||||||
@@ -1034,6 +1034,8 @@ static void gc_decref_child_dbg(JSRuntime *rt, JSGCObjectHeader *parent,
|
|||||||
const char *file, int line);
|
const char *file, int line);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void gc_decref_child(JSRuntime *rt, JSGCObjectHeader *p);
|
||||||
|
|
||||||
int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val);
|
int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val);
|
||||||
static blob *js_get_blob(JSContext *ctx, JSValueConst val);
|
static blob *js_get_blob(JSContext *ctx, JSValueConst val);
|
||||||
static JSValue JS_ToStringFree(JSContext *ctx, JSValue 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;
|
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 */
|
/* return NULL without exception if not a function or no bytecode */
|
||||||
static JSFunctionBytecode *JS_GetFunctionBytecode(JSValueConst val)
|
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) {
|
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->values[i] = JS_NULL;
|
||||||
}
|
|
||||||
arr->len = idx + 1;
|
arr->len = idx + 1;
|
||||||
arr->values[idx] = val;
|
arr->values[idx] = val;
|
||||||
} else {
|
} else {
|
||||||
@@ -7984,12 +7979,6 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop)
|
|||||||
return -1;
|
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)
|
BOOL JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, int magic)
|
||||||
{
|
{
|
||||||
JSFunction *f;
|
JSFunction *f;
|
||||||
@@ -8336,7 +8325,6 @@ static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val)
|
|||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
JSValue ret;
|
JSValue ret;
|
||||||
|
|
||||||
redo:
|
|
||||||
tag = JS_VALUE_GET_NORM_TAG(val);
|
tag = JS_VALUE_GET_NORM_TAG(val);
|
||||||
switch(tag) {
|
switch(tag) {
|
||||||
case JS_TAG_FLOAT64:
|
case JS_TAG_FLOAT64:
|
||||||
@@ -9982,7 +9970,6 @@ static __exception int JS_CopyDataProperties(JSContext *ctx,
|
|||||||
JSObject *pexcl = NULL;
|
JSObject *pexcl = NULL;
|
||||||
int ret, gpn_flags;
|
int ret, gpn_flags;
|
||||||
JSPropertyDescriptor desc;
|
JSPropertyDescriptor desc;
|
||||||
BOOL is_enumerable;
|
|
||||||
|
|
||||||
if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT)
|
if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -10821,39 +10808,32 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
#endif
|
#endif
|
||||||
/* Proxy method-call: detect [func, "name", ...args]
|
/* Proxy method-call: detect [func, "name", ...args]
|
||||||
and rewrite as 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];
|
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);
|
JSValue args = JS_NewArrayLen(ctx, call_argc);
|
||||||
if (unlikely(JS_IsException(args)))
|
if (unlikely(JS_IsException(args)))
|
||||||
goto exception;
|
goto exception;
|
||||||
|
|
||||||
/* Move args into the array, then null out stack slots. */
|
/* Move args into the array, then null out stack slots. */
|
||||||
|
JSArray *ar = JS_VALUE_GET_ARRAY(args);
|
||||||
for (i = 0; i < call_argc; i++) {
|
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;
|
call_argv[i] = JS_NULL;
|
||||||
if (unlikely(r < 0)) {
|
|
||||||
JS_FreeValue(ctx, args);
|
|
||||||
goto exception;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
JSValue proxy_argv[2];
|
||||||
JSValue proxy_argv[2];
|
proxy_argv[0] = name; /* still owned by stack; freed by normal cleanup */
|
||||||
proxy_argv[0] = name; /* still owned by stack; freed by normal cleanup */
|
proxy_argv[1] = args;
|
||||||
proxy_argv[1] = args;
|
|
||||||
|
|
||||||
ret_val = JS_CallInternal(ctx, call_argv[-2], JS_NULL,
|
ret_val = JS_CallInternal(ctx, call_argv[-2], JS_NULL,
|
||||||
2, proxy_argv, 0);
|
2, proxy_argv, 0);
|
||||||
JS_FreeValue(ctx, args);
|
JS_FreeValue(ctx, args);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ret_val = JS_CallInternal(ctx, call_argv[-1], call_argv[-2],
|
ret_val = JS_CallInternal(ctx, call_argv[-1], call_argv[-2],
|
||||||
call_argc, call_argv, 0);
|
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)))
|
if (unlikely(JS_IsException(ret_val)))
|
||||||
goto exception;
|
goto exception;
|
||||||
call_argv = sp - call_argc;
|
call_argv = sp - call_argc;
|
||||||
|
JSArray *ar = JS_VALUE_GET_ARRAY(ret_val);
|
||||||
for (i = 0; i < call_argc; i++) {
|
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;
|
call_argv[i] = JS_NULL;
|
||||||
if (ret < 0) {
|
|
||||||
JS_FreeValue(ctx, ret_val);
|
|
||||||
goto exception;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sp -= call_argc;
|
sp -= call_argc;
|
||||||
*sp++ = ret_val;
|
*sp++ = ret_val;
|
||||||
}
|
}
|
||||||
BREAK;
|
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):
|
CASE(OP_return):
|
||||||
ret_val = *--sp;
|
ret_val = *--sp;
|
||||||
goto done;
|
goto done;
|
||||||
@@ -10992,51 +10930,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
*sp++ = ret_val;
|
*sp++ = ret_val;
|
||||||
}
|
}
|
||||||
BREAK;
|
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):
|
CASE(OP_regexp):
|
||||||
{
|
{
|
||||||
sp[-2] = js_regexp_constructor_internal(ctx, sp[-2], sp[-1]);
|
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];
|
obj = sp[-1];
|
||||||
|
|
||||||
/* Functions don't support property access in cell script */
|
/* 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");
|
JS_ThrowTypeError(ctx, "cannot get property of function");
|
||||||
goto exception;
|
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...])
|
/* Proxy method-call sugar: func.name(...) -> func("name", [args...])
|
||||||
OP_get_field2 is only emitted when a call immediately follows. */
|
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" */
|
val = JS_AtomToValue(ctx, atom); /* "name" */
|
||||||
if (unlikely(JS_IsException(val)))
|
if (unlikely(JS_IsException(val)))
|
||||||
goto exception;
|
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);
|
profile_record_prop_site(rt, b, (uint32_t)(pc - b->byte_code_buf), atom);
|
||||||
#endif
|
#endif
|
||||||
/* Functions don't support property assignment in cell script */
|
/* Functions don't support property assignment in cell script */
|
||||||
if (js_is_proxy_callable(sp[-2])) {
|
if (!JS_IsObject(sp[-2])) {
|
||||||
JS_ThrowTypeError(ctx, "cannot set property of function");
|
JS_ThrowTypeError(ctx, "tried to set property of non-object");
|
||||||
goto exception;
|
goto exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11829,14 +11722,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
CASE(OP_define_method):
|
CASE(OP_define_method):
|
||||||
CASE(OP_define_method_computed):
|
CASE(OP_define_method_computed):
|
||||||
{
|
{
|
||||||
JSValue getter, setter, value;
|
JSValue value;
|
||||||
JSValueConst obj;
|
JSValueConst obj;
|
||||||
JSAtom atom;
|
JSAtom atom;
|
||||||
int ret, op_flags;
|
int ret, op_flags;
|
||||||
BOOL is_computed;
|
BOOL is_computed;
|
||||||
#define OP_DEFINE_METHOD_METHOD 0
|
#define OP_DEFINE_METHOD_METHOD 0
|
||||||
#define OP_DEFINE_METHOD_GETTER 1
|
|
||||||
#define OP_DEFINE_METHOD_SETTER 2
|
|
||||||
#define OP_DEFINE_METHOD_ENUMERABLE 4
|
#define OP_DEFINE_METHOD_ENUMERABLE 4
|
||||||
|
|
||||||
is_computed = (opcode == OP_define_method_computed);
|
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];
|
obj = sp[-2 - is_computed];
|
||||||
op_flags &= 3;
|
op_flags &= 3;
|
||||||
value = JS_NULL;
|
value = JS_NULL;
|
||||||
getter = JS_NULL;
|
|
||||||
setter = JS_NULL;
|
|
||||||
if (op_flags == OP_DEFINE_METHOD_METHOD) {
|
if (op_flags == OP_DEFINE_METHOD_METHOD) {
|
||||||
value = sp[-1];
|
value = sp[-1];
|
||||||
}
|
}
|
||||||
@@ -11884,13 +11774,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
CASE(OP_get_array_el):
|
CASE(OP_get_array_el):
|
||||||
{
|
{
|
||||||
JSValue val;
|
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;
|
sf->cur_pc = pc;
|
||||||
val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);
|
val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);
|
||||||
JS_FreeValue(ctx, sp[-2]);
|
JS_FreeValue(ctx, sp[-2]);
|
||||||
@@ -11904,35 +11787,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
CASE(OP_get_array_el2):
|
CASE(OP_get_array_el2):
|
||||||
{
|
{
|
||||||
JSValue val;
|
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;
|
sf->cur_pc = pc;
|
||||||
val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);
|
val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);
|
||||||
sp[-1] = val;
|
sp[-1] = val;
|
||||||
@@ -11944,13 +11798,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
CASE(OP_get_array_el3):
|
CASE(OP_get_array_el3):
|
||||||
{
|
{
|
||||||
JSValue val;
|
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])) {
|
switch (JS_VALUE_GET_TAG(sp[-2])) {
|
||||||
case JS_TAG_INT:
|
case JS_TAG_INT:
|
||||||
case JS_TAG_STRING:
|
case JS_TAG_STRING:
|
||||||
@@ -11959,7 +11806,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* must be tested nefore JS_ToPropertyKey */
|
/* 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");
|
JS_ThrowTypeError(ctx, "value has no property");
|
||||||
goto exception;
|
goto exception;
|
||||||
}
|
}
|
||||||
@@ -12003,7 +11850,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
JS_ThrowReferenceErrorNotDefined(ctx, atom);
|
JS_ThrowReferenceErrorNotDefined(ctx, atom);
|
||||||
JS_FreeAtom(ctx, atom);
|
JS_FreeAtom(ctx, atom);
|
||||||
goto exception;
|
goto exception;
|
||||||
val = JS_NULL;
|
|
||||||
} else {
|
} else {
|
||||||
val = JS_GetProperty(ctx, sp[-2], atom);
|
val = JS_GetProperty(ctx, sp[-2], atom);
|
||||||
}
|
}
|
||||||
@@ -12020,7 +11866,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Functions don't support property assignment in cell script */
|
/* 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");
|
JS_ThrowTypeError(ctx, "cannot set property of function");
|
||||||
goto exception;
|
goto exception;
|
||||||
}
|
}
|
||||||
@@ -15721,13 +15567,12 @@ static __exception int js_parse_object_literal(JSParseState *s)
|
|||||||
JSAtom name = JS_ATOM_NULL;
|
JSAtom name = JS_ATOM_NULL;
|
||||||
const uint8_t *start_ptr;
|
const uint8_t *start_ptr;
|
||||||
int prop_type;
|
int prop_type;
|
||||||
BOOL has_proto;
|
|
||||||
|
|
||||||
if (next_token(s))
|
if (next_token(s))
|
||||||
goto fail;
|
goto fail;
|
||||||
/* XXX: add an initial length that will be patched back */
|
/* XXX: add an initial length that will be patched back */
|
||||||
emit_op(s, OP_object);
|
emit_op(s, OP_object);
|
||||||
has_proto = FALSE;
|
|
||||||
while (s->token.val != '}') {
|
while (s->token.val != '}') {
|
||||||
/* specific case for getter/setter */
|
/* specific case for getter/setter */
|
||||||
start_ptr = s->token.ptr;
|
start_ptr = s->token.ptr;
|
||||||
@@ -16127,18 +15972,6 @@ duplicate:
|
|||||||
return js_parse_error(s, "duplicate parameter names not allowed in this context");
|
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)
|
static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)
|
||||||
{
|
{
|
||||||
JSAtom name;
|
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);
|
var_name = js_parse_destructuring_var(s, tok, is_arg);
|
||||||
if (var_name == JS_ATOM_NULL)
|
if (var_name == JS_ATOM_NULL)
|
||||||
goto prop_error;
|
goto prop_error;
|
||||||
if (need_var_reference(s, tok)) {
|
/* no need to make a reference for let/const */
|
||||||
/* Must make a reference for proper `with` semantics */
|
opcode = OP_scope_get_var;
|
||||||
emit_op(s, OP_scope_get_var);
|
scope = s->cur_func->scope_level;
|
||||||
emit_atom(s, var_name);
|
label_lvalue = -1;
|
||||||
emit_u16(s, s->cur_func->scope_level);
|
depth_lvalue = 0;
|
||||||
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;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (js_parse_left_hand_side_expr(s))
|
if (js_parse_left_hand_side_expr(s))
|
||||||
goto prop_error;
|
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");
|
js_parse_error(s, "invalid destructuring target");
|
||||||
goto prop_error;
|
goto prop_error;
|
||||||
}
|
}
|
||||||
if (!tok || need_var_reference(s, tok)) {
|
if (!tok) {
|
||||||
/* generate reference */
|
/* generate reference */
|
||||||
/* source -- source source */
|
/* source -- source source */
|
||||||
emit_op(s, OP_dup);
|
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 (s->token.val == '=') {
|
||||||
if (next_token(s))
|
if (next_token(s))
|
||||||
goto var_error;
|
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);
|
if (js_parse_assign_expr2(s, parse_flags))
|
||||||
emit_atom(s, name);
|
goto var_error;
|
||||||
emit_u16(s, fd->scope_level);
|
set_object_name(s, name);
|
||||||
if (get_lvalue(s, &opcode, &scope, &name1, &label, NULL, FALSE, '=') < 0)
|
emit_op(s, (tok == TOK_DEF || tok == TOK_VAR) ?
|
||||||
goto var_error;
|
OP_scope_put_var_init : OP_scope_put_var);
|
||||||
if (js_parse_assign_expr2(s, parse_flags)) {
|
emit_atom(s, name);
|
||||||
JS_FreeAtom(ctx, name1);
|
emit_u16(s, fd->scope_level);
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (tok == TOK_DEF) {
|
if (tok == TOK_DEF) {
|
||||||
js_parse_error(s, "missing initializer for const variable");
|
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);
|
dbuf_put_u16(&bc_out, s->scopes[scope].first - ARG_SCOPE_END);
|
||||||
}
|
}
|
||||||
break;
|
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_checkthis:
|
||||||
case OP_scope_get_var_undef:
|
case OP_scope_get_var_undef:
|
||||||
case OP_scope_get_var:
|
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)
|
static int check_function(JSContext *ctx, JSValueConst obj)
|
||||||
{
|
{
|
||||||
if (likely(JS_IsFunction(ctx, obj)))
|
if (likely(JS_IsFunction(obj)))
|
||||||
return 0;
|
return 0;
|
||||||
JS_ThrowTypeError(ctx, "not a function");
|
JS_ThrowTypeError(ctx, "not a function");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -25273,7 +25073,7 @@ static JSValue JS_RegExpExec(JSContext *ctx, JSValueConst r, JSValueConst s)
|
|||||||
method = JS_GetProperty(ctx, r, JS_ATOM_exec);
|
method = JS_GetProperty(ctx, r, JS_ATOM_exec);
|
||||||
if (JS_IsException(method))
|
if (JS_IsException(method))
|
||||||
return method;
|
return method;
|
||||||
if (JS_IsFunction(ctx, method)) {
|
if (JS_IsFunction(method)) {
|
||||||
ret = JS_CallFree(ctx, method, r, 1, &s);
|
ret = JS_CallFree(ctx, method, r, 1, &s);
|
||||||
if (JS_IsException(ret))
|
if (JS_IsException(ret))
|
||||||
return ret;
|
return ret;
|
||||||
@@ -25593,7 +25393,7 @@ static JSValue js_json_parse(JSContext *ctx, JSValueConst this_val,
|
|||||||
JS_FreeCString(ctx, str);
|
JS_FreeCString(ctx, str);
|
||||||
if (JS_IsException(obj))
|
if (JS_IsException(obj))
|
||||||
return obj;
|
return obj;
|
||||||
if (argc > 1 && JS_IsFunction(ctx, argv[1])) {
|
if (argc > 1 && JS_IsFunction(argv[1])) {
|
||||||
reviver = argv[1];
|
reviver = argv[1];
|
||||||
root = JS_NewObject(ctx);
|
root = JS_NewObject(ctx);
|
||||||
if (JS_IsException(root)) {
|
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);
|
JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);
|
||||||
if (JS_IsException(f))
|
if (JS_IsException(f))
|
||||||
goto exception;
|
goto exception;
|
||||||
if (JS_IsFunction(ctx, f)) {
|
if (JS_IsFunction(f)) {
|
||||||
v = JS_CallFree(ctx, f, val, 1, &key);
|
v = JS_CallFree(ctx, f, val, 1, &key);
|
||||||
JS_FreeValue(ctx, val);
|
JS_FreeValue(ctx, val);
|
||||||
val = v;
|
val = v;
|
||||||
@@ -25662,7 +25462,7 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
|
|||||||
switch (JS_VALUE_GET_NORM_TAG(val)) {
|
switch (JS_VALUE_GET_NORM_TAG(val)) {
|
||||||
case JS_TAG_ARRAY:
|
case JS_TAG_ARRAY:
|
||||||
case JS_TAG_OBJECT:
|
case JS_TAG_OBJECT:
|
||||||
if (JS_IsFunction(ctx, val))
|
if (JS_IsFunction(val))
|
||||||
break;
|
break;
|
||||||
case JS_TAG_STRING:
|
case JS_TAG_STRING:
|
||||||
case JS_TAG_STRING_ROPE:
|
case JS_TAG_STRING_ROPE:
|
||||||
@@ -25872,7 +25672,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
|
|||||||
jsc->stack = JS_NewArray(ctx);
|
jsc->stack = JS_NewArray(ctx);
|
||||||
if (JS_IsException(jsc->stack))
|
if (JS_IsException(jsc->stack))
|
||||||
goto exception;
|
goto exception;
|
||||||
if (JS_IsFunction(ctx, replacer)) {
|
if (JS_IsFunction(replacer)) {
|
||||||
jsc->replacer_func = replacer;
|
jsc->replacer_func = replacer;
|
||||||
} else {
|
} else {
|
||||||
res = JS_IsArray(ctx, replacer);
|
res = JS_IsArray(ctx, replacer);
|
||||||
@@ -27027,7 +26827,7 @@ array_fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Handle function - return source or native stub */
|
/* Handle function - return source or native stub */
|
||||||
if (JS_IsFunction(ctx, arg)) {
|
if (JS_IsFunction(arg)) {
|
||||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(arg);
|
JSFunction *fn = JS_VALUE_GET_FUNCTION(arg);
|
||||||
if (fn->kind == JS_FUNC_KIND_BYTECODE) {
|
if (fn->kind == JS_FUNC_KIND_BYTECODE) {
|
||||||
JSFunctionBytecode *b = fn->u.func.function_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;
|
JSValue rep;
|
||||||
|
|
||||||
if (argc > 2 && JS_IsFunction(ctx, argv[2])) {
|
if (argc > 2 && JS_IsFunction(argv[2])) {
|
||||||
JSValue args[2];
|
JSValue args[2];
|
||||||
args[0] = match_val;
|
args[0] = match_val;
|
||||||
args[1] = JS_NewInt32(ctx, found);
|
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");
|
JSValue exec = JS_GetPropertyStr(ctx, v, "exec");
|
||||||
if (JS_IsException(exec)) return -1;
|
if (JS_IsException(exec)) return -1;
|
||||||
|
|
||||||
int ok = JS_IsFunction(ctx, exec);
|
int ok = JS_IsFunction(exec);
|
||||||
JS_FreeValue(ctx, exec);
|
JS_FreeValue(ctx, exec);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -27843,7 +27643,7 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
|||||||
JSValue result = JS_NewArrayLen(ctx, len);
|
JSValue result = JS_NewArrayLen(ctx, len);
|
||||||
if (JS_IsException(result)) return result;
|
if (JS_IsException(result)) return result;
|
||||||
|
|
||||||
if (JS_IsFunction(ctx, argv[1])) {
|
if (JS_IsFunction(argv[1])) {
|
||||||
/* Fill with function results */
|
/* Fill with function results */
|
||||||
JSValueConst func = argv[1];
|
JSValueConst func = argv[1];
|
||||||
int arity = 0;
|
int arity = 0;
|
||||||
@@ -27896,7 +27696,7 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JS_IsFunction(ctx, argv[1])) {
|
if (JS_IsFunction(argv[1])) {
|
||||||
/* Map */
|
/* Map */
|
||||||
JSValueConst func = argv[1];
|
JSValueConst func = argv[1];
|
||||||
int arity = (JSFunction*)JS_VALUE_GET_FUNCTION(argv[1])->length;
|
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 (argc < 2) return JS_NULL;
|
||||||
if (!JS_IsArray(ctx, argv[0])) 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 arr = argv[0];
|
||||||
JSValueConst func = argv[1];
|
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 (argc < 2) return JS_NULL;
|
||||||
if (!JS_IsArray(ctx, argv[0])) 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];
|
JSValueConst func = argv[1];
|
||||||
int64_t len;
|
int len = arr->len;
|
||||||
if (js_get_length64(ctx, &len, arr))
|
|
||||||
return JS_EXCEPTION;
|
|
||||||
if (len == 0) return JS_NULL;
|
if (len == 0) return JS_NULL;
|
||||||
|
|
||||||
int reverse = argc > 2 && JS_ToBool(ctx, argv[2]);
|
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;
|
int arity = (JSFunction*)JS_VALUE_GET_FUNCTION(argv[1])->length;
|
||||||
|
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
for (int64_t i = len - 1; i >= 0; i--) {
|
for (int i = len - 1; i >= 0; i--) {
|
||||||
JSValue item = JS_GetPropertyInt64(ctx, arr, i);
|
|
||||||
if (JS_IsException(item)) return JS_EXCEPTION;
|
|
||||||
JSValue result;
|
JSValue result;
|
||||||
if (arity == 1) {
|
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 {
|
} else {
|
||||||
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
|
JSValue args[2];
|
||||||
result = JS_Call(ctx, func, JS_NULL, 2, args);
|
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, args[1]);
|
||||||
}
|
}
|
||||||
JS_FreeValue(ctx, item);
|
|
||||||
if (JS_IsException(result)) return JS_EXCEPTION;
|
if (JS_IsException(result)) return JS_EXCEPTION;
|
||||||
if (!JS_IsNull(exit_val) && js_strict_eq(ctx, result, exit_val)) {
|
if (!JS_IsNull(exit_val) && js_strict_eq(ctx, result, exit_val)) {
|
||||||
return result;
|
return result;
|
||||||
@@ -28422,18 +28224,21 @@ static JSValue js_cell_array_for(JSContext *ctx, JSValueConst this_val,
|
|||||||
JS_FreeValue(ctx, result);
|
JS_FreeValue(ctx, result);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int64_t i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
JSValue item = JS_GetPropertyInt64(ctx, arr, i);
|
|
||||||
if (JS_IsException(item)) return JS_EXCEPTION;
|
|
||||||
JSValue result;
|
JSValue result;
|
||||||
if (arity == 1) {
|
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 {
|
} else {
|
||||||
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
|
JSValue args[2];
|
||||||
result = JS_Call(ctx, func, JS_NULL, 2, args);
|
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, args[1]);
|
||||||
}
|
}
|
||||||
JS_FreeValue(ctx, item);
|
|
||||||
if (JS_IsException(result)) return JS_EXCEPTION;
|
if (JS_IsException(result)) return JS_EXCEPTION;
|
||||||
if (!JS_IsNull(exit_val) && js_strict_eq(ctx, result, exit_val)) {
|
if (!JS_IsNull(exit_val) && js_strict_eq(ctx, result, exit_val)) {
|
||||||
return result;
|
return result;
|
||||||
@@ -28466,7 +28271,7 @@ static JSValue js_cell_array_find(JSContext *ctx, JSValueConst this_val,
|
|||||||
from = reverse ? len - 1 : 0;
|
from = reverse ? len - 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JS_IsFunction(ctx, argv[1])) {
|
if (!JS_IsFunction(argv[1])) {
|
||||||
/* Compare exactly */
|
/* Compare exactly */
|
||||||
JSValue target = argv[1];
|
JSValue target = argv[1];
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
@@ -28549,7 +28354,7 @@ static JSValue js_cell_array_filter(JSContext *ctx, JSValueConst this_val,
|
|||||||
{
|
{
|
||||||
if (argc < 2) return JS_NULL;
|
if (argc < 2) return JS_NULL;
|
||||||
if (!JS_IsArray(ctx, argv[0])) 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 arr = argv[0];
|
||||||
JSValueConst func = argv[1];
|
JSValueConst func = argv[1];
|
||||||
@@ -28768,7 +28573,7 @@ static JSValue js_cell_object(JSContext *ctx, JSValueConst this_val,
|
|||||||
JSValue arg = argv[0];
|
JSValue arg = argv[0];
|
||||||
|
|
||||||
/* object(object) - shallow mutable copy */
|
/* 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])) {
|
if (argc < 2 || JS_IsNull(argv[1])) {
|
||||||
/* Shallow copy */
|
/* Shallow copy */
|
||||||
JSValue result = JS_NewObject(ctx);
|
JSValue result = JS_NewObject(ctx);
|
||||||
@@ -28896,7 +28701,7 @@ static JSValue js_cell_object(JSContext *ctx, JSValueConst this_val,
|
|||||||
JSValue val;
|
JSValue val;
|
||||||
if (argc < 2 || JS_IsNull(argv[1])) {
|
if (argc < 2 || JS_IsNull(argv[1])) {
|
||||||
val = JS_TRUE;
|
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);
|
val = JS_Call(ctx, argv[1], JS_NULL, 1, &key);
|
||||||
if (JS_IsException(val)) {
|
if (JS_IsException(val)) {
|
||||||
JS_FreeAtom(ctx, atom);
|
JS_FreeAtom(ctx, atom);
|
||||||
@@ -28927,7 +28732,7 @@ static JSValue js_cell_fn_apply(JSContext *ctx, JSValueConst this_val,
|
|||||||
int argc, JSValueConst *argv)
|
int argc, JSValueConst *argv)
|
||||||
{
|
{
|
||||||
if (argc < 1) return JS_NULL;
|
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];
|
JSValueConst func = argv[0];
|
||||||
|
|
||||||
@@ -29028,7 +28833,7 @@ static JSValue js_blob_constructor(JSContext *ctx, JSValueConst this_val,
|
|||||||
if (JS_IsBool(argv[1])) {
|
if (JS_IsBool(argv[1])) {
|
||||||
int is_one = JS_ToBool(ctx, argv[1]);
|
int is_one = JS_ToBool(ctx, argv[1]);
|
||||||
bd = blob_new_with_fill((size_t)length_bits, is_one);
|
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 */
|
/* Random function provided */
|
||||||
size_t bytes = (length_bits + 7) / 8;
|
size_t bytes = (length_bits + 7) / 8;
|
||||||
bd = blob_new((size_t)length_bits);
|
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 */
|
/* Call to_data if present */
|
||||||
JSValue to_data = JS_GetPropertyStr(ctx, obj, "to_data");
|
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 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)) {
|
||||||
@@ -29933,7 +29738,7 @@ static JSValue js_cell_length(JSContext *ctx, JSValueConst this_val,
|
|||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
|
|
||||||
/* Functions return arity (accessed directly, not via properties) */
|
/* Functions return arity (accessed directly, not via properties) */
|
||||||
if (JS_IsFunction(ctx, val)) {
|
if (JS_IsFunction(val)) {
|
||||||
JSFunction *f = JS_VALUE_GET_FUNCTION(val);
|
JSFunction *f = JS_VALUE_GET_FUNCTION(val);
|
||||||
return JS_NewInt32(ctx, f->length);
|
return JS_NewInt32(ctx, f->length);
|
||||||
}
|
}
|
||||||
@@ -29963,7 +29768,7 @@ static JSValue js_cell_length(JSContext *ctx, JSValueConst this_val,
|
|||||||
if (JS_IsObject(val)) {
|
if (JS_IsObject(val)) {
|
||||||
JSValue len = JS_GetPropertyStr(ctx, val, "length");
|
JSValue len = JS_GetPropertyStr(ctx, val, "length");
|
||||||
if (!JS_IsException(len) && !JS_IsNull(len)) {
|
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);
|
JSValue result = JS_Call(ctx, len, val, 0, NULL);
|
||||||
JS_FreeValue(ctx, len);
|
JS_FreeValue(ctx, len);
|
||||||
return result;
|
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");
|
return JS_ThrowTypeError(ctx, "call requires a function argument");
|
||||||
|
|
||||||
JSValue func = argv[0];
|
JSValue func = argv[0];
|
||||||
if (!JS_IsFunction(ctx, func))
|
if (!JS_IsFunction(func))
|
||||||
return JS_ThrowTypeError(ctx, "first argument must be a function");
|
return JS_ThrowTypeError(ctx, "first argument must be a function");
|
||||||
|
|
||||||
JSValue this_arg = JS_NULL;
|
JSValue this_arg = JS_NULL;
|
||||||
@@ -30042,7 +29847,7 @@ static JSValue js_cell_is_data(JSContext *ctx, JSValueConst this_val,
|
|||||||
JSValue val = argv[0];
|
JSValue val = argv[0];
|
||||||
if (!JS_IsObject(val)) return JS_FALSE;
|
if (!JS_IsObject(val)) return JS_FALSE;
|
||||||
if (JS_IsArray(ctx, 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;
|
if (js_get_blob(ctx, val)) return JS_FALSE;
|
||||||
/* Check if it's a plain object (prototype is Object.prototype or null) */
|
/* Check if it's a plain object (prototype is Object.prototype or null) */
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
@@ -30053,7 +29858,7 @@ static JSValue js_cell_is_function(JSContext *ctx, JSValueConst this_val,
|
|||||||
int argc, JSValueConst *argv)
|
int argc, JSValueConst *argv)
|
||||||
{
|
{
|
||||||
if (argc < 1) return JS_FALSE;
|
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) */
|
/* 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);
|
JSValue proto = JS_GetPrototype(ctx, val);
|
||||||
while (!JS_IsNull(proto) && !JS_IsException(proto)) {
|
while (!JS_IsNull(proto) && !JS_IsException(proto)) {
|
||||||
/* If master is a function with prototype property, check that */
|
/* 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");
|
JSValue master_proto = JS_GetPropertyStr(ctx, master, "prototype");
|
||||||
if (!JS_IsException(master_proto) && !JS_IsNull(master_proto)) {
|
if (!JS_IsException(master_proto) && !JS_IsNull(master_proto)) {
|
||||||
JSObject *p1 = JS_VALUE_GET_OBJ(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));
|
memset(dbg, 0, sizeof(*dbg));
|
||||||
|
|
||||||
if (!JS_IsFunction(js, fn)) return;
|
if (!JS_IsFunction(fn)) return;
|
||||||
JSFunction *f = JS_VALUE_GET_FUNCTION(fn);
|
JSFunction *f = JS_VALUE_GET_FUNCTION(fn);
|
||||||
|
|
||||||
const char *fn_name = NULL;
|
const char *fn_name = NULL;
|
||||||
@@ -31155,7 +30960,7 @@ static JSValue js_cell_json_decode(JSContext *ctx, JSValueConst this_val,
|
|||||||
JS_FreeCString(ctx, str);
|
JS_FreeCString(ctx, str);
|
||||||
|
|
||||||
/* Apply reviver if provided */
|
/* 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 */
|
/* Create wrapper object to pass to reviver */
|
||||||
JSValue wrapper = JS_NewObject(ctx);
|
JSValue wrapper = JS_NewObject(ctx);
|
||||||
JS_SetPropertyStr(ctx, wrapper, "", result);
|
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;
|
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)
|
static inline JS_BOOL JS_IsSymbol(JSValueConst v)
|
||||||
{
|
{
|
||||||
return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL;
|
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)
|
static inline JS_BOOL JS_IsObject(JSValueConst v)
|
||||||
{
|
{
|
||||||
return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT;
|
return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT;
|
||||||
}
|
}
|
||||||
int JS_IsArray(JSContext *ctx, JSValueConst val);
|
int JS_IsArray(JSContext *ctx, JSValueConst val);
|
||||||
JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val);
|
|
||||||
|
|
||||||
// Fundamental
|
// Fundamental
|
||||||
int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres);
|
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;
|
if (actor->disrupt) return;
|
||||||
JS_FreeValue(actor->context, actor->unneeded);
|
JS_FreeValue(actor->context, actor->unneeded);
|
||||||
|
|
||||||
if (!JS_IsFunction(actor->context, fn)) {
|
if (!JS_IsFunction(fn)) {
|
||||||
actor->unneeded = JS_NULL;
|
actor->unneeded = JS_NULL;
|
||||||
goto END;
|
goto END;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1077,7 +1077,7 @@ return {
|
|||||||
var parent = {a: 1}
|
var parent = {a: 1}
|
||||||
var mixin1 = {b: 2}
|
var mixin1 = {b: 2}
|
||||||
var mixin2 = {c: 3}
|
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"
|
if (child.a != 1 || child.b != 2 || child.c != 3) throw "meme multiple mixins failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1847,7 +1847,7 @@ return {
|
|||||||
var fn = function() {}
|
var fn = function() {}
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
try {
|
||||||
var x = fn["length"]
|
var x = fn["length"]()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
@@ -1875,14 +1875,14 @@ return {
|
|||||||
|
|
||||||
test_call_invokes_function: function() {
|
test_call_invokes_function: function() {
|
||||||
var fn = function(a, b) { return a + b }
|
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"
|
if (result != 7) throw "call(fn, null, 3, 4) should return 7"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_call_with_this_binding: function() {
|
test_call_with_this_binding: function() {
|
||||||
var obj = { value: 10 }
|
var obj = { value: 10 }
|
||||||
var fn = function(x) { return this.value + x }
|
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"
|
if (result != 15) throw "call(fn, obj, 5) should return 15"
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -2071,8 +2071,13 @@ return {
|
|||||||
var proxy = function(name, args) {
|
var proxy = function(name, args) {
|
||||||
return `key:${name}`
|
return `key:${name}`
|
||||||
}
|
}
|
||||||
var result = proxy[42]()
|
var caught = false
|
||||||
if (result != "key:42") throw "proxy with integer bracket key failed"
|
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() {
|
test_call_many_args: function() {
|
||||||
var fn = function(a, b, c, d) { return a * b + c * d }
|
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"
|
if (result != 26) throw "call many args failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -3045,7 +3050,7 @@ return {
|
|||||||
value: 10,
|
value: 10,
|
||||||
multiply: function(x) { return this.value * x }
|
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"
|
if (result != 50) throw "call method style failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user