mirror of
https://github.com/centau/vide.git
synced 2026-10-21 11:44:07 +00:00
Fix scope stack staying broken after a yield in strict mode
This commit is contained in:
parent
a4151bd41e
commit
6b7bbca811
2 changed files with 31 additions and 1 deletions
|
|
@ -43,6 +43,7 @@ end
|
||||||
|
|
||||||
local function ycall<T, U>(fn: (T) -> U, arg: T): (boolean, string|U)
|
local function ycall<T, U>(fn: (T) -> U, arg: T): (boolean, string|U)
|
||||||
|
|
||||||
|
local n = scopes.n
|
||||||
local thread = coroutine.create(xpcall)
|
local thread = coroutine.create(xpcall)
|
||||||
--local function efn(err: string) return debug.traceback(err, 3) end
|
--local function efn(err: string) return debug.traceback(err, 3) end
|
||||||
local resume_ok, run_ok, result = coroutine.resume(thread, fn, efn, arg)
|
local resume_ok, run_ok, result = coroutine.resume(thread, fn, efn, arg)
|
||||||
|
|
@ -50,7 +51,15 @@ local function ycall<T, U>(fn: (T) -> U, arg: T): (boolean, string|U)
|
||||||
assert(resume_ok)
|
assert(resume_ok)
|
||||||
|
|
||||||
if coroutine.status(thread) ~= "dead" then
|
if coroutine.status(thread) ~= "dead" then
|
||||||
return false, debug.traceback(thread, "attempt to yield in reactive scope")
|
local trace = debug.traceback(thread, "attempt to yield in reactive scope")
|
||||||
|
|
||||||
|
-- the thread can still be resumed (e.g. by task.wait), so stop it and
|
||||||
|
-- pop the scopes it pushed before yielding
|
||||||
|
if task then task.cancel(thread) else coroutine.close(thread) end
|
||||||
|
for i = scopes.n, n + 1, -1 do scopes[i] = nil end
|
||||||
|
scopes.n = n
|
||||||
|
|
||||||
|
return false, trace
|
||||||
end
|
end
|
||||||
|
|
||||||
return run_ok, result
|
return run_ok, result
|
||||||
|
|
|
||||||
|
|
@ -3009,6 +3009,27 @@ TEST("strict", wrap_root(function()
|
||||||
CHECK(not ok)
|
CHECK(not ok)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
do CASE "yield in a component"
|
||||||
|
local input = source(false)
|
||||||
|
local thread
|
||||||
|
local resumed = false
|
||||||
|
|
||||||
|
local destroy = root(function()
|
||||||
|
show(input, function()
|
||||||
|
thread = coroutine.running()
|
||||||
|
coroutine.yield()
|
||||||
|
resumed = true
|
||||||
|
return {}
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
CHECK(not pcall(input, true))
|
||||||
|
CHECK(not coroutine.resume(thread))
|
||||||
|
CHECK(not resumed)
|
||||||
|
CHECK(pcall(input, false))
|
||||||
|
CHECK(pcall(destroy))
|
||||||
|
end
|
||||||
|
|
||||||
do CASE "run derived callback twice"
|
do CASE "run derived callback twice"
|
||||||
local src = source(1)
|
local src = source(1)
|
||||||
local count = 0
|
local count = 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue