basic js support (#114)

Experimental JS support.
diff --git a/README.md b/README.md
index dc0f434..3605cd4 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
 [Skydoc documentation](https://bazelbuild.github.io/rules_kotlin)
 
 # Announcements
+* <b>August 14, 2018.</b> Js support. No documentation yet but see the nested example workspace `examples/node`.
 * <b>August 14, 2018.</b> Android support. No documentation but it's a simple integration. see 
   `kotlin/internal/jvm/android.bzl`.
 * <b>Jun 29, 2018.</b> The commits from this date forward are compatible with bazel `>=0.14`. JDK9 host issues were 
diff --git a/WORKSPACE b/WORKSPACE
index b6d1c29..c79c711 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -21,22 +21,6 @@
     repo = "google/protobuf",
 )
 
-git_repository(
-    name = "bazel_skylib",
-    remote = "https://github.com/bazelbuild/bazel-skylib.git",
-    tag = "0.5.0",
-)
-
-git_repository(
-    name = "build_bazel_rules_nodejs",
-    remote = "https://github.com/bazelbuild/rules_nodejs.git",
-    tag = "0.11.4",
-)
-
-load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
-
-node_repositories(package_json = [])
-
 http_jar(
     name = "bazel_deps",
     sha256 = "05498224710808be9687f5b9a906d11dd29ad592020246d4cd1a26eeaed0735e",
diff --git a/examples/node/BUILD b/examples/node/BUILD
new file mode 100644
index 0000000..9c0f139
--- /dev/null
+++ b/examples/node/BUILD
@@ -0,0 +1,13 @@
+# Copyright 2018 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/examples/node/README.MD b/examples/node/README.MD
new file mode 100644
index 0000000..5721a60
--- /dev/null
+++ b/examples/node/README.MD
@@ -0,0 +1 @@
+This example workspace demonstrates the JS support.
\ No newline at end of file
diff --git a/examples/node/WORKSPACE b/examples/node/WORKSPACE
new file mode 100644
index 0000000..81be52d
--- /dev/null
+++ b/examples/node/WORKSPACE
@@ -0,0 +1,33 @@
+workspace(name = "kotlin_node_examples")
+
+local_repository(
+    name = "io_bazel_rules_kotlin",
+    path = "../.."
+)
+
+load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kotlin_repositories", "kt_register_toolchains")
+kotlin_repositories()
+kt_register_toolchains()
+
+git_repository(
+    name = "bazel_skylib",
+    remote = "https://github.com/bazelbuild/bazel-skylib.git",
+    tag = "0.5.0",
+)
+
+git_repository(
+    name = "build_bazel_rules_nodejs",
+    remote = "https://github.com/bazelbuild/rules_nodejs.git",
+    tag = "0.11.4",
+)
+load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
+
+node_repositories(package_json = [])
+
+load("@build_bazel_rules_nodejs//:defs.bzl", "yarn_install")
+
+yarn_install(
+    name = "node_ws",
+    package_json = "//:package.json",
+    yarn_lock = "//:yarn.lock",
+)
diff --git a/examples/node/express/App.kt b/examples/node/express/App.kt
new file mode 100644
index 0000000..4cdc181
--- /dev/null
+++ b/examples/node/express/App.kt
@@ -0,0 +1,15 @@
+package express
+
+@JsModule("express")
+external fun express(): dynamic
+
+val app = express()
+
+fun main(args: Array<String>) {
+    // register the routes.
+    routes(app)
+
+    app.listen(3000, {
+        println("Listening on port 3000")
+    })
+}
\ No newline at end of file
diff --git a/examples/node/express/BUILD b/examples/node/express/BUILD
new file mode 100644
index 0000000..ca38a89
--- /dev/null
+++ b/examples/node/express/BUILD
@@ -0,0 +1,37 @@
+# Copyright 2018 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_js_library")
+load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
+
+# routes and auth have acme prepended to the rule name as these are the names of the resulting jars. The name of the
+# jar is the name of the module, and thus the name of the require statements.
+kt_js_library(
+    name = "acme-routes",
+    srcs = [":Routes.kt"],
+    deps = ["//express/auth:acme-auth"],
+)
+
+kt_js_library(
+    name ="app",
+    srcs = [":App.kt"],
+    deps = [":acme-routes"],
+)
+
+# The binary demonstrates an express app composed of three modules. The modules can co-exist in the same directory.
+nodejs_binary(
+    name = "express",
+    node_modules = "@node_ws//:node_modules",
+    data = [":app"],
+    entry_point = "kotlin_node_examples/express/app.js",
+)
diff --git a/examples/node/express/Routes.kt b/examples/node/express/Routes.kt
new file mode 100644
index 0000000..3f079d9
--- /dev/null
+++ b/examples/node/express/Routes.kt
@@ -0,0 +1,16 @@
+package express
+
+import express.auth.isAuthenticated
+
+//import express.auth.isAuthenticated
+
+fun routes(app: dynamic) {
+    app.get("/") { req, res ->
+        if(!isAuthenticated("bob")) {
+            res.send(401, "you sir, are not authorized !")
+        } else {
+            res.type("text/plain")
+            res.send("hello world")
+        }
+    }
+}
\ No newline at end of file
diff --git a/examples/node/express/auth/Auth.kt b/examples/node/express/auth/Auth.kt
new file mode 100644
index 0000000..f5a2d4c
--- /dev/null
+++ b/examples/node/express/auth/Auth.kt
@@ -0,0 +1,6 @@
+package express.auth
+
+
+fun isAuthenticated(user: String): Boolean {
+    return user != "bob"
+}
\ No newline at end of file
diff --git a/examples/node/express/auth/BUILD b/examples/node/express/auth/BUILD
new file mode 100644
index 0000000..835e9d6
--- /dev/null
+++ b/examples/node/express/auth/BUILD
@@ -0,0 +1,20 @@
+# Copyright 2018 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_js_library")
+
+kt_js_library(
+    name = "acme-auth",
+    srcs = ["Auth.kt"],
+    visibility=["//visibility:public"]
+)
diff --git a/examples/node/package.json b/examples/node/package.json
new file mode 100644
index 0000000..7ae63ad
--- /dev/null
+++ b/examples/node/package.json
@@ -0,0 +1,12 @@
+{
+  "name": "node_packages",
+  "version": "1.0.0",
+  "dependencies": {
+    "express": "^4.16.3",
+    "kotlin": "1.2.60",
+    "kotlin-test": "1.2.60"
+  },
+  "devDependencies": {
+    "source-map-support": "^0.5.6"
+  }
+}
diff --git a/examples/node/yarn.lock b/examples/node/yarn.lock
new file mode 100644
index 0000000..06dda37
--- /dev/null
+++ b/examples/node/yarn.lock
@@ -0,0 +1,331 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+accepts@~1.3.5:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
+  dependencies:
+    mime-types "~2.1.18"
+    negotiator "0.6.1"
+
+array-flatten@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+
+body-parser@1.18.2:
+  version "1.18.2"
+  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454"
+  dependencies:
+    bytes "3.0.0"
+    content-type "~1.0.4"
+    debug "2.6.9"
+    depd "~1.1.1"
+    http-errors "~1.6.2"
+    iconv-lite "0.4.19"
+    on-finished "~2.3.0"
+    qs "6.5.1"
+    raw-body "2.3.2"
+    type-is "~1.6.15"
+
+buffer-from@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04"
+
+bytes@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+
+content-disposition@0.5.2:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
+
+content-type@~1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+
+cookie-signature@1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+
+cookie@0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
+
+debug@2.6.9:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  dependencies:
+    ms "2.0.0"
+
+depd@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
+
+depd@~1.1.1, depd@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+
+destroy@~1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+
+ee-first@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+
+encodeurl@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+
+escape-html@~1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+
+etag@~1.8.1:
+  version "1.8.1"
+  resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+
+express@^4.16.3:
+  version "4.16.3"
+  resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53"
+  dependencies:
+    accepts "~1.3.5"
+    array-flatten "1.1.1"
+    body-parser "1.18.2"
+    content-disposition "0.5.2"
+    content-type "~1.0.4"
+    cookie "0.3.1"
+    cookie-signature "1.0.6"
+    debug "2.6.9"
+    depd "~1.1.2"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    finalhandler "1.1.1"
+    fresh "0.5.2"
+    merge-descriptors "1.0.1"
+    methods "~1.1.2"
+    on-finished "~2.3.0"
+    parseurl "~1.3.2"
+    path-to-regexp "0.1.7"
+    proxy-addr "~2.0.3"
+    qs "6.5.1"
+    range-parser "~1.2.0"
+    safe-buffer "5.1.1"
+    send "0.16.2"
+    serve-static "1.13.2"
+    setprototypeof "1.1.0"
+    statuses "~1.4.0"
+    type-is "~1.6.16"
+    utils-merge "1.0.1"
+    vary "~1.1.2"
+
+finalhandler@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
+  dependencies:
+    debug "2.6.9"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    on-finished "~2.3.0"
+    parseurl "~1.3.2"
+    statuses "~1.4.0"
+    unpipe "~1.0.0"
+
+forwarded@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
+
+fresh@0.5.2:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+
+http-errors@1.6.2:
+  version "1.6.2"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
+  dependencies:
+    depd "1.1.1"
+    inherits "2.0.3"
+    setprototypeof "1.0.3"
+    statuses ">= 1.3.1 < 2"
+
+http-errors@~1.6.2:
+  version "1.6.3"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
+  dependencies:
+    depd "~1.1.2"
+    inherits "2.0.3"
+    setprototypeof "1.1.0"
+    statuses ">= 1.4.0 < 2"
+
+iconv-lite@0.4.19:
+  version "0.4.19"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
+
+inherits@2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+
+ipaddr.js@1.8.0:
+  version "1.8.0"
+  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e"
+
+kotlin-test@1.2.60:
+  version "1.2.60"
+  resolved "https://registry.yarnpkg.com/kotlin-test/-/kotlin-test-1.2.60.tgz#e238c48740a1c9f1c036d3c3db04d40f47c934db"
+  dependencies:
+    kotlin "1.2.60"
+
+kotlin@1.2.60:
+  version "1.2.60"
+  resolved "https://registry.yarnpkg.com/kotlin/-/kotlin-1.2.60.tgz#3d7ec2328a0d46281e21b9d7cf5314032217b010"
+
+media-typer@0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+
+merge-descriptors@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+
+methods@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+
+mime-db@~1.35.0:
+  version "1.35.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47"
+
+mime-types@~2.1.18:
+  version "2.1.19"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0"
+  dependencies:
+    mime-db "~1.35.0"
+
+mime@1.4.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
+
+ms@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+
+negotiator@0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
+
+on-finished@~2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+  dependencies:
+    ee-first "1.1.1"
+
+parseurl@~1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
+
+path-to-regexp@0.1.7:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+
+proxy-addr@~2.0.3:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
+  dependencies:
+    forwarded "~0.1.2"
+    ipaddr.js "1.8.0"
+
+qs@6.5.1:
+  version "6.5.1"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
+
+range-parser@~1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
+
+raw-body@2.3.2:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"
+  dependencies:
+    bytes "3.0.0"
+    http-errors "1.6.2"
+    iconv-lite "0.4.19"
+    unpipe "1.0.0"
+
+safe-buffer@5.1.1:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+
+send@0.16.2:
+  version "0.16.2"
+  resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
+  dependencies:
+    debug "2.6.9"
+    depd "~1.1.2"
+    destroy "~1.0.4"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    fresh "0.5.2"
+    http-errors "~1.6.2"
+    mime "1.4.1"
+    ms "2.0.0"
+    on-finished "~2.3.0"
+    range-parser "~1.2.0"
+    statuses "~1.4.0"
+
+serve-static@1.13.2:
+  version "1.13.2"
+  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
+  dependencies:
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    parseurl "~1.3.2"
+    send "0.16.2"
+
+setprototypeof@1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
+
+setprototypeof@1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+
+source-map-support@^0.5.6:
+  version "0.5.6"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13"
+  dependencies:
+    buffer-from "^1.0.0"
+    source-map "^0.6.0"
+
+source-map@^0.6.0:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+
+"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2":
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+
+statuses@~1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
+
+type-is@~1.6.15, type-is@~1.6.16:
+  version "1.6.16"
+  resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
+  dependencies:
+    media-typer "0.3.0"
+    mime-types "~2.1.18"
+
+unpipe@1.0.0, unpipe@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+
+utils-merge@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+
+vary@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
diff --git a/kotlin/builder/proto/jars/libkotlin_model_proto-speed.jar b/kotlin/builder/proto/jars/libkotlin_model_proto-speed.jar
index 1038b72..5c04b63 100755
--- a/kotlin/builder/proto/jars/libkotlin_model_proto-speed.jar
+++ b/kotlin/builder/proto/jars/libkotlin_model_proto-speed.jar
Binary files differ
diff --git a/kotlin/builder/proto/kotlin_model.proto b/kotlin/builder/proto/kotlin_model.proto
index 8814ef6..3f108af 100644
--- a/kotlin/builder/proto/kotlin_model.proto
+++ b/kotlin/builder/proto/kotlin_model.proto
@@ -147,3 +147,25 @@
     Outputs outputs = 3;
     Inputs inputs = 4;
 }
+
+message JsCompilationTask {
+    message Outputs {
+        // The primary output
+        string js = 1;
+        string jar = 3;
+        string srcjar = 4;
+    }
+
+    message Inputs {
+        repeated string libraries = 1;
+        // Partitioned from the builder flags, expanding the source_jars.
+        repeated string kotlin_sources = 2;
+    }
+
+    CompilationTaskInfo info = 1;
+    Outputs outputs = 3;
+    Inputs inputs = 4;
+
+    // flags that should be passed through straight to the kotlinc-js compiler.
+    repeated string pass_through_flags = 5;
+}
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt b/kotlin/builder/src/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt
index 37cfd5f..9ef3736 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt
@@ -16,6 +16,7 @@
 package io.bazel.kotlin.builder.tasks
 
 import com.google.protobuf.util.JsonFormat
+import io.bazel.kotlin.builder.tasks.js.Kotlin2JsTaskExecutor
 import io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor
 import io.bazel.kotlin.builder.toolchain.CompilationStatusException
 import io.bazel.kotlin.builder.utils.*
@@ -33,7 +34,8 @@
 @Suppress("MemberVisibilityCanBePrivate")
 class KotlinBuilder @Inject internal constructor(
     private val outputProvider: Provider<PrintStream>,
-    private val jvmTaskExecutor: KotlinJvmTaskExecutor
+    private val jvmTaskExecutor: KotlinJvmTaskExecutor,
+    private val jsTaskExecutor: Kotlin2JsTaskExecutor
 ) : CommandLineProgram {
     companion object {
         @JvmStatic
@@ -55,7 +57,8 @@
             @Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA")
             when (context.info.platform) {
                 Platform.JVM -> executeJvmTask(context, argMap)
-                Platform.UNRECOGNIZED, Platform.JS -> throw IllegalStateException("unrecognized platform: ${context.info}")
+                Platform.JS -> executeJsTask(context, argMap)
+                Platform.UNRECOGNIZED -> throw IllegalStateException("unrecognized platform: ${context.info}")
             }
             success = true
         } catch (ex: CompilationStatusException) {
@@ -131,6 +134,9 @@
         PLUGINS("--kotlin_plugins"),
         FRIEND_PATHS("--kotlin_friend_paths"),
         OUTPUT_JDEPS("--kotlin_output_jdeps"),
+        OUTPUT_JS_JAR("--kotlin_output_js_jar"),
+        JS_PASSTHROUGH_FLAGS("--kotlin_js_passthrough_flags"),
+        JS_LIBRARIES("--kotlin_js_libraries"),
         DEBUG("--kotlin_debug_tags"),
         TASK_ID("--kotlin_task_id");
     }
@@ -159,6 +165,28 @@
             this
         }
 
+    private fun executeJsTask(context: CompilationTaskContext, argMap: ArgMap) =
+        buildJsTask(context.info, argMap).let { jsTask ->
+            context.whenTracing { printProto("js task input", jsTask) }
+            jsTaskExecutor.execute(context, jsTask)
+        }
+
+    private fun buildJsTask(info: CompilationTaskInfo, argMap: ArgMap): JsCompilationTask =
+        with(JsCompilationTask.newBuilder()) {
+            this.info = info
+            with(inputsBuilder) {
+                addAllLibraries(argMap.mandatory(KotlinBuilderFlags.JS_LIBRARIES))
+                addAllKotlinSources(argMap.mandatory(JavaBuilderFlags.SOURCES))
+            }
+            with(outputsBuilder) {
+                js = argMap.mandatorySingle(JavaBuilderFlags.OUTPUT)
+                jar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_JS_JAR)
+                srcjar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_SRCJAR)
+            }
+            addAllPassThroughFlags(argMap.mandatory(KotlinBuilderFlags.JS_PASSTHROUGH_FLAGS))
+            build()
+        }
+
     private fun executeJvmTask(context: CompilationTaskContext, argMap: ArgMap) {
         val task = buildJvmTask(context.info, argMap)
         context.whenTracing {
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt b/kotlin/builder/src/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt
new file mode 100644
index 0000000..630bd4b
--- /dev/null
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt
@@ -0,0 +1,82 @@
+package io.bazel.kotlin.builder.tasks.js
+
+import io.bazel.kotlin.builder.toolchain.CompilationException
+import io.bazel.kotlin.builder.toolchain.KotlinToolchain
+import io.bazel.kotlin.builder.utils.CompilationTaskContext
+import io.bazel.kotlin.builder.utils.addAll
+import io.bazel.kotlin.builder.utils.jars.JarCreator
+import io.bazel.kotlin.builder.utils.jars.SourceJarCreator
+import io.bazel.kotlin.builder.utils.resolveTwinVerified
+import io.bazel.kotlin.builder.utils.verifiedPath
+import io.bazel.kotlin.model.JsCompilationTask
+import java.io.FileOutputStream
+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.Paths
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class Kotlin2JsTaskExecutor @Inject constructor(
+    private val invoker: KotlinToolchain.K2JSCompilerInvoker
+) {
+    fun execute(context: CompilationTaskContext, task: JsCompilationTask) {
+        context.print(Paths.get(task.inputs.kotlinSourcesList[0]).toRealPath().toAbsolutePath().toString())
+        task.compile(context)
+
+        val jsPath = Paths.get(task.outputs.js)
+        val jsMetaFile = jsPath.resolveTwinVerified(".meta.js")
+        val jsDirectory = jsPath.parent.resolve(jsPath.toFile().nameWithoutExtension)
+        task.createJar(jsDirectory, listOf(jsPath, jsPath.resolveTwinVerified(".js.map"), jsMetaFile))
+        // this mutates the jsPath file , so do it after creating the jar.
+        appendMetaToPrimary(jsPath, jsMetaFile)
+        task.createSourceJar()
+    }
+
+    private fun JsCompilationTask.compile(context: CompilationTaskContext) {
+        val args = mutableListOf<String>().also {
+            it.addAll(passThroughFlagsList)
+            it.addAll("-libraries", inputs.librariesList.joinToString(":"))
+            it.addAll("-output", outputs.js)
+            it.addAll(inputs.kotlinSourcesList)
+        }
+        context.whenTracing { printLines("js compile args", args) }
+        context.executeCompilerTask(args, invoker::compile)
+    }
+
+    private fun JsCompilationTask.createSourceJar() {
+        try {
+            SourceJarCreator(Paths.get(outputs.srcjar), false).also { creator ->
+                creator.addSources(inputs.kotlinSourcesList.map { Paths.get(it) }.stream())
+            }.execute()
+        } catch (ex: Throwable) {
+            throw CompilationException("could not create source jar", ex)
+        }
+    }
+
+    /**
+     * Append the meta file to the JS file. This is an accepted pattern, and it allows us to not have to export the
+     * meta.js file with the js.
+     */
+    private fun appendMetaToPrimary(jsPath: Path, jsMetaFile: Path) {
+        try {
+            FileOutputStream(jsPath.toFile(), true).use { Files.copy(jsMetaFile, it) }
+        } catch (ex: Throwable) {
+            throw CompilationException("could not normalize js file", ex)
+        }
+    }
+
+    private fun JsCompilationTask.createJar(jsDirectoryPath: Path, rootEntries: List<Path>) {
+        try {
+            val outputJarPath = Paths.get(outputs.jar)
+
+            JarCreator(outputJarPath).also { creator ->
+                creator.addDirectory(jsDirectoryPath)
+                creator.addRootEntries(rootEntries.map { it.toString() })
+                creator.execute()
+            }
+        } catch (ex: Throwable) {
+            throw CompilationException("error creating js jar", ex)
+        }
+    }
+}
\ No newline at end of file
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt b/kotlin/builder/src/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt
index 5214657..2c626bd 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt
@@ -42,7 +42,6 @@
         throwable.printStackTrace(out)
     }
 
-    @Suppress("unused")
     fun print(msg: String) { out.println(msg) }
     /**
      * Print a list of debugging lines.
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/utils/MiscUtils.kt b/kotlin/builder/src/io/bazel/kotlin/builder/utils/MiscUtils.kt
index fcfd90a..356a02c 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/utils/MiscUtils.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/utils/MiscUtils.kt
@@ -21,6 +21,11 @@
 
 fun <T, C : MutableCollection<T>> C.addAll(vararg entries: T): C = this.also { addAll(entries) }
 
+/**
+ * Utility function to add multiple entries to a list with a leader.
+ */
+fun <T, C : MutableCollection<T>> C.addAll(leader: T,  entries: List<T>): C = this.also { add(leader); addAll(entries) }
+
 private fun extensionMatcher(vararg ext: String): Predicate<String> =
     Pattern.compile("^(.+?)${ext.joinToString("|\\.", prefix = "(\\.",postfix = ")$")}").asPredicate()
 
diff --git a/kotlin/internal/defs.bzl b/kotlin/internal/defs.bzl
index 67b6bbc..ea1b774 100644
--- a/kotlin/internal/defs.bzl
+++ b/kotlin/internal/defs.bzl
@@ -25,3 +25,14 @@
         "outputs": "output jars produced by this rule. [intelij-aspect]",
     },
 )
