js_import expanded, now compatible with node module conventions
diff --git a/.bazelproject b/.bazelproject
index 4dc8ce1..af125c4 100644
--- a/.bazelproject
+++ b/.bazelproject
@@ -14,6 +14,11 @@
 directories:
   # Add the directories you want added as source here
   # By default, we've added your entire workspace ('.')
+  -examples/node/bazel-node
+  -examples/node/bazel-bin
+  -examples/node/bazel-genfiles
+  -examples/node/bazel-out
+  -examples/node/bazel-testlogs
   .
 
 targets:
diff --git a/examples/node/express/BUILD b/examples/node/express/BUILD
index ca38a89..9c1b022 100644
--- a/examples/node/express/BUILD
+++ b/examples/node/express/BUILD
@@ -25,7 +25,7 @@
 kt_js_library(
     name ="app",
     srcs = [":App.kt"],
-    deps = [":acme-routes"],
+    deps = [":acme-routes"]
 )
 
 # The binary demonstrates an express app composed of three modules. The modules can co-exist in the same directory.
diff --git a/examples/node/package.json b/examples/node/package.json
index 7ae63ad..4f1fe67 100644
--- a/examples/node/package.json
+++ b/examples/node/package.json
@@ -2,9 +2,7 @@
   "name": "node_packages",
   "version": "1.0.0",
   "dependencies": {
-    "express": "^4.16.3",
-    "kotlin": "1.2.60",
-    "kotlin-test": "1.2.60"
+    "express": "^4.16.3"
   },
   "devDependencies": {
     "source-map-support": "^0.5.6"
diff --git a/examples/node/yarn.lock b/examples/node/yarn.lock
index 06dda37..e01d70c 100644
--- a/examples/node/yarn.lock
+++ b/examples/node/yarn.lock
@@ -171,16 +171,6 @@
   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"
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
index 630bd4b..028130b 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt
@@ -21,7 +21,6 @@
     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)
diff --git a/kotlin/internal/defs.bzl b/kotlin/internal/defs.bzl
index cde4313..62690d5 100644
--- a/kotlin/internal/defs.bzl
+++ b/kotlin/internal/defs.bzl
@@ -26,12 +26,10 @@
     },
 )
 
-# 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",
+        "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
index 9c0f139..9f0a0ec 100644
--- a/kotlin/internal/js/BUILD
+++ b/kotlin/internal/js/BUILD
@@ -11,3 +11,9 @@
 # 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.
+
+py_binary(
+    name = "importer",
+    srcs = ["importer.py"],
+    visibility = ["//visibility:public"],
+)
diff --git a/kotlin/internal/js/impl.bzl b/kotlin/internal/js/impl.bzl
index d565ed6..46580fb 100644
--- a/kotlin/internal/js/impl.bzl
+++ b/kotlin/internal/js/impl.bzl
@@ -13,6 +13,7 @@
 # limitations under the License.
 load(
     "//kotlin/internal:defs.bzl",
+    _KT_COMPILER_REPO = "KT_COMPILER_REPO",
     _KtJsInfo = "KtJsInfo",
     _TOOLCHAIN_TYPE = "TOOLCHAIN_TYPE",
 )
