Description
Description
Certain patterns in a Serializable
class will cause code to be compiled incorrectly for JS. While the class will appear to function normally when used from code, instances produced by deserialization will be broken.
To Reproduce
Given a class:
package sample
import kotlinx.serialization.Serializable
@Serializable
data class Model(
val abc: String?,
) {
val xyz = abc?.let { xyz -> "$xyz..." }
}
This test will fail when run on JS:
package sample
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.put
import kotlin.test.Test
import kotlin.test.assertEquals
class FailingTest {
@Test
fun fail() {
val jsonObject = buildJsonObject {
put("abc", "hello")
}
val model = Json.decodeFromJsonElement<Model>(jsonObject)
assertEquals("hello", model.abc)
assertEquals("hello...", model.xyz)
}
}
The test fails at the access of xyz
:
AssertionError: Expected <hello...>, actual <undefined...>.
at DefaultJsAsserter.protoOf.assertTrue_rpw5fg(/.../serialization-bug-sample/build/compileSync/js/test/testDevelopmentExecutable/kotlin/jsMainSources/kotlin/kotlin/test/JsImpl.kt:23)
at DefaultJsAsserter.assertEquals(/.../serialization-bug-sample/build/compileSync/js/test/testDevelopmentExecutable/kotlin/commonMainSources/kotlin/kotlin/test/Assertions.kt:671)
at DefaultJsAsserter.protoOf.assertEquals_ldumo(/.../serialization-bug-sample/build/compileSync/js/test/testDevelopmentExecutable/kotlin/jsMainSources/kotlin/kotlin/test/DefaultJsAsserter.kt:27)
at <global>.assertEquals(/.../serialization-bug-sample/build/compileSync/js/test/testDevelopmentExecutable/kotlin/commonMainSources/kotlin/kotlin/test/Assertions.kt:63)
at FailingTest.protoOf.fail_x6634e(/.../serialization-bug-sample/src/commonTest/kotlin/sample/FailingTest.kt:32)
at <global>.fn(kotlin/microgram-serialization-bug-sample-test.js:256)
at Context.<anonymous>(/.../build/js/packages_imported/kotlin-test-js-runner/src/KotlinTestTeamCityConsoleAdapter.ts:70)
at <global>.processImmediate(node:internal/timers:466)
Other Eamples
In a lazy:
@Serializable
data class Model(
val abc: String?,
) {
val xyz = lazy {
abc?.let { xyz -> "$xyz..." }
}
}
This will cause a stack overflow upon access:
RangeError: Maximum call stack size exceeded
at bitMaskWith (/.../serialization-bug-sample/build/compileSync/js/test/testDevelopmentExecutable/kotlin/js-ir/runtime/BitMask.kt:10:9)
at implement (/.../serialization-bug-sample/build/compileSync/js/test/testDevelopmentExecutable/kotlin/js-ir/runtime/BitMask.kt:53:45)
at getInterfaceMaskFor (/.../serialization-bug-sample/build/compileSync/js/test/testDevelopmentExecutable/kotlin/js-ir/runtime/reflectRuntime.kt:39:22)
at getPropertyCallableRef (/.../serialization-bug-sample/build/compileSync/js/test/testDevelopmentExecutable/kotlin/src/jsMainSources/libraries/stdlib/js/src/kotlin/dynamic.kt:18:56)
at xyz$factory (kotlin/microgram-serialization-bug-sample.js:254:12)
at Model.protoOf.get_xyz_18is40_k$ (/.../serialization-bug-sample/build/compileSync/js/test/testDevelopmentExecutable/kotlin/src/kotlin/util/Lazy.kt:4:1)
at /.../serialization-bug-sample/src/commonMain/kotlin/sample/Model.kt:5:1
at UnsafeLazyImpl.protoOf.get_value_j01efc_k$ (/.../serialization-bug-sample/build/compileSync/js/test/testDevelopmentExecutable/kotlin/src/kotlin/util/Lazy.kt:81:26)
at Model.protoOf.get_xyz_18is40_k$ (/.../serialization-bug-sample/build/compileSync/js/test/testDevelopmentExecutable/kotlin/src/kotlin/util/Lazy.kt:44:93)
...
Note the failure for such a test is not actually visible in the output report when running with Gradle, because of:
org.gradle.api.GradleException: Cannot process output: too long teamcity service message (more than 1Mb). Event was lost.
Build failed to prevent inconsistent behaviour. To ignore it use Gradle property 'kotlin.ignore.tcsm.overflow=true'
at org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessageOutputStreamHandler.overflow(TCServiceMessageOutputStreamHandler.kt:98)
at org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessageOutputStreamHandler.write(TCServiceMessageOutputStreamHandler.kt:64)
at org.gradle.process.internal.streams.ExecOutputHandleRunner.writeBuffer(ExecOutputHandleRunner.java:97)
at org.gradle.process.internal.streams.ExecOutputHandleRunner.lambda$forwardContent$0(ExecOutputHandleRunner.java:81)
at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:70)
at org.gradle.process.internal.streams.ExecOutputHandleRunner.forwardContent(ExecOutputHandleRunner.java:80)
at org.gradle.process.internal.streams.ExecOutputHandleRunner.run(ExecOutputHandleRunner.java:64)
at CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at 1.run(AbstractManagedExecutor.java:47)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:840)
Expected behavior
The test should pass. More specifically, the reference to the local parameter xyz
should not refer to the class's xyz
property in the compiled code. When the local parameter name xyz
is renamed to something else, the test passes as expected.
Environment
- Kotlin version: 1.9.21
- Library version: 1.6.2
- Kotlin platforms: JS
- Gradle version: 8.3
Rudimentary Analysis
This is the compiled code for the broken case (original example at the top):
Compiled Code
(function (root, factory) {
if (typeof define === 'function' && define.amd)
define(['exports', './kotlin-kotlin-stdlib.js', './kotlinx-serialization-kotlinx-serialization-core.js'], factory);
else if (typeof exports === 'object')
factory(module.exports, require('./kotlin-kotlin-stdlib.js'), require('./kotlinx-serialization-kotlinx-serialization-core.js'));
else {
if (typeof this['kotlin-kotlin-stdlib'] === 'undefined') {
throw new Error("Error loading module 'com.sample:serialization-bug-sample'. Its dependency 'kotlin-kotlin-stdlib' was not found. Please, check whether 'kotlin-kotlin-stdlib' is loaded prior to 'com.sample:serialization-bug-sample'.");
}
if (typeof this['kotlinx-serialization-kotlinx-serialization-core'] === 'undefined') {
throw new Error("Error loading module 'com.sample:serialization-bug-sample'. Its dependency 'kotlinx-serialization-kotlinx-serialization-core' was not found. Please, check whether 'kotlinx-serialization-kotlinx-serialization-core' is loaded prior to 'com.sample:serialization-bug-sample'.");
}
root['com.sample:serialization-bug-sample'] = factory(typeof this['com.sample:serialization-bug-sample'] === 'undefined' ? {} : this['com.sample:serialization-bug-sample'], this['kotlin-kotlin-stdlib'], this['kotlinx-serialization-kotlinx-serialization-core']);
}
}(this, function (_, kotlin_kotlin, kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core) {
'use strict';
//region block: imports
var protoOf = kotlin_kotlin.$_$.x5;
var objectMeta = kotlin_kotlin.$_$.w5;
var setMetadataFor = kotlin_kotlin.$_$.y5;
var PluginGeneratedSerialDescriptor = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.l;
var StringSerializer_getInstance = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.b;
var get_nullable = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.c;
var UnknownFieldException_init_$Create$ = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.a;
var THROW_CCE = kotlin_kotlin.$_$.q6;
var typeParametersSerializers = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.i;
var GeneratedSerializer = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.j;
var VOID = kotlin_kotlin.$_$.d;
var throwMissingFieldException = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.m;
var objectCreate = kotlin_kotlin.$_$.v5;
var getStringHashCode = kotlin_kotlin.$_$.f5;
var classMeta = kotlin_kotlin.$_$.b5;
//endregion
//region block: pre-declaration
setMetadataFor(Companion, 'Companion', objectMeta);
setMetadataFor($serializer, '$serializer', objectMeta, VOID, [GeneratedSerializer]);
setMetadataFor(Model, 'Model', classMeta, VOID, VOID, VOID, VOID, {0: $serializer_getInstance});
//endregion
function Companion() {
Companion_instance = this;
}
protoOf(Companion).serializer_9w0wvi_k$ = function () {
return $serializer_getInstance();
};
var Companion_instance;
function Companion_getInstance() {
if (Companion_instance == null)
new Companion();
return Companion_instance;
}
function $serializer() {
$serializer_instance = this;
var tmp0_serialDesc = new PluginGeneratedSerialDescriptor('sample.Model', this, 2);
tmp0_serialDesc.addElement_5pzumi_k$('abc', false);
tmp0_serialDesc.addElement_5pzumi_k$('xyz', true);
this.descriptor_1 = tmp0_serialDesc;
}
protoOf($serializer).get_descriptor_wjt6a0_k$ = function () {
return this.descriptor_1;
};
protoOf($serializer).childSerializers_5ghqw5_k$ = function () {
// Inline function 'kotlin.arrayOf' call
// Inline function 'kotlin.js.unsafeCast' call
// Inline function 'kotlin.js.asDynamic' call
return [get_nullable(StringSerializer_getInstance()), get_nullable(StringSerializer_getInstance())];
};
protoOf($serializer).deserialize_sy6x50_k$ = function (decoder) {
var tmp0_desc = this.descriptor_1;
var tmp1_flag = true;
var tmp2_index = 0;
var tmp3_bitMask0 = 0;
var tmp4_local0 = null;
var tmp5_local1 = null;
var tmp6_input = decoder.beginStructure_yljocp_k$(tmp0_desc);
if (tmp6_input.decodeSequentially_xlblqy_k$()) {
tmp4_local0 = tmp6_input.decodeNullableSerializableElement_k2y6ab_k$(tmp0_desc, 0, StringSerializer_getInstance(), tmp4_local0);
tmp3_bitMask0 = tmp3_bitMask0 | 1;
tmp5_local1 = tmp6_input.decodeNullableSerializableElement_k2y6ab_k$(tmp0_desc, 1, StringSerializer_getInstance(), tmp5_local1);
tmp3_bitMask0 = tmp3_bitMask0 | 2;
} else
while (tmp1_flag) {
tmp2_index = tmp6_input.decodeElementIndex_bstkhp_k$(tmp0_desc);
switch (tmp2_index) {
case -1:
tmp1_flag = false;
break;
case 0:
tmp4_local0 = tmp6_input.decodeNullableSerializableElement_k2y6ab_k$(tmp0_desc, 0, StringSerializer_getInstance(), tmp4_local0);
tmp3_bitMask0 = tmp3_bitMask0 | 1;
break;
case 1:
tmp5_local1 = tmp6_input.decodeNullableSerializableElement_k2y6ab_k$(tmp0_desc, 1, StringSerializer_getInstance(), tmp5_local1);
tmp3_bitMask0 = tmp3_bitMask0 | 2;
break;
default:
throw UnknownFieldException_init_$Create$(tmp2_index);
}
}
tmp6_input.endStructure_1xqz0n_k$(tmp0_desc);
return Model_init_$Create$(tmp3_bitMask0, tmp4_local0, tmp5_local1, null);
};
protoOf($serializer).serialize_n60lb7_k$ = function (encoder, value) {
var tmp0_desc = this.descriptor_1;
var tmp1_output = encoder.beginStructure_yljocp_k$(tmp0_desc);
tmp1_output.encodeNullableSerializableElement_5lquiv_k$(tmp0_desc, 0, StringSerializer_getInstance(), value.abc_1);
var tmp;
if (tmp1_output.shouldEncodeElementDefault_x8eyid_k$(tmp0_desc, 1)) {
tmp = true;
} else {
var tmp_0;
if (value.abc_1 == null) {
tmp_0 = null;
} else {
// Inline function 'kotlin.let' call
// Inline function 'kotlin.contracts.contract' call
// Inline function 'sample.$serializer.serialize.<anonymous>' call
tmp_0 = '' + value.xyz_1 + '...';
}
tmp = !(value.xyz_1 == tmp_0);
}
if (tmp) {
tmp1_output.encodeNullableSerializableElement_5lquiv_k$(tmp0_desc, 1, StringSerializer_getInstance(), value.xyz_1);
}
tmp1_output.endStructure_1xqz0n_k$(tmp0_desc);
};
protoOf($serializer).serialize_5ase3y_k$ = function (encoder, value) {
return this.serialize_n60lb7_k$(encoder, value instanceof Model ? value : THROW_CCE());
};
var $serializer_instance;
function $serializer_getInstance() {
if ($serializer_instance == null)
new $serializer();
return $serializer_instance;
}
function Model_init_$Init$(seen1, abc, xyz, serializationConstructorMarker, $this) {
if (!(1 === (1 & seen1))) {
throwMissingFieldException(seen1, 1, $serializer_getInstance().descriptor_1);
}
$this.abc_1 = abc;
if (0 === (seen1 & 2)) {
var tmp = $this;
var tmp_0;
if ($this.abc_1 == null) {
tmp_0 = null;
} else {
// Inline function 'kotlin.let' call
// Inline function 'kotlin.contracts.contract' call
// Inline function 'sample.Model.<init>.<anonymous>' call
tmp_0 = '' + $this.xyz_1 + '...';
}
tmp.xyz_1 = tmp_0;
} else
$this.xyz_1 = xyz;
return $this;
}
function Model_init_$Create$(seen1, abc, xyz, serializationConstructorMarker) {
return Model_init_$Init$(seen1, abc, xyz, serializationConstructorMarker, objectCreate(protoOf(Model)));
}
function Model(abc) {
Companion_getInstance();
this.abc_1 = abc;
var tmp = this;
var tmp0_safe_receiver = this.abc_1;
var tmp_0;
if (tmp0_safe_receiver == null) {
tmp_0 = null;
} else {
// Inline function 'kotlin.let' call
// Inline function 'kotlin.contracts.contract' call
// Inline function 'sample.Model.xyz.<anonymous>' call
tmp_0 = tmp0_safe_receiver + '...';
}
tmp.xyz_1 = tmp_0;
}
protoOf(Model).get_abc_18j9qf_k$ = function () {
return this.abc_1;
};
protoOf(Model).get_xyz_18is40_k$ = function () {
return this.xyz_1;
};
protoOf(Model).component1_7eebsc_k$ = function () {
return this.abc_1;
};
protoOf(Model).copy_q202ni_k$ = function (abc) {
return new Model(abc);
};
protoOf(Model).copy$default_1m1bzh_k$ = function (abc, $super) {
abc = abc === VOID ? this.abc_1 : abc;
return $super === VOID ? this.copy_q202ni_k$(abc) : $super.copy_q202ni_k$.call(this, abc);
};
protoOf(Model).toString = function () {
return 'Model(abc=' + this.abc_1 + ')';
};
protoOf(Model).hashCode = function () {
return this.abc_1 == null ? 0 : getStringHashCode(this.abc_1);
};
protoOf(Model).equals = function (other) {
if (this === other)
return true;
if (!(other instanceof Model))
return false;
var tmp0_other_with_cast = other instanceof Model ? other : THROW_CCE();
if (!(this.abc_1 == tmp0_other_with_cast.abc_1))
return false;
return true;
};
//region block: post-declaration
protoOf($serializer).typeParametersSerializers_fr94fx_k$ = typeParametersSerializers;
//endregion
return _;
}));
//# sourceMappingURL=serialization-bug-sample.js.map
When the xyz
parameter name is replaced by another name, e.g. other
:
@Serializable
data class Model(
val abc: String?,
) {
val xyz = abc?.let { other -> "$other..." }
}
Then we get the following compiled code:
Compiled Code
(function (root, factory) {
if (typeof define === 'function' && define.amd)
define(['exports', './kotlin-kotlin-stdlib.js', './kotlinx-serialization-kotlinx-serialization-core.js'], factory);
else if (typeof exports === 'object')
factory(module.exports, require('./kotlin-kotlin-stdlib.js'), require('./kotlinx-serialization-kotlinx-serialization-core.js'));
else {
if (typeof this['kotlin-kotlin-stdlib'] === 'undefined') {
throw new Error("Error loading module 'com.sample:serialization-bug-sample'. Its dependency 'kotlin-kotlin-stdlib' was not found. Please, check whether 'kotlin-kotlin-stdlib' is loaded prior to 'com.sample:serialization-bug-sample'.");
}
if (typeof this['kotlinx-serialization-kotlinx-serialization-core'] === 'undefined') {
throw new Error("Error loading module 'com.sample:serialization-bug-sample'. Its dependency 'kotlinx-serialization-kotlinx-serialization-core' was not found. Please, check whether 'kotlinx-serialization-kotlinx-serialization-core' is loaded prior to 'com.sample:serialization-bug-sample'.");
}
root['com.sample:serialization-bug-sample'] = factory(typeof this['com.sample:serialization-bug-sample'] === 'undefined' ? {} : this['com.sample:serialization-bug-sample'], this['kotlin-kotlin-stdlib'], this['kotlinx-serialization-kotlinx-serialization-core']);
}
}(this, function (_, kotlin_kotlin, kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core) {
'use strict';
//region block: imports
var protoOf = kotlin_kotlin.$_$.x5;
var objectMeta = kotlin_kotlin.$_$.w5;
var setMetadataFor = kotlin_kotlin.$_$.y5;
var PluginGeneratedSerialDescriptor = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.l;
var StringSerializer_getInstance = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.b;
var get_nullable = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.c;
var UnknownFieldException_init_$Create$ = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.a;
var THROW_CCE = kotlin_kotlin.$_$.q6;
var typeParametersSerializers = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.i;
var GeneratedSerializer = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.j;
var VOID = kotlin_kotlin.$_$.d;
var throwMissingFieldException = kotlin_org_jetbrains_kotlinx_kotlinx_serialization_core.$_$.m;
var objectCreate = kotlin_kotlin.$_$.v5;
var getStringHashCode = kotlin_kotlin.$_$.f5;
var classMeta = kotlin_kotlin.$_$.b5;
//endregion
//region block: pre-declaration
setMetadataFor(Companion, 'Companion', objectMeta);
setMetadataFor($serializer, '$serializer', objectMeta, VOID, [GeneratedSerializer]);
setMetadataFor(Model, 'Model', classMeta, VOID, VOID, VOID, VOID, {0: $serializer_getInstance});
//endregion
function Companion() {
Companion_instance = this;
}
protoOf(Companion).serializer_9w0wvi_k$ = function () {
return $serializer_getInstance();
};
var Companion_instance;
function Companion_getInstance() {
if (Companion_instance == null)
new Companion();
return Companion_instance;
}
function $serializer() {
$serializer_instance = this;
var tmp0_serialDesc = new PluginGeneratedSerialDescriptor('sample.Model', this, 2);
tmp0_serialDesc.addElement_5pzumi_k$('abc', false);
tmp0_serialDesc.addElement_5pzumi_k$('xyz', true);
this.descriptor_1 = tmp0_serialDesc;
}
protoOf($serializer).get_descriptor_wjt6a0_k$ = function () {
return this.descriptor_1;
};
protoOf($serializer).childSerializers_5ghqw5_k$ = function () {
// Inline function 'kotlin.arrayOf' call
// Inline function 'kotlin.js.unsafeCast' call
// Inline function 'kotlin.js.asDynamic' call
return [get_nullable(StringSerializer_getInstance()), get_nullable(StringSerializer_getInstance())];
};
protoOf($serializer).deserialize_sy6x50_k$ = function (decoder) {
var tmp0_desc = this.descriptor_1;
var tmp1_flag = true;
var tmp2_index = 0;
var tmp3_bitMask0 = 0;
var tmp4_local0 = null;
var tmp5_local1 = null;
var tmp6_input = decoder.beginStructure_yljocp_k$(tmp0_desc);
if (tmp6_input.decodeSequentially_xlblqy_k$()) {
tmp4_local0 = tmp6_input.decodeNullableSerializableElement_k2y6ab_k$(tmp0_desc, 0, StringSerializer_getInstance(), tmp4_local0);
tmp3_bitMask0 = tmp3_bitMask0 | 1;
tmp5_local1 = tmp6_input.decodeNullableSerializableElement_k2y6ab_k$(tmp0_desc, 1, StringSerializer_getInstance(), tmp5_local1);
tmp3_bitMask0 = tmp3_bitMask0 | 2;
} else
while (tmp1_flag) {
tmp2_index = tmp6_input.decodeElementIndex_bstkhp_k$(tmp0_desc);
switch (tmp2_index) {
case -1:
tmp1_flag = false;
break;
case 0:
tmp4_local0 = tmp6_input.decodeNullableSerializableElement_k2y6ab_k$(tmp0_desc, 0, StringSerializer_getInstance(), tmp4_local0);
tmp3_bitMask0 = tmp3_bitMask0 | 1;
break;
case 1:
tmp5_local1 = tmp6_input.decodeNullableSerializableElement_k2y6ab_k$(tmp0_desc, 1, StringSerializer_getInstance(), tmp5_local1);
tmp3_bitMask0 = tmp3_bitMask0 | 2;
break;
default:
throw UnknownFieldException_init_$Create$(tmp2_index);
}
}
tmp6_input.endStructure_1xqz0n_k$(tmp0_desc);
return Model_init_$Create$(tmp3_bitMask0, tmp4_local0, tmp5_local1, null);
};
protoOf($serializer).serialize_n60lb7_k$ = function (encoder, value) {
var tmp0_desc = this.descriptor_1;
var tmp1_output = encoder.beginStructure_yljocp_k$(tmp0_desc);
tmp1_output.encodeNullableSerializableElement_5lquiv_k$(tmp0_desc, 0, StringSerializer_getInstance(), value.abc_1);
var tmp;
if (tmp1_output.shouldEncodeElementDefault_x8eyid_k$(tmp0_desc, 1)) {
tmp = true;
} else {
var tmp0_safe_receiver = value.abc_1;
var tmp_0;
if (tmp0_safe_receiver == null) {
tmp_0 = null;
} else {
// Inline function 'kotlin.let' call
// Inline function 'kotlin.contracts.contract' call
// Inline function 'sample.$serializer.serialize.<anonymous>' call
tmp_0 = tmp0_safe_receiver + '...';
}
tmp = !(value.xyz_1 == tmp_0);
}
if (tmp) {
tmp1_output.encodeNullableSerializableElement_5lquiv_k$(tmp0_desc, 1, StringSerializer_getInstance(), value.xyz_1);
}
tmp1_output.endStructure_1xqz0n_k$(tmp0_desc);
};
protoOf($serializer).serialize_5ase3y_k$ = function (encoder, value) {
return this.serialize_n60lb7_k$(encoder, value instanceof Model ? value : THROW_CCE());
};
var $serializer_instance;
function $serializer_getInstance() {
if ($serializer_instance == null)
new $serializer();
return $serializer_instance;
}
function Model_init_$Init$(seen1, abc, xyz, serializationConstructorMarker, $this) {
if (!(1 === (1 & seen1))) {
throwMissingFieldException(seen1, 1, $serializer_getInstance().descriptor_1);
}
$this.abc_1 = abc;
if (0 === (seen1 & 2)) {
var tmp = $this;
var tmp0_safe_receiver = $this.abc_1;
var tmp_0;
if (tmp0_safe_receiver == null) {
tmp_0 = null;
} else {
// Inline function 'kotlin.let' call
// Inline function 'kotlin.contracts.contract' call
// Inline function 'sample.Model.<init>.<anonymous>' call
tmp_0 = tmp0_safe_receiver + '...';
}
tmp.xyz_1 = tmp_0;
} else
$this.xyz_1 = xyz;
return $this;
}
function Model_init_$Create$(seen1, abc, xyz, serializationConstructorMarker) {
return Model_init_$Init$(seen1, abc, xyz, serializationConstructorMarker, objectCreate(protoOf(Model)));
}
function Model(abc) {
Companion_getInstance();
this.abc_1 = abc;
var tmp = this;
var tmp0_safe_receiver = this.abc_1;
var tmp_0;
if (tmp0_safe_receiver == null) {
tmp_0 = null;
} else {
// Inline function 'kotlin.let' call
// Inline function 'kotlin.contracts.contract' call
// Inline function 'sample.Model.xyz.<anonymous>' call
tmp_0 = tmp0_safe_receiver + '...';
}
tmp.xyz_1 = tmp_0;
}
protoOf(Model).get_abc_18j9qf_k$ = function () {
return this.abc_1;
};
protoOf(Model).get_xyz_18is40_k$ = function () {
return this.xyz_1;
};
protoOf(Model).component1_7eebsc_k$ = function () {
return this.abc_1;
};
protoOf(Model).copy_q202ni_k$ = function (abc) {
return new Model(abc);
};
protoOf(Model).copy$default_1m1bzh_k$ = function (abc, $super) {
abc = abc === VOID ? this.abc_1 : abc;
return $super === VOID ? this.copy_q202ni_k$(abc) : $super.copy_q202ni_k$.call(this, abc);
};
protoOf(Model).toString = function () {
return 'Model(abc=' + this.abc_1 + ')';
};
protoOf(Model).hashCode = function () {
return this.abc_1 == null ? 0 : getStringHashCode(this.abc_1);
};
protoOf(Model).equals = function (other) {
if (this === other)
return true;
if (!(other instanceof Model))
return false;
var tmp0_other_with_cast = other instanceof Model ? other : THROW_CCE();
if (!(this.abc_1 == tmp0_other_with_cast.abc_1))
return false;
return true;
};
//region block: post-declaration
protoOf($serializer).typeParametersSerializers_fr94fx_k$ = typeParametersSerializers;
//endregion
return _;
}));
//# sourceMappingURL=serialization-bug-sample.js.map
The diff between these two is:
110d109
< var tmp0_safe_receiver = value.abc_1;
112c111
< if (tmp0_safe_receiver == null) {
---
> if (value.abc_1 == null) {
118c117
< tmp_0 = tmp0_safe_receiver + '...';
---
> tmp_0 = '' + value.xyz_1 + '...';
143d141
< var tmp0_safe_receiver = $this.abc_1;
145c143
< if (tmp0_safe_receiver == null) {
---
> if ($this.abc_1 == null) {
151c149
< tmp_0 = tmp0_safe_receiver + '...';
---
> tmp_0 = '' + $this.xyz_1 + '...';
It is evident that the compiler plugin mistakes the name xyz
in the scope of the let
lambda to refer to the xyz
property of the class, instead of by the local variable.