From c7f246e7a5c2934fc1a0d25497a1638c7bcd0f9a Mon Sep 17 00:00:00 2001 From: Xuan Son Nguyen Date: Sun, 28 Dec 2025 22:15:10 +0100 Subject: [PATCH] allow func to access ctx --- common/jinja/jinja-value.h | 5 ++++- common/jinja/jinja-vm-builtins.cpp | 3 +-- common/jinja/jinja-vm.cpp | 10 +++++----- common/jinja/jinja-vm.h | 3 +++ 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/common/jinja/jinja-value.h b/common/jinja/jinja-value.h index a5eafda2dd..b5ce893162 100644 --- a/common/jinja/jinja-value.h +++ b/common/jinja/jinja-value.h @@ -57,9 +57,12 @@ void ensure_val(const value & ptr) { } // End Helper +struct context; // forward declaration struct func_args { std::vector args; + context & ctx; + func_args(context & ctx) : ctx(ctx) {} void ensure_count(size_t count) const { if (args.size() != count) { throw std::runtime_error("Expected " + std::to_string(count) + " arguments, got " + std::to_string(args.size())); @@ -253,7 +256,7 @@ struct value_func_t : public value_t { } virtual value invoke(const func_args & args) const override { if (arg0) { - func_args new_args; + func_args new_args(args.ctx); new_args.args.push_back(arg0); for (const auto & a : args.args) { new_args.args.push_back(a); diff --git a/common/jinja/jinja-vm-builtins.cpp b/common/jinja/jinja-vm-builtins.cpp index 39ae955e79..258d0da487 100644 --- a/common/jinja/jinja-vm-builtins.cpp +++ b/common/jinja/jinja-vm-builtins.cpp @@ -103,9 +103,8 @@ const func_builtins & global_builtins() { std::string format = args.args[0]->as_string().str(); // get current time // TODO: make sure this is the same behavior as Python's strftime - std::time_t t = std::time(nullptr); char buf[100]; - if (std::strftime(buf, sizeof(buf), format.c_str(), std::localtime(&t))) { + if (std::strftime(buf, sizeof(buf), format.c_str(), std::localtime(&args.ctx.current_time))) { return mk_val(std::string(buf)); } else { throw raised_exception("strftime_now: failed to format time"); diff --git a/common/jinja/jinja-vm.cpp b/common/jinja/jinja-vm.cpp index 8ec8e742f0..f1f252108f 100644 --- a/common/jinja/jinja-vm.cpp +++ b/common/jinja/jinja-vm.cpp @@ -258,14 +258,14 @@ value filter_expression::execute_impl(context & ctx) { filter_id = "strip"; // alias } JJ_DEBUG("Applying filter '%s' to %s", filter_id.c_str(), input->type().c_str()); - return try_builtin_func(filter_id, input)->invoke({}); + return try_builtin_func(filter_id, input)->invoke(func_args(ctx)); } else if (is_stmt(filter)) { auto call = cast_stmt(filter); auto filter_id = cast_stmt(call->callee)->val; JJ_DEBUG("Applying filter '%s' with arguments to %s", filter_id.c_str(), input->type().c_str()); - func_args args; + func_args args(ctx); for (const auto & arg_expr : call->args) { args.args.push_back(arg_expr->execute(ctx)); } @@ -302,7 +302,7 @@ value test_expression::execute_impl(context & ctx) { throw std::runtime_error("Unknown test '" + test_id + "'"); } - func_args args; + func_args args(ctx); args.args.push_back(operand->execute(ctx)); auto res = it->second(args); @@ -574,7 +574,7 @@ value member_expression::execute_impl(context & ctx) { stop_val->as_repr().c_str(), step_val->as_repr().c_str()); auto slice_func = try_builtin_func("slice", object); - func_args args; + func_args args(ctx); args.args.push_back(start_val); args.args.push_back(stop_val); args.args.push_back(step_val); @@ -643,7 +643,7 @@ value member_expression::execute_impl(context & ctx) { value call_expression::execute_impl(context & ctx) { // gather arguments - func_args args; + func_args args(ctx); for (auto & arg_stmt : this->args) { auto arg_val = arg_stmt->execute(ctx); JJ_DEBUG(" Argument type: %s", arg_val->type().c_str()); diff --git a/common/jinja/jinja-vm.h b/common/jinja/jinja-vm.h index d67bc2d5c1..596f325194 100644 --- a/common/jinja/jinja-vm.h +++ b/common/jinja/jinja-vm.h @@ -50,10 +50,13 @@ struct context { std::map var; std::string source; // for debugging + std::time_t current_time; // for functions that need current time + context() { var["true"] = mk_val(true); var["false"] = mk_val(false); var["none"] = mk_val(); + current_time = std::time(nullptr); } ~context() = default;