Skip to content

Comments

feat: add RegisterConsoleCallback; add api verson check method#17

Open
langfod wants to merge 5 commits intoPrismaUI-SKSE:devfrom
langfod:js_console_callback
Open

feat: add RegisterConsoleCallback; add api verson check method#17
langfod wants to merge 5 commits intoPrismaUI-SKSE:devfrom
langfod:js_console_callback

Conversation

@langfod
Copy link
Contributor

@langfod langfod commented Feb 16, 2026

RegisterConsoleCallback() allows a plugin to request JS console logs specific to their View.

The public ABI is version and RegisterConsoleCallback() is only available using IVPrismaUI2.

Plugin developer should test if IVPrismaUI2 is available before using the function in case the end-user has an older version of the PrismaUI DLL.

PRISMA_UI_API::IVPrismaUI1* m_prismaUI = nullptr;
PRISMA_UI_API::IVPrismaUI2* m_prismaUIv2 = nullptr;
  
m_prismaUI = PRISMA_UI_API::RequestPluginAPI<PRISMA_UI_API::IVPrismaUI1>();
 
if ((m_prismaUIv2 = PRISMA_UI_API::RequestPluginAPI<PRISMA_UI_API::IVPrismaUI2>())) {
    m_prismaUIv2->RegisterConsoleCallback(m_view, OnConsoleMessage);
    logger::info("UIManager: Console callback registered");
} else {
    logger::warn("UIManager: PrismaUI v2 API not available - console callback not registered");
    }
    
void OnConsoleMessage(PrismaView view, PRISMA_UI_API::ConsoleMessageLevel level, const char* message)
{
    switch (level) {
        case PRISMA_UI_API::ConsoleMessageLevel::Error:
            logger::error("[JS]: {}", message);
            break;
        case PRISMA_UI_API::ConsoleMessageLevel::Warning:
            logger::warn("[JS]: {}", message);
            break;
        case PRISMA_UI_API::ConsoleMessageLevel::Debug:
            logger::debug("[JS] View {}: {}", view, message);
            break;
        default:
            logger::info("[JS] View {}: {}", view, message);
            break;
    }
}

In game testing:

Nexus PrismaUI
Several Nexus Prisma Mods.
Custom mod with and without new header and no change code
Custom mod with updated both new API's

Updated PrismaUI
Several Nexus Prisma Mods.
Custom mod with and without new header and no change code
Custom mod with updated both new API's


Console Callback API

PrismaUI exposes a mechanism for consumer plugins to receive JavaScript console messages (console.log, console.warn, console.error, etc.) from their views.

Requesting the V2 Interface

RegisterConsoleCallback is part of the IVPrismaUI2 interface. Use the template RequestPluginAPI to request it:

auto* v2 = PRISMA_UI_API::RequestPluginAPI<PRISMA_UI_API::IVPrismaUI2>();
if (v2) {
    // V2 interface is available
}

If the loaded PrismaUI DLL does not support IVPrismaUI2, the call returns nullptr. This allows your plugin to gracefully degrade when users have an older PrismaUI version installed.

Interface version history

Interface Added
IVPrismaUI1 Original API (CreateView through HasAnyActiveFocus)
IVPrismaUI2 RegisterConsoleCallback

RegisterConsoleCallback

Register a callback to receive JavaScript console messages from a specific view.

virtual void RegisterConsoleCallback(PrismaView view, ConsoleMessageCallback callback) noexcept = 0;

Parameters

  • view — The view to listen to. Messages from other views/plugins are not received.
  • callback — Function pointer to receive messages, or nullptr to unregister.

Callback signature

typedef void (*ConsoleMessageCallback)(PrismaView view, ConsoleMessageLevel level, const char* message);

ConsoleMessageLevel enum

enum class ConsoleMessageLevel : uint8_t {
    Log = 0,    // console.log()
    Warning,    // console.warn()
    Error,      // console.error(), uncaught exceptions, CSP violations
    Debug,      // console.debug()
    Info        // console.info()
};

Threading

The callback is dispatched on the game thread via SKSE::GetTaskInterface()->AddTask(), consistent with other PrismaUI callbacks like RegisterJSListener and OnDomReadyCallback. It is safe to call SKSE/RE functions from within the callback.

Scope

Each view has its own isolated JavaScript context. Registering a console callback on your view only receives messages from your view. Other plugins using PrismaUI are not affected and their messages are not visible to your callback.

What it catches

