I'm trying to use <fast-xml-parser> in my multipla...
# javascript
e
I'm trying to use fast-xml-parser in my multiplatform library. The external class definition I've come up with is
Copy code
open external class XMLParser(options: X2jOptions = definedExternally) {
  open fun <T> parse(xmlData: String, validationOptions: ValidationOptions = definedExternally): T
  open fun <T> parse(xmlData: String): T
  open fun <T> parse(xmlData: String, validationOptions: Boolean = definedExternally): T
  open fun <T> parse(xmlData: Buffer, validationOptions: ValidationOptions = definedExternally): T
  open fun <T> parse(xmlData: Buffer): T
  open fun <T> parse(xmlData: Buffer, validationOptions: Boolean = definedExternally): T
  open fun addEntity(entityIdentifier: String, entityValue: String)
}
The
parse
function returns
any
in the TS version (fxp.d.ts). It basically return a JSON-like object. To represent the
T
type in Kotlin, should I use an interface or a class?
Also, even if my
T
types are not `JsExport`ed, how do I prevent name mangling of properties?
a
For the first question, you can use both interface and class. For the second, I'm not sure, but you can try to use @JsName on each property you want to keep the name. But, you need to double-check if they will be mangled in production. If so, I think we should discuss inside the team, if we want to eliminate mangling for the declarations with @JsName annotation.
e
Hi @Artem Kobzar! It seems
JsName
turns off mangling, and I get the desired property name. It's also important to use a
class
, if it's not `JsExport`ed. If you use an
interface
, like
Copy code
interface ParseResult {
  val messages: Array<String>
}
The generated JS will have a function call instead of a property access.
Since these classes are used in
commonMain
, I can't use external definitions, which - maybe - would have been better suited
a
About the property access - it's true. The same situation with the interface with the
JsExport
right now, and I'm changing the behavior.
e
Thanks Artem. Seems like the overall KJS stability is going in the right direction, perfect
thank you color 1
One last question related to property/function access using interfaces. Being that on the JVM the default behavior is to generate a function (
val messages > getMessages()
), will the new property-by-default behavior be customizable to generate a function call instead?
a
If we are talking about generating such methods for @JsExport/external declarations, unfortunately, I feel that the answer is no. But, for @JsExport you have a nice workaround: https://pl.kotl.in/-fbYl3V7e
e
So I've tried this
The same situation with the interface with the
JsExport
right now
Copy code
@JsExport
public interface ZMessage {
  public val number: Int
  public val text: String
}
KT usage site:
Copy code
// Returns Array<ZMessage>, which simply type some data returned by Fast XML Parser
val messages = service.doSomething()
println(messages?.last()?.number)
Generated JS code:
Copy code
var tmp2_safe_receiver = this.result10__1;
var tmp3_safe_receiver = tmp2_safe_receiver == null ? null : last(tmp2_safe_receiver);
println(tmp3_safe_receiver == null ? null : tmp3_safe_receiver.number);
It seems working as expected to me (
tmp3_safe_receiver.number
). Or did you mean something else? In my case the issue manifest when I remove
JsExport
.
Copy code
public interface ZMessage {
  @JsName("number")
  public val number: Int
  public val text: String
}
Generated JS code:
Copy code
var tmp2_safe_receiver = this.result10__1;
var tmp3_safe_receiver = tmp2_safe_receiver == null ? null : last(tmp2_safe_receiver);
println(tmp3_safe_receiver == null ? null : tmp3_safe_receiver.get_number_hay53m_k$());
Note
tmp3_safe_receiver.get_number_hay53m_k$()
JsName
turns off mangling only for classes it seems.
a
Yes, this is the right behavior. The situation will be changed if you will annotate the message variable with
ZMessage
type
e
will annotate the message variable with
ZMessage
type
You mean only if you explicitly specify the type? Like
Copy code
val messages: Array<ZMessage> = service...
Or
Copy code
val message: ZMessage = messages.last()
a
Exactly. Because, we assume that if a class is not annotated with the JsExport, than we could use its properties getters/setters directly to reduce the bundle size.
e
I wonder how the IDE will help the user to understand this. Specifying types explicitly is something I've seen done 1% of the times
Maybe that's a better choice than an annotation tho. I feel like we are overdosing annotations lately 😞 Definitely don't want to cover my common code in JS annotations
a
Actually, all of the JS-specific annotations (and their behavior) were designed to use it from inside the common code. So, it's okay to do it.
✔️ 1