Skip to content

Regression (runtime-v0.1.107): eager per-file ScriptingVM in File::import breaks deferred view-model binding #110

Description

@bassrock

Summary

Since runtime-v0.1.107, a script in a state machine that reads data-bound view-model properties throws attempt to index nil (and its effects never apply) when the host binds the view-model instance after loading the file via the CommandQueue. It worked on runtime-v0.1.106 and earlier.

Bisect

Built rive_render (headless CommandQueue host) against successive tags:

runtime result
v0.1.106 ✅ script runs, reads bound VM data correctly
v0.1.107 attempt to index nil on data-bound property access in the script
v0.1.127 ❌ same

Cause

src/command_server.cpp, CommandServer::processCommands() loadFile case, gained (v0.1.107):

#ifdef WITH_RIVE_SCRIPTING
    auto scriptingContext = std::make_unique<CPPRuntimeScriptingContext>(m_factory);
    scriptingContext->setRenderContext(m_factory);
    auto vm = make_rcp<ScriptingVM>(std::move(scriptingContext));
    rcp<rive::File> file = rive::File::import(rivBytes, m_factory, nullptr, m_fileAssetLoader, vm.get());
#else
    rcp<rive::File> file = rive::File::import(rivBytes, m_factory, nullptr, m_fileAssetLoader);
#endif

The per-file ScriptingVM is now created eagerly, inside File::import, so the file's script instances initialize during import. But a CommandQueue host typically binds view-model data after loadFile:

loadFile → instantiateArtboard/StateMachine → createDefaultInstance →
setViewModelInstance* → bindViewModelInstance → advance

So the script's first run happens against a view model that isn't bound yet. Reads of data-bound (incl. nested) properties resolve to nil. Even though the script re-runs when the VM is later bound, the data-bound targets it needs are unavailable at the point it errors.

Expected

A script should be able to observe view-model data that the host binds after a scripted import (the pre-v0.1.107 behavior), or there should be a documented way to defer/re-initialize the script VM after bindViewModelInstance.

Workaround

Importing without the eager VM (the pre-0.1.107 File::import(...) path) restores correct behavior — scripts then initialize lazily, after the view model is bound.

Environment

  • Headless CommandQueue/CommandServer host (Metal on macOS, Vulkan/SwiftShader on Linux), WITH_RIVE_SCRIPTING enabled.
  • Reproduces identically on macOS and Linux; not platform-specific.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions