core: prevent scope parent-chain cycles when reusing pooled frames
- Scope.resetForReuse: fully detach before re-parenting (clear state, parent=null, new frameId), then validate with ensureNoCycle and assign parent/args/pos/thisObj - ScopePool.borrow (JVM/Android/JS/Native/Wasm): defensive fallback to fresh Scope allocation if resetForReuse detects a cycle - docs: add docs/fix-scope-parent-cycle.md describing the change and expectations - test: add ScopeCycleRegressionTest to ensure instance method call pattern does not crash and returns "ok"
This commit is contained in:
1 parent
b953282251
commit
d15dfb6087
8 files changed
+134
-28
No files matched your search
@@ -29,12 +29,18 @@ actual object ScopePool {
|
||||
|
||||
actual fun borrow(parent: Scope, args: Arguments, pos: Pos, thisObj: Obj): Scope {
|
||||
val s = if (pool.isNotEmpty()) pool.removeLast() else Scope(parent, args, pos, thisObj)
|
||||
if (s.parent !== parent || s.args !== args || s.pos !== pos || s.thisObj !== thisObj) {
|
||||
s.resetForReuse(parent, args, pos, thisObj)
|
||||
} else {
|
||||
s.frameId = nextFrameId()
|
||||
return try {
|
||||
if (s.parent !== parent || s.args !== args || s.pos !== pos || s.thisObj !== thisObj) {
|
||||
s.resetForReuse(parent, args, pos, thisObj)
|
||||
} else {
|
||||
s.frameId = nextFrameId()
|
||||
}
|
||||
s
|
||||
} catch (e: IllegalStateException) {
|
||||
if (e.message?.contains("cycle") == true && e.message?.contains("scope parent chain") == true) {
|
||||
Scope(parent, args, pos, thisObj)
|
||||
} else throw e
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
actual fun release(scope: Scope) {
|
||||
|
||||
Reference in new issue
Block a user