Kotlin to JS Iterator is not a function

Viewed 607

I am currently implementing a Part-of-speech-tagger in Kotlin and when building / running on JVM everything works just fine (the tagger tags things correct and the program is reasonable fast when it comes to tagging sentences). However when I exported the program to JS I get the following error message:

TypeError: tags.iterator is not a function. (In 'tags.iterator()', 'tags.iterator' is undefined)
Trigram — Trigram.kt:13
Globaler Code
evaluateWithScopeExtension
(anonyme Funktion)
_wrapCall


Things I tried:
1. I had this exact JS-Code within the HTML-File, then it worked but the performance was awful (took 2-3 seconds to tag one sentence, if I tag the same sentence via the JVM it takes like 0.2 seconds or less).
2. replaced for(word in tags)with for(word in tags.toList(), the iterator was still undefined

I am on macOS using Safari, the error occurs on chrome as well.

Thank you for your help!

Kotlin-Class producing errors

class Trigram (private val probabilities: Probabilities, tags: List<String>){
    // Creating the list mit all possible tags
    init {
        val list = ArrayList<String>()

        for(word in tags) { // This is where the error occurs
            list.add(word)
        }

    }

JS-File that returns the testing-strings

function getTags() {
  return ["NN", "$.", "$(" ... , "PPOSS"]
}

function getJsonString() {
 return ... // Returns a valid JSONString
}

Test-HTML-File

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
    <meta charset="utf-8">
    <title>Part-of-speech-tagger</title>

    <!-- Loading kotlin.js -->
    <script src="../../../js/packages_imported/kotlin/1.3.72/kotlin.js" charset="utf-8"></script>
    <!-- Loading kotlinx-serialization-kotlinx-serialization-runtime -->
    <script src="../../../js/packages_imported/kotlinx-serialization-kotlinx-serialization-runtime/0.20.0/kotlinx-serialization-kotlinx-serialization-runtime.js" charset="utf-8"></script>

    <!-- Loading the generated js file -->
    <script src="../../../js/packages/postagger/kotlin/postagger.js" charset="utf-8"></script>

    <!-- Loading the js file containing the strings -->
    <script src="strings.js" charset="utf-8"></script>
</head>
<body>
    <h1>This is a test html file to check for js support</h1>
</body>
</html>

build.gradle

plugins {
    id 'java'
    id 'org.jetbrains.kotlin.multiplatform' version '1.3.72'
    id 'org.jetbrains.kotlin.plugin.serialization' version "1.3.70"
}

group 'my group'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
    jcenter()
    maven { url "https://kotlin.bintray.com/kotlinx" }
}

kotlin {

    // JVM Target
    jvm() {
        withJava()
        jvmJar {
            manifest {
                // Specify main-class
                attributes(
                        'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
                        'Main-Class': 'postagger.MainKt'
                )
            }
        }
    }


    targets {
        fromPreset(presets.js, 'js') {
            nodejs {}
            configure([compilations.main, compilations.test]) {
                tasks.getByName(compileKotlinTaskName).kotlinOptions {
                    sourceMap = true
                    moduleKind = "umd"
                    metaInfo = true
                }
            }
        }
    }

    sourceSets {
        commonMain {
            dependencies {
                implementation kotlin('stdlib-common')
                implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:0.20.0"
            }
        }
        commonTest {
            dependencies {
                implementation kotlin('test-common')
                implementation kotlin('test-annotations-common')
            }
        }
        jvmMain {
            dependencies {
                implementation kotlin('stdlib-jdk8')
                implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0"
            }
        }
        jvmTest {
            dependencies {
                implementation kotlin('test')
                implementation kotlin('test-junit')
            }
        }
        jsMain {
            dependencies {
                implementation(kotlin('stdlib-js'))
                implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:0.20.0"
            }
        }
        jsTest {
            dependencies {
                implementation kotlin('test-js')
            }
        }
    }
}
1 Answers

In a similar (although not same) environment, I had the same problem: a correct kotlin file compiled to javascript code that would fail with iterator is not a function.

The object missing the iterator method was deserialized from a Json string.

If this is the case for you, then making sure that all the below conditions hold:

  1. build.gradle contains the serialization plugin
plugins {
...
    id 'org.jetbrains.kotlin.plugin.serialization' version "1.3.70"
...
}
  1. deserialization (json string to object) uses
  kotlinx.serialization.json.Json(JsonConfiguration.Stable)
                           .parse<YourObject>(jsonString)

instead of kotlin.js.JSON.parse(jsonString) method.

  1. Class YourObject has the @Serializable annotation

solved the problem for me.

Related