fixed some exception catching problems on wasm target
This commit is contained in:
parent
c6cfd52b01
commit
b6c6ef021a
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sergeych.lyng.obj
|
||||||
|
|
||||||
|
internal actual fun objListBoundsViolationMessageOrNull(size: Int, index: Int): String? = null
|
||||||
@ -3663,7 +3663,11 @@ class CmdGetIndex(
|
|||||||
val target = frame.storedSlotObj(targetSlot)
|
val target = frame.storedSlotObj(targetSlot)
|
||||||
val index = frame.storedSlotObj(indexSlot)
|
val index = frame.storedSlotObj(indexSlot)
|
||||||
if (target is ObjList && target::class == ObjList::class && index is ObjInt) {
|
if (target is ObjList && target::class == ObjList::class && index is ObjInt) {
|
||||||
frame.storeObjResult(dst, target.getObjAtFast(index.toInt()))
|
val i = index.toInt()
|
||||||
|
objListBoundsViolationMessageOrNull(target.sizeFast(), i)?.let {
|
||||||
|
frame.ensureScope().raiseIndexOutOfBounds(it)
|
||||||
|
}
|
||||||
|
frame.storeObjResult(dst, target.getObjAtFast(i))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val result = target.getAt(frame.ensureScope(), index)
|
val result = target.getAt(frame.ensureScope(), index)
|
||||||
@ -3682,7 +3686,11 @@ class CmdSetIndex(
|
|||||||
val index = frame.storedSlotObj(indexSlot)
|
val index = frame.storedSlotObj(indexSlot)
|
||||||
val value = frame.slotToObj(valueSlot)
|
val value = frame.slotToObj(valueSlot)
|
||||||
if (target is ObjList && target::class == ObjList::class && index is ObjInt) {
|
if (target is ObjList && target::class == ObjList::class && index is ObjInt) {
|
||||||
target.setObjAtFast(index.toInt(), value)
|
val i = index.toInt()
|
||||||
|
objListBoundsViolationMessageOrNull(target.sizeFast(), i)?.let {
|
||||||
|
frame.ensureScope().raiseIndexOutOfBounds(it)
|
||||||
|
}
|
||||||
|
target.setObjAtFast(i, value)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
target.putAt(frame.ensureScope(), index, value)
|
target.putAt(frame.ensureScope(), index, value)
|
||||||
@ -3699,6 +3707,9 @@ class CmdGetIndexInt(
|
|||||||
val target = frame.storedSlotObj(targetSlot)
|
val target = frame.storedSlotObj(targetSlot)
|
||||||
val index = frame.getInt(indexSlot).toInt()
|
val index = frame.getInt(indexSlot).toInt()
|
||||||
if (target is ObjList && target::class == ObjList::class) {
|
if (target is ObjList && target::class == ObjList::class) {
|
||||||
|
objListBoundsViolationMessageOrNull(target.sizeFast(), index)?.let {
|
||||||
|
frame.ensureScope().raiseIndexOutOfBounds(it)
|
||||||
|
}
|
||||||
target.getIntAtFast(index)?.let {
|
target.getIntAtFast(index)?.let {
|
||||||
frame.setInt(dst, it)
|
frame.setInt(dst, it)
|
||||||
return
|
return
|
||||||
@ -3722,6 +3733,9 @@ class CmdSetIndexInt(
|
|||||||
val target = frame.storedSlotObj(targetSlot)
|
val target = frame.storedSlotObj(targetSlot)
|
||||||
val index = frame.getInt(indexSlot).toInt()
|
val index = frame.getInt(indexSlot).toInt()
|
||||||
if (target is ObjList && target::class == ObjList::class) {
|
if (target is ObjList && target::class == ObjList::class) {
|
||||||
|
objListBoundsViolationMessageOrNull(target.sizeFast(), index)?.let {
|
||||||
|
frame.ensureScope().raiseIndexOutOfBounds(it)
|
||||||
|
}
|
||||||
target.setIntAtFast(index, frame.getInt(valueSlot))
|
target.setIntAtFast(index, frame.getInt(valueSlot))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -171,7 +171,9 @@ open class ObjList(initialList: MutableList<Obj> = mutableListOf()) : Obj() {
|
|||||||
override suspend fun getAt(scope: Scope, index: Obj): Obj {
|
override suspend fun getAt(scope: Scope, index: Obj): Obj {
|
||||||
return when (index) {
|
return when (index) {
|
||||||
is ObjInt -> {
|
is ObjInt -> {
|
||||||
getObjAtFast(index.toInt())
|
val i = index.toInt()
|
||||||
|
objListBoundsViolationMessageOrNull(sizeFast(), i)?.let { scope.raiseIndexOutOfBounds(it) }
|
||||||
|
getObjAtFast(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
is ObjRange -> {
|
is ObjRange -> {
|
||||||
@ -209,7 +211,9 @@ open class ObjList(initialList: MutableList<Obj> = mutableListOf()) : Obj() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open override suspend fun putAt(scope: Scope, index: Obj, newValue: Obj) {
|
open override suspend fun putAt(scope: Scope, index: Obj, newValue: Obj) {
|
||||||
setObjAtFast(index.toInt(), newValue)
|
val i = index.toInt()
|
||||||
|
objListBoundsViolationMessageOrNull(sizeFast(), i)?.let { scope.raiseIndexOutOfBounds(it) }
|
||||||
|
setObjAtFast(i, newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun compareTo(scope: Scope, other: Obj): Int {
|
override suspend fun compareTo(scope: Scope, other: Obj): Int {
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sergeych.lyng.obj
|
||||||
|
|
||||||
|
internal expect fun objListBoundsViolationMessageOrNull(size: Int, index: Int): String?
|
||||||
@ -16,8 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import net.sergeych.lyng.Script
|
||||||
import net.sergeych.lyng.eval
|
import net.sergeych.lyng.eval
|
||||||
|
import net.sergeych.lyng.evalNamed
|
||||||
|
import net.sergeych.lyng.obj.ObjException
|
||||||
|
import net.sergeych.lyng.obj.ObjInstance
|
||||||
|
import net.sergeych.lyng.obj.getLyngExceptionMessage
|
||||||
|
import net.sergeych.lyng.obj.getLyngExceptionStackTrace
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class StdlibTest {
|
class StdlibTest {
|
||||||
@Test
|
@Test
|
||||||
@ -373,4 +381,59 @@ class StdlibTest {
|
|||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testErrorCatching() = runTest {
|
||||||
|
val error = evalNamed("testErrorCatching", """
|
||||||
|
val src = [1,2,3]
|
||||||
|
val d = launch {
|
||||||
|
try {
|
||||||
|
for( i in 0..3 ) src[i]
|
||||||
|
} catch(e) {
|
||||||
|
e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.await()
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
val scope = when (error) {
|
||||||
|
is ObjException -> error.scope
|
||||||
|
is ObjInstance -> error.instanceScope
|
||||||
|
else -> Script.newScope()
|
||||||
|
}
|
||||||
|
val trace = error.getLyngExceptionStackTrace(scope)
|
||||||
|
val renderedTrace = trace.list.map { it.toString(scope).value }
|
||||||
|
|
||||||
|
assertEquals("Index 3 out of bounds for length 3", error.getLyngExceptionMessage(scope))
|
||||||
|
assertTrue(trace.list.size >= 2, "expected at least await and coroutine frames, got ${trace.list.size}")
|
||||||
|
assertTrue(
|
||||||
|
renderedTrace.all { it.contains("testErrorCatching:") },
|
||||||
|
"unexpected trace entries: $renderedTrace"
|
||||||
|
)
|
||||||
|
assertTrue(
|
||||||
|
renderedTrace.any { it.contains("launch") || it.contains("src[i]") },
|
||||||
|
"trace should include the coroutine body: $renderedTrace"
|
||||||
|
)
|
||||||
|
assertTrue(
|
||||||
|
renderedTrace.any { it.contains("d.await()") },
|
||||||
|
"trace should include await site: $renderedTrace"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCatchToIt() = runTest {
|
||||||
|
eval("""
|
||||||
|
var x = 0
|
||||||
|
try {
|
||||||
|
throw "msg1"
|
||||||
|
x = 1
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
assert(it.message == "msg1")
|
||||||
|
x = 2
|
||||||
|
}
|
||||||
|
assertEquals(2, x)
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sergeych.lyng.obj
|
||||||
|
|
||||||
|
internal actual fun objListBoundsViolationMessageOrNull(size: Int, index: Int): String? =
|
||||||
|
if (index < 0 || index >= size) "Index $index out of bounds for length $size" else null
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sergeych.lyng.obj
|
||||||
|
|
||||||
|
internal actual fun objListBoundsViolationMessageOrNull(size: Int, index: Int): String? = null
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sergeych.lyng.obj
|
||||||
|
|
||||||
|
internal actual fun objListBoundsViolationMessageOrNull(size: Int, index: Int): String? = null
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sergeych.lyng.obj
|
||||||
|
|
||||||
|
internal actual fun objListBoundsViolationMessageOrNull(size: Int, index: Int): String? =
|
||||||
|
if (index < 0 || index >= size) "Index $index out of bounds for length $size" else null
|
||||||
Loading…
x
Reference in New Issue
Block a user