Run Kotlin/JS libraries in Kotlin/JVM and Kotlin/Native programs

Related tags

Kotlin zipline
Overview

Zipline

This library streamlines using Kotlin/JS libraries from Kotlin/JVM and Kotlin/Native programs. It makes it possible to do continuous deployment of mobile apps, just like we do for servers and web applications.

It'd be simpler to do continuous deploys via the App Store & Play Store! But that process is too slow. Even if we could release via these channels every day, we can’t guarantee that user’s devices will take the updates immediately. For Cash App we support apps that haven’t been updated for a full year.

(Looking for Duktape Android?)

QuickJS

This library uses the QuickJS embeddable JavaScript engine to execute Kotlin/JS. It's included in this library and supports both Android and the JVM.

QuickJS Usage

try (QuickJs engine = QuickJs.create()) {
  Log.d("Greeting", engine.evaluate("'hello world'.toUpperCase();").toString());
}

For long-lived usage feel free to call QuickJs.create() and retain the returned instance for as long as you need. Be sure to call .close() when you are done to avoid leaking native components.

Supported Java Types

Currently, the following Java types are supported when interfacing with JavaScript:

  • boolean and Boolean
  • int and Integer - as an argument only (not a return value) when calling JavaScript from Java.
  • double and Double
  • String
  • void - as a return value.

Object is also supported in declarations, but the type of the actual value passed must be one of the above or null.

Calling Java from JavaScript

You can provide a Java object for use as a JavaScript global, and call Java functions from JavaScript!

Example

Suppose we wanted to expose the functionality of Okio's ByteString in JavaScript to convert hex-encoded strings back into UTF-8. First, define a Java interface that declares the methods you would like to call from JavaScript:

interface Utf8 {
  String fromHex(String hex);
}

Next, implement the interface in Java code (we leave the heavy lifting to Okio):

Utf8 utf8 = new Utf8() {
  @Override public String fromHex(String hex) {
    return okio.ByteString.decodeHex(hex).utf8();
  }
};

Now you can set the object to a JavaScript global, making it available in JavaScript code:

// Attach our interface to a JavaScript object called Utf8.
engine.set("Utf8", Utf8.class, utf8);

String greeting = (String) engine.evaluate(""
    // Here we have a hex encoded string.
    + "var hexEnc = 'EC9588EB8595ED9598EC84B8EC9A9421';\n"
    // Call out to Java to decode it!
    + "var message = Utf8.fromHex(hexEnc);\n"
    + "message;");

Log.d("Greeting", greeting);

Calling JavaScript from Java

You can attach a Java interface to a JavaScript global object, and call JavaScript functions directly from Java! The same Java types are supported for function arguments and return values as the opposite case above.

Example

TODO fix this example, as it no longer works with QuickJS! You should still be able to understand what is going on, though.

Imagine a world where we don't have Okio's ByteString. Fortunately, there's a [Duktape builtin][dukdec] that allows us to convert hex-encoded strings back into UTF-8! We can easily set up a proxy that allows us to use it directly from our Java code. First, define a Java interface that declares the JavaScript methods you would like to call:

interface Utf8 {
  String fromHex(String hex);
}

Next, we define a global JavaScript object in Duktape to connect to:

// Note that Duktape.dec returns a Buffer, we must convert it to a String return value.
engine.evaluate(""
    + "var Utf8 = {\n"
    + "  fromHex: function(v) { return String(Duktape.dec('hex', v)); }\n"
    + "};");

Now you can connect our interface to the JavaScript global, making it available in Java code:

// Connect our interface to a JavaScript object called Utf8.
Utf8 utf8 = engine.get("Utf8", Utf8.class);

// Call into the JavaScript object to decode a string.
String greeting = utf8.fromHex("EC9588EB8595ED9598EC84B8EC9A9421");
Log.d("Greeting", greeting);

Download

This project supports both Android and Java. On Java only Linux and macOS are currently supported.

repositories {
  mavenCentral()
}
dependencies {
  implementation 'app.cash.zipline:zipline:0.1.0'
}

This library is provided as a "fat" .aar with native binaries for all available architectures. To reduce your binary size, use ABI filtering/splitting when building an APK and/or enable Android App Bundles.

Snapshots of the development version are available in Sonatype's snapshots repository.

repository {
  mavenCentral()
  maven {
    url 'https://oss.sonatype.org/content/repositories/snapshots/'
  }
}
dependencies {
  implementation 'app.cash.zipline:zipline:1.0.0-SNAPSHOT'
}

Building

For Android

$ ./gradlew :quickjs:android:build

The build system will automatically cross-compile the native library to all applicable ABIs and create the fat .aar in quickjs/android/build/outputs/aar/.

This will not run the tests. You must have a working device or emulator connected at which point you can explicitly run them.

$ ./gradlew :quickjs:android:connectedCheck

For the JVM

First, build the native library for your host OS:

$ cmake -S quickjs/jvm/ -B build/jni/ -DQUICKJS_VERSION="$(cat quickjs/common/native/quickjs/VERSION)"
$ cmake --build build/jni/ --verbose

Next, copy the resulting binary into the resources of the JVM project:

$ mkdir -p quickjs/jvm/src/main/resources/
$ cp -v build/jni/libquickjs.* quickjs/jvm/src/main/resources/

Finally, build the platform-specific .jar and run the tests:

$ ./gradlew :quickjs:jvm:build

The .jar will be available in quickjs/jvm/build/libs/.

License

Copyright 2015 Square, Inc.

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.

Note: The included C code from QuickJS is licensed under MIT.

Duktape

This repository used to host an Android-specific packaging of the Duktape engine. We have changed to using QuickJS with exactly the same features and API. The Duktape history is still present in this repo as are the release tags. Available versions are listed on Maven central.

