Kotlin function references have no identity when compiled to JS (and have different semantics on JVM and JS platforms)


#1

Let’s have the following code:

class TestClass {
    fun memberFunction() {}

    val memberFunctionReference get() = this::memberFunction
}

fun main(args: Array<String>) {
    val a = TestClass()
    println(a.memberFunctionReference == a.memberFunctionReference)
}

Result on JS platform: false
Result on JVM platform: true
(I guess that the JVM platform is always right :wink: )

The problem is with the JS translation of memberFunctionReference():

  Object.defineProperty(TestClass.prototype, 'memberFunctionReference', {
    get: function () {
      return getCallableRef('memberFunction', function ($receiver) {
        return $receiver.memberFunction(), Unit;
      }.bind(null, this));
    }
  });

Ie. it always returns a new function instead of caching the result of the first invocation.

This is not a theoretical problem: when passing member function references as React component props, currently there is no way to check for their equality in shouldComponentUpdate().

Maybe have you met this problem yet (and do you have a workaround :slight_smile: )?


#2

On JVM the result is not cached. There will be two different values in term of reference comparison ("==="), but they override equals method, so they equals in term of “==” operator.


#3

On JVM the result is not cached

I see… but when compiling to JS, maybe caching would be a possible solution to maintain the semantics of the JVM.
What do you think, is this a bug?