diff --git a/quickjs.c b/quickjs.c index 224f67a..03a2c7b 100644 --- a/quickjs.c +++ b/quickjs.c @@ -1357,9 +1357,21 @@ static void js_trigger_gc(JSRuntime *rt, size_t size) (uint64_t)rt->malloc_state.malloc_size); } #endif - JS_RunGC(rt); - rt->malloc_gc_threshold = rt->malloc_state.malloc_size + - (rt->malloc_state.malloc_size >> 1); + //To ensure JS_RunGC cannot be executed again within callbacks. + size_t tmp_threshold = rt->malloc_gc_threshold; + rt->malloc_gc_threshold=-1; + + if((rt->malloc_gc_before_callback == NULL) || rt->malloc_gc_before_callback()){ + JS_RunGC(rt); + if(rt->malloc_gc_after_callback != NULL)rt->malloc_gc_after_callback(); + } + + rt->malloc_gc_threshold=tmp_threshold; + + if(rt->malloc_gc_fix_threshold == FALSE) { + rt->malloc_gc_threshold = rt->malloc_state.malloc_size + + (rt->malloc_state.malloc_size >> 1); + } } } @@ -1626,6 +1638,10 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) rt->malloc_state = ms; rt->malloc_gc_threshold = 256 * 1024; + rt->malloc_gc_fix_threshold = FALSE; + rt->malloc_gc_after_callback = NULL; + rt->malloc_gc_before_callback = NULL; + bf_context_init(&rt->bf_ctx, js_bf_realloc, rt); init_list_head(&rt->context_list); @@ -1768,6 +1784,28 @@ void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold) rt->malloc_gc_threshold = gc_threshold; } +size_t JS_GetGCThreshold(JSRuntime *rt) +{ + return rt->malloc_gc_threshold; +} + +void JS_SetGCThresholdFixed(JSRuntime *rt, BOOL fix) +{ + rt->malloc_gc_fix_threshold = fix; +} + + +void JS_SetGCBeforeCallback(JSRuntime *rt, BOOL(*fn)()) +{ + rt->malloc_gc_before_callback = fn; +} + +void JS_SetGCAfterCallback(JSRuntime *rt, void(*fn)()) +{ + rt->malloc_gc_after_callback = fn; +} + + #define malloc(s) malloc_is_forbidden(s) #define free(p) free_is_forbidden(p) #define realloc(p,s) realloc_is_forbidden(p,s) @@ -6638,7 +6676,7 @@ static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num, const char *fmt, va_list ap, BOOL add_backtrace) { char buf[256]; - JSValue obj, ret, msg; + JSValue obj, ret; vsnprintf(buf, sizeof(buf), fmt, ap); obj = JS_NewObjectProtoClass(ctx, ctx->native_error_proto[error_num], @@ -6647,13 +6685,9 @@ static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num, /* out of memory: throw JS_NULL to avoid recursing */ obj = JS_NULL; } else { - msg = JS_NewString(ctx, buf); - if (JS_IsException(msg)) - msg = JS_NewString(ctx, "Invalid error message"); - if (!JS_IsException(msg)) { - JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, msg, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - } + JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, + JS_NewString(ctx, buf), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } if (add_backtrace) { build_backtrace(ctx, obj, NULL, 0, 0, 0); @@ -18640,33 +18674,11 @@ int __attribute__((format(printf, 2, 3))) js_parse_error(JSParseState *s, const static int js_parse_expect(JSParseState *s, int tok) { - char buf[ATOM_GET_STR_BUF_SIZE]; - - if (s->token.val == tok) - return next_token(s); - - switch(s->token.val) { - case TOK_EOF: - return js_parse_error(s, "Unexpected end of input"); - case TOK_NUMBER: - return js_parse_error(s, "Unexpected number"); - case TOK_STRING: - return js_parse_error(s, "Unexpected string"); - case TOK_TEMPLATE: - return js_parse_error(s, "Unexpected string template"); - case TOK_REGEXP: - return js_parse_error(s, "Unexpected regexp"); - case TOK_IDENT: - return js_parse_error(s, "Unexpected identifier '%s'", - JS_AtomGetStr(s->ctx, buf, sizeof(buf), - s->token.u.ident.atom)); - case TOK_ERROR: - return js_parse_error(s, "Invalid or unexpected token"); - default: - return js_parse_error(s, "Unexpected token '%.*s'", - (int)(s->buf_ptr - s->token.ptr), - (const char *)s->token.ptr); + if (s->token.val != tok) { + /* XXX: dump token correctly in all cases */ + return js_parse_error(s, "expecting '%c'", tok); } + return next_token(s); } static int js_parse_expect_semi(JSParseState *s) @@ -20840,7 +20852,7 @@ static int __exception js_parse_property_name(JSParseState *s, goto fail1; if (s->token.val == ':' || s->token.val == ',' || s->token.val == '}' || s->token.val == '(' || - s->token.val == '=' ) { + s->token.val == '=') { is_non_reserved_ident = TRUE; goto ident_found; } @@ -20856,7 +20868,8 @@ static int __exception js_parse_property_name(JSParseState *s, if (next_token(s)) goto fail1; if (s->token.val == ':' || s->token.val == ',' || - s->token.val == '}' || s->token.val == '(') { + s->token.val == '}' || s->token.val == '(' || + s->token.val == '=') { is_non_reserved_ident = TRUE; goto ident_found; } @@ -21612,7 +21625,12 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, goto fail; continue; } - is_static = (s->token.val == TOK_STATIC); + is_static = FALSE; + if (s->token.val == TOK_STATIC) { + int next = peek_token(s, TRUE); + if (!(next == ';' || next == '}' || next == '(' || next == '=')) + is_static = TRUE; + } prop_type = -1; if (is_static) { if (next_token(s)) diff --git a/quickjs.h b/quickjs.h index 56c8ff5..632d399 100644 --- a/quickjs.h +++ b/quickjs.h @@ -303,9 +303,10 @@ JS_EXTERN void JS_SetMemoryLimit(JSRuntime *rt, size_t limit); JS_EXTERN void JS_SetDumpFlags(JSRuntime *rt, uint64_t flags); JS_EXTERN void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold); JS_EXTERN size_t JS_GetGCThreshold(JSRuntime *rt); -JS_EXTERN void JS_SetGCThresholdFixed(JSRuntime *rt, JS_BOOL fixed); -JS_EXTERN void JS_SetGCBeforeCallback(JSRuntime *rt, JS_BOOL (*fn)()); +JS_EXTERN void JS_SetGCThresholdFixed(JSRuntime *rt, BOOL fixed); +JS_EXTERN void JS_SetGCBeforeCallback(JSRuntime *rt, BOOL(*fn)()); JS_EXTERN void JS_SetGCAfterCallback(JSRuntime *rt, void(*fn)()); + /* use 0 to disable maximum stack size check */ JS_EXTERN void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size); /* should be called when changing thread to update the stack top value