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
@@ -302,11 +302,9 @@ open class Scope(
|
||||
* Clears locals and slots, assigns new frameId, and sets parent/args/pos/thisObj.
|
||||
*/
|
||||
fun resetForReuse(parent: Scope?, args: Arguments, pos: Pos, thisObj: Obj) {
|
||||
ensureNoCycle(parent)
|
||||
this.parent = parent
|
||||
this.args = args
|
||||
this.pos = pos
|
||||
this.thisObj = thisObj
|
||||
// Fully detach from any previous chain/state first to avoid residual ancestry
|
||||
// that could interact badly with the new parent and produce a cycle.
|
||||
this.parent = null
|
||||
this.skipScopeCreation = false
|
||||
// fresh identity for PIC caches
|
||||
this.frameId = nextFrameId()
|
||||
@@ -315,6 +313,12 @@ open class Scope(
|
||||
slots.clear()
|
||||
nameToSlot.clear()
|
||||
localBindings.clear()
|
||||
// Now safe to validate and re-parent
|
||||
ensureNoCycle(parent)
|
||||
this.parent = parent
|
||||
this.args = args
|
||||
this.pos = pos
|
||||
this.thisObj = thisObj
|
||||
// Pre-size local slots for upcoming parameter assignment where possible
|
||||
reserveLocalCapacity(args.list.size + 4)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user