Migrate examples to new JS plugin

    * General cleanup and TODOs

Co-authored with: ilya.goncharov@jetbrains.com
diff --git a/build.gradle b/build.gradle
index 1088e2b..f93a808 100644
--- a/build.gradle
+++ b/build.gradle
@@ -252,7 +252,14 @@
 }
 
 // Redefine source sets because we are not using 'kotlin/main/fqn' folder convention
-configure(subprojects.findAll { !sourceless.contains(it.name) && it.name != "benchmarks" && it.name != 'example-frontend-js' && it.name != coreModule }) {
+configure(subprojects.findAll {
+    !sourceless.contains(it.name) &&
+            it.name != "benchmarks" &&
+            it.name != coreModule &&
+            it.name != "example-frontend-js"
+}) {
+    // Pure JS and pure MPP doesn't have this notion and are configured separately
+    // TODO detect it via platformOf and migrate benchmarks to the same scheme
     sourceSets {
         main.kotlin.srcDirs = ['src']
         test.kotlin.srcDirs = ['test']
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index bbbf2a3..f998017 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -14,7 +14,7 @@
     experimentalWarning.set(false)
 }
 
-val props = Properties().apply {
+private val props = Properties().apply {
     file("../gradle.properties").inputStream().use { load(it) }
 }
 
diff --git a/buildSrc/src/main/kotlin/Dokka.kt b/buildSrc/src/main/kotlin/Dokka.kt
index 72365c1..dd5f1ea 100644
--- a/buildSrc/src/main/kotlin/Dokka.kt
+++ b/buildSrc/src/main/kotlin/Dokka.kt
@@ -10,6 +10,9 @@
 import java.io.File
 import java.net.URL
 
+/**
+ * Package-list by external URL for documentation generation.
+ */
 fun Project.externalDocumentationLink(
     url: String,
     packageList: File = projectDir.resolve("package.list")
diff --git a/buildSrc/src/main/kotlin/MavenCentral.kt b/buildSrc/src/main/kotlin/MavenCentral.kt
index 9a96f3c..3efaf33 100644
--- a/buildSrc/src/main/kotlin/MavenCentral.kt
+++ b/buildSrc/src/main/kotlin/MavenCentral.kt
@@ -7,7 +7,7 @@
 import org.gradle.api.Project
 import org.gradle.api.publish.maven.MavenPom
 
-// --------------- pom configuration ---------------
+// Pom configuration
 
 fun MavenPom.configureMavenCentralMetadata(project: Project) {
     name by project.name
diff --git a/buildSrc/src/main/kotlin/Platform.kt b/buildSrc/src/main/kotlin/Platform.kt
index 4cacd9e..b667a13 100644
--- a/buildSrc/src/main/kotlin/Platform.kt
+++ b/buildSrc/src/main/kotlin/Platform.kt
@@ -1,5 +1,6 @@
 import org.gradle.api.Project
 
+// Use from Groovy for now
 fun platformOf(project: Project): String =
     when (project.name.substringAfterLast("-")) {
         "js" -> "js"
diff --git a/buildSrc/src/main/kotlin/RunR8.kt b/buildSrc/src/main/kotlin/RunR8.kt
index fc91dc0..d9eba79 100644
--- a/buildSrc/src/main/kotlin/RunR8.kt
+++ b/buildSrc/src/main/kotlin/RunR8.kt
@@ -7,6 +7,11 @@
 import org.gradle.kotlin.dsl.named
 import java.io.File
 
+/*
+ * Task used by our ui/android tests to test minification results
+ * and keep track of size of the binary.
+ * TODO move back to kotlinx-coroutines-android when it's migrated to the kts
+ */
 open class RunR8 : JavaExec() {
 
     @OutputDirectory
diff --git a/buildSrc/src/main/kotlin/UnpackAar.kt b/buildSrc/src/main/kotlin/UnpackAar.kt
index 2b96df3..c7d0b53 100644
--- a/buildSrc/src/main/kotlin/UnpackAar.kt
+++ b/buildSrc/src/main/kotlin/UnpackAar.kt
@@ -9,6 +9,7 @@
 import java.util.zip.ZipEntry
 import java.util.zip.ZipFile
 
+// TODO move back to kotlinx-coroutines-play-services when it's migrated to the kts
 @Suppress("UnstableApiUsage")
 abstract class UnpackAar : TransformAction<TransformParameters.None> {
     @get:InputArtifact
diff --git a/gradle/compile-js.gradle b/gradle/compile-js.gradle
index 77de787..523380d 100644
--- a/gradle/compile-js.gradle
+++ b/gradle/compile-js.gradle
@@ -6,16 +6,22 @@
 
 apply plugin: 'org.jetbrains.kotlin.js'
 
-kotlin.sourceSets {
-    main.kotlin.srcDirs = ['src']
-    test.kotlin.srcDirs = ['test']
-    main.resources.srcDirs = ['resources']
-    test.resources.srcDirs = ['test-resources']
+dependencies {
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
+    testImplementation "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version"
 }
 
-dependencies {
-    compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
-    testCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version"
+kotlin {
+    js(LEGACY) {
+        moduleName = project.name - "-js"
+    }
+
+    sourceSets {
+        main.kotlin.srcDirs = ['src']
+        test.kotlin.srcDirs = ['test']
+        main.resources.srcDirs = ['resources']
+        test.resources.srcDirs = ['test-resources']
+    }
 }
 
 tasks.withType(compileKotlinJs.getClass()) {
@@ -25,11 +31,3 @@
         metaInfo = true
     }
 }
-
-compileKotlinJs {
-    kotlinOptions {
-        // drop -js suffix from outputFile
-        def baseName = project.name - "-js"
-        outputFile = new File(outputFile.parent, baseName + ".js")
-    }
-}
diff --git a/js/example-frontend-js/README.md b/js/example-frontend-js/README.md
index 4e534e4..ad61372 100644
--- a/js/example-frontend-js/README.md
+++ b/js/example-frontend-js/README.md
@@ -3,7 +3,7 @@
 Build application with
 
 ```
-gradlew :example-frontend-js:bundle
+gradlew :example-frontend-js:build
 ```
 
 The resulting application can be found in `build/dist` subdirectory.
@@ -11,7 +11,7 @@
 You can start application with webpack-dev-server using:
 
 ```
-gradlew :example-frontend-js:start
+gradlew :example-frontend-js:run
 ```
 
 Built and deployed application is available at the library documentation site
diff --git a/js/example-frontend-js/build.gradle b/js/example-frontend-js/build.gradle
index f81efdd..7abde63 100644
--- a/js/example-frontend-js/build.gradle
+++ b/js/example-frontend-js/build.gradle
@@ -2,28 +2,32 @@
  * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
  */
 
-apply plugin: 'kotlin-dce-js'
-apply from: rootProject.file('gradle/node-js.gradle')
-
-dependencies {
-    compile "org.jetbrains.kotlinx:kotlinx-html-js:$html_version"
-}
-
-compileKotlinJs {
-    kotlinOptions {
-        main = "call"
+project.kotlin {
+    js(LEGACY) {
+        binaries.executable()
+        browser {
+            distribution {
+                directory = new File(directory.parentFile, "dist")
+            }
+            webpackTask {
+                cssSupport.enabled = true
+            }
+            runTask {
+                cssSupport.enabled = true
+            }
+            testTask {
+                useKarma {
+                    useChromeHeadless()
+                    webpackConfig.cssSupport.enabled = true
+                }
+            }
+        }
     }
-}
 
-task bundle(type: NpmTask, dependsOn: [npmInstall, build]) {
-    inputs.files(fileTree("$buildDir/kotlin-js-min/main"))
-    inputs.files(fileTree("$buildDir/kotlin-js-min/legacy/main"))
-    inputs.files(fileTree(file("src/main/web")))
-    inputs.file("npm/webpack.config.js")
-    outputs.dir("$buildDir/dist")
-    args = ["run", "bundle"]
-}
-
-task start(type: NpmTask, dependsOn: bundle) {
-    args = ["run", "start"]
+    sourceSets {
+        main.dependencies {
+            implementation "org.jetbrains.kotlinx:kotlinx-html-js:$html_version"
+            implementation(npm("html-webpack-plugin", "3.2.0"))
+        }
+    }
 }
diff --git a/js/example-frontend-js/npm/package.json b/js/example-frontend-js/npm/package.json
deleted file mode 100644
index 7668cef..0000000
--- a/js/example-frontend-js/npm/package.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-  "name": "example-frontend-js",
-  "version": "$version",
-  "license": "Apache-2.0",
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/Kotlin/kotlinx.coroutines.git"
-  },
-  "devDependencies": {
-    "webpack": "4.29.1",
-    "webpack-cli": "3.2.3",
-    "webpack-dev-server": "3.1.14",
-    "html-webpack-plugin": "3.2.0",
-    "uglifyjs-webpack-plugin": "2.1.1",
-    "style-loader": "0.23.1",
-    "css-loader": "2.1.0"
-  },
-  "scripts": {
-    "bundle": "webpack",
-    "start": "webpack-dev-server --open --no-inline"
-  }
-}
diff --git a/js/example-frontend-js/npm/webpack.config.js b/js/example-frontend-js/npm/webpack.config.js
deleted file mode 100644
index 8428c55..0000000
--- a/js/example-frontend-js/npm/webpack.config.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-// This script is copied to "build" directory and run from there
-
-const webpack = require("webpack");
-const HtmlWebpackPlugin = require('html-webpack-plugin');
-const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
-const path = require("path");
-
-const dist = path.resolve(__dirname, "dist");
-
-module.exports = {
-    mode: "production",
-    entry: {
-        main: "main"
-    },
-    output: {
-        filename: "[name].bundle.js",
-        path: dist,
-        publicPath: ""
-    },
-    devServer: {
-        contentBase: dist
-    },
-    module: {
-        rules: [
-            {
-                test: /\.css$/,
-                use: [
-                    'style-loader',
-                    'css-loader'
-                ]
-            }
-        ]
-    },
-    resolve: {
-        modules: [
-            path.resolve(__dirname, "kotlin-js-min/main"),
-            path.resolve(__dirname, "kotlin-js-min/legacy/main"),
-            path.resolve(__dirname, "../src/main/web/")
-        ]
-    },
-    devtool: 'source-map',
-    plugins: [
-        new HtmlWebpackPlugin({
-            title: 'Kotlin Coroutines JS Example'
-        }),
-        new UglifyJSPlugin({
-            sourceMap: true
-        })
-    ]
-};
diff --git a/js/example-frontend-js/src/ExampleMain.kt b/js/example-frontend-js/src/ExampleMain.kt
index 25a73c6..da6e419 100644
--- a/js/example-frontend-js/src/ExampleMain.kt
+++ b/js/example-frontend-js/src/ExampleMain.kt
@@ -13,7 +13,10 @@
 import kotlin.math.*
 import kotlin.random.Random
 
+external fun require(resource: String)
+
 fun main() {
+    require("style.css")
     println("Starting example application...")
     document.addEventListener("DOMContentLoaded", {
         Application().start()
diff --git a/js/example-frontend-js/src/main/web/main.js b/js/example-frontend-js/src/main/web/main.js
deleted file mode 100644
index d2440ff..0000000
--- a/js/example-frontend-js/src/main/web/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-// ------ Main bundle for example application ------
-
-require("example-frontend");
-require("style.css");
diff --git a/js/example-frontend-js/webpack.config.d/custom-config.js b/js/example-frontend-js/webpack.config.d/custom-config.js
new file mode 100644
index 0000000..21939be
--- /dev/null
+++ b/js/example-frontend-js/webpack.config.d/custom-config.js
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+;(function (config) {
+    const HtmlWebpackPlugin = require('html-webpack-plugin');
+
+    config.output.filename = "[name].bundle.js"
+
+    config.plugins.push(
+        new HtmlWebpackPlugin({
+            title: 'Kotlin Coroutines JS Example'
+        })
+    )
+
+    // path from <root-build>/js/packages/example-frontend-js to src/main/web
+    config.resolve.modules.push("../../../../js/example-frontend-js/src/main/web");
+})(config);
diff --git a/site/build.gradle.kts b/site/build.gradle.kts
index 686e81d..eba7b1a 100644
--- a/site/build.gradle.kts
+++ b/site/build.gradle.kts
@@ -26,7 +26,7 @@
     from("$srcBuildDir/dist")
     into("$buildDocsDir/example-frontend-js")
 
-    dependsOn(":example-frontend-js:bundle")
+    dependsOn(":example-frontend-js:browserDistribution")
 }
 
 tasks.register<Exec>("site") {