tryling: better error reporting
This commit is contained in:
parent
01632dc6d7
commit
a229f227e1
@ -19,6 +19,7 @@ import androidx.compose.runtime.*
|
|||||||
import kotlinx.browser.window
|
import kotlinx.browser.window
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.sergeych.lyng.Scope
|
import net.sergeych.lyng.Scope
|
||||||
|
import net.sergeych.lyng.ScriptError
|
||||||
import net.sergeych.site.SiteHighlight
|
import net.sergeych.site.SiteHighlight
|
||||||
import org.jetbrains.compose.web.attributes.placeholder
|
import org.jetbrains.compose.web.attributes.placeholder
|
||||||
import org.jetbrains.compose.web.dom.*
|
import org.jetbrains.compose.web.dom.*
|
||||||
@ -44,6 +45,7 @@ fun TryLyngPage() {
|
|||||||
var running by remember { mutableStateOf(false) }
|
var running by remember { mutableStateOf(false) }
|
||||||
var output by remember { mutableStateOf<String?>(null) }
|
var output by remember { mutableStateOf<String?>(null) }
|
||||||
var error by remember { mutableStateOf<String?>(null) }
|
var error by remember { mutableStateOf<String?>(null) }
|
||||||
|
var extendedError by remember { mutableStateOf<String?>(null) }
|
||||||
|
|
||||||
fun runCode() {
|
fun runCode() {
|
||||||
if (running) return
|
if (running) return
|
||||||
@ -91,18 +93,27 @@ fun TryLyngPage() {
|
|||||||
// Prefer detailed message including stack if available (K/JS)
|
// Prefer detailed message including stack if available (K/JS)
|
||||||
val errText = buildString {
|
val errText = buildString {
|
||||||
append(t.toString())
|
append(t.toString())
|
||||||
|
if (t !is ScriptError) {
|
||||||
try {
|
try {
|
||||||
val st = t.asDynamic().stack as? String
|
val st = t.asDynamic().stack as? String
|
||||||
if (!st.isNullOrBlank()) {
|
if (!st.isNullOrBlank()) {
|
||||||
append("\n")
|
append("\n")
|
||||||
append(st)
|
append(st)
|
||||||
}
|
}
|
||||||
} catch (_: Throwable) {}
|
} catch (_: Throwable) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (printed.isNotEmpty()) {
|
if (printed.isNotEmpty()) {
|
||||||
output = printed.toString()
|
output = printed.toString()
|
||||||
}
|
}
|
||||||
error = errText
|
if (t is ScriptError) {
|
||||||
|
error = t.errorMessage
|
||||||
|
extendedError = errText
|
||||||
|
} else {
|
||||||
|
error = t.message
|
||||||
|
extendedError = errText
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
running = false
|
running = false
|
||||||
}
|
}
|
||||||
@ -182,10 +193,10 @@ fun TryLyngPage() {
|
|||||||
if (output != null) {
|
if (output != null) {
|
||||||
Pre({ classes("mb-0") }) { Code { Text(output!!) } }
|
Pre({ classes("mb-0") }) { Code { Text(output!!) } }
|
||||||
}
|
}
|
||||||
if (error != null) {
|
if (extendedError != null) {
|
||||||
if (output != null) Hr({})
|
if (output != null) Hr({})
|
||||||
Div({ classes("alert", "alert-danger", "mb-0") }) {
|
Div({ classes("alert", "alert-danger", "mb-0") }) {
|
||||||
Pre({ classes("mb-0") }) { Code { Text(error!!) } }
|
Pre({ classes("mb-0") }) { Code { Text(extendedError!!) } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,6 +368,7 @@ private fun EditorWithOverlay(
|
|||||||
val ta = taEl ?: return@LaunchedEffect
|
val ta = taEl ?: return@LaunchedEffect
|
||||||
val ov = overlayEl ?: return@LaunchedEffect
|
val ov = overlayEl ?: return@LaunchedEffect
|
||||||
val cs = window.getComputedStyle(ta)
|
val cs = window.getComputedStyle(ta)
|
||||||
|
|
||||||
// Resolve a concrete pixel line-height; some browsers return "normal" or unitless
|
// Resolve a concrete pixel line-height; some browsers return "normal" or unitless
|
||||||
fun ensurePxLineHeight(): String {
|
fun ensurePxLineHeight(): String {
|
||||||
val lh = cs.lineHeight ?: ""
|
val lh = cs.lineHeight ?: ""
|
||||||
@ -368,10 +380,14 @@ private fun EditorWithOverlay(
|
|||||||
probe.textContent = "M"
|
probe.textContent = "M"
|
||||||
val fw = try {
|
val fw = try {
|
||||||
(cs.asDynamic().fontWeight as? String) ?: cs.getPropertyValue("font-weight")
|
(cs.asDynamic().fontWeight as? String) ?: cs.getPropertyValue("font-weight")
|
||||||
} catch (_: Throwable) { null }
|
} catch (_: Throwable) {
|
||||||
|
null
|
||||||
|
}
|
||||||
val fs = try {
|
val fs = try {
|
||||||
(cs.asDynamic().fontStyle as? String) ?: cs.getPropertyValue("font-style")
|
(cs.asDynamic().fontStyle as? String) ?: cs.getPropertyValue("font-style")
|
||||||
} catch (_: Throwable) { null }
|
} catch (_: Throwable) {
|
||||||
|
null
|
||||||
|
}
|
||||||
probe.setAttribute(
|
probe.setAttribute(
|
||||||
"style",
|
"style",
|
||||||
buildString {
|
buildString {
|
||||||
@ -393,6 +409,7 @@ private fun EditorWithOverlay(
|
|||||||
val approx = if (fsPx != null) fsPx * 1.2 else 16.0 * 1.2
|
val approx = if (fsPx != null) fsPx * 1.2 else 16.0 * 1.2
|
||||||
return "${'$'}{approx}px"
|
return "${'$'}{approx}px"
|
||||||
}
|
}
|
||||||
|
|
||||||
val lineHeightPx = ensurePxLineHeight()
|
val lineHeightPx = ensurePxLineHeight()
|
||||||
// copy key properties
|
// copy key properties
|
||||||
val style = buildString {
|
val style = buildString {
|
||||||
@ -408,11 +425,15 @@ private fun EditorWithOverlay(
|
|||||||
// Try to mirror weight and style to eliminate metric differences
|
// Try to mirror weight and style to eliminate metric differences
|
||||||
val fw = try {
|
val fw = try {
|
||||||
(cs.asDynamic().fontWeight as? String) ?: cs.getPropertyValue("font-weight")
|
(cs.asDynamic().fontWeight as? String) ?: cs.getPropertyValue("font-weight")
|
||||||
} catch (_: Throwable) { null }
|
} catch (_: Throwable) {
|
||||||
|
null
|
||||||
|
}
|
||||||
if (!fw.isNullOrBlank()) append("font-weight:").append(fw).append(";")
|
if (!fw.isNullOrBlank()) append("font-weight:").append(fw).append(";")
|
||||||
val fs = try {
|
val fs = try {
|
||||||
(cs.asDynamic().fontStyle as? String) ?: cs.getPropertyValue("font-style")
|
(cs.asDynamic().fontStyle as? String) ?: cs.getPropertyValue("font-style")
|
||||||
} catch (_: Throwable) { null }
|
} catch (_: Throwable) {
|
||||||
|
null
|
||||||
|
}
|
||||||
if (!fs.isNullOrBlank()) append("font-style:").append(fs).append(";")
|
if (!fs.isNullOrBlank()) append("font-style:").append(fs).append(";")
|
||||||
// Disable ligatures in overlay to keep glyph advances identical to textarea
|
// Disable ligatures in overlay to keep glyph advances identical to textarea
|
||||||
append("font-variant-ligatures:none;")
|
append("font-variant-ligatures:none;")
|
||||||
@ -433,8 +454,10 @@ private fun EditorWithOverlay(
|
|||||||
if (!existing.contains("line-height")) {
|
if (!existing.contains("line-height")) {
|
||||||
ta.setAttribute("style", existing + " line-height: " + lineHeightPx + ";")
|
ta.setAttribute("style", existing + " line-height: " + lineHeightPx + ";")
|
||||||
}
|
}
|
||||||
} catch (_: Throwable) {}
|
} catch (_: Throwable) {
|
||||||
} catch (_: Throwable) {}
|
}
|
||||||
|
} catch (_: Throwable) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// container
|
// container
|
||||||
@ -558,7 +581,8 @@ private fun EditorWithOverlay(
|
|||||||
if (start != end) {
|
if (start != end) {
|
||||||
// Indent selected lines
|
// Indent selected lines
|
||||||
val regionStart = currentLineStartIndex(code, start)
|
val regionStart = currentLineStartIndex(code, start)
|
||||||
val regionEnd = code.indexOf('\n', startIndex = end).let { if (it == -1) code.length else it }
|
val regionEnd =
|
||||||
|
code.indexOf('\n', startIndex = end).let { if (it == -1) code.length else it }
|
||||||
val region = code.substring(regionStart, regionEnd)
|
val region = code.substring(regionStart, regionEnd)
|
||||||
val lines = region.split("\n")
|
val lines = region.split("\n")
|
||||||
val indentStr = " ".repeat(tabSize)
|
val indentStr = " ".repeat(tabSize)
|
||||||
@ -591,6 +615,7 @@ private fun EditorWithOverlay(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"Enter" -> {
|
"Enter" -> {
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
val before = code.substring(0, start)
|
val before = code.substring(0, start)
|
||||||
@ -610,6 +635,7 @@ private fun EditorWithOverlay(
|
|||||||
pendingScrollLeft = savedScrollLeft
|
pendingScrollLeft = savedScrollLeft
|
||||||
setCode(newCode)
|
setCode(newCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
"}" -> {
|
"}" -> {
|
||||||
// If the current line contains only indentation up to the caret,
|
// If the current line contains only indentation up to the caret,
|
||||||
// outdent by one indent level (tab or up to tabSize spaces) before inserting '}'.
|
// outdent by one indent level (tab or up to tabSize spaces) before inserting '}'.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user