Skip to content

File machine.cpp

File List > jac > machine > machine.cpp

Go to the documentation of this file

#include "machine.h"


namespace jac {


Module::Module(ContextRef ctx, std::string name) : _ctx(ctx) {
    _def = JS_NewCModule(ctx, name.c_str(), [](JSContext* context, JSModuleDef* def) {
        Module& mdl = base(context).findModule(def);

        for (auto& [exName, exVal] : mdl.exports) {
            JS_SetModuleExport(context, def, exName.c_str(), exVal.loot().second);
        }
        return 0;
    });
    if (!_def) {
        throw std::runtime_error("JS_NewCModule failed");
    }
}

void Module::addExport(std::string name, Value val) {
    JS_AddModuleExport(_ctx, _def, name.c_str());
    exports.emplace_back(name, val);
}

void MachineBase::initialize() {
    // last in stack

    _runtime = JS_NewRuntime();
    _context = JS_NewContext(_runtime);

    JS_SetContextOpaque(_context, this);
    JS_SetInterruptHandler(_runtime, [](JSRuntime*, void* opaque) noexcept {
        MachineBase& base = *static_cast<MachineBase*>(opaque);
        if (base._interrupt) {
            base._interrupt = false;
            return 1;
        }
        if (base._watchdogTimeout.count() > 0) {
            auto now = std::chrono::steady_clock::now();
            if (now > base._watchdogNext) {
                base._watchdogNext = now + base._watchdogTimeout;
                if (!base._wathdogCallback || base._wathdogCallback()) {
                    return 1;
                }
            }
        }
        return 0;
    }, this);
}

Value MachineBase::eval(std::string code, std::string filename, EvalFlags flags /*= EvalFlags::Global*/) {
    resetWatchdog();
    Value bytecode(_context, JS_Eval(_context, code.c_str(), code.size(), filename.c_str(), static_cast<int>(flags | EvalFlags::CompileOnly)));
    if (static_cast<int>(flags & EvalFlags::CompileOnly) != 0) {
        return bytecode;
    }
    code = "";
    resetWatchdog();
    return Value(_context, JS_EvalFunction(_context, bytecode.loot().second));
}

Module& MachineBase::newModule(std::string name) {
    Module mdl(_context, name);
    JSModuleDef* def = mdl.get();
    _modules.emplace(def, std::move(mdl));

    return _modules.find(def)->second;
}

Module& MachineBase::findModule(JSModuleDef* m) {
    auto it = _modules.find(m);
    if (it == _modules.end()) {
        throw std::runtime_error("module not found");
    }
    return it->second;
}


} // namespace jac