scraps

Abandon all hope, ye who enter here.
git clone https://git.neptards.moe/neptards/scraps.git
Log | Files | Refs | Submodules | README | LICENSE

js.hpp (2570B)


      1 #ifndef GUARD_SHIRTILY_SUBCORNEAL_ISOPROPYLTHIOGALACTOSIDE_DECULTURALIZES_7789
      2 #define GUARD_SHIRTILY_SUBCORNEAL_ISOPROPYLTHIOGALACTOSIDE_DECULTURALIZES_7789
      3 #pragma once
      4 
      5 #include <libshit/except.hpp>
      6 #include <libshit/random.hpp>
      7 
      8 #include <libshit/assert.hpp>
      9 #include <libshit/nonowning_string.hpp>
     10 #include <libshit/utils.hpp>
     11 #include <libshit/wtf8.hpp>
     12 
     13 #include <csetjmp>
     14 #include <stdexcept>
     15 #include <string>
     16 
     17 struct js_State;
     18 
     19 namespace Scraps
     20 {
     21 
     22   LIBSHIT_GEN_EXCEPTION_TYPE(JsError, std::runtime_error);
     23 
     24 #if LIBSHIT_HAS_ASSERT
     25 #  define SCRAPS_JS_GETTOP(vm, name) auto name = js_gettop(vm)
     26 #  define SCRAPS_JS_CHECKTOP(vm, val) LIBSHIT_ASSERT(js_gettop(vm) == (val))
     27 #else
     28 #  define SCRAPS_JS_GETTOP(vm, name) ((void) 0)
     29 #  define SCRAPS_JS_CHECKTOP(vm, val) ((void) 0)
     30 #endif
     31 
     32   class JsRef
     33   {
     34   public:
     35     constexpr JsRef(js_State* vm) noexcept : vm{vm} {}
     36     constexpr operator js_State*() noexcept { return vm; }
     37 
     38     void EvalToString(std::string& out, Libshit::StringView src);
     39     std::string EvalToString(Libshit::StringView src)
     40     { std::string res; EvalToString(res, src); return res; }
     41 
     42     void PushEval(Libshit::StringView src);
     43 
     44     template <typename T, typename U = js_State*>
     45     void Catch(T fun, U vm_ = nullptr)
     46     {
     47       // I do not want to include mujs.h here, so abuse templates
     48       vm_ = vm;
     49       auto top = js_gettop(vm_);
     50       // because mujs has to use braindead CESU8 and return void* instead of
     51       // jmp_buf which automatically decays to void* then inplicitly convertible
     52       // back to jmp_buf on most C compilers, because usually jmp_buf is typedefd
     53       // to something[1], but it's actually `typedef /* unspecified */ jmp_buf;`
     54       // according to the C standard, so it doesn't have to work even on C, and
     55       // it's completely broken on C++. why must everyone be a fucking idiot?!
     56       if (setjmp(*reinterpret_cast<jmp_buf*>(js_savetry(vm_))))
     57       {
     58         auto s = Libshit::Cesu8ToWtf8(js_tostring(vm_, -1));
     59         js_pop(vm_, js_gettop(vm_) - top);
     60         LIBSHIT_THROW(JsError, Libshit::Move(s));
     61       }
     62 
     63       // can't use AtScopeExit here because longjmping over a variable with
     64       // non-trivial destructor is UB
     65       try { fun(); } catch (...) { js_endtry(vm_); throw; }
     66       js_endtry(vm_);
     67     }
     68 
     69   protected:
     70     js_State* vm;
     71   };
     72 
     73   class JsState final : public JsRef
     74   {
     75     JsState(int dummy);
     76   public:
     77     JsState(Libshit::Xoshiro256p& random);
     78     ~JsState() noexcept;
     79     JsState(const JsState&) = delete;
     80     void operator=(const JsState&) = delete;
     81 
     82   };
     83 
     84 }
     85 
     86 #endif