+
+# TODO when kt_js_import is capable of unpacking the jars and making the js and js_map files available then uncomment
+# the fields below.
+KtJsInfo = provider(
+    fields = {
+        # "js": "The primary output of the library",
+        # "js_map": "The map file for the library",
+        "jar": "A jar of the library.",
+        "srcjar": "The jar containing the sources of the library",
+    },
+)
diff --git a/kotlin/internal/js/BUILD b/kotlin/internal/js/BUILD
new file mode 100644
index 0000000..9c0f139
--- /dev/null
+++ b/kotlin/internal/js/BUILD
@@ -0,0 +1,13 @@
+# Copyright 2018 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/kotlin/internal/js/impl.bzl b/kotlin/internal/js/impl.bzl
new file mode 100644
index 0000000..3b8a983
--- /dev/null
+++ b/kotlin/internal/js/impl.bzl
@@ -0,0 +1,121 @@
+# Copyright 2018 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+load(
+    "//kotlin/internal:defs.bzl",
+    _KtJsInfo = "KtJsInfo",
+    _TOOLCHAIN_TYPE = "TOOLCHAIN_TYPE",
+)
+load(
+    "//kotlin/internal/common:common.bzl",
+    _common = "common",
+)
+
+# The following kt-js flags are currently not used.
+# -Xfriend-modules=<path>
+#  -output-postfix <path>     Path to file which will be added to the end of output file
+#  -output-prefix <path>      Path to file which will be added to the beginning of output file
+#  -source-map-base-dirs <path> Base directories which are used to calculate relative paths to source files in source map
+#  -source-map-embed-sources { always, never, inlining }
+#                             Embed source files into source map
+#  -source-map-prefix         Prefix for paths in a source map
+#  -Xtyped-arrays
+
+def kt_js_library_impl(ctx):
+    toolchain = ctx.toolchains[_TOOLCHAIN_TYPE]
+
+    # meta.js is merged in with the js in the builder. It is declared as it's created at the package level and not in
+    # some anonymous directory.
+    out_meta = ctx.actions.declare_file(ctx.attr.name + ".meta.js")
+
+    # The Kotlin compiler and intellij infrastructure uses jars and bytecode. The out dir contains bytecode generated by
+    # the kotlin compiler. In addition to the js and js.map file a jar is also produced.
+    out_dir = ctx.actions.declare_directory(ctx.label.name)
+
+    libraries = depset([d[_KtJsInfo].jar for d in ctx.attr.deps])
+
+    args = _common.init_args(
+        ctx,
+        "kt_js_library",
+        _common.derive_module_name(ctx),
+    )
+
+    args.add_all(
+        "--kotlin_js_passthrough_flags",
+        [
+            "-source-map",
+            "-meta-info",
+            "-module-kind",
+            ctx.attr.module_kind,
+            "-target",
+            ctx.attr.js_target,
+        ],
+    )
+
+    args.add("--output", ctx.outputs.js)
+    args.add("--kotlin_js_dir", out_dir)  # TODO
+    args.add("--kotlin_output_js_jar", ctx.outputs.jar)
+    args.add("--kotlin_output_srcjar", ctx.outputs.srcjar)
+
+    args.add_all("--kotlin_js_libraries", libraries, omit_if_empty = False)
+    args.add_all("--sources", ctx.files.srcs)
+
+    inputs, _, input_manifests = ctx.resolve_command(tools = [toolchain.kotlinbuilder, toolchain.kotlin_home])
+
+    ctx.actions.run(
+        mnemonic = "KotlinCompile",
+        inputs = depset(inputs) + libraries + ctx.files.srcs,
+        outputs = [
+            ctx.outputs.js,
+            ctx.outputs.js_map,
+            ctx.outputs.jar,
+            ctx.outputs.srcjar,
+            out_meta,
+            out_dir,
+        ],
+        executable = toolchain.kotlinbuilder.files_to_run.executable,
+        execution_requirements = {"supports-workers": "1"},
+        arguments = [args],
+        progress_message = "Compiling Kotlin to JS %s { kt: %d }" % (ctx.label, len(ctx.files.srcs)),
+        input_manifests = input_manifests,
+    )
+
+    return [
+        DefaultInfo(
+            files = depset([ctx.outputs.js, ctx.outputs.js_map]),
+            runfiles = ctx.runfiles(files = [
+                ctx.outputs.js,
+                ctx.outputs.js_map,
+            ]),
+        ),
+        _KtJsInfo(
+            jar = ctx.outputs.jar,
+            srcjar = ctx.outputs.srcjar,
+        ),
+    ]
+
+# This is just a placeholder at the moment.
+def kt_js_import_impl(ctx):
+    if len(ctx.files.jars) != 1:
+        fail("a single jar should be supplied, multiple jars not supported")
+
+    files = depset(ctx.files.jars)
+    return [
+        DefaultInfo(
+            files = files,
+        ),
+        _KtJsInfo(
+            jar = ctx.attr.jars[0],
+            srcjar = ctx.attr.srcjar,
+        ),
+    ]
diff --git a/kotlin/internal/js/js.bzl b/kotlin/internal/js/js.bzl
new file mode 100644
index 0000000..d7bdcf3
--- /dev/null
+++ b/kotlin/internal/js/js.bzl
@@ -0,0 +1,105 @@
+# Copyright 2018 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+load(
+    "//kotlin/internal:defs.bzl",
+    _KtJsInfo = "KtJsInfo",
+    _TOOLCHAIN_TYPE = "TOOLCHAIN_TYPE",
+)
+load(
+    "//kotlin/internal/js:impl.bzl",
+    _kt_js_import_impl = "kt_js_import_impl",
+    _kt_js_library_impl = "kt_js_library_impl",
+)
+
+kt_js_library = rule(
+    attrs = {
+        "srcs": attr.label_list(
+            allow_empty = False,
+            allow_files = [".kt"],
+            mandatory = True,
+        ),
+        "deps": attr.label_list(
+            doc = """A list of other kotlin JS libraries.""",
+            allow_empty = True,
+            providers = [_KtJsInfo],
+        ),
+        "module_kind": attr.string(
+            doc = """The Kind of a module generated by compiler, users should stick to commonjs.""",
+            default = "commonjs",
+            values = ["umd", "commonjs", "amd", "plain"],
+        ),
+        "js_target": attr.string(
+            default = "v5",
+            values = ["v5"],
+        ),
+        "module_root": attr.string(
+            doc = "internal attriubte",
+            mandatory = False,
+        ),
+        "module_name": attr.string(
+            doc = "internal attribute",
+            mandatory = False,
+        ),
+    },
+    implementation = _kt_js_library_impl,
+    outputs = dict(
+        js = "%{name}.js",
+        js_map = "%{name}.js.map",
+        jar = "%{name}.jar",
+        srcjar = "%{name}-sources.jar",
+    ),
+    toolchains = [_TOOLCHAIN_TYPE],
+    provides = [_KtJsInfo],
+)
+
+# The macro exists to ensure compatibility with the nodejs rules, the nodejs rules process the attributes and not the
+# providers. Ideally providers would be used so the rules can pass the information along without having to have user
+# facing attributes visible.
+#   module_root: if the module_root is made settable then there is a possibility of collisions. Keeping it simple here.
+#   module_name: The require statement generated by Kotlinc-js seems to be based on the name of the jar. Unlike the jvm
+#       compiler, there is no 'module-name' flag available. So to keep things simple it's hard coded to the module name.
+def kt_js_library_macro(name, **kwargs):
+    if kwargs.get("module_root") != None:
+        fail("The module_root is an internal attribute.")
+    else:
+        kwargs["module_root"] = name + ".js"
+
+    if kwargs.get("module_name") != None:
+        fail("module_name is an internal attribute.")
+    else:
+        kwargs["module_name"] = name
+    kt_js_library(name = name, **kwargs)
+
+# TODO for Node the kotlin dependencies have to be provided via node_modules. The correct approach is to unpack the
+# the jars and make the js and js.map files available to node (via the module_root and module_name attributes?).
+kt_js_import = rule(
+    attrs = {
+        "jars": attr.label_list(
+            allow_files = [".jar"],
+            mandatory = True,
+        ),
+        "srcjar": attr.label(
+            allow_files = ["-sources.jar"],
+            mandatory = False,
+            single_file = True,
+        ),
+        "runtime_deps": attr.label_list(
+            default = [],
+            allow_files = [".jar"],
+            mandatory = False,
+        ),
+    },
+    implementation = _kt_js_import_impl,
+    provides = [_KtJsInfo],
+)
diff --git a/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin b/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin
index a2311f8..315a242 100644
--- a/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin
+++ b/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin
@@ -70,3 +70,20 @@
         "script-runtime",
     ]
 ]
