Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AP_Scripting: demystify require test #29006

Merged
merged 1 commit into from
Jan 4, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions libraries/AP_Scripting/tests/scripting_require_test_2.lua
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
-- main require tests are in scripting_test.lua

-- DO NOT EDIT!!!! it's very easy to make this accidentally pass even when the
-- original problem is still present!! we do some very careful work to check
-- that require works even when the function's first upvalue is not the script
-- environment.
-- CAREFUL WHEN EDITING!!!! we do some very careful work to check that require
-- works even when the update function's first upvalue is not the script
-- environment _ENV. this fact can be verified by looking at its upvalues using
-- e.g. https://www.luac.nl/

local loop_time = 500 -- number of ms between runs

-- need to shadow gcs to make the upvalues right
-- alias global gcs as a local so update uses it as an upvalue
local gcs = gcs -- luacheck: ignore

local passes = 0 -- run both before and after scheduling

-- this time running require, the main function that implicitly wraps the script
-- is the update function and its only upvalue is by definition _ENV; require
-- is expected to work here
local require_global = require("test/nested")

local function update()
-- need to send before requiring to make the upvalues right
-- reference gcs first so it's update's first upvalue
gcs:send_text(6, "testing")
local require_local = require("test/nested") -- should not crash
-- require is a global, so referencing it implicitly adds _ENV as update's
-- second upvalue, thus exercising the problem during the second and third
-- passes when this is in fact the update function
local require_local = require("test/nested") -- should not cause an error

-- validate we got the same object (object contents validated in main test)
-- no matter when require is called and what set of upvalues are used
if require_local == require_global then
passes = passes + 1
else
Expand All @@ -29,7 +36,11 @@ local function update()
gcs:send_text(3, "Require test 2 passed")
end

-- now schedule this function as the update function, not the main function
return update, loop_time
end

return update() -- run immediately before starting to reschedule
-- run immediately before starting to reschedule. the update function doesn't
-- change until the return, so the first time it's run the bug shouldn't trigger
-- as the main function's upvalues are still the ones checked
return update()
Loading