Comments
  • Call Java functions from duktape

    Call Java functions from duktape

    It would be useful to be able to call native Java/Android functions from within JavaScript, similar to how Rhino allows importing native functions.

    For my specific case there is no need to implement full support for conversion between Java and JS objects, it would be enough to just be able to call a function with primitive arguments like double, String, int.

    opened by josdejong 12
  • Zipline JVM artifacts assume Macs are X64

    Zipline JVM artifacts assume Macs are X64

    I’m getting failures like this from our internal releases:

    > /private/var/folders/6n/t4d4n1c506d9m_l6t331gftm0000gn/T/quickjs12749920372263119972.tmp: dlopen(/private/var/folders/6n/t4d4n1c506d9m_l6t331gftm0000gn/T/quickjs12749920372263119972.tmp, 0x0001): tried: '/private/var/folders/6n/t4d4n1c506d9m_l6t331gftm0000gn/T/quickjs12749920372263119972.tmp' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e')), '/usr/lib/quickjs12749920372263119972.tmp' (no such file)
    
    opened by swankjesse 8
  • JNI ERROR (app bug): local reference table overflow (max=512)

    JNI ERROR (app bug): local reference table overflow (max=512)

    JNI ERROR (app bug): local reference table overflow (max=512) art/runtime/indirect_reference_table.cc:132] local reference table dump: art/runtime/indirect_reference_table.cc:132] Last 10 entries (of 512): art/runtime/indirect_reference_table.cc:132] 511: 0x134f6250 libcore.util.ZoneInfo art/runtime/indirect_reference_table.cc:132] 510: 0x134f6220 libcore.util.ZoneInfo art/runtime/indirect_reference_table.cc:132] 509: 0x134f61f0 libcore.util.ZoneInfo art/runtime/indirect_reference_table.cc:132] 508: 0x134f61c0 libcore.util.ZoneInfo art/runtime/indirect_reference_table.cc:132] 507: 0x134f6190 libcore.util.ZoneInfo art/runtime/indirect_reference_table.cc:132] 506: 0x134f6160 libcore.util.ZoneInfo art/runtime/indirect_reference_table.cc:132] 505: 0x134f6130 libcore.util.ZoneInfo art/runtime/indirect_reference_table.cc:132] 504: 0x134f6100 libcore.util.ZoneInfo art/runtime/indirect_reference_table.cc:132] 503: 0x134f60d0 libcore.util.ZoneInfo art/runtime/indirect_reference_table.cc:132] 502: 0x134f60a0 libcore.util.ZoneInfo art/runtime/indirect_reference_table.cc:132] Summary: art/runtime/indirect_reference_table.cc:132] 2 of $Proxy21 (1 unique instances) art/runtime/indirect_reference_table.cc:132] 2 of $Proxy20 (1 unique instances) art/runtime/indirect_reference_table.cc:132] 1 of java.lang.Thread art/runtime/indirect_reference_table.cc:132] 2 of java.lang.reflect.Method (2 unique instances) art/runtime/indirect_reference_table.cc:132] 4 of java.lang.String (2 unique instances) art/runtime/indirect_reference_table.cc:132] 1 of java.util.ArrayList art/runtime/indirect_reference_table.cc:132] 1 of java.lang.Object[] (1 elements) art/runtime/indirect_reference_table.cc:132] 1 of java.lang.Object[] (2 elements) art/runtime/indirect_reference_table.cc:132] 498 of libcore.util.ZoneInfo (498 unique instances)

    I getting the above error when i am using

    get(final String name, final Class type)

    the type interface is this:

      interface JsBinder {
    
            fun androidWrapper(functionName: String, **input**: String): String
    
        }
    

    the String **input** in the interface is an Array of 44 objects. Work fine when less elements in array are present.

    Originally posted by @resengupta in https://github.com/square/duktape-android/issues/90#issuecomment-444849438

    opened by resengupta 7
  • DuktapeException: TypeError: cannot read property 'prototype' of undefined

    DuktapeException: TypeError: cannot read property 'prototype' of undefined

       Caused by: com.squareup.duktape.DuktapeException: TypeError: cannot read property 'prototype' of undefined
                                                                        at JavaScript.runInContext(?:43226)
                                                                        at JavaScript.s(?:1)
                                                                        at com.squareup.duktape.Duktape.evaluate(Native Method)
                                                                        at com.squareup.duktape.Duktape.evaluate(Duktape.java:69)
    

    here is my code:

    val duktape = Duktape.create()
            try {
                duktape.evaluate(assets.open("bundle.js").reader(Charset.forName("UTF-8")).readText())
                LogHelper.LogE("--->" + duktape.evaluate("generateAddress").toString())
            } finally {
                duktape.close()
            }
    
    Address.prototype.isPayToScriptHash = function() {
      return this.type === Address.PayToScriptHash;
    };
    
    opened by badboy-tian 7
  • Rhino over Duktape

    Rhino over Duktape

    Hi,

    I was searching for a JS engine for Android and it seems that Rhino is ~10% more efficient than Duktape. What do you think about it? Maybe a real benchmark could be helpful...

    opened by HugoGresse 7
  • When call Duktape.close() , native crash occured.

    When call Duktape.close() , native crash occured.

    **I'm using duktape-android in Thread and multi.

    when I run duktape-android about over 300 times, out of memory occured. So I called Duktape at end of script. When I called Duktape.close(), native crash occured. Below is the log.**

    12-18 10:00:12.897 29666-714/com.kwic.smartaibmonitormaster E/libc++abi: Pure virtual function called! 12-18 10:00:12.898 29666-714/com.kwic.smartaibmonitormaster A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 714 (Thread-4)

                                                                    [ 12-18 10:00:12.899   476:  476 W/         ]
                                                                    debuggerd: handling request: pid=29666 uid=10207 gid=10207 tid=714
    

    12-18 10:00:12.972 759-759/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 12-18 10:00:12.973 759-759/? A/DEBUG: Build fingerprint: 'lge/lucye_lgu_kr/lucye:7.0/NRD90U/172411421f9f3:user/release-keys' 12-18 10:00:12.973 759-759/? A/DEBUG: Revision: '12' 12-18 10:00:12.973 759-759/? A/DEBUG: ABI: 'arm64' 12-18 10:00:12.973 759-759/? A/DEBUG: pid: 29666, tid: 714, name: Thread-4 >>> com.kwic.smartaibmonitormaster <<< 12-18 10:00:12.973 759-759/? A/DEBUG: signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- 12-18 10:00:12.973 759-759/? A/DEBUG: x0 0000000000000000 x1 00000000000002ca x2 0000000000000006 x3 0000000000000008 12-18 10:00:12.973 759-759/? A/DEBUG: x4 ffffffffffffffff x5 8080800000000000 x6 0000000000808080 x7 fefeff2063646b6b 12-18 10:00:12.973 759-759/? A/DEBUG: x8 0000000000000083 x9 ffffffffffffffdf x10 0000000000000000 x11 0000000000000001 12-18 10:00:12.973 759-759/? A/DEBUG: x12 ffffffffffffffff x13 0000000000000000 x14 0000000000000000 x15 00357c6e098c12a3 12-18 10:00:12.973 759-759/? A/DEBUG: x16 00000075b8551ed0 x17 00000075b84fb3f4 x18 00000000ffffffff x19 00000075ac8c14f8 12-18 10:00:12.973 759-759/? A/DEBUG: x20 0000000000000006 x21 00000075ac8c1450 x22 0000000000000000 x23 00000000ffffffc8 12-18 10:00:12.973 759-759/? A/DEBUG: x24 00000075ac8bdd60 x25 00000075ac8bdc30 x26 00000075ac8bdc70 x27 0000000000000001 12-18 10:00:12.973 759-759/? A/DEBUG: x28 00000075ad48f728 x29 00000075ac8bdb40 x30 00000075b84f8884 12-18 10:00:12.973 759-759/? A/DEBUG: sp 00000075ac8bdb20 pc 00000075b84fb3fc pstate 0000000060000000 12-18 10:00:12.983 759-759/? A/DEBUG: backtrace: 12-18 10:00:12.983 759-759/? A/DEBUG: #00 pc 000000000006c3fc /system/lib64/libc.so (tgkill+8) 12-18 10:00:12.983 759-759/? A/DEBUG: #01 pc 0000000000069880 /system/lib64/libc.so (pthread_kill+64) 12-18 10:00:12.983 759-759/? A/DEBUG: #02 pc 0000000000024658 /system/lib64/libc.so (raise+24) 12-18 10:00:12.983 759-759/? A/DEBUG: #03 pc 000000000001d074 /system/lib64/libc.so (abort+52) 12-18 10:00:12.983 759-759/? A/DEBUG: #04 pc 000000000008c72c /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so 12-18 10:00:12.983 759-759/? A/DEBUG: #05 pc 000000000008a5b0 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so (__cxa_pure_virtual+16) 12-18 10:00:12.983 759-759/? A/DEBUG: #06 pc 0000000000017b64 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so 12-18 10:00:12.983 759-759/? A/DEBUG: #07 pc 0000000000017504 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so 12-18 10:00:12.983 759-759/? A/DEBUG: #08 pc 0000000000078d5c /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so 12-18 10:00:12.983 759-759/? A/DEBUG: #09 pc 000000000007f564 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so 12-18 10:00:12.983 759-759/? A/DEBUG: #10 pc 000000000007a1b0 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so 12-18 10:00:12.983 759-759/? A/DEBUG: #11 pc 0000000000078e24 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so 12-18 10:00:12.983 759-759/? A/DEBUG: #12 pc 0000000000021b98 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so 12-18 10:00:12.984 759-759/? A/DEBUG: #13 pc 0000000000024fd4 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so (duk_eval_raw+188) 12-18 10:00:12.984 759-759/? A/DEBUG: #14 pc 0000000000014500 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so 12-18 10:00:12.984 759-759/? A/DEBUG: #15 pc 0000000000015bf8 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so (Java_com_squareup_duktape_Duktape_evaluate__JLjava_lang_String_2Ljava_lang_String_2+52) 12-18 10:00:12.984 759-759/? A/DEBUG: #16 pc 00000000001f324c /data/app/com.kwic.smartaibmonitormaster-2/oat/arm64/base.odex (offset 0x1e9000)

    opened by jeonhoeun 6
  • local reference table overflow (max=512) error

    local reference table overflow (max=512) error

    when I call duktape.set ("someName" , interface.class, interface instance );

    local reference table overflow (max=512) error occured

    interface method has 40 methods.

    and if I set method count 30, the error is not occured.

    so I'm call set two interface.class.

    the first interface has 20 methods. and second interfacde has 20 method.

    Is it a bug?

    opened by jeonhoeun 6
  • JNI ERROR (app bug): accessed deleted global reference

    JNI ERROR (app bug): accessed deleted global reference

    09-10 12:11:44.183 7478 8530 E     art                                          JNI ERROR (app bug): accessed deleted global reference 0x100752
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: use of deleted global reference 0x100752
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]     from long com.squareup.duktape.Duktape.createContext()
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410] "RxIoScheduler-20" daemon prio=5 tid=82 Runnable
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   | group="main" sCount=0 dsCount=0 obj=0x339f5b20 self=0x7f0474d000
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   | sysTid=8530 nice=0 cgrp=bg_non_interactive sched=0/0 handle=0x7f60d03440
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   | state=R schedstat=( 100964150 70105114 208 ) utm=9 stm=1 core=5 HZ=100
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   | stack=0x7f60c01000-0x7f60c03000 stackSize=1037KB
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   | held mutexes= "mutator lock"(shared held)
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #00 pc 000000000048a5b0  /system/lib64/libart.so (_ZN3art15DumpNativeStackERNSt3__113basic_ostreamIcNS0_11char_traitsIcEEEEiP12BacktraceMapPKcPNS_9ArtMethodEPv+200)
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #01 pc 0000000000459358  /system/lib64/libart.so (_ZNK3art6Thread4DumpERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEEP12BacktraceMap+224)
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #02 pc 000000000030d764  /system/lib64/libart.so (_ZN3art9JavaVMExt8JniAbortEPKcS2_+1004)
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #03 pc 000000000030e138  /system/lib64/libart.so (_ZN3art9JavaVMExt9JniAbortFEPKcS2_z+224)
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #04 pc 000000000045988c  /system/lib64/libart.so (_ZNK3art6Thread13DecodeJObjectEP8_jobject+548)
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #05 pc 0000000000351d3c  /system/lib64/libart.so (_ZN3art3JNI17GetStaticMethodIDEP7_JNIEnvP7_jclassPKcS6_+464)
    09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #06 pc 00000000001529c8  /system/lib64/libart.so (_ZN3art8CheckJNI17GetStaticMethodIDEP7_JNIEnvP7_jclassPKcS6_+560) 
    
    opened by NitroXenon 6
  • ZiplineScope

    ZiplineScope

    It’s difficult bookkeeping to call ZiplineService.close() all the places it’s necessary to.

    Flow<T> is even worse. I’ve found a case where a Flow is never collected, and that causes it to leak. (We currently close flows after the first collect() completes; this is painful for both never collecting and also multiple collecting).

    I propose the following API:

    /**
     * Closes [ziplineService] when this scope completes (either through success,
     * failure, or cancelation). This will also attach all services returned from
     * [ziplineService] to this scope.
     *
     * This requires that [ziplineService] is a bridged proxy, either via
     * [Zipline.take], as a called function’s return value, or an implemented
     * function’s parameter value.
     */
    fun CoroutineScope.attach(ziplineService: ZiplineService) {
      ...
    }
    

    One place this falls short is Flow<T>, which isn’t a ZiplineService. Worse, it’s difficult to get the ZiplineService from a Flow<T>.

    We could do magic for inbound calls:

    /**
     * Attaches all inbound services to this scope, so they will be closed
     * when this scope completes. Attached services will either be parameters
     * to this function, or properties of the parameters to this function.
     * 
     * This must be called in the body of a ZiplineService function.
     */
    fun CoroutineScope.attachZiplineInboundCall() {
      ...
    }
    

    There’s a lot of room to experiment with syntax here, and I’m not particularly attached to the proposals above. But I do think there’s something handy to linking ZiplineService.close() to a coroutine scope.

    opened by swankjesse 5
  • Kotlin/Native compiler crashes, ‘Expecting descriptor for SuspendCallback.Companion.Adapter’

    Kotlin/Native compiler crashes, ‘Expecting descriptor for SuspendCallback.Companion.Adapter’

    I’ve been puzzling over this crash for almost 24 hours...

    Problem: Generated Code Can’t Reliably See Generated Declarations in Kotlin/Native

    When generated code in one module refers to generated code in another module, that can cause exceptions when deserializing the two modules together.

    java.lang.IllegalStateException: Expecting descriptor for app.cash.zipline.internal.bridge/SuspendCallback.Companion.Adapter|null[0])
    18:28:11 e: java.lang.IllegalStateException: Expecting descriptor for app.cash.zipline.internal.bridge/SuspendCallback.Companion.Adapter|null[0]
    18:28:11 	at org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker$KonanCachedLibraryModuleDeserializer.tryDeserializeIrSymbol(KonanIrlinker.kt:644)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.BasicIrModuleDeserializer.deserializeIrSymbol(BasicIrModuleDeserializer.kt:111)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.FileDeserializationState$symbolDeserializer$3.invoke(IrFileDeserializer.kt:88)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.FileDeserializationState$symbolDeserializer$3.invoke(IrFileDeserializer.kt:77)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrSymbolDeserializer.deserializeIrSymbolData(IrSymbolDeserializer.kt:67)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrSymbolDeserializer.deserializeIrSymbol(IrSymbolDeserializer.kt:84)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeIrSymbolAndRemap$ir_serialization_common(IrDeclarationDeserializer.kt:211)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeSimpleType(IrDeclarationDeserializer.kt:122)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeIrTypeData(IrDeclarationDeserializer.kt:181)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeIrType(IrDeclarationDeserializer.kt:97)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeIrVariable(IrDeclarationDeserializer.kt:622)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeDeclaration(IrDeclarationDeserializer.kt:791)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeDeclaration$default(IrDeclarationDeserializer.kt:782)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrBodyDeserializer.deserializeStatement$ir_serialization_common(IrBodyDeserializer.kt:136)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrBodyDeserializer.deserializeBlockBody(IrBodyDeserializer.kt:95)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrBodyDeserializer.deserializeStatement$ir_serialization_common(IrBodyDeserializer.kt:130)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeStatementBody(IrDeclarationDeserializer.kt:547)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer$withDeserializedIrFunctionBase$1$1$1$1.invoke(IrDeclarationDeserializer.kt:575)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer$withDeserializedIrFunctionBase$1$1$1$1.invoke(IrDeclarationDeserializer.kt:564)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.withBodyGuard(IrDeclarationDeserializer.kt:509)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.access$withBodyGuard(IrDeclarationDeserializer.kt:64)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeIrFunction$ir_serialization_common(IrDeclarationDeserializer.kt:1099)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeDeclaration(IrDeclarationDeserializer.kt:788)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeDeclaration$default(IrDeclarationDeserializer.kt:782)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeIrClass(IrDeclarationDeserializer.kt:375)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeDeclaration(IrDeclarationDeserializer.kt:787)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeDeclaration$default(IrDeclarationDeserializer.kt:782)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeIrClass(IrDeclarationDeserializer.kt:375)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeDeclaration(IrDeclarationDeserializer.kt:787)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeDeclaration$default(IrDeclarationDeserializer.kt:782)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeIrClass(IrDeclarationDeserializer.kt:375)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeDeclaration(IrDeclarationDeserializer.kt:787)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer.deserializeDeclaration$default(IrDeclarationDeserializer.kt:782)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.IrFileDeserializer.deserializeDeclaration(IrFileDeserializer.kt:40)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.FileDeserializationState.deserializeAllFileReachableTopLevel(IrFileDeserializer.kt:135)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.BasicIrModuleDeserializer$ModuleDeserializationState.deserializeReachableDeclarations(BasicIrModuleDeserializer.kt:190)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.BasicIrModuleDeserializer.deserializeReachableDeclarations(BasicIrModuleDeserializer.kt:158)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.deserializeAllReachableTopLevels(KotlinIrLinker.kt:111)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.findDeserializedDeclarationForSymbol(KotlinIrLinker.kt:129)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.deserializeOrResolveDeclaration(KotlinIrLinker.kt:169)
    18:28:11 	at org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.getDeclaration(KotlinIrLinker.kt:158)
    18:28:11 	at org.jetbrains.kotlin.ir.util.ExternalDependenciesGeneratorKt.getDeclaration(ExternalDependenciesGenerator.kt:57)
    18:28:11 	at org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator.generateUnboundSymbolsAsDependencies(ExternalDependenciesGenerator.kt:44)
    18:28:11 	at org.jetbrains.kotlin.psi2ir.generators.ModuleGenerator.generateUnboundSymbolsAsDependencies(ModuleGenerator.kt:52)
    18:28:11 	at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment(Psi2IrTranslator.kt:92)
    18:28:11 	at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment$default(Psi2IrTranslator.kt:75)
    18:28:11 	at org.jetbrains.kotlin.backend.konan.PsiToIrKt.psiToIr(PsiToIr.kt:187)
    18:28:11 	at org.jetbrains.kotlin.backend.konan.ToplevelPhasesKt$psiToIrPhase$1.invoke(ToplevelPhases.kt:120)
    18:28:11 	at org.jetbrains.kotlin.backend.konan.ToplevelPhasesKt$psiToIrPhase$1.invoke(ToplevelPhases.kt:118)
    18:28:11 	at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$namedOpUnitPhase$1.invoke(PhaseBuilders.kt:96)
    18:28:11 	at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$namedOpUnitPhase$1.invoke(PhaseBuilders.kt:94)
    18:28:11 	at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96)
    18:28:11 	at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:29)
    18:28:11 	at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96)
    18:28:11 	at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:43)
    18:28:11 	at org.jetbrains.kotlin.backend.konan.KonanDriverKt.runTopLevelPhases(KonanDriver.kt:40)
    18:28:11 	at org.jetbrains.kotlin.cli.bc.K2Native.doExecute(K2Native.kt:94)
    18:28:11 	at org.jetbrains.kotlin.cli.bc.K2Native.doExecute(K2Native.kt:37)
    18:28:11 	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:99)
    18:28:11 	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:47)
    18:28:11 	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
    18:28:11 	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:79)
    18:28:11 	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:43)
    18:28:11 	at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit(CLITool.kt:179)
    18:28:11 	at org.jetbrains.kotlin.cli.bc.K2Native$Companion$mainNoExitWithGradleRenderer$1.invoke(K2Native.kt:412)
    18:28:11 	at org.jetbrains.kotlin.cli.bc.K2Native$Companion$mainNoExitWithGradleRenderer$1.invoke(K2Native.kt:411)
    18:28:11 	at org.jetbrains.kotlin.util.UtilKt.profileIf(Util.kt:22)
    18:28:11 	at org.jetbrains.kotlin.util.UtilKt.profile(Util.kt:16)
    18:28:11 	at org.jetbrains.kotlin.cli.bc.K2Native$Companion.mainNoExitWithGradleRenderer(K2Native.kt:411)
    18:28:11 	at org.jetbrains.kotlin.cli.bc.K2NativeKt.mainNoExitWithGradleRenderer(K2Native.kt:666)
    18:28:11 	at org.jetbrains.kotlin.cli.utilities.MainKt$daemonMain$1$1.invoke(main.kt:70)
    18:28:11 	at org.jetbrains.kotlin.cli.utilities.MainKt$daemonMain$1$1.invoke(main.kt:70)
    18:28:11 	at org.jetbrains.kotlin.cli.utilities.MainKt.mainImpl(main.kt:19)
    18:28:11 	at org.jetbrains.kotlin.cli.utilities.MainKt.daemonMain(main.kt:70)
    18:28:11 	at jdk.internal.reflect.GeneratedMethodAccessor492.invoke(Unknown Source)
    18:28:11 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    18:28:11 	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    18:28:11 	at org.jetbrains.kotlin.compilerRunner.KotlinToolRunner.runInProcess(KotlinToolRunner.kt:140)
    18:28:11 	at org.jetbrains.kotlin.compilerRunner.KotlinToolRunner.run(KotlinToolRunner.kt:82)
    18:28:11 	at org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink.compile(KotlinNativeTasks.kt:660)
    18:28:11 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    18:28:11 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    18:28:11 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    18:28:11 	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    18:28:11 	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:104)
    18:28:11 	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:58)
    18:28:11 	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51)
    18:28:11 	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29)
    18:28:11 	at org.gradle.api.internal.tasks.execution.TaskExecution$3.run(TaskExecution.java:242)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)
    18:28:11 	at org.gradle.api.internal.tasks.execution.TaskExecution.executeAction(TaskExecution.java:227)
    18:28:11 	at org.gradle.api.internal.tasks.execution.TaskExecution.executeActions(TaskExecution.java:210)
    18:28:11 	at org.gradle.api.internal.tasks.execution.TaskExecution.executeWithPreviousOutputFiles(TaskExecution.java:193)
    18:28:11 	at org.gradle.api.internal.tasks.execution.TaskExecution.execute(TaskExecution.java:171)
    18:28:11 	at org.gradle.internal.execution.steps.ExecuteStep.executeInternal(ExecuteStep.java:89)
    18:28:11 	at org.gradle.internal.execution.steps.ExecuteStep.access$000(ExecuteStep.java:40)
    18:28:11 	at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:53)
    18:28:11 	at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:50)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
    18:28:11 	at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:50)
    18:28:11 	at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:40)
    18:28:11 	at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:68)
    18:28:11 	at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:38)
    18:28:11 	at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:48)
    18:28:11 	at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:36)
    18:28:11 	at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:41)
    18:28:11 	at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:74)
    18:28:11 	at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:55)
    18:28:11 	at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:51)
    18:28:11 	at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:29)
    18:28:11 	at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:61)
    18:28:11 	at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:42)
    18:28:11 	at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:60)
    18:28:11 	at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:27)
    18:28:11 	at org.gradle.internal.execution.steps.BuildCacheStep.executeWithoutCache(BuildCacheStep.java:180)
    18:28:11 	at org.gradle.internal.execution.steps.BuildCacheStep.lambda$execute$1(BuildCacheStep.java:75)
    18:28:11 	at org.gradle.internal.Either$Right.fold(Either.java:175)
    18:28:11 	at org.gradle.internal.execution.caching.CachingState.fold(CachingState.java:59)
    18:28:11 	at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:73)
    18:28:11 	at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:48)
    18:28:11 	at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:36)
    18:28:11 	at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:25)
    18:28:11 	at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:36)
    18:28:11 	at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:22)
    18:28:11 	at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:110)
    18:28:11 	at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$2(SkipUpToDateStep.java:56)
    18:28:11 	at java.base/java.util.Optional.orElseGet(Optional.java:369)
    18:28:11 	at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:56)
    18:28:11 	at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:38)
    18:28:11 	at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:73)
    18:28:11 	at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:44)
    18:28:11 	at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:37)
    18:28:11 	at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:27)
    18:28:11 	at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:89)
    18:28:11 	at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:50)
    18:28:11 	at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:114)
    18:28:11 	at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:57)
    18:28:11 	at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:76)
    18:28:11 	at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:50)
    18:28:11 	at org.gradle.internal.execution.steps.SkipEmptyWorkStep.executeWithNoEmptySources(SkipEmptyWorkStep.java:249)
    18:28:11 	at org.gradle.internal.execution.steps.SkipEmptyWorkStep.executeWithNoEmptySources(SkipEmptyWorkStep.java:204)
    18:28:11 	at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:83)
    18:28:11 	at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:54)
    18:28:11 	at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:32)
    18:28:11 	at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:21)
    18:28:11 	at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38)
    18:28:11 	at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:43)
    18:28:11 	at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:31)
    18:28:11 	at org.gradle.internal.execution.steps.AssignWorkspaceStep.lambda$execute$0(AssignWorkspaceStep.java:40)
    18:28:11 	at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:287)
    18:28:11 	at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:40)
    18:28:11 	at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:30)
    18:28:11 	at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:37)
    18:28:11 	at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:27)
    18:28:11 	at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:44)
    18:28:11 	at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:33)
    18:28:11 	at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:76)
    18:28:11 	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:144)
    18:28:11 	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:133)
    18:28:11 	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:77)
    18:28:11 	at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
    18:28:11 	at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
    18:28:11 	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
    18:28:11 	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
    18:28:11 	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
    18:28:11 	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
    18:28:11 	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
    18:28:11 	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
    18:28:11 	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
    18:28:11 	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
    18:28:11 	at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:74)
    18:28:11 	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:333)
    18:28:11 	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:320)
    18:28:11 	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:313)
    18:28:11 	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:299)
    18:28:11 	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:143)
    18:28:11 	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:227)
    18:28:11 	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:218)
    18:28:11 	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:140)
    18:28:11 	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    18:28:11 	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    18:28:11 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    18:28:11 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    18:28:11 	at java.base/java.lang.Thread.run(Thread.java:834)
    

    Exploration of the cause

    I’ve learned that the Kotlin/Native compiler is working against us somewhat. Here’s what it does:

    1. Reads source code in as a PSI model.
    2. Converts it to an IR model
    3. Runs transforms on the IR model
    4. Emits mostly all IR, but some symbols still as the original PSI

    To confirm this, set these breakpoints:

    1. LazyClassDescriptor.init(), to capture the compilation of SuspendCallback. (Breakpoint condition is name.asString().contains("Callback").)
    2. ZiplineIrGenerationExtension.generate(), to capture generating an adapter for SuspendCallback. (Breakpoint condition is "Callback" in declaration.name.asString())
    3. DescriptorSerializer.classProto() to capture serializing a Klib for SuspendCallback. (Breakpoint condition is "SuspendCallback" in classDescriptor.name.asString())

    Next, execute zipline:macosArm64Test in a debugger. This is easy enough to do in the Gradle sidebar.

    The breakpoints hit in the order above. On the first breakpoint, the unsubstitutedInnerClassesScope.invoke() function does not include a Companion member because it won’t be generated until breakpoint 2. That means the companion remains missing when serializing the Klib in step 3.

    This is a problem because our Kotlin compiler-generated code (the nested Companion and Adapter) refers to other generated code to lookup required serializers. But since the klib doesn’t include these declarations, compilation crashes with the exception above.

    Mitigation for Zipline

    Referring to generated code from generated code is super convenient! And losing that is very annoying for our model.

    But I think I can mitigate by looking up serializers with contextual serialization, rather than having them available statically. This will change generated code from emitting something like this:

    To emitting something like this:

      val adapter: MyService<String> = MyService.Companion.Adapter(String.serializer())
    

    to this:

      val adapter: MyService<String> = SerializersModule.requireContextual(MyService::class, String.serializer())
    

    We already do this for certain types, so it’s not a particularly big change. The biggest drawback is we’ll need to decide which adapters to preregister as available contextual ones. Hopefully not everything.

    engine/native 
    opened by swankjesse 5
  • Sample crashes with Flow serialization issue

    Sample crashes with Flow serialization issue

    I’m running the emoji search sample and it’s bitrotted.

    2022-08-15 12:46:38.358 6126-6151/com.example.zipline.emojisearch.debug E/Zipline: java.lang.Exception: SerializationException: Class 'ChannelFlowBuilder' is not registered for polymorphic serialization in the scope of 'Flow'.
        Mark the base class as 'sealed' or register the serializer explicitly.
            at captureStack (../../../../../runtime/coreRuntime.kt:86)
            at SerializationException_init_$Create$_0 (kotlinx-serialization-kotlinx-serialization-core-js-ir.js)
            at throwSubtypeNotRegistered_0 (../../../../../Z:/BuildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/internal/AbstractPolymorphicSerializer.kt:102)
            at throwSubtypeNotRegistered (../../../../../Z:/BuildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/internal/AbstractPolymorphicSerializer.kt:113)
            at findPolymorphicSerializer (../../../../../Z:/BuildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/PolymorphicSerializer.kt:109)
            at <anonymous> (../../../../../Z:/BuildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/internal/AbstractPolymorphicSerializer.kt:32)
            at <anonymous> (../../../../../Polymorphic.kt:89)
            at <anonymous> (../../../../../Z:/BuildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/encoding/AbstractEncoder.kt:80)
            at <anonymous> (../../../../../commonMainSources/libraries/stdlib/src/kotlin/util/Preconditions.kt:287)
            at <anonymous> (zipline-root-zipline.js)
            at <anonymous> (../../../../../Polymorphic.kt:89)
            at <anonymous> (../../../../../Z:/BuildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/encoding/AbstractEncoder.kt:80)
            at <anonymous> (../../../../../Z:/BuildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/encoding/Encoding.kt:287)
            at <anonymous> (zipline-root-zipline.js)
            at <anonymous> (../../../../../Polymorphic.kt:89)
            at encodeToDynamic_0 (../../../../../DynamicEncoders.kt:42)
            at encodeToDynamic (../../../../../Dynamics.kt)
            at encodeToStringFast (../../../../../jsonJs.kt)
            at <anonymous> (../../../../../CallCodec.kt:56)
            at <anonymous> (../../../../../OutboundCallHandler.kt:52)
            at <anonymous> (../../../../../SuspendCallback.kt)
            at <anonymous> (zipline-root-zipline.js)
            at <anonymous> (../../../../../InboundService.kt:713)
            at <anonymous> (../../../../../InboundService.kt)
            at l (zipline-root-zipline.js)
            at <anonymous> (../../../../../src/kotlin/coroutines_13/IntrinsicsJs.kt:163)
            at <anonymous> (../../../../../src/kotlin/coroutines_13/CoroutineImpl.kt:55)
            at <anonymous> (kotlin-kotlin-stdlib-js-ir.js)
            at <anonymous> (../../../../../DispatchedTask.kt:10131)
            at <anonymous> (../../../../../commonMainSources/libraries/stdlib/src/kotlin/util/Standard.kt:153)
            at <anonymous> (../../../../../JSDispatcher.kt:19)
            at apply (native)
            at <anonymous> (../../../../../GlobalBridge.kt:70)
            at <anonymous> (../../../../../platform.kt)
            at <anonymous> (zipline-root-zipline.js)
            at <anonymous> (../../../../../InboundService.kt:835)
            at <anonymous> (../../../../../Endpoint.kt:79)
            at <anonymous> (zipline-root-zipline.js)
            at <anonymous> (../../../../../GlobalBridge.kt)
            at <anonymous> (zipline-root-zipline.js)
            at app.cash.zipline.internal.JsPlatform$Companion$Adapter$GeneratedOutboundService.runJob(platform.kt:37)
            at app.cash.zipline.internal.CoroutineEventLoop$DelayedJob$run$1.invokeSuspend(CoroutineEventLoop.kt:59)
            at app.cash.zipline.internal.CoroutineEventLoop$DelayedJob$run$1.invoke(Unknown Source:8)
            at app.cash.zipline.internal.CoroutineEventLoop$DelayedJob$run$1.invoke(Unknown Source:4)
            at kotlinx.coroutines.intrinsics.UndispatchedKt.startCoroutineUndispatched(Undispatched.kt:55)
            at kotlinx.coroutines.BuildersKt__Builders_commonKt.startCoroutineImpl(Builders.common.kt:198)
            at kotlinx.coroutines.BuildersKt.startCoroutineImpl(Unknown Source:1)
            at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:134)
            at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
            at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
    2022-08-15 12:46:38.358 6126-6151/com.example.zipline.emojisearch.debug E/Zipline:     at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
            at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
            at app.cash.zipline.internal.CoroutineEventLoop$DelayedJob.run(CoroutineEventLoop.kt:57)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
            at java.lang.Thread.run(Thread.java:920)
    
    opened by swankjesse 5
  • SuspendCallbacks can leak

    SuspendCallbacks can leak

    I’ve got a Redwood application that creates and cancels flows, and in some situations I’ve got SuspendCallback objects that never get called back, and never get canceled. I suspect it’s a book-keeping issue with ZiplineScope, possibly exacerbated by our flows.

    I’m able to create this leak by creating and closing services. The leaked callback is tracked in Endpoint.inboundServices; here’s a sample.

    zipline/host-1029 -> {InboundService@56720} SuspendCallback/Call(receiver=zipline/js-865, function=suspend fun emit(T): kotlin.Unit, args=[HostConfiguration(darkMode=false)])
    
    opened by swankjesse 0
  • callSuspending() should’t force a suspend

    callSuspending() should’t force a suspend

    Right now InboundService always does a launch() and the caller always resumes asynchronously, even if there’s no blocking in the body of the service.

    We should attempt to return synchronously when that’s possible.

    On the API we’d change callSuspending to return either an encoded CancelCallback or the synchronous result.

    opened by swankjesse 0
  • Zipline incremental builds fail deserializing app.cash.zipline/Zipline.take

    Zipline incremental builds fail deserializing app.cash.zipline/Zipline.take

    I’ve seen incremental builds crash the compiler like this:

    > Task :zipline:compileKotlinJs FAILED
    e: Could not load module <app.cash.zipline:zipline> in an attempt to find deserializer for symbol app.cash.zipline/Zipline.take|-4455680448914447453[0].
    e: org.jetbrains.kotlin.ir.linkage.KotlinIrLinkerInternalException: Kotlin IR Linker exception
            at org.jetbrains.kotlin.backend.common.serialization.linkerissues.KotlinIrLinkerIssue.raiseIssue(KotlinIrLinkerIssues.kt:26)
            at org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.resolveModuleDeserializer(KotlinIrLinker.kt:95)
            at org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.findDeserializedDeclarationForSymbol(KotlinIrLinker.kt:125)
            at org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.deserializeOrResolveDeclaration(KotlinIrLinker.kt:169)
            at org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.getDeclaration(KotlinIrLinker.kt:158)
            at org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl.resolveSymbolCollection(IrPluginContextImpl.kt:93)
            at org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl.referenceFunctions(IrPluginContextImpl.kt:130)
            at app.cash.zipline.kotlin.ZiplineApis.rewritePair(ZiplineApis.kt:189)
            at app.cash.zipline.kotlin.ZiplineApis.<init>(ZiplineApis.kt:179)
            at app.cash.zipline.kotlin.ZiplineIrGenerationExtension.generate(ZiplineIrGenerationExtension.kt:35)
    

    We should find a fix. A workaround is to do a gradle clean.

    opened by swankjesse 0
  • Support for overloaded functions

    Support for overloaded functions

    I saw a crash without them:

    e: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering
    File being compiled: /data/app/kochiku-worker/shared/build-partition/squareup/cash-treehouse/treehouse/apis/flows/src/commonMain/kotlin/com/squareup/cash/treehouse/flows/FlowsApp.kt
    The root cause java.lang.RuntimeException was thrown at: org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:47)
    	at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:239)
    	at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:235)
    Caused by: java.lang.IllegalArgumentException: No argument for parameter VALUE_PARAMETER name:parameters index:2 type:@[Contextual] okio.ByteString?:
    CALL 'public open fun getScreen (path: kotlin.String, navigator: com.squareup.cash.treehouse.navigation.Navigator, parameters: @[Contextual] okio.ByteString?): app.cash.redwood.treehouse.ZiplineTreehouseUi
    
    bug 
    opened by swankjesse 1