Because this hooks into Ultralight's native OnAddConsoleMessage listener, it captures more than just console.log() calls:

  • console.log(), console.warn(), console.error(), console.info(), console.debug()
  • Uncaught JavaScript exceptions
  • console.assert() failures
  • CSP (Content Security Policy) violations
  • CSS/rendering warnings
  • Network errors from the view

Full Example

#include "PrismaUI_API.h"

PRISMA_UI_API::IVPrismaUI1* g_prismaUI = nullptr;
PRISMA_UI_API::IVPrismaUI2* g_prismaUIv2 = nullptr;
PrismaView g_view = 0;

// Console message handler
void OnConsoleMessage(PrismaView view, PRISMA_UI_API::ConsoleMessageLevel level, const char* message) {
    switch (level) {
        case PRISMA_UI_API::ConsoleMessageLevel::Error:
            logger::error("[JS Error] View {}: {}", view, message);
            break;
        case PRISMA_UI_API::ConsoleMessageLevel::Warning:
            logger::warn("[JS Warn] View {}: {}", view, message);
            break;
        default:
            logger::info("[JS] View {}: {}", view, message);
            break;
    }
}

void OnDomReady(PrismaView view) {
    // Register console callback if V2 interface is available
    if (g_prismaUIv2) {
        g_prismaUIv2->RegisterConsoleCallback(view, OnConsoleMessage);
        logger::info("Console callback registered for view {}", view);
    }
}

void SetupUI() {
    g_prismaUI = PRISMA_UI_API::RequestPluginAPI<PRISMA_UI_API::IVPrismaUI1>();
    g_prismaUIv2 = PRISMA_UI_API::RequestPluginAPI<PRISMA_UI_API::IVPrismaUI2>();

    if (g_prismaUI) {
        g_view = g_prismaUI->CreateView("my_plugin/index.html", OnDomReady);
    }
}

// To unregister later:
void Cleanup() {
    if (g_prismaUIv2 && g_view) {
        g_prismaUIv2->RegisterConsoleCallback(g_view, nullptr);
    }
}

Minimal Example (without version guard)

If your plugin requires the latest PrismaUI and doesn't need to support older versions:

void OnConsoleMessage(PrismaView view, PRISMA_UI_API::ConsoleMessageLevel level, const char* message) {
    logger::info("[JS] {}", message);
}

// In OnDomReady:
g_prismaUIv2->RegisterConsoleCallback(view, OnConsoleMessage);

- addedRequestPluginAPI() to safely return a simple api version like check
- added UpdateExternalDeps.ps1 to sync submodule and check for UL file
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new JavaScript console callback API to PrismaUI, allowing consumer plugins to receive JavaScript console messages (console.log, console.warn, console.error, etc.) from their views. The PR also introduces API versioning through GetAPIVersion() to enable safe backward compatibility checks, preventing crashes when newer plugins interact with older PrismaUI DLLs. Additionally, it includes build infrastructure improvements and a critical CMake configuration fix.

Changes:

  • Added RegisterConsoleCallback() API for receiving JavaScript console messages with proper thread safety via SKSE task dispatching
  • Added GetAPIVersion() for defensive version checking before calling new API features
  • Fixed critical CMake version requirement from invalid 4.1 to correct 3.21
  • Added build configuration management with local overrides support

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/main.cpp Exports GetPrismaUIAPIVersion() returning version 2
src/PrismaUI_API.h Adds ConsoleMessageLevel enum, ConsoleMessageCallback typedef, RegisterConsoleCallback() declaration, and GetAPIVersion() implementation
src/PrismaUI/ViewManager.h Declares RegisterConsoleCallback() function signature
src/PrismaUI/ViewManager.cpp Implements RegisterConsoleCallback() with thread-safe callback registration
src/PrismaUI/Listeners.cpp Implements OnAddConsoleMessage() to invoke registered console callbacks
src/PrismaUI/Core.h Adds consoleMessageCallback field to PrismaView struct
src/API/API.h Declares RegisterConsoleCallback() in plugin API interface
src/API/API.cpp Implements callback wrapping for game thread dispatch via SKSE tasks
CMakeLists.txt Fixes invalid cmake_minimum_required version from 4.1 to 3.21
BuildRelease.ps1 Adds configuration file management with template and local overrides
Build_Config_Template.ps1 Provides template for local build configuration
UpdateExternalDeps.ps1 Adds script for managing external dependencies and git submodules
.gitignore Excludes Build_Config_Local.ps1 from version control

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@StarkMP StarkMP self-requested a review February 16, 2026 07:52
@StarkMP StarkMP added the enhancement New feature or request label Feb 16, 2026
@StarkMP StarkMP changed the title JS console log callback feat: add RegisterConsoleCallback; add api verson check method Feb 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants