Support skipping values equals to defaults in output stream for JS and IR backends

This commit is contained in:
Leonid Startsev
2018-10-16 14:04:58 +03:00
parent dba6396e95
commit 662e918a7b
7 changed files with 103 additions and 48 deletions
@@ -380,6 +380,23 @@ interface IrBuilderExtension {
) )
} }
fun buildInitializersRemapping(irClass: IrClass): (IrField) -> IrExpression? {
val original = irClass.constructors.singleOrNull { it.isPrimary }
?: throw IllegalStateException("Serializable class must have single primary constructor")
// default arguments of original constructor
val defaultsMap: Map<ParameterDescriptor, IrExpression?> =
original.valueParameters.associate { it.descriptor to it.defaultValue?.expression }
return fun(f: IrField): IrExpression? {
val i = f.initializer?.expression ?: return null
return if (i is IrGetValueImpl && i.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER) {
// this is a primary constructor property, use corresponding default of value parameter
defaultsMap.getValue(i.descriptor as ParameterDescriptor)
} else {
i
}
}
}
fun findEnumValuesMethod(enumClass: ClassDescriptor): IrFunction { fun findEnumValuesMethod(enumClass: ClassDescriptor): IrFunction {
assert(enumClass.kind == ClassKind.ENUM_CLASS) assert(enumClass.kind == ClassKind.ENUM_CLASS)
return compilerContext.externalSymbols.referenceClass(enumClass).owner.functions return compilerContext.externalSymbols.referenceClass(enumClass).owner.functions
@@ -6,7 +6,6 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
@@ -18,7 +17,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
@@ -40,19 +38,7 @@ class SerializableIrGenerator(
override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) = override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) =
irClass.contributeConstructor(constructorDescriptor) { ctor -> irClass.contributeConstructor(constructorDescriptor) { ctor ->
val original = irClass.constructors.singleOrNull { it.isPrimary } ?: throw IllegalStateException("Serializable class must have single primary constructor") val transformFieldInitializer = buildInitializersRemapping(irClass)
// default arguments of original constructor
val defaultsMap: Map<ParameterDescriptor, IrExpression?> = original.valueParameters.associate { it.descriptor to it.defaultValue?.expression }
fun transformFieldInitializer(f: IrField): IrExpression? {
val i = f.initializer?.expression ?: return null
return if (i is IrGetValueImpl && i.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER) {
// this is a primary constructor property, use corresponding default of value parameter
defaultsMap.getValue(i.descriptor as ParameterDescriptor)
} else {
i
}
}
// Missing field exception parts // Missing field exception parts
val exceptionCtor = val exceptionCtor =
@@ -7,6 +7,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.common.lower.irThrow import org.jetbrains.kotlin.backend.common.lower.irThrow
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
@@ -14,11 +15,8 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
import org.jetbrains.kotlin.ir.expressions.mapValueParametersIndexed
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
@@ -48,6 +46,8 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
override val BackendContext.localSymbolTable: SymbolTable override val BackendContext.localSymbolTable: SymbolTable
get() = _table get() = _table
private val serializableIrClass = compilerContext.externalSymbols.referenceClass(serializableDescriptor)
override fun generateSerialDesc() { override fun generateSerialDesc() {
val desc: PropertyDescriptor = generatedSerialDescPropertyDescriptor ?: return val desc: PropertyDescriptor = generatedSerialDescPropertyDescriptor ?: return
val serialDescImplClass = serializerDescriptor val serialDescImplClass = serializerDescriptor
@@ -157,6 +157,9 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc -> override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc ->
val fieldInitializer: (SerializableProperty) -> IrExpression? =
buildInitializersRemapping(serializableIrClass.owner).run { { invoke(it.irField) } }
fun irThis(): IrExpression = fun irThis(): IrExpression =
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol) IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
@@ -183,35 +186,51 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
val serialObjectSymbol = saveFunc.valueParameters[1] val serialObjectSymbol = saveFunc.valueParameters[1]
val localOutput = irTemporary(call, "output") val localOutput = irTemporary(call, "output")
fun SerializableProperty.irGet(): IrGetField = irGetField(irGet(serialObjectSymbol), irField)
// internal serialization via virtual calls? // internal serialization via virtual calls?
val labeledProperties = orderedProperties.filter { !it.transient } for ((index, property) in orderedProperties.filter { !it.transient }.withIndex()) {
for (index in labeledProperties.indices) {
val property = labeledProperties[index]
if (property.transient) continue
// output.writeXxxElementValue(classDesc, index, value) // output.writeXxxElementValue(classDesc, index, value)
val sti = getSerialTypeInfo(property) val sti = getSerialTypeInfo(property)
val innerSerial = serializerInstance(this@SerializerIrGenerator, serializableDescriptor, sti.serializer, property.module, property.type, property.genericIndex) val innerSerial = serializerInstance(this@SerializerIrGenerator, serializableDescriptor, sti.serializer, property.module, property.type, property.genericIndex)
if (innerSerial == null) { val elementCall = if (innerSerial == null) {
val writeFunc = val writeFunc =
kOutputClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}") kOutputClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}")
+irInvoke( irInvoke(
irGet(localOutput), irGet(localOutput),
writeFunc, writeFunc,
irGet(localSerialDesc), irGet(localSerialDesc),
irInt(index), irInt(index),
irGetField(irGet(serialObjectSymbol), property.irField) property.irGet()
) )
} else { } else {
val writeFunc = kOutputClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}") val writeFunc = kOutputClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}")
+irInvoke( irInvoke(
irGet(localOutput), irGet(localOutput),
writeFunc, writeFunc,
irGet(localSerialDesc), irGet(localSerialDesc),
irInt(index), irInt(index),
innerSerial, innerSerial,
irGetField(irGet(serialObjectSymbol), property.irField) property.irGet()
) )
} }
// check for call to .shouldEncodeElementDefault
if (!property.optional) {
// emit call right away
+elementCall
} else {
// emit check:
// if (obj.prop != DEFAULT_VALUE || output.shouldEncodeElementDefault(this.descriptor, i))
// output.encodeIntElement(this.descriptor, i, obj.prop)
val shouldEncodeFunc = kOutputClass.referenceMethod(CallingConventions.shouldEncodeDefault)
val partA = irNotEquals(property.irGet(), fieldInitializer(property)!!) // todo: props w/o backing fields
val partB = irInvoke(irGet(localOutput), shouldEncodeFunc, irGet(localSerialDesc), irInt(index))
// Ir infrastructure does not have dedicated symbol for ||, so
// `a || b == if (a) true else b`, see org.jetbrains.kotlin.ir.builders.PrimitivesKt.oror
val condition = irIfThenElse(compilerContext.irBuiltIns.booleanType, partA, irTrue(), partB)
+irIfThen(condition, elementCall)
}
} }
// output.writeEnd(serialClassDesc) // output.writeEnd(serialClassDesc)
@@ -350,7 +369,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
// todo: set properties in external deserialization // todo: set properties in external deserialization
var args: List<IrExpression> = localProps.map { it.get() } var args: List<IrExpression> = localProps.map { it.get() }
val ctor: IrConstructorSymbol = if (serializableDescriptor.isInternalSerializable) { val ctor: IrConstructorSymbol = if (serializableDescriptor.isInternalSerializable) {
val ctorDesc = compilerContext.externalSymbols.referenceClass(serializableDescriptor) val ctorDesc = serializableIrClass
.owner.constructors.single { it.origin == SERIALIZABLE_PLUGIN_ORIGIN } .owner.constructors.single { it.origin == SERIALIZABLE_PLUGIN_ORIGIN }
args = listOf(irGet(bitMasks[0])) + args + irNull() args = listOf(irGet(bitMasks[0])) + args + irNull()
ctorDesc.symbol ctorDesc.symbol
@@ -16,20 +16,21 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.js package org.jetbrains.kotlinx.serialization.compiler.backend.js
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.js.translate.context.TranslationContext import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlinx.serialization.compiler.backend.common.bodyPropertiesDescriptorsMap
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContext import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContext
import org.jetbrains.kotlinx.serialization.compiler.backend.common.primaryPropertiesDescriptorsMap
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
@@ -172,3 +173,8 @@ internal fun SerializerJsTranslator.createGetKClassExpression(classDescriptor: C
context.namer().kotlin("getKClass"), context.namer().kotlin("getKClass"),
context.translateQualifiedReference(classDescriptor) context.translateQualifiedReference(classDescriptor)
) )
fun TranslationContext.buildInitializersRemapping(forClass: KtPureClassOrObject): Map<PropertyDescriptor, KtExpression?> = forClass.run {
(bodyPropertiesDescriptorsMap(bindingContext()).mapValues { it.value.delegateExpressionOrInitializer } +
primaryPropertiesDescriptorsMap(bindingContext()).mapValues { it.value.defaultValue })
}
@@ -43,10 +43,7 @@ class SerializableJsTranslator(
val context: TranslationContext val context: TranslationContext
) : SerializableCodegen(descriptor, context.bindingContext()) { ) : SerializableCodegen(descriptor, context.bindingContext()) {
private val initMap: Map<PropertyDescriptor, KtExpression?> = declaration.run { private val initMap: Map<PropertyDescriptor, KtExpression?> = context.buildInitializersRemapping(declaration)
(bodyPropertiesDescriptorsMap(context.bindingContext()).mapValues { it.value.delegateExpressionOrInitializer } +
primaryPropertiesDescriptorsMap(context.bindingContext()).mapValues { it.value.defaultValue })
}
override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) { override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) {
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.js.translate.context.Namer import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TranslationContext import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.declaration.DeclarationBodyVisitor import org.jetbrains.kotlin.js.translate.declaration.DeclarationBodyVisitor
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPureClassOrObject import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
@@ -123,12 +125,19 @@ class SerializerJsTranslator(descriptor: ClassDescriptor,
context.addDeclarationStatement(f.makeStmt()) context.addDeclarationStatement(f.makeStmt())
} }
private fun TranslationContext.referenceMethod(clazz: ClassDescriptor, name: String) =
clazz.getFuncDesc(name).single().let { getNameForDescriptor(it) }
override fun generateSave(function: FunctionDescriptor) = generateFunction(function) { jsFun, ctx -> override fun generateSave(function: FunctionDescriptor) = generateFunction(function) { jsFun, ctx ->
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS) val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS)
val kOutputClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_ENCODER_CLASS) val kOutputClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_ENCODER_CLASS)
val wBeginFunc = ctx.getNameForDescriptor( val wBeginFunc = ctx.getNameForDescriptor(
encoderClass.getFuncDesc(CallingConventions.begin).single { it.valueParameters.size == 2 }) encoderClass.getFuncDesc(CallingConventions.begin).single { it.valueParameters.size == 2 })
val serialClassDescRef = JsNameRef(context.getNameForDescriptor(anySerialDescProperty!!), JsThisRef()) val serialClassDescRef = JsNameRef(context.getNameForDescriptor(anySerialDescProperty!!), JsThisRef())
val initializersMap: Map<PropertyDescriptor, KtExpression?> = context.buildInitializersRemapping(
(serializableDescriptor.findPsi() as? KtPureClassOrObject)
?: throw AssertionError("Serializable descriptor $serializableDescriptor must have source file to build initializers map")
)
// output.writeBegin(desc, []) // output.writeBegin(desc, [])
val typeParams = serializableDescriptor.declaredTypeParameters.mapIndexed { idx, _ -> val typeParams = serializableDescriptor.declaredTypeParameters.mapIndexed { idx, _ ->
@@ -143,6 +152,8 @@ class SerializerJsTranslator(descriptor: ClassDescriptor,
val localOutputRef = JsNameRef(localOutputName) val localOutputRef = JsNameRef(localOutputName)
+JsVars(JsVars.JsVar(localOutputName, call)) +JsVars(JsVars.JsVar(localOutputName, call))
fun SerializableProperty.jsNameRef() = JsNameRef(ctx.getNameForDescriptor(descriptor), objRef)
// todo: internal serialization via virtual calls // todo: internal serialization via virtual calls
val labeledProperties = orderedProperties.filter { !it.transient } val labeledProperties = orderedProperties.filter { !it.transient }
for (index in labeledProperties.indices) { for (index in labeledProperties.indices) {
@@ -151,24 +162,42 @@ class SerializerJsTranslator(descriptor: ClassDescriptor,
// output.writeXxxElementValue(classDesc, index, value) // output.writeXxxElementValue(classDesc, index, value)
val sti = getSerialTypeInfo(property) val sti = getSerialTypeInfo(property)
val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex) val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex)
if (innerSerial == null) { val invocation = if (innerSerial == null) {
val writeFunc = val writeFunc =
kOutputClass.getFuncDesc("${CallingConventions.encode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}").single() kOutputClass.getFuncDesc("${CallingConventions.encode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}").single()
.let { ctx.getNameForDescriptor(it) } .let { ctx.getNameForDescriptor(it) }
+JsInvocation(JsNameRef(writeFunc, localOutputRef), JsInvocation(
serialClassDescRef, JsNameRef(writeFunc, localOutputRef),
JsIntLiteral(index), serialClassDescRef,
JsNameRef(ctx.getNameForDescriptor(property.descriptor), objRef)).makeStmt() JsIntLiteral(index),
property.jsNameRef()
).makeStmt()
} }
else { else {
val writeFunc = val writeFunc =
kOutputClass.getFuncDesc("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}").single() kOutputClass.getFuncDesc("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}").single()
.let { ctx.getNameForDescriptor(it) } .let { ctx.getNameForDescriptor(it) }
+JsInvocation(JsNameRef(writeFunc, localOutputRef), JsInvocation(
serialClassDescRef, JsNameRef(writeFunc, localOutputRef),
JsIntLiteral(index), serialClassDescRef,
innerSerial, JsIntLiteral(index),
JsNameRef(ctx.getNameForDescriptor(property.descriptor), objRef)).makeStmt() innerSerial,
property.jsNameRef()
).makeStmt()
}
if (!property.optional) {
+invocation
} else {
val shouldEncodeFunc = ctx.referenceMethod(kOutputClass, CallingConventions.shouldEncodeDefault)
val defaultValue =
initializersMap.getValue(property.descriptor)?.let { Translation.translateAsExpression(it, ctx) }
?: throw IllegalStateException("Optional property does not have an initializer?")
val partA = JsBinaryOperation(JsBinaryOperator.NEQ, property.jsNameRef(), defaultValue)
val partB =
JsInvocation(JsNameRef(shouldEncodeFunc, localOutputRef), serialClassDescRef, JsIntLiteral(index))
val cond = JsBinaryOperation(JsBinaryOperator.OR, partA, partB)
+JsIf(cond, invocation)
} }
} }
@@ -87,6 +87,7 @@ object CallingConventions {
const val encode = "encode" const val encode = "encode"
const val decodeElementIndex = "decodeElementIndex" const val decodeElementIndex = "decodeElementIndex"
const val elementPostfix = "Element" const val elementPostfix = "Element"
const val shouldEncodeDefault = "shouldEncodeElementDefault"
const val addElement = "addElement" const val addElement = "addElement"
const val addAnnotation = "pushAnnotation" const val addAnnotation = "pushAnnotation"