While trying to migrate KVision to Kotlin 2.0.0 I ...
# javascript
r
While trying to migrate KVision to Kotlin 2.0.0 I have strange runtime errors when dealing with some large data classes. See thread.
Copy code
ColumnDefinition.<init>' can not be called: No constructor found for symbol 'io.kvision.tabulator/ColumnDefinition.<init>|<init>(kotlin.String;kotlin.String?;kotlin.collections.List<io.kvision.tabulator.ColumnDefinition<1:0>>?;kotlin.Boolean?;io.kvision.tabulator.Align?;kotlin.String?;kotlin.Int?;kotlin.Int?;kotlin.Int?;<dynamic>;kotlin.Boolean?;kotlin.Int?;<dynamic>;kotlin.String?;kotlin.Boolean?;kotlin.Boolean?;io.kvision.tabulator.Sorter?;kotlin.Function7<kotlin.Nothing?,kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.RowComponent,io.kvision.tabulator.js.Tabulator.RowComponent,io.kvision.tabulator.js.Tabulator.ColumnComponent,io.kvision.tabulator.SortingDir,kotlin.Nothing?,kotlin.Number>?;<dynamic>;io.kvision.tabulator.Formatter?;kotlin.Function3<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Nothing?,kotlin.Function1<kotlin.Function0<kotlin.Unit>,kotlin.Unit>,<dynamic>>?;kotlin.Function3<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Function1<kotlin.Function0<kotlin.Unit>,kotlin.Unit>,1:0,io.kvision.core.Component>?;<dynamic>;kotlin.Boolean?;kotlin.Function1<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Boolean>?;io.kvision.tabulator.Editor?;kotlin.Function5<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Function1<kotlin.Function0<kotlin.Unit>,kotlin.Unit>,kotlin.Function1<kotlin.Nothing?,kotlin.Unit>,kotlin.Function1<kotlin.Nothing?,kotlin.Unit>,kotlin.Nothing?,<dynamic>>?;kotlin.Function5<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Function1<kotlin.Function0<kotlin.Unit>,kotlin.Unit>,kotlin.Function1<kotlin.Nothing?,kotlin.Unit>,kotlin.Function1<kotlin.Nothing?,kotlin.Unit>,1:0,io.kvision.core.Component>?;<dynamic>;io.kvision.tabulator.Validator?;<dynamic>;kotlin.String?;<dynamic>;kotlin.String?;io.kvision.tabulator.Calc?;<dynamic>;io.kvision.tabulator.Formatter?;<dynamic>;io.kvision.tabulator.Calc?;<dynamic>;io.kvision.tabulator.Formatter?;<dynamic>;kotlin.Boolean?;io.kvision.tabulator.SortingDir?;kotlin.Boolean?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.ColumnComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.ColumnComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.ColumnComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.ColumnComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.ColumnComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.ColumnComponent,kotlin.Unit>?;<dynamic>;kotlin.Boolean?;kotlin.Boolean?;io.kvision.tabulator.Formatter?;kotlin.Function3<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Nothing?,kotlin.Function1<kotlin.Function0<kotlin.Unit>,kotlin.Unit>,<dynamic>>?;kotlin.Function2<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Function1<kotlin.Function0<kotlin.Unit>,kotlin.Unit>,io.kvision.core.Component>?;<dynamic>;io.kvision.tabulator.Editor?;<dynamic>;kotlin.Function5<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Function1<kotlin.Function0<kotlin.Unit>,kotlin.Unit>,kotlin.Function1<kotlin.Nothing?,kotlin.Unit>,kotlin.Function1<kotlin.Nothing?,kotlin.Unit>,kotlin.Nothing?,<dynamic>>?;kotlin.String?;kotlin.Function1<kotlin.Any,kotlin.Boolean>?;io.kvision.tabulator.Filter?;kotlin.Function4<kotlin.Nothing?,kotlin.Nothing?,kotlin.Nothing?,kotlin.Nothing?,kotlin.Boolean>?;<dynamic>;kotlin.Boolean?;<dynamic>;<dynamic>;kotlin.Function3<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Nothing?,kotlin.Function1<kotlin.Function0<kotlin.Unit>,kotlin.Unit>,<dynamic>>?;<dynamic>;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function2<kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function1<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function1<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;kotlin.Function1<io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Unit>?;<dynamic>;<dynamic>;<dynamic>;io.kvision.tabulator.Align?;io.kvision.tabulator.VAlign?;<dynamic>;io.kvision.tabulator.Align?;<dynamic>;<dynamic>;kotlin.Int?;kotlin.Function5<kotlin.Nothing?,kotlin.Nothing?,kotlin.String,kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Any>?;<dynamic>;kotlin.Function5<kotlin.Nothing?,kotlin.Nothing?,kotlin.String,kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Any>?;<dynamic>;kotlin.Function5<kotlin.Nothing?,kotlin.Nothing?,kotlin.String,kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Any>?;<dynamic>;kotlin.Function5<kotlin.Nothing?,kotlin.Nothing?,kotlin.String,kotlin.Nothing?,io.kvision.tabulator.js.Tabulator.CellComponent,kotlin.Any>?;<dynamic>;kotlin.Int?;<dynamic>;<dynamic>;<dynamic>;<dynamic>;<dynamic>;<dynamic>;<dynamic>;kotlin.Boolean?;<dynamic>;<dynamic>;<dynamic>;<dynamic>;<dynamic>;<dynamic>;kotlin.Boolean?;kotlin.String?;kotlin.String?){}[0]'
or
Copy code
IrLinkageError: Constructor 'TabulatorOptions.<init>' can not be called: No constructor found for symbol 'io.kvision.tabulator/TabulatorOptions.<init>|<init>(kotlin.String?;kotlin.String?;kotlin.Function0<kotlin.String?>?;kotlin.String?;kotlin.String?;kotlin.Boolean?;<dynamic>;<dynamic>;io.kvision.tabulator.DownloadConfig?;kotlin.Boolean?;kotlin.Boolean?;kotlin.collections.List<io.kvision.tabulator.ColumnDefinition<1:0>>?;kotlin.Boolean?;kotlin.Boolean?;io.kvision.tabulator.Layout?;kotlin.Boolean?;io.kvision.tabulator.ResponsiveLayout?;kotlin.Boolean?;kotlin.Boolean?;kotlin.Boolean?;io.kvision.tabulator.ColumnPosition?;kotlin.Boolean?;kotlin.Function1<io.kvision.tabulator.js.Tabulator.RowComponent,kotlin.Unit>?;io.kvision.tabulator.RowPos?;<dynamic>;io.kvision.tabulator.RangeMode?;kotlin.Boolean?;kotlin.Boolean?;kotlin.Function1<io.kvision.tabulator.js.Tabulator.RowComponent,kotlin.Boolean>?;kotlin.Boolean?;<dynamic>;<dynamic>;<dynamic>;kotlin.Boolean?;io.kvision.tabulator.RowPosition?;kotlin.Boolean?;kotlin.String?;kotlin.Array<1:0>?;kotlin.String?;<dynamic>;<dynamic>;<dynamic>;kotlin.Function3<kotlin.String,kotlin.Nothing?,kotlin.Nothing?,kotlin.String>?;kotlin.Function3<kotlin.String,kotlin.Nothing?,kotlin.Nothing?,kotlin.js.Promise<kotlin.Any>>?;io.kvision.tabulator.ProgressiveMode?;kotlin.Int?;kotlin.Int?;kotlin.Boolean?;kotlin.String?;kotlin.String?;kotlin.collections.List<io.kvision.tabulator.js.Tabulator.Sorter>?;kotlin.Boolean?;kotlin.collections.List<io.kvision.tabulator.js.Tabulator.Filter>?;kotlin.collections.List<kotlin.Any?>?;kotlin.Boolean?;io.kvision.tabulator.PaginationMode?;kotlin.Int?;<dynamic>;<dynamic>;<dynamic>;<dynamic>;io.kvision.tabulator.AddRowMode?;kotlin.Int?;kotlin.String?;kotlin.Boolean?;kotlin.Boolean?;kotlin.Boolean?;kotlin.Boolean?;kotlin.String?;<dynamic>;kotlin.Function2<kotlin.String,kotlin.Nothing?,kotlin.Unit>?;kotlin.Boolean?;<dynamic>;kotlin.Boolean?;<dynamic>;kotlin.Boolean?;kotlin.Boolean?;kotlin.String?;kotlin.String?;kotlin.Function2<kotlin.Nothing?,kotlin.Nothing?,kotlin.Unit>?;<dynamic>;kotlin.Boolean?;kotlin.Boolean?;kotlin.String?;<dynamic>;<dynamic>;kotlin.String?;<dynamic>;kotlin.Number?;kotlin.Function2<io.kvision.tabulator.js.Tabulator.RowComponent,kotlin.Number,kotlin.Boolean>?;kotlin.Function2<kotlin.String,kotlin.Nothing?,kotlin.Boolean>?;kotlin.Function3<kotlin.String,kotlin.Nothing?,kotlin.Nothing?,kotlin.Any>?;<dynamic>;<dynamic>;<dynamic>;kotlin.Int?;io.kvision.tabulator.VAlign?;kotlin.String?;kotlin.String?;<dynamic>;kotlin.Boolean?;kotlin.Boolean?;kotlin.Int?;io.kvision.tabulator.TextDirection?;<dynamic>;<dynamic>;<dynamic>;kotlin.Boolean?;kotlin.Boolean?;io.kvision.tabulator.RenderType?;kotlin.Int?;io.kvision.tabulator.RenderType?;io.kvision.tabulator.ColumnDefinition<1:0>?;io.kvision.tabulator.SortMode?;io.kvision.tabulator.FilterMode?;io.kvision.tabulator.ImportFormat?;io.kvision.tabulator.ImportReader?;kotlin.Int?;<dynamic>;<dynamic>;<dynamic>;<dynamic>;<dynamic>;kotlin.Boolean?;kotlin.Int?;<dynamic>;kotlin.String?;io.kvision.tabulator.HeaderSortClickElement?;<dynamic>;<dynamic>;kotlin.Function1<kotlin.Array<<dynamic>>,org.w3c.dom.Element>?;<dynamic>;kotlin.Boolean?;kotlin.Boolean?;kotlin.Boolean?;kotlin.String?;io.kvision.tabulator.EditTriggerEvent?;<dynamic>;kotlin.Boolean?;kotlin.Int?;kotlin.Int?;<dynamic>;<dynamic>;kotlin.Boolean?;<dynamic>;kotlin.Boolean?;kotlin.Boolean?;kotlin.Boolean?;<dynamic>;kotlin.Function1<<dynamic>,kotlin.Boolean>?){}[0]'
The compilation doesn't give any warnings or errors, but the application fails at runtime (including tests).
t
Will it work if use
Any?
instead of
dynamic
?
r
I've managed to identify the problem - any property of a function type with dynamic parameter.
e.g.
val ajaxURLGenerator: ((url: String, config: dynamic, params: dynamic) -> String)? = null
replacing this
dynamic
with
Any?
fixes the issue
t
Cool! :)
r
Not cool ๐Ÿ™‚
I need those dynamics ๐Ÿ™‚
t
In common case it's your internal details
r
In my case it's a public api of KVision components.
t
Any?
works fine in most cases :)
r
The important question - is it Kotlin/JS bug? Or just a feature of K2 I need to live with.
t
Will you create issue?
r
I've tried to create a simplified reproducer, but failed to do this. It works fine in simple scenarios.
But it doesn't work in KVision and I don't know why.
I've replaced all
dynamic
parameters with
Any?
and both the library and the app work. But before I had
val cellClick: ((e: dynamic, cell: Tabulator.CellComponent) -> Unit)? = null
and I could easily use it like this:
Copy code
cellClick = { evt: Event, cell ->
    evt.preventDefault()
}
When changing to
e:  Any?
I can't do this anymore.
t
Easily = unsafe
r
That's what
dynamic
is for ๐Ÿ˜‰
t
That's what doesn't work :)
r
I think I need to fill an issue giving KVision branch as a reproducer ๐Ÿ™‚
t
Your example looks like example of invalid call
In fact you changed parameter type
And it's illegal
r
with 1.9 it works fine without even a single warning from the compiler or IDE
t
New compiler works better :)
Missed warning is problem
But type processing is fine
r
No. New compiler doesn't work better. It works the same way: https://pl.kotl.in/svMiZo8rm
It tries to work "better" only in KVision. And that's a bug in my opinion.
t
Robert, Current behavior of Kotlin in case of dynamic parameters in lambdas - bug You can abuse current behavior, but you must be ready for such problems which you have and for possible fix in future
r
I'll probably go with
Any?
, because I don't have much hope for a quick fix without a simple reproducer. I'll have a major release anyway, so I can live with "small" breaking changes ๐Ÿ˜‰
๐Ÿ‘ 1
๐ŸŽ‰ 1
K 1
a
@Robert Jaros, did you report this issue to Kotlin team?
r
No I didn't. I can't create a simple reproducer. Do you think it's worth reporting anyway?
a
@Robert Jaros, of course. Moreover, Victor confirmed that this is a bug, so please create an issue on YouTrack to Kotlin team
t
Good practice in common - don't use
dynamic
in parameters and properties. We will add issue in FAQ as additional argument ๐Ÿ˜œ
๐Ÿ‘ 1
a
True, if itโ€™s your responsibility, then using `dynamic`โ€™s looks weird, you should avoid them. But in the case of third-parties, when you canโ€™t influence the library author, or itโ€™s probably deprecated/not updated, then K2 should not break existing code. Thank you for the report!
e
dynamic
should still work perfectly, it's an integral part of the JS interop
AFAIR there is
dynamic
usage in the stdlib too, but I think it's not yet compiled with K2