Skip to content

Commit f177e27

Browse files
authored
Merge pull request #82 from modelix/text-editor4
Several fixes for the light-model-client when used in the browser
2 parents c9e7359 + 98e99fd commit f177e27

File tree

26 files changed

+519
-353
lines changed

26 files changed

+519
-353
lines changed

light-model-client/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ kotlin {
2121
}
2222
}
2323
}
24+
useCommonJs()
2425
}
2526

2627
sourceSets {

light-model-client/src/commonMain/kotlin/org/modelix/client/light/LightModelClient.kt

Lines changed: 164 additions & 108 deletions
Large diffs are not rendered by default.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.modelix.client.light
2+
3+
internal expect class ReadWriteLock() {
4+
fun <T> runRead(body: () -> T): T
5+
fun <T> runWrite(body: () -> T): T
6+
fun canRead(): Boolean
7+
fun canWrite(): Boolean
8+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.modelix.client.light
2+
3+
internal actual class ReadWriteLock {
4+
private var lock: LockType = LockType.Unlocked
5+
actual fun <T> runRead(body: () -> T): T {
6+
val previous = lock
7+
try {
8+
lock = LockType.Read
9+
return body()
10+
} finally {
11+
lock = previous
12+
}
13+
}
14+
15+
actual fun <T> runWrite(body: () -> T): T {
16+
if (lock == LockType.Read) throw IllegalStateException("Cannot start write from read")
17+
val previous = lock
18+
try {
19+
lock = LockType.Write
20+
return body()
21+
} finally {
22+
lock = previous
23+
}
24+
}
25+
26+
actual fun canRead(): Boolean = lock != LockType.Unlocked
27+
28+
actual fun canWrite(): Boolean = lock == LockType.Write
29+
}
30+
31+
private enum class LockType {
32+
Unlocked,
33+
Read,
34+
Write
35+
}

light-model-client/src/jsMain/kotlin/org/modelix/client/light/WebsocketConnectionJS.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ fun createLightModelClient(url: String = "ws://localhost:48302/ws", query: Model
2525
val httpClient = HttpClient(Js) {
2626
install(WebSockets)
2727
}
28-
val modelClient = LightModelClient(WebsocketConnection(httpClient, url))
28+
val modelClient = LightModelClient.builder().httpClient(httpClient).url(url).build()
2929
if (query != null) modelClient.changeQuery(query)
3030
return modelClient
3131
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.modelix.client.light
2+
3+
import java.util.concurrent.locks.ReentrantReadWriteLock
4+
import kotlin.concurrent.read
5+
import kotlin.concurrent.write
6+
7+
internal actual class ReadWriteLock {
8+
private val lock = ReentrantReadWriteLock()
9+
private val isReadLockedByCurrentThread: ThreadLocal<Boolean> = ThreadLocal.withInitial { false }
10+
actual fun <T> runRead(body: () -> T): T {
11+
return lock.read {
12+
val wasInRead = isReadLockedByCurrentThread.get()
13+
try {
14+
if (!wasInRead) isReadLockedByCurrentThread.set(true)
15+
body()
16+
} finally {
17+
if (!wasInRead) isReadLockedByCurrentThread.set(false)
18+
}
19+
}
20+
}
21+
actual fun <T> runWrite(body: () -> T): T = lock.write(body)
22+
actual fun canRead(): Boolean = lock.isWriteLockedByCurrentThread || isReadLockedByCurrentThread.get()
23+
24+
actual fun canWrite(): Boolean = lock.isWriteLockedByCurrentThread
25+
26+
}

light-model-client/src/jvmTest/kotlin/org/modelix/client/light/LightModelClientTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class LightModelClientTest {
6868
.url("ws://localhost/json/v2/test-repo/ws")
6969
.debugName(debugName)
7070
.build()
71-
wait {client.isInitialized() }
71+
wait { client.isInitialized() }
7272
client
7373
}
7474
block(createClient)

model-api-gen-runtime/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ kotlin {
1919
}
2020
}
2121
}
22+
useCommonJs()
2223
}
2324

2425
sourceSets {

model-api/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ kotlin {
3939
}
4040
}
4141
}
42+
useCommonJs()
4243
}
4344
sourceSets {
4445
val commonMain by getting {
@@ -83,6 +84,6 @@ kotlin {
8384
listOf("sourcesJar", "runKtlintCheckOverJsMainSourceSet", "jsSourcesJar", "jsPackageJson", "compileKotlinJs", "jsProcessResources").forEach {
8485
tasks.named(it) {
8586
dependsOn(":ts-model-api:npm_run_build")
86-
dependsOn(":ts-model-api:npm_run_generateKotlin")
87+
dependsOn(":ts-model-api:patchKotlinExternals")
8788
}
8889
}

model-api/src/jsMain/kotlin/org/modelix/model/api/NodeAdapterCache.kt

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ object NodeAdapterCache {
2828
}, 0)
2929
}
3030

31-
val key = toINode(node)
31+
val key = JSNodeConverter.toINode(node)
3232
var wrapper = caches[0][key]
3333
if (wrapper == null) {
3434
wrapper = caches.asSequence().drop(1).mapNotNull { it.remove(key) }.firstOrNull()
@@ -39,18 +39,4 @@ object NodeAdapterCache {
3939
}
4040
return wrapper as Out
4141
}
42-
43-
private fun toINode(node: Any): INode {
44-
if (node is INode) return node
45-
if (node is NodeAdapterJS) return node.node
46-
47-
// if (node is TypedNode) return toINode(node.node)
48-
49-
// Workaround, because the line above fails with 'TypedNode is not defined'.
50-
// The import for '@modelix/ts-model-api' seems to be missing in the generated JS.
51-
val unwrapped = node.asDynamic().node
52-
if (unwrapped != null) return toINode(unwrapped)
53-
54-
throw IllegalArgumentException("Unsupported node type: $node")
55-
}
5642
}

0 commit comments

Comments
 (0)