Skip to content

Incorrect provideDelegate behavior in serial initializer #547

@SnailAfterRain

Description

@SnailAfterRain

Describe the bug
When you have properties that are provided with provideDelegate, backed delegate field is set to an instance of a class that has provideDelegate instead of a result of invoking this function.

To Reproduce

interface IField : IMessage

@Serializable
class SimpleField<T : Any>(val name: String, var value: T) : IField {
    operator fun getValue(t: Container, p: KProperty<*>): T { return value }
    operator fun setValue(t: Container, p: KProperty<*>, v: T) { value = v }
}

class FieldMapper<T : Any>(val default: T) {
    operator fun provideDelegate(
        container: Container,
        kProp: KProperty<*>
    ): SimpleField<T> {
        val name = kProp.name
        val value = default
        return container.properties.getOrPut(name) {
            SimpleField(name, value)
        } as SimpleField<T>
    }
}

@Serializable
open class Container() : IMessage {
    val properties: MutableMap<String, IField> = hashMapOf()

    inline fun <reified T : Any> field(default: T)
            = FieldMapper(default)
}


@Serializable
data class FooObject(val name: String) : Container() {
    val simpleIntField by field(123)
}

Expected behavior
Basically, after deserialization of FooObject, accessing simpleIntField field throws an error
this.simpleIntField_jgn9mv$_0.getValue_r0wl14$ is not a function

In produced JS code you can see differences between normal constructor

function FooObject(name) {
    FooObject$Companion_getInstance();
    Container.call(this);
    this.name = name;
    this.simpleIntField_jgn9mv$_0 = (new FieldMapper(123)).provideDelegate_r0wl14$(this, FooObject$simpleIntField_metadata);
  }

and generated serial constructor

  function FooObject_init(seen1, properties, name, serializationConstructorMarker) {
    var $this = serializationConstructorMarker || Object.create(FooObject.prototype);
    $this = Container_init(seen1, properties, $this);
    if ((seen1 & 2) === 0)
      throw new MissingFieldException('name');
    else
      $this.name = name;
    $this.simpleIntField_jgn9mv$_0 = new FieldMapper(123);
    return $this;
  }

Environment

  • Kotlin version: 1.3.50
  • Library version: 0.12.0
  • Kotlin platforms: JS
  • Gradle version: 4.8
  • IDE version IntellijIDEA 2019.2

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions