Skip to content

TypeError: setUserProperty is not a function on Kotlin/JS target Description #826

Description

@bpappin

Description

When running firebase-analytics on the Kotlin/JS target, calling the common API function FirebaseAnalytics.setUserProperty(name, value) throws a runtime TypeError: setUserProperty is not a function.

Underlying Cause

In the jsMain actual wrapper for FirebaseAnalytics, the library defines an external binding mapping directly to an export named setUserProperty in the "firebase/analytics" NPM module:

// dev.gitlive.firebase.analytics.externals.analytics.kt
@file:JsModule("firebase/analytics")
@file:JsNonModule
package dev.gitlive.firebase.analytics.externals

public external fun setUserProperty(app: FirebaseAnalytics, name: String, value: String)

However, the official Firebase JS SDK (v9/v10 modular API) does not export a function named setUserProperty (singular) under "firebase/analytics". Instead, the official JS SDK only exports setUserProperties (plural) which takes an analytics instance and a properties object:

import { setUserProperties } from "firebase/analytics";
setUserProperties(analytics, { favorite_food: "apples" });

Because of this, the imported JS function resolves to undefined at runtime, causing any invocation of setUserProperty(...) in Kotlin/JS common code to crash.

Environment Details

  • Library Group/Artifact: dev.gitlive:firebase-analytics / dev.gitlive:firebase-analytics-js
  • Library Version: 2.4.0
  • Kotlin Compiler Version: 2.3.21 (Kotlin/JS)
  • Firebase JS SDK NPM version: 10.13.2
  • Platform Target: Kotlin/JS (Browser Webpack / Web target)

Steps to Reproduce

  1. In commonMain code, instantiate and call Firebase Analytics:
    val analytics = Firebase.analytics
    analytics.setUserProperty("app_os_family", "Web")
  2. Build and launch the Kotlin/JS target in a browser environment.
  3. The application crashes immediately during initialization with the following stack trace:
    TypeError: setUserProperty is not a function
        at protoOf.setUserProperty_rx7df6_k$ (webpack-internal:///./kotlin/firebase-kotlin-sdk-firebase-analytics.js:225:5)
        at firebaseModule$lambda$lambda (webpack-internal:///./kotlin/EvolynClient-data.js:28802:12)
    

Expected Behavior

The library's setUserProperty(name, value) implementation should map to the official JS SDK's setUserProperties method under the hood:

// Expected jsMain delegation mapping
public actual fun setUserProperty(name: String, value: String) {
    setUserProperties(this.js, json(name to value)) 
}

Workaround / Mitigation

We mitigated this locally in our codebase by declaring the correct external JS binding and using an expect/actual extension to bypass the broken wrapper function on the JS target:

// webMain actual mapping
@file:JsModule("firebase/analytics")
@file:JsNonModule
package app.evolyn.data.firebase

import dev.gitlive.firebase.analytics.externals.FirebaseAnalytics

@JsName("setUserProperties")
public external fun setUserProperties(app: FirebaseAnalytics, properties: dynamic)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions