Mercurial > code
changeset 411:2a0b8613498f
Js: add more stack tests
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 07 Oct 2015 08:30:19 +0200 |
parents | a786ad1bdf75 |
children | f16164e720ba |
files | C++/modules/Js/Js.cpp C++/modules/Js/Js.h C++/tests/Js/main.cpp |
diffstat | 3 files changed, 69 insertions(+), 53 deletions(-) [+] |
line wrap: on
line diff
--- a/C++/modules/Js/Js.cpp Tue Oct 06 16:25:51 2015 +0200 +++ b/C++/modules/Js/Js.cpp Wed Oct 07 08:30:19 2015 +0200 @@ -63,4 +63,45 @@ } } +void TypeInfo<Function>::push(Context &ctx, Function fn) +{ + /* 1. Push function wrapper */ + duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t { + Context context{ctx}; + + duk_push_current_function(ctx); + duk_get_prop_string(ctx, -1, "\xff""\xff""js-func"); + Function *f = static_cast<Function *>(duk_to_pointer(ctx, -1)); + duk_pop_2(ctx); + + return static_cast<duk_ret_t>(f->function(context)); + }, fn.nargs); + + /* 2. Store the moved function */ + duk_push_pointer(ctx, new Function(std::move(fn))); + duk_put_prop_string(ctx, -2, "\xff""\xff""js-func"); + + /* 3. Store deletion flags */ + duk_push_boolean(ctx, false); + duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted"); + + /* 4. Push and set a finalizer */ + duk_push_c_function(ctx, [] (duk_context *ctx) { + duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted"); + + if (duk_to_boolean(ctx, -1)) { + duk_push_boolean(ctx, true); + duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted"); + duk_get_prop_string(ctx, 0, "\xff""\xff""js-func"); + delete static_cast<Function *>(duk_to_pointer(ctx, -1)); + duk_pop(ctx); + } + + duk_pop(ctx); + + return 0; + }, 1); + duk_set_finalizer(ctx, -2); +} + } // !js
--- a/C++/modules/Js/Js.h Tue Oct 06 16:25:51 2015 +0200 +++ b/C++/modules/Js/Js.h Wed Oct 07 08:30:19 2015 +0200 @@ -1082,46 +1082,7 @@ template <> class TypeInfo<Function> { public: - static void push(Context &ctx, Function fn) - { - /* 1. Push function wrapper */ - duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t { - Context context{ctx}; - - duk_push_current_function(ctx); - duk_get_prop_string(ctx, -1, "\xff""\xff""js-func"); - Function *f = static_cast<Function *>(duk_to_pointer(ctx, -1)); - duk_pop_2(ctx); - - return static_cast<duk_ret_t>(f->function(context)); - }, fn.nargs); - - /* 2. Store the moved function */ - duk_push_pointer(ctx, new Function(std::move(fn))); - duk_put_prop_string(ctx, -2, "\xff""\xff""js-func"); - - /* 3. Store deletion flags */ - duk_push_boolean(ctx, false); - duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted"); - - /* 4. Push and set a finalizer */ - duk_push_c_function(ctx, [] (duk_context *ctx) { - duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted"); - - if (duk_to_boolean(ctx, -1)) { - duk_push_boolean(ctx, true); - duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted"); - duk_get_prop_string(ctx, 0, "\xff""\xff""js-func"); - delete static_cast<Function *>(duk_to_pointer(ctx, -1)); - duk_pop(ctx); - } - - duk_pop(ctx); - - return 0; - }, 1); - duk_set_finalizer(ctx, -2); - } + static void push(Context &ctx, Function fn); }; /**
--- a/C++/tests/Js/main.cpp Tue Oct 06 16:25:51 2015 +0200 +++ b/C++/tests/Js/main.cpp Wed Oct 07 08:30:19 2015 +0200 @@ -501,30 +501,35 @@ { Context context; + ASSERT_EQ(0, context.top()); context.eval(Script{"x = 123;"}); ASSERT_EQ(123, context.getGlobal<int>("x")); + ASSERT_EQ(1, context.top()); } TEST(Eval, function) { Context context; + ASSERT_EQ(0, context.top()); context.eval(Script{"function f() { x = 123; }; f();"}); ASSERT_EQ(123, context.getGlobal<int>("x")); + ASSERT_EQ(1, context.top()); } TEST(Eval, cfunction) { Context context; + ASSERT_EQ(0, context.top()); context.putGlobal("f", Function{[] (Context &ctx) -> int { ctx.putGlobal("x", 123); return 0; }}); context.eval(Script{"f()"}); - ASSERT_EQ(123, context.getGlobal<int>("x")); + ASSERT_EQ(1, context.top()); } /* ------------------------------------------------------------------ @@ -535,23 +540,27 @@ { Context context; + ASSERT_EQ(0, context.top()); try { context.peval(Script{"x = 1"}); } catch (const ErrorInfo &info) { FAIL() << "error unexpected: " << info.what(); } + ASSERT_EQ(1, context.top()); } TEST(Peval, failure) { Context context; + ASSERT_EQ(0, context.top()); try { context.peval(Script{"doesnotexists()"}); FAIL() << "expected exception"; } catch (const std::exception &) { } + ASSERT_EQ(0, context.top()); } /* ------------------------------------------------------------------ @@ -619,7 +628,7 @@ ctx.push(Object{}); /* "update" method */ - ctx.putProperty(-1, "update", Function{[] (Context &ctx) -> int { + ctx.putProperty(-1, "update", Function{[&] (Context &ctx) -> int { ctx.self<Player *>()->m_updated = true; return 0; @@ -659,11 +668,13 @@ TEST(Pointer, simple) { - Context ctx; + Context context; Player *p{new Player}; - ctx.push(p); - Player *p2 = ctx.get<Player *>(-1); + ASSERT_EQ(0, context.top()); + context.push(p); + Player *p2 = context.get<Player *>(-1); + ASSERT_EQ(1, context.top()); p2->m_updated = true; @@ -696,16 +707,19 @@ auto f2 = [&] (Context &) -> int { f2called = true; return 0; }; FunctionMap map{ - { "f1", { f1, 0 }}, - { "f2", { f2, 0 }} + { "f1", { f1, 0 } }, + { "f2", { f2, 0 } } }; - Context ctx; + Context context; - ctx.push(Global{}); - ctx.push(map); - ctx.pop(); - ctx.peval(Script{"f1();"}); - ctx.peval(Script{"f2();"}); + ASSERT_EQ(0, context.top()); + context.push(Global{}); + ASSERT_EQ(1, context.top()); + context.push(map); + ASSERT_EQ(1, context.top()); + context.pop(); + context.peval(Script{"f1();"}); + context.peval(Script{"f2();"}); ASSERT_TRUE(f1called); ASSERT_TRUE(f2called);