From c874751224237aaed7509960d14823d9c06e6eb5 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Tue, 6 Oct 2020 19:05:21 +0200 Subject: eval: restore context pointer of first evaluated dot/bracket expression When an expression such as `foo.bar(a.b, c.d)` is evaluated, the state context pointer will point to `c` while we need `foo` when invoking functions. Since the context pointer is only relevant for function calls and since for function call opcodes, the lhs expression is always the first operand, there is no need to store the context of subsequent ops. Adjust the ut_get_operands() procedure to restore state->ctx to the result of the first evaluated operand. Signed-off-by: Jo-Philipp Wich --- eval.c | 9 +++++++++ tests/02_runtime/02_this | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/eval.c b/eval.c index 1803355..074baa5 100644 --- a/eval.c +++ b/eval.c @@ -746,6 +746,7 @@ ut_cmp(int how, struct json_object *v1, struct json_object *v2) static struct json_object * _ut_get_operands(struct ut_state *state, struct ut_op *op, size_t n, struct json_object **v) { + struct json_object *ctx = NULL; struct ut_op *child; size_t i, j; @@ -759,7 +760,12 @@ _ut_get_operands(struct ut_state *state, struct ut_op *op, size_t n, struct json else v[i] = NULL; + if (i == 0) + ctx = json_object_get(state->ctx); + if (ut_is_type(v[i], T_EXCEPTION)) { + json_object_put(ctx); + for (j = 0; j < i; j++) json_object_put(v[j]); @@ -767,6 +773,9 @@ _ut_get_operands(struct ut_state *state, struct ut_op *op, size_t n, struct json } } + json_object_put(state->ctx); + state->ctx = ctx; + return NULL; } diff --git a/tests/02_runtime/02_this b/tests/02_runtime/02_this index d41be7f..e1efd80 100644 --- a/tests/02_runtime/02_this +++ b/tests/02_runtime/02_this @@ -23,3 +23,25 @@ true print(o.test(), "\n"); %} -- End -- + +Test that the context is properly restored if function call arguments are +dot or bracket expressions as well. + +-- Expect stdout -- +true +true +-- End -- + +-- Testcase -- +{% + local o = { + test: function() { + return (this === o); + } + }; + + local dummy = { foo: true, bar: false }; + + print(o.test(dummy.foo, dummy.bar), "\n"); + print(o.test(dummy.foo, o.test(dummy.foo, dummy.bar)), "\n"); +%} -- cgit v1.2.3