Releases(0.9.13)
  • 0.9.13(Dec 22, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • New: ZiplineScope is a new mechanism to close pass-by-reference services and flows. Pass a ZiplineScope to Zipline.take() or implement ZiplineScoped in a ZiplineService to declare a scope, then call ZiplineScope.close() to close all received services. Note that Flows that were passed-by-reference previously needed to be collected exactly once; with this change Flows may be collected any number of times.
    • New: Configure the development HTTP server's local port in Gradle:
      zipline {
        ...
        httpServerPort.set(22364)
      }
      
    • New: Include the service name in ZiplineApiMismatchException.
    • Fix: Prevent .zipline files from being stored in the HTTP cache. We've added 'Cache-Control: no-store' request headers to downloads to prevent caching that's redundant with ZiplineLoader's cache.
    • Fix: Make ZiplineService.close() idempotent for outbound services.
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.13.zip(13.41 MB)
  • 0.9.12(Dec 6, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • New: Add ZiplineFunction.isSuspending.
    • New: Add events for ziplineCreate(), moduleLoadStart(), and moduleLoadEnd().
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.12.zip(13.40 MB)
  • 0.9.11(Dec 5, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • New: Publish an event when Zipline is closed.
    • Fix: Avoid a linear search through endpoint names.
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.11.zip(13.40 MB)
  • 0.9.10(Nov 30, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • New: Add support for var and val declarations in service interfaces.
    • Fix: Update Gradle task to serve zipline files for compatibility with Gradle 7.6.
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.10.zip(13.40 MB)
  • 0.9.9(Nov 17, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • Changed: Roll back Kotlin 1.7.20 to ensure downstream users can still use Compose easily. The plugin remains compatible with 1.7.21.
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.9.zip(13.36 MB)
  • 0.9.8(Nov 16, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • New: Support Kotlin 1.7.21.
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.8.zip(13.36 MB)
  • 0.9.7(Nov 11, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • Breaking: Change EventListener to pass the Zipline instance when it is available.
    • Breaking: Introduce EventListener.applicationLoadSkipped() when a downloaded manifest hasn't changed.
    • New: The development server (serveDevelopmentZipline) now notifies code changes via web socket. Connect to /ws to receive "reload" messages.
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.7.zip(13.32 MB)
  • 0.9.6(Oct 14, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • Fix: Don't fail with unexpected call errors because code was not being rewritten by our Kotlin compiler plugin.
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.6.zip(13.32 MB)
  • 0.9.5(Oct 6, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • New: Support @Contextual as a type annotation on ZiplineService parameters and return types. This will attempt to find a contextual serializer for the annotated type.
    • Breaking: Rename LoadedZipline to LoadResult. This allows ZiplineLoader.load() to return a flow that includes both successes and failures.
    • Breaking: Remove eval() support from QuickJs. As a security measure Zipline doesn't support evaluating JavaScript at runtime.
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.5.zip(13.31 MB)
  • 0.9.4(Sep 8, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • New: Build in a basic HTTP client for Apple platforms.
    • Breaking change: Wrap exceptions thrown in bridged calls with ZiplineException. Previously these were wrapped in Exception which was difficult to catch generically.
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.4.zip(13.31 MB)
  • 0.9.3(Aug 24, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • Breaking change: Move SerializersModule from a property of ZiplineLoader to a parameter in load() and loadOnce(). This enables using a single loader for different applications that have different serializers.
    • Breaking change: Make ZiplineCache a top-level type. It has its own lifecycle and is best managed directly.
    • Breaking change: Pass a startValue parameter consistently to event listener callbacks.
    • New: Extension OkHttpClient.asZiplineHttpClient() makes it easier to use general-purpose Zipline APIs from multiplatform code.
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.3.zip(13.30 MB)
  • 0.9.2(Aug 22, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • Breaking change: ZiplineLoader.load(...) is no longer suspending.
    • Breaking change: Don't require implementors of ZiplineHttpClient to implement URL resolution.
    • Breaking change: Include a default clock implementation on iOS.
    • Breaking change: Require callers to explicitly opt out of signature checks. Pass ManifestVerifier.Companion.NO_SIGNATURE_CHECKS to use ZiplineLoader without code signature verification.
    • New: Support ECDSA P-256 for signatures.
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.2.zip(13.30 MB)
  • 0.9.1(Aug 19, 2022)

    We've changed this project to focus exclusively on executing Kotlin/JS libraries.

    We plan to drop support for executing arbitrary JavaScript code. If you've been using either QuickJS Java (this project's name until September 2021) or Duktape Android (this project's name until June 2021), those projects remain as git branches but will not receive further updates.

    The project's new Maven coordinates are app.cash.zipline:zipline.

    • New: Gradle extension zipline {} block.
    • New: Compile files in parallel.
    • New: Replace webpack with a dedicated static file server. Use serveDevelopmentZipline or serveProductionZipline to serve an application locally.
    • Fix: Always run Kotlin/JS in strict mode.
    • Upgrade: [Kotlin Serialization 1.4.0][kotlin_serialization_1_4_0].
    Source code(tar.gz)
    Source code(zip)
    zipline-cli-0.9.1.zip(13.30 MB)
Owner
Cash App
Cash App
A Kotlin library providing a simple, high-performance way to use off-heap native memory in JVM applications.

native_memory_allocator A library which uses sun.misc.Unsafe to allocate off-heap native memory. Motivation The goal of this project is to provide a s

Target 5 Dec 8, 2022
🎑 Up to date IANA timezone database library for Kotlin (JVM, JS, Native)

?? IANA Timezone Library for Kotlin Multiplatform Up to date IANA timezone database library for Kotlin (JVM, JS, Native) Usage import org.noelware.ian

Noelware 3 Jun 18, 2022
Yet Another Native Loader for the JVM.

yanl - yet another native loader Yet another Native library extractor/loader for the JVM, written in Kotlin. why other libraries simply don't fit my n

Stardust Enterprises 5 Dec 23, 2022
:bouquet: An easy way to persist and run code block only as many times as necessary on Android.

Only ?? An easy way to persist and run code block only as many times as necessary on Android. Download Gradle Add below codes to your root build.gradl

Jaewoong Eum 479 Dec 25, 2022
:bouquet: An easy way to persist and run code block only as many times as necessary on Android.

Only ?? An easy way to persist and run code block only as many times as necessary on Android. Download Gradle Add below codes to your root build.gradl

Jaewoong Eum 468 Apr 14, 2021
Run shell commands from a Kotlin script or application with ease

Run shell commands from a Kotlin script or application with ease. Turtle simplifies the process of running external commands and processes from your K

Andrew Lord 187 Jan 9, 2023
Gradle plugin adding a task to run a Paper Minecraft server

Run Paper Run Paper is a Gradle plugin which adds a task to automatically download and run a Paper Minecraft server along with your plugin built by Gr

Jason 64 Dec 29, 2022
Run Minecraft on the command line

HeadlessForge While headless Minecraft Clients aren't anything new, they come with a drawback. The Minecraft API is missing and you need to add all fu

null 28 Oct 17, 2022
Actions are things that run, with parameters. Serves as a common dependency for a variety of Cepi extensions.

Actions Actions that take in customizable paramaters, an optional target, and do things. Installation Download the jar from Releases OR compile it you

Cepi 1 Jan 9, 2022
Android app with minimal UI to run snowflake pluggable transports proxy, based on library IPtProxy

Simple Kotlin app for testing IPtProxy's snowflake proxy on Android Essentially a button for starting and stopping a Snowflake Proxy with the default

null 2 Jun 26, 2022
Solid - A CLI that tries to cover a dry-run phase for liquibase database change management

solid a CLI that tries to cover a dry-run phase for liquibase database change ma

Giovanni Panice (mos_) 1 Jan 28, 2022
Create an application with Kotlin/JVM and Kotlin/JS, and explore features around code sharing, serialization, server- and client

Practical Kotlin Multiplatform on the Web 본 저장소는 코틀린 멀티플랫폼 기반 웹 프로그래밍 워크숍(강좌)을 위해 작성된 템플릿 프로젝트가 있는 곳입니다. 워크숍 과정에서 코틀린 멀티플랫폼을 기반으로 프론트엔드(front-end)는 Ko

SpringRunner 14 Nov 5, 2022
Create an application with Kotlin/JVM and Kotlin/JS, and explore features around code sharing, serialization, server- and client

Building a Full Stack Web App with Kotlin Multiplatform 본 저장소는 INFCON 2022에서 코틀린 멀티플랫폼 기반 웹 프로그래밍 핸즈온랩을 위해 작성된 템플릿 프로젝트가 있는 곳입니다. 핸즈온 과정에서 코틀린 멀티플랫폼을

Arawn Park 19 Sep 8, 2022
Android project setup files when developing apps from scratch. The codebase uses lates jetpack libraries and MVVM repository architecture for setting up high performance apps

Android architecture app Includes the following Android Respository architecture MVVM Jepack libraries Carousel view Kotlin Kotlin Flow and Livedata P

null 2 Mar 31, 2022
An awesome list that curates the best KMM libraries, tools and more.

Awesome KMM Kotlin Multiplatform Mobile (KMM) is an SDK designed to simplify creating cross-platform mobile applications. With the help of KMM, you ca

Konstantin 994 Dec 28, 2022
A personal project made using Jetpack Compose, Clean-MVVM architecture and other jetpack libraries

A basic CRUD for recording your personal credit and debit transactions. Made using Jetpack Compose, Clean-MVVM and other Jetpack libraries, incorporated with Unit Tests.

Shoaib Ahmed 3 Dec 6, 2022
Boilerplate code for implementing MVVM in Android using Jetpack libraries, coroutines, dependency injection and local persistance

MVVM Foundation This projects aims to speed up development of Android apps by providing a solid base to extend Libraries Jetpack Fragment Material3 :

Gabriel Gonzalez 2 Nov 10, 2022
🚟 Lightweight, and simple scheduling library made for Kotlin (JVM)

Haru ?? Lightweight, and simple scheduling library made for Kotlin (JVM) Why did you build this? I built this library as a personal usage library to h

Noel 13 Dec 16, 2022
Lightweight compiler plugin intended for Kotlin/JVM library development and symbol visibility control.

Restrikt A Kotlin/JVM compiler plugin to restrict symbols access, from external project sources. This plugin offers two ways to hide symbols: An autom

Lorris Creantor 18 Nov 24, 2022