diff --git a/quickjs.c b/quickjs.c
index bb2491d8a..bbd3b6447 100644
--- a/quickjs.c
+++ b/quickjs.c
@@ -422,7 +422,7 @@ struct JSContext {
/* if NULL, eval is not supported */
JSValue (*eval_internal)(JSContext *ctx, JSValue this_obj,
const char *input, size_t input_len,
- const char *filename, int flags, int scope_idx);
+ const char *filename, int line, int flags, int scope_idx);
void *user_opaque;
};
@@ -1236,7 +1236,7 @@ static void js_async_function_resolve_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
static JSValue JS_EvalInternal(JSContext *ctx, JSValue this_obj,
const char *input, size_t input_len,
- const char *filename, int flags, int scope_idx);
+ const char *filename, int line, int flags, int scope_idx);
static void js_free_module_def(JSContext *ctx, JSModuleDef *m);
static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
JS_MarkFunc *mark_func);
@@ -33431,12 +33431,12 @@ static __exception int js_parse_program(JSParseState *s)
static void js_parse_init(JSContext *ctx, JSParseState *s,
const char *input, size_t input_len,
- const char *filename)
+ const char *filename, int line)
{
memset(s, 0, sizeof(*s));
s->ctx = ctx;
s->filename = filename;
- s->line_num = 1;
+ s->line_num = line;
s->col_num = 1;
s->buf_start = s->buf_ptr = (const uint8_t *)input;
s->buf_end = s->buf_ptr + input_len;
@@ -33488,7 +33488,7 @@ JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj)
/* `export_name` and `input` may be pure ASCII or UTF-8 encoded */
static JSValue __JS_EvalInternal(JSContext *ctx, JSValue this_obj,
const char *input, size_t input_len,
- const char *filename, int flags, int scope_idx)
+ const char *filename, int line, int flags, int scope_idx)
{
JSParseState s1, *s = &s1;
int err, eval_type;
@@ -33500,7 +33500,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValue this_obj,
JSModuleDef *m;
bool is_strict_mode;
- js_parse_init(ctx, s, input, input_len, filename);
+ js_parse_init(ctx, s, input, input_len, filename, line);
skip_shebang(&s->buf_ptr, s->buf_end);
eval_type = flags & JS_EVAL_TYPE_MASK;
@@ -33530,7 +33530,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValue this_obj,
is_strict_mode = true;
}
}
- fd = js_new_function_def(ctx, NULL, true, false, filename, 1, 1);
+ fd = js_new_function_def(ctx, NULL, true, false, filename, line, 1);
if (!fd)
goto fail1;
s->cur_func = fd;
@@ -33603,12 +33603,12 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValue this_obj,
/* the indirection is needed to make 'eval' optional */
static JSValue JS_EvalInternal(JSContext *ctx, JSValue this_obj,
const char *input, size_t input_len,
- const char *filename, int flags, int scope_idx)
+ const char *filename, int line, int flags, int scope_idx)
{
if (unlikely(!ctx->eval_internal)) {
return JS_ThrowTypeError(ctx, "eval is not supported");
}
- return ctx->eval_internal(ctx, this_obj, input, input_len, filename,
+ return ctx->eval_internal(ctx, this_obj, input, input_len, filename, line,
flags, scope_idx);
}
@@ -33624,7 +33624,7 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValue this_obj,
str = JS_ToCStringLen(ctx, &len, val);
if (!str)
return JS_EXCEPTION;
- ret = JS_EvalInternal(ctx, this_obj, str, len, "", flags, scope_idx);
+ ret = JS_EvalInternal(ctx, this_obj, str, len, "", 1, flags, scope_idx);
JS_FreeCString(ctx, str);
return ret;
@@ -33634,11 +33634,36 @@ JSValue JS_EvalThis(JSContext *ctx, JSValue this_obj,
const char *input, size_t input_len,
const char *filename, int eval_flags)
{
+ JSEvalOptions options = {
+ .version = JS_EVAL_OPTIONS_VERSION,
+ .filename = filename,
+ .line_num = 1,
+ .eval_flags = eval_flags
+ };
+ return JS_EvalThis2(ctx, this_obj, input, input_len, &options);
+}
+
+JSValue JS_EvalThis2(JSContext *ctx, JSValue this_obj,
+ const char *input, size_t input_len,
+ JSEvalOptions *options)
+{
+ const char *filename = "";
+ int line = 1;
+ int eval_flags = 0;
+ if (options) {
+ if (options->version != JS_EVAL_OPTIONS_VERSION)
+ return JS_ThrowInternalError(ctx, "bad JSEvalOptions version");
+ if (options->filename)
+ filename = options->filename;
+ if (options->line_num != 0)
+ line = options->line_num;
+ eval_flags = options->eval_flags;
+ }
JSValue ret;
assert((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_GLOBAL ||
(eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE);
- ret = JS_EvalInternal(ctx, this_obj, input, input_len, filename,
+ ret = JS_EvalInternal(ctx, this_obj, input, input_len, filename, line,
eval_flags, -1);
return ret;
}
@@ -33646,8 +33671,18 @@ JSValue JS_EvalThis(JSContext *ctx, JSValue this_obj,
JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
const char *filename, int eval_flags)
{
- return JS_EvalThis(ctx, ctx->global_obj, input, input_len, filename,
- eval_flags);
+ JSEvalOptions options = {
+ .version = JS_EVAL_OPTIONS_VERSION,
+ .filename = filename,
+ .line_num = 1,
+ .eval_flags = eval_flags
+ };
+ return JS_EvalThis2(ctx, ctx->global_obj, input, input_len, &options);
+}
+
+JSValue JS_Eval2(JSContext *ctx, const char *input, size_t input_len, JSEvalOptions *options)
+{
+ return JS_EvalThis2(ctx, ctx->global_obj, input, input_len, options);
}
int JS_ResolveModule(JSContext *ctx, JSValue obj)
@@ -45293,7 +45328,7 @@ JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, const char
JSParseState s1, *s = &s1;
JSValue val = JS_UNDEFINED;
- js_parse_init(ctx, s, buf, buf_len, filename);
+ js_parse_init(ctx, s, buf, buf_len, filename, 1);
if (json_next_token(s))
goto fail;
val = json_parse_value(s);
@@ -56236,7 +56271,7 @@ bool JS_DetectModule(const char *input, size_t input_len)
return false;
}
JS_AddIntrinsicRegExp(ctx); // otherwise regexp literals don't parse
- val = __JS_EvalInternal(ctx, JS_UNDEFINED, input, input_len, "",
+ val = __JS_EvalInternal(ctx, JS_UNDEFINED, input, input_len, "", 1,
JS_EVAL_TYPE_MODULE|JS_EVAL_FLAG_COMPILE_ONLY, -1);
if (JS_IsException(val)) {
const char *msg = JS_ToCString(ctx, rt->current_exception);
diff --git a/quickjs.h b/quickjs.h
index b54154c7d..863adabee 100644
--- a/quickjs.h
+++ b/quickjs.h
@@ -540,6 +540,16 @@ typedef struct JSClassDef {
JSClassExoticMethods *exotic;
} JSClassDef;
+#define JS_EVAL_OPTIONS_VERSION 1
+
+typedef struct JSEvalOptions {
+ int version;
+ int eval_flags;
+ const char *filename;
+ int line_num;
+ // can add new fields in ABI-compatible manner by incrementing JS_EVAL_OPTIONS_VERSION
+} JSEvalOptions;
+
#define JS_INVALID_CLASS_ID 0
JS_EXTERN JSClassID JS_NewClassID(JSRuntime *rt, JSClassID *pclass_id);
/* Returns the class ID if `v` is an object, otherwise returns JS_INVALID_CLASS_ID. */
@@ -803,10 +813,14 @@ JS_EXTERN bool JS_DetectModule(const char *input, size_t input_len);
/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */
JS_EXTERN JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
const char *filename, int eval_flags);
-/* same as JS_Eval() but with an explicit 'this_obj' parameter */
+JS_EXTERN JSValue JS_Eval2(JSContext *ctx, const char *input, size_t input_len,
+ JSEvalOptions *options);
JS_EXTERN JSValue JS_EvalThis(JSContext *ctx, JSValue this_obj,
const char *input, size_t input_len,
const char *filename, int eval_flags);
+JS_EXTERN JSValue JS_EvalThis2(JSContext *ctx, JSValue this_obj,
+ const char *input, size_t input_len,
+ JSEvalOptions *options);
JS_EXTERN JSValue JS_GetGlobalObject(JSContext *ctx);
JS_EXTERN int JS_IsInstanceOf(JSContext *ctx, JSValue val, JSValue obj);
JS_EXTERN int JS_DefineProperty(JSContext *ctx, JSValue this_obj,