Prevent cross-script module slot aliasing
This commit is contained in:
parent
ee634c8dff
commit
c80900c503
@ -108,11 +108,7 @@ class Script(
|
|||||||
seedImportBindings(scope, seedScope)
|
seedImportBindings(scope, seedScope)
|
||||||
}
|
}
|
||||||
if (moduleSlotPlan.isNotEmpty()) {
|
if (moduleSlotPlan.isNotEmpty()) {
|
||||||
scope.applySlotPlan(moduleSlotPlan)
|
installModuleSlotPlan(scope)
|
||||||
for (name in moduleSlotPlan.keys) {
|
|
||||||
val record = scope.objects[name] ?: scope.localBindings[name] ?: continue
|
|
||||||
scope.updateSlotFor(name, record)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,12 +116,26 @@ class Script(
|
|||||||
if (importBindings.isEmpty() && importedModules.isEmpty()) return
|
if (importBindings.isEmpty() && importedModules.isEmpty()) return
|
||||||
seedImportBindings(scope, seedScope)
|
seedImportBindings(scope, seedScope)
|
||||||
if (moduleSlotPlan.isNotEmpty()) {
|
if (moduleSlotPlan.isNotEmpty()) {
|
||||||
scope.applySlotPlan(moduleSlotPlan)
|
installModuleSlotPlan(scope)
|
||||||
for (name in moduleSlotPlan.keys) {
|
}
|
||||||
val record = scope.objects[name] ?: scope.localBindings[name] ?: continue
|
}
|
||||||
scope.updateSlotFor(name, record)
|
|
||||||
|
private fun installModuleSlotPlan(scope: Scope) {
|
||||||
|
for ((name, index) in moduleSlotPlan) {
|
||||||
|
if (scope.getSlotIndexOf(name) != null) continue
|
||||||
|
if (scope.hasSlotPlanConflict(mapOf(name to index))) {
|
||||||
|
val record = scope.objects[name]
|
||||||
|
?: scope.localBindings[name]
|
||||||
|
?: ObjRecord(ObjUnset, isMutable = true)
|
||||||
|
scope.allocateSlotFor(name, record)
|
||||||
|
} else {
|
||||||
|
scope.applySlotPlan(mapOf(name to index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (name in moduleSlotPlan.keys) {
|
||||||
|
val record = scope.objects[name] ?: scope.localBindings[name] ?: continue
|
||||||
|
scope.updateSlotFor(name, record)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun seedModuleLocals(
|
private suspend fun seedModuleLocals(
|
||||||
|
|||||||
@ -5654,6 +5654,14 @@ class CmdFrame(
|
|||||||
if (index < target.slotCount) return index
|
if (index < target.slotCount) return index
|
||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
|
if (target.hasSlotPlanConflict(mapOf(name to index))) {
|
||||||
|
val record = target.getLocalRecordDirect(name)
|
||||||
|
?: target.localBindings[name]
|
||||||
|
?: target.parent?.get(name)
|
||||||
|
?: target.get(name)
|
||||||
|
?: ObjRecord(ObjUnset, isMutable = true)
|
||||||
|
return target.allocateSlotFor(name, record)
|
||||||
|
}
|
||||||
target.applySlotPlan(mapOf(name to index))
|
target.applySlotPlan(mapOf(name to index))
|
||||||
val existing = target.getLocalRecordDirect(name) ?: target.localBindings[name]
|
val existing = target.getLocalRecordDirect(name) ?: target.localBindings[name]
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
|
|||||||
@ -150,6 +150,37 @@ class CompilerVmReviewRegressionTest {
|
|||||||
assertEquals(42, callable.call(scope, ObjInt.of(40)).toInt())
|
assertEquals(42, callable.call(scope, ObjInt.of(40)).toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun preparedLambdaKeepsImmutableModuleCaptureAcrossOtherScriptsInSameScope() = runTest {
|
||||||
|
val unaryLambda = Compiler.compile(
|
||||||
|
Source(
|
||||||
|
"<cross-script-capture-unary>",
|
||||||
|
"""
|
||||||
|
val delta = 2
|
||||||
|
{ x -> x + delta }
|
||||||
|
""".trimIndent()
|
||||||
|
),
|
||||||
|
Script.defaultImportManager
|
||||||
|
)
|
||||||
|
val unrelatedScript = Compiler.compile(
|
||||||
|
Source(
|
||||||
|
"<cross-script-capture-unrelated>",
|
||||||
|
"""
|
||||||
|
val base = 7
|
||||||
|
base
|
||||||
|
""".trimIndent()
|
||||||
|
),
|
||||||
|
Script.defaultImportManager
|
||||||
|
)
|
||||||
|
|
||||||
|
val scope = Script.newScope()
|
||||||
|
val callable = unaryLambda.execute(scope) as Statement
|
||||||
|
unrelatedScript.execute(scope)
|
||||||
|
|
||||||
|
assertEquals(42, callable.call(scope, ObjInt.of(40)).toInt())
|
||||||
|
assertEquals(42, scope.asFacade().call(callable, Arguments(ObjInt.of(40))).toInt())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun subjectlessWhenReportsScriptError() = runTest {
|
fun subjectlessWhenReportsScriptError() = runTest {
|
||||||
val ex = assertFailsWith<ScriptError> {
|
val ex = assertFailsWith<ScriptError> {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user