Skip to content

Commit bea1f52

Browse files
bodymovinbodymovin
andcommitted
fix(runtime): ensure lua data is initialized (#13010) e27bf13d74
Co-authored-by: hernan <hernan@rive.app>
1 parent 244aa55 commit bea1f52

5 files changed

Lines changed: 51 additions & 2 deletions

File tree

.rive_head

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
afd68206e676b8b4d360a720a86068094740d330
1+
e27bf13d74952314871275f26d0ed7228b97b4dc

include/rive/lua/rive_lua_libs.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,10 @@ class ScriptingContext
14821482
virtual void printEndLine() = 0;
14831483
virtual int pCall(lua_State* state, int nargs, int nresults) = 0;
14841484

1485+
// When true, the VM's owner sets up the Lua `Data` global itself (the
1486+
// editor builds it in Dart), so File should not call initializeLuaData.
1487+
virtual bool initializesDataGlobalExternally() const { return false; }
1488+
14851489
// Add a module to be registered later via performRegistration()
14861490
void addModule(ModuleDetails* moduleDetails);
14871491
// Perform registration of all added modules, handling dependencies and

src/file.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,14 @@ void File::registerScripts()
693693
ScriptingVM* vm = m_scriptingVM.get();
694694
if (vm != nullptr)
695695
{
696+
// Set up the Data global (view model constructors) on the active
697+
// VM, whether it was created here or supplied externally (e.g. by
698+
// the CommandServer). Skip it when the VM's owner builds Data
699+
// itself, as the editor does in Dart.
700+
if (!vm->context()->initializesDataGlobalExternally())
701+
{
702+
initializeLuaData(vm->state(), m_ViewModels);
703+
}
696704
for (auto scriptAsset : scripts)
697705
{
698706
// At runtime, if the script is verified, add it to be
@@ -729,7 +737,6 @@ void File::makeScriptingVM()
729737
cleanupScriptingVM();
730738
auto context = std::make_unique<CPPRuntimeScriptingContext>(m_factory);
731739
m_scriptingVM = make_rcp<ScriptingVM>(std::move(context));
732-
initializeLuaData(m_scriptingVM->state(), m_ViewModels);
733740
}
734741

735742
lua_State* File::scriptingState()
1.76 KB
Binary file not shown.

tests/unit_tests/runtime/scripting/scripting_context_test.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,44 @@ TEST_CASE("script has access to user created view models via Data", "[silver]")
237237
CHECK(silver.matches("script_create_viewmodel_instance"));
238238
}
239239

240+
// Regression test for rive-ios#454: when a ScriptingVM is supplied to
241+
// File::import (as the CommandServer does on iOS), the Lua `Data` global —
242+
// which exposes view model constructors like Data.ProbeChipVM.new() — must
243+
// still be initialized. Before the fix, initializeLuaData only ran inside
244+
// makeScriptingVM(), which is skipped when an external VM is provided, so
245+
// `Data` was nil in scripts.
246+
TEST_CASE("Data global is initialized when a ScriptingVM is provided to import",
247+
"[scripting]")
248+
{
249+
// Mirror CommandServer::processCommands: create the VM up front and pass
250+
// it into File::import.
251+
auto context =
252+
std::make_unique<rive::CPPRuntimeScriptingContext>(&gNoOpFactory);
253+
auto vm = rive::make_rcp<rive::ScriptingVM>(std::move(context));
254+
255+
auto bytes = ReadFile("assets/data_global_repro.riv");
256+
rive::ImportResult result;
257+
auto file =
258+
rive::File::import(bytes, &gNoOpFactory, &result, nullptr, vm.get());
259+
REQUIRE(result == rive::ImportResult::success);
260+
REQUIRE(file != nullptr);
261+
262+
// The file adopts the VM we supplied...
263+
REQUIRE(file->scriptingVM() == vm.get());
264+
265+
// ...and its `Data` global is a populated table (was nil before the fix),
266+
// exposing the file's view model as a constructor.
267+
lua_State* L = vm->state();
268+
REQUIRE(L != nullptr);
269+
lua_getglobal(L, "Data");
270+
REQUIRE(lua_istable(L, -1));
271+
lua_getfield(L, -1, "ProbeChipVM");
272+
REQUIRE(lua_istable(L, -1));
273+
lua_getfield(L, -1, "new");
274+
CHECK(lua_isfunction(L, -1));
275+
lua_pop(L, 3);
276+
}
277+
240278
TEST_CASE("script has access to the data bound view model", "[silver]")
241279
{
242280
rive::SerializingFactory silver;

0 commit comments

Comments
 (0)