mozjs

2025-02-21 18:16
vak: (Default)
[personal profile] vak
Народ попенял в комментах, что libjavascriptcoregtk.so дофига зависимостей за собой тащит. Это верно, спору нет. Подсказали обратить внимание на альтернативную реализацию Джаваскрипта от Мозиллы. На Гитхабе нашлась коллекция примеров:

github.com/mozilla-spidermonkey/spidermonkey-embedding-examples

Интерфейс несколько тяжелее, чем у JavaScriptCore. Вот тот же пример факториала, переписанный для mozjs:
#include <js/compilationandevaluation.h>
#include <js/conversions.h>
#include <js/initialization.h>
#include <js/sourcetext.h>
#include <jsapi.h>
#include <iostream>

static const char code[] = R"(
function factorial(n) {
    if (n === 0) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}

factorial(10)
)";

int main()
{
    // Create a new JavaScript virtual machine.
    if (!JS_Init()) {
        throw std::runtime_error("JS_Init failed");
    }
    JSContext *vm = JS_NewContext(JS::DefaultHeapMaxBytes);
    if (!vm) {
        throw std::runtime_error("JS_NewContext failed");
    }
    if (!JS::InitSelfHostedCode(vm)) {
        throw std::runtime_error("JS::InitSelfHostedCode failed");
    }

    // Create a global object: the top-level 'this' value in a script.
    JS::RealmOptions realm_options;
    static JSClass BoilerplateGlobalClass = { "BoilerplateGlobal", JSCLASS_GLOBAL_FLAGS,
                                              &JS::DefaultGlobalClassOps };
    JS::RootedObject global(vm, JS_NewGlobalObject(vm, &BoilerplateGlobalClass, nullptr,
                                                   JS::FireOnNewGlobalHook, realm_options));
    if (!global) {
        throw std::runtime_error("JS_NewGlobalObject failed");
    }

    {
        // Enter a "realm": environment within one global object.
        JSAutoRealm realm(vm, global);

        // Create buffer with source code.
        JS::SourceText source;
        if (!source.init(vm, code, strlen(code), JS::SourceOwnership::Borrowed)) {
            throw std::runtime_error("Cannot initialize JS::SourceText");
        }

        // Evaluate arbitrary JavaScript code.
        JS::CompileOptions options(vm);
        JS::RootedValue rval(vm);
        if (!JS::Evaluate(vm, options, source, &rval)) {
            throw std::runtime_error("JS::Evaluate failed");
        }

        // Print the result.
        if (rval.isNumber()) {
            std::cout << "The result is: "
                      << JS_EncodeStringToASCII(vm, JS::ToString(vm, rval)).get()
                      << '\n';
        } else {
            std::cout << "The result is not a number.\n";
        }
    }

    JS_DestroyContext(vm);
    JS_ShutDown();
}
Запускаем:
$ c++ -std=c++17 factorial.cpp -o factorial `pkg-config --cflags --libs mozjs-102`
$ ./factorial
The result is: 3628800.000000
Зависимостей здесь намного меньше:
$ ldd factorial 
	linux-vdso.so.1 (0x0000ffffb3e22000)
	libmozjs-102.so.0 => /lib/aarch64-linux-gnu/libmozjs-102.so.0 (0x0000ffffb20a0000)
	libstdc++.so.6 => /lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000ffffb1e80000)
	libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000ffffb1e40000)
	libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffffb1c90000)
	libz.so.1 => /lib/aarch64-linux-gnu/libz.so.1 (0x0000ffffb1c50000)
	libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000ffffb1bb0000)
	/lib/ld-linux-aarch64.so.1 (0x0000ffffb3de5000)
Одно важное принципиальное отличие: libjavascriptcoregtk.so с вероятностью 99% уже имеется в вашем линуксе или маке. А libmozjs.so придётся дополнительно устанавливать. Зато на маке ничего не надо менять, всё одинаково работает.

Date: 2025-02-22 04:00 (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi
Как варварски смотрится. Можно же прокладки приделать, чтоб читалось.

Ну ладно, работает и ладно.

Date: 2025-02-22 04:48 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
А если сделать ldd /lib/aarch64-linux-gnu/libmozjs-102.so.0 ?