+
+load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_js_import")
+
+#  The Kotlin standard libraries. These should be setup in a Toolchain.
+[
+    kt_js_import(
+        name = "kotlin-%s" % art,
+        jars = ["lib/kotlin-%s.jar" % art],
+        srcjar = "lib/kotlin-%s-sources.jar" % art,
+        visibility = ["//visibility:public"],
+    )
+    for art in [
+        "jslib",
+        "test-js",
+        "stdlib-js",
+    ]
+]
diff --git a/kotlin/internal/toolchains.bzl b/kotlin/internal/toolchains.bzl
index a386d79..0d883bc 100644
--- a/kotlin/internal/toolchains.bzl
+++ b/kotlin/internal/toolchains.bzl
@@ -12,8 +12,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//kotlin/internal/common:common.bzl", _common = "common")
-load("//kotlin/internal:defs.bzl", _KT_COMPILER_REPO = "KT_COMPILER_REPO", _TOOLCHAIN_TYPE = "TOOLCHAIN_TYPE")
+load(
+    "//kotlin/internal/common:common.bzl",
+    _common = "common",
+)
+load(
+    "//kotlin/internal:defs.bzl",
+    _KT_COMPILER_REPO = "KT_COMPILER_REPO",
+    _KtJsInfo = "KtJsInfo",
+    _TOOLCHAIN_TYPE = "TOOLCHAIN_TYPE",
+)
 
 """Kotlin Toolchains
 
@@ -53,6 +61,7 @@
             runtime_jars = ctx.files.jvm_runtime,
             use_ijar = False,
         ),
+        js_stdlibs = ctx.files.js_stdlibs,
     )
     return [
         platform_common.ToolchainInfo(**toolchain),
@@ -132,6 +141,16 @@
                 "1.8",
             ],
         ),
+        "js_target": attr.string(
+            default = "v5",
+            values = ["v5"],
+        ),
+        "js_stdlibs": attr.label_list(
+            default = [
+                Label("@" + _KT_COMPILER_REPO + "//:kotlin-stdlib-js"),
+            ],
+            providers = [_KtJsInfo],
+        ),
     },
     implementation = _kotlin_toolchain_impl,
     provides = [platform_common.ToolchainInfo],
diff --git a/kotlin/kotlin.bzl b/kotlin/kotlin.bzl
index 2a043de..77eb8c4 100644
--- a/kotlin/kotlin.bzl
+++ b/kotlin/kotlin.bzl
@@ -24,3 +24,10 @@
     "//kotlin/internal/jvm:android.bzl",
     "kt_android_library",
 )
+load(
+    "//kotlin/internal/js:js.bzl",
+    "kt_js_import",
+    _kt_js_library = "kt_js_library_macro",
+)
+
+kt_js_library = _kt_js_library