@@ -55,6 +56,7 @@
         [
             "-source-map",
             "-meta-info",
+            "-no-stdlib",  # TODO remove this once the stdlib is not conveyed to node via the deps attribute.
             "-module-kind",
             ctx.attr.module_kind,
             "-target",
@@ -93,29 +95,51 @@
     return [
         DefaultInfo(
             files = depset([ctx.outputs.js, ctx.outputs.js_map]),
-            runfiles = ctx.runfiles(files = [
-                ctx.outputs.js,
-                ctx.outputs.js_map,
-            ]),
         ),
         _KtJsInfo(
+            js = ctx.outputs.js,
+            js_map = ctx.outputs.js_map,
             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")
+    jar_file = ctx.files.jars[0]
 
-    files = depset(ctx.files.jars)
+    # Lock the jar name to the label name -- only make an exception for the compiler repo.
+    if not (ctx.label.workspace_root.startswith("external/") and ctx.label.workspace_root.endswith(_KT_COMPILER_REPO)):
+        expected_basename = "%s.jar" % ctx.label.name
+        if not jar_file.basename == expected_basename:
+            fail("label name %s is not the same as the jar name %s" % (jar_file.basename, expected_basename))
+
+    args = ctx.actions.args()
+    args.add("--jar", jar_file)
+    args.add("--out", ctx.outputs.js)
+    args.add("--aux", ctx.outputs.js_map)
+
+    inputs, _, input_manifest = ctx.resolve_command(tools = [ctx.attr._importer])
+    ctx.actions.run(
+        inputs = inputs + [jar_file],
+        executable = ctx.executable._importer,
+        outputs = [
+            ctx.outputs.js,
+            ctx.outputs.js_map,
+        ],
+        arguments = [args],
+        input_manifests = input_manifest,
+    )
+
     return [
         DefaultInfo(
-            files = files,
+            files = depset([ctx.outputs.js, ctx.outputs.js_map]),
         ),
         _KtJsInfo(
-            jar = ctx.attr.jars[0],
-            srcjar = ctx.attr.srcjar,
+            js = ctx.outputs.js,
+            js_map = ctx.outputs.js_map,
+            jar = jar_file,
+            srcjar = ctx.files.srcjar[0],
         ),
     ]
diff --git a/kotlin/internal/js/importer.py b/kotlin/internal/js/importer.py
new file mode 100644
index 0000000..7e54d50
--- /dev/null
+++ b/kotlin/internal/js/importer.py
@@ -0,0 +1,64 @@
+# 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.
+import argparse
+import os
+import zipfile
+
+
+def _is_jar(jar):
+    if not os.path.exists(jar):
+        raise argparse.ArgumentTypeError("jar:{0} does not exist".format(jar))
+    else:
+        return zipfile.ZipFile(jar)
+
+
+def _extract_root_entry(jar, entry_path, touch=False):
+    """
+    Extracts a root entry from a jar. and write it to a path.
+
+    entry_path is absolute and the basename is used to extract the entry from the jar.
+
+    :param jar: The jar from which to make the extraction.
+    :param entry_path: An absolute file path to where the entry should be written.
+    :param touch: Should the file be touched if it was not found in the jar.
+    """
+    basename = os.path.basename(entry_path)
+    try:
+        jar.read(basename)
+    except Exception as ex:
+        if touch:
+            f = open(entry_path, 'a')
+            f.close()
+            return
+        else:
+            raise ex
+    jar.extract(basename, path=os.path.dirname(entry_path))
+
+
+def _main(p):
+    args = p.parse_args()
+    _extract_root_entry(args.jar, args.out)
+    for e in args.aux:
+        _extract_root_entry(args.jar, e, touch=True)
+
+
+parser = argparse.ArgumentParser()
+
+parser.add_argument("--jar", type=_is_jar, required=True)
+parser.add_argument("--out", required=True, help="mandatory paths to files that should be extracted from the root")
+parser.add_argument(
+    "--aux", nargs="*",
+    help="""paths to files that should be extracted from the root, if the files do not exist they are touched.""")
+
+_main(parser)
diff --git a/kotlin/internal/js/js.bzl b/kotlin/internal/js/js.bzl
index d7bdcf3..7360ebb 100644
--- a/kotlin/internal/js/js.bzl
+++ b/kotlin/internal/js/js.bzl
@@ -13,6 +13,7 @@
 # limitations under the License.
 load(
     "//kotlin/internal:defs.bzl",
+    _KT_COMPILER_REPO = "KT_COMPILER_REPO",
     _KtJsInfo = "KtJsInfo",
     _TOOLCHAIN_TYPE = "TOOLCHAIN_TYPE",
 )
@@ -22,6 +23,30 @@
     _kt_js_library_impl = "kt_js_library_impl",
 )
 
+_JS_STDLIB_MAP = {
+    "kotlin-stdlib-js": "kotlin",
+    "kotlin-test-js": "kotlin-test",
+}
+
+# The macro, and the ones using it exist 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 _lock_attrs(name, kwargs):
+    if native.repository_name().startswith("@") and native.repository_name().endswith(_KT_COMPILER_REPO):
+        name = _JS_STDLIB_MAP.get(name, default = name)
+    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
+    return kwargs
+
 kt_js_library = rule(
     attrs = {
         "srcs": attr.label_list(
@@ -29,8 +54,20 @@
             allow_files = [".kt"],
             mandatory = True,
         ),
+        "data": attr.label_list(
+            allow_files = True,
+            default = [],
+            cfg = "data",
+        ),
         "deps": attr.label_list(
             doc = """A list of other kotlin JS libraries.""",
+            default = [],
+            allow_empty = True,
+            providers = [_KtJsInfo],
+        ),
+        "runtime_deps": attr.label_list(
+            doc = """A list of other kotlin JS libraries that should be available at runtime.""",
+            default = [],
             allow_empty = True,
             providers = [_KtJsInfo],
         ),
@@ -51,6 +88,11 @@
             doc = "internal attribute",
             mandatory = False,
         ),
+        "_toolchain": attr.label(
+            doc = """The Kotlin JS Runtime.""",
+            default = Label("@" + _KT_COMPILER_REPO + "//:kotlin-stdlib-js"),
+            cfg = "target",
+        ),
     },
     implementation = _kt_js_library_impl,
     outputs = dict(
@@ -63,26 +105,13 @@
     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"
+    kwargs = _lock_attrs(name, kwargs)
 
-    if kwargs.get("module_name") != None:
-        fail("module_name is an internal attribute.")
-    else:
-        kwargs["module_name"] = name
+    # TODO this is a runtime dep, it should be picked up from the _toolchain attr or from a provider.
+    kwargs["deps"] = kwargs.get("deps", []) + ["@" + _KT_COMPILER_REPO + "//:kotlin-stdlib-js"]
     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(
@@ -99,7 +128,29 @@
             allow_files = [".jar"],
             mandatory = False,
         ),
+        "module_name": attr.string(
+            doc = "internal attribute",
+            mandatory = False,
+        ),
+        "module_root": attr.string(
+            doc = "internal attriubte",
+            mandatory = False,
+        ),
+        "_importer": attr.label(
+            default = "//kotlin/internal/js:importer",
+            allow_files = True,
+            executable = True,
+            cfg = "host",
+        ),
     },
+    outputs = dict(
+        js = "%{module_name}.js",
+        js_map = "%{module_name}.js.map",
+    ),
     implementation = _kt_js_import_impl,
     provides = [_KtJsInfo],
 )
+
+def kt_js_import_macro(name, **kwargs):
+    kwargs = _lock_attrs(name, kwargs)
+    kt_js_import(name = name, **kwargs)
diff --git a/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin b/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin
index 315a242..9d11d95 100644
--- a/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin
+++ b/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin
@@ -82,7 +82,6 @@
         visibility = ["//visibility:public"],
     )
     for art in [
-        "jslib",
         "test-js",
         "stdlib-js",
     ]
diff --git a/kotlin/internal/toolchains.bzl b/kotlin/internal/toolchains.bzl
index a22cba6..1f37feb 100644
--- a/kotlin/internal/toolchains.bzl
+++ b/kotlin/internal/toolchains.bzl
@@ -56,7 +56,7 @@
             runtime_jars = ctx.files.jvm_runtime,
             use_ijar = False,
         ),
-        js_stdlibs = ctx.files.js_stdlibs,
+        js_stdlibs = ctx.attr.js_stdlibs,
     )
     return [
         platform_common.ToolchainInfo(**toolchain),
diff --git a/kotlin/kotlin.bzl b/kotlin/kotlin.bzl
index 09158d0..bdae1a8 100644
--- a/kotlin/kotlin.bzl
+++ b/kotlin/kotlin.bzl
@@ -32,8 +32,9 @@
 )
 load(
     "//kotlin/internal/js:js.bzl",
-    "kt_js_import",
+    _kt_js_import = "kt_js_import_macro",
     _kt_js_library = "kt_js_library_macro",
 )
 
 kt_js_library = _kt_js_library
+kt_js_import = _kt_js_import