Merge remote-tracking branch 'origin/master' into develop
diff --git a/README.md b/README.md
index 631bf8a..3d9ec1c 100644
--- a/README.md
+++ b/README.md
@@ -117,6 +117,17 @@
 }
 ```
 
+## Building 
+
+This library is built with Gradle. To build it, use `./gradlew build`. 
+You can import this project into IDEA, but you have to delegate build actions
+to Gradle (in Preferences -> Build, Execution, Deployment -> Build Tools -> Gradle -> Runner)
+
+### Requirements
+
+* JDK >= 1.8 referred to by the `JAVA_HOME` environment variable.
+* JDK 1.6 referred to by the `JDK_16` environment variable.
+
 ## Contributions and releases
 
 All development (both new features and bug fixes) is performed in `develop` branch. 
diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ChannelCopyBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/ChannelCopyBenchmark.kt
index cf2e043..8a41d03 100644
--- a/benchmarks/src/jmh/kotlin/benchmarks/ChannelCopyBenchmark.kt
+++ b/benchmarks/src/jmh/kotlin/benchmarks/ChannelCopyBenchmark.kt
@@ -169,7 +169,7 @@
         val pIn = ByteChannel(true)
         val pOut = ByteChannel(true)
 
-        launch(coroutineContext) {
+        launch(this.coroutineContext) {
             pOut.joinTo(pIn, true)
         }
 
@@ -193,7 +193,7 @@
         val pIn = ByteChannel(true)
         val pOut = ByteChannel(true)
 
-        launch(coroutineContext) {
+        launch(this.coroutineContext) {
             pOut.joinTo(pIn, true)
         }
 
@@ -217,7 +217,7 @@
         val pIn = ByteChannel(true)
         val pOut = ByteChannel(true)
 
-        launch(coroutineContext) {
+        launch(this.coroutineContext) {
             pOut.copyTo(pIn)
             pIn.close()
         }
@@ -242,7 +242,7 @@
         val pIn = ByteChannel(true)
         val pOut = ByteChannel(true)
 
-        launch(coroutineContext) {
+        launch(this.coroutineContext) {
             pOut.copyTo(pIn)
             pIn.close()
         }
@@ -298,7 +298,7 @@
 
     @Benchmark
     fun runBlockingAndLaunch() = runBlocking {
-        launch(coroutineContext) {
+        launch(this.coroutineContext) {
             yield()
         }
 
diff --git a/build.gradle b/build.gradle
index 922a3ec..32632ff 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,4 @@
 allprojects {
-    group = 'org.jetbrains.kotlinx'
     def deployVersion = properties['DeployVersion']
     if (deployVersion != null) version = deployVersion
 }
@@ -13,12 +12,14 @@
     }
     repositories {
         jcenter()
-        maven { url "http://kotlin.bintray.com/kotlinx" }
-        maven { url "http://kotlin.bintray.com/kotlin-dev" }
+        maven { url "https://kotlin.bintray.com/kotlinx" }
+        maven { url "https://kotlin.bintray.com/kotlin-dev" }
+        maven { url "https://jetbrains.bintray.com/kotlin-native-dependencies" }
         maven { url "https://plugins.gradle.org/m2/" }
     }
     dependencies {
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+        classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$kotlin_native_version"
         classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
         classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicFU_version"
         classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$bintray_version"
@@ -36,6 +37,7 @@
 static def platformOf(project) {
     if (project.name.endsWith("-common")) return "common"
     if (project.name.endsWith("-js")) return "js"
+    if (project.name.endsWith("-native")) return "native"
     return "jvm"
 }
 
@@ -46,93 +48,17 @@
 
 configure(subprojects.findAll { !sourceless.contains(it.name)  }) {
     def platform = platformOf(it)
-    apply plugin: "kotlin-platform-$platform"
-
-    if (platform == "jvm") {
-        sourceCompatibility = 1.6
-        targetCompatibility = 1.6
-    }
-
-    kotlin.experimental.coroutines "enable"
-
-    if (platform == "js") {
-        tasks.withType(compileKotlin2Js.getClass()) {
-            kotlinOptions {
-                moduleKind = "umd"
-                sourceMap = true
-                metaInfo = true
-                // drop -js suffix from outputFile
-                def baseName = project.name - "-js"
-                outputFile = new File(outputFile.parent, baseName + ".js")
-            }
-        }
-    }
-    
-    tasks.withType(Test) {
-        testLogging {
-            showStandardStreams = true
-            events "passed", "failed"
-        }
-        def stressTest = project.properties['stressTest']
-        if (stressTest != null) systemProperties['stressTest'] = stressTest
-    }
-
-    repositories {
-        jcenter()
-        maven { url "http://kotlin.bintray.com/kotlinx" }
-        maven { url "https://dl.bintray.com/devexperts/Maven/" }
-    }
-
-    def kotlin_stdlib = platformLib("kotlin-stdlib", platform)
-    def kotlin_test = platformLib("kotlin-test", platform)
-
-    dependencies {
-        compile "org.jetbrains.kotlin:$kotlin_stdlib:$kotlin_version"
-        testCompile "org.jetbrains.kotlin:$kotlin_test:$kotlin_version"
-    }
-
-    if (platform == "common") {
-        dependencies {
-            testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
-        }
-    }
-
-    if (platform == "jvm") {
-        dependencies {
-            testCompile "junit:junit:$junit_version"
-            testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
-        }
-    }
+    apply from: rootProject.file("gradle/compile-${platform}.gradle")
 }
 
 // --------------- Configure sub-projects that are part of the library ---------------
 
 def internal = sourceless + ['benchmarks', 'knit', 'js-stub']
 
-// configure atomicfu for JVM modules
-configure(subprojects.findAll { !internal.contains(it.name) && platformOf(it) == "jvm" }) {
-    apply plugin: 'kotlinx-atomicfu'
-
-    dependencies {
-        compileOnly "org.jetbrains.kotlinx:atomicfu:$atomicFU_version"
-        testCompile "org.jetbrains.kotlinx:atomicfu:$atomicFU_version"
-    }
-
-    atomicFU {
-        inputFiles = sourceSets.main.output.classesDirs
-        outputDir = file("$buildDir/classes-atomicfu/main")
-        classPath = sourceSets.main.runtimeClasspath
-    }
-
-    jar {
-        mainSpec.sourcePaths.clear() // hack to clear existing paths
-        from files(atomicFU.outputs, sourceSets.main.output.resourcesDir)
-    }
-
-    test {
-        classpath = files(configurations.testRuntime, atomicFU.outputs, sourceSets.test.output.classesDirs,
-                sourceSets.main.output.resourcesDir)
-    }
+// configure atomicfu
+configure(subprojects.findAll { !internal.contains(it.name) }) {
+    def platform = platformOf(it)
+    apply from: rootProject.file("gradle/atomicfu-${platform}.gradle")
 }
 
 // configure dependencies on core
@@ -155,7 +81,8 @@
 
 // --------------- Configure sub-projects that are published ---------------
 
-def unpublished = internal + ['kotlinx-coroutines-rx-example', 'example-frontend-js']
+// todo: native is not published yet
+def unpublished = internal + ['kotlinx-coroutines-rx-example', 'example-frontend-js', 'kotlinx-coroutines-core-native']
 
 def core_docs_url = "https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/"
 def core_docs_file = "$projectDir/core/kotlinx-coroutines-core/build/dokka/kotlinx-coroutines-core/package-list"
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/AbstractContinuation.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/AbstractContinuation.kt
similarity index 95%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/AbstractContinuation.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/AbstractContinuation.kt
index f747f02..67a7fc6 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/AbstractContinuation.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/AbstractContinuation.kt
@@ -16,10 +16,9 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlinx.atomicfu.atomic
-import kotlinx.atomicfu.loop
-import kotlin.coroutines.experimental.Continuation
-import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED
+import kotlinx.atomicfu.*
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
 
 private const val UNDECIDED = 0
 private const val SUSPENDED = 1
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/AbstractCoroutine.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/AbstractCoroutine.kt
index b1f1877..5143c15 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/AbstractCoroutine.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/AbstractCoroutine.kt
@@ -47,6 +47,7 @@
 ) : JobSupport(active), Job, Continuation<T>, CoroutineScope {
     @Suppress("LeakingThis")
     public final override val context: CoroutineContext = parentContext + this
+    @Deprecated("Replaced with context", replaceWith = ReplaceWith("context"))
     public final override val coroutineContext: CoroutineContext get() = context
 
     /**
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Annotations.common.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Annotations.common.kt
new file mode 100644
index 0000000..a0ea9b3
--- /dev/null
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Annotations.common.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+// NOTE: We are defining them in a special internalAnnotations package because they would break
+// user code that uses kotlinx.coroutines library otherwise, see https://youtrack.jetbrains.com/issue/KT-23727
+package kotlinx.coroutines.experimental.internalAnnotations
+
+@Target(AnnotationTarget.FILE)
+internal expect annotation class JvmName(val name: String)
+
+@Target(AnnotationTarget.FILE)
+internal expect annotation class JvmMultifileClass()
+
+internal expect annotation class JvmField()
+
+internal expect annotation class Volatile()
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Builders.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Builders.common.kt
similarity index 68%
rename from js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Builders.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Builders.common.kt
index a2af761..5c6d1f2 100644
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Builders.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Builders.common.kt
@@ -14,22 +14,26 @@
  * limitations under the License.
  */
 
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
+@file:JvmMultifileClass
+@file:JvmName("BuildersKt")
 
 package kotlinx.coroutines.experimental
 
+import kotlinx.coroutines.experimental.internalAnnotations.*
 import kotlinx.coroutines.experimental.intrinsics.*
 import kotlin.coroutines.experimental.*
 import kotlin.coroutines.experimental.intrinsics.*
 
+// --------------- basic coroutine builders ---------------
+
 /**
  * Launches new coroutine without blocking current thread and returns a reference to the coroutine as a [Job].
  * The coroutine is cancelled when the resulting job is [cancelled][Job.cancel].
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.coroutineContext] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
+ * of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
@@ -50,21 +54,49 @@
  * @param context context of the coroutine. The default value is [DefaultDispatcher].
  * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
  * @param parent explicitly specifies the parent job, overrides job from the [context] (if any).
+ * @param onCompletion optional completion handler for the coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
-public actual fun launch(
-        context: CoroutineContext = DefaultDispatcher,
-        start: CoroutineStart = CoroutineStart.DEFAULT,
-        parent: Job? = null,
-        block: suspend CoroutineScope.() -> Unit
+public fun launch(
+    context: CoroutineContext = DefaultDispatcher,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
+    parent: Job? = null,
+    onCompletion: CompletionHandler? = null,
+    block: suspend CoroutineScope.() -> Unit
 ): Job {
     val newContext = newCoroutineContext(context, parent)
     val coroutine = if (start.isLazy)
         LazyStandaloneCoroutine(newContext, block) else
         StandaloneCoroutine(newContext, active = true)
+    if (onCompletion != null) coroutine.invokeOnCompletion(handler = onCompletion)
     coroutine.start(start, coroutine, block)
     return coroutine
 }
+/** @suppress **Deprecated**: Binary compatibility */
+@Deprecated(message = "Binary compatibility", level = DeprecationLevel.HIDDEN)
+public fun launch(
+    context: CoroutineContext = DefaultDispatcher,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
+    parent: Job? = null,
+    block: suspend CoroutineScope.() -> Unit
+): Job = launch(context, start, parent, block = block)
+
+/** @suppress **Deprecated**: Binary compatibility */
+@Deprecated(message = "Binary compatibility", level = DeprecationLevel.HIDDEN)
+public fun launch(
+    context: CoroutineContext = DefaultDispatcher,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
+    block: suspend CoroutineScope.() -> Unit
+): Job =
+    launch(context, start, block = block)
+
+/**
+ * @suppress **Deprecated**: Use `start = CoroutineStart.XXX` parameter
+ */
+@Deprecated(message = "Use `start = CoroutineStart.XXX` parameter",
+    replaceWith = ReplaceWith("launch(context, if (start) CoroutineStart.DEFAULT else CoroutineStart.LAZY, block)"))
+public fun launch(context: CoroutineContext, start: Boolean, block: suspend CoroutineScope.() -> Unit): Job =
+    launch(context, if (start) CoroutineStart.DEFAULT else CoroutineStart.LAZY, block = block)
 
 /**
  * Calls the specified suspending block with a given coroutine context, suspends until it completes, and returns
@@ -82,7 +114,7 @@
  * Other options can be specified via `start` parameter. See [CoroutineStart] for details.
  * A value of [CoroutineStart.LAZY] is not supported and produces [IllegalArgumentException].
  */
-public actual suspend fun <T> withContext(
+public suspend fun <T> withContext(
     context: CoroutineContext,
     start: CoroutineStart = CoroutineStart.DEFAULT,
     block: suspend () -> T
@@ -107,17 +139,34 @@
     val completion = RunCompletion(
         context = newContext,
         delegate = cont,
-        resumeMode = if (start == CoroutineStart.ATOMIC) MODE_ATOMIC_DEFAULT else MODE_CANCELLABLE)
+        resumeMode = if (start == CoroutineStart.ATOMIC) MODE_ATOMIC_DEFAULT else MODE_CANCELLABLE
+    )
     completion.initParentJobInternal(newContext[Job]) // attach to job
+    @Suppress("DEPRECATION")
     start(block, completion)
     completion.getResult()
 }
 
+/** @suppress **Deprecated**: Renamed to [withContext]. */
+@Deprecated(message = "Renamed to `withContext`", level=DeprecationLevel.WARNING,
+    replaceWith = ReplaceWith("withContext(context, start, block)"))
+public suspend fun <T> run(
+    context: CoroutineContext,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
+    block: suspend () -> T
+): T =
+    withContext(context, start, block)
+
+/** @suppress **Deprecated** */
+@Deprecated(message = "It is here for binary compatibility only", level=DeprecationLevel.HIDDEN)
+public suspend fun <T> run(context: CoroutineContext, block: suspend () -> T): T =
+    withContext(context, start = CoroutineStart.ATOMIC, block = block)
+
 // --------------- implementation ---------------
 
 private open class StandaloneCoroutine(
-        private val parentContext: CoroutineContext,
-        active: Boolean
+    private val parentContext: CoroutineContext,
+    active: Boolean
 ) : AbstractCoroutine<Unit>(parentContext, active) {
     override fun hasOnFinishingHandler(update: Any?) = update is CompletedExceptionally
     override fun onFinishingInternal(update: Any?) {
@@ -127,8 +176,8 @@
 }
 
 private class LazyStandaloneCoroutine(
-        parentContext: CoroutineContext,
-        private val block: suspend CoroutineScope.() -> Unit
+    parentContext: CoroutineContext,
+    private val block: suspend CoroutineScope.() -> Unit
 ) : StandaloneCoroutine(parentContext, active = false) {
     override fun onStart() {
         block.startCoroutineCancellable(this, this)
@@ -140,12 +189,9 @@
     continuation: Continuation<T>
 ) : Continuation<T> by continuation
 
-
 @Suppress("UNCHECKED_CAST")
 private class RunCompletion<in T>(
     override val context: CoroutineContext,
     delegate: Continuation<T>,
     resumeMode: Int
 ) : AbstractContinuation<T>(delegate, resumeMode)
-
-
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt
similarity index 88%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt
index bba910f..3b4ff8a 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt
@@ -14,16 +14,12 @@
  * limitations under the License.
  */
 
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
-
 package kotlinx.coroutines.experimental
 
-import kotlinx.coroutines.experimental.internal.LockFreeLinkedListNode
-import kotlin.coroutines.experimental.Continuation
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn
-import kotlin.coroutines.experimental.suspendCoroutine
+import kotlinx.coroutines.experimental.internal.*
+import kotlinx.coroutines.experimental.internalAnnotations.*
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
 
 // --------------- cancellable continuations ---------------
 
@@ -61,24 +57,24 @@
  *
  * ```
  */
-public actual interface CancellableContinuation<in T> : Continuation<T>, Job {
+public interface CancellableContinuation<in T> : Continuation<T>, Job {
     /**
      * Returns `true` when this continuation is active -- it has not completed or cancelled yet.
      */
-    public actual override val isActive: Boolean
+    public override val isActive: Boolean
 
     /**
      * Returns `true` when this continuation has completed for any reason. A continuation
      * that was cancelled is also considered complete.
      */
-    public actual override val isCompleted: Boolean
+    public override val isCompleted: Boolean
 
     /**
      * Returns `true` if this continuation was [cancelled][cancel].
      *
      * It implies that [isActive] is `false` and [isCompleted] is `true`.
      */
-    public actual override val isCancelled: Boolean
+    public override val isCancelled: Boolean
 
     /**
      * Tries to resume this continuation with a given value and returns non-null object token if it was successful,
@@ -90,7 +86,7 @@
      *
      * @suppress **This is unstable API and it is subject to change.**
      */
-    public actual fun tryResume(value: T, idempotent: Any? = null): Any?
+    public fun tryResume(value: T, idempotent: Any? = null): Any?
 
     /**
      * Tries to resume this continuation with a given exception and returns non-null object token if it was successful,
@@ -106,20 +102,20 @@
      *
      * @suppress **This is unstable API and it is subject to change.**
      */
-    public actual fun completeResume(token: Any)
+    public fun completeResume(token: Any)
 
     /**
      * Makes this continuation cancellable. Use it with `holdCancellability` optional parameter to
      * [suspendCancellableCoroutine] function. It throws [IllegalStateException] if invoked more than once.
      */
-    public actual fun initCancellability()
+    public fun initCancellability()
 
     /**
      * Cancels this continuation with an optional cancellation [cause]. The result is `true` if this continuation was
      * cancelled as a result of this invocation and `false` otherwise.
      */
     @Suppress("DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE")
-    public actual override fun cancel(cause: Throwable? = null): Boolean
+    public override fun cancel(cause: Throwable? = null): Boolean
 
     /**
      * Registers handler that is **synchronously** invoked once on completion of this continuation.
@@ -135,7 +131,7 @@
      * Installed [handler] should not throw any exceptions. If it does, they will get caught,
      * wrapped into [CompletionHandlerException], and rethrown, potentially causing crash of unrelated code.
      */
-    public actual override fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle
+    public override fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle
 
     /**
      * Resumes this continuation with a given [value] in the invoker thread without going though
@@ -143,7 +139,7 @@
      * This function is designed to be used only by the [CoroutineDispatcher] implementations themselves.
      * **It should not be used in general code**.
      */
-    public actual fun CoroutineDispatcher.resumeUndispatched(value: T)
+    public fun CoroutineDispatcher.resumeUndispatched(value: T)
 
     /**
      * Resumes this continuation with a given [exception] in the invoker thread without going though
@@ -151,7 +147,7 @@
      * This function is designed to be used only by the [CoroutineDispatcher] implementations themselves.
      * **It should not be used in general code**.
      */
-    public actual fun CoroutineDispatcher.resumeUndispatchedWithException(exception: Throwable)
+    public fun CoroutineDispatcher.resumeUndispatchedWithException(exception: Throwable)
 }
 
 /**
@@ -163,7 +159,7 @@
  *
  * See [suspendAtomicCancellableCoroutine] for suspending functions that need *atomic cancellation*.
  */
-public actual inline suspend fun <T> suspendCancellableCoroutine(
+public suspend inline fun <T> suspendCancellableCoroutine(
     holdCancellability: Boolean = false,
     crossinline block: (CancellableContinuation<T>) -> Unit
 ): T =
@@ -172,7 +168,7 @@
         if (!holdCancellability) cancellable.initCancellability()
         block(cancellable)
         cancellable.getResult()
-}
+    }
 
 /**
  * Suspends coroutine similar to [suspendCancellableCoroutine], but with *atomic cancellation*.
@@ -182,7 +178,7 @@
  * continue to execute even after it was cancelled from the same thread in the case when the continuation
  * was already resumed and was posted for execution to the thread's queue.
  */
-public actual inline suspend fun <T> suspendAtomicCancellableCoroutine(
+public suspend inline fun <T> suspendAtomicCancellableCoroutine(
     holdCancellability: Boolean = false,
     crossinline block: (CancellableContinuation<T>) -> Unit
 ): T =
@@ -198,15 +194,15 @@
  * @suppress **This is unstable API and it is subject to change.**
  */
 public fun CancellableContinuation<*>.removeOnCancel(node: LockFreeLinkedListNode): DisposableHandle =
-    invokeOnCompletion(handler = RemoveOnCancel(this, node))
+    invokeOnCompletion(handler = RemoveOnCancel(this, node).asHandler)
 
 // --------------- implementation details ---------------
 
 private class RemoveOnCancel(
     cont: CancellableContinuation<*>,
-    val node: LockFreeLinkedListNode
+    @JvmField val node: LockFreeLinkedListNode
 ) : JobNode<CancellableContinuation<*>>(cont)  {
-    override fun invoke(reason: Throwable?) {
+    override fun invoke(cause: Throwable?) {
         if (job.isCancelled)
             node.remove()
     }
@@ -283,12 +279,16 @@
 
     override fun nameString(): String =
         "CancellableContinuation(${delegate.toDebugString()})"
+
+    // todo: This workaround for KT-21968, should be removed in the future
+    public override fun cancel(cause: Throwable?): Boolean =
+        super.cancel(cause)
 }
 
 private class CompletedIdempotentResult(
     @JvmField val idempotentResume: Any?,
     @JvmField val result: Any?,
-    @JvmField val token: JobSupport.Incomplete
+    @JvmField val token: Incomplete
 ) {
     override fun toString(): String = "CompletedIdempotentResult[$result]"
 }
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonBuilders.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonBuilders.kt
deleted file mode 100644
index 924910b..0000000
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonBuilders.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.CoroutineContext
-
-@Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-public expect fun launch(
-    context: CoroutineContext = DefaultDispatcher,
-    start: CoroutineStart = CoroutineStart.DEFAULT,
-    parent: Job? = null,
-    block: suspend CoroutineScope.() -> Unit
-): Job
-
-@Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-public expect suspend fun <T> withContext(
-    context: CoroutineContext,
-    start: CoroutineStart = CoroutineStart.DEFAULT,
-    block: suspend () -> T
-): T
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCancellableContinuation.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCancellableContinuation.kt
deleted file mode 100644
index 663cc58..0000000
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCancellableContinuation.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.Continuation
-
-public expect interface CancellableContinuation<in T> : Continuation<T> {
-    public val isActive: Boolean
-    public val isCompleted: Boolean
-    public val isCancelled: Boolean
-    @Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-    public fun tryResume(value: T, idempotent: Any? = null): Any?
-    public fun completeResume(token: Any)
-    public fun initCancellability()
-    @Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-    public actual fun cancel(cause: Throwable? = null): Boolean
-    public fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle
-    public fun CoroutineDispatcher.resumeUndispatched(value: T)
-    public fun CoroutineDispatcher.resumeUndispatchedWithException(exception: Throwable)
-}
-
-@Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-public expect suspend fun <T> suspendCancellableCoroutine(
-    holdCancellability: Boolean = false,
-    block: (CancellableContinuation<T>) -> Unit
-): T
-
-@Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-public expect suspend fun <T> suspendAtomicCancellableCoroutine(
-    holdCancellability: Boolean = false,
-    block: (CancellableContinuation<T>) -> Unit
-): T
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCompletableDeferred.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCompletableDeferred.kt
deleted file mode 100644
index c24c4a1..0000000
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCompletableDeferred.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-public expect interface CompletableDeferred<T> : Deferred<T> {
-    public fun complete(value: T): Boolean
-    public fun completeExceptionally(exception: Throwable): Boolean
-}
-
-@Suppress("FunctionName", "EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-public expect fun <T> CompletableDeferred(parent: Job? = null): CompletableDeferred<T>
-
-@Suppress("FunctionName", "EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-public expect fun <T> CompletableDeferred(value: T): CompletableDeferred<T>
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineDispatcher.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineDispatcher.kt
deleted file mode 100644
index e184307..0000000
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineDispatcher.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.*
-
-public expect abstract class CoroutineDispatcher constructor() : AbstractCoroutineContextElement, ContinuationInterceptor {
-    public open fun isDispatchNeeded(context: CoroutineContext): Boolean
-    public abstract fun dispatch(context: CoroutineContext, block: Runnable)
-    public override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T>
-}
-
-public expect interface Runnable {
-    public fun run()
-}
-
-@Suppress("PropertyName")
-public expect val DefaultDispatcher: CoroutineDispatcher
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineExceptionHandler.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineExceptionHandler.kt
deleted file mode 100644
index 2141027..0000000
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineExceptionHandler.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.CoroutineContext
-
-public expect fun handleCoroutineException(context: CoroutineContext, exception: Throwable)
-
-public expect interface CoroutineExceptionHandler : CoroutineContext.Element {
-    public companion object Key : CoroutineContext.Key<CoroutineExceptionHandler>
-    public fun handleException(context: CoroutineContext, exception: Throwable)
-}
-
-@Suppress("FunctionName")
-public expect fun CoroutineExceptionHandler(handler: (CoroutineContext, Throwable) -> Unit): CoroutineExceptionHandler
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineScope.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineScope.kt
deleted file mode 100644
index c523800..0000000
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineScope.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.CoroutineContext
-
-public expect interface CoroutineScope {
-    public val isActive: Boolean
-    public val coroutineContext: CoroutineContext
-}
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonDeferred.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonDeferred.kt
deleted file mode 100644
index fbabf3d..0000000
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonDeferred.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.CoroutineContext
-
-public expect interface Deferred<out T> : Job {
-    public val isCompletedExceptionally: Boolean
-    public suspend fun await(): T
-    public fun getCompleted(): T
-    public fun getCompletionExceptionOrNull(): Throwable?
-}
-
-@Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-public expect fun <T> async(
-    context: CoroutineContext = DefaultDispatcher,
-    start: CoroutineStart = CoroutineStart.DEFAULT,
-    parent: Job? = null,
-    block: suspend CoroutineScope.() -> T
-): Deferred<T>
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonJob.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonJob.kt
deleted file mode 100644
index c6d22d0..0000000
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonJob.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.CoroutineContext
-
-expect public interface Job : CoroutineContext.Element {
-    public companion object Key : CoroutineContext.Key<Job>
-    public val isActive: Boolean
-    public val isCompleted: Boolean
-    public val isCancelled: Boolean
-    public fun getCancellationException(): CancellationException
-    public fun start(): Boolean
-    @Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-    public fun cancel(cause: Throwable? = null): Boolean
-    public val children: Sequence<Job>
-    @Deprecated(message = "Start child coroutine with 'parent' parameter", level = DeprecationLevel.WARNING)
-    public fun attachChild(child: Job): DisposableHandle
-    public suspend fun join()
-    @Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-    public actual fun invokeOnCompletion(
-        onCancelling: Boolean = false,
-        invokeImmediately: Boolean = true,
-        handler: CompletionHandler): DisposableHandle
-}
-
-@Suppress("FunctionName", "EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-public expect fun Job(parent: Job? = null): Job
-
-public expect interface DisposableHandle {
-    public fun dispose()
-}
-
-@Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-public expect fun CoroutineContext.cancel(cause: Throwable? = null): Boolean
-@Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
-public expect fun CoroutineContext.cancelChildren(cause: Throwable? = null)
-
-public expect fun Job.disposeOnCompletion(handle: DisposableHandle): DisposableHandle
-public expect suspend fun Job.cancelAndJoin()
-@Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER", "EXTENSION_SHADOWED_BY_MEMBER") // See KT-21598
-public expect fun Job.cancelChildren(cause: Throwable? = null)
-public expect suspend fun Job.joinChildren()
-
-public expect object NonDisposableHandle : DisposableHandle {
-    override fun dispose()
-}
-
-internal expect open class JobSupport(active: Boolean) : Job {
-    public final override val key: CoroutineContext.Key<*>
-    public final override val isActive: Boolean
-    public final override val isCompleted: Boolean
-    public final override val isCancelled: Boolean
-
-    public final override fun getCancellationException(): CancellationException
-    public final override fun start(): Boolean
-    public final override val children: Sequence<Job>
-
-    public override fun cancel(cause: Throwable?): Boolean
-
-    public final override fun attachChild(child: Job): DisposableHandle
-    public final override suspend fun join()
-
-    // todo: non-final as a workaround for KT-21968, should be final in the future
-    public override fun invokeOnCompletion(
-        onCancelling: Boolean,
-        invokeImmediately: Boolean,
-        handler: CompletionHandler
-    ): DisposableHandle
-
-    public val isCompletedExceptionally: Boolean
-    public fun getCompletionExceptionOrNull(): Throwable?
-
-    internal fun initParentJobInternal(parent: Job?)
-    internal fun makeCompletingOnce(proposedUpdate: Any?, mode: Int): Boolean
-    internal open fun hasOnFinishingHandler(update: Any?): Boolean
-    internal open fun onFinishingInternal(update: Any?)
-    internal open fun onCompletionInternal(state: Any?, mode: Int)
-    internal open fun onStartInternal()
-    internal open fun onCancellationInternal(exceptionally: CompletedExceptionally?)
-    internal open fun nameString(): String
-    internal open fun handleException(exception: Throwable)
-}
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonNonCancellable.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonNonCancellable.kt
deleted file mode 100644
index 756c06e..0000000
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonNonCancellable.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-public expect object NonCancellable : Job {
-    override val isActive: Boolean
-    override val isCompleted: Boolean
-    override val isCancelled: Boolean
-    override fun start(): Boolean
-    suspend override fun join()
-    override fun getCancellationException(): CancellationException
-    override fun invokeOnCompletion(onCancelling: Boolean, invokeImmediately: Boolean, handler: CompletionHandler): DisposableHandle
-    override fun cancel(cause: Throwable?): Boolean
-    override val children: Sequence<Job>
-    @Suppress("OverridingDeprecatedMember")
-    override fun attachChild(child: Job): DisposableHandle
-}
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CompletableDeferred.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CompletableDeferred.kt
similarity index 85%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CompletableDeferred.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CompletableDeferred.kt
index af61dd9..d1d8894 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CompletableDeferred.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CompletableDeferred.kt
@@ -14,9 +14,6 @@
  * limitations under the License.
  */
 
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
-
 package kotlinx.coroutines.experimental
 
 import kotlinx.coroutines.experimental.selects.*
@@ -32,14 +29,14 @@
  * All functions on this interface and on all interfaces derived from it are **thread-safe** and can
  * be safely invoked from concurrent coroutines without external synchronization.
  */
-public actual interface CompletableDeferred<T> : Deferred<T> {
+public interface CompletableDeferred<T> : Deferred<T> {
     /**
      * Completes this deferred value with a given [value]. The result is `true` if this deferred was
      * completed as a result of this invocation and `false` otherwise (if it was already completed).
      *
      * Repeated invocations of this function have no effect and always produce `false`.
      */
-    public actual fun complete(value: T): Boolean
+    public fun complete(value: T): Boolean
 
     /**
      * Completes this deferred value exceptionally with a given [exception]. The result is `true` if this deferred was
@@ -47,7 +44,7 @@
      *
      * Repeated invocations of this function have no effect and always produce `false`.
      */
-    public actual fun completeExceptionally(exception: Throwable): Boolean
+    public fun completeExceptionally(exception: Throwable): Boolean
 }
 
 /**
@@ -55,7 +52,7 @@
  * It is optionally a child of a [parent] job.
  */
 @Suppress("FunctionName")
-public actual fun <T> CompletableDeferred(parent: Job? = null): CompletableDeferred<T> = CompletableDeferredImpl(parent)
+public fun <T> CompletableDeferred(parent: Job? = null): CompletableDeferred<T> = CompletableDeferredImpl(parent)
 
 /** @suppress **Deprecated:** Binary compatibility only */
 @Deprecated(message = "Binary compatibility only", level = DeprecationLevel.HIDDEN)
@@ -66,7 +63,7 @@
  * Creates an already _completed_ [CompletableDeferred] with a given [value].
  */
 @Suppress("FunctionName")
-public actual fun <T> CompletableDeferred(value: T): CompletableDeferred<T> = CompletableDeferredImpl<T>(null).apply { complete(value) }
+public fun <T> CompletableDeferred(value: T): CompletableDeferred<T> = CompletableDeferredImpl<T>(null).apply { complete(value) }
 
 /**
  * Concrete implementation of [CompletableDeferred].
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CompletedExceptionally.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CompletedExceptionally.kt
index 8984a28..8e3276e 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CompletedExceptionally.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CompletedExceptionally.kt
@@ -16,6 +16,8 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlinx.coroutines.experimental.internalAnnotations.*
+
 /**
  * Class for an internal state of a job that had completed exceptionally, including cancellation.
  *
@@ -27,7 +29,7 @@
  * @suppress **This is unstable API and it is subject to change.**
  */
 public open class CompletedExceptionally protected constructor(
-    public val cause: Throwable?,
+    @JvmField public val cause: Throwable?,
     allowNullCause: Boolean
 ) {
     /**
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCompletionHandler.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CompletionHandler.common.kt
similarity index 65%
rename from common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCompletionHandler.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CompletionHandler.common.kt
index d039861..dc2fd9a 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCompletionHandler.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CompletionHandler.common.kt
@@ -16,6 +16,8 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlinx.coroutines.experimental.internal.*
+
 /**
  * Handler for [Job.invokeOnCompletion].
  *
@@ -28,3 +30,14 @@
  * Implementations of `CompletionHandler` must be fast and _lock-free_.
  */
 public typealias CompletionHandler = (cause: Throwable?) -> Unit
+
+// We want class that extends LockFreeLinkedListNode & CompletionHandler but we cannot do it on Kotlin/JS,
+// so this expect class provides us with the corresponding abstraction in a platform-agnostic way.
+internal expect abstract class CompletionHandlerNode() : LockFreeLinkedListNode {
+    val asHandler: CompletionHandler
+    abstract fun invoke(cause: Throwable?)
+}
+
+// :KLUDGE: We have to invoke a handler in platform-specific way via `invokeIt` extension,
+// because we play type tricks on Kotlin/JS and handler is not necessarily a function there
+internal expect fun CompletionHandler.invokeIt(cause: Throwable?)
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineContext.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.common.kt
similarity index 74%
rename from common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineContext.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.common.kt
index c9aa202..a60cec0 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonCoroutineContext.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.common.kt
@@ -18,10 +18,14 @@
 
 import kotlin.coroutines.experimental.*
 
-public expect object Unconfined : CoroutineDispatcher {
-    override fun isDispatchNeeded(context: CoroutineContext): Boolean
-    override fun dispatch(context: CoroutineContext, block: Runnable)
-}
+@Suppress("EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER")
+public expect fun newCoroutineContext(context: CoroutineContext, parent: Job? = null): CoroutineContext
+
+@Suppress("PropertyName")
+public expect val DefaultDispatcher: CoroutineDispatcher
+
+@Suppress("PropertyName")
+internal expect val DefaultDelay: Delay
 
 internal expect inline fun <T> withCoroutineContext(context: CoroutineContext, block: () -> T): T
 internal expect fun Continuation<*>.toDebugString(): String
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineDispatcher.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineDispatcher.kt
similarity index 89%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineDispatcher.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineDispatcher.kt
index feb4b0d..9b98ba4 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineDispatcher.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineDispatcher.kt
@@ -37,7 +37,7 @@
  *
  * This class ensures that debugging facilities in [newCoroutineContext] function work properly.
  */
-public actual abstract class CoroutineDispatcher actual constructor() :
+public abstract class CoroutineDispatcher :
     AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
     /**
      * Returns `true` if execution shall be dispatched onto another thread.
@@ -70,17 +70,17 @@
      * parameter that allows one to optionally choose C#-style [CoroutineStart.UNDISPATCHED] behaviour
      * whenever it is needed for efficiency.
      */
-    public actual open fun isDispatchNeeded(context: CoroutineContext): Boolean = true
+    public open fun isDispatchNeeded(context: CoroutineContext): Boolean = true
 
     /**
      * Dispatches execution of a runnable [block] onto another thread in the given [context].
      */
-    public actual abstract fun dispatch(context: CoroutineContext, block: Runnable)
+    public abstract fun dispatch(context: CoroutineContext, block: Runnable)
 
     /**
      * Returns continuation that wraps the original [continuation], thus intercepting all resumptions.
      */
-    public actual override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
+    public override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
         DispatchedContinuation(this, continuation)
 
     /**
@@ -98,11 +98,6 @@
     public operator fun plus(other: CoroutineDispatcher) = other
 
     // for nicer debugging
-    override fun toString(): String =
-        "${this::class.java.simpleName}@${Integer.toHexString(System.identityHashCode(this))}"
+    override fun toString(): String = "$classSimpleName@$hexAddress"
 }
 
-/**
- * A runnable task for [CoroutineDispatcher.dispatch].
- */
-public actual typealias Runnable = java.lang.Runnable
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandler.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandler.kt
similarity index 69%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandler.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandler.kt
index 2bb0cc7..44e60fd 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandler.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandler.kt
@@ -16,9 +16,9 @@
 
 package kotlinx.coroutines.experimental
 
-import java.util.*
-import kotlin.coroutines.experimental.AbstractCoroutineContextElement
-import kotlin.coroutines.experimental.CoroutineContext
+import kotlin.coroutines.experimental.*
+
+internal expect fun handleCoroutineExceptionImpl(context: CoroutineContext, exception: Throwable)
 
 /**
  * Helper function for coroutine builder implementations to handle uncaught exception in coroutines.
@@ -32,7 +32,7 @@
  *     * all instances of [CoroutineExceptionHandler] found via [ServiceLoader] are invoked;
  *     * current thread's [Thread.uncaughtExceptionHandler] is invoked.
  */
-public actual fun handleCoroutineException(context: CoroutineContext, exception: Throwable) {
+public fun handleCoroutineException(context: CoroutineContext, exception: Throwable) {
     // if exception handling fails, make sure the original exception is not lost
     try {
         context[CoroutineExceptionHandler]?.let {
@@ -43,24 +43,30 @@
         if (exception is CancellationException) return
         // try cancel job in the context
         context[Job]?.cancel(exception)
-        // use additional extension handlers
-        ServiceLoader.load(CoroutineExceptionHandler::class.java).forEach { handler ->
-            handler.handleException(context, exception)
-        }
-        // use thread's handler
-        val currentThread = Thread.currentThread()
-        currentThread.uncaughtExceptionHandler.uncaughtException(currentThread, exception)
+        // platform-specific
+        handleCoroutineExceptionImpl(context, exception)
     } catch (handlerException: Throwable) {
         // simply rethrow if handler threw the original exception
         if (handlerException === exception) throw exception
         // handler itself crashed for some other reason -- that is bad -- keep both
         throw RuntimeException("Exception while trying to handle coroutine exception", exception).apply {
-            addSuppressed(handlerException)
+            addSuppressedThrowable(handlerException)
         }
     }
 }
 
 /**
+ * Creates new [CoroutineExceptionHandler] instance.
+ * @param handler a function which handles exception thrown by a coroutine
+ */
+@Suppress("FunctionName")
+public inline fun CoroutineExceptionHandler(crossinline handler: (CoroutineContext, Throwable) -> Unit): CoroutineExceptionHandler =
+    object: AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler {
+        override fun handleException(context: CoroutineContext, exception: Throwable) =
+            handler.invoke(context, exception)
+    }
+
+/**
  * An optional element on the coroutine context to handle uncaught exceptions.
  *
  * By default, when no handler is installed, uncaught exception are handled in the following way:
@@ -73,35 +79,15 @@
  *
  * See [handleCoroutineException].
  */
-public actual interface CoroutineExceptionHandler : CoroutineContext.Element {
+public interface CoroutineExceptionHandler : CoroutineContext.Element {
     /**
      * Key for [CoroutineExceptionHandler] instance in the coroutine context.
      */
-    public actual companion object Key : CoroutineContext.Key<CoroutineExceptionHandler> {
-        /**
-         * Creates new [CoroutineExceptionHandler] instance.
-         * @param handler a function which handles exception thrown by a coroutine
-         * @suppress **Deprecated**
-         */
-        @Deprecated("Replaced with top-level function", level = DeprecationLevel.HIDDEN)
-        public operator inline fun invoke(crossinline handler: (CoroutineContext, Throwable) -> Unit): CoroutineExceptionHandler =
-           CoroutineExceptionHandler(handler)
-    }
+    public companion object Key : CoroutineContext.Key<CoroutineExceptionHandler>
 
     /**
      * Handles uncaught [exception] in the given [context]. It is invoked
      * if coroutine has an uncaught exception. See [handleCoroutineException].
      */
-    public actual fun handleException(context: CoroutineContext, exception: Throwable)
+    public fun handleException(context: CoroutineContext, exception: Throwable)
 }
-
-/**
- * Creates new [CoroutineExceptionHandler] instance.
- * @param handler a function which handles exception thrown by a coroutine
- */
-@Suppress("FunctionName")
-public actual inline fun CoroutineExceptionHandler(crossinline handler: (CoroutineContext, Throwable) -> Unit): CoroutineExceptionHandler =
-    object: AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler {
-        override fun handleException(context: CoroutineContext, exception: Throwable) =
-            handler.invoke(context, exception)
-    }
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineScope.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineScope.kt
new file mode 100644
index 0000000..875574a
--- /dev/null
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineScope.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package kotlinx.coroutines.experimental
+
+import kotlin.coroutines.experimental.*
+import kotlin.internal.*
+
+/**
+ * Receiver interface for generic coroutine builders, so that the code inside coroutine has a convenient
+ * and fast access to its own cancellation status via [isActive].
+ */
+public interface CoroutineScope {
+    /**
+     * Returns `true` when this coroutine is still active (has not completed and was not cancelled yet).
+     *
+     * Check this property in long-running computation loops to support cancellation:
+     * ```
+     * while (isActive) {
+     *     // do some computation
+     * }
+     * ```
+     *
+     * This property is a shortcut for `coroutineContext.isActive` in the scope when
+     * [CoroutineScope] is available.
+     * See [coroutineContext][kotlin.coroutines.experimental.coroutineContext],
+     * [isActive][kotlinx.coroutines.experimental.isActive] and [Job.isActive].
+     */
+    public val isActive: Boolean
+
+    /**
+     * Returns the context of this coroutine.
+     *
+     * @suppress: **Deprecated**: Replaced with top-level [kotlin.coroutines.experimental.coroutineContext].
+     */
+    @Deprecated("Replace with top-level coroutineContext",
+        replaceWith = ReplaceWith("coroutineContext",
+            imports = ["kotlin.coroutines.experimental.coroutineContext"]))
+    @LowPriorityInOverloadResolution
+    @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
+    public val coroutineContext: CoroutineContext
+}
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonDebug.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Debug.common.kt
similarity index 93%
rename from common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonDebug.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Debug.common.kt
index 3143a1f..b6fb337 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonDebug.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Debug.common.kt
@@ -16,4 +16,5 @@
 
 package kotlinx.coroutines.experimental
 
-internal expect val Any.classSimpleName: String
\ No newline at end of file
+internal expect val Any.hexAddress: String
+internal expect val Any.classSimpleName: String
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt
similarity index 88%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt
index fd0edfc..3f15e8a 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt
@@ -14,9 +14,6 @@
  * limitations under the License.
  */
 
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
-
 package kotlinx.coroutines.experimental
 
 import kotlinx.coroutines.experimental.intrinsics.*
@@ -66,8 +63,9 @@
  *  +-----------+
  * ```
  *
- * A deferred value is a [Job]. A job in the coroutine [context][CoroutineScope.coroutineContext] of [async] builder
- * represents the coroutine itself.
+ * A deferred value is a [Job]. A job in the
+ * [coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
+ * of [async] builder represents the coroutine itself.
  * A deferred value is active while the coroutine is working and cancellation aborts the coroutine when
  * the coroutine is suspended on a _cancellable_ suspension point by throwing [CancellationException]
  * or the cancellation cause inside the coroutine.
@@ -80,14 +78,14 @@
  * All functions on this interface and on all interfaces derived from it are **thread-safe** and can
  * be safely invoked from concurrent coroutines without external synchronization.
  */
-public actual interface Deferred<out T> : Job {
+public interface Deferred<out T> : Job {
     /**
      * Returns `true` if computation of this deferred value has _completed exceptionally_ -- it had
      * either _failed_ with exception during computation or was [cancelled][cancel].
      *
      * It implies that [isActive] is `false` and [isCompleted] is `true`.
      */
-    public actual val isCompletedExceptionally: Boolean
+    public val isCompletedExceptionally: Boolean
 
     /**
      * Awaits for completion of this value without blocking a thread and resumes when deferred computation is complete,
@@ -100,7 +98,7 @@
      * This function can be used in [select] invocation with [onAwait] clause.
      * Use [isCompleted] to check for completion of this deferred value without waiting.
      */
-    public actual suspend fun await(): T
+    public suspend fun await(): T
 
     /**
      * Clause for [select] expression of [await] suspending function that selects with the deferred value when it is
@@ -117,7 +115,7 @@
      * This function is designed to be used from [invokeOnCompletion] handlers, when there is an absolute certainty that
      * the value is already complete. See also [getCompletionExceptionOrNull].
      */
-    public actual fun getCompleted(): T
+    public fun getCompleted(): T
 
     /**
      * Returns *completion exception* result if this deferred [completed exceptionally][isCompletedExceptionally],
@@ -127,7 +125,7 @@
      * This function is designed to be used from [invokeOnCompletion] handlers, when there is an absolute certainty that
      * the value is already complete. See also [getCompleted].
      */
-    public actual fun getCompletionExceptionOrNull(): Throwable?
+    public fun getCompletionExceptionOrNull(): Throwable?
 
     /**
      * @suppress **Deprecated**: Use `isActive`.
@@ -143,7 +141,8 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.coroutineContext] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
+ * of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
@@ -157,19 +156,22 @@
  *
  * @param context context of the coroutine. The default value is [DefaultDispatcher].
  * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
- * @param parent explicitly specifies the parent job, overrides job from the [context] (if any).*
+ * @param parent explicitly specifies the parent job, overrides job from the [context] (if any).
+ * @param onCompletion optional completion handler for the coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
-public actual fun <T> async(
+public fun <T> async(
     context: CoroutineContext = DefaultDispatcher,
     start: CoroutineStart = CoroutineStart.DEFAULT,
     parent: Job? = null,
+    onCompletion: CompletionHandler? = null,
     block: suspend CoroutineScope.() -> T
 ): Deferred<T> {
     val newContext = newCoroutineContext(context, parent)
     val coroutine = if (start.isLazy)
         LazyDeferredCoroutine(newContext, block) else
         DeferredCoroutine<T>(newContext, active = true)
+    if (onCompletion != null) coroutine.invokeOnCompletion(handler = onCompletion)
     coroutine.start(start, coroutine, block)
     return coroutine
 }
@@ -179,6 +181,15 @@
 public fun <T> async(
     context: CoroutineContext = DefaultDispatcher,
     start: CoroutineStart = CoroutineStart.DEFAULT,
+    parent: Job? = null,
+    block: suspend CoroutineScope.() -> T
+): Deferred<T> = async(context, start, parent, block = block)
+
+/** @suppress **Deprecated**: Binary compatibility */
+@Deprecated(message = "Binary compatibility", level = DeprecationLevel.HIDDEN)
+public fun <T> async(
+    context: CoroutineContext = DefaultDispatcher,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
     block: suspend CoroutineScope.() -> T
 ): Deferred<T> =
     async(context, start, block = block)
@@ -195,7 +206,7 @@
  * @suppress **Deprecated**: `defer` was renamed to `async`.
  */
 @Deprecated(message = "`defer` was renamed to `async`", level = DeprecationLevel.WARNING,
-        replaceWith = ReplaceWith("async(context, block = block)"))
+    replaceWith = ReplaceWith("async(context, block = block)"))
 public fun <T> defer(context: CoroutineContext, block: suspend CoroutineScope.() -> T): Deferred<T> =
     async(context, block = block)
 
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Delay.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Delay.kt
similarity index 84%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Delay.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Delay.kt
index 8d1e01e..25775d1 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Delay.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Delay.kt
@@ -16,12 +16,9 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlinx.coroutines.experimental.selects.SelectBuilder
-import kotlinx.coroutines.experimental.selects.select
-import java.util.concurrent.Future
-import java.util.concurrent.TimeUnit
-import kotlin.coroutines.experimental.ContinuationInterceptor
-import kotlin.coroutines.experimental.CoroutineContext
+import kotlinx.coroutines.experimental.selects.*
+import kotlinx.coroutines.experimental.timeunit.*
+import kotlin.coroutines.experimental.*
 
 /**
  * This dispatcher _feature_ is implemented by [CoroutineDispatcher] implementations that natively support
@@ -30,7 +27,7 @@
  * Implementation of this interface affects operation of
  * [delay][kotlinx.coroutines.experimental.delay] and [withTimeout] functions.
  */
-public actual interface Delay {
+public interface Delay {
     /**
      * Delays coroutine for a given time without blocking a thread and resumes it after a specified time.
      * This suspending function is cancellable.
@@ -68,7 +65,7 @@
      * This implementation uses a built-in single-threaded scheduled executor service.
      */
     fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle =
-        DefaultExecutor.invokeOnTimeout(time, unit, block)
+        DefaultDelay.invokeOnTimeout(time, unit, block)
 }
 
 /**
@@ -84,7 +81,7 @@
  *
  * @param time time in milliseconds.
  */
-public actual suspend fun delay(time: Int) =
+public suspend fun delay(time: Int) =
     delay(time.toLong(), TimeUnit.MILLISECONDS)
 
 /**
@@ -109,16 +106,5 @@
     }
 }
 
-/**
- * An implementation of [DisposableHandle] that cancels the specified future on dispose.
- * @suppress **This is unstable API and it is subject to change.**
- */
-public class DisposableFutureHandle(private val future: Future<*>) : DisposableHandle {
-    override fun dispose() {
-        future.cancel(false)
-    }
-    override fun toString(): String = "DisposableFutureHandle[$future]"
-}
-
 /** Returns [Delay] implementation of the given context */
-internal val CoroutineContext.delay: Delay get() = get(ContinuationInterceptor) as? Delay ?: DefaultExecutor
+internal val CoroutineContext.delay: Delay get() = get(ContinuationInterceptor) as? Delay ?: DefaultDelay
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Dispatched.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Dispatched.kt
index ba29b44..e81e5a9 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Dispatched.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Dispatched.kt
@@ -17,14 +17,15 @@
 package kotlinx.coroutines.experimental
 
 import kotlinx.coroutines.experimental.internal.*
+import kotlinx.coroutines.experimental.internalAnnotations.*
 import kotlin.coroutines.experimental.*
 
 @Suppress("PrivatePropertyName")
 private val UNDEFINED = Symbol("UNDEFINED")
 
 internal class DispatchedContinuation<in T>(
-    val dispatcher: CoroutineDispatcher,
-    val continuation: Continuation<T>
+    @JvmField val dispatcher: CoroutineDispatcher,
+    @JvmField val continuation: Continuation<T>
 ) : Continuation<T> by continuation, DispatchedTask<T> {
     private var _state: Any? = UNDEFINED
     public override var resumeMode: Int = 0
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonExceptions.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Exceptions.common.kt
similarity index 92%
rename from common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonExceptions.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Exceptions.common.kt
index 437fc71..e2e67d3 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonExceptions.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Exceptions.common.kt
@@ -28,6 +28,6 @@
     val job: Job
 }
 
-public expect class TimeoutCancellationException public constructor(message: String)
+internal expect class DispatchException(message: String, cause: Throwable) : RuntimeException
 
-internal expect class DispatchException(message: String, cause: Throwable) : RuntimeException
\ No newline at end of file
+internal expect fun Throwable.addSuppressedThrowable(other: Throwable)
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt
similarity index 85%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt
index 8180cf2..e94e951 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
+@file:JvmMultifileClass
+@file:JvmName("JobKt")
 
 package kotlinx.coroutines.experimental
 
 import kotlinx.atomicfu.*
 import kotlinx.coroutines.experimental.internal.*
+import kotlinx.coroutines.experimental.internalAnnotations.*
 import kotlinx.coroutines.experimental.intrinsics.*
 import kotlinx.coroutines.experimental.selects.*
-import java.util.concurrent.*
 import kotlin.coroutines.experimental.*
 import kotlin.coroutines.experimental.intrinsics.*
 
@@ -73,7 +73,9 @@
  *  +-----------+
  * ```
  *
- * A job in the [coroutineContext][CoroutineScope.coroutineContext] represents the coroutine itself.
+ * A job in the
+ * [coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
+ * represents the coroutine itself.
  * A job is active while the coroutine is working and job's cancellation aborts the coroutine when
  * the coroutine is suspended on a _cancellable_ suspension point by throwing [CancellationException].
  *
@@ -85,11 +87,11 @@
  * All functions on this interface and on all interfaces derived from it are **thread-safe** and can
  * be safely invoked from concurrent coroutines without external synchronization.
  */
-public actual interface Job : CoroutineContext.Element {
+public interface Job : CoroutineContext.Element {
     /**
      * Key for [Job] instance in the coroutine context.
      */
-    public actual companion object Key : CoroutineContext.Key<Job> {
+    public companion object Key : CoroutineContext.Key<Job> {
         /**
          * Creates a new job object in _active_ state.
          * It is optionally a child of a [parent] job.
@@ -115,20 +117,20 @@
      * The job that is waiting for its [children] to complete is still considered to be active if it
      * was not cancelled.
      */
-    public actual val isActive: Boolean
+    public val isActive: Boolean
 
     /**
      * Returns `true` when this job has completed for any reason. A job that was cancelled and has
      * finished its execution is also considered complete. Job becomes complete only after
      * all its [children] complete.
      */
-    public actual val isCompleted: Boolean
+    public val isCompleted: Boolean
 
     /**
      * Returns `true` if this job was [cancelled][cancel]. In the general case, it does not imply that the
      * job has already [completed][isCompleted] (it may still be cancelling whatever it was doing).
      */
-    public actual val isCancelled: Boolean
+    public val isCancelled: Boolean
 
     /**
      * Returns [CancellationException] that signals the completion of this job. This function is
@@ -144,7 +146,7 @@
      * This function throws [IllegalStateException] when invoked on a job that has not
      * [completed][isCompleted] nor [cancelled][isCancelled] yet.
      */
-    public actual fun getCancellationException(): CancellationException
+    public fun getCancellationException(): CancellationException
 
     /**
      * @suppress **Deprecated**: Renamed to [getCancellationException]
@@ -160,7 +162,7 @@
      * The result `true` if this invocation actually started coroutine or `false`
      * if it was already started or completed.
      */
-    public actual fun start(): Boolean
+    public fun start(): Boolean
 
     /**
      * Cancels this job with an optional cancellation [cause]. The result is `true` if this job was
@@ -172,7 +174,7 @@
      * at the corresponding original cancellation site and passed into this method to aid in debugging by providing
      * both the context of cancellation and text description of the reason.
      */
-    public actual fun cancel(cause: Throwable? = null): Boolean
+    public fun cancel(cause: Throwable? = null): Boolean
 
     // ------------ parent-child ------------
 
@@ -193,7 +195,7 @@
      *   coroutine builders do not have uncaught exceptions by definition, since all their exceptions are
      *   caught and are encapsulated in their result.
      */
-    public actual val children: Sequence<Job>
+    public val children: Sequence<Job>
 
     /**
      * Attaches child job so that this job becomes its parent and
@@ -215,7 +217,7 @@
      * @suppress This is an internal API. This method is too error prone for public API.
      */
     @Deprecated(message = "Start child coroutine with 'parent' parameter", level = DeprecationLevel.WARNING)
-    public actual fun attachChild(child: Job): DisposableHandle
+    public fun attachChild(child: Job): DisposableHandle
 
     /**
      * Cancels all children jobs of this coroutine with the given [cause]. Unlike [cancel],
@@ -248,7 +250,7 @@
      *
      * There is [cancelAndJoin] function that combines an invocation of [cancel] and `join`.
      */
-    public actual suspend fun join()
+    public suspend fun join()
 
     /**
      * Clause for [select] expression of [join] suspending function that selects when the job is complete.
@@ -322,7 +324,7 @@
      *        when `false` then [NonDisposableHandle] is returned, but the [handler] is not invoked.
      * @param handler the handler.
      */
-    public actual fun invokeOnCompletion(
+    public fun invokeOnCompletion(
         onCancelling: Boolean = false,
         invokeImmediately: Boolean = true,
         handler: CompletionHandler): DisposableHandle
@@ -336,27 +338,10 @@
      */
     @Suppress("DeprecatedCallableAddReplaceWith")
     @Deprecated(message = "Operator '+' on two Job objects is meaningless. " +
-                    "Job is a coroutine context element and `+` is a set-sum operator for coroutine contexts. " +
-                    "The job to the right of `+` just replaces the job the left of `+`.",
-            level = DeprecationLevel.ERROR)
+        "Job is a coroutine context element and `+` is a set-sum operator for coroutine contexts. " +
+        "The job to the right of `+` just replaces the job the left of `+`.",
+        level = DeprecationLevel.ERROR)
     public operator fun plus(other: Job) = other
-
-    /**
-     * Registration object for [invokeOnCompletion]. It can be used to [unregister] if needed.
-     * There is no need to unregister after completion.
-     * @suppress **Deprecated**: Replace with `DisposableHandle`
-     */
-    @Deprecated(message = "Replace with `DisposableHandle`",
-        replaceWith = ReplaceWith("DisposableHandle"))
-    public interface Registration {
-        /**
-         * Unregisters completion handler.
-         * @suppress **Deprecated**: Replace with `dispose`
-         */
-        @Deprecated(message = "Replace with `dispose`",
-            replaceWith = ReplaceWith("dispose()"))
-        public fun unregister()
-    }
 }
 
 /**
@@ -364,26 +349,17 @@
  * It is optionally a child of a [parent] job.
  */
 @Suppress("FunctionName")
-public actual fun Job(parent: Job? = null): Job = JobImpl(parent)
+public fun Job(parent: Job? = null): Job = JobImpl(parent)
 
 /**
  * A handle to an allocated object that can be disposed to make it eligible for garbage collection.
  */
-@Suppress("DEPRECATION") // todo: remove when Job.Registration is removed
-public actual interface DisposableHandle : Job.Registration {
+public interface DisposableHandle {
     /**
      * Disposes the corresponding object, making it eligible for garbage collection.
      * Repeated invocation of this function has no effect.
      */
-    public actual fun dispose()
-
-    /**
-     * Unregisters completion handler.
-     * @suppress **Deprecated**: Replace with `dispose`
-     */
-    @Deprecated(message = "Replace with `dispose`",
-        replaceWith = ReplaceWith("dispose()"))
-    public override fun unregister() = dispose()
+    public fun dispose()
 }
 
 // -------------------- Job extensions --------------------
@@ -400,7 +376,7 @@
 @Deprecated(message = "Renamed to `disposeOnCompletion`",
     replaceWith = ReplaceWith("disposeOnCompletion(registration)"))
 public fun Job.unregisterOnCompletion(registration: DisposableHandle): DisposableHandle =
-    invokeOnCompletion(handler = DisposeOnCompletion(this, registration))
+    invokeOnCompletion(handler = DisposeOnCompletion(this, registration).asHandler)
 
 /**
  * Disposes a specified [handle] when this job is complete.
@@ -410,19 +386,8 @@
  * invokeOnCompletion { handle.dispose() }
  * ```
  */
-public actual fun Job.disposeOnCompletion(handle: DisposableHandle): DisposableHandle =
-    invokeOnCompletion(handler = DisposeOnCompletion(this, handle))
-
-/**
- * Cancels a specified [future] when this job is complete.
- *
- * This is a shortcut for the following code with slightly more efficient implementation (one fewer object created).
- * ```
- * invokeOnCompletion { future.cancel(false) }
- * ```
- */
-public fun Job.cancelFutureOnCompletion(future: Future<*>): DisposableHandle =
-    invokeOnCompletion(handler = CancelFutureOnCompletion(this, future))
+public fun Job.disposeOnCompletion(handle: DisposableHandle): DisposableHandle =
+    invokeOnCompletion(handler = DisposeOnCompletion(this, handle).asHandler)
 
 /**
  * Cancels the job and suspends invoking coroutine until the cancelled job is complete.
@@ -438,7 +403,7 @@
  *
  * This is a shortcut for the invocation of [cancel][Job.cancel] followed by [join][Job.join].
  */
-public actual suspend fun Job.cancelAndJoin() {
+public suspend fun Job.cancelAndJoin() {
     cancel()
     return join()
 }
@@ -448,7 +413,7 @@
  * for all of them. Unlike [Job.cancel] on this job as a whole, the state of this job itself is not affected.
  */
 @Suppress("EXTENSION_SHADOWED_BY_MEMBER") // See KT-21598
-public actual fun Job.cancelChildren(cause: Throwable? = null) {
+public fun Job.cancelChildren(cause: Throwable? = null) {
     children.forEach { it.cancel(cause) }
 }
 
@@ -457,18 +422,37 @@
  * [Job.join] for all of them. Unlike [Job.join] on this job as a whole, it does not wait until
  * this job is complete.
  */
-public actual suspend fun Job.joinChildren() {
+public suspend fun Job.joinChildren() {
     children.forEach { it.join() }
 }
 
 // -------------------- CoroutineContext extensions --------------------
 
 /**
+ * Returns `true` when the [Job] of the coroutine in this context is still active
+ * (has not completed and was not cancelled yet).
+ *
+ * Check this property in long-running computation loops to support cancellation
+ * when [CoroutineScope.isActive] is not available:
+ *
+ * ```
+ * while (coroutineContext.isActive) {
+ *     // do some computation
+ * }
+ * ```
+ *
+ * The `coroutineContext.isActive` expression is a shortcut for `coroutineContext[Job]?.isActive == true`.
+ * See [Job.isActive].
+ */
+public val CoroutineContext.isActive: Boolean
+    get() = this[Job]?.isActive == true
+
+/**
  * Cancels [Job] of this context with an optional cancellation [cause]. The result is `true` if the job was
  * cancelled as a result of this invocation and `false` if there is no job in the context or if it was already
  * cancelled or completed. See [Job.cancel] for details.
  */
-public actual fun CoroutineContext.cancel(cause: Throwable? = null): Boolean =
+public fun CoroutineContext.cancel(cause: Throwable? = null): Boolean =
     this[Job]?.cancel(cause) ?: false
 
 /**
@@ -476,8 +460,8 @@
  * It does not do anything if there is no job in the context or it has no children.
  * See [Job.cancelChildren] for details.
  */
-public actual fun CoroutineContext.cancelChildren(cause: Throwable? = null) {
-   this[Job]?.cancelChildren(cause)
+public fun CoroutineContext.cancelChildren(cause: Throwable? = null) {
+    this[Job]?.cancelChildren(cause)
 }
 
 /**
@@ -488,20 +472,11 @@
 public suspend fun Job.join() = this.join()
 
 /**
- * No-op implementation of [Job.Registration].
- * @suppress: **Deprecated**: Replace with [NonDisposableHandle]
- */
-@Deprecated(message = "Replace with `NonDisposableHandle`",
-    replaceWith = ReplaceWith("NonDisposableHandle"))
-@Suppress("unused")
-typealias EmptyRegistration = NonDisposableHandle
-
-/**
  * No-op implementation of [DisposableHandle].
  */
-public actual object NonDisposableHandle : DisposableHandle {
+public object NonDisposableHandle : DisposableHandle {
     /** Does not do anything. */
-    actual override fun dispose() {}
+    override fun dispose() {}
 
     /** Returns "NonDisposableHandle" string. */
     override fun toString(): String = "NonDisposableHandle"
@@ -519,8 +494,8 @@
  * @param active when `true` the job is created in _active_ state, when `false` in _new_ state. See [Job] for details.
  * @suppress **This is unstable API and it is subject to change.**
  */
-internal actual open class JobSupport actual constructor(active: Boolean) : Job, SelectClause0 {
-    actual final override val key: CoroutineContext.Key<*> get() = Job
+internal open class JobSupport constructor(active: Boolean) : Job, SelectClause0 {
+    final override val key: CoroutineContext.Key<*> get() = Job
 
     /*
        === Internal states ===
@@ -542,7 +517,7 @@
        === Transitions ===
 
            New states      Active states       Inactive states
-           
+
           +---------+       +---------+                          }
           | EMPTY_N | --+-> | EMPTY_A | ----+                    } Empty states
           +---------+   |   +---------+     |                    }
@@ -592,7 +567,7 @@
      * It shall be invoked at most once after construction after all other initialization.
      * @suppress **This is unstable API and it is subject to change.**
      */
-    internal actual fun initParentJobInternal(parent: Job?) {
+    internal fun initParentJobInternal(parent: Job?) {
         check(parentHandle == null)
         if (parent == null) {
             parentHandle = NonDisposableHandle
@@ -631,14 +606,14 @@
         }
     }
 
-    public actual final override val isActive: Boolean get() {
+    public final override val isActive: Boolean get() {
         val state = this.state
         return state is Incomplete && state.isActive
     }
 
-    public actual final override val isCompleted: Boolean get() = state !is Incomplete
+    public final override val isCompleted: Boolean get() = state !is Incomplete
 
-    public actual final override val isCancelled: Boolean get() {
+    public final override val isCancelled: Boolean get() {
         val state = this.state
         return state is Cancelled || (state is Finishing && state.cancelled != null)
     }
@@ -674,7 +649,7 @@
         if (proposedUpdate !is CompletedExceptionally) return cancelled // not exception -- just use original cancelled
         val exception = proposedUpdate.exception
         if (cancelled.exception == exception) return cancelled // that is the cancelled we need already!
-        cancelled.cause?.let { exception.addSuppressed(it) }
+        cancelled.cause?.let { exception.addSuppressedThrowable(it) }
         return Cancelled(this, exception)
     }
 
@@ -721,7 +696,7 @@
             try {
                 node.invoke(cause)
             } catch (ex: Throwable) {
-                exception?.apply { addSuppressed(ex) } ?: run {
+                exception?.apply { addSuppressedThrowable(ex) } ?: run {
                     exception =  CompletionHandlerException("Exception in completion handler $node for $this", ex)
                 }
             }
@@ -735,7 +710,7 @@
     private fun notifyCancellation(list: NodeList, cause: Throwable?) =
         notifyHandlers<JobCancellationNode<*>>(list, cause)
 
-    public actual final override fun start(): Boolean {
+    public final override fun start(): Boolean {
         loopOnState { state ->
             when (startInternal(state)) {
                 FALSE -> return false
@@ -769,9 +744,9 @@
      * Override to provide the actual [start] action.
      * This function is invoked exactly once when non-active coroutine is [started][start].
      */
-    internal actual open fun onStartInternal() {}
+    internal open fun onStartInternal() {}
 
-    public actual final override fun getCancellationException(): CancellationException {
+    public final override fun getCancellationException(): CancellationException {
         val state = this.state
         return when {
             state is Finishing && state.cancelled != null ->
@@ -817,7 +792,7 @@
         invokeOnCompletion(onCancelling = onCancelling_, invokeImmediately = true, handler = handler)
 
     // todo: non-final as a workaround for KT-21968, should be final in the future
-    public actual override fun invokeOnCompletion(
+    public override fun invokeOnCompletion(
         onCancelling: Boolean,
         invokeImmediately: Boolean,
         handler: CompletionHandler
@@ -849,7 +824,9 @@
                     }
                 }
                 else -> { // is complete
-                    if (invokeImmediately) handler((state as? CompletedExceptionally)?.cause)
+                    // :KLUDGE: We have to invoke a handler in platform-specific way via `invokeIt` extension,
+                    // because we play type tricks on Kotlin/JS and handler is not necessarily a function there
+                    if (invokeImmediately) handler.invokeIt((state as? CompletedExceptionally)?.cause)
                     return NonDisposableHandle
                 }
             }
@@ -878,12 +855,12 @@
         // try to promote it to list (SINGLE+ state)
         state.addOneIfEmpty(NodeList(active = true))
         // it must be in SINGLE+ state or state has changed (node could have need removed from state)
-        val list = state.next // either NodeList or somebody else won the race, updated state
+        val list = state.nextNode // either our NodeList or somebody else won the race, updated state
         // just attempt converting it to list if state is still the same, then we'll continue lock-free loop
         _state.compareAndSet(state, list)
     }
 
-    public actual final override suspend fun join() {
+    public final override suspend fun join() {
         if (!joinInternal()) { // fast-path no wait
             return suspendCoroutineOrReturn { cont ->
                 cont.context.checkCompletion()
@@ -901,7 +878,7 @@
     }
 
     private suspend fun joinSuspend() = suspendCancellableCoroutine<Unit> { cont ->
-        cont.disposeOnCompletion(invokeOnCompletion(handler = ResumeOnCompletion(this, cont)))
+        cont.disposeOnCompletion(invokeOnCompletion(handler = ResumeOnCompletion(this, cont).asHandler))
     }
 
     public final override val onJoin: SelectClause0
@@ -922,7 +899,7 @@
             }
             if (startInternal(state) == 0) {
                 // slow-path -- register waiter for completion
-                select.disposeOnSelect(invokeOnCompletion(handler = SelectJoinOnCompletion(this, select, block)))
+                select.disposeOnSelect(invokeOnCompletion(handler = SelectJoinOnCompletion(this, select, block).asHandler))
                 return
             }
         }
@@ -955,7 +932,7 @@
      */
     internal open val onCancelMode: Int get() = ON_CANCEL_MAKE_CANCELLING
 
-    public actual override fun cancel(cause: Throwable?): Boolean = when (onCancelMode) {
+    public override fun cancel(cause: Throwable?): Boolean = when (onCancelMode) {
         ON_CANCEL_MAKE_CANCELLED -> makeCancelled(cause)
         ON_CANCEL_MAKE_CANCELLING -> makeCancelling(cause)
         ON_CANCEL_MAKE_COMPLETING -> makeCompletingOnCancel(cause)
@@ -1041,7 +1018,7 @@
      * @throws IllegalStateException if job is already complete or completing
      * @suppress **This is unstable API and it is subject to change.**
      */
-    internal actual fun makeCompletingOnce(proposedUpdate: Any?, mode: Int): Boolean =
+    internal fun makeCompletingOnce(proposedUpdate: Any?, mode: Int): Boolean =
         when (makeCompletingInternal(proposedUpdate, mode)) {
             COMPLETING_COMPLETED -> true
             COMPLETING_WAITING_CHILDREN -> false
@@ -1056,23 +1033,23 @@
             if (state is Finishing && state.completing)
                 return COMPLETING_ALREADY_COMPLETING
             val child: Child? = firstChild(state) ?: // or else complete immediately w/o children
-                when {
-                    state !is Finishing && hasOnFinishingHandler(proposedUpdate) -> null // unless it has onFinishing handler
-                    updateState(state, proposedUpdate, mode) -> return COMPLETING_COMPLETED
-                    else -> return@loopOnState
-                }
+            when {
+                state !is Finishing && hasOnFinishingHandler(proposedUpdate) -> null // unless it has onFinishing handler
+                updateState(state, proposedUpdate, mode) -> return COMPLETING_COMPLETED
+                else -> return@loopOnState
+            }
             val list = state.list ?: // must promote to list to correctly operate on child lists
-                when (state) {
-                    is Empty -> {
-                        promoteEmptyToNodeList(state)
-                        return@loopOnState // retry
-                    }
-                    is JobNode<*> -> {
-                        promoteSingleToNodeList(state)
-                        return@loopOnState // retry
-                    }
-                    else -> error("Unexpected state with an empty list: $state")
+            when (state) {
+                is Empty -> {
+                    promoteEmptyToNodeList(state)
+                    return@loopOnState // retry
                 }
+                is JobNode<*> -> {
+                    promoteSingleToNodeList(state)
+                    return@loopOnState // retry
+                }
+                else -> error("Unexpected state with an empty list: $state")
+            }
             // cancel all children in list on exceptional completion
             if (proposedUpdate is CompletedExceptionally)
                 child?.cancelChildrenInternal(proposedUpdate.exception)
@@ -1103,7 +1080,7 @@
     // return false when there is no more incomplete children to wait
     private tailrec fun tryWaitForChild(child: Child, proposedUpdate: Any?): Boolean {
         val handle = child.childJob.invokeOnCompletion(invokeImmediately = false,
-            handler = ChildCompletion(this, child, proposedUpdate))
+            handler = ChildCompletion(this, child, proposedUpdate).asHandler)
         if (handle !== NonDisposableHandle) return true // child is not complete and we've started waiting for it
         val nextChild = child.nextChild() ?: return false
         return tryWaitForChild(nextChild, proposedUpdate)
@@ -1127,16 +1104,16 @@
 
     private fun LockFreeLinkedListNode.nextChild(): Child? {
         var cur = this
-        while (cur.isRemoved) cur = cur.prev.unwrap() // rollback to prev non-removed (or list head)
+        while (cur.isRemoved) cur = cur.prevNode // rollback to prev non-removed (or list head)
         while (true) {
-            cur = cur.next.unwrap()
+            cur = cur.nextNode
             if (cur.isRemoved) continue
             if (cur is Child) return cur
             if (cur is NodeList) return null // checked all -- no more children
         }
     }
 
-    public actual final override val children: Sequence<Job> get() = buildSequence {
+    public final override val children: Sequence<Job> get() = buildSequence {
         val state = this@JobSupport.state
         when (state) {
             is Child -> yield(state.childJob)
@@ -1147,8 +1124,8 @@
     }
 
     @Suppress("OverridingDeprecatedMember")
-    public actual final override fun attachChild(child: Job): DisposableHandle =
-        invokeOnCompletion(onCancelling = true, handler = Child(this, child))
+    public final override fun attachChild(child: Job): DisposableHandle =
+        invokeOnCompletion(onCancelling = true, handler = Child(this, child).asHandler)
 
     @Suppress("OverridingDeprecatedMember")
     public final override fun cancelChildren(cause: Throwable?) {
@@ -1160,7 +1137,7 @@
      * installed via [invokeOnCompletion].
      * @suppress **This is unstable API and it is subject to change.**
      */
-    internal actual open fun handleException(exception: Throwable) {
+    internal open fun handleException(exception: Throwable) {
         throw exception
     }
 
@@ -1171,24 +1148,24 @@
      *               null when it has completed normally.
      * @suppress **This is unstable API and it is subject to change.**
      */
-    internal actual open fun onCancellationInternal(exceptionally: CompletedExceptionally?) {}
+    internal open fun onCancellationInternal(exceptionally: CompletedExceptionally?) {}
 
     /**
      * @suppress **This is unstable API and it is subject to change.**
      */
-    internal actual open fun hasOnFinishingHandler(update: Any?) = false
+    internal open fun hasOnFinishingHandler(update: Any?) = false
 
     /**
      * @suppress **This is unstable API and it is subject to change.**
      */
-    internal actual open fun onFinishingInternal(update: Any?) {}
+    internal open fun onFinishingInternal(update: Any?) {}
 
     /**
      * Override for post-completion actions that need to do something with the state.
      * @param mode completion mode.
      * @suppress **This is unstable API and it is subject to change.**
      */
-    internal actual open fun onCompletionInternal(state: Any?, mode: Int) {}
+    internal open fun onCompletionInternal(state: Any?, mode: Int) {}
 
     // for nicer debugging
     public override fun toString(): String =
@@ -1197,7 +1174,7 @@
     /**
      * @suppress **This is unstable API and it is subject to change.**
      */
-    internal actual open fun nameString(): String = this::class.java.simpleName
+    internal open fun nameString(): String = classSimpleName
 
     private fun stateString(): String {
         val state = this.state
@@ -1213,14 +1190,6 @@
         }
     }
 
-    /**
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal interface Incomplete {
-        val isActive: Boolean
-        val list: NodeList? // is null only for Empty and JobNode incomplete state objects
-    }
-
     // Cancelling or Completing
     private class Finishing(
         override val list: NodeList,
@@ -1233,36 +1202,6 @@
     private val Incomplete.isCancelling: Boolean
         get() = this is Finishing && cancelled != null
 
-    /**
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal class NodeList(
-        active: Boolean
-    ) : LockFreeLinkedListHead(), Incomplete {
-        private val _active = atomic(if (active) 1 else 0)
-
-        override val isActive: Boolean get() = _active.value != 0
-        override val list: NodeList get() = this
-
-        fun tryMakeActive(): Int {
-            if (_active.value != 0) return FALSE
-            if (_active.compareAndSet(0, 1)) return TRUE
-            return RETRY
-        }
-
-        override fun toString(): String = buildString {
-            append("List")
-            append(if (isActive) "{Active}" else "{New}")
-            append("[")
-            var first = true
-            this@NodeList.forEach<JobNode<*>> { node ->
-                if (first) first = false else append(", ")
-                append(node)
-            }
-            append("]")
-        }
-    }
-
     /*
      * =================================================================================================
      * This is ready-to-use implementation for Deferred interface.
@@ -1271,9 +1210,9 @@
      * =================================================================================================
      */
 
-    public actual val isCompletedExceptionally: Boolean get() = state is CompletedExceptionally
+    public val isCompletedExceptionally: Boolean get() = state is CompletedExceptionally
 
-    public actual fun getCompletionExceptionOrNull(): Throwable? {
+    public fun getCompletionExceptionOrNull(): Throwable? {
         val state = this.state
         check(state !is Incomplete) { "This job has not completed yet" }
         return state.exceptionOrNull
@@ -1339,7 +1278,7 @@
             }
             if (startInternal(state) == 0) {
                 // slow-path -- register waiter for completion
-                select.disposeOnSelect(invokeOnCompletion(handler = SelectAwaitOnCompletion(this, select, block)))
+                select.disposeOnSelect(invokeOnCompletion(handler = SelectAwaitOnCompletion(this, select, block).asHandler))
                 return
             }
         }
@@ -1348,8 +1287,8 @@
     /**
      * @suppress **This is unstable API and it is subject to change.**
      */
-   @Suppress("UNCHECKED_CAST")
-   internal fun <T, R> selectAwaitCompletion(select: SelectInstance<R>, block: suspend (T) -> R) {
+    @Suppress("UNCHECKED_CAST")
+    internal fun <T, R> selectAwaitCompletion(select: SelectInstance<R>, block: suspend (T) -> R) {
         val state = this.state
         // Note: await is non-atomic (can be cancelled while dispatched)
         if (state is CompletedExceptionally)
@@ -1376,8 +1315,8 @@
 @Suppress("PrivatePropertyName")
 private val EmptyActive = Empty(true)
 
-private class Empty(override val isActive: Boolean) : JobSupport.Incomplete {
-    override val list: JobSupport.NodeList? get() = null
+private class Empty(override val isActive: Boolean) : Incomplete {
+    override val list: NodeList? get() = null
     override fun toString(): String = "Empty{${if (isActive) "Active" else "New" }}"
 }
 
@@ -1388,28 +1327,59 @@
 
 // -------- invokeOnCompletion nodes
 
-internal abstract class JobNode<out J : Job>(
+internal interface Incomplete {
+    val isActive: Boolean
+    val list: NodeList? // is null only for Empty and JobNode incomplete state objects
+}
+
+internal abstract class JobNode<out J : Job> actual constructor(
     @JvmField val job: J
-) : LockFreeLinkedListNode(), DisposableHandle, CompletionHandler, JobSupport.Incomplete {
-    final override val isActive: Boolean get() = true
-    final override val list: JobSupport.NodeList? get() = null
-    final override fun dispose() = (job as JobSupport).removeNode(this)
-    abstract override fun invoke(reason: Throwable?)
+) : CompletionHandlerNode(), DisposableHandle, Incomplete {
+    override val isActive: Boolean get() = true
+    override val list: NodeList? get() = null
+    override fun dispose() = (job as JobSupport).removeNode(this)
+}
+
+internal class NodeList(
+    active: Boolean
+) : LockFreeLinkedListHead(), Incomplete {
+    private val _active = atomic(if (active) 1 else 0)
+
+    override val isActive: Boolean get() = _active.value != 0
+    override val list: NodeList get() = this
+
+    fun tryMakeActive(): Int {
+        if (_active.value != 0) return FALSE
+        if (_active.compareAndSet(0, 1)) return TRUE
+        return RETRY
+    }
+
+    override fun toString(): String = buildString {
+        append("List")
+        append(if (isActive) "{Active}" else "{New}")
+        append("[")
+        var first = true
+        this@NodeList.forEach<JobNode<*>> { node ->
+            if (first) first = false else append(", ")
+            append(node)
+        }
+        append("]")
+    }
 }
 
 private class InvokeOnCompletion(
     job: Job,
     private val handler: CompletionHandler
 ) : JobNode<Job>(job)  {
-    override fun invoke(reason: Throwable?) = handler.invoke(reason)
-    override fun toString() = "InvokeOnCompletion[${handler::class.java.name}@${Integer.toHexString(System.identityHashCode(handler))}]"
+    override fun invoke(cause: Throwable?) = handler.invoke(cause)
+    override fun toString() = "InvokeOnCompletion[$classSimpleName@$hexAddress]"
 }
 
 private class ResumeOnCompletion(
     job: Job,
     private val continuation: Continuation<Unit>
 ) : JobNode<Job>(job)  {
-    override fun invoke(reason: Throwable?) = continuation.resume(Unit)
+    override fun invoke(cause: Throwable?) = continuation.resume(Unit)
     override fun toString() = "ResumeOnCompletion[$continuation]"
 }
 
@@ -1417,28 +1387,16 @@
     job: Job,
     private val handle: DisposableHandle
 ) : JobNode<Job>(job) {
-    override fun invoke(reason: Throwable?) = handle.dispose()
+    override fun invoke(cause: Throwable?) = handle.dispose()
     override fun toString(): String = "DisposeOnCompletion[$handle]"
 }
 
-private class CancelFutureOnCompletion(
-    job: Job,
-    private val future: Future<*>
-) : JobNode<Job>(job)  {
-    override fun invoke(reason: Throwable?) {
-        // Don't interrupt when cancelling future on completion, because no one is going to reset this
-        // interruption flag and it will cause spurious failures elsewhere
-        future.cancel(false)
-    }
-    override fun toString() = "CancelFutureOnCompletion[$future]"
-}
-
 private class SelectJoinOnCompletion<R>(
     job: JobSupport,
     private val select: SelectInstance<R>,
     private val block: suspend () -> R
 ) : JobNode<JobSupport>(job) {
-    override fun invoke(reason: Throwable?) {
+    override fun invoke(cause: Throwable?) {
         if (select.trySelect(null))
             block.startCoroutineCancellable(select.completion)
     }
@@ -1450,7 +1408,7 @@
     private val select: SelectInstance<R>,
     private val block: suspend (T) -> R
 ) : JobNode<JobSupport>(job) {
-    override fun invoke(reason: Throwable?) {
+    override fun invoke(cause: Throwable?) {
         if (select.trySelect(null))
             job.selectAwaitCompletion(select, block)
     }
@@ -1471,17 +1429,17 @@
 ) : JobCancellationNode<Job>(job)  {
     // delegate handler shall be invoked at most once, so here is an additional flag
     private val _invoked = atomic(0)
-    override fun invoke(reason: Throwable?) {
-        if (_invoked.compareAndSet(0, 1)) handler.invoke(reason)
+    override fun invoke(cause: Throwable?) {
+        if (_invoked.compareAndSet(0, 1)) handler.invoke(cause)
     }
-    override fun toString() = "InvokeOnCancellation[${handler::class.java.name}@${Integer.toHexString(System.identityHashCode(handler))}]"
+    override fun toString() = "InvokeOnCancellation[$classSimpleName@$hexAddress]"
 }
 
 internal class Child(
     parent: JobSupport,
     @JvmField val childJob: Job
 ) : JobCancellationNode<JobSupport>(parent) {
-    override fun invoke(reason: Throwable?) {
+    override fun invoke(cause: Throwable?) {
         // Always materialize the actual instance of parent's completion exception and cancel child with it
         childJob.cancel(job.getCancellationException())
     }
@@ -1493,8 +1451,7 @@
     private val child: Child,
     private val proposedUpdate: Any?
 ) : JobNode<Job>(child.childJob) {
-    override fun invoke(reason: Throwable?) {
+    override fun invoke(cause: Throwable?) {
         parent.continueCompleting(child, proposedUpdate)
     }
-}
-
+}
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/NonCancellable.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/NonCancellable.kt
similarity index 72%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/NonCancellable.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/NonCancellable.kt
index 51aa9cf..4dc1b8a 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/NonCancellable.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/NonCancellable.kt
@@ -17,8 +17,8 @@
 package kotlinx.coroutines.experimental
 
 import kotlinx.coroutines.experimental.NonCancellable.isActive
-import kotlinx.coroutines.experimental.selects.SelectClause0
-import kotlin.coroutines.experimental.AbstractCoroutineContextElement
+import kotlinx.coroutines.experimental.selects.*
+import kotlin.coroutines.experimental.*
 
 /**
  * A non-cancelable job that is always [active][isActive]. It is designed for [withContext] function
@@ -31,21 +31,21 @@
  * }
  * ```
  */
-public actual object NonCancellable : AbstractCoroutineContextElement(Job), Job {
+public object NonCancellable : AbstractCoroutineContextElement(Job), Job {
     /** Always returns `true`. */
-    actual override val isActive: Boolean  get() = true
+    override val isActive: Boolean  get() = true
 
     /** Always returns `false`. */
-    actual override val isCompleted: Boolean get() = false
+    override val isCompleted: Boolean get() = false
 
     /** Always returns `false`. */
-    actual override val isCancelled: Boolean get() = false
+    override val isCancelled: Boolean get() = false
 
     /** Always returns `false`. */
-    actual override fun start(): Boolean = false
+    override fun start(): Boolean = false
 
     /** Always throws [UnsupportedOperationException]. */
-    actual suspend override fun join() {
+    override suspend fun join() {
         throw UnsupportedOperationException("This job is always active")
     }
 
@@ -53,7 +53,7 @@
         get() = throw UnsupportedOperationException("This job is always active")
 
     /** Always throws [IllegalStateException]. */
-    actual override fun getCancellationException(): CancellationException = throw IllegalStateException("This job is always active")
+    override fun getCancellationException(): CancellationException = throw IllegalStateException("This job is always active")
 
     /** Always returns [NonDisposableHandle]. */
     @Suppress("OverridingDeprecatedMember")
@@ -71,19 +71,19 @@
         NonDisposableHandle
 
     /** Always returns [NonDisposableHandle]. */
-    actual override fun invokeOnCompletion(onCancelling: Boolean, invokeImmediately: Boolean, handler: CompletionHandler): DisposableHandle =
+    override fun invokeOnCompletion(onCancelling: Boolean, invokeImmediately: Boolean, handler: CompletionHandler): DisposableHandle =
         NonDisposableHandle
 
     /** Always returns `false`. */
-    actual override fun cancel(cause: Throwable?): Boolean = false
+    override fun cancel(cause: Throwable?): Boolean = false
 
     /** Always returns [emptySequence]. */
-    actual override val children: Sequence<Job>
+    override val children: Sequence<Job>
         get() = emptySequence()
 
     /** Always returns [NonDisposableHandle] and does not do anything. */
     @Suppress("OverridingDeprecatedMember")
-    actual override fun attachChild(child: Job): DisposableHandle = NonDisposableHandle
+    override fun attachChild(child: Job): DisposableHandle = NonDisposableHandle
 
     /** Does not do anything. */
     @Suppress("OverridingDeprecatedMember")
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonDelay.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Runnable.common.kt
similarity index 80%
rename from common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonDelay.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Runnable.common.kt
index 51a8a88..4152946 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonDelay.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Runnable.common.kt
@@ -16,6 +16,9 @@
 
 package kotlinx.coroutines.experimental
 
-public expect interface Delay
+public expect interface Runnable {
+    public fun run()
+}
 
-public expect suspend fun delay(time: Int)
+@Suppress("FunctionName")
+public expect inline fun Runnable(crossinline block: () -> Unit): Runnable
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt
similarity index 89%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt
index b881d98..93a522e 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt
@@ -16,9 +16,9 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlinx.coroutines.experimental.internalAnnotations.*
 import kotlinx.coroutines.experimental.intrinsics.*
-import kotlinx.coroutines.experimental.selects.*
-import java.util.concurrent.*
+import kotlinx.coroutines.experimental.timeunit.*
 import kotlin.coroutines.experimental.*
 import kotlin.coroutines.experimental.intrinsics.*
 
@@ -39,7 +39,7 @@
  *
  * @param time timeout time in milliseconds.
  */
-public actual suspend fun <T> withTimeout(time: Int, block: suspend CoroutineScope.() -> T): T =
+public suspend fun <T> withTimeout(time: Int, block: suspend CoroutineScope.() -> T): T =
     withTimeout(time.toLong(), TimeUnit.MILLISECONDS, block)
 
 /**
@@ -129,7 +129,7 @@
  *
  * @param time timeout time in milliseconds.
  */
-public actual suspend fun <T> withTimeoutOrNull(time: Int, block: suspend CoroutineScope.() -> T): T? =
+public suspend fun <T> withTimeoutOrNull(time: Int, block: suspend CoroutineScope.() -> T): T? =
     withTimeoutOrNull(time.toLong(), TimeUnit.MILLISECONDS, block)
 
 /**
@@ -182,3 +182,22 @@
     }
 }
 
+/**
+ * This exception is thrown by [withTimeout] to indicate timeout.
+ */
+public class TimeoutCancellationException internal constructor(
+    message: String,
+    @JvmField internal val coroutine: Job?
+) : CancellationException(message) {
+    /**
+     * Creates timeout exception with a given message.
+     */
+    public constructor(message: String) : this(message, null)
+}
+
+@Suppress("FunctionName")
+internal fun TimeoutCancellationException(
+    time: Long,
+    unit: TimeUnit,
+    coroutine: Job
+) : TimeoutCancellationException = TimeoutCancellationException("Timed out waiting for $time $unit", coroutine)
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Unconfined.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Unconfined.kt
new file mode 100644
index 0000000..bb7397e
--- /dev/null
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Unconfined.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package kotlinx.coroutines.experimental
+
+import kotlin.coroutines.experimental.*
+
+/**
+ * A coroutine dispatcher that is not confined to any specific thread.
+ * It executes initial continuation of the coroutine _right here_ in the current call-frame
+ * and let the coroutine resume in whatever thread that is used by the corresponding suspending function, without
+ * mandating any specific threading policy.
+ *
+ * Note, that if you need your coroutine to be confined to a particular thread or a thread-pool after resumption,
+ * but still want to execute it in the current call-frame until its first suspension, then you can use
+ * an optional [CoroutineStart] parameter in coroutine builders like [launch] and [async] setting it to the
+ * the value of [CoroutineStart.UNDISPATCHED].
+ */
+public object Unconfined : CoroutineDispatcher() {
+    override fun isDispatchNeeded(context: CoroutineContext): Boolean = false
+    override fun dispatch(context: CoroutineContext, block: Runnable) { throw UnsupportedOperationException() }
+    override fun toString(): String = "Unconfined"
+}
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Yield.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Yield.kt
similarity index 84%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Yield.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Yield.kt
index 833a728..2a53760 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Yield.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/Yield.kt
@@ -16,9 +16,8 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED
-import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
 
 /**
  * Yields a thread (or thread pool) of the current coroutine dispatcher to other coroutines to run.
@@ -28,7 +27,7 @@
  * If the [Job] of the current coroutine is cancelled or completed when this suspending function is invoked or while
  * this function is waiting for dispatching, it resumes with [CancellationException].
  */
-public actual suspend fun yield(): Unit = suspendCoroutineOrReturn sc@ { cont ->
+public suspend fun yield(): Unit = suspendCoroutineOrReturn sc@ { cont ->
     val context = cont.context
     context.checkCompletion()
     if (cont !is DispatchedContinuation<Unit>) return@sc Unit
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/Atomic.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/internal/Atomic.kt
similarity index 98%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/Atomic.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/internal/Atomic.kt
index 1eaa6e6..ce19e05 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/Atomic.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/internal/Atomic.kt
@@ -41,7 +41,7 @@
  * by Timothy L. Harris, Keir Fraser and Ian A. Pratt.
  *
  * Note: parts of atomic operation must be globally ordered. Otherwise, this implementation will produce
- * [StackOverflowError].
+ * `StackOverflowError`.
  *
  * @suppress **This is unstable API and it is subject to change.**
  */
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedList.common.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedList.common.kt
new file mode 100644
index 0000000..9cc3e14
--- /dev/null
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedList.common.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package kotlinx.coroutines.experimental.internal
+
+import kotlin.jvm.*
+
+/** @suppress **This is unstable API and it is subject to change.** */
+public expect open class LockFreeLinkedListNode() {
+    public val isRemoved: Boolean
+    public val nextNode: LockFreeLinkedListNode
+    public val prevNode: LockFreeLinkedListNode
+    public fun addLast(node: LockFreeLinkedListNode)
+    public fun addOneIfEmpty(node: LockFreeLinkedListNode): Boolean
+    public inline fun addLastIf(node: LockFreeLinkedListNode, crossinline condition: () -> Boolean): Boolean
+    public inline fun addLastIfPrev(
+        node: LockFreeLinkedListNode,
+        predicate: (LockFreeLinkedListNode) -> Boolean
+    ): Boolean
+
+    public inline fun addLastIfPrevAndIf(
+        node: LockFreeLinkedListNode,
+        predicate: (LockFreeLinkedListNode) -> Boolean, // prev node predicate
+        crossinline condition: () -> Boolean // atomically checked condition
+    ): Boolean
+
+    public open fun remove(): Boolean
+    public fun removeFirstOrNull(): LockFreeLinkedListNode?
+    public inline fun <reified T> removeFirstIfIsInstanceOfOrPeekIf(predicate: (T) -> Boolean): T?
+}
+
+/** @suppress **This is unstable API and it is subject to change.** */
+public expect open class LockFreeLinkedListHead() : LockFreeLinkedListNode {
+    public val isEmpty: Boolean
+    public inline fun <reified T : LockFreeLinkedListNode> forEach(block: (T) -> Unit)
+    public final override fun remove(): Nothing
+}
+
+/** @suppress **This is unstable API and it is subject to change.** */
+public expect open class AddLastDesc<T : LockFreeLinkedListNode>(
+    queue: LockFreeLinkedListNode,
+    node: T
+) : AbstractAtomicDesc {
+    val queue: LockFreeLinkedListNode
+    val node: T
+    protected override fun onPrepare(affected: LockFreeLinkedListNode, next: LockFreeLinkedListNode): Any?
+}
+
+/** @suppress **This is unstable API and it is subject to change.** */
+public expect abstract class AbstractAtomicDesc : AtomicDesc {
+    protected abstract fun onPrepare(affected: LockFreeLinkedListNode, next: LockFreeLinkedListNode): Any?
+    final override fun prepare(op: AtomicOp<*>): Any?
+    final override fun complete(op: AtomicOp<*>, failure: Any?)
+}
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/selects/Select.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/selects/Select.kt
similarity index 89%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/selects/Select.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/selects/Select.kt
index 603308f..85ba53c 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/selects/Select.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/selects/Select.kt
@@ -18,11 +18,10 @@
 
 import kotlinx.atomicfu.*
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.channels.*
 import kotlinx.coroutines.experimental.internal.*
+import kotlinx.coroutines.experimental.internalAnnotations.*
 import kotlinx.coroutines.experimental.intrinsics.*
-import kotlinx.coroutines.experimental.sync.*
-import java.util.concurrent.*
+import kotlinx.coroutines.experimental.timeunit.*
 import kotlin.coroutines.experimental.*
 import kotlin.coroutines.experimental.intrinsics.*
 
@@ -58,30 +57,6 @@
      * @param unit timeout unit (milliseconds by default)
      */
     public fun onTimeout(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS, block: suspend () -> R)
-
-    /** @suppress **Deprecated: for binary compatibility only **/
-    @Deprecated("for binary compatibility only", level=DeprecationLevel.HIDDEN)
-    public fun Job.onJoin(block: suspend () -> R) { onJoin(block) }
-
-    /** @suppress **Deprecated: for binary compatibility only **/
-    @Deprecated("for binary compatibility only", level=DeprecationLevel.HIDDEN)
-    public fun <T> Deferred<T>.onAwait(block: suspend (T) -> R) { onAwait(block) }
-
-    /** @suppress **Deprecated: for binary compatibility only **/
-    @Deprecated("for binary compatibility only", level=DeprecationLevel.HIDDEN)
-    public fun Mutex.onLock(owner: Any? = null, block: suspend () -> R) { onLock { block() } }
-
-    /** @suppress **Deprecated: for binary compatibility only **/
-    @Deprecated("for binary compatibility only", level=DeprecationLevel.HIDDEN)
-    public fun <E> SendChannel<E>.onSend(element: E, block: suspend () -> R) { onSend(element) { block() } }
-
-    /** @suppress **Deprecated: for binary compatibility only **/
-    @Deprecated("for binary compatibility only", level=DeprecationLevel.HIDDEN)
-    public fun <E> ReceiveChannel<E>.onReceive(block: suspend (E) -> R) { onReceive(block) }
-
-    /** @suppress **Deprecated: for binary compatibility only **/
-    @Deprecated("for binary compatibility only", level=DeprecationLevel.HIDDEN)
-    public fun <E> ReceiveChannel<E>.onReceiveOrNull(block: suspend (E?) -> R) { onReceiveOrNull(block) }
 }
 
 /**
@@ -203,7 +178,7 @@
  * Note, that this function does not check for cancellation when it is not suspended.
  * Use [yield] or [CoroutineScope.isActive] to periodically check for cancellation in tight loops if needed.
  */
-public inline suspend fun <R> select(crossinline builder: SelectBuilder<R>.() -> Unit): R =
+public suspend inline fun <R> select(crossinline builder: SelectBuilder<R>.() -> Unit): R =
     suspendCoroutineOrReturn { cont ->
         val scope = SelectBuilderImpl(cont)
         try {
@@ -222,7 +197,8 @@
 @PublishedApi
 internal class SelectBuilderImpl<in R>(
     private val delegate: Continuation<R>
-) : LockFreeLinkedListHead(), SelectBuilder<R>, SelectInstance<R>, Continuation<R> {
+) : LockFreeLinkedListHead(), SelectBuilder<R>,
+    SelectInstance<R>, Continuation<R> {
     // selection state is "this" (list of nodes) initially and is replaced by idempotent marker (or null) when selected
     private val _state = atomic<Any?>(this)
 
@@ -258,7 +234,9 @@
         _result.loop { result ->
             when {
                 result === UNDECIDED -> if (_result.compareAndSet(UNDECIDED, value())) return
-                result === COROUTINE_SUSPENDED -> if (_result.compareAndSet(COROUTINE_SUSPENDED, RESUMED)) {
+                result === COROUTINE_SUSPENDED -> if (_result.compareAndSet(COROUTINE_SUSPENDED,
+                        RESUMED
+                    )) {
                     block()
                     return
                 }
@@ -305,7 +283,8 @@
 
     private fun initCancellability() {
         val parent = context[Job] ?: return
-        val newRegistration = parent.invokeOnCompletion(onCancelling = true, handler = SelectOnCancellation(parent))
+        val newRegistration = parent.invokeOnCompletion(
+            onCancelling = true, handler = SelectOnCancellation(parent).asHandler)
         parentHandle = newRegistration
         // now check our state _after_ registering
         if (isSelected) newRegistration.dispose()
@@ -313,7 +292,7 @@
 
     private inner class SelectOnCancellation(job: Job) : JobCancellationNode<Job>(job) {
         // Note: may be invoked multiple times, but only the first trySelect succeeds anyway
-        override fun invoke(reason: Throwable?) {
+        override fun invoke(cause: Throwable?) {
             if (trySelect(null))
                 resumeSelectCancellableWithException(job.getCancellationException())
         }
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/selects/SelectUnbiased.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/selects/SelectUnbiased.kt
similarity index 88%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/selects/SelectUnbiased.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/selects/SelectUnbiased.kt
index cf79b47..59bfb5d 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/selects/SelectUnbiased.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/selects/SelectUnbiased.kt
@@ -16,10 +16,9 @@
 
 package kotlinx.coroutines.experimental.selects
 
-import java.util.*
-import java.util.concurrent.TimeUnit
-import kotlin.coroutines.experimental.Continuation
-import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn
+import kotlinx.coroutines.experimental.timeunit.*
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
 
 /**
  * Waits for the result of multiple suspending functions simultaneously like [select], but in an _unbiased_
@@ -31,7 +30,7 @@
  *
  * See [select] function description for all the other details.
  */
-public inline suspend fun <R> selectUnbiased(crossinline builder: SelectBuilder<R>.() -> Unit): R =
+public suspend inline fun <R> selectUnbiased(crossinline builder: SelectBuilder<R>.() -> Unit): R =
     suspendCoroutineOrReturn { cont ->
         val scope = UnbiasedSelectBuilderImpl(cont)
         try {
@@ -44,7 +43,8 @@
 
 
 @PublishedApi
-internal class UnbiasedSelectBuilderImpl<in R>(cont: Continuation<R>) : SelectBuilder<R> {
+internal class UnbiasedSelectBuilderImpl<in R>(cont: Continuation<R>) :
+    SelectBuilder<R> {
     val instance = SelectBuilderImpl(cont)
     val clauses = arrayListOf<() -> Unit>()
 
@@ -55,7 +55,7 @@
     internal fun initSelectResult(): Any? {
         if (!instance.isSelected) {
             try {
-                Collections.shuffle(clauses)
+                clauses.shuffle()
                 clauses.forEach { it.invoke() }
             } catch (e: Throwable) {
                 instance.handleBuilderException(e)
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/selects/WhileSelect.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/selects/WhileSelect.kt
similarity index 100%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/selects/WhileSelect.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/selects/WhileSelect.kt
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/sync/Mutex.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/sync/Mutex.kt
similarity index 94%
rename from core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/sync/Mutex.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/sync/Mutex.kt
index 3130085..9807059 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/sync/Mutex.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/sync/Mutex.kt
@@ -16,16 +16,13 @@
 
 package kotlinx.coroutines.experimental.sync
 
-import kotlinx.atomicfu.atomic
-import kotlinx.atomicfu.loop
+import kotlinx.atomicfu.*
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.internal.*
-import kotlinx.coroutines.experimental.intrinsics.startCoroutineUndispatched
-import kotlinx.coroutines.experimental.selects.ALREADY_SELECTED
-import kotlinx.coroutines.experimental.selects.SelectClause2
-import kotlinx.coroutines.experimental.selects.SelectInstance
-import kotlinx.coroutines.experimental.selects.select
-import kotlin.coroutines.experimental.startCoroutine
+import kotlinx.coroutines.experimental.intrinsics.*
+import kotlinx.coroutines.experimental.selects.*
+import kotlin.coroutines.experimental.*
+import kotlinx.coroutines.experimental.internalAnnotations.*
 
 /**
  * Mutual exclusion for coroutines.
@@ -36,19 +33,6 @@
  */
 public interface Mutex {
     /**
-     * Factory for [Mutex] instances.
-     * @suppress **Deprecated**
-     */
-    public companion object Factory {
-        /**
-         * Creates new [Mutex] instance.
-         * @suppress **Deprecated**
-         */
-        @Deprecated("Replaced with top-level function", level = DeprecationLevel.HIDDEN)
-        public operator fun invoke(locked: Boolean = false): Mutex = Mutex(locked)
-    }
-
-    /**
      * Returns `true` when this mutex is locked.
      */
     public val isLocked: Boolean
@@ -113,7 +97,9 @@
  *
  * @param locked initial state of the mutex.
  */
-public fun Mutex(locked: Boolean = false): Mutex = MutexImpl(locked)
+@Suppress("FunctionName")
+public fun Mutex(locked: Boolean = false): Mutex =
+    MutexImpl(locked)
 
 /**
  * Executes the given [action] under this mutex's lock.
@@ -122,7 +108,7 @@
  *
  * @return the return value of the action.
  */
-public inline suspend fun <T> Mutex.withLock(owner: Any? = null, action: () -> T): T {
+public suspend inline fun <T> Mutex.withLock(owner: Any? = null, action: () -> T): T {
     lock(owner)
     try {
         return action()
@@ -200,7 +186,9 @@
             when (state) {
                 is Empty -> {
                     if (state.locked !== UNLOCKED) return false
-                    val update = if (owner == null) EmptyLocked else Empty(owner)
+                    val update = if (owner == null) EmptyLocked else Empty(
+                        owner
+                    )
                     if (_state.compareAndSet(state, update)) return true
                 }
                 is LockedQueue -> {
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonYield.kt b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/timeunit/TimeUnit.common.kt
similarity index 78%
rename from common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonYield.kt
rename to common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/timeunit/TimeUnit.common.kt
index e461c47..d41e2d2 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonYield.kt
+++ b/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/timeunit/TimeUnit.common.kt
@@ -14,6 +14,11 @@
  * limitations under the License.
  */
 
-package kotlinx.coroutines.experimental
+package kotlinx.coroutines.experimental.timeunit
 
-public expect suspend fun yield()
\ No newline at end of file
+public expect enum class TimeUnit {
+    MILLISECONDS,
+    SECONDS;
+
+    public fun toMillis(time: Long): Long
+}
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AbstractCoroutineTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AbstractCoroutineTest.kt
index b380354..bafb2eb 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AbstractCoroutineTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AbstractCoroutineTest.kt
@@ -16,12 +16,14 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
 class AbstractCoroutineTest : TestBase() {
     @Test
     fun testNotifications() = runTest {
         expect(1)
+        val coroutineContext = coroutineContext // workaround for KT-22984
         val coroutine = object : AbstractCoroutine<String>(coroutineContext, false) {
             override fun onStart() {
                 expect(3)
@@ -59,6 +61,7 @@
     @Test
     fun testNotificationsWithException() = runTest {
         expect(1)
+        val coroutineContext = coroutineContext // workaround for KT-22984
         val coroutine = object : AbstractCoroutine<String>(coroutineContext, false) {
             override fun onStart() {
                 expect(3)
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonAsyncLazyTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AsyncLazyTest.kt
similarity index 98%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonAsyncLazyTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AsyncLazyTest.kt
index a56084d..af3115c 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonAsyncLazyTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AsyncLazyTest.kt
@@ -18,9 +18,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class CommonAsyncLazyTest : TestBase() {
+class AsyncLazyTest : TestBase() {
     @Test
     fun testSimple() = runTest {
         expect(1)
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonAsyncTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AsyncTest.kt
similarity index 97%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonAsyncTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AsyncTest.kt
index f933f72..2eac23c 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonAsyncTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AsyncTest.kt
@@ -18,9 +18,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class CommonAsyncTest : TestBase() {
+class AsyncTest : TestBase() {
     @Test
     fun testSimple() = runTest {
         expect(1)
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonAtomicCancellationTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AtomicCancellationCommonTest.kt
similarity index 69%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonAtomicCancellationTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AtomicCancellationCommonTest.kt
index b336bfd..fe69a8a 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonAtomicCancellationTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/AtomicCancellationCommonTest.kt
@@ -16,9 +16,12 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlinx.coroutines.experimental.selects.*
+import kotlinx.coroutines.experimental.sync.*
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class CommonAtomicCancellationTest : TestBase() {
+class AtomicCancellationCommonTest : TestBase() {
     @Test
     fun testCancellableLaunch() = runTest {
         expect(1)
@@ -95,4 +98,42 @@
         yield() // to jobToJoin & canceller
         expect(6)
     }
+
+    @Test
+    fun testLockAtomicCancel() = runTest {
+        expect(1)
+        val mutex = Mutex(true) // locked mutex
+        val job = launch(coroutineContext, start = CoroutineStart.UNDISPATCHED) {
+            expect(2)
+            mutex.lock() // suspends
+            expect(4) // should execute despite cancellation
+        }
+        expect(3)
+        mutex.unlock() // unlock mutex first
+        job.cancel() // cancel the job next
+        yield() // now yield
+        finish(5)
+    }
+
+    @Test
+    fun testSelectLockAtomicCancel() = runTest {
+        expect(1)
+        val mutex = Mutex(true) // locked mutex
+        val job = launch(coroutineContext, start = CoroutineStart.UNDISPATCHED) {
+            expect(2)
+            val result = select<String> { // suspends
+                mutex.onLock {
+                    expect(4)
+                    "OK"
+                }
+            }
+            assertEquals("OK", result)
+            expect(5) // should execute despite cancellation
+        }
+        expect(3)
+        mutex.unlock() // unlock mutex first
+        job.cancel() // cancel the job next
+        yield() // now yield
+        finish(6)
+    }
 }
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonCompletableDeferredTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CompletableDeferredTest.kt
similarity index 98%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonCompletableDeferredTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CompletableDeferredTest.kt
index 67556e5..d7ea3ac 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonCompletableDeferredTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CompletableDeferredTest.kt
@@ -18,9 +18,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class CommonCompletableDeferredTest : TestBase() {
+class CompletableDeferredTest : TestBase() {
     @Test
     fun testFresh() {
         val c = CompletableDeferred<String>()
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonCoroutineExceptionHandlerTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandlerTest.kt
similarity index 92%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonCoroutineExceptionHandlerTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandlerTest.kt
index fb0e31d..becd2c7 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonCoroutineExceptionHandlerTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandlerTest.kt
@@ -16,9 +16,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class CommonCoroutineExceptionHandlerTest : TestBase() {
+class CoroutineExceptionHandlerTest : TestBase() {
     @Test
     fun testCoroutineExceptionHandlerCreator() = runTest {
         expect(1)
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonCoroutinesTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CoroutinesTest.kt
similarity index 99%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonCoroutinesTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CoroutinesTest.kt
index b94ca92..5ebd129 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonCoroutinesTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CoroutinesTest.kt
@@ -18,9 +18,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class CommonCoroutinesTest : TestBase() {
+class CoroutinesTest : TestBase() {
     @Test
     fun testSimple() = runTest {
         expect(1)
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonJobTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt
similarity index 98%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonJobTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt
index 1b9e822..7ecbfdf 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonJobTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt
@@ -16,9 +16,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class CommonJobTest : TestBase() {
+class JobTest : TestBase() {
     @Test
     fun testState() {
         val job = Job()
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonLaunchLazyTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/LaunchLazyTest.kt
similarity index 96%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonLaunchLazyTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/LaunchLazyTest.kt
index 29651f5..bb2a845 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonLaunchLazyTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/LaunchLazyTest.kt
@@ -16,9 +16,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class CommonLaunchLazyTest : TestBase() {
+class LaunchLazyTest : TestBase() {
     @Test
     fun testLaunchAndYieldJoin() = runTest {
         expect(1)
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonTestBase.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.common.kt
similarity index 100%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonTestBase.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.common.kt
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonWithContextTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/WithContextTest.kt
similarity index 97%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonWithContextTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/WithContextTest.kt
index 7a3f4e9..2679ad5 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonWithContextTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/WithContextTest.kt
@@ -19,11 +19,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
-import kotlin.coroutines.experimental.ContinuationInterceptor
-import kotlin.coroutines.experimental.CoroutineContext
 
-class CommonWithContextTest : TestBase() {
+class WithContextTest : TestBase() {
     @Test
     fun testSameContextNoSuspend() = runTest {
         expect(1)
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonWithTimeoutOrNullTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullTest.kt
similarity index 75%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonWithTimeoutOrNullTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullTest.kt
index 1a1ec91..69b9bd4 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonWithTimeoutOrNullTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullTest.kt
@@ -19,9 +19,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class CommonWithTimeoutOrNullTest : TestBase() {
+class WithTimeoutOrNullTest : TestBase() {
     /**
      * Tests a case of no timeout and no suspension inside.
      */
@@ -141,4 +142,54 @@
         override fun hashCode(): Int = error("Should not be called")
         override fun toString(): String = error("Should not be called")
     }
+
+    @Test
+    fun testNullOnTimeout() = runTest {
+        expect(1)
+        val result = withTimeoutOrNull(100) {
+            expect(2)
+            delay(1000)
+            expectUnreached()
+            "OK"
+        }
+        assertEquals(null, result)
+        finish(3)
+    }
+
+    @Test
+    fun testSuppressExceptionWithResult() = runTest {
+        expect(1)
+        val result = withTimeoutOrNull(100) {
+            expect(2)
+            try {
+                delay(1000)
+            } catch (e: CancellationException) {
+                expect(3)
+            }
+            "OK"
+        }
+        assertEquals(null, result)
+        finish(4)
+    }
+
+    @Test
+    fun testSuppressExceptionWithAnotherException() = runTest(
+        expected = { it is TestException }
+    ) {
+        expect(1)
+        val result = withTimeoutOrNull(100) {
+            expect(2)
+            try {
+                delay(1000)
+            } catch (e: CancellationException) {
+                finish(3)
+                throw TestException()
+            }
+            expectUnreached()
+            "OK"
+        }
+        expectUnreached()
+    }
+
+    private class TestException : Exception()
 }
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonWithTimeoutTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutTest.kt
similarity index 69%
rename from common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonWithTimeoutTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutTest.kt
index e5360de..1aa2368 100644
--- a/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/CommonWithTimeoutTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutTest.kt
@@ -19,9 +19,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class CommonWithTimeoutTest : TestBase() {
+class WithTimeoutTest : TestBase() {
     /**
      * Tests a case of no timeout and no suspension inside.
      */
@@ -124,5 +125,59 @@
         override fun hashCode(): Int = error("Should not be called")
         override fun toString(): String = error("Should not be called")
     }
+
+    @Test
+    fun testExceptionOnTimeout() = runTest {
+        expect(1)
+        try {
+            withTimeout(100) {
+                expect(2)
+                delay(1000)
+                expectUnreached()
+                "OK"
+            }
+        } catch (e: CancellationException) {
+            assertEquals("Timed out waiting for 100 MILLISECONDS", e.message)
+            finish(3)
+        }
+    }
+
+    @Test
+    fun testSuppressExceptionWithResult() = runTest(
+        expected = { it is CancellationException }
+    ) {
+        expect(1)
+        val result = withTimeout(100) {
+            expect(2)
+            try {
+                delay(1000)
+            } catch (e: CancellationException) {
+                finish(3)
+            }
+            "OK"
+        }
+        expectUnreached()
+    }
+
+    @Test
+    fun testSuppressExceptionWithAnotherException() = runTest(
+        expected = { it is TestException }
+    ) {
+        expect(1)
+        withTimeout(100) {
+            expect(2)
+            try {
+                delay(1000)
+            } catch (e: CancellationException) {
+                finish(3)
+                throw TestException()
+            }
+            expectUnreached()
+            "OK"
+        }
+        expectUnreached()
+    }
+
+    private class TestException : Exception()
 }
 
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectBuilderImplTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectBuilderImplTest.kt
similarity index 90%
rename from core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectBuilderImplTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectBuilderImplTest.kt
index 39e289d..299156a 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectBuilderImplTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectBuilderImplTest.kt
@@ -16,11 +16,9 @@
 
 package kotlinx.coroutines.experimental.selects
 
-import org.junit.Test
-import kotlin.coroutines.experimental.Continuation
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.coroutines.experimental.EmptyCoroutineContext
-import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
+import kotlin.test.*
 
 class SelectBuilderImplTest {
     @Test
@@ -34,7 +32,7 @@
             }
             override fun resumeWithException(exception: Throwable) { error("Should not happen") }
         }
-        val c = SelectBuilderImpl<String>(delegate)
+        val c = SelectBuilderImpl(delegate)
         // still running builder
         check(!c.isSelected)
         check(c.trySelect("SELECT"))
@@ -60,7 +58,7 @@
             }
             override fun resumeWithException(exception: Throwable) { error("Should not happen") }
         }
-        val c = SelectBuilderImpl<String>(delegate)
+        val c = SelectBuilderImpl(delegate)
         check(c.getResult() === COROUTINE_SUSPENDED) // suspend first
         check(!c.isSelected)
         check(c.trySelect("SELECT"))
@@ -86,7 +84,7 @@
                 resumed = true
             }
         }
-        val c = SelectBuilderImpl<String>(delegate)
+        val c = SelectBuilderImpl(delegate)
         // still running builder
         check(!c.isSelected)
         check(c.trySelect("SELECT"))
@@ -117,7 +115,7 @@
                 resumed = true
             }
         }
-        val c = SelectBuilderImpl<String>(delegate)
+        val c = SelectBuilderImpl(delegate)
         check(c.getResult() === COROUTINE_SUSPENDED) // suspend first
         check(!c.isSelected)
         check(c.trySelect("SELECT"))
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectDeferredTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectDeferredTest.kt
similarity index 87%
rename from core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectDeferredTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectDeferredTest.kt
index cbf1e6c..dcaa857 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectDeferredTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectDeferredTest.kt
@@ -14,17 +14,19 @@
  * limitations under the License.
  */
 
+@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
+
 package kotlinx.coroutines.experimental.selects
 
 import kotlinx.coroutines.experimental.*
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import kotlin.coroutines.experimental.*
+import kotlin.test.*
 
 class SelectDeferredTest : TestBase() {
     @Test
-    fun testSimpleReturnsImmediately() = runBlocking<Unit> {
+    fun testSimpleReturnsImmediately() = runTest {
         expect(1)
-        val d1 = async<Int>(coroutineContext) {
+        val d1 = async(coroutineContext) {
             expect(3)
             42
         }
@@ -42,9 +44,9 @@
     }
 
     @Test
-    fun testSimpleWithYield() = runBlocking<Unit> {
+    fun testSimpleWithYield() = runTest {
         expect(1)
-        val d1 = async<Int>(coroutineContext) {
+        val d1 = async(coroutineContext) {
             expect(3)
             42
         }
@@ -68,7 +70,7 @@
     }
 
     @Test
-    fun testSelectIncompleteLazy() = runBlocking<Unit> {
+    fun testSelectIncompleteLazy() = runTest {
         expect(1)
         val d1 = async(coroutineContext, CoroutineStart.LAZY) {
             expect(5)
@@ -96,9 +98,9 @@
     }
 
     @Test
-    fun testSelectTwo() = runBlocking<Unit> {
+    fun testSelectTwo() = runTest {
         expect(1)
-        val d1 = async<String>(coroutineContext) {
+        val d1 = async(coroutineContext) {
             expect(3)
             yield() // to the other deffered
             expect(5)
@@ -106,7 +108,7 @@
             expect(7)
             "d1"
         }
-        val d2 = async<String>(coroutineContext) {
+        val d2 = async(coroutineContext) {
             expect(4)
             "d2" // returns result
         }
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectJobTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectJobTest.kt
similarity index 96%
rename from core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectJobTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectJobTest.kt
index 9d38aaf..3ca3e07 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectJobTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectJobTest.kt
@@ -17,8 +17,8 @@
 package kotlinx.coroutines.experimental.selects
 
 import kotlinx.coroutines.experimental.*
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import kotlin.coroutines.experimental.*
+import kotlin.test.*
 
 class SelectJobTest : TestBase() {
     @Test
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectJobTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexTest.kt
similarity index 61%
copy from core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectJobTest.kt
copy to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexTest.kt
index 9d38aaf..f2204dc 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectJobTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexTest.kt
@@ -17,64 +17,53 @@
 package kotlinx.coroutines.experimental.selects
 
 import kotlinx.coroutines.experimental.*
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import kotlinx.coroutines.experimental.sync.*
+import kotlin.coroutines.experimental.*
+import kotlin.test.*
 
-class SelectJobTest : TestBase() {
+class SelectMutexTest : TestBase() {
     @Test
-    fun testSelectCompleted() = runTest {
+    fun testSelectLock() = runTest {
+        val mutex = Mutex()
         expect(1)
-        launch(coroutineContext) { // makes sure we don't yield to it earlier
+        launch(coroutineContext) { // ensure that it is not scheduled earlier than needed
             finish(4) // after main exits
         }
-        val job = Job()
-        job.cancel()
-        select<Unit> {
-            job.onJoin {
+        val res = select<String> {
+            mutex.onLock {
+                assertTrue(mutex.isLocked)
                 expect(2)
+                "OK"
             }
         }
+        assertEquals("OK", res)
         expect(3)
         // will wait for the first coroutine
     }
 
     @Test
-    fun testSelectIncomplete() = runTest {
+    fun testSelectLockWait() = runTest {
+        val mutex = Mutex(true) // locked
         expect(1)
-        val job = Job()
-        launch(coroutineContext) { // makes sure we don't yield to it earlier
+        launch(coroutineContext) {
             expect(3)
             val res = select<String> {
-                job.onJoin {
+                // will suspended
+                mutex.onLock {
+                    assertTrue(mutex.isLocked)
                     expect(6)
                     "OK"
                 }
             }
-            expect(7)
             assertEquals("OK", res)
+            expect(7)
         }
         expect(2)
-        yield()
+        yield() // to launched coroutine
         expect(4)
-        job.cancel()
+        mutex.unlock()
         expect(5)
-        yield()
+        yield() // to resumed select
         finish(8)
     }
-
-    @Test
-    fun testSelectLazy() = runTest {
-        expect(1)
-        val job = launch(coroutineContext, CoroutineStart.LAZY) {
-            expect(2)
-        }
-        val res = select<String> {
-            job.onJoin {
-                expect(3)
-                "OK"
-            }
-        }
-        finish(4)
-        assertEquals("OK", res)
-    }
 }
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectTimeoutTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectTimeoutTest.kt
similarity index 79%
rename from core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectTimeoutTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectTimeoutTest.kt
index b8842c1..26bb748 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectTimeoutTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectTimeoutTest.kt
@@ -16,15 +16,12 @@
 
 package kotlinx.coroutines.experimental.selects
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.runBlocking
-import org.hamcrest.MatcherAssert.assertThat
-import org.hamcrest.core.IsEqual
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import kotlin.test.*
 
 class SelectTimeoutTest : TestBase() {
     @Test
-    fun testBasic() = runBlocking {
+    fun testBasic() = runTest {
         expect(1)
         val result = select<String> {
             onTimeout(1000) {
@@ -40,7 +37,7 @@
                 "FAIL"
             }
         }
-        assertThat(result, IsEqual("OK"))
+        assertEquals("OK", result)
         finish(3)
     }
 }
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexTest.kt b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexTest.kt
similarity index 78%
rename from core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexTest.kt
rename to common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexTest.kt
index 4a3fd32..050a103 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexTest.kt
+++ b/common/kotlinx-coroutines-core-common/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexTest.kt
@@ -17,13 +17,12 @@
 package kotlinx.coroutines.experimental.sync
 
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.core.IsEqual
-import org.junit.Assert.*
-import org.junit.Test
+import kotlin.test.*
+import kotlin.coroutines.experimental.*
 
 class MutexTest : TestBase() {
     @Test
-    fun testSimple() = runBlocking<Unit> {
+    fun testSimple() = runTest {
         val mutex = Mutex()
         expect(1)
         launch(coroutineContext) {
@@ -63,7 +62,7 @@
     }
 
     @Test
-    fun withLockTest() = runBlocking {
+    fun withLockTest() = runTest {
         val mutex = Mutex()
         assertFalse(mutex.isLocked)
         mutex.withLock {
@@ -73,26 +72,6 @@
     }
 
     @Test
-    fun testStress() = runBlocking<Unit> {
-        val n = 1000 * stressTestMultiplier
-        val k = 100
-        var shared = 0
-        val mutex = Mutex()
-        val jobs = List(n) {
-            launch(CommonPool) {
-                repeat(k) {
-                    mutex.lock()
-                    shared++
-                    mutex.unlock()
-                }
-            }
-        }
-        jobs.forEach { it.join() }
-        println("Shared value = $shared")
-        assertEquals(n * k, shared)
-    }
-
-    @Test
     fun testUnconfinedStackOverflow() {
         val waiters = 10000
         val mutex = Mutex(true)
@@ -105,11 +84,11 @@
             }
         }
         mutex.unlock() // should not produce StackOverflowError
-        assertThat(done, IsEqual(waiters))
+        assertEquals(waiters, done)
     }
 
     @Test
-    fun holdLock() = runBlocking {
+    fun holdLock() = runTest {
         val mutex = Mutex()
         val firstOwner = Any()
         val secondOwner = Any()
@@ -120,7 +99,7 @@
 
         // owner firstOwner
         mutex.lock(firstOwner)
-        val secondLockJob = launch(CommonPool) {
+        val secondLockJob = launch {
             mutex.lock(secondOwner)
         }
 
diff --git a/core/kotlinx-coroutines-core/README.md b/core/kotlinx-coroutines-core/README.md
index ab1759e..1e1c722 100644
--- a/core/kotlinx-coroutines-core/README.md
+++ b/core/kotlinx-coroutines-core/README.md
@@ -87,6 +87,10 @@
 
 Low-level primitives for finer-grained control of coroutines.
 
+# Package kotlinx.coroutines.experimental.timeunit
+
+Optional time unit support for multiplatform projects.
+
 <!--- MODULE kotlinx-coroutines-core -->
 <!--- INDEX kotlinx.coroutines.experimental -->
 [launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
diff --git a/core/kotlinx-coroutines-core/build.gradle b/core/kotlinx-coroutines-core/build.gradle
index b7ffdb6..ca4131d 100644
--- a/core/kotlinx-coroutines-core/build.gradle
+++ b/core/kotlinx-coroutines-core/build.gradle
@@ -2,8 +2,21 @@
     testCompile "com.devexperts.lincheck:core:$lincheck_version"
 }
 
+task checkJdk16() {
+    // only fail w/o JDK_16 when actually trying to compile, not during project setup phase
+    doLast {
+        if (!System.env.JDK_16) {
+            throw new GradleException("JDK_16 environment variable is not defined. " +
+                    "Can't build against JDK 1.6 runtime and run JDK 1.6 compatibility tests. " +
+                    "Please ensure JDK 1.6 is installed and that JDK_16 points to it.")
+        }
+    }
+}
+
 tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) {
     kotlinOptions.jdkHome = System.env.JDK_16
+    // only fail when actually trying to compile, not during project setup phase
+    dependsOn(checkJdk16)
 }
 
 tasks.withType(Test) {
@@ -24,7 +37,8 @@
     include '**/*LFTest.*'
 }
 
-task jdk16Test(type: Test, dependsOn: testClasses) {
+
+task jdk16Test(type: Test, dependsOn: [testClasses, checkJdk16]) {
     executable = "$System.env.JDK_16/bin/java"
     exclude '**/*LinearizabilityTest.*'
     exclude '**/*LFTest.*'
@@ -41,4 +55,4 @@
 
 artifacts {
     archives testsJar
-}
\ No newline at end of file
+}
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Annotations.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Annotations.kt
new file mode 100644
index 0000000..21e4c78
--- /dev/null
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Annotations.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package kotlinx.coroutines.experimental.internalAnnotations
+
+@Suppress("ACTUAL_WITHOUT_EXPECT")
+internal actual typealias JvmName = kotlin.jvm.JvmName
+
+@Suppress("ACTUAL_WITHOUT_EXPECT")
+internal actual typealias JvmMultifileClass = kotlin.jvm.JvmMultifileClass
+
+@Suppress("ACTUAL_WITHOUT_EXPECT")
+internal actual typealias JvmField = kotlin.jvm.JvmField
+
+@Suppress("ACTUAL_WITHOUT_EXPECT")
+internal actual typealias Volatile = kotlin.jvm.Volatile
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Builders.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Builders.kt
index 7b79f46..7d20709 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Builders.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Builders.kt
@@ -14,140 +14,13 @@
  * limitations under the License.
  */
 
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
+@file:JvmMultifileClass
+@file:JvmName("BuildersKt")
 
 package kotlinx.coroutines.experimental
 
-import kotlinx.coroutines.experimental.intrinsics.*
 import java.util.concurrent.locks.*
 import kotlin.coroutines.experimental.*
-import kotlin.coroutines.experimental.intrinsics.*
-
-// --------------- basic coroutine builders ---------------
-
-/**
- * Launches new coroutine without blocking current thread and returns a reference to the coroutine as a [Job].
- * The coroutine is cancelled when the resulting job is [cancelled][Job.cancel].
- *
- * The [context] for the new coroutine can be explicitly specified.
- * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.coroutineContext] of the parent coroutine from its [scope][CoroutineScope] may be used,
- * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
- * The parent job may be also explicitly specified using [parent] parameter.
- *
- * If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [DefaultDispatcher] is used.
- *
- * By default, the coroutine is immediately scheduled for execution.
- * Other options can be specified via `start` parameter. See [CoroutineStart] for details.
- * An optional [start] parameter can be set to [CoroutineStart.LAZY] to start coroutine _lazily_. In this case,
- * the coroutine [Job] is created in _new_ state. It can be explicitly started with [start][Job.start] function
- * and will be started implicitly on the first invocation of [join][Job.join].
- *
- * Uncaught exceptions in this coroutine cancel parent job in the context by default
- * (unless [CoroutineExceptionHandler] is explicitly specified), which means that when `launch` is used with
- * the context of another coroutine, then any uncaught exception leads to the cancellation of parent coroutine.
- *
- * See [newCoroutineContext] for a description of debugging facilities that are available for newly created coroutine.
- *
- * @param context context of the coroutine. The default value is [DefaultDispatcher].
- * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
- * @param parent explicitly specifies the parent job, overrides job from the [context] (if any).
- * @param block the coroutine code.
- */
-public actual fun launch(
-    context: CoroutineContext = DefaultDispatcher,
-    start: CoroutineStart = CoroutineStart.DEFAULT,
-    parent: Job? = null,
-    block: suspend CoroutineScope.() -> Unit
-): Job {
-    val newContext = newCoroutineContext(context, parent)
-    val coroutine = if (start.isLazy)
-        LazyStandaloneCoroutine(newContext, block) else
-        StandaloneCoroutine(newContext, active = true)
-    coroutine.start(start, coroutine, block)
-    return coroutine
-}
-
-/** @suppress **Deprecated**: Binary compatibility */
-@Deprecated(message = "Binary compatibility", level = DeprecationLevel.HIDDEN)
-public fun launch(
-    context: CoroutineContext = DefaultDispatcher,
-    start: CoroutineStart = CoroutineStart.DEFAULT,
-    block: suspend CoroutineScope.() -> Unit
-): Job =
-    launch(context, start, block = block)
-
-/**
- * @suppress **Deprecated**: Use `start = CoroutineStart.XXX` parameter
- */
-@Deprecated(message = "Use `start = CoroutineStart.XXX` parameter",
-    replaceWith = ReplaceWith("launch(context, if (start) CoroutineStart.DEFAULT else CoroutineStart.LAZY, block)"))
-public fun launch(context: CoroutineContext, start: Boolean, block: suspend CoroutineScope.() -> Unit): Job =
-    launch(context, if (start) CoroutineStart.DEFAULT else CoroutineStart.LAZY, block = block)
-
-/**
- * Calls the specified suspending block with a given coroutine context, suspends until it completes, and returns
- * the result.
- *
- * This function immediately applies dispatcher from the new context, shifting execution of the block into the
- * different thread inside the block, and back when it completes.
- * The specified [context] is added onto the current coroutine context for the execution of the block.
- *
- * An optional `start` parameter is used only if the specified `context` uses a different [CoroutineDispatcher] than
- * a current one, otherwise it is ignored.
- * By default, the coroutine is immediately scheduled for execution and can be cancelled
- * while it is waiting to be executed and it can be cancelled while the result is scheduled
- * to be processed by the invoker context.
- * Other options can be specified via `start` parameter. See [CoroutineStart] for details.
- * A value of [CoroutineStart.LAZY] is not supported and produces [IllegalArgumentException].
- */
-public actual suspend fun <T> withContext(
-    context: CoroutineContext,
-    start: CoroutineStart = CoroutineStart.DEFAULT,
-    block: suspend () -> T
-): T = suspendCoroutineOrReturn sc@ { cont ->
-    val oldContext = cont.context
-    // fast path #1 if there is no change in the actual context:
-    if (context === oldContext || context is CoroutineContext.Element && oldContext[context.key] === context)
-        return@sc block.startCoroutineUninterceptedOrReturn(cont)
-    // compute new context
-    val newContext = oldContext + context
-    // fast path #2 if the result is actually the same
-    if (newContext === oldContext)
-        return@sc block.startCoroutineUninterceptedOrReturn(cont)
-    // fast path #3 if the new dispatcher is the same as the old one.
-    // `equals` is used by design (see equals implementation is wrapper context like ExecutorCoroutineDispatcher)
-    if (newContext[ContinuationInterceptor] == oldContext[ContinuationInterceptor]) {
-        val newContinuation = RunContinuationDirect(newContext, cont)
-        return@sc block.startCoroutineUninterceptedOrReturn(newContinuation)
-    }
-    // slowest path otherwise -- use new interceptor, sync to its result via a full-blown instance of RunCompletion
-    require(!start.isLazy) { "$start start is not supported" }
-    val completion = RunCompletion(
-        context = newContext,
-        delegate = cont,
-        resumeMode = if (start == CoroutineStart.ATOMIC) MODE_ATOMIC_DEFAULT else MODE_CANCELLABLE)
-    completion.initParentJobInternal(newContext[Job]) // attach to job
-    @Suppress("DEPRECATION")
-    start(block, completion)
-    completion.getResult()
-}
-
-/** @suppress **Deprecated**: Renamed to [withContext]. */
-@Deprecated(message = "Renamed to `withContext`", level=DeprecationLevel.WARNING,
-    replaceWith = ReplaceWith("withContext(context, start, block)"))
-public suspend fun <T> run(
-    context: CoroutineContext,
-    start: CoroutineStart = CoroutineStart.DEFAULT,
-    block: suspend () -> T
-): T =
-    withContext(context, start, block)
-
-/** @suppress **Deprecated** */
-@Deprecated(message = "It is here for binary compatibility only", level=DeprecationLevel.HIDDEN)
-public suspend fun <T> run(context: CoroutineContext, block: suspend () -> T): T =
-    withContext(context, start = CoroutineStart.ATOMIC, block = block)
 
 /**
  * Runs new coroutine and **blocks** current thread _interruptibly_ until its completion.
@@ -185,41 +58,6 @@
     return coroutine.joinBlocking()
 }
 
-// --------------- implementation ---------------
-
-private open class StandaloneCoroutine(
-    private val parentContext: CoroutineContext,
-    active: Boolean
-) : AbstractCoroutine<Unit>(parentContext, active) {
-    override fun hasOnFinishingHandler(update: Any?) = update is CompletedExceptionally
-    override fun onFinishingInternal(update: Any?) {
-        // note the use of the parent's job context below!
-        if (update is CompletedExceptionally) handleCoroutineException(parentContext, update.exception)
-    }
-}
-
-private class LazyStandaloneCoroutine(
-    parentContext: CoroutineContext,
-    private val block: suspend CoroutineScope.() -> Unit
-) : StandaloneCoroutine(parentContext, active = false) {
-    override fun onStart() {
-        block.startCoroutineCancellable(this, this)
-    }
-}
-
-private class RunContinuationDirect<in T>(
-    override val context: CoroutineContext,
-    continuation: Continuation<T>
-) : Continuation<T> by continuation
-
-
-@Suppress("UNCHECKED_CAST")
-private class RunCompletion<in T>(
-    override val context: CoroutineContext,
-    delegate: Continuation<T>,
-    resumeMode: Int
-) : AbstractContinuation<T>(delegate, resumeMode)
-
 private class BlockingCoroutine<T>(
     parentContext: CoroutineContext,
     private val blockedThread: Thread,
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CommonPool.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CommonPool.kt
index a73ad00..10081ef 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CommonPool.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CommonPool.kt
@@ -16,6 +16,7 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlinx.coroutines.experimental.timeunit.TimeUnit
 import java.util.concurrent.*
 import java.util.concurrent.atomic.AtomicInteger
 import kotlin.coroutines.experimental.CoroutineContext
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonScheduled.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CompletionHandler.kt
similarity index 60%
copy from common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonScheduled.kt
copy to core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CompletionHandler.kt
index d9181d0..0f5cd77 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonScheduled.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CompletionHandler.kt
@@ -16,6 +16,12 @@
 
 package kotlinx.coroutines.experimental
 
-public expect suspend fun <T> withTimeout(time: Int, block: suspend CoroutineScope.() -> T): T
+import kotlinx.coroutines.experimental.internal.*
 
-public expect suspend fun <T> withTimeoutOrNull(time: Int, block: suspend CoroutineScope.() -> T): T?
+internal actual abstract class CompletionHandlerNode actual constructor() : LockFreeLinkedListNode(), CompletionHandler {
+    actual inline val asHandler: CompletionHandler get() = this
+    actual abstract override fun invoke(cause: Throwable?)
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal actual inline fun CompletionHandler.invokeIt(cause: Throwable?) = invoke(cause)
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.kt
index 832e1f0..774ebe7 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.kt
@@ -42,30 +42,6 @@
 }
 
 /**
- * A coroutine dispatcher that is not confined to any specific thread.
- * It executes initial continuation of the coroutine _right here_ in the current call-frame
- * and let the coroutine resume in whatever thread that is used by the corresponding suspending function, without
- * mandating any specific threading policy.
- *
- * Note, that if you need your coroutine to be confined to a particular thread or a thread-pool after resumption,
- * but still want to execute it in the current call-frame until its first suspension, then you can use
- * an optional [CoroutineStart] parameter in coroutine builders like [launch] and [async] setting it to the
- * the value of [CoroutineStart.UNDISPATCHED].
- */
-public actual object Unconfined : CoroutineDispatcher() {
-    actual override fun isDispatchNeeded(context: CoroutineContext): Boolean = false
-    actual override fun dispatch(context: CoroutineContext, block: Runnable) { throw UnsupportedOperationException() }
-    override fun toString(): String = "Unconfined"
-}
-
-/**
- * @suppress **Deprecated**: `Here` was renamed to `Unconfined`.
- */
-@Deprecated(message = "`Here` was renamed to `Unconfined`",
-        replaceWith = ReplaceWith(expression = "Unconfined"))
-public typealias Here = Unconfined
-
-/**
  * This is the default [CoroutineDispatcher] that is used by all standard builders like
  * [launch], [async], etc if no dispatcher nor any other [ContinuationInterceptor] is specified in their context.
  *
@@ -94,7 +70,7 @@
  * The string "coroutine" is used as a default name.
  */
 @JvmOverloads // for binary compatibility with newCoroutineContext(context: CoroutineContext) version
-public fun newCoroutineContext(context: CoroutineContext, parent: Job? = null): CoroutineContext {
+public actual fun newCoroutineContext(context: CoroutineContext, parent: Job? = null): CoroutineContext {
     val debug = if (DEBUG) context + CoroutineId(COROUTINE_ID.incrementAndGet()) else context
     val wp = if (parent == null) debug else debug + parent
     return if (context !== DefaultDispatcher && context[ContinuationInterceptor] == null)
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandlerImpl.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandlerImpl.kt
new file mode 100644
index 0000000..04246d3
--- /dev/null
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandlerImpl.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package kotlinx.coroutines.experimental
+
+import java.util.*
+import kotlin.coroutines.experimental.AbstractCoroutineContextElement
+import kotlin.coroutines.experimental.CoroutineContext
+
+internal actual fun handleCoroutineExceptionImpl(context: CoroutineContext, exception: Throwable) {
+    // use additional extension handlers
+    ServiceLoader.load(CoroutineExceptionHandler::class.java).forEach { handler ->
+        handler.handleException(context, exception)
+    }
+    // use thread's handler
+    val currentThread = Thread.currentThread()
+    currentThread.uncaughtExceptionHandler.uncaughtException(currentThread, exception)
+}
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineScope.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineScope.kt
deleted file mode 100644
index 222919e..0000000
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineScope.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.CoroutineContext
-
-/**
- * Receiver interface for generic coroutine builders, so that the code inside coroutine has a convenient access
- * to its [coroutineContext] and its cancellation status via [isActive].
- */
-public interface CoroutineScope {
-    /**
-     * Returns `true` when this coroutine is still active (has not completed and was not cancelled yet).
-     *
-     * Check this property in long-running computation loops to support cancellation:
-     * ```
-     * while (isActive) {
-     *     // do some computation
-     * }
-     * ```
-     *
-     * This property is a shortcut for `coroutineContext[Job]!!.isActive`. See [coroutineContext] and [Job].
-     */
-    public actual val isActive: Boolean
-
-    /**
-     * Returns the context of this coroutine.
-     * @suppress **Deprecated**: Renamed to [coroutineContext]
-     */
-    @Deprecated("Renamed to `coroutineContext`", replaceWith = ReplaceWith("coroutineContext"))
-    public val context: CoroutineContext
-
-    /**
-     * Returns the context of this coroutine.
-     */
-    @Suppress("DEPRECATION", "ACTUAL_WITHOUT_EXPECT")
-    public actual val coroutineContext: CoroutineContext get() = context
-}
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Debug.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Debug.kt
index 6930f33..a86d98f 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Debug.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Debug.kt
@@ -20,7 +20,7 @@
 
 // internal debugging tools
 
-internal val Any.hexAddress: String
+internal actual val Any.hexAddress: String
     get() = Integer.toHexString(System.identityHashCode(this))
 
 internal fun Any?.toSafeString(): String =
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/DefaultExecutor.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/DefaultExecutor.kt
index d2aab07..7d7d67d 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/DefaultExecutor.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/DefaultExecutor.kt
@@ -16,7 +16,9 @@
 
 package kotlinx.coroutines.experimental
 
-import java.util.concurrent.*
+import kotlinx.coroutines.experimental.timeunit.*
+
+internal actual val DefaultDelay: Delay = DefaultExecutor
 
 @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
 internal object DefaultExecutor : EventLoopBase(), Runnable {
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/EventLoop.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/EventLoop.kt
index e752994..6d6685b 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/EventLoop.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/EventLoop.kt
@@ -18,7 +18,7 @@
 
 import kotlinx.atomicfu.*
 import kotlinx.coroutines.experimental.internal.*
-import java.util.concurrent.*
+import kotlinx.coroutines.experimental.timeunit.TimeUnit
 import java.util.concurrent.locks.*
 import kotlin.coroutines.experimental.*
 
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Exceptions.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Exceptions.kt
index ed43104..7d7c532 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Exceptions.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Exceptions.kt
@@ -26,9 +26,12 @@
     cause: Throwable
 ) : RuntimeException(message, cause)
 
-    /**
-     * Thrown by cancellable suspending functions if the [Job] of the coroutine is cancelled while it is suspending.
-     */
+/**
+ * Thrown by cancellable suspending functions if the [Job] of the coroutine is cancelled while it is suspending.
+ * It indicates _normal_ cancellation of a coroutine.
+ * **It is not printed to console/log by default uncaught exception handler**.
+ * (see [handleCoroutineException]).
+*/
 public actual typealias CancellationException = java.util.concurrent.CancellationException
 
 /**
@@ -53,31 +56,8 @@
         (message!!.hashCode() * 31 + job.hashCode()) * 31 + (cause?.hashCode() ?: 0)
 }
 
-/**
- * This exception is thrown by [withTimeout] to indicate timeout.
- */
-@Suppress("DEPRECATION")
-public actual class TimeoutCancellationException internal constructor(
-    message: String,
-    @JvmField internal val coroutine: Job?
-) : TimeoutException(message) {
-    /**
-     * Creates timeout exception with a given message.
-     */
-    public actual constructor(message: String) : this(message, null)
-}
-
-@Suppress("FunctionName")
-internal fun TimeoutCancellationException(
-    time: Long,
-    unit: TimeUnit,
-    coroutine: Job
-) : TimeoutCancellationException = TimeoutCancellationException("Timed out waiting for $time $unit", coroutine)
-
-/**
- * @suppress **Deprecated**: Renamed to TimeoutCancellationException
- */
-@Deprecated("Renamed to TimeoutCancellationException", replaceWith = ReplaceWith("TimeoutCancellationException"))
-public open class TimeoutException(message: String) : CancellationException(message)
-
 internal actual class DispatchException actual constructor(message: String, cause: Throwable) : RuntimeException(message, cause)
+
+@Suppress("NOTHING_TO_INLINE")
+internal actual inline fun Throwable.addSuppressedThrowable(other: Throwable) =
+    addSuppressed(other)
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Executors.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Executors.kt
index a55dd31..f20753a 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Executors.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Executors.kt
@@ -16,11 +16,22 @@
 
 package kotlinx.coroutines.experimental
 
-import java.util.concurrent.Executor
-import java.util.concurrent.RejectedExecutionException
-import java.util.concurrent.ScheduledExecutorService
-import java.util.concurrent.TimeUnit
-import kotlin.coroutines.experimental.CoroutineContext
+import kotlinx.coroutines.experimental.timeunit.TimeUnit
+import java.io.*
+import java.util.concurrent.*
+import kotlin.coroutines.experimental.*
+
+/**
+ * [CoroutineDispatcher] that implements [Closeable]
+ */
+abstract class CloseableCoroutineDispatcher: CoroutineDispatcher(), Closeable
+
+/**
+ * Converts an instance of [ExecutorService] to an implementation of [CloseableCoroutineDispatcher].
+ */
+public fun ExecutorService.asCoroutineDispatcher(): CloseableCoroutineDispatcher =
+    // we know that an implementation of Executor.asCoroutineDispatcher actually returns a closeable one
+    (this as Executor).asCoroutineDispatcher() as CloseableCoroutineDispatcher
 
 /**
  * Converts an instance of [Executor] to an implementation of [CoroutineDispatcher].
@@ -42,7 +53,7 @@
 /**
  * @suppress **This is unstable API and it is subject to change.**
  */
-public abstract class ExecutorCoroutineDispatcherBase : CoroutineDispatcher(), Delay {
+public abstract class ExecutorCoroutineDispatcherBase : CloseableCoroutineDispatcher(), Delay {
     /**
      * @suppress **This is unstable API and it is subject to change.**
      */
@@ -77,6 +88,10 @@
             return DefaultExecutor.invokeOnTimeout(time, unit, block)
     }
 
+    override fun close() {
+        (executor as? ExecutorService)?.shutdown()
+    }
+
     override fun toString(): String = executor.toString()
     override fun equals(other: Any?): Boolean = other is ExecutorCoroutineDispatcherBase && other.executor === executor
     override fun hashCode(): Int = System.identityHashCode(executor)
@@ -90,3 +105,14 @@
         with(continuation) { dispatcher.resumeUndispatched(Unit) }
     }
 }
+
+/**
+ * An implementation of [DisposableHandle] that cancels the specified future on dispose.
+ * @suppress **This is unstable API and it is subject to change.**
+ */
+public class DisposableFutureHandle(private val future: Future<*>) : DisposableHandle {
+    override fun dispose() {
+        future.cancel(false)
+    }
+    override fun toString(): String = "DisposableFutureHandle[$future]"
+}
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Future.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Future.kt
new file mode 100644
index 0000000..b10f0cd
--- /dev/null
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Future.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+@file:JvmMultifileClass
+@file:JvmName("JobKt")
+
+package kotlinx.coroutines.experimental
+
+import java.util.concurrent.*
+
+/**
+ * Cancels a specified [future] when this job is complete.
+ *
+ * This is a shortcut for the following code with slightly more efficient implementation (one fewer object created).
+ * ```
+ * invokeOnCompletion { future.cancel(false) }
+ * ```
+ */
+public fun Job.cancelFutureOnCompletion(future: Future<*>): DisposableHandle =
+    invokeOnCompletion(handler = CancelFutureOnCompletion(this, future))
+
+private class CancelFutureOnCompletion(
+    job: Job,
+    private val future: Future<*>
+) : JobNode<Job>(job)  {
+    override fun invoke(reason: Throwable?) {
+        // Don't interrupt when cancelling future on completion, because no one is going to reset this
+        // interruption flag and it will cause spurious failures elsewhere
+        future.cancel(false)
+    }
+    override fun toString() = "CancelFutureOnCompletion[$future]"
+}
+
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonScheduled.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Runnable.kt
similarity index 67%
rename from common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonScheduled.kt
rename to core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Runnable.kt
index d9181d0..83e239d 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonScheduled.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Runnable.kt
@@ -16,6 +16,14 @@
 
 package kotlinx.coroutines.experimental
 
-public expect suspend fun <T> withTimeout(time: Int, block: suspend CoroutineScope.() -> T): T
+/**
+ * A runnable task for [CoroutineDispatcher.dispatch].
+ */
+public actual typealias Runnable = java.lang.Runnable
 
-public expect suspend fun <T> withTimeoutOrNull(time: Int, block: suspend CoroutineScope.() -> T): T?
+/**
+ * Creates [Runnable] task instance.
+ */
+@Suppress("FunctionName")
+public actual inline fun Runnable(crossinline block: () -> Unit): Runnable =
+    java.lang.Runnable { block() }
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/AbstractChannel.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/AbstractChannel.kt
index a42517a..4ce28da 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/AbstractChannel.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/AbstractChannel.kt
@@ -138,7 +138,7 @@
      */
     protected fun describeSendBuffered(element: E): AddLastDesc<*> = SendBufferedDesc(queue, element)
 
-    private open class SendBufferedDesc<out E>(
+    private open class SendBufferedDesc<E>(
         queue: LockFreeLinkedListHead,
         element: E
     ) : AddLastDesc<SendBuffered<E>>(queue, SendBuffered(element)) {
@@ -153,7 +153,7 @@
      */
     protected fun describeSendConflated(element: E): AddLastDesc<*> = SendConflatedDesc(queue, element)
 
-    private class SendConflatedDesc<out E>(
+    private class SendConflatedDesc<E>(
         queue: LockFreeLinkedListHead,
         element: E
     ) : SendBufferedDesc<E>(queue, element) {
@@ -647,7 +647,7 @@
         }
     }
 
-    private inner class TryEnqueueReceiveDesc<in E, R>(
+    private inner class TryEnqueueReceiveDesc<E, R>(
         select: SelectInstance<R>,
         block: suspend (E?) -> R,
         nullOnClose: Boolean
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Actor.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Actor.kt
index 5594cde..54adc81 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Actor.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Actor.kt
@@ -56,7 +56,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
@@ -116,6 +116,7 @@
  * @param capacity capacity of the channel's buffer (no buffer by default).
  * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
  * @param parent explicitly specifies the parent job, overrides job from the [context] (if any).*
+ * @param onCompletion optional completion handler for the actor coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
 public fun <E> actor(
@@ -123,6 +124,7 @@
     capacity: Int = 0,
     start: CoroutineStart = CoroutineStart.DEFAULT,
     parent: Job? = null,
+    onCompletion: CompletionHandler? = null,
     block: suspend ActorScope<E>.() -> Unit
 ): SendChannel<E> {
     val newContext = newCoroutineContext(context, parent)
@@ -130,6 +132,7 @@
     val coroutine = if (start.isLazy)
         LazyActorCoroutine(newContext, channel, block) else
         ActorCoroutine(newContext, channel, active = true)
+    if (onCompletion != null) coroutine.invokeOnCompletion(handler = onCompletion)
     coroutine.start(start, coroutine, block)
     return coroutine
 }
@@ -140,6 +143,16 @@
     context: CoroutineContext = DefaultDispatcher,
     capacity: Int = 0,
     start: CoroutineStart = CoroutineStart.DEFAULT,
+    parent: Job? = null,
+    block: suspend ActorScope<E>.() -> Unit
+): SendChannel<E> = actor(context, capacity, start, parent, block = block)
+
+/** @suppress **Deprecated**: Binary compatibility */
+@Deprecated(message = "Binary compatibility", level = DeprecationLevel.HIDDEN)
+public fun <E> actor(
+    context: CoroutineContext = DefaultDispatcher,
+    capacity: Int = 0,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
     block: suspend ActorScope<E>.() -> Unit
 ): ActorJob<E> =
     actor(context, capacity, start, block = block) as ActorJob<E>
@@ -159,7 +172,8 @@
     parentContext: CoroutineContext,
     channel: Channel<E>,
     private val block: suspend ActorScope<E>.() -> Unit
-) : ActorCoroutine<E>(parentContext, channel, active = false), SelectClause2<E, SendChannel<E>> {
+) : ActorCoroutine<E>(parentContext, channel, active = false),
+    SelectClause2<E, SendChannel<E>> {
     override fun onStart() {
         block.startCoroutineCancellable(this, this)
     }
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Channels.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Channels.kt
index 4623ece..87abbf5 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Channels.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Channels.kt
@@ -78,7 +78,7 @@
 /**
  * Subscribes to this [BroadcastChannel] and performs the specified action for each received element.
  */
-public inline suspend fun <E> BroadcastChannel<E>.consumeEach(action: (E) -> Unit) =
+public suspend inline fun <E> BroadcastChannel<E>.consumeEach(action: (E) -> Unit) =
     consume {
         for (element in this) action(element)
     }
@@ -93,24 +93,78 @@
 // -------- Operations on ReceiveChannel --------
 
 /**
+ * Returns a [CompletionHandler] that invokes [cancel][ReceiveChannel.cancel] on the [ReceiveChannel]
+ * with the corresponding cause. See also [ReceiveChannel.consume].
+ *
+ * **WARNING**: It is planned that in the future a second invocation of this method
+ * on an channel that is already being consumed is going to fail fast, that is
+ * immediately throw an [IllegalStateException].
+ * See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/167)
+ * for details.
+ */
+public fun ReceiveChannel<*>.consumes(): CompletionHandler =
+    { cause: Throwable? -> cancel(cause) }
+
+/**
+ * Returns a [CompletionHandler] that invokes [cancel][ReceiveChannel.cancel] on all the
+ * specified [ReceiveChannel] instances with the corresponding cause.
+ * See also [ReceiveChannel.consumes()] for a version on one channel.
+ */
+public fun consumesAll(vararg channels: ReceiveChannel<*>): CompletionHandler =
+    { cause: Throwable? ->
+        var exception: Throwable? = null
+        for (channel in channels)
+            try {
+                channel.cancel(cause)
+            } catch (e: Throwable) {
+                if (exception == null) {
+                    exception = e
+                } else {
+                    exception.addSuppressed(e)
+                }
+            }
+        exception?.let { throw it }
+    }
+
+/**
  * Makes sure that the given [block] consumes all elements from the given channel
  * by always invoking [cancel][ReceiveChannel.cancel] after the execution of the block.
+ *
+ * **WARNING**: It is planned that in the future a second invocation of this method
+ * on an channel that is already being consumed is going to fail fast, that is
+ * immediately throw an [IllegalStateException].
+ * See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/167)
+ * for details.
+ *
+ * The operation is _terminal_.
  */
-public inline fun <E, R> ReceiveChannel<E>.consume(block: ReceiveChannel<E>.() -> R): R =
+public inline fun <E, R> ReceiveChannel<E>.consume(block: ReceiveChannel<E>.() -> R): R {
+    var cause: Throwable? = null
     try {
-        block()
+        return block()
+    } catch (e: Throwable) {
+        cause = e
+        throw e
     } finally {
-        cancel()
+        cancel(cause)
     }
+}
 
 /**
  * Performs the given [action] for each received element.
  *
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * **WARNING**: It is planned that in the future a second invocation of this method
+ * on an channel that is already being consumed is going to fail fast, that is
+ * immediately throw an [IllegalStateException].
+ * See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/167)
+ * for details.
+ *
+ * The operation is _terminal_.
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.consumeEach(action: (E) -> Unit) =
+public suspend inline fun <E> ReceiveChannel<E>.consumeEach(action: (E) -> Unit) =
     consume {
-        for (element in this) action(element)
+        for (e in this) action(e)
     }
 
 /**
@@ -123,9 +177,10 @@
 /**
  * Performs the given [action] for each received element.
  *
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * The operation is _terminal_.
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.consumeEachIndexed(action: (IndexedValue<E>) -> Unit) {
+public suspend inline fun <E> ReceiveChannel<E>.consumeEachIndexed(action: (IndexedValue<E>) -> Unit) {
     var index = 0
     consumeEach {
         action(IndexedValue(index++, it))
@@ -136,7 +191,7 @@
  * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.elementAt(index: Int): E =
     elementAtOrElse(index) { throw IndexOutOfBoundsException("ReceiveChannel doesn't contain element at index $index.") }
@@ -145,9 +200,9 @@
  * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.elementAtOrElse(index: Int, defaultValue: (Int) -> E): E =
+public suspend inline fun <E> ReceiveChannel<E>.elementAtOrElse(index: Int, defaultValue: (Int) -> E): E =
     consume {
         if (index < 0)
             return defaultValue(index)
@@ -163,7 +218,7 @@
  * Returns an element at the given [index] or `null` if the [index] is out of bounds of this channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.elementAtOrNull(index: Int): E? =
     consume {
@@ -181,18 +236,18 @@
  * Returns the first element matching the given [predicate], or `null` if no such element was found.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.find(predicate: (E) -> Boolean): E? =
+public suspend inline fun <E> ReceiveChannel<E>.find(predicate: (E) -> Boolean): E? =
     firstOrNull(predicate)
 
 /**
  * Returns the last element matching the given [predicate], or `null` if no such element was found.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.findLast(predicate: (E) -> Boolean): E? =
+public suspend inline fun <E> ReceiveChannel<E>.findLast(predicate: (E) -> Boolean): E? =
     lastOrNull(predicate)
 
 /**
@@ -200,7 +255,7 @@
  * @throws [NoSuchElementException] if the channel is empty.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.first(): E =
     consume {
@@ -215,9 +270,9 @@
  * @throws [NoSuchElementException] if no such element is found.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.first(predicate: (E) -> Boolean): E {
+public suspend inline fun <E> ReceiveChannel<E>.first(predicate: (E) -> Boolean): E {
     consumeEach {
         if (predicate(it)) return it
     }
@@ -228,7 +283,7 @@
  * Returns the first element, or `null` if the channel is empty.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.firstOrNull(): E? =
     consume {
@@ -242,7 +297,7 @@
  * Returns the first element matching the given [predicate], or `null` if element was not found.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public inline suspend fun <E> ReceiveChannel<E>.firstOrNull(predicate: (E) -> Boolean): E? {
     consumeEach {
@@ -255,7 +310,7 @@
  * Returns first index of [element], or -1 if the channel does not contain element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.indexOf(element: E): Int {
     var index = 0
@@ -271,9 +326,9 @@
  * Returns index of the first element matching the given [predicate], or -1 if the channel does not contain such element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.indexOfFirst(predicate: (E) -> Boolean): Int {
+public suspend inline fun <E> ReceiveChannel<E>.indexOfFirst(predicate: (E) -> Boolean): Int {
     var index = 0
     consumeEach {
         if (predicate(it))
@@ -287,7 +342,7 @@
  * Returns index of the last element matching the given [predicate], or -1 if the channel does not contain such element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public inline suspend fun <E> ReceiveChannel<E>.indexOfLast(predicate: (E) -> Boolean): Int {
     var lastIndex = -1
@@ -305,7 +360,7 @@
  * @throws [NoSuchElementException] if the channel is empty.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.last(): E =
     consume {
@@ -323,9 +378,9 @@
  * @throws [NoSuchElementException] if no such element is found.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.last(predicate: (E) -> Boolean): E {
+public suspend inline fun <E> ReceiveChannel<E>.last(predicate: (E) -> Boolean): E {
     var last: E? = null
     var found = false
     consumeEach {
@@ -343,7 +398,7 @@
  * Returns last index of [element], or -1 if the channel does not contain element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.lastIndexOf(element: E): Int {
     var lastIndex = -1
@@ -360,7 +415,7 @@
  * Returns the last element, or `null` if the channel is empty.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.lastOrNull(): E? =
     consume {
@@ -377,9 +432,9 @@
  * Returns the last element matching the given [predicate], or `null` if no such element was found.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.lastOrNull(predicate: (E) -> Boolean): E? {
+public suspend inline fun <E> ReceiveChannel<E>.lastOrNull(predicate: (E) -> Boolean): E? {
     var last: E? = null
     consumeEach {
         if (predicate(it)) {
@@ -393,7 +448,7 @@
  * Returns the single element, or throws an exception if the channel is empty or has more than one element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.single(): E =
     consume {
@@ -410,9 +465,9 @@
  * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.single(predicate: (E) -> Boolean): E {
+public suspend inline fun <E> ReceiveChannel<E>.single(predicate: (E) -> Boolean): E {
     var single: E? = null
     var found = false
     consumeEach {
@@ -431,7 +486,7 @@
  * Returns single element, or `null` if the channel is empty or has more than one element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.singleOrNull(): E? =
     consume {
@@ -448,9 +503,9 @@
  * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.singleOrNull(predicate: (E) -> Boolean): E? {
+public suspend inline fun <E> ReceiveChannel<E>.singleOrNull(predicate: (E) -> Boolean): E? {
     var single: E? = null
     var found = false
     consumeEach {
@@ -468,22 +523,20 @@
  * Returns a channel containing all elements except first [n] elements.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public fun <E> ReceiveChannel<E>.drop(n: Int, context: CoroutineContext = Unconfined): ReceiveChannel<E> =
-    produce(context) {
-        consume {
-            require(n >= 0) { "Requested element count $n is less than zero." }
-            var remaining: Int = n
-            if (remaining > 0)
-                for (element in this@drop) {
-                    remaining--
-                    if (remaining == 0)
-                        break
-                }
-            for (element in this@drop) {
-                send(element)
+    produce(context, onCompletion = consumes()) {
+        require(n >= 0) { "Requested element count $n is less than zero." }
+        var remaining: Int = n
+        if (remaining > 0)
+            for (e in this@drop) {
+                remaining--
+                if (remaining == 0)
+                    break
             }
+        for (e in this@drop) {
+            send(e)
         }
     }
 
@@ -491,21 +544,19 @@
  * Returns a channel containing all elements except first elements that satisfy the given [predicate].
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E> ReceiveChannel<E>.dropWhile(context: CoroutineContext = Unconfined, predicate: suspend (E) -> Boolean): ReceiveChannel<E> =
-    produce(context) {
-        consume {
-            for (element in this@dropWhile) {
-                if (!predicate(element)) {
-                    send(element)
-                    break
-                }
+    produce(context, onCompletion = consumes()) {
+        for (e in this@dropWhile) {
+            if (!predicate(e)) {
+                send(e)
+                break
             }
-            for (element in this@dropWhile) {
-                send(element)
-            }
+        }
+        for (e in this@dropWhile) {
+            send(e)
         }
     }
 
@@ -513,13 +564,13 @@
  * Returns a channel containing only elements matching the given [predicate].
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E> ReceiveChannel<E>.filter(context: CoroutineContext = Unconfined, predicate: suspend (E) -> Boolean): ReceiveChannel<E> =
-    produce(context) {
-        consumeEach {
-            if (predicate(it)) send(it)
+    produce(context, onCompletion = consumes()) {
+        for (e in this@filter) {
+            if (predicate(e)) send(e)
         }
     }
 
@@ -529,14 +580,14 @@
  * and returns the result of predicate evaluation on the element.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E> ReceiveChannel<E>.filterIndexed(context: CoroutineContext = Unconfined, predicate: suspend (index: Int, E) -> Boolean): ReceiveChannel<E> =
-    produce(context) {
+    produce(context, onCompletion = consumes()) {
         var index = 0
-        consumeEach {
-            if (predicate(index++, it)) send(it)
+        for (e in this@filterIndexed) {
+            if (predicate(index++, e)) send(e)
         }
     }
 
@@ -546,9 +597,9 @@
  * and returns the result of predicate evaluation on the element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, C : MutableCollection<in E>> ReceiveChannel<E>.filterIndexedTo(destination: C, predicate: (index: Int, E) -> Boolean): C {
+public suspend inline fun <E, C : MutableCollection<in E>> ReceiveChannel<E>.filterIndexedTo(destination: C, predicate: (index: Int, E) -> Boolean): C {
     consumeEachIndexed { (index, element) ->
         if (predicate(index, element)) destination.add(element)
     }
@@ -561,9 +612,9 @@
  * and returns the result of predicate evaluation on the element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, C : SendChannel<E>> ReceiveChannel<E>.filterIndexedTo(destination: C, predicate: (index: Int, E) -> Boolean): C {
+public suspend inline fun <E, C : SendChannel<E>> ReceiveChannel<E>.filterIndexedTo(destination: C, predicate: (index: Int, E) -> Boolean): C {
     consumeEachIndexed { (index, element) ->
         if (predicate(index, element)) destination.send(element)
     }
@@ -574,18 +625,13 @@
  * Returns a channel containing all elements not matching the given [predicate].
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E> ReceiveChannel<E>.filterNot(context: CoroutineContext = Unconfined, predicate: suspend (E) -> Boolean): ReceiveChannel<E> =
     filter(context) { !predicate(it) }
 
 /**
- * Returns a channel containing all elements not matching the given [predicate].
- *
- * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
- *
  * @suppress **Deprecated**: For binary compatibility only
  */
 @Deprecated("For binary compatibility only", level = DeprecationLevel.HIDDEN)
@@ -595,7 +641,7 @@
  * Returns a channel containing all elements that are not `null`.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 @Suppress("UNCHECKED_CAST")
 public fun <E : Any> ReceiveChannel<E?>.filterNotNull(): ReceiveChannel<E> =
@@ -605,7 +651,7 @@
  * Appends all elements that are not `null` to the given [destination].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E : Any, C : MutableCollection<in E>> ReceiveChannel<E?>.filterNotNullTo(destination: C): C {
     consumeEach {
@@ -618,7 +664,7 @@
  * Appends all elements that are not `null` to the given [destination].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E : Any, C : SendChannel<E>> ReceiveChannel<E?>.filterNotNullTo(destination: C): C {
     consumeEach {
@@ -631,9 +677,9 @@
  * Appends all elements not matching the given [predicate] to the given [destination].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, C : MutableCollection<in E>> ReceiveChannel<E>.filterNotTo(destination: C, predicate: (E) -> Boolean): C {
+public suspend inline fun <E, C : MutableCollection<in E>> ReceiveChannel<E>.filterNotTo(destination: C, predicate: (E) -> Boolean): C {
     consumeEach {
         if (!predicate(it)) destination.add(it)
     }
@@ -644,9 +690,9 @@
  * Appends all elements not matching the given [predicate] to the given [destination].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, C : SendChannel<E>> ReceiveChannel<E>.filterNotTo(destination: C, predicate: (E) -> Boolean): C {
+public suspend inline fun <E, C : SendChannel<E>> ReceiveChannel<E>.filterNotTo(destination: C, predicate: (E) -> Boolean): C {
     consumeEach {
         if (!predicate(it)) destination.send(it)
     }
@@ -657,9 +703,9 @@
  * Appends all elements matching the given [predicate] to the given [destination].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, C : MutableCollection<in E>> ReceiveChannel<E>.filterTo(destination: C, predicate: (E) -> Boolean): C {
+public suspend inline fun <E, C : MutableCollection<in E>> ReceiveChannel<E>.filterTo(destination: C, predicate: (E) -> Boolean): C {
     consumeEach {
         if (predicate(it)) destination.add(it)
     }
@@ -670,9 +716,9 @@
  * Appends all elements matching the given [predicate] to the given [destination].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, C : SendChannel<E>> ReceiveChannel<E>.filterTo(destination: C, predicate: (E) -> Boolean): C {
+public suspend inline fun <E, C : SendChannel<E>> ReceiveChannel<E>.filterTo(destination: C, predicate: (E) -> Boolean): C {
     consumeEach {
         if (predicate(it)) destination.send(it)
     }
@@ -683,20 +729,18 @@
  * Returns a channel containing first [n] elements.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public fun <E> ReceiveChannel<E>.take(n: Int, context: CoroutineContext = Unconfined): ReceiveChannel<E> =
-    produce(context) {
-        consume {
-            if (n == 0) return@produce
-            require(n >= 0) { "Requested element count $n is less than zero." }
-            var remaining: Int = n
-            for (element in this@take) {
-                send(element)
-                remaining--
-                if (remaining == 0)
-                    return@produce
-            }
+    produce(context, onCompletion = consumes()) {
+        if (n == 0) return@produce
+        require(n >= 0) { "Requested element count $n is less than zero." }
+        var remaining: Int = n
+        for (e in this@take) {
+            send(e)
+            remaining--
+            if (remaining == 0)
+                return@produce
         }
     }
 
@@ -704,14 +748,14 @@
  * Returns a channel containing first elements satisfying the given [predicate].
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E> ReceiveChannel<E>.takeWhile(context: CoroutineContext = Unconfined, predicate: suspend (E) -> Boolean): ReceiveChannel<E> =
-    produce(context) {
-        consumeEach {
-            if (!predicate(it)) return@produce
-            send(it)
+    produce(context, onCompletion = consumes()) {
+        for (e in this@takeWhile) {
+            if (!predicate(e)) return@produce
+            send(e)
         }
     }
 
@@ -724,9 +768,9 @@
  * The returned map preserves the entry iteration order of the original channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, K, V> ReceiveChannel<E>.associate(transform: (E) -> Pair<K, V>): Map<K, V> =
+public suspend inline fun <E, K, V> ReceiveChannel<E>.associate(transform: (E) -> Pair<K, V>): Map<K, V> =
     associateTo(LinkedHashMap(), transform)
 
 /**
@@ -738,9 +782,9 @@
  * The returned map preserves the entry iteration order of the original channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, K> ReceiveChannel<E>.associateBy(keySelector: (E) -> K): Map<K, E> =
+public suspend inline fun <E, K> ReceiveChannel<E>.associateBy(keySelector: (E) -> K): Map<K, E> =
     associateByTo(LinkedHashMap(), keySelector)
 
 /**
@@ -751,9 +795,9 @@
  * The returned map preserves the entry iteration order of the original channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, K, V> ReceiveChannel<E>.associateBy(keySelector: (E) -> K, valueTransform: (E) -> V): Map<K, V> =
+public suspend inline fun <E, K, V> ReceiveChannel<E>.associateBy(keySelector: (E) -> K, valueTransform: (E) -> V): Map<K, V> =
     associateByTo(LinkedHashMap(), keySelector, valueTransform)
 
 /**
@@ -764,9 +808,9 @@
  * If any two elements would have the same key returned by [keySelector] the last one gets added to the map.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, K, M : MutableMap<in K, in E>> ReceiveChannel<E>.associateByTo(destination: M, keySelector: (E) -> K): M {
+public suspend inline fun <E, K, M : MutableMap<in K, in E>> ReceiveChannel<E>.associateByTo(destination: M, keySelector: (E) -> K): M {
     consumeEach {
         destination.put(keySelector(it), it)
     }
@@ -781,9 +825,9 @@
  * If any two elements would have the same key returned by [keySelector] the last one gets added to the map.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, K, V, M : MutableMap<in K, in V>> ReceiveChannel<E>.associateByTo(destination: M, keySelector: (E) -> K, valueTransform: (E) -> V): M {
+public suspend inline fun <E, K, V, M : MutableMap<in K, in V>> ReceiveChannel<E>.associateByTo(destination: M, keySelector: (E) -> K, valueTransform: (E) -> V): M {
     consumeEach {
         destination.put(keySelector(it), valueTransform(it))
     }
@@ -797,9 +841,9 @@
  * If any of two pairs would have the same key the last one gets added to the map.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, K, V, M : MutableMap<in K, in V>> ReceiveChannel<E>.associateTo(destination: M, transform: (E) -> Pair<K, V>): M {
+public suspend inline fun <E, K, V, M : MutableMap<in K, in V>> ReceiveChannel<E>.associateTo(destination: M, transform: (E) -> Pair<K, V>): M {
     consumeEach {
         destination += transform(it)
     }
@@ -811,7 +855,7 @@
  * and appends the results to the given [destination].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E, C : SendChannel<E>> ReceiveChannel<E>.toChannel(destination: C): C {
     consumeEach {
@@ -824,7 +868,7 @@
  * Appends all elements to the given [destination] collection.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E, C : MutableCollection<in E>> ReceiveChannel<E>.toCollection(destination: C): C {
     consumeEach {
@@ -837,7 +881,7 @@
  * Returns a [List] containing all elements.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.toList(): List<E> =
     this.toMutableList()
@@ -846,7 +890,7 @@
  * Returns a [Map] filled with all elements of this channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <K, V> ReceiveChannel<Pair<K, V>>.toMap(): Map<K, V> =
     toMap(LinkedHashMap())
@@ -855,7 +899,7 @@
  * Returns a [MutableMap] filled with all elements of this channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <K, V, M : MutableMap<in K, in V>> ReceiveChannel<Pair<K, V>>.toMap(destination: M): M {
     consumeEach {
@@ -868,7 +912,7 @@
  * Returns a [MutableList] filled with all elements of this channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.toMutableList(): MutableList<E> =
     toCollection(ArrayList())
@@ -879,22 +923,22 @@
  * The returned set preserves the element iteration order of the original channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.toSet(): Set<E> =
-    toCollection(LinkedHashSet())
+    this.toMutableSet()
 
 /**
  * Returns a single channel of all elements from results of [transform] function being invoked on each element of original channel.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, R> ReceiveChannel<E>.flatMap(context: CoroutineContext = Unconfined, transform: suspend (E) -> ReceiveChannel<R>): ReceiveChannel<R> =
-    produce(context) {
-        consumeEach {
-            transform(it).toChannel(this)
+    produce(context, onCompletion = consumes()) {
+        for (e in this@flatMap) {
+            transform(e).toChannel(this)
         }
     }
 
@@ -905,9 +949,9 @@
  * The returned map preserves the entry iteration order of the keys produced from the original channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, K> ReceiveChannel<E>.groupBy(keySelector: (E) -> K): Map<K, List<E>> =
+public suspend inline fun <E, K> ReceiveChannel<E>.groupBy(keySelector: (E) -> K): Map<K, List<E>> =
     groupByTo(LinkedHashMap(), keySelector)
 
 /**
@@ -918,9 +962,9 @@
  * The returned map preserves the entry iteration order of the keys produced from the original channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, K, V> ReceiveChannel<E>.groupBy(keySelector: (E) -> K, valueTransform: (E) -> V): Map<K, List<V>> =
+public suspend inline fun <E, K, V> ReceiveChannel<E>.groupBy(keySelector: (E) -> K, valueTransform: (E) -> V): Map<K, List<V>> =
     groupByTo(LinkedHashMap(), keySelector, valueTransform)
 
 /**
@@ -930,9 +974,9 @@
  * @return The [destination] map.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, K, M : MutableMap<in K, MutableList<E>>> ReceiveChannel<E>.groupByTo(destination: M, keySelector: (E) -> K): M {
+public suspend inline fun <E, K, M : MutableMap<in K, MutableList<E>>> ReceiveChannel<E>.groupByTo(destination: M, keySelector: (E) -> K): M {
     consumeEach {
         val key = keySelector(it)
         val list = destination.getOrPut(key) { ArrayList() }
@@ -949,9 +993,9 @@
  * @return The [destination] map.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, K, V, M : MutableMap<in K, MutableList<V>>> ReceiveChannel<E>.groupByTo(destination: M, keySelector: (E) -> K, valueTransform: (E) -> V): M {
+public suspend inline fun <E, K, V, M : MutableMap<in K, MutableList<V>>> ReceiveChannel<E>.groupByTo(destination: M, keySelector: (E) -> K, valueTransform: (E) -> V): M {
     consumeEach {
         val key = keySelector(it)
         val list = destination.getOrPut(key) { ArrayList() }
@@ -965,11 +1009,11 @@
  * to each element in the original channel.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-// todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
+// todo: mark transform with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, R> ReceiveChannel<E>.map(context: CoroutineContext = Unconfined, transform: suspend (E) -> R): ReceiveChannel<R> =
-    produce(context) {
+    produce(context, onCompletion = consumes()) {
         consumeEach {
             send(transform(it))
         }
@@ -982,14 +1026,14 @@
  * and returns the result of the transform applied to the element.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, R> ReceiveChannel<E>.mapIndexed(context: CoroutineContext = Unconfined, transform: suspend (index: Int, E) -> R): ReceiveChannel<R> =
-    produce(context) {
+    produce(context, onCompletion = consumes()) {
         var index = 0
-        consumeEach {
-            send(transform(index++, it))
+        for (e in this@mapIndexed) {
+            send(transform(index++, e))
         }
     }
 
@@ -1000,7 +1044,7 @@
  * and returns the result of the transform applied to the element.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, R : Any> ReceiveChannel<E>.mapIndexedNotNull(context: CoroutineContext = Unconfined, transform: suspend (index: Int, E) -> R?): ReceiveChannel<R> =
@@ -1013,9 +1057,9 @@
  * and returns the result of the transform applied to the element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R : Any, C : MutableCollection<in R>> ReceiveChannel<E>.mapIndexedNotNullTo(destination: C, transform: (index: Int, E) -> R?): C {
+public suspend inline fun <E, R : Any, C : MutableCollection<in R>> ReceiveChannel<E>.mapIndexedNotNullTo(destination: C, transform: (index: Int, E) -> R?): C {
     consumeEachIndexed { (index, element) ->
         transform(index, element)?.let { destination.add(it) }
     }
@@ -1029,9 +1073,9 @@
  * and returns the result of the transform applied to the element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R : Any, C : SendChannel<R>> ReceiveChannel<E>.mapIndexedNotNullTo(destination: C, transform: (index: Int, E) -> R?): C {
+public suspend inline fun <E, R : Any, C : SendChannel<R>> ReceiveChannel<E>.mapIndexedNotNullTo(destination: C, transform: (index: Int, E) -> R?): C {
     consumeEachIndexed { (index, element) ->
         transform(index, element)?.let { destination.send(it) }
     }
@@ -1045,9 +1089,9 @@
  * and returns the result of the transform applied to the element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R, C : MutableCollection<in R>> ReceiveChannel<E>.mapIndexedTo(destination: C, transform: (index: Int, E) -> R): C {
+public suspend inline fun <E, R, C : MutableCollection<in R>> ReceiveChannel<E>.mapIndexedTo(destination: C, transform: (index: Int, E) -> R): C {
     var index = 0
     consumeEach {
         destination.add(transform(index++, it))
@@ -1062,9 +1106,9 @@
  * and returns the result of the transform applied to the element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R, C : SendChannel<R>> ReceiveChannel<E>.mapIndexedTo(destination: C, transform: (index: Int, E) -> R): C {
+public suspend inline fun <E, R, C : SendChannel<R>> ReceiveChannel<E>.mapIndexedTo(destination: C, transform: (index: Int, E) -> R): C {
     var index = 0
     consumeEach {
         destination.send(transform(index++, it))
@@ -1077,7 +1121,7 @@
  * to each element in the original channel.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, R : Any> ReceiveChannel<E>.mapNotNull(context: CoroutineContext = Unconfined, transform: suspend (E) -> R?): ReceiveChannel<R> =
@@ -1088,9 +1132,9 @@
  * and appends only the non-null results to the given [destination].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R : Any, C : MutableCollection<in R>> ReceiveChannel<E>.mapNotNullTo(destination: C, transform: (E) -> R?): C {
+public suspend inline fun <E, R : Any, C : MutableCollection<in R>> ReceiveChannel<E>.mapNotNullTo(destination: C, transform: (E) -> R?): C {
     consumeEach {
         transform(it)?.let { destination.add(it) }
     }
@@ -1102,9 +1146,9 @@
  * and appends only the non-null results to the given [destination].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R : Any, C : SendChannel<R>> ReceiveChannel<E>.mapNotNullTo(destination: C, transform: (E) -> R?): C {
+public suspend inline fun <E, R : Any, C : SendChannel<R>> ReceiveChannel<E>.mapNotNullTo(destination: C, transform: (E) -> R?): C {
     consumeEach {
         transform(it)?.let { destination.send(it) }
     }
@@ -1116,9 +1160,9 @@
  * and appends the results to the given [destination].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R, C : MutableCollection<in R>> ReceiveChannel<E>.mapTo(destination: C, transform: (E) -> R): C {
+public suspend inline fun <E, R, C : MutableCollection<in R>> ReceiveChannel<E>.mapTo(destination: C, transform: (E) -> R): C {
     consumeEach {
         destination.add(transform(it))
     }
@@ -1130,9 +1174,9 @@
  * and appends the results to the given [destination].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R, C : SendChannel<R>> ReceiveChannel<E>.mapTo(destination: C, transform: (E) -> R): C {
+public suspend inline fun <E, R, C : SendChannel<R>> ReceiveChannel<E>.mapTo(destination: C, transform: (E) -> R): C {
     consumeEach {
         destination.send(transform(it))
     }
@@ -1143,13 +1187,13 @@
  * Returns a channel of [IndexedValue] for each element of the original channel.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public fun <E> ReceiveChannel<E>.withIndex(context: CoroutineContext = Unconfined): ReceiveChannel<IndexedValue<E>> =
-    produce(context) {
+    produce(context, onCompletion = consumes()) {
         var index = 0
-        consumeEach {
-            send(IndexedValue(index++, it))
+        for (e in this@withIndex) {
+            send(IndexedValue(index++, e))
         }
     }
 
@@ -1159,7 +1203,7 @@
  * The elements in the resulting channel are in the same order as they were in the source channel.
  *
  * The operation is _intermediate_ and _stateful_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public fun <E> ReceiveChannel<E>.distinct(): ReceiveChannel<E> =
     this.distinctBy { it }
@@ -1171,16 +1215,16 @@
  * The elements in the resulting channel are in the same order as they were in the source channel.
  *
  * The operation is _intermediate_ and _stateful_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, K> ReceiveChannel<E>.distinctBy(context: CoroutineContext = Unconfined, selector: suspend (E) -> K): ReceiveChannel<E> =
-    produce(context) {
+    produce(context, onCompletion = consumes()) {
         val keys = HashSet<K>()
-        consumeEach {
-            val k = selector(it)
+        for (e in this@distinctBy) {
+            val k = selector(e)
             if (k !in keys) {
-                send(it)
+                send(e)
                 keys += k
             }
         }
@@ -1192,23 +1236,18 @@
  * The returned set preserves the element iteration order of the original channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public suspend fun <E> ReceiveChannel<E>.toMutableSet(): MutableSet<E> {
-    val set = LinkedHashSet<E>()
-    consumeEach {
-        set.add(it)
-    }
-    return set
-}
+public suspend fun <E> ReceiveChannel<E>.toMutableSet(): MutableSet<E> =
+    toCollection(LinkedHashSet())
 
 /**
  * Returns `true` if all elements match the given [predicate].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.all(predicate: (E) -> Boolean): Boolean {
+public suspend inline fun <E> ReceiveChannel<E>.all(predicate: (E) -> Boolean): Boolean {
     consumeEach {
         if (!predicate(it)) return false
     }
@@ -1219,7 +1258,7 @@
  * Returns `true` if channel has at least one element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.any(): Boolean =
     consume {
@@ -1230,9 +1269,9 @@
  * Returns `true` if at least one element matches the given [predicate].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.any(predicate: (E) -> Boolean): Boolean {
+public suspend inline fun <E> ReceiveChannel<E>.any(predicate: (E) -> Boolean): Boolean {
     consumeEach {
         if (predicate(it)) return true
     }
@@ -1243,7 +1282,7 @@
  * Returns the number of elements in this channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.count(): Int {
     var count = 0
@@ -1255,9 +1294,9 @@
  * Returns the number of elements matching the given [predicate].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.count(predicate: (E) -> Boolean): Int {
+public suspend inline fun <E> ReceiveChannel<E>.count(predicate: (E) -> Boolean): Int {
     var count = 0
     consumeEach {
         if (predicate(it)) count++
@@ -1269,9 +1308,9 @@
  * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R> ReceiveChannel<E>.fold(initial: R, operation: (acc: R, E) -> R): R {
+public suspend inline fun <E, R> ReceiveChannel<E>.fold(initial: R, operation: (acc: R, E) -> R): R {
     var accumulator = initial
     consumeEach {
         accumulator = operation(accumulator, it)
@@ -1286,9 +1325,9 @@
  * and the element itself, and calculates the next accumulator value.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R> ReceiveChannel<E>.foldIndexed(initial: R, operation: (index: Int, acc: R, E) -> R): R {
+public suspend inline fun <E, R> ReceiveChannel<E>.foldIndexed(initial: R, operation: (index: Int, acc: R, E) -> R): R {
     var index = 0
     var accumulator = initial
     consumeEach {
@@ -1301,9 +1340,9 @@
  * Returns the first element yielding the largest value of the given function or `null` if there are no elements.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R : Comparable<R>> ReceiveChannel<E>.maxBy(selector: (E) -> R): E? =
+public suspend inline fun <E, R : Comparable<R>> ReceiveChannel<E>.maxBy(selector: (E) -> R): E? =
     consume {
         val iterator = iterator()
         if (!iterator.hasNext()) return null
@@ -1324,7 +1363,7 @@
  * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.maxWith(comparator: Comparator<in E>): E? =
     consume {
@@ -1342,9 +1381,9 @@
  * Returns the first element yielding the smallest value of the given function or `null` if there are no elements.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E, R : Comparable<R>> ReceiveChannel<E>.minBy(selector: (E) -> R): E? =
+public suspend inline fun <E, R : Comparable<R>> ReceiveChannel<E>.minBy(selector: (E) -> R): E? =
     consume {
         val iterator = iterator()
         if (!iterator.hasNext()) return null
@@ -1365,7 +1404,7 @@
  * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.minWith(comparator: Comparator<in E>): E? =
     consume {
@@ -1383,7 +1422,7 @@
  * Returns `true` if the channel has no elements.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public suspend fun <E> ReceiveChannel<E>.none(): Boolean =
     consume {
@@ -1394,9 +1433,9 @@
  * Returns `true` if no elements match the given [predicate].
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.none(predicate: (E) -> Boolean): Boolean {
+public suspend inline fun <E> ReceiveChannel<E>.none(predicate: (E) -> Boolean): Boolean {
     consumeEach {
         if (predicate(it)) return false
     }
@@ -1407,9 +1446,9 @@
  * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <S, E : S> ReceiveChannel<E>.reduce(operation: (acc: S, E) -> S): S =
+public suspend inline fun <S, E : S> ReceiveChannel<E>.reduce(operation: (acc: S, E) -> S): S =
     consume {
         val iterator = this.iterator()
         if (!iterator.hasNext()) throw UnsupportedOperationException("Empty channel can't be reduced.")
@@ -1427,9 +1466,10 @@
  * and the element itself and calculates the next accumulator value.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <S, E : S> ReceiveChannel<E>.reduceIndexed(operation: (index: Int, acc: S, E) -> S): S =
+// todo: mark operation with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
+public suspend inline fun <S, E : S> ReceiveChannel<E>.reduceIndexed(operation: (index: Int, acc: S, E) -> S): S =
     consume {
         val iterator = this.iterator()
         if (!iterator.hasNext()) throw UnsupportedOperationException("Empty channel can't be reduced.")
@@ -1445,9 +1485,9 @@
  * Returns the sum of all values produced by [selector] function applied to each element in the channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.sumBy(selector: (E) -> Int): Int {
+public suspend inline fun <E> ReceiveChannel<E>.sumBy(selector: (E) -> Int): Int {
     var sum = 0
     consumeEach {
         sum += selector(it)
@@ -1459,9 +1499,9 @@
  * Returns the sum of all values produced by [selector] function applied to each element in the channel.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.sumByDouble(selector: (E) -> Double): Double {
+public suspend inline fun <E> ReceiveChannel<E>.sumByDouble(selector: (E) -> Double): Double {
     var sum = 0.0
     consumeEach {
         sum += selector(it)
@@ -1473,7 +1513,7 @@
  * Returns an original collection containing all the non-`null` elements, throwing an [IllegalArgumentException] if there are any `null` elements.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
 public fun <E : Any> ReceiveChannel<E?>.requireNoNulls(): ReceiveChannel<E> =
     map { it ?: throw IllegalArgumentException("null element found in $this.") }
@@ -1484,9 +1524,9 @@
  * while *second* list contains elements for which [predicate] yielded `false`.
  *
  * The operation is _terminal_.
- * This function [consumes][consume] all elements of the original [ReceiveChannel].
+ * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
  */
-public inline suspend fun <E> ReceiveChannel<E>.partition(predicate: (E) -> Boolean): Pair<List<E>, List<E>> {
+public suspend inline fun <E> ReceiveChannel<E>.partition(predicate: (E) -> Boolean): Pair<List<E>, List<E>> {
     val first = ArrayList<E>()
     val second = ArrayList<E>()
     consumeEach {
@@ -1504,7 +1544,7 @@
  * Resulting channel has length of shortest input channel.
  *
  * The operation is _intermediate_ and _stateless_.
- * This function [consumes][consume] all elements of both the original [ReceiveChannel] and the `other` one.
+ * This function [consumes][ReceiveChannel.consume] all elements of both the original [ReceiveChannel] and the `other` one.
  */
 public infix fun <E, R> ReceiveChannel<E>.zip(other: ReceiveChannel<R>): ReceiveChannel<Pair<E, R>> =
     zip(other) { t1, t2 -> t1 to t2 }
@@ -1515,15 +1555,15 @@
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][consume] all elements of both the original [ReceiveChannel] and the `other` one.
  */
+// todo: mark transform with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, R, V> ReceiveChannel<E>.zip(other: ReceiveChannel<R>, context: CoroutineContext = Unconfined, transform: (a: E, b: R) -> V): ReceiveChannel<V> =
-    produce(context) {
-        other.consume {
-            val otherIterator = other.iterator()
-            this@zip.consumeEach { element1 ->
-                if (!otherIterator.hasNext()) return@consumeEach
-                val element2 = otherIterator.next()
-                send(transform(element1, element2))
-            }
+    produce(context, onCompletion = consumesAll(this, other)) {
+        val otherIterator = other.iterator()
+        this@zip.consumeEach { element1 ->
+            if (!otherIterator.hasNext()) return@consumeEach
+            val element2 = otherIterator.next()
+            send(transform(element1, element2))
         }
     }
 
+
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Produce.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Produce.kt
index 61e6a6f..fc86b0a 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Produce.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Produce.kt
@@ -56,7 +56,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
@@ -70,17 +70,20 @@
  * @param context context of the coroutine. The default value is [DefaultDispatcher].
  * @param capacity capacity of the channel's buffer (no buffer by default).
  * @param parent explicitly specifies the parent job, overrides job from the [context] (if any).*
+ * @param onCompletion optional completion handler for the producer coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
 public fun <E> produce(
     context: CoroutineContext = DefaultDispatcher,
     capacity: Int = 0,
     parent: Job? = null,
+    onCompletion: CompletionHandler? = null,
     block: suspend ProducerScope<E>.() -> Unit
 ): ReceiveChannel<E> {
     val channel = Channel<E>(capacity)
     val newContext = newCoroutineContext(context, parent)
     val coroutine = ProducerCoroutine(newContext, channel)
+    if (onCompletion != null) coroutine.invokeOnCompletion(handler = onCompletion)
     coroutine.start(CoroutineStart.DEFAULT, coroutine, block)
     return coroutine
 }
@@ -90,6 +93,15 @@
 public fun <E> produce(
     context: CoroutineContext = DefaultDispatcher,
     capacity: Int = 0,
+    parent: Job? = null,
+    block: suspend ProducerScope<E>.() -> Unit
+): ReceiveChannel<E> = produce(context, capacity, parent, block = block)
+
+/** @suppress **Deprecated**: Binary compatibility */
+@Deprecated(message = "Binary compatibility", level = DeprecationLevel.HIDDEN)
+public fun <E> produce(
+    context: CoroutineContext = DefaultDispatcher,
+    capacity: Int = 0,
     block: suspend ProducerScope<E>.() -> Unit
 ): ProducerJob<E> =
     produce(context, capacity, block = block) as ProducerJob<E>
diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedList.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedList.kt
index 06e9384..17a0ebb 100644
--- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedList.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedList.kt
@@ -41,15 +41,14 @@
 
 private val REMOVE_PREPARED: Any = Symbol("REMOVE_PREPARED")
 
-/**
- * @suppress **This is unstable API and it is subject to change.**
- */
+/** @suppress **This is unstable API and it is subject to change.** */
 public typealias RemoveFirstDesc<T> = LockFreeLinkedListNode.RemoveFirstDesc<T>
 
-/**
- * @suppress **This is unstable API and it is subject to change.**
- */
-public typealias AddLastDesc<T> = LockFreeLinkedListNode.AddLastDesc<T>
+/** @suppress **This is unstable API and it is subject to change.** */
+public actual typealias AddLastDesc<T> = LockFreeLinkedListNode.AddLastDesc<T>
+
+/** @suppress **This is unstable API and it is subject to change.** */
+public actual typealias AbstractAtomicDesc = LockFreeLinkedListNode.AbstractAtomicDesc
 
 /**
  * Doubly-linked concurrent list node with remove support.
@@ -67,7 +66,7 @@
  * @suppress **This is unstable API and it is subject to change.**
  */
 @Suppress("LeakingThis")
-public open class LockFreeLinkedListNode {
+public actual open class LockFreeLinkedListNode {
     private val _next = atomic<Any>(this) // Node | Removed | OpDescriptor
     private val _prev = atomic<Any>(this) // Node | Removed
     private val _removedRef = atomic<Removed?>(null) // lazily cached removed ref to this
@@ -99,7 +98,7 @@
 
     public val isFresh: Boolean get() = _next.value === this
 
-    public val isRemoved: Boolean get() = next is Removed
+    public actual val isRemoved: Boolean get() = next is Removed
 
     // LINEARIZABLE. Returns Node | Removed
     public val next: Any get() {
@@ -109,6 +108,8 @@
         }
     }
 
+    public actual val nextNode: Node get() = next.unwrap()
+
     // LINEARIZABLE. Returns Node | Removed
     public val prev: Any get() {
         _prev.loop { prev ->
@@ -119,9 +120,11 @@
         }
     }
 
+    public actual val prevNode: Node get() = prev.unwrap()
+
     // ------ addOneIfEmpty ------
 
-    public fun addOneIfEmpty(node: Node): Boolean {
+    public actual fun addOneIfEmpty(node: Node): Boolean {
         node._prev.lazySet(this)
         node._next.lazySet(this)
         while (true) {
@@ -140,7 +143,7 @@
     /**
      * Adds last item to this list.
      */
-    public fun addLast(node: Node) {
+    public actual fun addLast(node: Node) {
         while (true) { // lock-free loop on prev.next
             val prev = prev as Node // sentinel node is never removed, so prev is always defined
             if (prev.addNext(node, this)) return
@@ -152,7 +155,7 @@
     /**
      * Adds last item to this list atomically if the [condition] is true.
      */
-    public inline fun addLastIf(node: Node, crossinline condition: () -> Boolean): Boolean {
+    public actual inline fun addLastIf(node: Node, crossinline condition: () -> Boolean): Boolean {
         val condAdd = makeCondAddOp(node, condition)
         while (true) { // lock-free loop on prev.next
             val prev = prev as Node // sentinel node is never removed, so prev is always defined
@@ -163,7 +166,7 @@
         }
     }
 
-    public inline fun addLastIfPrev(node: Node, predicate: (Node) -> Boolean): Boolean {
+    public actual inline fun addLastIfPrev(node: Node, predicate: (Node) -> Boolean): Boolean {
         while (true) { // lock-free loop on prev.next
             val prev = prev as Node // sentinel node is never removed, so prev is always defined
             if (!predicate(prev)) return false
@@ -171,7 +174,7 @@
         }
     }
 
-    public inline fun addLastIfPrevAndIf(
+    public actual inline fun addLastIfPrevAndIf(
             node: Node,
             predicate: (Node) -> Boolean, // prev node predicate
             crossinline condition: () -> Boolean // atomically checked condition
@@ -239,7 +242,7 @@
      * Removes this node from the list. Returns `true` when removed successfully, or `false` if the node was already
      * removed or if it was not added to any list in the first place.
      */
-    public open fun remove(): Boolean {
+    public actual open fun remove(): Boolean {
         while (true) { // lock-free loop on next
             val next = this.next
             if (next is Removed) return false // was already removed -- don't try to help (original thread will take care)
@@ -273,7 +276,7 @@
         }
     }
 
-    public fun removeFirstOrNull(): Node? {
+    public actual fun removeFirstOrNull(): Node? {
         while (true) { // try to linearize
             val first = next as Node
             if (first === this) return null
@@ -295,7 +298,7 @@
     }
 
     // just peek at item when predicate is true
-    public inline fun <reified T> removeFirstIfIsInstanceOfOrPeekIf(predicate: (T) -> Boolean): T? {
+    public actual inline fun <reified T> removeFirstIfIsInstanceOfOrPeekIf(predicate: (T) -> Boolean): T? {
         while (true) { // try to linearize
             val first = next as Node
             if (first === this) return null
@@ -308,7 +311,7 @@
 
     // ------ multi-word atomic operations helpers ------
 
-    public open class AddLastDesc<out T : Node>(
+    public open class AddLastDesc<T : Node> actual constructor(
         @JvmField val queue: Node,
         @JvmField val node: T
     ) : AbstractAtomicDesc() {
@@ -340,7 +343,7 @@
 
         override fun retry(affected: Node, next: Any): Boolean = next !== queue
 
-        override fun onPrepare(affected: Node, next: Node): Any? {
+        protected override fun onPrepare(affected: Node, next: Node): Any? {
             // Note: onPrepare must use CAS to make sure the stale invocation is not
             // going to overwrite the previous decision on successful preparation.
             // Result of CAS is irrelevant, but we must ensure that it is set when invoker completes
@@ -659,20 +662,20 @@
 }
 
 @PublishedApi
-internal fun Any.unwrap(): Node = if (this is Removed) ref else this as Node
+internal fun Any.unwrap(): Node = (this as? Removed)?.ref ?: this as Node
 
 /**
  * Head (sentinel) item of the linked list that is never removed.
  *
  * @suppress **This is unstable API and it is subject to change.**
  */
-public open class LockFreeLinkedListHead : LockFreeLinkedListNode() {
-    public val isEmpty: Boolean get() = next === this
+public actual open class LockFreeLinkedListHead : LockFreeLinkedListNode() {
+    public actual val isEmpty: Boolean get() = next === this
 
     /**
      * Iterates over all elements in this list of a specified type.
      */
-    public inline fun <reified T : Node> forEach(block: (T) -> Unit) {
+    public actual inline fun <reified T : Node> forEach(block: (T) -> Unit) {
         var cur: Node = next as Node
         while (cur != this) {
             if (cur is T) block(cur)
@@ -681,8 +684,9 @@
     }
 
     // just a defensive programming -- makes sure that list head sentinel is never removed
-    public final override fun remove() = throw UnsupportedOperationException()
-    public final override fun describeRemove(): AtomicDesc? = throw UnsupportedOperationException()
+    public actual final override fun remove(): Nothing = throw UnsupportedOperationException()
+
+    public final override fun describeRemove(): Nothing = throw UnsupportedOperationException()
 
     internal fun validate() {
         var prev: Node = this
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonYield.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/timeunit/TimeUnit.kt
similarity index 73%
copy from common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonYield.kt
copy to core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/timeunit/TimeUnit.kt
index e461c47..8c0a66c 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonYield.kt
+++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/timeunit/TimeUnit.kt
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
-package kotlinx.coroutines.experimental
+package kotlinx.coroutines.experimental.timeunit
 
-public expect suspend fun yield()
\ No newline at end of file
+/**
+ * Time unit type alias for writing multiplatform code.
+ */
+@Suppress("ACTUAL_WITHOUT_EXPECT")
+public actual typealias TimeUnit = java.util.concurrent.TimeUnit
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt
index b14666e..166a4ad 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt
@@ -19,7 +19,7 @@
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
-import kotlin.coroutines.experimental.CoroutineContext
+import kotlin.coroutines.experimental.*
 
 fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) {
     var x = start
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-07.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-07.kt
index d10c5ed..ee74930 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-07.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-07.kt
@@ -19,6 +19,7 @@
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
+import kotlin.coroutines.experimental.*
 
 suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
     while (true) {
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-08.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-08.kt
index 096f435..484cd88 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-08.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-08.kt
@@ -19,6 +19,7 @@
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     val channel = Channel<Int>(4) // create buffered channel
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-09.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-09.kt
index 2a5e064..fe93386 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-09.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-09.kt
@@ -19,6 +19,7 @@
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
+import kotlin.coroutines.experimental.*
 
 data class Ball(var hits: Int)
 
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-01.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-01.kt
index af083f3..d4a0901 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-01.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-01.kt
@@ -18,7 +18,7 @@
 package guide.compose.example01
 
 import kotlinx.coroutines.experimental.*
-import kotlin.system.measureTimeMillis
+import kotlin.system.*
 
 suspend fun doSomethingUsefulOne(): Int {
     delay(1000L) // pretend we are doing something useful here
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-02.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-02.kt
index f39d98e..b6dfd4a 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-02.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-02.kt
@@ -18,7 +18,7 @@
 package guide.compose.example02
 
 import kotlinx.coroutines.experimental.*
-import kotlin.system.measureTimeMillis
+import kotlin.system.*
 
 suspend fun doSomethingUsefulOne(): Int {
     delay(1000L) // pretend we are doing something useful here
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-03.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-03.kt
index adc8eab..d3745fe 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-03.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-03.kt
@@ -18,7 +18,7 @@
 package guide.compose.example03
 
 import kotlinx.coroutines.experimental.*
-import kotlin.system.measureTimeMillis
+import kotlin.system.*
 
 suspend fun doSomethingUsefulOne(): Int {
     delay(1000L) // pretend we are doing something useful here
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-04.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-04.kt
index 4161bdd..f85002c 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-04.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-04.kt
@@ -18,7 +18,7 @@
 package guide.compose.example04
 
 import kotlinx.coroutines.experimental.*
-import kotlin.system.measureTimeMillis
+import kotlin.system.*
 
 suspend fun doSomethingUsefulOne(): Int {
     delay(1000L) // pretend we are doing something useful here
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-01.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-01.kt
index cfe3a48..9472d06 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-01.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-01.kt
@@ -18,6 +18,7 @@
 package guide.context.example01
 
 import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     val jobs = arrayListOf<Job>()
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-02.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-02.kt
index 286860d..a62929f 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-02.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-02.kt
@@ -18,6 +18,7 @@
 package guide.context.example02
 
 import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     val jobs = arrayListOf<Job>()
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-03.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-03.kt
index ce62288..86b3004 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-03.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-03.kt
@@ -18,6 +18,7 @@
 package guide.context.example03
 
 import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 
 fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
 
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-05.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-05.kt
index b58185e..8eb44ff 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-05.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-05.kt
@@ -18,6 +18,7 @@
 package guide.context.example05
 
 import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     println("My job is ${coroutineContext[Job]}")
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-06.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-06.kt
index b69a2af..ecb012c 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-06.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-06.kt
@@ -18,6 +18,7 @@
 package guide.context.example06
 
 import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     // launch a coroutine to process some kind of incoming request
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-07.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-07.kt
index 0ad533a..1093685 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-07.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-07.kt
@@ -18,6 +18,7 @@
 package guide.context.example07
 
 import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     // start a coroutine to process some kind of incoming request
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-08.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-08.kt
index a5675ef..7f2fc2b 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-08.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-08.kt
@@ -18,6 +18,7 @@
 package guide.context.example08
 
 import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     // launch a coroutine to process some kind of incoming request
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-10.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-10.kt
index ab26685..ad98c11 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-10.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-10.kt
@@ -18,6 +18,7 @@
 package guide.context.example10
 
 import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     val job = Job() // create a job object to manage our lifecycle
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-01.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-01.kt
index 9e46a7c..9a07954 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-01.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-01.kt
@@ -20,7 +20,8 @@
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
 import kotlinx.coroutines.experimental.selects.*
-import kotlin.coroutines.experimental.CoroutineContext
+import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 
 fun fizz(context: CoroutineContext) = produce<String>(context) {
     while (true) { // sends "Fizz" every 300 ms
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-02.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-02.kt
index b128877..ee8421b 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-02.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-02.kt
@@ -20,6 +20,7 @@
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
 import kotlinx.coroutines.experimental.selects.*
+import kotlin.coroutines.experimental.*
 
 suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
     select<String> {
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-03.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-03.kt
index acff08f..4674e9f 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-03.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-03.kt
@@ -20,7 +20,7 @@
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
 import kotlinx.coroutines.experimental.selects.*
-import kotlin.coroutines.experimental.CoroutineContext
+import kotlin.coroutines.experimental.*
 
 fun produceNumbers(context: CoroutineContext, side: SendChannel<Int>) = produce<Int>(context) {
     for (num in 1..10) { // produce 10 numbers from 1 to 10
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-05.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-05.kt
index 84ba4e5..ba02006 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-05.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-05.kt
@@ -20,6 +20,7 @@
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
 import kotlinx.coroutines.experimental.selects.*
+import kotlin.coroutines.experimental.*
 
 fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
     var current = input.receive() // start with first received deferred value
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01.kt
index 6d2de04..b761c7d 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01.kt
@@ -18,8 +18,8 @@
 package guide.sync.example01
 
 import kotlinx.coroutines.experimental.*
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.system.measureTimeMillis
+import kotlin.system.*
+import kotlin.coroutines.experimental.*
 
 suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
     val n = 1000 // number of coroutines to launch
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01b.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01b.kt
index 68b320d..c032747 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01b.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01b.kt
@@ -18,8 +18,8 @@
 package guide.sync.example01b
 
 import kotlinx.coroutines.experimental.*
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.system.measureTimeMillis
+import kotlin.system.*
+import kotlin.coroutines.experimental.*
 
 suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
     val n = 1000 // number of coroutines to launch
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-02.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-02.kt
index ecba342..e5cf125 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-02.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-02.kt
@@ -18,8 +18,8 @@
 package guide.sync.example02
 
 import kotlinx.coroutines.experimental.*
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.system.measureTimeMillis
+import kotlin.system.*
+import kotlin.coroutines.experimental.*
 
 suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
     val n = 1000 // number of coroutines to launch
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-03.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-03.kt
index bc1dfaf..37dd5d8 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-03.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-03.kt
@@ -18,9 +18,9 @@
 package guide.sync.example03
 
 import kotlinx.coroutines.experimental.*
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.system.measureTimeMillis
-import java.util.concurrent.atomic.AtomicInteger
+import java.util.concurrent.atomic.*
+import kotlin.system.*
+import kotlin.coroutines.experimental.*
 
 suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
     val n = 1000 // number of coroutines to launch
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-04.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-04.kt
index 1adff14..bd69d12 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-04.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-04.kt
@@ -18,8 +18,8 @@
 package guide.sync.example04
 
 import kotlinx.coroutines.experimental.*
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.system.measureTimeMillis
+import kotlin.system.*
+import kotlin.coroutines.experimental.*
 
 suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
     val n = 1000 // number of coroutines to launch
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-05.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-05.kt
index adf8612..cfd5c19 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-05.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-05.kt
@@ -18,8 +18,8 @@
 package guide.sync.example05
 
 import kotlinx.coroutines.experimental.*
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.system.measureTimeMillis
+import kotlin.system.*
+import kotlin.coroutines.experimental.*
 
 suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
     val n = 1000 // number of coroutines to launch
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-06.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-06.kt
index 73fe116..73702dd 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-06.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-06.kt
@@ -18,10 +18,9 @@
 package guide.sync.example06
 
 import kotlinx.coroutines.experimental.*
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.system.measureTimeMillis
-import kotlinx.coroutines.experimental.sync.Mutex
-import kotlinx.coroutines.experimental.sync.withLock
+import kotlinx.coroutines.experimental.sync.*
+import kotlin.system.*
+import kotlin.coroutines.experimental.*
 
 suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
     val n = 1000 // number of coroutines to launch
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-07.kt b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-07.kt
index 433d688..4d00d7c 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-07.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-07.kt
@@ -18,9 +18,9 @@
 package guide.sync.example07
 
 import kotlinx.coroutines.experimental.*
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.system.measureTimeMillis
 import kotlinx.coroutines.experimental.channels.*
+import kotlin.system.*
+import kotlin.coroutines.experimental.*
 
 suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
     val n = 1000 // number of coroutines to launch
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/AsyncTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/AsyncJvmTest.kt
similarity index 96%
rename from core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/AsyncTest.kt
rename to core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/AsyncJvmTest.kt
index adf0450..a2f4d5c 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/AsyncTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/AsyncJvmTest.kt
@@ -16,9 +16,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class AsyncTest : TestBase() {
+class AsyncJvmTest : TestBase() {
     // This must be a common test but it fails on JS because of KT-21961
     @Test
     fun testAsyncWithFinally() = runTest {
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/AtomicCancellationTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/AtomicCancellationTest.kt
index 6d43cc1..1ea089a 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/AtomicCancellationTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/AtomicCancellationTest.kt
@@ -16,51 +16,14 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlinx.coroutines.experimental.channels.Channel
-import kotlinx.coroutines.experimental.selects.select
-import kotlinx.coroutines.experimental.sync.Mutex
+import kotlinx.coroutines.experimental.channels.*
+import kotlinx.coroutines.experimental.selects.*
+import kotlinx.coroutines.experimental.sync.*
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
 class AtomicCancellationTest : TestBase() {
     @Test
-    fun testLockAtomicCancel() = runBlocking {
-        expect(1)
-        val mutex = Mutex(true) // locked mutex
-        val job = launch(coroutineContext, start = CoroutineStart.UNDISPATCHED) {
-            expect(2)
-            mutex.lock() // suspends
-            expect(4) // should execute despite cancellation
-        }
-        expect(3)
-        mutex.unlock() // unlock mutex first
-        job.cancel() // cancel the job next
-        yield() // now yield
-        finish(5)
-    }
-
-    @Test
-    fun testSelectLockAtomicCancel() = runBlocking {
-        expect(1)
-        val mutex = Mutex(true) // locked mutex
-        val job = launch(coroutineContext, start = CoroutineStart.UNDISPATCHED) {
-            expect(2)
-            val result = select<String> { // suspends
-                mutex.onLock {
-                    expect(4)
-                    "OK"
-                }
-            }
-            assertEquals("OK", result)
-            expect(5) // should execute despite cancellation
-        }
-        expect(3)
-        mutex.unlock() // unlock mutex first
-        job.cancel() // cancel the job next
-        yield() // now yield
-        finish(6)
-    }
-
-    @Test
     fun testSendAtomicCancel() = runBlocking {
         expect(1)
         val channel = Channel<Int>()
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/CoroutinesTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/CoroutinesJvmTest.kt
similarity index 95%
rename from core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/CoroutinesTest.kt
rename to core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/CoroutinesJvmTest.kt
index 4c284b0..b200015 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/CoroutinesTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/CoroutinesJvmTest.kt
@@ -16,9 +16,10 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
-class CoroutinesTest : TestBase() {
+class CoroutinesJvmTest : TestBase() {
     @Test
     fun testNotCancellableCodeWithExceptionCancelled() = runTest {
         expect(1)
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/ExecutorsTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/ExecutorsTest.kt
index 2a9bbb7..d6a8268 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/ExecutorsTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/ExecutorsTest.kt
@@ -66,4 +66,15 @@
         ctx1.close()
         ctx2.close()
     }
+
+    @Test
+    fun testShutdownExecutorService() {
+        val executorService = Executors.newSingleThreadExecutor { r -> Thread(r, "TestExecutor") }
+        val dispatcher = executorService.asCoroutineDispatcher()
+        runBlocking (dispatcher) {
+            checkThreadName("TestExecutor")
+        }
+        dispatcher.close()
+        check(executorService.isShutdown)
+    }
 }
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobStressTest.kt
similarity index 95%
rename from core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt
rename to core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobStressTest.kt
index 06f7c68..50ef98e 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobStressTest.kt
@@ -18,7 +18,7 @@
 
 import kotlin.test.*
 
-class JobTest : TestBase() {
+class JobStressTest : TestBase() {
     @Test
     fun testMemoryRelease() {
         val job = Job()
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt
index 4edc6e9..f6f087b 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt
@@ -14,9 +14,6 @@
  * limitations under the License.
  */
 
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
-
 package kotlinx.coroutines.experimental
 
 import org.junit.After
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithContextTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithContextCommonPoolTest.kt
similarity index 95%
rename from core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithContextTest.kt
rename to core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithContextCommonPoolTest.kt
index ee26c07..993aeef 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithContextTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithContextCommonPoolTest.kt
@@ -18,7 +18,7 @@
 
 import kotlin.test.*
 
-class WithContextTest : TestBase() {
+class WithContextCommonPoolTest : TestBase() {
     @Test
     fun testCommonPoolNoSuspend() = runTest {
         expect(1)
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullJvmTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullJvmTest.kt
new file mode 100644
index 0000000..560d087
--- /dev/null
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullJvmTest.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package kotlinx.coroutines.experimental
+
+import kotlin.test.*
+
+class WithTimeoutOrNullJvmTest : TestBase() {
+    @Test
+    fun testOuterTimeoutFiredBeforeInner() = runTest {
+        val result = withTimeoutOrNull(100) {
+            Thread.sleep(200) // wait enough for outer timeout to fire
+            withContext(NonCancellable) { yield() } // give an event loop a chance to run and process that cancellation
+            withTimeoutOrNull(100) {
+                yield() // will cancel because of outer timeout
+                expectUnreached()
+            }
+            expectUnreached() // should not be reached, because it is outer timeout
+        }
+        // outer timeout results in null
+        assertEquals(null, result)
+    }
+}
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullTest.kt
deleted file mode 100644
index 6c43f76..0000000
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullTest.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.test.*
-
-class WithTimeoutOrNullTest : TestBase() {
-    @Test
-    fun testNullOnTimeout() = runTest {
-        expect(1)
-        val result = withTimeoutOrNull(100) {
-            expect(2)
-            delay(1000)
-            expectUnreached()
-            "OK"
-        }
-        assertEquals(null, result)
-        finish(3)
-    }
-
-    @Test
-    fun testSuppressExceptionWithResult() = runTest {
-        expect(1)
-        val result = withTimeoutOrNull(100) {
-            expect(2)
-            try {
-                delay(1000)
-            } catch (e: CancellationException) {
-                expect(3)
-            }
-            "OK"
-        }
-        assertEquals(null, result)
-        finish(4)
-    }
-
-    @Test
-    fun testSuppressExceptionWithAnotherException() = runTest(
-        expected = { it is TestException }
-    ) {
-        expect(1)
-        val result = withTimeoutOrNull(100) {
-            expect(2)
-            try {
-                delay(1000)
-            } catch (e: CancellationException) {
-                finish(3)
-                throw TestException()
-            }
-            expectUnreached()
-            "OK"
-        }
-        expectUnreached()
-    }
-
-    @Test
-    fun testOuterTimeoutFiredBeforeInner() = runTest {
-        val result = withTimeoutOrNull(100) {
-            Thread.sleep(200) // wait enough for outer timeout to fire
-            withContext(NonCancellable) { yield() } // give an event loop a chance to run and process that cancellation
-            withTimeoutOrNull(100) {
-                yield() // will cancel because of outer timeout
-                expectUnreached()
-            }
-            expectUnreached() // should not be reached, because it is outer timeout
-        }
-        // outer timeout results in null
-        assertEquals(null, result)
-    }
-
-    private class TestException : Exception()
-}
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullThreadDispatchTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullThreadDispatchTest.kt
index df1387c..f5b8562 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullThreadDispatchTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullThreadDispatchTest.kt
@@ -47,7 +47,6 @@
         }
     }
 
-
     @Test
     fun testCancellationDispatchCustomNoDelay() {
         // it also checks that there is at most once scheduled request in flight (no spurious concurrency)
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutTest.kt
deleted file mode 100644
index a793a1e..0000000
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutTest.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
-
-package kotlinx.coroutines.experimental
-
-import kotlin.test.*
-import java.io.IOException
-
-class WithTimeoutTest : TestBase() {
-    @Test
-    fun testExceptionOnTimeout() = runTest {
-        expect(1)
-        try {
-            withTimeout(100) {
-                expect(2)
-                delay(1000)
-                expectUnreached()
-                "OK"
-            }
-        } catch (e: CancellationException) {
-            assertEquals("Timed out waiting for 100 MILLISECONDS", e.message)
-            finish(3)
-        }
-    }
-
-    @Test
-    fun testSuppressExceptionWithResult() = runTest(
-        expected = { it is CancellationException }
-    ) {
-        expect(1)
-        val result = withTimeout(100) {
-            expect(2)
-            try {
-                delay(1000)
-            } catch (e: CancellationException) {
-                finish(3)
-            }
-            "OK"
-        }
-        expectUnreached()
-    }
-
-    @Test
-    fun testSuppressExceptionWithAnotherException() = runTest(
-        expected = { it is IOException }
-    ) {
-        expect(1)
-        withTimeout(100) {
-            expect(2)
-            try {
-                delay(1000)
-            } catch (e: CancellationException) {
-                finish(3)
-                throw IOException(e)
-            }
-            expectUnreached()
-            "OK"
-        }
-        expectUnreached()
-    }
-}
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ActorLazyTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ActorLazyTest.kt
index b0a2ac9..4a06251 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ActorLazyTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ActorLazyTest.kt
@@ -17,9 +17,10 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.core.IsEqual
-import org.junit.Assert.assertThat
-import org.junit.Test
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class ActorLazyTest : TestBase() {
     @Test
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ActorTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ActorTest.kt
index c757d29..1494d2f 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ActorTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ActorTest.kt
@@ -16,13 +16,11 @@
 
 package kotlinx.coroutines.experimental.channels
 
-import kotlinx.coroutines.experimental.Job
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.hamcrest.core.IsEqual
-import org.junit.Assert.assertThat
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class ActorTest : TestBase() {
     @Test
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ArrayBroadcastChannelTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ArrayBroadcastChannelTest.kt
index e5c4609..a71e3f8 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ArrayBroadcastChannelTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ArrayBroadcastChannelTest.kt
@@ -17,10 +17,10 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsNull
+import org.hamcrest.core.*
+import org.junit.*
 import org.junit.Assert.*
-import org.junit.Test
+import kotlin.coroutines.experimental.*
 
 class ArrayBroadcastChannelTest : TestBase() {
     @Test
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ArrayChannelTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ArrayChannelTest.kt
index 8e71093..80d3682 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ArrayChannelTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ArrayChannelTest.kt
@@ -17,8 +17,9 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
+import org.junit.*
 import org.junit.Assert.*
-import org.junit.Test
+import kotlin.coroutines.experimental.*
 
 class ArrayChannelTest : TestBase() {
     @Test
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/BroadcastChannelMultiReceiveStressTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/BroadcastChannelMultiReceiveStressTest.kt
index cabb762..60bdeb1 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/BroadcastChannelMultiReceiveStressTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/BroadcastChannelMultiReceiveStressTest.kt
@@ -17,13 +17,13 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.selects.select
-import org.junit.After
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.atomic.AtomicLong
+import kotlinx.coroutines.experimental.selects.*
+import kotlinx.coroutines.experimental.timeunit.*
+import org.junit.*
+import org.junit.runner.*
+import org.junit.runners.*
+import java.util.concurrent.atomic.*
+import kotlin.coroutines.experimental.*
 
 /**
  * Tests delivery of events to multiple broadcast channel subscribers.
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/BroadcastChannelSubStressTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/BroadcastChannelSubStressTest.kt
index 8bd7b63..cfef040 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/BroadcastChannelSubStressTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/BroadcastChannelSubStressTest.kt
@@ -17,11 +17,12 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.atomic.AtomicLong
+import kotlinx.coroutines.experimental.timeunit.*
+import org.junit.*
+import org.junit.runner.*
+import org.junit.runners.*
+import java.util.concurrent.atomic.*
+import kotlin.coroutines.experimental.*
 
 /**
  * Creates a broadcast channel and repeatedly opens new subscription, receives event, closes it,
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelSendReceiveStressTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelSendReceiveStressTest.kt
index 98fc716..4a98f40 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelSendReceiveStressTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelSendReceiveStressTest.kt
@@ -17,14 +17,13 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.selects.select
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertTrue
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-import java.util.concurrent.atomic.AtomicInteger
-import java.util.concurrent.atomic.AtomicIntegerArray
+import kotlinx.coroutines.experimental.selects.*
+import org.junit.*
+import org.junit.Assert.*
+import org.junit.runner.*
+import org.junit.runners.*
+import java.util.concurrent.atomic.*
+import kotlin.coroutines.experimental.*
 
 @RunWith(Parameterized::class)
 class ChannelSendReceiveStressTest(
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelsConsumeTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelsConsumeTest.kt
new file mode 100644
index 0000000..46c5e71
--- /dev/null
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelsConsumeTest.kt
@@ -0,0 +1,914 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package kotlinx.coroutines.experimental.channels
+
+import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
+import kotlin.test.*
+
+/**
+ * Tests that various operators on channels properly consume (close) their source channels.
+ */
+class ChannelsConsumeTest {
+    private val sourceList = (1..10).toList()
+
+    // test source with numbers 1..10
+    private fun testSource(context: CoroutineContext) = produce(context) {
+        for (i in sourceList) {
+            send(i)
+        }
+    }
+
+    @Test
+    fun testConsume() {
+        checkTerminal {
+            consume {
+                assertEquals(1, receive())
+            }
+        }
+    }
+
+    @Test
+    fun testConsumeEach() {
+        checkTerminal {
+            var sum = 0
+            consumeEach { sum += it }
+            assertEquals(55, sum)
+        }
+    }
+
+    @Test
+    fun testConsumeEachIndexed() {
+        checkTerminal {
+            var sum = 0
+            consumeEachIndexed { (index, i) -> sum += index * i }
+            assertEquals(330, sum)
+        }
+    }
+
+    @Test
+    fun testElementAt() {
+        checkTerminal {
+            assertEquals(2, elementAt(1))
+        }
+        checkTerminal(expected = { it is IndexOutOfBoundsException }) {
+            elementAt(10)
+        }
+    }
+
+    @Test
+    fun testElementAtOrElse() {
+        checkTerminal {
+            assertEquals(3, elementAtOrElse(2) { error("Cannot happen") })
+        }
+        checkTerminal {
+            assertEquals(-23, elementAtOrElse(10) { -23 })
+        }
+    }
+
+    @Test
+    fun testElementOrNull() {
+        checkTerminal {
+            assertEquals(4, elementAtOrNull(3))
+        }
+        checkTerminal {
+            assertEquals(null, elementAtOrNull(10))
+        }
+    }
+
+    @Test
+    fun testFind() {
+        checkTerminal {
+            assertEquals(3, find { it % 3 == 0 })
+        }
+    }
+
+    @Test
+    fun testFindLast() {
+        checkTerminal {
+            assertEquals(9, findLast { it % 3 == 0 })
+        }
+    }
+
+    @Test
+    fun testFirst() {
+        checkTerminal {
+            assertEquals(1, first())
+        }
+    }
+
+    @Test
+    fun testFirstPredicate() {
+        checkTerminal {
+            assertEquals(3, first { it % 3 == 0 })
+        }
+        checkTerminal(expected = { it is NoSuchElementException }) {
+            first { it > 10 }
+        }
+    }
+
+    @Test
+    fun testFirstOrNull() {
+        checkTerminal {
+            assertEquals(1, firstOrNull())
+        }
+    }
+
+    @Test
+    fun testFirstOrNullPredicate() {
+        checkTerminal {
+            assertEquals(3, firstOrNull { it % 3 == 0 })
+        }
+        checkTerminal {
+            assertEquals(null, firstOrNull { it > 10 })
+        }
+    }
+
+    @Test
+    fun testIndexOf() {
+        checkTerminal {
+            assertEquals(2, indexOf(3))
+        }
+        checkTerminal {
+            assertEquals(-1, indexOf(11))
+        }
+    }
+
+    @Test
+    fun testIndexOfFirst() {
+        checkTerminal {
+            assertEquals(2, indexOfFirst { it % 3 == 0 })
+        }
+        checkTerminal {
+            assertEquals(-1, indexOfFirst { it > 10 })
+        }
+    }
+
+    @Test
+    fun testIndexOfLast() {
+        checkTerminal {
+            assertEquals(8, indexOfLast { it % 3 == 0 })
+        }
+        checkTerminal {
+            assertEquals(-1, indexOfLast { it > 10 })
+        }
+    }
+
+    @Test
+    fun testLast() {
+        checkTerminal {
+            assertEquals(10, last())
+        }
+    }
+
+    @Test
+    fun testLastPredicate() {
+        checkTerminal {
+            assertEquals(9, last { it % 3 == 0 })
+        }
+        checkTerminal(expected = { it is NoSuchElementException }) {
+            last { it > 10 }
+        }
+    }
+
+    @Test
+    fun testLastIndexOf() {
+        checkTerminal {
+            assertEquals(8, lastIndexOf(9))
+        }
+    }
+
+    @Test
+    fun testLastOrNull() {
+        checkTerminal {
+            assertEquals(10, lastOrNull())
+        }
+    }
+
+    @Test
+    fun testLastOrNullPredicate() {
+        checkTerminal {
+            assertEquals(9, lastOrNull { it % 3 == 0 })
+        }
+        checkTerminal {
+            assertEquals(null, lastOrNull { it > 10 })
+        }
+    }
+
+    @Test
+    fun testSingle() {
+        checkTerminal(expected = { it is IllegalArgumentException }) {
+            single()
+        }
+    }
+
+    @Test
+    fun testSinglePredicate() {
+        checkTerminal {
+            assertEquals(7, single { it % 7 == 0 })
+        }
+        checkTerminal(expected = { it is IllegalArgumentException }) {
+            single { it % 3 == 0 }
+        }
+        checkTerminal(expected = { it is NoSuchElementException }) {
+            single { it > 10 }
+        }
+    }
+
+    @Test
+    fun testSingleOrNull() {
+        checkTerminal {
+            assertEquals(null, singleOrNull())
+        }
+    }
+
+    @Test
+    fun testSingleOrNullPredicate() {
+        checkTerminal {
+            assertEquals(7, singleOrNull { it % 7 == 0 })
+        }
+        checkTerminal {
+            assertEquals(null, singleOrNull { it % 3 == 0 })
+        }
+        checkTerminal {
+            assertEquals(null, singleOrNull { it > 10 })
+        }
+    }
+
+    @Test
+    fun testDrop() {
+        checkTransform(sourceList.drop(3)) { ctx ->
+            drop(3, ctx)
+        }
+    }
+
+    @Test
+    fun testDropWhile() {
+        checkTransform(sourceList.dropWhile { it < 4}) { ctx ->
+            dropWhile(ctx) { it < 4 }
+        }
+    }
+
+    @Test
+    fun testFilter() {
+        checkTransform(sourceList.filter { it % 2 == 0 }) { ctx ->
+            filter(ctx) { it % 2 == 0 }
+        }
+    }
+
+    @Test
+    fun testFilterIndexed() {
+        checkTransform(sourceList.filterIndexed { index, _ -> index % 2 == 0 }) { ctx ->
+            filterIndexed(ctx) { index, _ -> index % 2 == 0 }
+        }
+    }
+
+    @Test
+    fun testFilterIndexedToCollection() {
+        checkTerminal {
+            val list = mutableListOf<Int>()
+            filterIndexedTo(list) { index, _ -> index % 2 == 0 }
+            assertEquals(listOf(1, 3, 5, 7, 9), list)
+        }
+    }
+
+    @Test
+    fun testFilterIndexedToChannel() {
+        checkTerminal {
+            val channel = Channel<Int>()
+            val result = async { channel.toList() }
+            filterIndexedTo(channel) { index, _ -> index % 2 == 0 }
+            channel.close()
+            assertEquals(listOf(1, 3, 5, 7, 9), result.await())
+        }
+    }
+
+    @Test
+    fun testFilterNot() {
+        checkTransform(sourceList.filterNot { it % 2 == 0 }) { ctx ->
+            filterNot(ctx) { it % 2 == 0 }
+        }
+    }
+
+    @Test
+    fun testFilterNotNullToCollection() {
+        checkTerminal {
+            val list = mutableListOf<Int>()
+            filterNotNullTo(list)
+            assertEquals((1..10).toList(), list)
+        }
+    }
+
+    @Test
+    fun testFilterNotNullToChannel() {
+        checkTerminal {
+            val channel = Channel<Int>()
+            val result = async { channel.toList() }
+            filterNotNullTo(channel)
+            channel.close()
+            assertEquals((1..10).toList(), result.await())
+        }
+    }
+
+    @Test
+    fun testFilterNotToCollection() {
+        checkTerminal {
+            val list = mutableListOf<Int>()
+            filterNotTo(list) { it % 2 == 0 }
+            assertEquals(listOf(1, 3, 5, 7, 9), list)
+        }
+    }
+
+    @Test
+    fun testFilterNotToChannel() {
+        checkTerminal {
+            val channel = Channel<Int>()
+            val result = async { channel.toList() }
+            filterNotTo(channel) { it % 2 == 0 }
+            channel.close()
+            assertEquals(listOf(1, 3, 5, 7, 9), result.await())
+        }
+    }
+
+    @Test
+    fun testFilterToCollection() {
+        checkTerminal {
+            val list = mutableListOf<Int>()
+            filterTo(list) { it % 2 == 0 }
+            assertEquals(listOf(2, 4, 6, 8, 10), list)
+        }
+    }
+
+    @Test
+    fun testFilterToChannel() {
+        checkTerminal {
+            val channel = Channel<Int>()
+            val result = async { channel.toList() }
+            filterTo(channel) { it % 2 == 0 }
+            channel.close()
+            assertEquals(listOf(2, 4, 6, 8, 10), result.await())
+        }
+    }
+
+    @Test
+    fun testTake() {
+        checkTransform(sourceList.take(3)) { ctx ->
+            take(3, ctx)
+        }
+    }
+
+    @Test
+    fun testTakeWhile() {
+        checkTransform(sourceList.takeWhile { it < 4 }) { ctx ->
+            takeWhile(ctx) { it < 4 }
+        }
+    }
+
+    @Test
+    fun testAssociate() {
+        checkTerminal {
+            assertEquals(sourceList.associate { it to it.toString() }, associate { it to it.toString() })
+        }
+    }
+
+    @Test
+    fun testAssociateBy() {
+        checkTerminal {
+            assertEquals(sourceList.associateBy { it.toString() }, associateBy { it.toString() })
+        }
+    }
+
+    @Test
+    fun testAssociateByTwo() {
+        checkTerminal {
+            assertEquals(sourceList.associateBy({ it.toString() }, { it + 1}), associateBy({ it.toString() }, { it + 1}))
+        }
+    }
+
+    @Test
+    fun testAssociateByToMap() {
+        checkTerminal {
+            val map = mutableMapOf<String, Int>()
+            associateByTo(map) { it.toString() }
+            assertEquals(sourceList.associateBy { it.toString() }, map)
+        }
+    }
+
+    @Test
+    fun testAssociateByTwoToMap() {
+        checkTerminal {
+            val map = mutableMapOf<String, Int>()
+            associateByTo(map, { it.toString() }, { it + 1})
+            assertEquals(sourceList.associateBy({ it.toString() }, { it + 1}), map)
+        }
+    }
+
+    @Test
+    fun testAssociateToMap() {
+        checkTerminal {
+            val map = mutableMapOf<Int, String>()
+            associateTo(map) { it to it.toString() }
+            assertEquals(sourceList.associate { it to it.toString() }, map)
+        }
+    }
+
+    @Test
+    fun testToChannel() {
+        checkTerminal {
+            val channel = Channel<Int>()
+            val result = async { channel.toList() }
+            toChannel(channel)
+            channel.close()
+            assertEquals(sourceList, result.await())
+        }
+    }
+
+    @Test
+    fun testToCollection() {
+        checkTerminal {
+            val list = mutableListOf<Int>()
+            toCollection(list)
+            assertEquals(sourceList, list)
+        }
+    }
+
+    @Test
+    fun testToList() {
+        checkTerminal {
+            val list = toList()
+            assertEquals(sourceList, list)
+        }
+    }
+
+    @Test
+    fun testToMap() {
+        checkTerminal {
+            val map = map { it to it.toString() }.toMap()
+            assertEquals(sourceList.map { it to it.toString() }.toMap(), map)
+        }
+    }
+
+    @Test
+    fun testToMapWithMap() {
+        checkTerminal {
+            val map = mutableMapOf<Int, String>()
+            map { it to it.toString() }.toMap(map)
+            assertEquals(sourceList.map { it to it.toString() }.toMap(), map)
+        }
+    }
+
+    @Test
+    fun testToMutableList() {
+        checkTerminal {
+            val list = toMutableList()
+            assertEquals(sourceList, list)
+        }
+    }
+
+    @Test
+    fun testToSet() {
+        checkTerminal {
+            val set = toSet()
+            assertEquals(sourceList.toSet(), set)
+        }
+    }
+
+    @Test
+    fun testFlatMap() {
+        checkTransform(sourceList.flatMap { listOf("A$it", "B$it") }) { ctx ->
+            flatMap(ctx) {
+                produce {
+                    send("A$it")
+                    send("B$it")
+                }
+            }
+        }
+    }
+
+    @Test
+    fun testGroupBy() {
+        checkTerminal {
+            val map = groupBy { it % 2 }
+            assertEquals(sourceList.groupBy { it % 2 }, map)
+        }
+    }
+
+    @Test
+    fun testGroupByTwo() {
+        checkTerminal {
+            val map = groupBy({ it % 2 }, { it.toString() })
+            assertEquals(sourceList.groupBy({ it % 2 }, { it.toString() }), map)
+        }
+    }
+
+    @Test
+    fun testGroupByTo() {
+        checkTerminal {
+            val map = mutableMapOf<Int, MutableList<Int>>()
+            groupByTo(map) { it % 2 }
+            assertEquals(sourceList.groupBy { it % 2 }, map)
+        }
+    }
+
+    @Test
+    fun testGroupByToTwo() {
+        checkTerminal {
+            val map = mutableMapOf<Int, MutableList<String>>()
+            groupByTo(map, { it % 2 }, { it.toString() })
+            assertEquals(sourceList.groupBy({ it % 2 }, { it.toString() }), map)
+        }
+    }
+
+    @Test
+    fun testMap() {
+        checkTransform(sourceList.map { it.toString() }) { ctx ->
+            map(ctx) { it.toString() }
+        }
+    }
+
+    @Test
+    fun testMapIndexed() {
+        checkTransform(sourceList.mapIndexed { index, v -> "$index$v" }) { ctx ->
+            mapIndexed(ctx) { index, v -> "$index$v" }
+        }
+    }
+
+    @Test
+    fun testMapIndexedNotNull() {
+        checkTransform(sourceList.mapIndexedNotNull { index, v -> "$index$v".takeIf { v % 2 == 0 } }) { ctx ->
+            mapIndexedNotNull(ctx) { index, v -> "$index$v".takeIf { v % 2 == 0 } }
+        }
+    }
+
+    @Test
+    fun testMapIndexedNotNullToCollection() {
+        checkTerminal {
+            val list = mutableListOf<String>()
+            mapIndexedNotNullTo(list) { index, v -> "$index$v".takeIf { v % 2 == 0 } }
+            assertEquals(sourceList.mapIndexedNotNull { index, v -> "$index$v".takeIf { v % 2 == 0 } }, list)
+        }
+    }
+
+    @Test
+    fun testMapIndexedNotNullToChannel() {
+        checkTerminal {
+            val channel = Channel<String>()
+            val result = async { channel.toList() }
+            mapIndexedNotNullTo(channel) { index, v -> "$index$v".takeIf { v % 2 == 0 } }
+            channel.close()
+            assertEquals(sourceList.mapIndexedNotNull { index, v -> "$index$v".takeIf { v % 2 == 0 } }, result.await())
+        }
+    }
+
+    @Test
+    fun testMapIndexedToCollection() {
+        checkTerminal {
+            val list = mutableListOf<String>()
+            mapIndexedTo(list) { index, v -> "$index$v" }
+            assertEquals(sourceList.mapIndexed { index, v -> "$index$v" }, list)
+        }
+    }
+
+    @Test
+    fun testMapIndexedToChannel() {
+        checkTerminal {
+            val channel = Channel<String>()
+            val result = async { channel.toList() }
+            mapIndexedTo(channel) { index, v -> "$index$v" }
+            channel.close()
+            assertEquals(sourceList.mapIndexed { index, v -> "$index$v" }, result.await())
+        }
+    }
+
+    @Test
+    fun testMapNotNull() {
+        checkTransform(sourceList.mapNotNull { (it + 3).takeIf { it % 2 == 0 } }) { ctx ->
+            mapNotNull(ctx) { (it + 3).takeIf { it % 2 == 0 } }
+        }
+    }
+
+    @Test
+    fun testMapNotNullToCollection() {
+        checkTerminal {
+            val list = mutableListOf<Int>()
+            mapNotNullTo(list) { (it + 3).takeIf { it % 2 == 0 } }
+            assertEquals(sourceList.mapNotNull { (it + 3).takeIf { it % 2 == 0 } }, list)
+        }
+    }
+
+    @Test
+    fun testMapNotNullToChannel() {
+        checkTerminal {
+            val channel = Channel<Int>()
+            val result = async { channel.toList() }
+            mapNotNullTo(channel) { (it + 3).takeIf { it % 2 == 0 } }
+            channel.close()
+            assertEquals(sourceList.mapNotNull { (it + 3).takeIf { it % 2 == 0 } }, result.await())
+        }
+    }
+
+    @Test
+    fun testMapToCollection() {
+        checkTerminal {
+            val list = mutableListOf<Int>()
+            mapTo(list) { it + 3 }
+            assertEquals(sourceList.map { it + 3 }, list)
+        }
+    }
+
+    @Test
+    fun testMapToChannel() {
+        checkTerminal {
+            val channel = Channel<Int>()
+            val result = async { channel.toList() }
+            mapTo(channel) { it + 3 }
+            channel.close()
+            assertEquals(sourceList.map { it + 3 }, result.await())
+        }
+    }
+
+    @Test
+    fun testWithIndex() {
+        checkTransform(sourceList.withIndex().toList()) { ctx ->
+            withIndex(ctx)
+        }
+    }
+
+    @Test
+    fun testDistinctBy() {
+        checkTransform(sourceList.distinctBy { it / 2 }) { ctx ->
+            distinctBy(ctx) { it / 2 }
+        }
+    }
+
+    @Test
+    fun testToMutableSet() {
+        checkTerminal {
+            val set = toMutableSet()
+            assertEquals(sourceList.toSet(), set)
+        }
+    }
+
+    @Test
+    fun testAll() {
+        checkTerminal {
+            val all = all { it < 11 }
+            assertEquals(sourceList.all { it < 11 }, all)
+        }
+    }
+
+    @Test
+    fun testAny() {
+        checkTerminal {
+            val any = any()
+            assertEquals(sourceList.any(), any)
+        }
+    }
+
+    @Test
+    fun testAnyPredicate() {
+        checkTerminal {
+            val any = any { it % 3 == 0 }
+            assertEquals(sourceList.any { it % 3 == 0 }, any)
+        }
+    }
+    
+    @Test
+    fun testCount() {
+        checkTerminal {
+            val c = count()
+            assertEquals(sourceList.count(), c)
+        }
+    }
+
+    @Test
+    fun testCountPredicate() {
+        checkTerminal {
+            val c = count { it % 3 == 0 }
+            assertEquals(sourceList.count { it % 3 == 0 }, c)
+        }
+    }
+
+    @Test
+    fun testFold() {
+        checkTerminal {
+            val c = fold(1) { a, b -> a + b }
+            assertEquals(sourceList.fold(1) { a, b -> a + b }, c)
+        }
+    }
+
+    @Test
+    fun testFoldIndexed() {
+        checkTerminal {
+            val c = foldIndexed(1) { i, a, b -> i * a + b }
+            assertEquals(sourceList.foldIndexed(1) { i, a, b -> i * a + b }, c)
+        }
+    }
+
+    @Test
+    fun testMaxBy() {
+        checkTerminal {
+            val c = maxBy { it % 3 }
+            assertEquals(sourceList.maxBy { it % 3 }, c)
+        }
+    }
+
+    @Test
+    fun testMaxWith() {
+        checkTerminal {
+            val c = maxWith(compareBy { it % 3 })
+            assertEquals(sourceList.maxWith(compareBy { it % 3 }), c)
+        }
+    }
+
+    @Test
+    fun testMinBy() {
+        checkTerminal {
+            val c = maxBy { it % 3 }
+            assertEquals(sourceList.maxBy { it % 3 }, c)
+        }
+    }
+
+    @Test
+    fun testMinWith() {
+        checkTerminal {
+            val c = maxWith(compareBy { it % 3 })
+            assertEquals(sourceList.maxWith(compareBy { it % 3 }), c)
+        }
+    }
+
+    @Test
+    fun testNone() {
+        checkTerminal {
+            val none = none()
+            assertEquals(sourceList.none(), none)
+        }
+    }
+
+    @Test
+    fun testNonePredicate() {
+        checkTerminal {
+            val none = none { it > 10 }
+            assertEquals(sourceList.none { it > 10 }, none)
+        }
+    }
+
+    @Test
+    fun testReduce() {
+        checkTerminal {
+            val c = reduce { a, b -> a + b }
+            assertEquals(sourceList.reduce { a, b -> a + b }, c)
+        }
+    }
+
+    @Test
+    fun testReduceIndexed() {
+        checkTerminal {
+            val c = reduceIndexed { i, a, b -> i * a + b }
+            assertEquals(sourceList.reduceIndexed { i, a, b -> i * a + b }, c)
+        }
+    }
+
+    @Test
+    fun testSubBy() {
+        checkTerminal {
+            val c = sumBy { it }
+            assertEquals(sourceList.sumBy { it }, c)
+        }
+    }
+
+    @Test
+    fun testSubByDouble() {
+        checkTerminal {
+            val c = sumByDouble { it.toDouble() }
+            assertEquals(sourceList.sumByDouble { it.toDouble() }, c)
+        }
+    }
+
+    @Test
+    fun testPartition() {
+        checkTerminal {
+            val pair = partition { it % 2 == 0 }
+            assertEquals(sourceList.partition { it % 2 == 0 }, pair)
+        }
+    }
+
+    @Test
+    fun testZip() {
+        val expect = sourceList.zip(sourceList) { a, b -> a + 2 * b }
+        checkTransform(expect) { ctx ->
+            zip(testSource(ctx), ctx) { a, b -> a + 2*b }
+        }
+        checkTransform(expect) { ctx ->
+            testSource(ctx).zip(this, ctx) { a, b -> a + 2*b }
+        }
+    }
+
+    // ------------------
+    
+    private fun checkTerminal(
+        expected: ((Throwable?) -> Unit)? = null,
+        terminal: suspend ReceiveChannel<Int>.() -> Unit
+    ) {
+        checkTerminalCompletion(expected, terminal)
+        checkTerminalCancellation(expected, terminal)
+    }
+
+    private fun checkTerminalCompletion(
+        expected: ((Throwable?) -> Unit)? = null,
+        terminal: suspend ReceiveChannel<Int>.() -> Unit
+    ) {
+        val src = runBlocking {
+            val src = testSource(coroutineContext)
+            try {
+                // terminal operation
+                terminal(src)
+                // source must be cancelled at the end of terminal op
+                if (expected != null) error("Exception was expected")
+            } catch (e: Throwable) {
+                if (expected == null) throw e
+                expected(e)
+            }
+            src
+        }
+        assertTrue(src.isClosedForReceive, "Source must be closed")
+    }
+
+    private fun checkTerminalCancellation(
+        expected: ((Throwable?) -> Unit)? = null,
+        terminal: suspend ReceiveChannel<Int>.() -> Unit
+    ) {
+        val src = runBlocking {
+            val src = testSource(coroutineContext)
+            // terminal operation in a separate async context started until the first suspension
+            val d = async(coroutineContext, start = CoroutineStart.UNDISPATCHED) {
+                terminal(src)
+            }
+            // then cancel it
+            d.cancel()
+            // and try to get it's result
+            try {
+                d.await()
+            } catch (e: CancellationException) {
+                // ok -- was cancelled
+            } catch (e: Throwable) {
+                // if threw a different exception -- must be an expected one
+                if (expected == null) throw e
+                expected(e)
+            }
+            src
+        }
+        // source must be cancelled at the end of terminal op even if it was cancelled while in process
+        assertTrue(src.isClosedForReceive, "Source must be closed")
+    }
+
+    private fun <R> checkTransform(
+        expect: List<R>,
+        transform: ReceiveChannel<Int>.(CoroutineContext) -> ReceiveChannel<R>
+    ) {
+        // check for varying number of received elements from the channel
+        for (nReceive in 0..expect.size) {
+            checkTransform(nReceive, expect, transform)
+        }
+    }
+
+    private fun <R> checkTransform(
+        nReceive: Int,
+        expect: List<R>,
+        transform: ReceiveChannel<Int>.(CoroutineContext) -> ReceiveChannel<R>
+    ) {
+        val src = runBlocking {
+            val src = testSource(coroutineContext)
+            // transform
+            val res = transform(src, coroutineContext)
+            // receive nReceive elements from the result
+            repeat(nReceive) { i ->
+                assertEquals(expect[i], res.receive())
+            }
+            if (nReceive < expect.size) {
+                // then cancel
+                res.cancel()
+            } else {
+                // then check that result is closed
+                assertEquals(null, res.receiveOrNull(), "Result has unexpected values")
+            }
+            src
+        }
+        // source must be cancelled when runBlocking processes all the scheduled stuff
+        assertTrue(src.isClosedForReceive, "Source must be closed")
+    }
+}
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedBroadcastChannelNotifyStressTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedBroadcastChannelNotifyStressTest.kt
index bc5324e..64df05c 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedBroadcastChannelNotifyStressTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedBroadcastChannelNotifyStressTest.kt
@@ -17,10 +17,11 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.MatcherAssert.assertThat
-import org.hamcrest.core.IsEqual
-import org.junit.Test
-import java.util.concurrent.atomic.AtomicInteger
+import org.hamcrest.MatcherAssert.*
+import org.hamcrest.core.*
+import org.junit.*
+import java.util.concurrent.atomic.*
+import kotlin.coroutines.experimental.*
 
 class ConflatedBroadcastChannelNotifyStressTest : TestBase() {
     val nSenders = 2
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedBroadcastChannelTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedBroadcastChannelTest.kt
index b3d197b..707b780 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedBroadcastChannelTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedBroadcastChannelTest.kt
@@ -17,11 +17,10 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.hamcrest.core.IsNull
-import org.junit.Assert.assertThat
-import org.junit.Test
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class ConflatedBroadcastChannelTest : TestBase() {
     @Test
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedChannelCloseStressTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedChannelCloseStressTest.kt
index dfa6f8d..201258c 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedChannelCloseStressTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedChannelCloseStressTest.kt
@@ -21,6 +21,7 @@
 import org.junit.Test
 import java.util.concurrent.atomic.AtomicInteger
 import java.util.concurrent.atomic.AtomicReference
+import kotlin.coroutines.experimental.*
 
 class ConflatedChannelCloseStressTest : TestBase() {
 
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedChannelTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedChannelTest.kt
index 2db3537..6819170 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedChannelTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ConflatedChannelTest.kt
@@ -16,14 +16,11 @@
 
 package kotlinx.coroutines.experimental.channels
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsNull
-import org.junit.Assert.assertThat
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class ConflatedChannelTest : TestBase() {
     @Test
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ProduceConsumeTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ProduceConsumeTest.kt
index 019e58a..8aea78f 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ProduceConsumeTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ProduceConsumeTest.kt
@@ -21,6 +21,7 @@
 import org.junit.Assert.*
 import org.junit.runner.*
 import org.junit.runners.*
+import kotlin.coroutines.experimental.*
 
 @RunWith(Parameterized::class)
 class ProduceConsumeTest(
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ProduceTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ProduceTest.kt
index 167cbd7..641eff0 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ProduceTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ProduceTest.kt
@@ -16,10 +16,9 @@
 
 package kotlinx.coroutines.experimental.channels
 
-import kotlinx.coroutines.experimental.Job
-import kotlinx.coroutines.experimental.JobCancellationException
-import kotlinx.coroutines.experimental.TestBase
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import org.junit.*
+import kotlin.coroutines.experimental.*
 
 class ProduceTest : TestBase() {
     @Test
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/RendezvousChannelTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/RendezvousChannelTest.kt
index e77ba12..7edbe42 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/RendezvousChannelTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/RendezvousChannelTest.kt
@@ -17,10 +17,10 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsNull
+import org.hamcrest.core.*
+import org.junit.*
 import org.junit.Assert.*
-import org.junit.Test
+import kotlin.coroutines.experimental.*
 
 class RendezvousChannelTest : TestBase() {
     @Test
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/SimpleSendReceiveTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/SimpleSendReceiveTest.kt
index b36aa53..feb06e0 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/SimpleSendReceiveTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/SimpleSendReceiveTest.kt
@@ -16,15 +16,13 @@
 
 package kotlinx.coroutines.experimental.channels
 
-import kotlinx.coroutines.experimental.CommonPool
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import org.hamcrest.core.IsEqual
-import org.junit.Assert.assertThat
-import org.junit.Assert.assertTrue
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
+import kotlinx.coroutines.experimental.*
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import org.junit.runner.*
+import org.junit.runners.*
+import kotlin.coroutines.experimental.*
 
 @RunWith(Parameterized::class)
 class SimpleSendReceiveTest(
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectArrayChannelTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectArrayChannelTest.kt
index 0620ed1..54aaae0 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectArrayChannelTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectArrayChannelTest.kt
@@ -16,15 +16,12 @@
 
 package kotlinx.coroutines.experimental.selects
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.channels.ArrayChannel
-import kotlinx.coroutines.experimental.channels.ClosedReceiveChannelException
-import kotlinx.coroutines.experimental.intrinsics.startCoroutineUndispatched
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import kotlinx.coroutines.experimental.channels.*
+import kotlinx.coroutines.experimental.intrinsics.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class SelectArrayChannelTest : TestBase() {
     @Test
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectBiasTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectBiasTest.kt
index 6f5682d..eee7283 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectBiasTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectBiasTest.kt
@@ -16,11 +16,10 @@
 
 package kotlinx.coroutines.experimental.selects
 
-import kotlinx.coroutines.experimental.async
-import kotlinx.coroutines.experimental.runBlocking
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertTrue
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class SelectBiasTest {
     val n = 10_000
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexStressTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexStressTest.kt
new file mode 100644
index 0000000..d7be9ee
--- /dev/null
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexStressTest.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package kotlinx.coroutines.experimental.selects
+
+import kotlinx.coroutines.experimental.*
+import kotlinx.coroutines.experimental.sync.*
+import kotlin.test.*
+
+class SelectMutexStressTest : TestBase() {
+    @Test
+    fun testSelectCancelledResourceRelease() = runTest {
+        val n = 1_000 * stressTestMultiplier
+        val mutex = Mutex(true) as MutexImpl // locked
+        expect(1)
+        repeat(n) { i ->
+            val job = launch(kotlin.coroutines.experimental.coroutineContext) {
+                expect(i + 2)
+                select<Unit> {
+                    mutex.onLock {
+                        expectUnreached() // never able to lock
+                    }
+                }
+            }
+            yield() // to the launched job, so that it suspends
+            job.cancel() // cancel the job and select
+            yield() // so it can cleanup after itself
+        }
+        assertTrue(mutex.isLocked)
+        assertTrue(mutex.isLockedEmptyQueueState)
+        finish(n + 2)
+    }
+}
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexTest.kt
deleted file mode 100644
index 4f60faf..0000000
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexTest.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental.selects
-
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.sync.Mutex
-import kotlinx.coroutines.experimental.sync.MutexImpl
-import kotlinx.coroutines.experimental.yield
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertTrue
-import org.junit.Test
-
-class SelectMutexTest : TestBase() {
-    @Test
-    fun testSelectLock() = runTest {
-        val mutex = Mutex()
-        expect(1)
-        launch(coroutineContext) { // ensure that it is not scheduled earlier than needed
-            finish(4) // after main exits
-        }
-        val res = select<String> {
-            mutex.onLock {
-                assertTrue(mutex.isLocked)
-                expect(2)
-                "OK"
-            }
-        }
-        assertEquals("OK", res)
-        expect(3)
-        // will wait for the first coroutine
-    }
-
-    @Test
-    fun testSelectLockWait() = runTest {
-        val mutex = Mutex(true) // locked
-        expect(1)
-        launch(coroutineContext) {
-            expect(3)
-            val res = select<String> { // will suspended
-                mutex.onLock {
-                    assertTrue(mutex.isLocked)
-                    expect(6)
-                    "OK"
-                }
-            }
-            assertEquals("OK", res)
-            expect(7)
-        }
-        expect(2)
-        yield() // to launched coroutine
-        expect(4)
-        mutex.unlock()
-        expect(5)
-        yield() // to resumed select
-        finish(8)
-    }
-
-    @Test
-    fun testSelectCancelledResourceRelease() = runTest {
-        val n = 1_000 * stressTestMultiplier
-        val mutex = Mutex(true) as MutexImpl // locked
-        expect(1)
-        repeat(n) { i ->
-            val job = launch(coroutineContext) {
-                expect(i + 2)
-                select<Unit> {
-                    mutex.onLock {
-                        expectUnreached() // never able to lock
-                    }
-                }
-            }
-            yield() // to the launched job, so that it suspends
-            job.cancel() // cancel the job and select
-            yield() // so it can cleanup after itself
-        }
-        assertTrue(mutex.isLocked)
-        assertTrue(mutex.isLockedEmptyQueueState)
-        finish(n + 2)
-    }
-}
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectPhilosophersStressTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectPhilosophersStressTest.kt
index 05892d6..4528a4c 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectPhilosophersStressTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectPhilosophersStressTest.kt
@@ -17,9 +17,10 @@
 package kotlinx.coroutines.experimental.selects
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.sync.Mutex
-import org.junit.Assert.assertTrue
-import org.junit.Test
+import kotlinx.coroutines.experimental.sync.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class SelectPhilosophersStressTest : TestBase() {
     val TEST_DURATION = 3000L * stressTestMultiplier
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectRendezvousChannelTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectRendezvousChannelTest.kt
index b377dd6..d71be6a 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectRendezvousChannelTest.kt
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectRendezvousChannelTest.kt
@@ -16,15 +16,12 @@
 
 package kotlinx.coroutines.experimental.selects
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.channels.ClosedReceiveChannelException
-import kotlinx.coroutines.experimental.channels.RendezvousChannel
-import kotlinx.coroutines.experimental.intrinsics.startCoroutineUndispatched
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import kotlinx.coroutines.experimental.channels.*
+import kotlinx.coroutines.experimental.intrinsics.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class SelectRendezvousChannelTest : TestBase() {
     @Test
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexStressTest.kt b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexStressTest.kt
new file mode 100644
index 0000000..720bd3b
--- /dev/null
+++ b/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexStressTest.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package kotlinx.coroutines.experimental.sync
+
+import kotlinx.coroutines.experimental.*
+import kotlin.test.*
+
+class MutexStressTest : TestBase() {
+    @Test
+    fun testStress() = runTest {
+        val n = 1000 * stressTestMultiplier
+        val k = 100
+        var shared = 0
+        val mutex = Mutex()
+        val jobs = List(n) {
+            launch(CommonPool) {
+                repeat(k) {
+                    mutex.lock()
+                    shared++
+                    mutex.unlock()
+                }
+            }
+        }
+        jobs.forEach { it.join() }
+        println("Shared value = $shared")
+        assertEquals(n * k, shared)
+    }
+}
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannel.kt b/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannel.kt
index 3233a17..59dd21a 100644
--- a/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannel.kt
+++ b/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannel.kt
@@ -164,7 +164,10 @@
         }
 
         var _allocated: ReadWriteBufferState.Initial? = null
-        val (old, newState) = updateState { state ->
+        var old: ReadWriteBufferState? = null
+
+        val newState = updateStateAndGet { state ->
+            old = state
             when {
                 joining != null -> {
                     _allocated?.let { releaseBuffer(it) }
@@ -209,7 +212,7 @@
     private fun restoreStateAfterWrite() {
         var toRelease: ReadWriteBufferState.IdleNonEmpty? = null
 
-        val (_, newState) = updateState {
+        val newState = updateStateAndGet {
             val writeStopped = it.stopWriting()
             if (writeStopped is ReadWriteBufferState.IdleNonEmpty && writeStopped.capacity.isEmpty()) {
                 toRelease = writeStopped
@@ -279,10 +282,10 @@
         }
     }
 
-    private fun setupDelegateTo(delegate: ByteBufferChannel, delegateClose: Boolean): JoiningState {
+    private fun setupDelegateTo(delegate: ByteBufferChannel, delegateClose: Boolean, delegateFlush: Boolean): JoiningState {
         require(this !== delegate)
 
-        val joined = JoiningState(delegate, delegateClose)
+        val joined = JoiningState(delegate, delegateClose, delegateFlush)
         delegate.writeByteOrder = writeByteOrder
         this.joining = joined
 
@@ -290,7 +293,7 @@
         if (alreadyClosed != null) {
             if (alreadyClosed.cause != null) delegate.close(alreadyClosed.cause)
             else if (delegateClose && state === ReadWriteBufferState.Terminated) delegate.close()
-            else delegate.flush()
+            else if (delegateFlush) delegate.flush()
         } else {
             flush()
         }
@@ -324,7 +327,7 @@
     private fun tryReleaseBuffer(forceTermination: Boolean): Boolean {
         var toRelease: ReadWriteBufferState.Initial? = null
 
-        updateState { state ->
+        updateStateAndGet { state ->
             toRelease?.let { buffer ->
                 toRelease = null
                 buffer.capacity.resetForWrite()
@@ -1171,7 +1174,7 @@
         }
     }
 
-    internal suspend fun joinFrom(src: ByteBufferChannel, delegateClose: Boolean) {
+    internal suspend fun joinFrom(src: ByteBufferChannel, delegateClose: Boolean, delegateFlush: Boolean) {
         if (src.closed != null && src.state === ReadWriteBufferState.Terminated) {
             if (delegateClose) close(src.closed!!.cause)
             return
@@ -1181,7 +1184,7 @@
             return
         }
 
-        val joined = src.setupDelegateTo(this, delegateClose)
+        val joined = src.setupDelegateTo(this, delegateClose, delegateFlush)
         if (src.tryCompleteJoining(joined)) {
             return src.awaitClose()
         }
@@ -1195,7 +1198,9 @@
         if (delegateClose && src.isClosedForRead) {
             close()
         } else {
-            flush()
+            if (joined.delegateFlush) {
+                flush()
+            }
             src.awaitClose()
         }
     }
@@ -1312,10 +1317,10 @@
             val writing = joined.delegatedTo.state.let { it is ReadWriteBufferState.Writing || it is ReadWriteBufferState.ReadingWriting }
             if (closed.cause != null || !writing) {
                 joined.delegatedTo.close(closed.cause)
-            } else {
+            } else if (joined.delegateFlush) {
                 joined.delegatedTo.flush()
             }
-        } else {
+        } else if (joined.delegateFlush) {
             joined.delegatedTo.flush()
         }
 
@@ -2283,19 +2288,6 @@
         }
     }
 
-    // todo: replace with atomicfu
-    private inline fun updateState(block: (ReadWriteBufferState) -> ReadWriteBufferState?):
-        Pair<ReadWriteBufferState, ReadWriteBufferState> = update({ state }, State, block)
-
-    // todo: replace with atomicfu
-    private inline fun <T : Any> update(getter: () -> T, updater: AtomicReferenceFieldUpdater<ByteBufferChannel, T>, block: (old: T) -> T?): Pair<T, T> {
-        while (true) {
-            val old = getter()
-            val newValue = block(old) ?: continue
-            if (old === newValue || updater.compareAndSet(this, old, newValue)) return Pair(old, newValue)
-        }
-    }
-
     companion object {
 
         private const val ReservedLongIndex = -8
@@ -2328,7 +2320,7 @@
         }
     }
 
-    internal class JoiningState(val delegatedTo: ByteBufferChannel, val delegateClose: Boolean) {
+    internal class JoiningState(val delegatedTo: ByteBufferChannel, val delegateClose: Boolean, val delegateFlush: Boolean) {
         private val _closeWaitJob = atomic<Job?>(null)
         private val closed = atomic(0)
 
diff --git a/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteReadChannel.kt b/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteReadChannel.kt
index 656d18e..37e4e25 100644
--- a/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteReadChannel.kt
+++ b/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteReadChannel.kt
@@ -167,21 +167,21 @@
 
 typealias ConsumeEachBufferVisitor = (buffer: java.nio.ByteBuffer, last: Boolean) -> Boolean
 
-suspend fun ByteReadChannel.joinTo(dst: ByteWriteChannel, closeOnEnd: Boolean) {
+suspend fun ByteReadChannel.joinTo(dst: ByteWriteChannel, closeOnEnd: Boolean, flushOnEnd: Boolean = true) {
     require(dst !== this)
 
     if (this is ByteBufferChannel && dst is ByteBufferChannel) {
-        return dst.joinFrom(this, closeOnEnd)
+        return dst.joinFrom(this, closeOnEnd, flushOnEnd)
     }
 
-    return joinToImplSuspend(dst, closeOnEnd)
+    return joinToImplSuspend(dst, closeOnEnd, flushOnEnd)
 }
 
-private suspend fun ByteReadChannel.joinToImplSuspend(dst: ByteWriteChannel, close: Boolean) {
+private suspend fun ByteReadChannel.joinToImplSuspend(dst: ByteWriteChannel, close: Boolean, flush: Boolean) {
     copyToImpl(dst, Long.MAX_VALUE)
     if (close) {
         dst.close()
-    } else {
+    } else if (flush) {
         dst.flush()
     }
 }
diff --git a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelScenarioTest.kt b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelScenarioTest.kt
index 5a31352..c7afd0e 100644
--- a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelScenarioTest.kt
+++ b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelScenarioTest.kt
@@ -1,14 +1,12 @@
 package kotlinx.coroutines.experimental.io
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.channels.ClosedReceiveChannelException
+import kotlinx.coroutines.experimental.*
+import kotlinx.coroutines.experimental.channels.*
 import kotlinx.coroutines.experimental.io.internal.*
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
 import org.junit.*
 import org.junit.Test
-import java.io.IOException
+import java.io.*
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
 class ByteBufferChannelScenarioTest : TestBase() {
diff --git a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelTest.kt b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelTest.kt
index f21fa00..1ff9673 100644
--- a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelTest.kt
+++ b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelTest.kt
@@ -1,29 +1,22 @@
 package kotlinx.coroutines.experimental.io
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.channels.ClosedReceiveChannelException
-import kotlinx.coroutines.experimental.io.internal.BUFFER_SIZE
-import kotlinx.coroutines.experimental.io.internal.RESERVED_SIZE
-import kotlinx.coroutines.experimental.io.internal.ReadWriteBufferState
+import kotlinx.coroutines.experimental.CancellationException
+import kotlinx.coroutines.experimental.channels.*
+import kotlinx.coroutines.experimental.io.internal.*
+import kotlinx.coroutines.experimental.io.packet.*
 import kotlinx.coroutines.experimental.io.packet.ByteReadPacket
-import kotlinx.coroutines.experimental.io.packet.ByteWritePacket
-import kotlinx.io.core.BufferView
-import kotlinx.io.core.BytePacketBuilder
-import kotlinx.io.core.readUTF8Line
-import kotlinx.io.pool.DefaultPool
-import kotlinx.io.pool.NoPoolImpl
+import kotlinx.io.core.*
+import kotlinx.io.pool.*
 import org.junit.*
-import org.junit.rules.ErrorCollector
-import org.junit.rules.Timeout
+import org.junit.Test
+import org.junit.rules.*
 import java.nio.CharBuffer
 import java.util.*
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.atomic.AtomicInteger
-import kotlin.test.assertEquals
-import kotlin.test.assertNotEquals
-import kotlin.test.assertTrue
-import kotlin.test.fail
+import java.util.concurrent.*
+import java.util.concurrent.atomic.*
+import kotlin.coroutines.experimental.*
+import kotlin.test.*
 
 class ByteBufferChannelTest : TestBase() {
     @get:Rule
@@ -822,7 +815,7 @@
         latch.await()
     }
 
-    private fun CoroutineScope.launch(name: String = "child", block: suspend () -> Unit): Job {
+    private suspend fun launch(name: String = "child", block: suspend () -> Unit): Job {
         return launch(context = DefaultDispatcher + CoroutineName(name), parent = coroutineContext[Job]) {
             block()
         }.apply {
@@ -1433,6 +1426,21 @@
     }
 
     @Test
+    fun testJoinToNoFlush() = runTest {
+        val src = ByteChannel(false)
+        launch(coroutineContext) {
+            src.joinTo(ch, closeOnEnd = false, flushOnEnd = false)
+            assertEquals(0, ch.availableForRead)
+            ch.flush()
+            assertEquals(4, ch.availableForRead)
+        }
+        yield()
+
+        src.writeInt(777)
+        src.close()
+    }
+
+    @Test
     fun testReadBlock() = runTest {
         var bytesRead = 0L
 
diff --git a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/CopyAndCloseNoAutoFlushTest.kt b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/CopyAndCloseNoAutoFlushTest.kt
index f026567..ab02c29 100644
--- a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/CopyAndCloseNoAutoFlushTest.kt
+++ b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/CopyAndCloseNoAutoFlushTest.kt
@@ -1,15 +1,12 @@
 package kotlinx.coroutines.experimental.io
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.io.internal.BufferObjectPool
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.junit.Rule
+import kotlinx.coroutines.experimental.*
+import kotlinx.coroutines.experimental.io.internal.*
+import org.junit.*
 import org.junit.Test
-import org.junit.rules.TestRule
-import kotlin.test.assertEquals
-import kotlin.test.assertTrue
+import org.junit.rules.*
+import kotlin.coroutines.experimental.*
+import kotlin.test.*
 
 class CopyAndCloseNoAutoFlushTest : TestBase() {
     private val verifyingPool = VerifyingObjectPool(BufferObjectPool)
diff --git a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/CopyAndCloseTest.kt b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/CopyAndCloseTest.kt
index edd0b14..504a103 100644
--- a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/CopyAndCloseTest.kt
+++ b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/CopyAndCloseTest.kt
@@ -1,12 +1,12 @@
 package kotlinx.coroutines.experimental.io
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.io.internal.asByteBuffer
-import org.junit.After
+import kotlinx.coroutines.experimental.io.internal.*
+import org.junit.*
 import org.junit.Test
-import java.io.IOException
-import kotlin.test.assertEquals
-import kotlin.test.fail
+import java.io.*
+import kotlin.coroutines.experimental.*
+import kotlin.test.*
 
 class CopyAndCloseTest : TestBase() {
     private val from = ByteChannel(true)
diff --git a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/InlineRendezvousSwapTest.kt b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/InlineRendezvousSwapTest.kt
index 549f703..8d868c2 100644
--- a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/InlineRendezvousSwapTest.kt
+++ b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/InlineRendezvousSwapTest.kt
@@ -5,6 +5,7 @@
 import kotlinx.coroutines.experimental.io.internal.*
 import org.junit.Ignore
 import org.junit.Test
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
 @Ignore
diff --git a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/JavaIOTest.kt b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/JavaIOTest.kt
index 91a7ad0..c8bc8e7 100644
--- a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/JavaIOTest.kt
+++ b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/JavaIOTest.kt
@@ -7,6 +7,7 @@
 import java.io.*
 import java.nio.channels.*
 import java.util.*
+import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
 class JavaIOTest : TestBase() {
diff --git a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ReadUntilDelimiterTest.kt b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ReadUntilDelimiterTest.kt
index e18e406..5001037 100644
--- a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ReadUntilDelimiterTest.kt
+++ b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ReadUntilDelimiterTest.kt
@@ -1,15 +1,12 @@
 package kotlinx.coroutines.experimental.io
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.io.internal.BUFFER_SIZE
-import kotlinx.coroutines.experimental.io.internal.asByteBuffer
-import org.junit.After
-import org.junit.Before
+import kotlinx.coroutines.experimental.io.internal.*
+import org.junit.*
 import org.junit.Test
-import java.io.IOException
-import kotlin.test.assertEquals
-import kotlin.test.assertTrue
-import kotlin.test.fail
+import java.io.*
+import kotlin.coroutines.experimental.*
+import kotlin.test.*
 
 class ReadUntilDelimiterTest : TestBase() {
     private val source = ByteChannel(true)
diff --git a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/StringScenarioTest.kt b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/StringScenarioTest.kt
index 3ccd35e..3f49233 100644
--- a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/StringScenarioTest.kt
+++ b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/StringScenarioTest.kt
@@ -1,15 +1,12 @@
 package kotlinx.coroutines.experimental.io
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.junit.Rule
+import kotlinx.coroutines.experimental.*
+import org.junit.*
 import org.junit.Test
-import org.junit.rules.Timeout
-import java.util.concurrent.TimeUnit
-import kotlin.test.assertEquals
-import kotlin.test.assertTrue
+import org.junit.rules.*
+import java.util.concurrent.*
+import kotlin.coroutines.experimental.*
+import kotlin.test.*
 
 class StringScenarioTest : TestBase() {
     @get:Rule
diff --git a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/StringsTest.kt b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/StringsTest.kt
index 0e2d32a..a1a81f9 100644
--- a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/StringsTest.kt
+++ b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/StringsTest.kt
@@ -1,15 +1,13 @@
 package kotlinx.coroutines.experimental.io
 
 import kotlinx.coroutines.experimental.*
-import org.junit.Rule
+import org.junit.*
 import org.junit.Test
-import org.junit.rules.Timeout
+import org.junit.rules.*
 import java.util.*
-import java.util.concurrent.TimeUnit
-import kotlin.test.assertEquals
-import kotlin.test.assertNotEquals
-import kotlin.test.assertNull
-import kotlin.test.fail
+import java.util.concurrent.*
+import kotlin.coroutines.experimental.*
+import kotlin.test.*
 
 class StringsTest : TestBase() {
     @get:Rule
diff --git a/coroutines-guide.md b/coroutines-guide.md
index 59b86b8..65e9130 100644
--- a/coroutines-guide.md
+++ b/coroutines-guide.md
@@ -620,7 +620,7 @@
 delays for a second for the purpose of this example:
 
 <!--- INCLUDE .*/example-compose-([0-9]+).kt
-import kotlin.system.measureTimeMillis
+import kotlin.system.*
 -->
 
 ```kotlin
@@ -807,6 +807,10 @@
 
 Try the following example:
 
+<!--- INCLUDE
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 fun main(args: Array<String>) = runBlocking<Unit> {
     val jobs = arrayListOf<Job>()
@@ -843,7 +847,8 @@
 is equal to [CommonPool] in the current implementation. So, `launch { ... }` is the same 
 as `launch(DefaultDispatcher) { ... }`, which is the same as `launch(CommonPool) { ... }`. 
 
-The difference between parent [coroutineContext][CoroutineScope.coroutineContext] and
+The difference between parent 
+[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html) and
 [Unconfined] context will be shown later.
 
 Note, that [newSingleThreadContext] creates a new thread, which is a very expensive resource. 
@@ -857,12 +862,17 @@
 suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
 consume CPU time nor updates any shared data (like UI) that is confined to a specific thread. 
 
-On the other side, [coroutineContext][CoroutineScope.coroutineContext] property that is available inside the block of any coroutine
-via [CoroutineScope] interface, is a reference to a context of this particular coroutine. 
+On the other side, 
+[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
+property, that is available inside any coroutine, is a reference to a context of this particular coroutine. 
 This way, a parent context can be inherited. The default dispatcher for [runBlocking] coroutine, in particular,
 is confined to the invoker thread, so inheriting it has the effect of confining execution to
 this thread with a predictable FIFO scheduling.
 
+<!--- INCLUDE
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 fun main(args: Array<String>) = runBlocking<Unit> {
     val jobs = arrayListOf<Job>()
@@ -908,6 +918,10 @@
 
 Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
 
+<!--- INCLUDE
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
 
@@ -990,6 +1004,10 @@
 The coroutine's [Job] is part of its context. The coroutine can retrieve it from its own context 
 using `coroutineContext[Job]` expression:
 
+<!--- INCLUDE  
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 fun main(args: Array<String>) = runBlocking<Unit> {
     println("My job is ${coroutineContext[Job]}")
@@ -1007,15 +1025,21 @@
 <!--- TEST lines.size == 1 && lines[0].startsWith("My job is \"coroutine#1\":BlockingCoroutine{Active}@") -->
 
 So, [isActive][CoroutineScope.isActive] in [CoroutineScope] is just a convenient shortcut for
-`coroutineContext[Job]!!.isActive`.
+`coroutineContext[Job]?.isActive == true`.
 
 ### Children of a coroutine
 
-When [coroutineContext][CoroutineScope.coroutineContext] of a coroutine is used to launch another coroutine,
+When 
+[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
+of a coroutine is used to launch another coroutine,
 the [Job] of the new coroutine becomes
 a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
 are recursively cancelled, too. 
   
+<!--- INCLUDE
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 fun main(args: Array<String>) = runBlocking<Unit> {
     // launch a coroutine to process some kind of incoming request
@@ -1063,6 +1087,10 @@
 of the context on the left-hand side. For example, a [Job] of the parent coroutine can be inherited, while 
 its dispatcher replaced:
 
+<!--- INCLUDE
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 fun main(args: Array<String>) = runBlocking<Unit> {
     // start a coroutine to process some kind of incoming request
@@ -1098,6 +1126,10 @@
 A parent coroutine always waits for completion of all its children. Parent does not have to explicitly track
 all the children it launches and it does not have to use [Job.join] to wait for them at the end:
 
+<!--- INCLUDE
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 fun main(args: Array<String>) = runBlocking<Unit> {
     // launch a coroutine to process some kind of incoming request
@@ -1189,6 +1221,10 @@
 Moreover, [Job.join] waits for all of them to complete, so we can also use [cancelAndJoin] here in
 this example:
 
+<!--- INCLUDE
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 fun main(args: Array<String>) = runBlocking<Unit> {
     val job = Job() // create a job object to manage our lifecycle
@@ -1394,8 +1430,8 @@
 explicit `context` parameter and pass it to [produce] builder, 
 so that caller can control where our coroutines run:
  
-<!--- INCLUDE core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt  
-import kotlin.coroutines.experimental.CoroutineContext
+<!--- INCLUDE  
+import kotlin.coroutines.experimental.*
 -->
  
 ```kotlin
@@ -1423,8 +1459,9 @@
  
 The following example prints the first ten prime numbers, 
 running the whole pipeline in the context of the main thread. Since all the coroutines are launched as
-children of the main [runBlocking] coroutine in its [coroutineContext][CoroutineScope.coroutineContext],
-we don't have to keep an explicit list of all the coroutine we have started. 
+children of the main [runBlocking] coroutine in its 
+[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html),
+we don't have to keep an explicit list of all the coroutines we have started. 
 We use [cancelChildren][kotlin.coroutines.experimental.CoroutineContext.cancelChildren] 
 extension function to cancel all the children coroutines. 
 
@@ -1539,6 +1576,10 @@
 For example, let us have a channel of strings, and a suspending function that 
 repeatedly sends a specified string to this channel with a specified delay:
 
+<!--- INCLUDE  
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
     while (true) {
@@ -1590,6 +1631,10 @@
 
 Take a look at the behavior of the following code:
 
+<!--- INCLUDE  
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 fun main(args: Array<String>) = runBlocking<Unit> {
     val channel = Channel<Int>(4) // create buffered channel
@@ -1628,6 +1673,10 @@
 gets the element. In the following example two coroutines "ping" and "pong" are 
 receiving the "ball" object from the shared "table" channel. 
 
+<!--- INCLUDE
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 data class Ball(var hits: Int)
 
@@ -1680,24 +1729,23 @@
 Let us launch a thousand coroutines all doing the same action thousand times (for a total of a million executions). 
 We'll also measure their completion time for further comparisons:
 
-<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.system.measureTimeMillis
--->
-
 <!--- INCLUDE .*/example-sync-03.kt
-import java.util.concurrent.atomic.AtomicInteger
+import java.util.concurrent.atomic.*
 -->
 
 <!--- INCLUDE .*/example-sync-06.kt
-import kotlinx.coroutines.experimental.sync.Mutex
-import kotlinx.coroutines.experimental.sync.withLock
+import kotlinx.coroutines.experimental.sync.*
 -->
 
 <!--- INCLUDE .*/example-sync-07.kt
 import kotlinx.coroutines.experimental.channels.*
 -->
 
+<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
+import kotlin.system.*
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
     val n = 1000 // number of coroutines to launch
@@ -1999,8 +2047,9 @@
 
 Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
 
-<!--- INCLUDE .*/example-select-01.kt
-import kotlin.coroutines.experimental.CoroutineContext
+<!--- INCLUDE
+import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -2076,6 +2125,10 @@
 specific action when the channel is closed. The following example also shows that `select` is an expression that returns 
 the result of its selected clause:
 
+<!--- INCLUDE
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
     select<String> {
@@ -2149,7 +2202,7 @@
 the consumers on its primary channel cannot keep up with it:
 
 <!--- INCLUDE
-import kotlin.coroutines.experimental.CoroutineContext
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -2165,7 +2218,7 @@
 ```
 
 Consumer is going to be quite slow, taking 250 ms to process each number:
- 
+
 ```kotlin
 fun main(args: Array<String>) = runBlocking<Unit> {
     val side = Channel<Int>() // allocate side channel
@@ -2265,6 +2318,10 @@
 deferred value, but only until the next deferred value comes over or the channel is closed. This example puts together 
 [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
 
+<!--- INCLUDE
+import kotlin.coroutines.experimental.*
+-->
+
 ```kotlin
 fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
     var current = input.receive() // start with first received deferred value
@@ -2365,7 +2422,6 @@
 [CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
 [DefaultDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-default-dispatcher.html
 [CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
-[CoroutineScope.coroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/coroutine-context.html
 [Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
 [newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
 [ThreadPoolDispatcher.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-thread-pool-dispatcher/close.html
diff --git a/gradle.properties b/gradle.properties
index 9b81562..a062258 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,11 +1,13 @@
 version = 0.22.5-SNAPSHOT
+group = org.jetbrains.kotlinx
 
-kotlin_version = 1.2.21
+kotlin_version = 1.2.31
+kotlin_native_version = 0.7-dev-1436
 junit_version = 4.12
-atomicFU_version = 0.9.2
+atomicFU_version = 0.10.0-alpha
 html_version = 0.6.8
 lincheck_version=1.9
-dokka_version = 0.9.16-dev-mpp-hacks-1
+dokka_version = 0.9.16-rdev-2-mpp-hacks
 bintray_version = 1.7.3
 
 gradle_node_version = 1.2.0
@@ -14,6 +16,6 @@
 mocha_version = 4.1.0
 mocha_headless_chrome_version = 1.8.2
 mocha_teamcity_reporter_version = 2.2.2
-source_map_suport_version = 0.5.3
+source_map_support_version = 0.5.3
 
 kotlin.incremental.multiplatform=true
\ No newline at end of file
diff --git a/gradle/atomicfu-common.gradle b/gradle/atomicfu-common.gradle
new file mode 100644
index 0000000..bf524c1
--- /dev/null
+++ b/gradle/atomicfu-common.gradle
@@ -0,0 +1,4 @@
+
+dependencies {
+    compile "org.jetbrains.kotlinx:atomicfu-common:$atomicFU_version"
+}
\ No newline at end of file
diff --git a/gradle/atomicfu-js.gradle b/gradle/atomicfu-js.gradle
new file mode 100644
index 0000000..05f09f4
--- /dev/null
+++ b/gradle/atomicfu-js.gradle
@@ -0,0 +1,4 @@
+
+dependencies {
+    compile "org.jetbrains.kotlinx:atomicfu-js:$atomicFU_version"
+}
diff --git a/gradle/atomicfu-jvm.gradle b/gradle/atomicfu-jvm.gradle
new file mode 100644
index 0000000..a812931
--- /dev/null
+++ b/gradle/atomicfu-jvm.gradle
@@ -0,0 +1,22 @@
+apply plugin: 'kotlinx-atomicfu'
+
+dependencies {
+    compileOnly "org.jetbrains.kotlinx:atomicfu:$atomicFU_version"
+    testCompile "org.jetbrains.kotlinx:atomicfu:$atomicFU_version"
+}
+
+atomicFU {
+    inputFiles = sourceSets.main.output.classesDirs
+    outputDir = file("$buildDir/classes-atomicfu/main")
+    classPath = sourceSets.main.runtimeClasspath
+}
+
+jar {
+    mainSpec.sourcePaths.clear() // hack to clear existing paths
+    from files(atomicFU.outputs, sourceSets.main.output.resourcesDir)
+}
+
+test {
+    classpath = files(configurations.testRuntime, atomicFU.outputs, sourceSets.test.output.classesDirs,
+            sourceSets.main.output.resourcesDir)
+}
diff --git a/gradle/atomicfu-native.gradle b/gradle/atomicfu-native.gradle
new file mode 100644
index 0000000..75f0128
--- /dev/null
+++ b/gradle/atomicfu-native.gradle
@@ -0,0 +1,6 @@
+
+// todo: this does not work in Kotlin/Native
+
+//dependencies {
+//    compile "org.jetbrains.kotlinx:atomicfu-native:$atomicFU_version"
+//}
diff --git a/gradle/compile-common.gradle b/gradle/compile-common.gradle
new file mode 100644
index 0000000..b09589c
--- /dev/null
+++ b/gradle/compile-common.gradle
@@ -0,0 +1,17 @@
+
+// Platform-specific configuration to compile common modules
+
+apply plugin: 'kotlin-platform-common'
+
+kotlin.experimental.coroutines "enable"
+
+dependencies {
+    compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
+    testCompile "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
+    testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
+}
+
+repositories {
+    jcenter()
+    maven { url "https://kotlin.bintray.com/kotlinx" }
+}
diff --git a/gradle/compile-js.gradle b/gradle/compile-js.gradle
new file mode 100644
index 0000000..59c47d2
--- /dev/null
+++ b/gradle/compile-js.gradle
@@ -0,0 +1,33 @@
+
+// Platform-specific configuration to compile JS modules
+
+apply plugin: 'kotlin-platform-js'
+
+kotlin.experimental.coroutines "enable"
+
+dependencies {
+    compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
+    testCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version"
+}
+
+repositories {
+    jcenter()
+    maven { url "https://kotlin.bintray.com/kotlinx" }
+}
+
+tasks.withType(compileKotlin2Js.getClass()) {
+    kotlinOptions {
+        moduleKind = "umd"
+        sourceMap = true
+        metaInfo = true
+    }
+}
+
+compileKotlin2Js {
+    kotlinOptions {
+        // drop -js suffix from outputFile
+        def baseName = project.name - "-js"
+        outputFile = new File(outputFile.parent, baseName + ".js")
+    }
+}
+
diff --git a/gradle/compile-jvm.gradle b/gradle/compile-jvm.gradle
new file mode 100644
index 0000000..74030e5
--- /dev/null
+++ b/gradle/compile-jvm.gradle
@@ -0,0 +1,31 @@
+
+// Platform-specific configuration to compile JVM modules
+
+apply plugin: 'kotlin-platform-jvm'
+
+sourceCompatibility = 1.6
+targetCompatibility = 1.6
+
+kotlin.experimental.coroutines "enable"
+
+dependencies {
+    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+    testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
+    testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
+    testCompile "junit:junit:$junit_version"
+}
+
+repositories {
+    jcenter()
+    maven { url "https://kotlin.bintray.com/kotlinx" }
+    maven { url "https://dl.bintray.com/devexperts/Maven/" }
+}
+
+tasks.withType(Test) {
+    testLogging {
+        showStandardStreams = true
+        events "passed", "failed"
+    }
+    def stressTest = project.properties['stressTest']
+    if (stressTest != null) systemProperties['stressTest'] = stressTest
+}
diff --git a/gradle/compile-native.gradle b/gradle/compile-native.gradle
new file mode 100644
index 0000000..6de11bb
--- /dev/null
+++ b/gradle/compile-native.gradle
@@ -0,0 +1,37 @@
+apply plugin: 'konan'
+
+repositories {
+    jcenter()
+    maven { url "https://kotlin.bintray.com/kotlinx" }
+}
+
+def libraryName = project.name
+def testProgramName = libraryName + "-test"
+
+konanArtifacts {
+    library(libraryName, targets: ["ios_arm64", "ios_x64", "macos_x64"]) {
+        artifactName libraryName.replace('-', '_')
+        enableMultiplatform true
+        dependencies {
+            "artifact$libraryName" "org.jetbrains.kotlinx:atomicfu-native:$atomicFU_version"
+        }
+    }
+    // TODO: THIS IS A WORKAROUND: Cannot do tests together with publishing in Kotlin/Native
+    if (!rootProject.properties["publish"]) {
+        program(testProgramName, targets: ["macos_x64"]) {
+            srcDir 'src/test/kotlin'
+            commonSourceSet 'test'
+            libraries {
+                artifact libraryName
+            }
+            extraOpts '-tr'
+        }
+    }
+}
+
+task test(dependsOn: run)
+
+// TODO: THIS IS A WORKAROUND: Cannot do tests together with publishing in Kotlin/Native
+if (rootProject.properties["publish"]) {
+    publishToMavenLocal.dependsOn(build)
+}
diff --git a/gradle/test-mocha-js.gradle b/gradle/test-mocha-js.gradle
index 42023b8..c2f7503 100644
--- a/gradle/test-mocha-js.gradle
+++ b/gradle/test-mocha-js.gradle
@@ -3,7 +3,7 @@
 task installDependenciesMochaNode(type: NpmTask, dependsOn: [npmInstall]) {
     args = ['install',
             "mocha@$mocha_version",
-            "source-map-support@$source_map_suport_version",
+            "source-map-support@$source_map_support_version",
             '--no-save']
     if (project.hasProperty("teamcity")) args += [
             "mocha-teamcity-reporter@$mocha_teamcity_reporter_version"]
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 7a3265e..f6b961f 100644
--- a/gradle/wrapper/gradle-wrapper.jar
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 7ee7399..bf3de21 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-#Sun Oct 15 15:39:27 MSK 2017
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.2.1-all.zip
diff --git a/integration/kotlinx-coroutines-guava/src/main/kotlin/kotlinx/coroutines/experimental/guava/ListenableFuture.kt b/integration/kotlinx-coroutines-guava/src/main/kotlin/kotlinx/coroutines/experimental/guava/ListenableFuture.kt
index b8d8ff5..81bbbb5 100644
--- a/integration/kotlinx-coroutines-guava/src/main/kotlin/kotlinx/coroutines/experimental/guava/ListenableFuture.kt
+++ b/integration/kotlinx-coroutines-guava/src/main/kotlin/kotlinx/coroutines/experimental/guava/ListenableFuture.kt
@@ -16,14 +16,9 @@
 
 package kotlinx.coroutines.experimental.guava
 
-import com.google.common.util.concurrent.AbstractFuture
-import com.google.common.util.concurrent.FutureCallback
-import com.google.common.util.concurrent.Futures
-import com.google.common.util.concurrent.ListenableFuture
+import com.google.common.util.concurrent.*
 import kotlinx.coroutines.experimental.*
-import kotlin.coroutines.experimental.Continuation
-import kotlin.coroutines.experimental.ContinuationInterceptor
-import kotlin.coroutines.experimental.CoroutineContext
+import kotlin.coroutines.experimental.*
 
 /**
  * Starts new coroutine and returns its results an an implementation of [ListenableFuture].
@@ -33,7 +28,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
@@ -50,12 +45,14 @@
  * @param context context of the coroutine. The default value is [DefaultDispatcher].
  * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
  * @param parent explicitly specifies the parent job, overrides job from the [context] (if any).
+ * @param onCompletion optional completion handler for the coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
 public fun <T> future(
     context: CoroutineContext = DefaultDispatcher,
     start: CoroutineStart = CoroutineStart.DEFAULT,
     parent: Job? = null,
+    onCompletion: CompletionHandler? = null,
     block: suspend CoroutineScope.() -> T
 ): ListenableFuture<T> {
     require(!start.isLazy) { "$start start is not supported" }
@@ -63,6 +60,7 @@
     val job = Job(newContext[Job])
     val future = ListenableFutureCoroutine<T>(newContext + job)
     job.cancelFutureOnCompletion(future)
+    if (onCompletion != null) job.invokeOnCompletion(handler = onCompletion)
     start(block, receiver=future, completion=future) // use the specified start strategy
     return future
 }
@@ -72,6 +70,15 @@
 public fun <T> future(
     context: CoroutineContext = DefaultDispatcher,
     start: CoroutineStart = CoroutineStart.DEFAULT,
+    parent: Job? = null,
+    block: suspend CoroutineScope.() -> T
+): ListenableFuture<T> = future(context, start, parent, block = block)
+
+/** @suppress **Deprecated**: Binary compatibility */
+@Deprecated(message = "Binary compatibility", level = DeprecationLevel.HIDDEN)
+public fun <T> future(
+    context: CoroutineContext = DefaultDispatcher,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
     block: suspend CoroutineScope.() -> T
 ): ListenableFuture<T> =
     future(context, start, block = block)
diff --git a/integration/kotlinx-coroutines-guava/src/test/kotlin/kotlinx/coroutines/experimental/guava/ListenableFutureTest.kt b/integration/kotlinx-coroutines-guava/src/test/kotlin/kotlinx/coroutines/experimental/guava/ListenableFutureTest.kt
index 767bb1c..7db81ca 100644
--- a/integration/kotlinx-coroutines-guava/src/test/kotlin/kotlinx/coroutines/experimental/guava/ListenableFutureTest.kt
+++ b/integration/kotlinx-coroutines-guava/src/test/kotlin/kotlinx/coroutines/experimental/guava/ListenableFutureTest.kt
@@ -16,17 +16,14 @@
 
 package kotlinx.coroutines.experimental.guava
 
-import com.google.common.util.concurrent.MoreExecutors
-import com.google.common.util.concurrent.SettableFuture
+import com.google.common.util.concurrent.*
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
+import kotlinx.coroutines.experimental.CancellationException
+import org.hamcrest.core.*
+import org.junit.*
 import org.junit.Assert.*
-import org.junit.Before
-import org.junit.Test
-import java.util.concurrent.Callable
-import java.util.concurrent.ExecutionException
-import java.util.concurrent.ForkJoinPool
+import java.util.concurrent.*
+import kotlin.coroutines.experimental.*
 
 class ListenableFutureTest : TestBase() {
     @Before
diff --git a/integration/kotlinx-coroutines-jdk8/src/main/kotlin/kotlinx/coroutines/experimental/future/Future.kt b/integration/kotlinx-coroutines-jdk8/src/main/kotlin/kotlinx/coroutines/experimental/future/Future.kt
index 8bb8462..ee908e3 100644
--- a/integration/kotlinx-coroutines-jdk8/src/main/kotlin/kotlinx/coroutines/experimental/future/Future.kt
+++ b/integration/kotlinx-coroutines-jdk8/src/main/kotlin/kotlinx/coroutines/experimental/future/Future.kt
@@ -17,15 +17,9 @@
 package kotlinx.coroutines.experimental.future
 
 import kotlinx.coroutines.experimental.*
-import java.util.concurrent.CompletableFuture
-import java.util.concurrent.CompletionStage
-import java.util.concurrent.ExecutionException
-import java.util.concurrent.Future
-import java.util.function.BiConsumer
-import kotlin.coroutines.experimental.Continuation
-import kotlin.coroutines.experimental.ContinuationInterceptor
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.coroutines.experimental.suspendCoroutine
+import java.util.concurrent.*
+import java.util.function.*
+import kotlin.coroutines.experimental.*
 
 /**
  * Starts new coroutine and returns its result as an implementation of [CompletableFuture].
@@ -35,7 +29,8 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.coroutineContext] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
+ * of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
@@ -52,12 +47,14 @@
  * @param context context of the coroutine. The default value is [DefaultDispatcher].
  * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
  * @param parent explicitly specifies the parent job, overrides job from the [context] (if any).
+ * @param onCompletion optional completion handler for the coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
 public fun <T> future(
     context: CoroutineContext = DefaultDispatcher,
     start: CoroutineStart = CoroutineStart.DEFAULT,
     parent: Job? = null,
+    onCompletion: CompletionHandler? = null,
     block: suspend CoroutineScope.() -> T
 ): CompletableFuture<T> {
     require(!start.isLazy) { "$start start is not supported" }
@@ -66,6 +63,7 @@
     val future = CompletableFutureCoroutine<T>(newContext + job)
     job.cancelFutureOnCompletion(future)
     future.whenComplete { _, exception -> job.cancel(exception) }
+    if (onCompletion != null) job.invokeOnCompletion(handler = onCompletion)
     start(block, receiver=future, completion=future) // use the specified start strategy
     return future
 }
@@ -75,6 +73,15 @@
 public fun <T> future(
     context: CoroutineContext = DefaultDispatcher,
     start: CoroutineStart = CoroutineStart.DEFAULT,
+    parent: Job? = null,
+    block: suspend CoroutineScope.() -> T
+): CompletableFuture<T> = future(context, start, parent, block = block)
+
+/** @suppress **Deprecated**: Binary compatibility */
+@Deprecated(message = "Binary compatibility", level = DeprecationLevel.HIDDEN)
+public fun <T> future(
+    context: CoroutineContext = DefaultDispatcher,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
     block: suspend CoroutineScope.() -> T
 ): CompletableFuture<T> =
     future(context, start, block = block)
diff --git a/integration/kotlinx-coroutines-jdk8/src/test/kotlin/kotlinx/coroutines/experimental/future/FutureTest.kt b/integration/kotlinx-coroutines-jdk8/src/test/kotlin/kotlinx/coroutines/experimental/future/FutureTest.kt
index 2996b21..1363287 100644
--- a/integration/kotlinx-coroutines-jdk8/src/test/kotlin/kotlinx/coroutines/experimental/future/FutureTest.kt
+++ b/integration/kotlinx-coroutines-jdk8/src/test/kotlin/kotlinx/coroutines/experimental/future/FutureTest.kt
@@ -18,15 +18,14 @@
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.CancellationException
-import org.hamcrest.core.IsEqual
+import org.hamcrest.core.*
+import org.junit.*
 import org.junit.Assert.*
-import org.junit.Before
-import org.junit.Test
 import java.util.concurrent.*
-import java.util.concurrent.atomic.AtomicInteger
-import java.util.concurrent.locks.ReentrantLock
-import kotlin.concurrent.withLock
-import kotlin.coroutines.experimental.CoroutineContext
+import java.util.concurrent.atomic.*
+import java.util.concurrent.locks.*
+import kotlin.concurrent.*
+import kotlin.coroutines.experimental.*
 
 class FutureTest : TestBase() {
     @Before
diff --git a/integration/kotlinx-coroutines-nio/src/test/kotlin/examples/echo-example.kt b/integration/kotlinx-coroutines-nio/src/test/kotlin/examples/echo-example.kt
index e279cbd..5692c35 100644
--- a/integration/kotlinx-coroutines-nio/src/test/kotlin/examples/echo-example.kt
+++ b/integration/kotlinx-coroutines-nio/src/test/kotlin/examples/echo-example.kt
@@ -16,16 +16,12 @@
 
 package examples
 
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.nio.aAccept
-import kotlinx.coroutines.experimental.nio.aRead
-import kotlinx.coroutines.experimental.nio.aWrite
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.withTimeout
-import java.net.InetSocketAddress
-import java.nio.ByteBuffer
-import java.nio.channels.AsynchronousServerSocketChannel
-import java.nio.channels.AsynchronousSocketChannel
+import kotlinx.coroutines.experimental.*
+import kotlinx.coroutines.experimental.nio.*
+import java.net.*
+import java.nio.*
+import java.nio.channels.*
+import kotlin.coroutines.experimental.*
 
 val PORT = 12345
 val CLIENT_READ_TIMEOUT = 5000L // 5 sec
diff --git a/integration/kotlinx-coroutines-nio/src/test/kotlin/kotlinx/coroutines/experimental/nio/AsyncIOTest.kt b/integration/kotlinx-coroutines-nio/src/test/kotlin/kotlinx/coroutines/experimental/nio/AsyncIOTest.kt
index 7fd38d8..0121c51 100644
--- a/integration/kotlinx-coroutines-nio/src/test/kotlin/kotlinx/coroutines/experimental/nio/AsyncIOTest.kt
+++ b/integration/kotlinx-coroutines-nio/src/test/kotlin/kotlinx/coroutines/experimental/nio/AsyncIOTest.kt
@@ -16,19 +16,16 @@
 
 package kotlinx.coroutines.experimental.nio
 
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import org.apache.commons.io.FileUtils
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.TemporaryFolder
-import java.net.InetSocketAddress
-import java.nio.ByteBuffer
-import java.nio.channels.AsynchronousFileChannel
-import java.nio.channels.AsynchronousServerSocketChannel
-import java.nio.channels.AsynchronousSocketChannel
-import java.nio.file.StandardOpenOption
+import kotlinx.coroutines.experimental.*
+import org.apache.commons.io.*
+import org.junit.*
 import org.junit.Assert.*
+import org.junit.rules.*
+import java.net.*
+import java.nio.*
+import java.nio.channels.*
+import java.nio.file.*
+import kotlin.coroutines.experimental.*
 
 class AsyncIOTest {
     @Rule
diff --git a/integration/kotlinx-coroutines-quasar/src/test/kotlin/kotlinx/coroutines/experimental/quasar/QuasarTest.kt b/integration/kotlinx-coroutines-quasar/src/test/kotlin/kotlinx/coroutines/experimental/quasar/QuasarTest.kt
index 0782882..43f23e7 100644
--- a/integration/kotlinx-coroutines-quasar/src/test/kotlin/kotlinx/coroutines/experimental/quasar/QuasarTest.kt
+++ b/integration/kotlinx-coroutines-quasar/src/test/kotlin/kotlinx/coroutines/experimental/quasar/QuasarTest.kt
@@ -16,14 +16,13 @@
 
 package kotlinx.coroutines.experimental.quasar
 
-import co.paralleluniverse.fibers.Fiber
-import co.paralleluniverse.fibers.SuspendExecution
-import co.paralleluniverse.strands.SuspendableCallable
-import co.paralleluniverse.strands.dataflow.Val
+import co.paralleluniverse.fibers.*
+import co.paralleluniverse.strands.*
+import co.paralleluniverse.strands.dataflow.*
 import kotlinx.coroutines.experimental.*
-import org.junit.Before
-import org.junit.Test
-import java.util.concurrent.TimeUnit
+import org.junit.*
+import java.util.concurrent.*
+import kotlin.coroutines.experimental.*
 
 class QuasarTest : TestBase() {
     @Before
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/AbstractContinuation.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/AbstractContinuation.kt
deleted file mode 100644
index 6b31a91..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/AbstractContinuation.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.Continuation
-import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED
-
-private const val UNDECIDED = 0
-private const val SUSPENDED = 1
-private const val RESUMED = 2
-
-/**
- * @suppress **This is unstable API and it is subject to change.**
- */
-internal abstract class AbstractContinuation<in T>(
-    public final override val delegate: Continuation<T>,
-    public final override val resumeMode: Int
-) : JobSupport(true), Continuation<T>, DispatchedTask<T> {
-    private var decision = UNDECIDED
-
-    /* decision state machine
-
-        +-----------+   trySuspend   +-----------+
-        | UNDECIDED | -------------> | SUSPENDED |
-        +-----------+                +-----------+
-              |
-              | tryResume
-              V
-        +-----------+
-        |  RESUMED  |
-        +-----------+
-
-        Note: both tryResume and trySuspend can be invoked at most once, first invocation wins
-     */
-
-    override fun takeState(): Any? = state
-
-    private fun trySuspend(): Boolean = when (decision) {
-        UNDECIDED -> { decision = SUSPENDED; true }
-        RESUMED -> false
-        else -> error("Already suspended")
-    }
-
-    private fun tryResume(): Boolean = when (decision) {
-        UNDECIDED -> { decision = RESUMED; true }
-        SUSPENDED -> false
-        else -> error("Already resumed")
-    }
-
-    @PublishedApi
-    internal fun getResult(): Any? {
-        if (trySuspend()) return COROUTINE_SUSPENDED
-        // otherwise, onCompletionInternal was already invoked & invoked tryResume, and the result is in the state
-        val state = this.state
-        if (state is CompletedExceptionally) throw state.exception
-        return getSuccessfulResult(state)
-    }
-
-    internal final override fun onCompletionInternal(state: Any?, mode: Int) {
-        if (tryResume()) return // completed before getResult invocation -- bail out
-        // otherwise, getResult has already commenced, i.e. completed later or in other thread
-        dispatch(mode)
-    }
-
-    override fun resume(value: T) =
-        resumeImpl(value, resumeMode)
-
-    override fun resumeWithException(exception: Throwable) =
-        resumeImpl(CompletedExceptionally(exception), resumeMode)
-
-    protected fun resumeImpl(proposedUpdate: Any?, resumeMode: Int) {
-        val state = this.state
-        return when (state) {
-            is Incomplete -> updateState(proposedUpdate, resumeMode)
-            is Cancelled -> {
-                // Ignore resumes in cancelled coroutines, but handle exception if a different one here
-                if (proposedUpdate is CompletedExceptionally && proposedUpdate.exception != state.exception)
-                    handleException(proposedUpdate.exception)
-                return
-            }
-            else -> error("Already resumed, but got $proposedUpdate")
-        }
-    }
-
-    override fun handleException(exception: Throwable) {
-        handleCoroutineException(context, exception)
-    }
-}
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonScheduled.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Annotations.kt
similarity index 64%
copy from common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonScheduled.kt
copy to js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Annotations.kt
index d9181d0..26c19ae 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonScheduled.kt
+++ b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Annotations.kt
@@ -14,8 +14,14 @@
  * limitations under the License.
  */
 
-package kotlinx.coroutines.experimental
+package kotlinx.coroutines.experimental.internalAnnotations
 
-public expect suspend fun <T> withTimeout(time: Int, block: suspend CoroutineScope.() -> T): T
+@Target(AnnotationTarget.FILE)
+internal actual annotation class JvmName(actual val name: String)
 
-public expect suspend fun <T> withTimeoutOrNull(time: Int, block: suspend CoroutineScope.() -> T): T?
+@Target(AnnotationTarget.FILE)
+internal actual annotation class JvmMultifileClass
+
+internal actual annotation class JvmField
+
+internal actual annotation class Volatile
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt
deleted file mode 100644
index 8a36f27..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.Continuation
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn
-import kotlin.coroutines.experimental.suspendCoroutine
-
-// --------------- cancellable continuations ---------------
-
-/**
- * Cancellable continuation. Its job is _completed_ when it is resumed or cancelled.
- * When [cancel] function is explicitly invoked, this continuation immediately resumes with [CancellationException] or
- * with the specified cancel cause.
- *
- * Cancellable continuation has three states (as subset of [Job] states):
- *
- * | **State**                           | [isActive] | [isCompleted] | [isCancelled] |
- * | ----------------------------------- | ---------- | ------------- | ------------- |
- * | _Active_ (initial state)            | `true`     | `false`       | `false`       |
- * | _Resumed_ (final _completed_ state) | `false`    | `true`        | `false`       |
- * | _Canceled_ (final _completed_ state)| `false`    | `true`        | `true`        |
- *
- * Invocation of [cancel] transitions this continuation from _active_ to _cancelled_ state, while
- * invocation of [resume] or [resumeWithException] transitions it from _active_ to _resumed_ state.
- *
- * A [cancelled][isCancelled] continuation implies that it is [completed][isCompleted].
- *
- * Invocation of [resume] or [resumeWithException] in _resumed_ state produces [IllegalStateException]
- * but is ignored in _cancelled_ state.
- *
- * ```
- *    +-----------+   resume    +---------+
- *    |  Active   | ----------> | Resumed |
- *    +-----------+             +---------+
- *          |
- *          | cancel
- *          V
- *    +-----------+
- *    | Cancelled |
- *    +-----------+
- *
- * ```
- */
-public actual interface CancellableContinuation<in T> : Continuation<T> {
-    /**
-     * Returns `true` when this continuation is active -- it has not completed or cancelled yet.
-     */
-    public actual val isActive: Boolean
-
-    /**
-     * Returns `true` when this continuation has completed for any reason. A continuation
-     * that was cancelled is also considered complete.
-     */
-    public actual val isCompleted: Boolean
-
-    /**
-     * Returns `true` if this continuation was [cancelled][cancel].
-     *
-     * It implies that [isActive] is `false` and [isCompleted] is `true`.
-     */
-    public actual val isCancelled: Boolean
-
-    /**
-     * Tries to resume this continuation with a given value and returns non-null object token if it was successful,
-     * or `null` otherwise (it was already resumed or cancelled). When non-null object was returned,
-     * [completeResume] must be invoked with it.
-     *
-     * When [idempotent] is not `null`, this function performs _idempotent_ operation, so that
-     * further invocations with the same non-null reference produce the same result.
-     *
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    public actual fun tryResume(value: T, idempotent: Any? = null): Any?
-
-    /**
-     * Tries to resume this continuation with a given exception and returns non-null object token if it was successful,
-     * or `null` otherwise (it was already resumed or cancelled). When non-null object was returned,
-     * [completeResume] must be invoked with it.
-     *
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    public fun tryResumeWithException(exception: Throwable): Any?
-
-    /**
-     * Completes the execution of [tryResume] or [tryResumeWithException] on its non-null result.
-     *
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    public actual fun completeResume(token: Any)
-
-    /**
-     * Makes this continuation cancellable. Use it with `holdCancellability` optional parameter to
-     * [suspendCancellableCoroutine] function. It throws [IllegalStateException] if invoked more than once.
-     */
-    public actual fun initCancellability()
-
-    /**
-     * Cancels this continuation with an optional cancellation [cause]. The result is `true` if this continuation was
-     * cancelled as a result of this invocation and `false` otherwise.
-     */
-    public actual fun cancel(cause: Throwable? = null): Boolean
-
-    /**
-     * Registers handler that is **synchronously** invoked once on completion of this continuation.
-     * When continuation is already complete, then the handler is immediately invoked
-     * with continuation's exception or `null`. Otherwise, handler will be invoked once when this
-     * continuation is complete.
-     *
-     * The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] the
-     * registration of this handler and release its memory if its invocation is no longer needed.
-     * There is no need to dispose the handler after completion of this continuation. The references to
-     * all the handlers are released when this continuation completes.
-     *
-     * Installed [handler] should not throw any exceptions. If it does, they will get caught,
-     * wrapped into [CompletionHandlerException], and rethrown, potentially causing crash of unrelated code.
-     */
-    public actual fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle
-
-    /**
-     * Resumes this continuation with a given [value] in the invoker thread without going though
-     * [dispatch][CoroutineDispatcher.dispatch] function of the [CoroutineDispatcher] in the [context].
-     * This function is designed to be used only by the [CoroutineDispatcher] implementations themselves.
-     * **It should not be used in general code**.
-     */
-    public actual fun CoroutineDispatcher.resumeUndispatched(value: T)
-
-    /**
-     * Resumes this continuation with a given [exception] in the invoker thread without going though
-     * [dispatch][CoroutineDispatcher.dispatch] function of the [CoroutineDispatcher] in the [context].
-     * This function is designed to be used only by the [CoroutineDispatcher] implementations themselves.
-     * **It should not be used in general code**.
-     */
-    public actual fun CoroutineDispatcher.resumeUndispatchedWithException(exception: Throwable)
-}
-
-/**
- * Suspends coroutine similar to [suspendCoroutine], but provide an implementation of [CancellableContinuation] to
- * the [block]. This function throws [CancellationException] if the coroutine is cancelled or completed while suspended.
- *
- * If [holdCancellability] optional parameter is `true`, then the coroutine is suspended, but it is not
- * cancellable until [CancellableContinuation.initCancellability] is invoked.
- *
- * See [suspendAtomicCancellableCoroutine] for suspending functions that need *atomic cancellation*.
- */
-public actual inline suspend fun <T> suspendCancellableCoroutine(
-    holdCancellability: Boolean = false,
-    crossinline block: (CancellableContinuation<T>) -> Unit
-): T =
-    suspendCoroutineOrReturn { cont ->
-        val cancellable = CancellableContinuationImpl(cont, resumeMode = MODE_CANCELLABLE)
-        if (!holdCancellability) cancellable.initCancellability()
-        block(cancellable)
-        cancellable.getResult()
-}
-
-/**
- * Suspends coroutine similar to [suspendCancellableCoroutine], but with *atomic cancellation*.
- *
- * When suspended function throws [CancellationException] it means that the continuation was not resumed.
- * As a side-effect of atomic cancellation, a thread-bound coroutine (to some UI thread, for example) may
- * continue to execute even after it was cancelled from the same thread in the case when the continuation
- * was already resumed and was posted for execution to the thread's queue.
- */
-public actual inline suspend fun <T> suspendAtomicCancellableCoroutine(
-    holdCancellability: Boolean = false,
-    crossinline block: (CancellableContinuation<T>) -> Unit
-): T =
-    suspendCoroutineOrReturn { cont ->
-        val cancellable = CancellableContinuationImpl(cont, resumeMode = MODE_ATOMIC_DEFAULT)
-        if (!holdCancellability) cancellable.initCancellability()
-        block(cancellable)
-        cancellable.getResult()
-    }
-
-// --------------- implementation details ---------------
-
-@PublishedApi
-internal class CancellableContinuationImpl<in T>(
-    delegate: Continuation<T>,
-    resumeMode: Int
-) : AbstractContinuation<T>(delegate, resumeMode), CancellableContinuation<T> {
-    @Volatile // just in case -- we don't want an extra data race, even benign one
-    private var _context: CoroutineContext? = null // created on first need
-
-    public override val context: CoroutineContext
-        get() = _context ?: (delegate.context + this).also { _context = it }
-
-    override fun initCancellability() {
-        initParentJobInternal(delegate.context[Job])
-    }
-
-    override val onCancelMode: Int get() = ON_CANCEL_MAKE_CANCELLED
-    
-    override fun tryResume(value: T, idempotent: Any?): Any? {
-        val state = this.state
-        return when (state) {
-            is Incomplete -> {
-                val update: Any? = if (idempotent == null) value else
-                    CompletedIdempotentResult(idempotent, value, state)
-                tryUpdateState(update)
-                state
-            }
-            is CompletedIdempotentResult -> {
-                if (state.idempotentResume === idempotent) {
-                    check(state.result === value) { "Non-idempotent resume" }
-                    state.token
-                } else
-                    null
-            }
-            else -> null // cannot resume -- not active anymore
-        }
-    }
-
-    override fun tryResumeWithException(exception: Throwable): Any? {
-        val state = this.state
-        return when (state) {
-            is Incomplete -> {
-                tryUpdateState(CompletedExceptionally(exception))
-                state
-            }
-            else -> null // cannot resume -- not active anymore
-        }
-    }
-
-    override fun completeResume(token: Any) {
-        completeUpdateState(token as Incomplete, state, resumeMode)
-    }
-
-    override fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle =
-        invokeOnCompletion(onCancelling = false, invokeImmediately = true, handler = handler)
-
-    override fun CoroutineDispatcher.resumeUndispatched(value: T) {
-        val dc = delegate as? DispatchedContinuation
-        resumeImpl(value, if (dc?.dispatcher === this) MODE_UNDISPATCHED else resumeMode)
-    }
-
-    override fun CoroutineDispatcher.resumeUndispatchedWithException(exception: Throwable) {
-        val dc = delegate as? DispatchedContinuation
-        resumeImpl(CompletedExceptionally(exception), if (dc?.dispatcher === this) MODE_UNDISPATCHED else resumeMode)
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    override fun <T> getSuccessfulResult(state: Any?): T =
-        if (state is CompletedIdempotentResult) state.result as T else state as T
-
-    override fun nameString(): String =
-        "CancellableContinuation(${delegate.toDebugString()})"
-
-    // todo: This workaround for KT-21968, should be removed in the future
-    public override fun cancel(cause: Throwable?): Boolean =
-        super.cancel(cause)
-}
-
-private class CompletedIdempotentResult(
-    val idempotentResume: Any?,
-    val result: Any?,
-    val token: JobSupport.Incomplete
-) {
-    override fun toString(): String = "CompletedIdempotentResult[$result]"
-}
-
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CompletableDeferred.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CompletableDeferred.kt
deleted file mode 100644
index dca6ee9..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CompletableDeferred.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
-
-package kotlinx.coroutines.experimental
-
-/**
- * A [Deferred] that can be completed via public functions
- * [complete], [completeExceptionally], and [cancel].
- *
- * Completion functions return `false` when this deferred value is already complete or completing.
- *
- * An instance of completable deferred can be created by `CompletableDeferred()` function in _active_ state.
- *
- * All functions on this interface and on all interfaces derived from it are **thread-safe** and can
- * be safely invoked from concurrent coroutines without external synchronization.
- */
-public actual interface CompletableDeferred<T> : Deferred<T> {
-    /**
-     * Completes this deferred value with a given [value]. The result is `true` if this deferred was
-     * completed as a result of this invocation and `false` otherwise (if it was already completed).
-     *
-     * Repeated invocations of this function have no effect and always produce `false`.
-     */
-    public actual fun complete(value: T): Boolean
-
-    /**
-     * Completes this deferred value exceptionally with a given [exception]. The result is `true` if this deferred was
-     * completed as a result of this invocation and `false` otherwise (if it was already completed).
-     *
-     * Repeated invocations of this function have no effect and always produce `false`.
-     */
-    public actual fun completeExceptionally(exception: Throwable): Boolean
-}
-
-/**
- * Creates a [CompletableDeferred] in an _active_ state.
- * It is optionally a child of a [parent] job.
- */
-@Suppress("FunctionName")
-public actual fun <T> CompletableDeferred(parent: Job? = null): CompletableDeferred<T> = CompletableDeferredImpl(parent)
-
-/**
- * Creates an already _completed_ [CompletableDeferred] with a given [value].
- */
-@Suppress("FunctionName")
-public actual fun <T> CompletableDeferred(value: T): CompletableDeferred<T> = CompletableDeferredImpl<T>(null).apply { complete(value) }
-
-/**
- * Concrete implementation of [CompletableDeferred].
- */
-@Suppress("UNCHECKED_CAST")
-private class CompletableDeferredImpl<T>(
-    parent: Job?
-) : JobSupport(true), CompletableDeferred<T> {
-    init { initParentJobInternal(parent) }
-    override val onCancelMode: Int get() = ON_CANCEL_MAKE_COMPLETING
-
-    override fun getCompleted(): T = getCompletedInternal() as T
-    override suspend fun await(): T = awaitInternal() as T
-
-    override fun complete(value: T): Boolean =
-        makeCompleting(value)
-
-    override fun completeExceptionally(exception: Throwable): Boolean =
-        makeCompleting(CompletedExceptionally(exception))
-}
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CompletionHandler.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CompletionHandler.kt
new file mode 100644
index 0000000..82db551
--- /dev/null
+++ b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CompletionHandler.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package kotlinx.coroutines.experimental
+
+import kotlinx.coroutines.experimental.internal.*
+
+internal actual abstract class CompletionHandlerNode : LinkedListNode() {
+    @Suppress("UnsafeCastFromDynamic")
+    actual inline val asHandler: CompletionHandler get() = asDynamic()
+    actual abstract fun invoke(cause: Throwable?)
+}
+
+internal actual fun CompletionHandler.invokeIt(cause: Throwable?) {
+    when(jsTypeOf(this)) {
+        "function" -> invoke(cause)
+        else -> (this as CompletionHandlerNode).invoke(cause)
+    }
+}
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.kt
index 73358a9..6d1cbd8 100644
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.kt
+++ b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.kt
@@ -19,23 +19,6 @@
 import kotlin.browser.*
 import kotlin.coroutines.experimental.*
 
-/**
- * A coroutine dispatcher that is not confined to any specific thread.
- * It executes initial continuation of the coroutine _right here_ in the current call-frame
- * and let the coroutine resume in whatever thread that is used by the corresponding suspending function, without
- * mandating any specific threading policy.
- *
- * Note, that if you need your coroutine to be confined to a particular thread or a thread-pool after resumption,
- * but still want to execute it in the current call-frame until its first suspension, then you can use
- * an optional [CoroutineStart] parameter in coroutine builders like [launch] and [async] setting it to the
- * the value of [CoroutineStart.UNDISPATCHED].
- */
-public actual object Unconfined : CoroutineDispatcher() {
-    actual override fun isDispatchNeeded(context: CoroutineContext): Boolean = false
-    actual override fun dispatch(context: CoroutineContext, block: Runnable) { throw UnsupportedOperationException() }
-    override fun toString(): String = "Unconfined"
-}
-
 private external val navigator: dynamic
 private const val UNDEFINED = "undefined"
 
@@ -58,11 +41,13 @@
     else -> NodeDispatcher()
 }
 
+internal actual val DefaultDelay: Delay = DefaultDispatcher as Delay
+
 /**
  * Creates context for the new coroutine. It installs [DefaultDispatcher] when no other dispatcher nor
  * [ContinuationInterceptor] is specified, and adds optional support for debugging facilities (when turned on).
  */
-public fun newCoroutineContext(context: CoroutineContext, parent: Job? = null): CoroutineContext {
+public actual fun newCoroutineContext(context: CoroutineContext, parent: Job? = null): CoroutineContext {
     val wp = if (parent == null) context else context + parent
     return if (context !== DefaultDispatcher && context[ContinuationInterceptor] == null)
         wp + DefaultDispatcher else wp
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineDispatcher.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineDispatcher.kt
deleted file mode 100644
index b6e659e..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineDispatcher.kt
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.AbstractCoroutineContextElement
-import kotlin.coroutines.experimental.Continuation
-import kotlin.coroutines.experimental.ContinuationInterceptor
-import kotlin.coroutines.experimental.CoroutineContext
-
-/**
- * Base class that shall be extended by all coroutine dispatcher implementations.
- *
- * The following standard implementations are provided by `kotlinx.coroutines`:
- * * [Unconfined] -- starts coroutine execution in the current call-frame until the first suspension.
- *   On first  suspension the coroutine builder function returns.
- *   The coroutine will resume in whatever thread that is used by the
- *   corresponding suspending function, without confining it to any specific thread or pool.
- *   This in an appropriate choice for IO-intensive coroutines that do not consume CPU resources.
- * * [DefaultDispatcher] -- is used by all standard builder if no dispatcher nor any other [ContinuationInterceptor]
- *   is specified in their context.
- */
-public actual abstract class CoroutineDispatcher actual constructor() :
-    AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
-    /**
-     * Returns `true` if execution shall be dispatched onto another thread.
-     * The default behaviour for most dispatchers is to return `true`.
-     *
-     * UI dispatchers _should not_ override `isDispatchNeeded`, but leave a default implementation that
-     * returns `true`. To understand the rationale beyond this recommendation, consider the following code:
-     *
-     * ```kotlin
-     * fun asyncUpdateUI() = async(MainThread) {
-     *     // do something here that updates something in UI
-     * }
-     * ```
-     *
-     * When you invoke `asyncUpdateUI` in some background thread, it immediately continues to the next
-     * line, while UI update happens asynchronously in the UI thread. However, if you invoke
-     * it in the UI thread itself, it updates UI _synchronously_ if your `isDispatchNeeded` is
-     * overridden with a thread check. Checking if we are already in the UI thread seems more
-     * efficient (and it might indeed save a few CPU cycles), but this subtle and context-sensitive
-     * difference in behavior makes the resulting async code harder to debug.
-     *
-     * Basically, the choice here is between "JS-style" asynchronous approach (async actions
-     * are always postponed to be executed later in the even dispatch thread) and "C#-style" approach
-     * (async actions are executed in the invoker thread until the first suspension point).
-     * While, C# approach seems to be more efficient, it ends up with recommendations like
-     * "use `yield` if you need to ....". This is error-prone. JS-style approach is more consistent
-     * and does not require programmers to think about whether they need to yield or not.
-     *
-     * However, coroutine builders like [launch] and [async] accept an optional [CoroutineStart]
-     * parameter that allows one to optionally choose C#-style [CoroutineStart.UNDISPATCHED] behaviour
-     * whenever it is needed for efficiency.
-     */
-    public actual open fun isDispatchNeeded(context: CoroutineContext): Boolean = true
-
-    /**
-     * Dispatches execution of a runnable [block] onto another thread in the given [context].
-     */
-    public actual abstract fun dispatch(context: CoroutineContext, block: Runnable)
-
-    /**
-     * Returns continuation that wraps the original [continuation], thus intercepting all resumptions.
-     */
-    public actual override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
-        DispatchedContinuation(this, continuation)
-}
-
-/**
- * A runnable task for [CoroutineDispatcher.dispatch].
- */
-public actual interface Runnable {
-    public actual fun run()
-}
-
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandler.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandler.kt
deleted file mode 100644
index 61743d0..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandler.kt
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.AbstractCoroutineContextElement
-import kotlin.coroutines.experimental.CoroutineContext
-
-/**
- * Helper function for coroutine builder implementations to handle uncaught exception in coroutines.
- *
- * It tries to handle uncaught exception in the following way:
- * * If there is [CoroutineExceptionHandler] in the context, then it is used.
- * * Otherwise, if exception is [CancellationException] then it is ignored
- *   (because that is the supposed mechanism to cancel the running coroutine)
- * * Otherwise:
- *     * if there is a [Job] in the context, then [Job.cancel] is invoked;
- *     * exception is logged to console.
- */
-public actual fun handleCoroutineException(context: CoroutineContext, exception: Throwable) {
-    context[CoroutineExceptionHandler]?.let {
-        it.handleException(context, exception)
-        return
-    }
-    // ignore CancellationException (they are normal means to terminate a coroutine)
-    if (exception is CancellationException) return
-    // try cancel job in the context
-    context[Job]?.cancel(exception)
-    // log exception
-    console.error(exception)
-}
-
-/**
- * An optional element on the coroutine context to handle uncaught exceptions.
- *
- * By default, when no handler is installed, uncaught exception are handled in the following way:
- * * If exception is [CancellationException] then it is ignored
- *   (because that is the supposed mechanism to cancel the running coroutine)
- * * Otherwise:
- *     * if there is a [Job] in the context, then [Job.cancel] is invoked;
- *     * exception is logged to console.
- *
- * See [handleCoroutineException].
- */
-public actual interface CoroutineExceptionHandler : CoroutineContext.Element {
-    /**
-     * Key for [CoroutineExceptionHandler] instance in the coroutine context.
-     */
-    public actual companion object Key : CoroutineContext.Key<CoroutineExceptionHandler>
-    
-    /**
-     * Handles uncaught [exception] in the given [context]. It is invoked
-     * if coroutine has an uncaught exception. See [handleCoroutineException].
-     */
-    public actual fun handleException(context: CoroutineContext, exception: Throwable)
-}
-
-/**
- * Creates new [CoroutineExceptionHandler] instance.
- * @param handler a function which handles exception thrown by a coroutine
- */
-@Suppress("FunctionName")
-public actual inline fun CoroutineExceptionHandler(crossinline handler: (CoroutineContext, Throwable) -> Unit): CoroutineExceptionHandler =
-    object: AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler {
-        override fun handleException(context: CoroutineContext, exception: Throwable) =
-            handler.invoke(context, exception)
-    }
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonYield.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandlerImpl.kt
similarity index 76%
copy from common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonYield.kt
copy to js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandlerImpl.kt
index e461c47..d9ade66 100644
--- a/common/kotlinx-coroutines-core-common/src/main/kotlin/kotlinx/coroutines/experimental/CommonYield.kt
+++ b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineExceptionHandlerImpl.kt
@@ -16,4 +16,9 @@
 
 package kotlinx.coroutines.experimental
 
-public expect suspend fun yield()
\ No newline at end of file
+import kotlin.coroutines.experimental.*
+
+internal actual fun handleCoroutineExceptionImpl(context: CoroutineContext, exception: Throwable) {
+    // log exception
+    console.error(exception)
+}
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineScope.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineScope.kt
deleted file mode 100644
index 784e36d..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineScope.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.CoroutineContext
-
-/**
- * Receiver interface for generic coroutine builders, so that the code inside coroutine has a convenient access
- * to its [coroutineContext] and its cancellation status via [isActive].
- */
-public actual interface CoroutineScope {
-    /**
-     * Returns `true` when this coroutine is still active (has not completed and was not cancelled yet).
-     *
-     * Check this property in long-running computation loops to support cancellation:
-     * ```
-     * while (isActive) {
-     *     // do some computation
-     * }
-     * ```
-     *
-     * This property is a shortcut for `coroutineContext[Job]!!.isActive`. See [coroutineContext] and [Job].
-     */
-    public actual val isActive: Boolean
-
-    /**
-     * Returns the context of this coroutine.
-     */
-    public actual val coroutineContext: CoroutineContext
-}
\ No newline at end of file
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Debug.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Debug.kt
index e2e8908..546864c 100644
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Debug.kt
+++ b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Debug.kt
@@ -16,4 +16,17 @@
 
 package kotlinx.coroutines.experimental
 
+private var counter = 0
+
+internal actual val Any.hexAddress: String
+    get() {
+        var result = this.asDynamic().__debug_counter
+        if (jsTypeOf(result) !== "number") {
+            result = ++counter
+            this.asDynamic().__debug_counter = result
+
+        }
+        return (result as Int).toString()
+    }
+
 internal actual val Any.classSimpleName: String get() = this::class.simpleName ?: "Unknown"
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt
deleted file mode 100644
index 7625a74..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
-
-package kotlinx.coroutines.experimental
-
-import kotlinx.coroutines.experimental.intrinsics.*
-import kotlin.coroutines.experimental.*
-
-/**
- * Deferred value is a non-blocking cancellable future.
- *
- * It is created with [async] coroutine builder or via constructor of [CompletableDeferred] class.
- * It is in [active][isActive] state while the value is being computed.
- *
- * Deferred value has the following states:
- *
- * | **State**                               | [isActive] | [isCompleted] | [isCompletedExceptionally] | [isCancelled] |
- * | --------------------------------------- | ---------- | ------------- | -------------------------- | ------------- |
- * | _New_ (optional initial state)          | `false`    | `false`       | `false`                    | `false`       |
- * | _Active_ (default initial state)        | `true`     | `false`       | `false`                    | `false`       |
- * | _Completing_ (optional transient state) | `true`     | `false`       | `false`                    | `false`       |
- * | _Cancelling_ (optional transient state) | `false`    | `false`       | `false`                    | `true`        |
- * | _Cancelled_ (final state)               | `false`    | `true`        | `true`                     | `true`        |
- * | _Resolved_  (final state)               | `false`    | `true`        | `false`                    | `false`       |
- * | _Failed_    (final state)               | `false`    | `true`        | `true`                     | `false`       |
- *
- * Usually, a deferred value is created in _active_ state (it is created and started).
- * However, [async] coroutine builder has an optional `start` parameter that creates a deferred value in _new_ state
- * when this parameter is set to [CoroutineStart.LAZY].
- * Such a deferred can be be made _active_ by invoking [start], [join], or [await].
- *
- * A deferred can be _cancelled_ at any time with [cancel] function that forces it to transition to
- * _cancelling_ state immediately. Deferred that is not backed by a coroutine (see [CompletableDeferred]) and does not have
- * [children] becomes _cancelled_ on [cancel] immediately.
- * Otherwise, deferred becomes _cancelled_  when it finishes executing its code and
- * when all its children [complete][isCompleted].
- *
- * ```
- *                                                     wait children
- *    +-----+       start      +--------+   complete  +-------------+ finish +-----------+
- *    | New | ---------------> | Active | ----------> | Completing  | ---+-> | Resolved  |
- *    +-----+                  +--------+             +-------------+    |   |(completed)|
- *       |                         |                        |            |   +-----------+
- *       | cancel                  | cancel                 | cancel     |
- *       V                         V                        |            |   +-----------+
- *  +-----------+   finish   +------------+                 |            +-> |  Failed   |
- *  | Cancelled | <--------- | Cancelling | <---------------+                |(completed)|
- *  |(completed)|            +------------+                                  +-----------+
- *  +-----------+
- * ```
- *
- * A deferred value is a [Job]. A job in the coroutine [context][CoroutineScope.coroutineContext] of [async] builder
- * represents the coroutine itself.
- * A deferred value is active while the coroutine is working and cancellation aborts the coroutine when
- * the coroutine is suspended on a _cancellable_ suspension point by throwing [CancellationException]
- * or the cancellation cause inside the coroutine.
- *
- * A deferred value can have a _parent_ job. A deferred value with a parent is cancelled when its parent is
- * cancelled or completes. Parent waits for all its [children] to complete in _completing_ or
- * _cancelling_ state. _Completing_ state is purely internal. For an outside observer a _completing_
- * deferred is still active, while internally it is waiting for its children.
- *
- * All functions on this interface and on all interfaces derived from it are **thread-safe** and can
- * be safely invoked from concurrent coroutines without external synchronization.
- */
-public actual interface Deferred<out T> : Job {
-    /**
-     * Returns `true` if computation of this deferred value has _completed exceptionally_ -- it had
-     * either _failed_ with exception during computation or was [cancelled][cancel].
-     *
-     * It implies that [isActive] is `false` and [isCompleted] is `true`.
-     */
-    public actual val isCompletedExceptionally: Boolean
-
-    /**
-     * Awaits for completion of this value without blocking a thread and resumes when deferred computation is complete,
-     * returning the resulting value or throwing the corresponding exception if the deferred had completed exceptionally.
-     *
-     * This suspending function is cancellable.
-     * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
-     * immediately resumes with [CancellationException].
-     */
-    public actual suspend fun await(): T
-
-    /**
-     * Returns *completed* result or throws [IllegalStateException] if this deferred value has not
-     * [completed][isCompleted] yet. It throws the corresponding exception if this deferred has
-     * [completed exceptionally][isCompletedExceptionally].
-     *
-     * This function is designed to be used from [invokeOnCompletion] handlers, when there is an absolute certainty that
-     * the value is already complete. See also [getCompletionExceptionOrNull].
-     */
-    public actual fun getCompleted(): T
-
-    /**
-     * Returns *completion exception* result if this deferred [completed exceptionally][isCompletedExceptionally],
-     * `null` if it is completed normally, or throws [IllegalStateException] if this deferred value has not
-     * [completed][isCompleted] yet.
-     *
-     * This function is designed to be used from [invokeOnCompletion] handlers, when there is an absolute certainty that
-     * the value is already complete. See also [getCompleted].
-     */
-    public actual fun getCompletionExceptionOrNull(): Throwable?
-}
-
-/**
- * Creates new coroutine and returns its future result as an implementation of [Deferred].
- *
- * The running coroutine is cancelled when the resulting object is [cancelled][Job.cancel].
- *
- * The [context] for the new coroutine can be explicitly specified.
- * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.coroutineContext] of the parent coroutine from its [scope][CoroutineScope] may be used,
- * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
- * The parent job may be also explicitly specified using [parent] parameter.
- *
- * If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [DefaultDispatcher] is used.
- *
- * By default, the coroutine is immediately scheduled for execution.
- * Other options can be specified via `start` parameter. See [CoroutineStart] for details.
- * An optional [start] parameter can be set to [CoroutineStart.LAZY] to start coroutine _lazily_. In this case,,
- * the resulting [Deferred] is created in _new_ state. It can be explicitly started with [start][Job.start]
- * function and will be started implicitly on the first invocation of [join][Job.join] or [await][Deferred.await].
- *
- * @param context context of the coroutine. The default value is [DefaultDispatcher].
- * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
- * @param parent explicitly specifies the parent job, overrides job from the [context] (if any).*
- * @param block the coroutine code.
- */
-public actual fun <T> async(
-    context: CoroutineContext = DefaultDispatcher,
-    start: CoroutineStart = CoroutineStart.DEFAULT,
-    parent: Job? = null,
-    block: suspend CoroutineScope.() -> T
-): Deferred<T> {
-    val newContext = newCoroutineContext(context, parent)
-    val coroutine = if (start.isLazy)
-        LazyDeferredCoroutine(newContext, block) else
-        DeferredCoroutine<T>(newContext, active = true)
-    coroutine.start(start, coroutine, block)
-    return coroutine
-}
-
-@Suppress("UNCHECKED_CAST")
-private open class DeferredCoroutine<T>(
-    parentContext: CoroutineContext,
-    active: Boolean
-) : AbstractCoroutine<T>(parentContext, active), Deferred<T> {
-    override fun getCompleted(): T = getCompletedInternal() as T
-    override suspend fun await(): T = awaitInternal() as T
-}
-
-private class LazyDeferredCoroutine<T>(
-    parentContext: CoroutineContext,
-    private val block: suspend CoroutineScope.() -> T
-) : DeferredCoroutine<T>(parentContext, active = false) {
-    override fun onStart() {
-        block.startCoroutineCancellable(this, this)
-    }
-}
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Delay.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Delay.kt
deleted file mode 100644
index 10b7c18..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Delay.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.ContinuationInterceptor
-import kotlin.coroutines.experimental.CoroutineContext
-
-/**
- * This dispatcher _feature_ is implemented by [CoroutineDispatcher] implementations that natively support
- * scheduled execution of tasks.
- *
- * Implementation of this interface affects operation of
- * [delay][kotlinx.coroutines.experimental.delay] and [withTimeout] functions.
- */
-public actual interface Delay {
-    /**
-     * Schedules resume of a specified [continuation] after a specified delay [time].
-     *
-     * Continuation **must be scheduled** to resume even if it is already cancelled, because a cancellation is just
-     * an exception that the coroutine that used `delay` might wanted to catch and process. It might
-     * need to close some resources in its `finally` blocks, for example.
-     *
-     * This implementation is supposed to use dispatcher's native ability for scheduled execution in its thread(s).
-     * In order to avoid an extra delay of execution, the following code shall be used to resume this
-     * [continuation] when the code is already executing in the appropriate dispatcher:
-     *
-     * ```kotlin
-     * with(continuation) { resumeUndispatched(Unit) }
-     * ```
-     */
-    fun scheduleResumeAfterDelay(time: Int, continuation: CancellableContinuation<Unit>)
-
-    /**
-     * Schedules invocation of a specified [block] after a specified delay [time].
-     * The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] of this invocation
-     * request if it is not needed anymore.
-     */
-    fun invokeOnTimeout(time: Int, block: Runnable): DisposableHandle
-}
-
-/**
- * Delays coroutine for a given time without blocking and resumes it after a specified time.
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * immediately resumes with [CancellationException].
- *
- * This function delegates to [Delay.scheduleResumeAfterDelay] if the context [CoroutineDispatcher]
- * implements [Delay] interface, otherwise it resumes using a built-in scheduler.
- *
- * @param time time in milliseconds.
- */
-public actual suspend fun delay(time: Int) {
-    kotlin.require(time >= 0) { "Delay time $time cannot be negative" }
-    if (time <= 0) return // don't delay
-    return suspendCancellableCoroutine sc@ { cont: CancellableContinuation<Unit> ->
-        cont.context.delay.scheduleResumeAfterDelay(time, cont)
-    }
-}
-
-/** Returns [Delay] implementation of the given context */
-internal val CoroutineContext.delay: Delay get() =
-    get(ContinuationInterceptor) as? Delay ?: (DefaultDispatcher as Delay)
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Exceptions.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Exceptions.kt
index 0d95eba..37a0437 100644
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Exceptions.kt
+++ b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Exceptions.kt
@@ -24,6 +24,12 @@
     public override val cause: Throwable
 ) : RuntimeException(message.withCause(cause))
 
+/**
+ * Thrown by cancellable suspending functions if the [Job] of the coroutine is cancelled while it is suspending.
+ * It indicates _normal_ cancellation of a coroutine.
+ * **It is not printed to console/log by default uncaught exception handler**.
+ * (see [handleCoroutineException]).
+ */
 public actual open class CancellationException actual constructor(message: String) : IllegalStateException(message)
 
 /**
@@ -47,26 +53,6 @@
         (message!!.hashCode() * 31 + job.hashCode()) * 31 + (cause?.hashCode() ?: 0)
 }
 
-/**
- * This exception is thrown by [withTimeout] to indicate timeout.
- */
-@Suppress("DEPRECATION")
-public actual class TimeoutCancellationException internal constructor(
-    message: String,
-    internal val coroutine: Job?
-) : CancellationException(message) {
-    /**
-     * Creates timeout exception with a given message.
-     */
-    public actual constructor(message: String) : this(message, null)
-}
-
-@Suppress("FunctionName")
-internal fun TimeoutCancellationException(
-    time: Int,
-    coroutine: Job
-) : TimeoutCancellationException = TimeoutCancellationException("Timed out waiting for $time", coroutine)
-
 internal actual class DispatchException actual constructor(message: String, cause: Throwable) : RuntimeException(message.withCause(cause))
 
 @Suppress("FunctionName")
@@ -75,3 +61,6 @@
 
 private fun String.withCause(cause: Throwable?) =
     if (cause == null) this else "$this; caused by $cause"
+
+@Suppress("NOTHING_TO_INLINE")
+internal actual inline fun Throwable.addSuppressedThrowable(other: Throwable) { /* empty */ }
\ No newline at end of file
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/JSDispatcher.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/JSDispatcher.kt
index 53cadc1..10e072f 100644
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/JSDispatcher.kt
+++ b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/JSDispatcher.kt
@@ -16,6 +16,7 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlinx.coroutines.experimental.timeunit.TimeUnit
 import kotlin.coroutines.experimental.*
 import org.w3c.dom.*
 
@@ -24,12 +25,12 @@
         setTimeout({ block.run() }, 0)
     }
 
-    override fun scheduleResumeAfterDelay(time: Int, continuation: CancellableContinuation<Unit>) {
-        setTimeout({ with(continuation) { resumeUndispatched(Unit) } }, time.coerceAtLeast(0))
+    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
+        setTimeout({ with(continuation) { resumeUndispatched(Unit) } }, time.toIntMillis(unit))
     }
 
-    override fun invokeOnTimeout(time: Int, block: Runnable): DisposableHandle {
-        val handle = setTimeout({ block.run() }, time.coerceAtLeast(0))
+    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle {
+        val handle = setTimeout({ block.run() }, time.toIntMillis(unit))
         return object : DisposableHandle {
             override fun dispose() {
                 clearTimeout(handle)
@@ -60,12 +61,12 @@
         queue.enqueue(block)
     }
 
-    override fun scheduleResumeAfterDelay(time: Int, continuation: CancellableContinuation<Unit>) {
-        window.setTimeout({ with(continuation) { resumeUndispatched(Unit) } }, time.coerceAtLeast(0))
+    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
+        window.setTimeout({ with(continuation) { resumeUndispatched(Unit) } }, time.toIntMillis(unit))
     }
 
-    override fun invokeOnTimeout(time: Int, block: Runnable): DisposableHandle {
-        val handle = window.setTimeout({ block.run() }, time.coerceAtLeast(0))
+    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle {
+        val handle = window.setTimeout({ block.run() }, time.toIntMillis(unit))
         return object : DisposableHandle {
             override fun dispose() {
                 window.clearTimeout(handle)
@@ -106,6 +107,9 @@
     }
 }
 
+private fun Long.toIntMillis(unit: TimeUnit): Int =
+    unit.toMillis(this).coerceIn(0L, Int.MAX_VALUE.toLong()).toInt()
+
 internal open class Queue<T : Any> {
     private var queue = arrayOfNulls<Any?>(8)
     private var head = 0
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt
deleted file mode 100644
index c83e708..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt
+++ /dev/null
@@ -1,1092 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
-
-package kotlinx.coroutines.experimental
-
-import kotlinx.coroutines.experimental.internal.LinkedListHead
-import kotlinx.coroutines.experimental.internal.LinkedListNode
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.coroutines.experimental.buildSequence
-import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn
-
-/**
- * A background job. Conceptually, a job is a cancellable thing with a simple life-cycle that
- * culminates in its completion. Jobs can be arranged into parent-child hierarchies where cancellation
- * or completion of parent immediately cancels all its [children].
- *
- * The most basic instances of [Job] are created with [launch] coroutine builder or with a
- * `Job()` factory function.  Other coroutine builders and primitives like
- * [Deferred] also implement [Job] interface.
- *
- * A job has the following states:
- *
- * | **State**                               | [isActive] | [isCompleted] | [isCancelled] |
- * | --------------------------------------- | ---------- | ------------- | ------------- |
- * | _New_ (optional initial state)          | `false`    | `false`       | `false`       |
- * | _Active_ (default initial state)        | `true`     | `false`       | `false`       |
- * | _Completing_ (optional transient state) | `true`     | `false`       | `false`       |
- * | _Cancelling_ (optional transient state) | `false`    | `false`       | `true`        |
- * | _Cancelled_ (final state)               | `false`    | `true`        | `true`        |
- * | _Completed_ (final state)               | `false`    | `true`        | `false`       |
- *
- * Usually, a job is created in _active_ state (it is created and started). However, coroutine builders
- * that provide an optional `start` parameter create a coroutine in _new_ state when this parameter is set to
- * [CoroutineStart.LAZY]. Such a job can be made _active_ by invoking [start] or [join].
- *
- * A job can be _cancelled_ at any time with [cancel] function that forces it to transition to
- * _cancelling_ state immediately. Job that is not backed by a coroutine (see `Job()` function) and does not have
- * [children] becomes _cancelled_ on [cancel] immediately.
- * Otherwise, job becomes _cancelled_  when it finishes executing its code and
- * when all its children [complete][isCompleted].
- *
- * ```
- *                                                      wait children
- *    +-----+       start      +--------+   complete   +-------------+  finish  +-----------+
- *    | New | ---------------> | Active | -----------> | Completing  | -------> | Completed |
- *    +-----+                  +--------+              +-------------+          +-----------+
- *       |                         |                         |
- *       | cancel                  | cancel                  | cancel
- *       V                         V                         |
- *  +-----------+   finish   +------------+                  |
- *  | Cancelled | <--------- | Cancelling | <----------------+
- *  |(completed)|            +------------+
- *  +-----------+
- * ```
- *
- * A job in the [coroutineContext][CoroutineScope.coroutineContext] represents the coroutine itself.
- * A job is active while the coroutine is working and job's cancellation aborts the coroutine when
- * the coroutine is suspended on a _cancellable_ suspension point by throwing [CancellationException].
- *
- * A job can have a _parent_ job. A job with a parent is cancelled when its parent is cancelled or completes exceptionally.
- * Parent job waits for all its children to complete in _completing_ or _cancelling_ state.
- * _Completing_ state is purely internal to the job. For an outside observer a _completing_ job is still active,
- * while internally it is waiting for its children.
- *
- * All functions on this interface and on all interfaces derived from it are **thread-safe** and can
- * be safely invoked from concurrent coroutines without external synchronization.
- */
-public actual interface Job : CoroutineContext.Element {
-
-    // ------------ state query ------------
-
-    /**
-     * Returns `true` when this job is active -- it was already started and has not completed or cancelled yet.
-     * The job that is waiting for its [children] to complete is still considered to be active if it
-     * was not cancelled.
-     */
-    public actual val isActive: Boolean
-
-    /**
-     * Returns `true` when this job has completed for any reason. A job that was cancelled and has
-     * finished its execution is also considered complete. Job becomes complete only after
-     * all its [children] complete.
-     */
-    public actual val isCompleted: Boolean
-
-    /**
-     * Returns `true` if this job was [cancelled][cancel]. In the general case, it does not imply that the
-     * job has already [completed][isCompleted] (it may still be cancelling whatever it was doing).
-     */
-    public actual val isCancelled: Boolean
-
-    /**
-     * Returns [CancellationException] that signals the completion of this job. This function is
-     * used by [cancellable][suspendCancellableCoroutine] suspending functions. They throw exception
-     * returned by this function when they suspend in the context of this job and this job becomes _complete_.
-     *
-     * This function returns the original [cancel] cause of this job if that `cause` was an instance of
-     * [CancellationException]. Otherwise (if this job was cancelled with a cause of a different type, or
-     * was cancelled without a cause, or had completed normally), an instance of [JobCancellationException] is
-     * returned. The [JobCancellationException.cause] of the resulting [JobCancellationException] references
-     * the original cancellation cause that was passed to [cancel] function.
-     *
-     * This function throws [IllegalStateException] when invoked on a job that has not
-     * [completed][isCompleted] nor [cancelled][isCancelled] yet.
-     */
-    public actual fun getCancellationException(): CancellationException
-
-    // ------------ state update ------------
-
-    /**
-     * Starts coroutine related to this job (if any) if it was not started yet.
-     * The result `true` if this invocation actually started coroutine or `false`
-     * if it was already started or completed.
-     */
-    public actual fun start(): Boolean
-
-    /**
-     * Cancels this job with an optional cancellation [cause]. The result is `true` if this job was
-     * cancelled as a result of this invocation and `false` otherwise
-     * (if it was already _completed_ or if it is [NonCancellable]).
-     * Repeated invocations of this function have no effect and always produce `false`.
-     *
-     * When cancellation has a clear reason in the code, an instance of [CancellationException] should be created
-     * at the corresponding original cancellation site and passed into this method to aid in debugging by providing
-     * both the context of cancellation and text description of the reason.
-     */
-    public actual fun cancel(cause: Throwable? = null): Boolean
-
-    // ------------ parent-child ------------
-
-    /**
-     * Returns a sequence of this job's children.
-     *
-     * A job becomes a child of this job when it is constructed with this job in its
-     * [CoroutineContext] or using an explicit `parent` parameter.
-     *
-     * A parent-child relation has the following effect:
-     *
-     * * Cancellation of parent with [cancel] or its exceptional completion (failure)
-     *   immediately cancels all its children.
-     * * Parent cannot complete until all its children are complete. Parent waits for all its children to
-     *   complete in _completing_ or _cancelling_ state.
-     * * Uncaught exception in a child, by default, cancels parent. In particular, this applies to
-     *   children created with [launch] coroutine builder. Note, that [async] and other future-like
-     *   coroutine builders do not have uncaught exceptions by definition, since all their exceptions are
-     *   caught and are encapsulated in their result.
-     */
-    public actual val children: Sequence<Job>
-
-    /**
-     * Attaches child job so that this job becomes its parent and
-     * returns a handle that should be used to detach it.
-     *
-     * A parent-child relation has the following effect:
-     * * Cancellation of parent with [cancel] or its exceptional completion (failure)
-     *   immediately cancels all its children.
-     * * Parent cannot complete until all its children are complete. Parent waits for all its children to
-     *   complete in _completing_ or _cancelling_ state.
-     *
-     * **A child must store the resulting [DisposableHandle] and [dispose][DisposableHandle.dispose] the attachment
-     * to its parent on its own completion.**
-     *
-     * Coroutine builders and job factory functions that accept `parent` [CoroutineContext] parameter
-     * lookup a [Job] instance in the parent context and use this function to attach themselves as a child.
-     * They also store a reference to the resulting [DisposableHandle] and dispose a handle when they complete.
-     *
-     * @suppress This is an internal API. This method is too error prone for public API.
-     */
-    @Deprecated(message = "Start child coroutine with 'parent' parameter", level = DeprecationLevel.WARNING)
-    public actual fun attachChild(child: Job): DisposableHandle
-
-    // ------------ state waiting ------------
-
-    /**
-     * Suspends coroutine until this job is complete. This invocation resumes normally (without exception)
-     * when the job is complete for any reason and the [Job] of the invoking coroutine is still [active][isActive].
-     * This function also [starts][Job.start] the corresponding coroutine if the [Job] was still in _new_ state.
-     *
-     * Note, that the job becomes complete only when all its children are complete.
-     *
-     * This suspending function is cancellable and **always** checks for the cancellation of invoking coroutine's Job.
-     * If the [Job] of the invoking coroutine is cancelled or completed when this
-     * suspending function is invoked or while it is suspended, this function
-     * throws [CancellationException].
-     *
-     * In particular, it means that a parent coroutine invoking `join` on a child coroutine that was started using
-     * `launch(coroutineContext) { ... }` builder throws [CancellationException] if the child
-     * had crashed, unless a non-standard [CoroutineExceptionHandler] if installed in the context.
-     *
-     * There is [cancelAndJoin] function that combines an invocation of [cancel] and `join`.
-     */
-    public actual suspend fun join()
-
-    // ------------ low-level state-notification ------------
-
-    /**
-     * Registers handler that is **synchronously** invoked once on cancellation or completion of this job.
-     * When job is already cancelling or complete, then the handler is immediately invoked
-     * with a job's cancellation cause or `null` unless [invokeImmediately] is set to false.
-     * Otherwise, handler will be invoked once when this job is cancelled or complete.
-     *
-     * Invocation of this handler on a transition to a transient _cancelling_ state
-     * is controlled by [onCancelling] boolean parameter.
-     * The handler is invoked on invocation of [cancel] when
-     * job becomes _cancelling_ if [onCancelling] parameter is set to `true`. However,
-     * when this [Job] is not backed by a coroutine, like [CompletableDeferred] or [CancellableContinuation]
-     * (both of which do not posses a _cancelling_ state), then the value of [onCancelling] parameter is ignored.
-     *
-     * The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] the
-     * registration of this handler and release its memory if its invocation is no longer needed.
-     * There is no need to dispose the handler after completion of this job. The references to
-     * all the handlers are released when this job completes.
-     *
-     * Installed [handler] should not throw any exceptions. If it does, they will get caught,
-     * wrapped into [CompletionHandlerException], and rethrown, potentially causing crash of unrelated code.
-     *
-     * **Note**: This function is a part of internal machinery that supports parent-child hierarchies
-     * and allows for implementation of suspending functions that wait on the Job's state.
-     * This function should not be used in general application code.
-     * Implementations of `CompletionHandler` must be fast and _lock-free_.
-     *
-     * @param onCancelling when `true`, then the [handler] is invoked as soon as this job transitions to _cancelling_ state;
-     *        when `false` then the [handler] is invoked only when it transitions to _completed_ state.
-     * @param invokeImmediately when `true` and this job is already in the desired state (depending on [onCancelling]),
-     *        then the [handler] is immediately and synchronously invoked and [NonDisposableHandle] is returned;
-     *        when `false` then [NonDisposableHandle] is returned, but the [handler] is not invoked.
-     * @param handler the handler.
-     */
-    public actual fun invokeOnCompletion(
-        onCancelling: Boolean = false,
-        invokeImmediately: Boolean = true,
-        handler: CompletionHandler): DisposableHandle
-
-    /**
-     * Key for [Job] instance in the coroutine context.
-     */
-    public actual companion object Key : CoroutineContext.Key<Job>
-}
-
-/**
- * Creates a new job object in an _active_ state.
- * It is optionally a child of a [parent] job.
- */
-@Suppress("FunctionName")
-public actual fun Job(parent: Job? = null): Job = JobImpl(parent)
-
-/**
- * A handle to an allocated object that can be disposed to make it eligible for garbage collection.
- */
-public actual interface DisposableHandle {
-    /**
-     * Disposes the corresponding object, making it eligible for garbage collection.
-     * Repeated invocation of this function has no effect.
-     */
-    public actual fun dispose()
-}
-
-// -------------------- CoroutineContext extensions --------------------
-
-/**
- * Cancels [Job] of this context with an optional cancellation [cause]. The result is `true` if the job was
- * cancelled as a result of this invocation and `false` if there is no job in the context or if it was already
- * cancelled or completed. See [Job.cancel] for details.
- */
-public actual fun CoroutineContext.cancel(cause: Throwable? = null): Boolean =
-    this[Job]?.cancel(cause) ?: false
-
-/**
- * Cancels all children of the [Job] in this context with an optional cancellation [cause].
- * It does not do anything if there is no job in the context or it has no children.
- * See [Job.cancelChildren] for details.
- */
-public actual fun CoroutineContext.cancelChildren(cause: Throwable? = null) {
-    this[Job]?.cancelChildren(cause)
-}
-
-// -------------------- Job extensions --------------------
-
-/**
- * Disposes a specified [handle] when this job is complete.
- *
- * This is a shortcut for the following code:
- * ```
- * invokeOnCompletion { handle.dispose() }
- * ```
- */
-public actual fun Job.disposeOnCompletion(handle: DisposableHandle): DisposableHandle =
-    invokeOnCompletion { handle.dispose() }
-
-/**
- * Cancels the job and suspends invoking coroutine until the cancelled job is complete.
- *
- * This suspending function is cancellable and **always** checks for the cancellation of invoking coroutine's Job.
- * If the [Job] of the invoking coroutine is cancelled or completed when this
- * suspending function is invoked or while it is suspended, this function
- * throws [CancellationException].
- *
- * In particular, it means that a parent coroutine invoking `cancelAndJoin` on a child coroutine that was started using
- * `launch(coroutineContext) { ... }` builder throws [CancellationException] if the child
- * had crashed, unless a non-standard [CoroutineExceptionHandler] if installed in the context.
- *
- * This is a shortcut for the invocation of [cancel][Job.cancel] followed by [join][Job.join].
- */
-public actual suspend fun Job.cancelAndJoin() {
-    cancel()
-    return join()
-}
-
-/**
- * Cancels all [children][Job.children] jobs of this coroutine with the given [cause] using [Job.cancel]
- * for all of them. Unlike [Job.cancel] on this job as a whole, the state of this job itself is not affected.
- */
-public actual fun Job.cancelChildren(cause: Throwable? = null) {
-    children.forEach { it.cancel(cause) }
-}
-
-/**
- * Suspends coroutine until all [children][Job.children] of this job are complete using
- * [Job.join] for all of them. Unlike [Job.join] on this job as a whole, it does not wait until
- * this job is complete.
- */
-public actual suspend fun Job.joinChildren() {
-    children.forEach { it.join() }
-}
-
-/**
- * No-op implementation of [DisposableHandle].
- */
-public actual object NonDisposableHandle : DisposableHandle {
-    /** Does not do anything. */
-    actual override fun dispose() {}
-
-    /** Returns "NonDisposableHandle" string. */
-    override fun toString(): String = "NonDisposableHandle"
-}
-
-// --------------- helper classes to simplify job implementation
-
-
-/**
- * A concrete implementation of [Job]. It is optionally a child to a parent job.
- * This job is cancelled when the parent is complete, but not vise-versa.
- *
- * This is an open class designed for extension by more specific classes that might augment the
- * state and mare store addition state information for completed jobs, like their result values.
- *
- * @param active when `true` the job is created in _active_ state, when `false` in _new_ state. See [Job] for details.
- * @suppress **This is unstable API and it is subject to change.**
- */
-internal actual open class JobSupport actual constructor(active: Boolean) : Job {
-    public actual override val key: CoroutineContext.Key<*> get() = Job
-
-    /**
-     * Returns current state of this job.
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    // Note: use shared objects while we have no listeners
-    internal var state: Any? = if (active) EmptyActive else EmptyNew
-        private set
-
-    private var parentHandle: DisposableHandle? = null
-
-    // ------------ initialization ------------
-
-    /**
-     * Initializes parent job.
-     * It shall be invoked at most once after construction after all other initialization.
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal actual fun initParentJobInternal(parent: Job?) {
-        check(parentHandle == null) { "Shall be invoked at most once" }
-        if (parent == null) {
-            parentHandle = NonDisposableHandle
-            return
-        }
-        parent.start() // make sure the parent is started
-        @Suppress("DEPRECATION")
-        val handle = parent.attachChild(this)
-        parentHandle = handle
-        // now check our state _after_ registering (see updateState order of actions)
-        if (isCompleted) {
-            handle.dispose()
-            parentHandle = NonDisposableHandle // release it just in case, to aid GC
-        }
-    }
-
-    // ------------ state query ------------
-
-    public actual final override val isActive: Boolean get() {
-        val state = this.state
-        return state is Incomplete && state.isActive
-    }
-
-    public actual final override val isCompleted: Boolean get() = state !is Incomplete
-
-    public actual final override val isCancelled: Boolean get() {
-        val state = this.state
-        return state is Cancelled || (state is Finishing && state.cancelled != null)
-    }
-
-    // ------------ state update ------------
-
-    /**
-     * Updates current [state] of this job.
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal fun updateState(proposedUpdate: Any?, mode: Int) {
-        val state = this.state as Incomplete // current state must be incomplete
-        val update = coerceProposedUpdate(state, proposedUpdate)
-        tryUpdateState(update)
-        completeUpdateState(state, update, mode)
-    }
-
-    internal fun tryUpdateState(update: Any?) {
-        require(update !is Incomplete) // only incomplete -> completed transition is allowed
-        this.state = update
-        // Unregister from parent job
-        parentHandle?.let {
-            it.dispose()
-            parentHandle = NonDisposableHandle // release it just in case, to aid GC
-        }
-    }
-
-    // when Job is in Cancelling state, it can only be promoted to Cancelled state,
-    // so if the proposed Update is not an appropriate Cancelled (preserving the cancellation cause),
-    // then the corresponding Cancelled state is constructed.
-    private fun coerceProposedUpdate(expect: Incomplete, proposedUpdate: Any?): Any? =
-        if (expect is Finishing && expect.cancelled != null && !isCorrespondinglyCancelled(expect.cancelled, proposedUpdate))
-            createCancelled(expect.cancelled, proposedUpdate) else proposedUpdate
-
-    private fun isCorrespondinglyCancelled(cancelled: Cancelled, proposedUpdate: Any?): Boolean {
-        if (proposedUpdate !is Cancelled) return false
-        // NOTE: equality comparison of causes is performed here by design, see equals of JobCancellationException
-        return proposedUpdate.cause == cancelled.cause ||
-                proposedUpdate.cause is JobCancellationException && cancelled.cause == null
-    }
-
-    private fun createCancelled(cancelled: Cancelled, proposedUpdate: Any?): Cancelled {
-        if (proposedUpdate !is CompletedExceptionally) return cancelled // not exception -- just use original cancelled
-        val exception = proposedUpdate.exception
-        if (cancelled.exception == exception) return cancelled // that is the cancelled we need already!
-        //cancelled.cause?.let { exception.addSuppressed(it) }
-        return Cancelled(this, exception)
-    }
-
-    /**
-     * Completes update of the current [state] of this job.
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal fun completeUpdateState(expect: Incomplete, update: Any?, mode: Int) {
-        val exceptionally = update as? CompletedExceptionally
-        // Do overridable processing before completion handlers
-        if (!expect.isCancelling) onCancellationInternal(exceptionally) // only notify when was not cancelling before
-        onCompletionInternal(update, mode)
-        // Invoke completion handlers
-        val cause = exceptionally?.cause
-        if (expect is JobNode<*>) { // SINGLE/SINGLE+ state -- one completion handler (common case)
-            try {
-                expect.invoke(cause)
-            } catch (ex: Throwable) {
-                handleException(CompletionHandlerException("Exception in completion handler $expect for $this", ex))
-            }
-        } else {
-            expect.list?.notifyCompletion(cause)
-        }
-    }
-
-    private inline fun <reified T: JobNode<*>> notifyHandlers(list: NodeList, cause: Throwable?) {
-        var exception: Throwable? = null
-        list.forEach<T> { node ->
-            try {
-                node.invoke(cause)
-            } catch (ex: Throwable) {
-                exception?.apply { /* addSuppressed(ex) */ } ?: run {
-                    exception =  CompletionHandlerException("Exception in completion handler $node for $this", ex)
-                }
-            }
-        }
-        exception?.let { handleException(it) }
-    }
-
-    private fun NodeList.notifyCompletion(cause: Throwable?) =
-            notifyHandlers<JobNode<*>>(this, cause)
-
-    private fun notifyCancellation(list: NodeList, cause: Throwable?) =
-            notifyHandlers<JobCancellationNode<*>>(list, cause)
-
-    public actual final override fun start(): Boolean {
-        val state = this.state
-        when (state) {
-            is Empty -> { // EMPTY_X state -- no completion handlers
-                if (state.isActive) return false // already active
-                this.state = EmptyActive
-                onStartInternal()
-                return true
-            }
-            is NodeList -> { // LIST -- a list of completion handlers (either new or active)
-                return state.makeActive().also { result ->
-                    if (result) onStartInternal()
-                }
-            }
-            else -> return false // not a new state
-        }
-    }
-
-    /**
-     * Override to provide the actual [start] action.
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal actual open fun onStartInternal() {}
-
-    public actual final override fun getCancellationException(): CancellationException {
-        val state = this.state
-        return when {
-            state is Finishing && state.cancelled != null ->
-                state.cancelled.exception.toCancellationException("Job is being cancelled")
-            state is Incomplete ->
-                error("Job was not completed or cancelled yet: $this")
-            state is CompletedExceptionally ->
-                state.exception.toCancellationException("Job has failed")
-            else -> JobCancellationException("Job has completed normally", null, this)
-        }
-    }
-
-    private fun Throwable.toCancellationException(message: String): CancellationException =
-            this as? CancellationException ?: JobCancellationException(message, this, this@JobSupport)
-
-    /**
-     * Returns the cause that signals the completion of this job -- it returns the original
-     * [cancel] cause or **`null` if this job had completed
-     * normally or was cancelled without a cause**. This function throws
-     * [IllegalStateException] when invoked for an job that has not [completed][isCompleted] nor
-     * [isCancelled] yet.
-     */
-    protected fun getCompletionCause(): Throwable? {
-        val state = this.state
-        return when {
-            state is Finishing && state.cancelled != null -> state.cancelled.cause
-            state is Incomplete -> error("Job was not completed or cancelled yet")
-            state is CompletedExceptionally -> state.cause
-            else -> null
-        }
-    }
-
-    // todo: non-final as a workaround for KT-21968, should be final in the future
-    public actual override fun invokeOnCompletion(onCancelling: Boolean, invokeImmediately: Boolean, handler: CompletionHandler) =
-        installNode(onCancelling, invokeImmediately, makeNode(handler, onCancelling))
-
-    private fun installNode(
-        onCancelling: Boolean,
-        invokeImmediately: Boolean,
-        node: JobNode<*>
-    ): DisposableHandle {
-        while (true) {
-            val state = this.state
-            when (state) {
-                is Empty -> { // EMPTY_X state -- no completion handlers
-                    if (state.isActive) {
-                        // move to SINGLE state
-                        this.state = node
-                        return node
-                    } else
-                        promoteEmptyToNodeList(state) // that way we can add listener for non-active coroutine
-                }
-                is Incomplete -> {
-                    val list = state.list
-                    if (list == null) { // SINGLE/SINGLE+
-                        promoteSingleToNodeList(state as JobNode<*>)
-                    } else {
-                        if (state is Finishing && state.cancelled != null && onCancelling) {
-                            // cannot be in this state unless were support cancelling state
-                            check(onCancelMode != ON_CANCEL_MAKE_CANCELLED) // cannot be in this state unless were support cancelling state
-                            // installing cancellation handler on job that is being cancelled
-                            if (invokeImmediately) node.invoke(state.cancelled.cause)
-                            return NonDisposableHandle
-                        }
-                        list.addLast(node)
-                        return node
-                    }
-                }
-                else -> { // is complete
-                    if (invokeImmediately) node.invoke((state as? CompletedExceptionally)?.cause)
-                    return NonDisposableHandle
-                }
-            }
-        }
-    }
-
-    private fun makeNode(handler: CompletionHandler, onCancelling: Boolean): JobNode<*> {
-        val hasCancellingState = onCancelMode != ON_CANCEL_MAKE_CANCELLED
-        return if (onCancelling && hasCancellingState)
-            InvokeOnCancellation(this, handler)
-        else
-            InvokeOnCompletion(this, handler)
-    }
-
-
-    private fun promoteEmptyToNodeList(state: Empty) {
-        check(state === this.state) { "Expected empty state"}
-        // promote it to list in new state
-        this.state = NodeList(state.isActive)
-    }
-
-    private fun promoteSingleToNodeList(state: JobNode<*>) {
-        check(state === this.state) { "Expected single state" }
-        // promote it to list (SINGLE+ state)
-        val list = NodeList(isActive = true)
-        list.addLast(state)
-        this.state = list
-    }
-
-    public actual final override suspend fun join() {
-        if (!joinInternal()) { // fast-path no wait
-            return suspendCoroutineOrReturn { cont ->
-                cont.context.checkCompletion()
-                Unit // do not suspend
-            }
-        }
-        return joinSuspend() // slow-path wait
-    }
-
-    private fun joinInternal(): Boolean {
-        if (state !is Incomplete) return false // not active anymore (complete) -- no need to wait
-        start()
-        return true // wait
-    }
-
-    private suspend fun joinSuspend() = suspendCancellableCoroutine<Unit> { cont ->
-        val handle = invokeOnCompletion { cont.resume(Unit) }
-        cont.invokeOnCompletion { handle.dispose() }
-    }
-
-    internal fun removeNode(node: JobNode<*>) {
-        // remove logic depends on the state of the job
-        val state = this.state
-        when (state) {
-            is JobNode<*> -> { // SINGE/SINGLE+ state -- one completion handler
-                if (state !== node) return // a different job node --> we were already removed
-                // remove and revert back to empty state
-                this.state = EmptyActive
-            }
-            is Incomplete -> { // may have a list of completion handlers
-                // remove node from the list if there is a list
-                if (state.list != null) node.remove()
-            }
-        }
-    }
-
-    protected open val onCancelMode: Int get() = ON_CANCEL_MAKE_CANCELLING
-
-    public actual override fun cancel(cause: Throwable?): Boolean = when (onCancelMode) {
-        ON_CANCEL_MAKE_CANCELLED -> makeCancelled(cause)
-        ON_CANCEL_MAKE_CANCELLING -> makeCancelling(cause)
-        ON_CANCEL_MAKE_COMPLETING -> makeCompletingOnCancel(cause)
-        else -> error("Invalid onCancelMode $onCancelMode")
-    }
-
-    // we will be dispatching coroutine to process its cancellation exception, so there is no need for
-    // an extra check for Job status in MODE_CANCELLABLE
-    private fun updateStateCancelled(cause: Throwable?) =
-        updateState(Cancelled(this, cause), mode = MODE_ATOMIC_DEFAULT)
-
-    // transitions to Cancelled state
-    private fun makeCancelled(cause: Throwable?): Boolean {
-        if (state !is Incomplete) return false // quit if already complete
-        updateStateCancelled(cause)
-        return true
-    }
-
-    // transitions to Cancelling state
-    private fun makeCancelling(cause: Throwable?): Boolean {
-        while (true) {
-            val state = this.state
-            when (state) {
-                is Empty -> { // EMPTY_X state -- no completion handlers
-                    if (state.isActive) {
-                        promoteEmptyToNodeList(state) // this way can wrap it into Cancelling on next pass
-                    } else {
-                        // cancelling a non-started coroutine makes it immediately cancelled
-                        // (and we have no listeners to notify which makes it very simple)
-                        updateStateCancelled(cause)
-                        return true
-                    }
-                }
-                is JobNode<*> -> { // SINGLE/SINGLE+ state -- one completion handler
-                    promoteSingleToNodeList(state)
-                }
-                is NodeList -> { // LIST -- a list of completion handlers (either new or active)
-                    if (state.isActive) {
-                        makeCancellingList(state.list, cause)
-                        return true
-                    } else {
-                        // cancelling a non-started coroutine makes it immediately cancelled
-                        updateStateCancelled(cause)
-                        return true
-                    }
-                }
-                is Finishing -> { // Completing/Cancelling the job, may cancel
-                    if (state.cancelled != null) return false // already cancelling
-                    makeCancellingList(state.list, cause)
-                    return true
-                }
-                else -> { // is inactive
-                    return false
-                }
-            }
-        }
-    }
-
-    // make expected state in cancelling
-    private fun makeCancellingList(list: NodeList, cause: Throwable?) {
-        val cancelled = Cancelled(this, cause)
-        state = Finishing(list, cancelled, false)
-        onFinishingInternal(cancelled)
-        onCancellationInternal(cancelled)
-        notifyCancellation(list, cause)
-    }
-
-    private fun makeCompletingOnCancel(cause: Throwable?): Boolean =
-        makeCompleting(Cancelled(this, cause))
-
-    internal fun makeCompleting(proposedUpdate: Any?): Boolean =
-        when (makeCompletingInternal(proposedUpdate, mode = MODE_ATOMIC_DEFAULT)) {
-            COMPLETING_ALREADY_COMPLETING -> false
-            else -> true
-        }
-
-    /**
-     * Returns:
-     * * `true` if state was updated to completed/cancelled;
-     * * `false` if made completing or it is cancelling and is waiting for children.
-     *
-     * @throws IllegalStateException if job is already complete or completing
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal actual fun makeCompletingOnce(proposedUpdate: Any?, mode: Int): Boolean =
-        when (makeCompletingInternal(proposedUpdate, mode)) {
-            COMPLETING_COMPLETED -> true
-            COMPLETING_WAITING_CHILDREN -> false
-            else -> throw IllegalStateException("Job $this is already complete or completing, " +
-                "but is being completed with $proposedUpdate", proposedUpdate.exceptionOrNull)
-        }
-
-    private fun makeCompletingInternal(proposedUpdate: Any?, mode: Int): Int {
-        loop@ while (true) {
-            val state = this.state
-            @Suppress("FoldInitializerAndIfToElvis")
-            if (state !is Incomplete)
-                return COMPLETING_ALREADY_COMPLETING
-            if (state is Finishing && state.completing)
-                return COMPLETING_ALREADY_COMPLETING
-            val child: Child? = firstChild(state) ?: // or else complete immediately w/o children
-                when {
-                    state !is Finishing && hasOnFinishingHandler(proposedUpdate) -> null // unless it has onCompleting handler
-                    else -> {
-                        updateState(proposedUpdate, mode)
-                        return COMPLETING_COMPLETED
-                    }
-                }
-            val list = state.list ?: // must promote to list to correctly operate on child lists
-                when (state) {
-                    is Empty -> {
-                        promoteEmptyToNodeList(state)
-                        continue@loop // retry
-                    }
-                    is JobNode<*> -> {
-                        promoteSingleToNodeList(state)
-                        continue@loop // retry
-                    }
-                    else -> error("Unexpected state with an empty list: $state")
-                }
-            // cancel all children in list on exceptional completion
-            if (proposedUpdate is CompletedExceptionally)
-                child?.cancelChildrenInternal(proposedUpdate.exception)
-            // switch to completing state
-            val completing = Finishing(list, (state as? Finishing)?.cancelled, true)
-            this.state = completing
-            if (state !is Finishing) onFinishingInternal(proposedUpdate)
-            if (child != null && tryWaitForChild(child, proposedUpdate))
-                return COMPLETING_WAITING_CHILDREN
-            updateState(proposedUpdate, mode = MODE_ATOMIC_DEFAULT)
-            return COMPLETING_COMPLETED
-        }
-    }
-
-    private tailrec fun Child.cancelChildrenInternal(cause: Throwable) {
-        childJob.cancel(JobCancellationException("Child job was cancelled because of parent failure", cause, childJob))
-        nextChild()?.cancelChildrenInternal(cause)
-    }
-
-    private val Any?.exceptionOrNull: Throwable?
-        get() = (this as? CompletedExceptionally)?.exception
-
-    private fun firstChild(state: Incomplete) =
-        state as? Child ?: state.list?.nextChild()
-
-    // return false when there is no more incomplete children to wait
-    private tailrec fun tryWaitForChild(child: Child, proposedUpdate: Any?): Boolean {
-        val handle = child.childJob.invokeOnCompletion(invokeImmediately = false) {
-            continueCompleting(child, proposedUpdate)
-        }
-        if (handle !== NonDisposableHandle) return true // child is not complete and we've started waiting for it
-        val nextChild = child.nextChild() ?: return false
-        return tryWaitForChild(nextChild, proposedUpdate)
-    }
-
-    internal fun continueCompleting(lastChild: Child, proposedUpdate: Any?) {
-        val state = this.state
-        @Suppress("FoldInitializerAndIfToElvis")
-        if (state !is Finishing)
-            throw IllegalStateException("Job $this is found in expected state while completing with $proposedUpdate", proposedUpdate.exceptionOrNull)
-        // figure out if we need to wait for next child
-        val waitChild = lastChild.nextChild()
-        // try wait for next child
-        if (waitChild != null && tryWaitForChild(waitChild, proposedUpdate)) return // waiting for next child
-        // no more children to wait -- update state
-        updateState(proposedUpdate, mode = MODE_ATOMIC_DEFAULT)
-    }
-
-    private fun LinkedListNode.nextChild(): Child? {
-        var cur = this
-        while (cur.isRemoved) cur = cur.prev // rollback to prev non-removed (or list head)
-        while (true) {
-            cur = cur.next
-            if (cur is Child) return cur
-            if (cur is NodeList) return null // checked all -- no more children
-        }
-    }
-
-    public actual final override val children: Sequence<Job> get() = buildSequence<Job> {
-        val state = this@JobSupport.state
-        when (state) {
-            is Child -> yield(state.childJob)
-            is Incomplete -> state.list?.let { list ->
-                list.forEach<Child> { yield(it.childJob) }
-            }
-        }
-    }
-
-    @Suppress("OverridingDeprecatedMember")
-    public actual override fun attachChild(child: Job): DisposableHandle =
-        installNode(onCancelling = true, invokeImmediately = true, node = Child(this, child))
-
-    /**
-     * Override to process any exceptions that were encountered while invoking completion handlers
-     * installed via [invokeOnCompletion].
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal actual open fun handleException(exception: Throwable) {
-        throw exception
-    }
-
-    /**
-     * It is invoked once when job is cancelled or is completed, similarly to [invokeOnCompletion] with
-     * `onCancelling` set to `true`.
-     * @param exceptionally not null when the the job was cancelled or completed exceptionally,
-     *               null when it has completed normally.
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal actual open fun onCancellationInternal(exceptionally: CompletedExceptionally?) {}
-
-    /**
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal actual open fun hasOnFinishingHandler(update: Any?) = false
-
-    /**
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal actual open fun onFinishingInternal(update: Any?) {}
-
-    /**
-     * Override for completion actions that need to do something with the state.
-     * @param mode completion mode.
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal actual open fun onCompletionInternal(state: Any?, mode: Int) {}
-
-    // for nicer debugging
-    public override fun toString(): String =
-        "${nameString()}{${stateString()}}"
-
-    /**
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal actual open fun nameString(): String = classSimpleName
-
-    private fun stateString(): String {
-        val state = this.state
-        return when (state) {
-            is Finishing -> buildString {
-                if (state.cancelled != null) append("Cancelling")
-                if (state.completing) append("Completing")
-            }
-            is Incomplete -> if (state.isActive) "Active" else "New"
-            is Cancelled -> "Cancelled"
-            is CompletedExceptionally -> "CompletedExceptionally"
-            else -> "Completed"
-        }
-    }
-
-    /**
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal interface Incomplete {
-        val isActive: Boolean
-        val list: NodeList? // is null only for Empty and JobNode incomplete state objects
-    }
-
-    // Cancelling or Completing
-    private class Finishing(
-        override val list: NodeList,
-        val cancelled: Cancelled?, /* != null when cancelling */
-        val completing: Boolean /* true when completing */
-    ) : Incomplete {
-        override val isActive: Boolean get() = cancelled == null
-    }
-
-    private val Incomplete.isCancelling: Boolean
-        get() = this is Finishing && cancelled != null
-
-    /**
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal class NodeList(
-        override var isActive: Boolean
-    ) : LinkedListHead(), Incomplete {
-        override val list: NodeList get() = this
-
-        fun makeActive(): Boolean {
-            if (isActive) return false
-            isActive = true
-            return true
-        }
-
-        override fun toString(): String = buildString {
-            append("List")
-            append(if (isActive) "{Active}" else "{New}")
-            append("[")
-            var first = true
-            this@NodeList.forEach<JobNode<*>> { node ->
-                if (first) first = false else append(", ")
-                append(node)
-            }
-            append("]")
-        }
-    }
-
-    /*
-     * =================================================================================================
-     * This is ready-to-use implementation for Deferred interface.
-     * However, it is not type-safe. Conceptually it just exposes the value of the underlying
-     * completed state as `Any?`
-     * =================================================================================================
-     */
-
-    public actual val isCompletedExceptionally: Boolean get() = state is CompletedExceptionally
-
-    public actual fun getCompletionExceptionOrNull(): Throwable? {
-        val state = this.state
-        check(state !is Incomplete) { "This job has not completed yet" }
-        return state.exceptionOrNull
-    }
-
-    /**
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal fun getCompletedInternal(): Any? {
-        val state = this.state
-        check(state !is Incomplete) { "This job has not completed yet" }
-        if (state is CompletedExceptionally) throw state.exception
-        return state
-    }
-
-    /**
-     * @suppress **This is unstable API and it is subject to change.**
-     */
-    internal suspend fun awaitInternal(): Any? {
-        val state = this.state
-        if (state !is Incomplete) {
-            // already complete -- just return result
-            if (state is CompletedExceptionally) throw state.exception
-            return state
-        }
-        start()
-        return awaitSuspend() // slow-path
-    }
-
-    private suspend fun awaitSuspend(): Any? = suspendCancellableCoroutine { cont ->
-        val handle = invokeOnCompletion {
-            val state = this.state
-            check(state !is Incomplete) { "State should be complete "}
-            if (state is CompletedExceptionally)
-                cont.resumeWithException(state.exception)
-            else
-                cont.resume(state)
-        }
-        cont.invokeOnCompletion { handle.dispose() }
-    }
-}
-
-internal const val ON_CANCEL_MAKE_CANCELLED = 0
-internal const val ON_CANCEL_MAKE_CANCELLING = 1
-internal const val ON_CANCEL_MAKE_COMPLETING = 2
-
-private const val COMPLETING_ALREADY_COMPLETING = 0
-private const val COMPLETING_COMPLETED = 1
-private const val COMPLETING_WAITING_CHILDREN = 2
-
-@Suppress("PrivatePropertyName")
-private val EmptyNew = Empty(false)
-@Suppress("PrivatePropertyName")
-private val EmptyActive = Empty(true)
-
-private class Empty(override val isActive: Boolean) : JobSupport.Incomplete {
-    override val list: JobSupport.NodeList? get() = null
-    override fun toString(): String = "Empty{${if (isActive) "Active" else "New" }}"
-}
-
-private class JobImpl(parent: Job? = null) : JobSupport(true) {
-    init { initParentJobInternal(parent) }
-    override val onCancelMode: Int get() = ON_CANCEL_MAKE_COMPLETING
-}
-
-// -------- invokeOnCompletion nodes
-
-internal abstract class JobNode<out J : Job>(
-    val job: J
-) : LinkedListNode(), DisposableHandle, JobSupport.Incomplete {
-    final override val isActive: Boolean get() = true
-    final override val list: JobSupport.NodeList? get() = null
-    final override fun dispose() = (job as JobSupport).removeNode(this)
-    abstract fun invoke(reason: Throwable?) // CompletionHandler -- invoked on completion
-}
-
-private class InvokeOnCompletion(
-    job: Job,
-    private val handler: CompletionHandler
-) : JobNode<Job>(job)  {
-    override fun invoke(reason: Throwable?) = handler.invoke(reason)
-    override fun toString() = "InvokeOnCompletion"
-}
-
-// -------- invokeOnCancellation nodes
-
-/**
- * Marker for node that shall be invoked on cancellation (in _cancelling_ state).
- * **Note: may be invoked multiple times during cancellation.**
- */
-internal abstract class JobCancellationNode<out J : Job>(job: J) : JobNode<J>(job)
-
-private class InvokeOnCancellation(
-    job: Job,
-    private val handler: CompletionHandler
-) : JobCancellationNode<Job>(job)  {
-    // delegate handler shall be invoked at most once, so here is an additional flag
-    private var invoked = false
-    override fun invoke(reason: Throwable?) {
-        if (invoked) return
-        invoked = true
-        handler.invoke(reason)
-    }
-    override fun toString() = "InvokeOnCancellation"
-}
-
-internal class Child(
-    parent: JobSupport,
-    val childJob: Job
-) : JobCancellationNode<JobSupport>(parent) {
-    override fun invoke(reason: Throwable?) {
-        // Always materialize the actual instance of parent's completion exception and cancel child with it
-        childJob.cancel(job.getCancellationException())
-    }
-    override fun toString(): String = "Child[$childJob]"
-}
-
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/NonCancellable.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/NonCancellable.kt
deleted file mode 100644
index 09a8789..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/NonCancellable.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlinx.coroutines.experimental.NonCancellable.isActive
-import kotlin.coroutines.experimental.AbstractCoroutineContextElement
-
-/**
- * A non-cancelable job that is always [active][isActive]. It is designed to be used with [run] builder
- * to prevent cancellation of code blocks that need to run without cancellation.
- *
- * Use it like this:
- * ```
- * run(NonCancellable) {
- *     // this code will not be cancelled
- * }
- * ```
- */
-public actual object NonCancellable : AbstractCoroutineContextElement(Job), Job {
-    /** Always returns `true`. */
-    actual override val isActive: Boolean  get() = true
-
-    /** Always returns `false`. */
-    actual override val isCompleted: Boolean get() = false
-
-    /** Always returns `false`. */
-    actual override val isCancelled: Boolean get() = false
-
-    /** Always returns `false`. */
-    actual override fun start(): Boolean = false
-
-    /** Always throws [UnsupportedOperationException]. */
-    actual suspend override fun join() {
-        throw UnsupportedOperationException("This job is always active")
-    }
-
-    /** Always throws [IllegalStateException]. */
-    actual override fun getCancellationException(): CancellationException = throw IllegalStateException("This job is always active")
-
-    /** Always returns [NonDisposableHandle]. */
-    actual override fun invokeOnCompletion(onCancelling: Boolean, invokeImmediately: Boolean, handler: CompletionHandler): DisposableHandle =
-        NonDisposableHandle
-
-    /** Always returns `false`. */
-    actual override fun cancel(cause: Throwable?): Boolean = false
-
-    /** Always returns [emptySequence]. */
-    actual override val children: Sequence<Job>
-        get() = emptySequence()
-
-    /** Always returns [NonDisposableHandle] and does not do anything. */
-    @Suppress("OverridingDeprecatedMember")
-    actual override fun attachChild(child: Job): DisposableHandle = NonDisposableHandle
-}
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Promise.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Promise.kt
index 621a737..5e12cba 100644
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Promise.kt
+++ b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Promise.kt
@@ -16,16 +16,16 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlin.coroutines.experimental.ContinuationInterceptor
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.js.Promise
+import kotlin.coroutines.experimental.*
+import kotlin.js.*
 
 /**
  * Starts new coroutine and returns its result as an implementation of [Promise].
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.coroutineContext] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
+ * of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
@@ -37,15 +37,17 @@
  * @param context context of the coroutine. The default value is [DefaultDispatcher].
  * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
  * @param parent explicitly specifies the parent job, overrides job from the [context] (if any).
+ * @param onCompletion optional completion handler for the coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
 public fun <T> promise(
     context: CoroutineContext = DefaultDispatcher,
     start: CoroutineStart = CoroutineStart.DEFAULT,
     parent: Job? = null,
+    onCompletion: CompletionHandler? = null,
     block: suspend CoroutineScope.() -> T
 ): Promise<T> =
-    async(context, start, parent, block).asPromise()
+    async(context, start, parent, onCompletion, block = block).asPromise()
 
 /**
  * Converts this deferred value to the instance of [Promise].
diff --git a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Runnable.kt
similarity index 64%
copy from core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt
copy to js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Runnable.kt
index 06f7c68..e9e1b7d 100644
--- a/core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt
+++ b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Runnable.kt
@@ -16,14 +16,20 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlin.test.*
+/**
+ * A runnable task for [CoroutineDispatcher.dispatch].
+ */
+public actual interface Runnable {
+    public actual fun run()
+}
 
-class JobTest : TestBase() {
-    @Test
-    fun testMemoryRelease() {
-        val job = Job()
-        val n = 10_000_000 * stressTestMultiplier
-        var fireCount = 0
-        for (i in 0 until n) job.invokeOnCompletion { fireCount++ }.dispose()
+/**
+ * Creates [Runnable] task instance.
+ */
+@Suppress("FunctionName")
+public actual inline fun Runnable(crossinline block: () -> Unit): Runnable =
+    object : Runnable {
+        override fun run() {
+            block()
+        }
     }
-}
\ No newline at end of file
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt
deleted file mode 100644
index bbe49ce..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlinx.coroutines.experimental.intrinsics.*
-import kotlin.coroutines.experimental.Continuation
-import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED
-import kotlin.coroutines.experimental.intrinsics.startCoroutineUninterceptedOrReturn
-import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn
-
-/**
- * Runs a given suspending [block] of code inside a coroutine with a specified timeout and throws
- * [TimeoutCancellationException] if timeout was exceeded.
- *
- * The code that is executing inside the [block] is cancelled on timeout and the active or next invocation of
- * cancellable suspending function inside the block throws [TimeoutCancellationException].
- * Even if the code in the block suppresses [TimeoutCancellationException], it
- * is still thrown by `withTimeout` invocation.
- *
- * The sibling function that does not throw exception on timeout is [withTimeoutOrNull].
- *
- * This function delegates to [Delay.invokeOnTimeout] if the context [CoroutineDispatcher]
- * implements [Delay] interface, otherwise it tracks time using a built-in single-threaded scheduled executor service.
- *
- * @param time timeout time in milliseconds.
- */
-public actual suspend fun <T> withTimeout(time: Int, block: suspend CoroutineScope.() -> T): T {
-    require(time >= 0) { "Timeout time $time cannot be negative" }
-    if (time <= 0L) throw CancellationException("Timed out immediately")
-    return suspendCoroutineOrReturn { cont: Continuation<T> ->
-        setupTimeout(TimeoutCoroutine(time, cont), block)
-    }
-}
-
-private fun <U, T: U> setupTimeout(
-    coroutine: TimeoutCoroutine<U, T>,
-    block: suspend CoroutineScope.() -> T
-): Any? {
-    // schedule cancellation of this coroutine on time
-    val cont = coroutine.cont
-    val context = cont.context
-    coroutine.disposeOnCompletion(context.delay.invokeOnTimeout(coroutine.time, coroutine))
-    // restart block using new coroutine with new job,
-    // however start it as undispatched coroutine, because we are already in the proper context
-    return coroutine.startUndispatchedOrReturn(coroutine, block)
-}
-
-private open class TimeoutCoroutine<U, in T: U>(
-    val time: Int,
-    val cont: Continuation<U>
-) : AbstractCoroutine<T>(cont.context, active = true), Runnable, Continuation<T> {
-    override val defaultResumeMode: Int get() = MODE_DIRECT
-
-    @Suppress("LeakingThis")
-    override fun run() {
-        cancel(TimeoutCancellationException(time, this))
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    internal override fun onCompletionInternal(state: Any?, mode: Int) {
-        if (state is CompletedExceptionally)
-            cont.resumeWithExceptionMode(state.exception, mode)
-        else
-            cont.resumeMode(state as T, mode)
-    }
-
-    override fun toString(): String  =
-        "TimeoutCoroutine($time)"
-}
-
-/**
- * Runs a given suspending block of code inside a coroutine with a specified timeout and returns
- * `null` if this timeout was exceeded.
- *
- * The code that is executing inside the [block] is cancelled on timeout and the active or next invocation of
- * cancellable suspending function inside the block throws [TimeoutCancellationException].
- * Even if the code in the block suppresses [TimeoutCancellationException], this
- * invocation of `withTimeoutOrNull` still returns `null`.
- *
- * The sibling function that throws exception on timeout is [withTimeout].
- *
- * This function delegates to [Delay.invokeOnTimeout] if the context [CoroutineDispatcher]
- * implements [Delay] interface, otherwise it tracks time using a built-in single-threaded scheduled executor service.
- *
- * @param time timeout time in milliseconds.
- */
-public actual suspend fun <T> withTimeoutOrNull(time: Int, block: suspend CoroutineScope.() -> T): T? {
-    require(time >= 0) { "Timeout time $time cannot be negative" }
-    if (time <= 0L) return null
-    return suspendCoroutineOrReturn { cont: Continuation<T?> ->
-        setupTimeout(TimeoutOrNullCoroutine(time, cont), block)
-    }
-}
-
-private class TimeoutOrNullCoroutine<T>(
-    time: Int,
-    cont: Continuation<T?>
-) : TimeoutCoroutine<T?, T>(time, cont) {
-    @Suppress("UNCHECKED_CAST")
-    internal override fun onCompletionInternal(state: Any?, mode: Int) {
-        if (state is CompletedExceptionally) {
-            val exception = state.exception
-            if (exception is TimeoutCancellationException && exception.coroutine === this)
-                cont.resumeMode(null, mode) else
-                cont.resumeWithExceptionMode(exception, mode)
-        } else
-            cont.resumeMode(state as T, mode)
-    }
-
-    override fun toString(): String  =
-        "TimeoutOrNullCoroutine($time)"
-}
-
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Yield.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Yield.kt
deleted file mode 100644
index 833a728..0000000
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Yield.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2016-2017 JetBrains s.r.o.
- *
- * 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.
- */
-
-package kotlinx.coroutines.experimental
-
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED
-import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn
-
-/**
- * Yields a thread (or thread pool) of the current coroutine dispatcher to other coroutines to run.
- * If the coroutine dispatcher does not have its own thread pool (like [Unconfined] dispatcher) then this
- * function does nothing, but checks if the coroutine [Job] was completed.
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed when this suspending function is invoked or while
- * this function is waiting for dispatching, it resumes with [CancellationException].
- */
-public actual suspend fun yield(): Unit = suspendCoroutineOrReturn sc@ { cont ->
-    val context = cont.context
-    context.checkCompletion()
-    if (cont !is DispatchedContinuation<Unit>) return@sc Unit
-    if (!cont.dispatcher.isDispatchNeeded(context)) return@sc Unit
-    cont.dispatchYield(Unit)
-    COROUTINE_SUSPENDED
-}
-
-internal fun CoroutineContext.checkCompletion() {
-    val job = get(Job)
-    if (job != null && !job.isActive) throw job.getCancellationException()
-}
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/internal/LinkedList.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/internal/LinkedList.kt
index 54aa2b3..453bf84 100644
--- a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/internal/LinkedList.kt
+++ b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/internal/LinkedList.kt
@@ -18,62 +18,121 @@
 
 private typealias Node = LinkedListNode
 
-/**
- * @suppress **This is unstable API and it is subject to change.**
- */
+/** @suppress **This is unstable API and it is subject to change.** */
+@Suppress("NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS") // :TODO: Remove when fixed: https://youtrack.jetbrains.com/issue/KT-23703
+public actual typealias LockFreeLinkedListNode = LinkedListNode
+
+/** @suppress **This is unstable API and it is subject to change.** */
+public actual typealias LockFreeLinkedListHead = LinkedListHead
+
+/** @suppress **This is unstable API and it is subject to change.** */
 public open class LinkedListNode {
-    public var next = this
-        private set
-    public var prev = this
-        private set
-    public var isRemoved: Boolean = false
-        private set
-    public val isFresh: Boolean = next === this
+    @PublishedApi internal var _next = this
+    @PublishedApi internal var _prev = this
+    @PublishedApi internal var _removed: Boolean = false
+
+    public inline val nextNode get() = _next
+    public inline val prevNode get() = _prev
+    public inline val isRemoved get() = _removed
 
     public fun addLast(node: Node) {
-        val prev = this.prev
-        node.next = this
-        node.prev = prev
-        prev.next = node
-        this.prev = node
+        val prev = this._prev
+        node._next = this
+        node._prev = prev
+        prev._next = node
+        this._prev = node
     }
 
     public open fun remove(): Boolean {
-        if (isRemoved) return false
-        val prev = this.prev
-        val next = this.next
-        prev.next = next
-        next.prev = prev
-        isRemoved = true
+        if (_removed) return false
+        val prev = this._prev
+        val next = this._next
+        prev._next = next
+        next._prev = prev
+        _removed = true
         return true
     }
+
+    public fun addOneIfEmpty(node: Node): Boolean {
+        if (_next !== this) return false
+        addLast(node)
+        return true
+    }
+
+    public inline fun addLastIf(node: Node, crossinline condition: () -> Boolean): Boolean {
+        if (!condition()) return false
+        addLast(node)
+        return true
+    }
+
+    public inline fun addLastIfPrev(node: Node, predicate: (Node) -> Boolean): Boolean {
+        if (!predicate(_prev)) return false
+        addLast(node)
+        return true
+    }
+
+    public inline fun addLastIfPrevAndIf(
+        node: Node,
+        predicate: (Node) -> Boolean, // prev node predicate
+        crossinline condition: () -> Boolean // atomically checked condition
+    ): Boolean {
+        if (!predicate(_prev)) return false
+        if (!condition()) return false
+        addLast(node)
+        return true
+    }
+
+    public fun removeFirstOrNull(): Node? {
+        val next = _next
+        if (next === this) return null
+        check(next.remove()) { "Should remove" }
+        return next
+    }
+
+    public inline fun <reified T> removeFirstIfIsInstanceOfOrPeekIf(predicate: (T) -> Boolean): T? {
+        val next = _next
+        if (next === this) return null
+        if (next !is T) return null
+        if (predicate(next)) return next
+        check(next.remove()) { "Should remove" }
+        return next
+    }
 }
 
-/**
- * @suppress **This is unstable API and it is subject to change.**
- */
+/** @suppress **This is unstable API and it is subject to change.** */
+public actual open class AddLastDesc<T : Node> actual constructor(
+    actual val queue: Node,
+    actual val node: T
+) : AbstractAtomicDesc() {
+    protected override val affectedNode: Node get() = queue._prev
+    protected actual override fun onPrepare(affected: Node, next: Node): Any? = null
+    protected override fun onComplete() = queue.addLast(node)
+}
+
+/** @suppress **This is unstable API and it is subject to change.** */
+public actual abstract class AbstractAtomicDesc : AtomicDesc() {
+    protected abstract val affectedNode: Node
+    protected actual abstract fun onPrepare(affected: Node, next: Node): Any?
+    protected abstract fun onComplete()
+    actual final override fun prepare(op: AtomicOp<*>): Any? = onPrepare(affectedNode, affectedNode._next)
+    actual final override fun complete(op: AtomicOp<*>, failure: Any?) = onComplete()
+}
+
+/** @suppress **This is unstable API and it is subject to change.** */
 public open class LinkedListHead : LinkedListNode() {
-    public val isEmpty get() = next === this
+    public val isEmpty get() = _next === this
 
     /**
      * Iterates over all elements in this list of a specified type.
      */
     public inline fun <reified T : Node> forEach(block: (T) -> Unit) {
-        var cur: Node = next
+        var cur: Node = _next
         while (cur != this) {
             if (cur is T) block(cur)
-            cur = cur.next
+            cur = cur._next
         }
     }
 
     // just a defensive programming -- makes sure that list head sentinel is never removed
     public final override fun remove() = throw UnsupportedOperationException()
-
-    fun removeFirstOrNull(): Node? {
-        val node = next
-        if (node === this) return null
-        node.remove()
-        return node
-    }
 }
-
diff --git a/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/timeunit/TimeUnit.kt b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/timeunit/TimeUnit.kt
new file mode 100644
index 0000000..5bf8eae
--- /dev/null
+++ b/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/timeunit/TimeUnit.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package kotlinx.coroutines.experimental.timeunit
+
+/**
+ * Time unit. This class is provided for better JVM interoperability.
+ * **It is available for common code, but its use in common code is not recommended.**
+ */
+@Deprecated("Using this TimeUnit enum in JS code is not recommended, use functions without it")
+public actual enum class TimeUnit {
+    /** Milliseconds. */
+    MILLISECONDS,
+    /** Seconds. */
+    SECONDS;
+
+    /**
+     * Converts time in this time unit to milliseconds.
+     */
+    public actual fun toMillis(time: Long): Long = when(this) {
+        MILLISECONDS -> time
+        SECONDS -> when {
+            time >= Long.MAX_VALUE / 1000L -> Long.MAX_VALUE
+            time <= Long.MIN_VALUE / 1000L -> Long.MIN_VALUE
+            else -> time * 1000L
+        }
+    }
+}
\ No newline at end of file
diff --git a/js/kotlinx-coroutines-core-js/src/test/kotlin/kotlinx/coroutines/experimental/PromiseTest.kt b/js/kotlinx-coroutines-core-js/src/test/kotlin/kotlinx/coroutines/experimental/PromiseTest.kt
index 5f9414c..2fa3245 100644
--- a/js/kotlinx-coroutines-core-js/src/test/kotlin/kotlinx/coroutines/experimental/PromiseTest.kt
+++ b/js/kotlinx-coroutines-core-js/src/test/kotlin/kotlinx/coroutines/experimental/PromiseTest.kt
@@ -16,7 +16,8 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlin.js.Promise
+import kotlin.coroutines.experimental.*
+import kotlin.js.*
 import kotlin.test.*
 
 class PromiseTest : TestBase() {
diff --git a/js/kotlinx-coroutines-core-js/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt b/js/kotlinx-coroutines-core-js/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt
index fccde08..7a3da04 100644
--- a/js/kotlinx-coroutines-core-js/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt
+++ b/js/kotlinx-coroutines-core-js/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt
@@ -14,9 +14,6 @@
  * limitations under the License.
  */
 
-// :todo: Remove after transition to Kotlin 1.2.30+
-@file:Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
-
 package kotlinx.coroutines.experimental
 
 import kotlin.js.*
@@ -34,6 +31,7 @@
      * complete successfully even if this exception is consumed somewhere in the test.
      */
     public actual fun error(message: Any, cause: Throwable? = null): Nothing {
+        if (cause != null) console.log(cause)
         val exception = IllegalStateException(
             if (cause == null) message.toString() else "$message; caused by $cause")
         if (error == null) error = exception
diff --git a/reactive/coroutines-guide-reactive.md b/reactive/coroutines-guide-reactive.md
index fd8e30a..76e89bf 100644
--- a/reactive/coroutines-guide-reactive.md
+++ b/reactive/coroutines-guide-reactive.md
@@ -101,6 +101,7 @@
 <!--- INCLUDE
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -157,6 +158,7 @@
 <!--- INCLUDE
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -214,6 +216,12 @@
 In Rx lingo this is called a _cold_ publisher. Many standard Rx operators produce cold streams, too. We can iterate
 over them from a coroutine, and every subscription produces the same stream of elements.
 
+**WARNING**: It is planned that in the future a second invocation of `consumeEach` method
+on an channel that is already being consumed is going to fail fast, that is
+immediately throw an `IllegalStateException`.
+See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/167)
+for details.
+
 > Note, that we can replicate the same behaviour that we saw with channels by using Rx 
 [publish](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html#publish()) 
 operator and [connect](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/flowables/ConnectableFlowable.html#connect())
@@ -230,6 +238,7 @@
 import io.reactivex.*
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -277,6 +286,7 @@
 import io.reactivex.*
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -332,9 +342,10 @@
 The subscriber is slow. It takes 500 ms to process each item, which is simulated using `Thread.sleep`.
 
 <!--- INCLUDE
+import io.reactivex.schedulers.*
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.rx2.rxFlowable
-import io.reactivex.schedulers.Schedulers
+import kotlinx.coroutines.experimental.rx2.*
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -463,11 +474,10 @@
 sequence of updates and to release the main thread:
 
 <!--- INCLUDE
-import io.reactivex.subjects.BehaviorSubject
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.rx2.consumeEach
-import kotlinx.coroutines.experimental.yield
+import io.reactivex.subjects.*
+import kotlinx.coroutines.experimental.*
+import kotlinx.coroutines.experimental.rx2.*
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -501,11 +511,9 @@
 without going through the bridge to the reactive streams:
 
 <!--- INCLUDE
-import kotlinx.coroutines.experimental.channels.ConflatedBroadcastChannel
-import kotlinx.coroutines.experimental.channels.consumeEach
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
+import kotlinx.coroutines.experimental.channels.*
+import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -613,8 +621,8 @@
 <!--- INCLUDE
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
-import org.reactivestreams.Publisher
-import kotlin.coroutines.experimental.CoroutineContext
+import org.reactivestreams.*
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -671,9 +679,9 @@
 <!--- INCLUDE
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
-import org.reactivestreams.Publisher
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlinx.coroutines.experimental.selects.whileSelect
+import kotlinx.coroutines.experimental.selects.*
+import org.reactivestreams.*
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -740,8 +748,8 @@
 <!--- INCLUDE
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
-import org.reactivestreams.Publisher
-import kotlin.coroutines.experimental.CoroutineContext
+import org.reactivestreams.*
+import kotlin.coroutines.experimental.*
 -->
 
 ```kotlin
@@ -754,8 +762,10 @@
 }
 ```
 
-Notice, the use of `coroutineContext` in the invocation of [launch] coroutine builder. It is used to refer
-to the [CoroutineScope.coroutineContext] that is provided by [publish] builder. This way, all the coroutines that are
+Notice, the use of 
+[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
+in the invocation of [launch] coroutine builder. It is used to refer
+to the context of the enclosing `publish` coroutine. This way, all the coroutines that are
 being launched here are [children](../coroutines-guide.md#children-of-a-coroutine) of the `publish`
 coroutine and will get cancelled when the `publish` coroutine is cancelled or is otherwise completed. 
 Moreover, since parent coroutine waits until all children are complete, this implementation fully
@@ -1054,7 +1064,6 @@
 [Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
 [yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
 [launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
-[CoroutineScope.coroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/coroutine-context.html
 [CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
 [Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/join.html
 <!--- INDEX kotlinx.coroutines.experimental.channels -->
diff --git a/reactive/kotlinx-coroutines-reactive/src/main/kotlin/kotlinx/coroutines/experimental/reactive/Publish.kt b/reactive/kotlinx-coroutines-reactive/src/main/kotlin/kotlinx/coroutines/experimental/reactive/Publish.kt
index 2c8c2d6..63fa447 100644
--- a/reactive/kotlinx-coroutines-reactive/src/main/kotlin/kotlinx/coroutines/experimental/reactive/Publish.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/main/kotlin/kotlinx/coroutines/experimental/reactive/Publish.kt
@@ -40,7 +40,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
 
@@ -131,7 +131,7 @@
         } catch (e: Throwable) {
             try {
                 if (!cancel(e))
-                    handleCoroutineException(coroutineContext, e)
+                    handleCoroutineException(context, e)
             } finally {
                 doLockedSignalCompleted()
             }
@@ -172,7 +172,7 @@
                     else
                         subscriber.onComplete()
                 } catch (e: Throwable) {
-                    handleCoroutineException(coroutineContext, e)
+                    handleCoroutineException(context, e)
                 }
             }
         } finally {
diff --git a/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/IntegrationTest.kt b/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/IntegrationTest.kt
index 1d3ad80..741111f 100644
--- a/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/IntegrationTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/IntegrationTest.kt
@@ -17,15 +17,13 @@
 package kotlinx.coroutines.experimental.reactive
 
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.MatcherAssert.assertThat
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.hamcrest.core.IsNull
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-import org.reactivestreams.Publisher
-import kotlin.coroutines.experimental.CoroutineContext
+import org.hamcrest.MatcherAssert.*
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.runner.*
+import org.junit.runners.*
+import org.reactivestreams.*
+import kotlin.coroutines.experimental.*
 
 @RunWith(Parameterized::class)
 class IntegrationTest(
diff --git a/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublishTest.kt b/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublishTest.kt
index 5c7db3b..7636918 100644
--- a/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublishTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublishTest.kt
@@ -16,15 +16,12 @@
 
 package kotlinx.coroutines.experimental.reactive
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.junit.Assert.assertThat
-import org.junit.Test
-import org.reactivestreams.Subscriber
-import org.reactivestreams.Subscription
+import kotlinx.coroutines.experimental.*
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import org.reactivestreams.*
+import kotlin.coroutines.experimental.*
 
 class PublishTest : TestBase() {
     @Test
diff --git a/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublisherBackpressureTest.kt b/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublisherBackpressureTest.kt
index d74eeac..68e2b62 100644
--- a/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublisherBackpressureTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublisherBackpressureTest.kt
@@ -16,12 +16,10 @@
 
 package kotlinx.coroutines.experimental.reactive
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.junit.Test
-import org.reactivestreams.Subscriber
-import org.reactivestreams.Subscription
+import kotlinx.coroutines.experimental.*
+import org.junit.*
+import org.reactivestreams.*
+import kotlin.coroutines.experimental.*
 
 class PublisherBackpressureTest : TestBase() {
     @Test
diff --git a/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublisherSubscriptionSelectTest.kt b/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublisherSubscriptionSelectTest.kt
index 647d662..0d584be 100644
--- a/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublisherSubscriptionSelectTest.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/test/kotlin/kotlinx/coroutines/experimental/reactive/PublisherSubscriptionSelectTest.kt
@@ -22,6 +22,7 @@
 import org.junit.Assert.*
 import org.junit.runner.*
 import org.junit.runners.*
+import kotlin.coroutines.experimental.*
 
 @RunWith(Parameterized::class)
 class PublisherSubscriptionSelectTest(val request: Int) : TestBase() {
diff --git a/reactive/kotlinx-coroutines-reactor/src/main/kotlin/kotlinx/coroutines/experimental/reactor/Mono.kt b/reactive/kotlinx-coroutines-reactor/src/main/kotlin/kotlinx/coroutines/experimental/reactor/Mono.kt
index 0a165d6..612bbb1 100644
--- a/reactive/kotlinx-coroutines-reactor/src/main/kotlin/kotlinx/coroutines/experimental/reactor/Mono.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/main/kotlin/kotlinx/coroutines/experimental/reactor/Mono.kt
@@ -33,7 +33,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
diff --git a/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/ConvertTest.kt b/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/ConvertTest.kt
index 4cc3a42..e0cfa98 100644
--- a/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/ConvertTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/ConvertTest.kt
@@ -16,21 +16,12 @@
 
 package kotlinx.coroutines.experimental.reactor
 
-import kotlinx.coroutines.experimental.CommonPool
-import kotlinx.coroutines.experimental.NonCancellable
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.Unconfined
-import kotlinx.coroutines.experimental.async
-import kotlinx.coroutines.experimental.channels.produce
-import kotlinx.coroutines.experimental.delay
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.reactive.consumeEach
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertNull
-import org.junit.Assert.fail
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import kotlinx.coroutines.experimental.channels.*
+import kotlinx.coroutines.experimental.reactive.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class ConvertTest : TestBase() {
     class TestException(s: String): RuntimeException(s)
diff --git a/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/FluxTest.kt b/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/FluxTest.kt
index 74d3cdb..8cdf3de 100644
--- a/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/FluxTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/FluxTest.kt
@@ -16,13 +16,10 @@
 
 package kotlinx.coroutines.experimental.reactor
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.junit.Assert
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import org.hamcrest.core.*
+import org.junit.*
+import kotlin.coroutines.experimental.*
 
 class FluxTest : TestBase() {
     @Test
diff --git a/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/MonoTest.kt b/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/MonoTest.kt
index 4ea6a39..a66d6bf 100644
--- a/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/MonoTest.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/test/kotlin/kotlinx/coroutines/experimental/reactor/MonoTest.kt
@@ -17,18 +17,13 @@
 package kotlinx.coroutines.experimental.reactor
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.reactive.awaitFirst
-import kotlinx.coroutines.experimental.reactive.awaitLast
-import kotlinx.coroutines.experimental.reactive.awaitSingle
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.junit.Assert
-import org.junit.Assert.assertEquals
-import org.junit.Before
-import org.junit.Test
-import reactor.core.publisher.Flux
-import reactor.core.publisher.Mono
-import java.time.Duration.ofMillis
+import kotlinx.coroutines.experimental.reactive.*
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import reactor.core.publisher.*
+import java.time.Duration.*
+import kotlin.coroutines.experimental.*
 
 /**
  * Tests emitting single item with [mono].
diff --git a/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxCompletable.kt b/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxCompletable.kt
index 6b5fed9..6e5431b 100644
--- a/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxCompletable.kt
+++ b/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxCompletable.kt
@@ -32,7 +32,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
diff --git a/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxObservable.kt b/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxObservable.kt
index 2ede105..e482de2 100644
--- a/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxObservable.kt
+++ b/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxObservable.kt
@@ -40,7 +40,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
@@ -132,7 +132,7 @@
         } catch (e: Throwable) {
             try {
                 if (!cancel(e))
-                    handleCoroutineException(coroutineContext, e)
+                    handleCoroutineException(context, e)
             } finally {
                 doLockedSignalCompleted()
             }
@@ -173,7 +173,7 @@
                     else
                         subscriber.onCompleted()
                 } catch (e: Throwable) {
-                    handleCoroutineException(coroutineContext, e)
+                    handleCoroutineException(context, e)
                 }
             }
         } finally {
diff --git a/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxSingle.kt b/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxSingle.kt
index b6e6d22..7627f7c 100644
--- a/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxSingle.kt
+++ b/reactive/kotlinx-coroutines-rx1/src/main/kotlin/kotlinx/coroutines/experimental/rx1/RxSingle.kt
@@ -32,7 +32,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  * 
diff --git a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/CompletableTest.kt b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/CompletableTest.kt
index 584a896..4c1ae5b 100644
--- a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/CompletableTest.kt
+++ b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/CompletableTest.kt
@@ -16,14 +16,11 @@
 
 package kotlinx.coroutines.experimental.rx1
 
-import kotlinx.coroutines.experimental.CancellationException
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.junit.Assert.assertThat
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class CompletableTest : TestBase() {
     @Test
diff --git a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ConvertTest.kt b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ConvertTest.kt
index 9a6cc6e..6089f0b 100644
--- a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ConvertTest.kt
+++ b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ConvertTest.kt
@@ -17,11 +17,11 @@
 package kotlinx.coroutines.experimental.rx1
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.channels.produce
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.junit.Assert.assertThat
-import org.junit.Test
+import kotlinx.coroutines.experimental.channels.*
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class ConvertTest : TestBase() {
     class TestException(s: String): RuntimeException(s)
diff --git a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/IntegrationTest.kt b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/IntegrationTest.kt
index d4c0a24..c225869 100644
--- a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/IntegrationTest.kt
+++ b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/IntegrationTest.kt
@@ -17,15 +17,13 @@
 package kotlinx.coroutines.experimental.rx1
 
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.MatcherAssert.assertThat
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.hamcrest.core.IsNull
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-import rx.Observable
-import kotlin.coroutines.experimental.CoroutineContext
+import org.hamcrest.MatcherAssert.*
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.runner.*
+import org.junit.runners.*
+import rx.*
+import kotlin.coroutines.experimental.*
 
 @RunWith(Parameterized::class)
 class IntegrationTest(
diff --git a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableBackpressureTest.kt b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableBackpressureTest.kt
index 9213c72..0a0a361 100644
--- a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableBackpressureTest.kt
+++ b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableBackpressureTest.kt
@@ -16,11 +16,10 @@
 
 package kotlinx.coroutines.experimental.rx1
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.junit.Test
-import rx.Subscriber
+import kotlinx.coroutines.experimental.*
+import org.junit.*
+import rx.*
+import kotlin.coroutines.experimental.*
 
 class ObservableBackpressureTest : TestBase() {
     @Test
diff --git a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableSubscriptionSelectTest.kt b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableSubscriptionSelectTest.kt
index 49e7abf..960d676 100644
--- a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableSubscriptionSelectTest.kt
+++ b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableSubscriptionSelectTest.kt
@@ -22,6 +22,7 @@
 import org.junit.Assert.*
 import org.junit.runner.*
 import org.junit.runners.*
+import kotlin.coroutines.experimental.*
 
 @RunWith(Parameterized::class)
 class ObservableSubscriptionSelectTest(val request: Int) : TestBase() {
diff --git a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableTest.kt b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableTest.kt
index 203d936..cc28bf2 100644
--- a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableTest.kt
+++ b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/ObservableTest.kt
@@ -16,13 +16,10 @@
 
 package kotlinx.coroutines.experimental.rx1
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.junit.Assert
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import org.hamcrest.core.*
+import org.junit.*
+import kotlin.coroutines.experimental.*
 
 class ObservableTest : TestBase() {
     @Test
diff --git a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/SingleTest.kt b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/SingleTest.kt
index 4953657..23a63b6 100644
--- a/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/SingleTest.kt
+++ b/reactive/kotlinx-coroutines-rx1/src/test/kotlin/kotlinx/coroutines/experimental/rx1/SingleTest.kt
@@ -17,16 +17,13 @@
 package kotlinx.coroutines.experimental.rx1
 
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.hamcrest.core.IsNull
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertThat
-import org.junit.Before
-import org.junit.Test
-import rx.Observable
-import rx.Single
-import java.util.concurrent.TimeUnit
+import kotlinx.coroutines.experimental.CancellationException
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import rx.*
+import java.util.concurrent.*
+import kotlin.coroutines.experimental.*
 
 /**
  * Tests emitting single item with [rxSingle].
diff --git a/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxCompletable.kt b/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxCompletable.kt
index eb94ab6..114e185 100644
--- a/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxCompletable.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxCompletable.kt
@@ -33,7 +33,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  * 
diff --git a/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxFlowable.kt b/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxFlowable.kt
index d4cb3c2..a140485 100644
--- a/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxFlowable.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxFlowable.kt
@@ -23,8 +23,7 @@
 import kotlinx.coroutines.experimental.Job
 import kotlinx.coroutines.experimental.channels.ProducerScope
 import kotlinx.coroutines.experimental.reactive.publish
-import kotlin.coroutines.experimental.ContinuationInterceptor
-import kotlin.coroutines.experimental.CoroutineContext
+import kotlin.coroutines.experimental.*
 
 /**
  * Creates cold [flowable][Flowable] that will run a given [block] in a coroutine.
@@ -42,7 +41,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [DefaultDispatcher] is used.
  *
diff --git a/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxMaybe.kt b/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxMaybe.kt
index 391107e..e83be12 100644
--- a/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxMaybe.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxMaybe.kt
@@ -34,7 +34,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
diff --git a/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxObservable.kt b/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxObservable.kt
index ba7c170..0251495 100644
--- a/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxObservable.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxObservable.kt
@@ -41,7 +41,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
@@ -133,7 +133,7 @@
         } catch (e: Throwable) {
             try {
                 if (!cancel(e))
-                    handleCoroutineException(coroutineContext, e)
+                    handleCoroutineException(context, e)
             } finally {
                 doLockedSignalCompleted()
             }
@@ -163,7 +163,7 @@
                     else
                         subscriber.onComplete()
                 } catch (e: Throwable) {
-                    handleCoroutineException(coroutineContext, e)
+                    handleCoroutineException(context, e)
                 }
             }
         } finally {
diff --git a/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxSingle.kt b/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxSingle.kt
index ed214fd..6e63cdb 100644
--- a/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxSingle.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/main/kotlin/kotlinx/coroutines/experimental/rx2/RxSingle.kt
@@ -33,7 +33,7 @@
  *
  * The [context] for the new coroutine can be explicitly specified.
  * See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
- * The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
+ * The [coroutineContext] of the parent coroutine may be used,
  * in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
  * The parent job may be also explicitly specified using [parent] parameter.
  *
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-01.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-01.kt
index 79dd6af..9f4f3b2 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-01.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-01.kt
@@ -19,6 +19,7 @@
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     // create a channel that produces numbers from 1 to 3 with 200ms delays between them
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-02.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-02.kt
index c8279a7..175fdf4 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-02.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-02.kt
@@ -19,6 +19,7 @@
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     // create a publisher that produces numbers from 1 to 3 with 200ms delays between them
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-03.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-03.kt
index df620eb..2431f62 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-03.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-03.kt
@@ -20,6 +20,7 @@
 import io.reactivex.*
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     val source = Flowable.range(1, 5) // a range of five numbers
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-04.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-04.kt
index f41348a..85fcf31 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-04.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-04.kt
@@ -20,6 +20,7 @@
 import io.reactivex.*
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     val source = Flowable.range(1, 5) // a range of five numbers
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-05.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-05.kt
index 7528b4e..5f96bd3 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-05.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-05.kt
@@ -17,9 +17,10 @@
 // This file was automatically generated from coroutines-guide-reactive.md by Knit tool. Do not edit.
 package guide.reactive.basic.example05
 
+import io.reactivex.schedulers.*
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.rx2.rxFlowable
-import io.reactivex.schedulers.Schedulers
+import kotlinx.coroutines.experimental.rx2.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> { 
     // coroutine -- fast producer of elements in the context of the main thread
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-08.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-08.kt
index dc78fff..78bcee3 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-08.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-08.kt
@@ -17,11 +17,10 @@
 // This file was automatically generated from coroutines-guide-reactive.md by Knit tool. Do not edit.
 package guide.reactive.basic.example08
 
-import io.reactivex.subjects.BehaviorSubject
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.rx2.consumeEach
-import kotlinx.coroutines.experimental.yield
+import io.reactivex.subjects.*
+import kotlinx.coroutines.experimental.*
+import kotlinx.coroutines.experimental.rx2.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     val subject = BehaviorSubject.create<String>()
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-09.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-09.kt
index 34f88e3..3b48ac2 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-09.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-basic-09.kt
@@ -17,11 +17,9 @@
 // This file was automatically generated from coroutines-guide-reactive.md by Knit tool. Do not edit.
 package guide.reactive.basic.example09
 
-import kotlinx.coroutines.experimental.channels.ConflatedBroadcastChannel
-import kotlinx.coroutines.experimental.channels.consumeEach
-import kotlinx.coroutines.experimental.launch
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
+import kotlinx.coroutines.experimental.channels.*
+import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
     val broadcast = ConflatedBroadcastChannel<String>()
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-02.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-02.kt
index 97b6ac2..78cd943 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-02.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-02.kt
@@ -19,8 +19,8 @@
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
-import org.reactivestreams.Publisher
-import kotlin.coroutines.experimental.CoroutineContext
+import org.reactivestreams.*
+import kotlin.coroutines.experimental.*
 
 fun <T, R> Publisher<T>.fusedFilterMap(
     context: CoroutineContext,   // the context to execute this coroutine in
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-03.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-03.kt
index 160840d..bd6d72d 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-03.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-03.kt
@@ -19,9 +19,9 @@
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
-import org.reactivestreams.Publisher
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlinx.coroutines.experimental.selects.whileSelect
+import kotlinx.coroutines.experimental.selects.*
+import org.reactivestreams.*
+import kotlin.coroutines.experimental.*
 
 fun <T, U> Publisher<T>.takeUntil(context: CoroutineContext, other: Publisher<U>) = publish<T>(context) {
     this@takeUntil.openSubscription().use { thisChannel -> // explicitly open channel to Publisher<T>
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-04.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-04.kt
index 5725b26..da8c1b5 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-04.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/guide/example-reactive-operators-04.kt
@@ -19,8 +19,8 @@
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.reactive.*
-import org.reactivestreams.Publisher
-import kotlin.coroutines.experimental.CoroutineContext
+import org.reactivestreams.*
+import kotlin.coroutines.experimental.*
 
 fun <T> Publisher<Publisher<T>>.merge(context: CoroutineContext) = publish<T>(context) {
   consumeEach { pub ->                 // for each publisher received on the source channel
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/CompletableTest.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/CompletableTest.kt
index 59e928a..8e8d0ef 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/CompletableTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/CompletableTest.kt
@@ -16,13 +16,11 @@
 
 package kotlinx.coroutines.experimental.rx2
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.junit.Assert.assertThat
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class CompletableTest : TestBase() {
     @Test
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ConvertTest.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ConvertTest.kt
index a16cf5f..d3315a2 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ConvertTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ConvertTest.kt
@@ -17,10 +17,10 @@
 package kotlinx.coroutines.experimental.rx2
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.channels.produce
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertNull
-import org.junit.Test
+import kotlinx.coroutines.experimental.channels.*
+import org.junit.*
+import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class ConvertTest : TestBase() {
     class TestException(s: String): RuntimeException(s)
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/FlowableTest.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/FlowableTest.kt
index 82e4a76..1777dc1 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/FlowableTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/FlowableTest.kt
@@ -16,13 +16,10 @@
 
 package kotlinx.coroutines.experimental.rx2
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.junit.Assert
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import org.hamcrest.core.*
+import org.junit.*
+import kotlin.coroutines.experimental.*
 
 class FlowableTest : TestBase() {
     @Test
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/IntegrationTest.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/IntegrationTest.kt
index 905278d..0b00b27 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/IntegrationTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/IntegrationTest.kt
@@ -16,16 +16,14 @@
 
 package kotlinx.coroutines.experimental.rx2
 
-import io.reactivex.Observable
+import io.reactivex.*
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.MatcherAssert.assertThat
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.hamcrest.core.IsNull
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-import kotlin.coroutines.experimental.CoroutineContext
+import org.hamcrest.MatcherAssert.*
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.runner.*
+import org.junit.runners.*
+import kotlin.coroutines.experimental.*
 
 @RunWith(Parameterized::class)
 class IntegrationTest(
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/MaybeTest.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/MaybeTest.kt
index 451c0fb..9eeec99 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/MaybeTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/MaybeTest.kt
@@ -16,20 +16,15 @@
 
 package kotlinx.coroutines.experimental.rx2
 
-import io.reactivex.Maybe
-import io.reactivex.Observable
-import io.reactivex.functions.Action
-import io.reactivex.internal.functions.Functions.ON_ERROR_MISSING
-import io.reactivex.internal.functions.Functions.emptyConsumer
+import io.reactivex.*
+import io.reactivex.functions.*
+import io.reactivex.internal.functions.Functions.*
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.junit.Assert
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertNull
-import org.junit.Before
-import org.junit.Test
-import java.util.concurrent.TimeUnit
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import java.util.concurrent.*
+import kotlin.coroutines.experimental.*
 
 class MaybeTest : TestBase() {
     @Before
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ObservableSubscriptionSelectTest.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ObservableSubscriptionSelectTest.kt
index 24c31af..68d7069 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ObservableSubscriptionSelectTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ObservableSubscriptionSelectTest.kt
@@ -20,6 +20,7 @@
 import kotlinx.coroutines.experimental.selects.*
 import org.junit.*
 import org.junit.Assert.*
+import kotlin.coroutines.experimental.*
 
 class ObservableSubscriptionSelectTest() : TestBase() {
     @Test
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ObservableTest.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ObservableTest.kt
index a2c4c5d..ac2e9eb 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ObservableTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/ObservableTest.kt
@@ -16,13 +16,10 @@
 
 package kotlinx.coroutines.experimental.rx2
 
-import kotlinx.coroutines.experimental.TestBase
-import kotlinx.coroutines.experimental.runBlocking
-import kotlinx.coroutines.experimental.yield
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.junit.Assert
-import org.junit.Test
+import kotlinx.coroutines.experimental.*
+import org.hamcrest.core.*
+import org.junit.*
+import kotlin.coroutines.experimental.*
 
 class ObservableTest : TestBase() {
     @Test
diff --git a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/SingleTest.kt b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/SingleTest.kt
index d7f4a0d..226d869 100644
--- a/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/SingleTest.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/test/kotlin/kotlinx/coroutines/experimental/rx2/SingleTest.kt
@@ -16,16 +16,13 @@
 
 package kotlinx.coroutines.experimental.rx2
 
-import io.reactivex.Observable
-import io.reactivex.Single
+import io.reactivex.*
 import kotlinx.coroutines.experimental.*
-import org.hamcrest.core.IsEqual
-import org.hamcrest.core.IsInstanceOf
-import org.junit.Assert
-import org.junit.Assert.assertEquals
-import org.junit.Before
-import org.junit.Test
-import java.util.concurrent.TimeUnit
+import org.hamcrest.core.*
+import org.junit.*
+import org.junit.Assert.*
+import java.util.concurrent.*
+import kotlin.coroutines.experimental.*
 
 /**
  * Tests emitting single item with [rxSingle].
diff --git a/settings.gradle b/settings.gradle
index b7657f3..ebe9b16 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,48 +1,41 @@
 rootProject.name = 'kotlinx.coroutines'
 
-include 'kotlinx-coroutines-core-common'
+def module(String path) {
+    int i = path.lastIndexOf('/')
+    def name = path.substring(i + 1)
+    include(name)
+    project(":$name").projectDir = file(path)
+}
 
-include 'kotlinx-coroutines-core'
-include 'kotlinx-coroutines-io'
+// ---------------------------
 
-include 'kotlinx-coroutines-guava'
-include 'kotlinx-coroutines-jdk8'
-include 'kotlinx-coroutines-nio'
-include 'kotlinx-coroutines-quasar'
+include('benchmarks')
+include('knit')
+include('site')
 
-include 'kotlinx-coroutines-reactive'
-include 'kotlinx-coroutines-reactor'
-include 'kotlinx-coroutines-rx1'
-include 'kotlinx-coroutines-rx2'
-include 'kotlinx-coroutines-rx-example'
+module('common/kotlinx-coroutines-core-common')
 
-include 'kotlinx-coroutines-android'
-include 'kotlinx-coroutines-javafx'
-include 'kotlinx-coroutines-swing'
+module('core/kotlinx-coroutines-core')
+module('core/kotlinx-coroutines-io')
 
-include 'kotlinx-coroutines-core-js'
-include 'js-stub'
-include 'example-frontend-js'
+module('integration/kotlinx-coroutines-guava')
+module('integration/kotlinx-coroutines-jdk8')
+module('integration/kotlinx-coroutines-nio')
+module('integration/kotlinx-coroutines-quasar')
 
-include 'benchmarks'
-include 'knit'
-include 'site'
+module('reactive/kotlinx-coroutines-reactive')
+module('reactive/kotlinx-coroutines-reactor')
+module('reactive/kotlinx-coroutines-rx1')
+module('reactive/kotlinx-coroutines-rx2')
+module('reactive/kotlinx-coroutines-rx-example')
 
-project(':kotlinx-coroutines-core-common').projectDir = file('common/kotlinx-coroutines-core-common')
-project(':kotlinx-coroutines-core').projectDir = file('core/kotlinx-coroutines-core')
-project(':kotlinx-coroutines-io').projectDir = file('core/kotlinx-coroutines-io')
-project(':kotlinx-coroutines-guava').projectDir = file('integration/kotlinx-coroutines-guava')
-project(':kotlinx-coroutines-jdk8').projectDir = file('integration/kotlinx-coroutines-jdk8')
-project(':kotlinx-coroutines-nio').projectDir = file('integration/kotlinx-coroutines-nio')
-project(':kotlinx-coroutines-quasar').projectDir = file('integration/kotlinx-coroutines-quasar')
-project(':kotlinx-coroutines-reactive').projectDir = file('reactive/kotlinx-coroutines-reactive')
-project(':kotlinx-coroutines-reactor').projectDir = file('reactive/kotlinx-coroutines-reactor')
-project(':kotlinx-coroutines-rx1').projectDir = file('reactive/kotlinx-coroutines-rx1')
-project(':kotlinx-coroutines-rx2').projectDir = file('reactive/kotlinx-coroutines-rx2')
-project(':kotlinx-coroutines-rx-example').projectDir = file('reactive/kotlinx-coroutines-rx-example')
-project(':kotlinx-coroutines-android').projectDir = file('ui/kotlinx-coroutines-android')
-project(':kotlinx-coroutines-javafx').projectDir = file('ui/kotlinx-coroutines-javafx')
-project(':kotlinx-coroutines-swing').projectDir = file('ui/kotlinx-coroutines-swing')
-project(':kotlinx-coroutines-core-js').projectDir = file('js/kotlinx-coroutines-core-js')
-project(':js-stub').projectDir = file('js/js-stub')
-project(':example-frontend-js').projectDir = file('js/example-frontend-js')
+module('ui/kotlinx-coroutines-android')
+module('ui/kotlinx-coroutines-javafx')
+module('ui/kotlinx-coroutines-swing')
+
+module('js/kotlinx-coroutines-core-js')
+module('js/js-stub')
+module('js/example-frontend-js')
+
+//module('native/kotlinx-coroutines-core-native')
+
diff --git a/ui/kotlinx-coroutines-android/animation-app/app/build.gradle b/ui/kotlinx-coroutines-android/animation-app/app/build.gradle
index 380734c..a32834e 100644
--- a/ui/kotlinx-coroutines-android/animation-app/app/build.gradle
+++ b/ui/kotlinx-coroutines-android/animation-app/app/build.gradle
@@ -3,11 +3,11 @@
 apply plugin: 'kotlin-android-extensions'
 
 android {
-    compileSdkVersion 26
+    compileSdkVersion 27
     defaultConfig {
         applicationId "org.jetbrains.kotlinx.animation"
         minSdkVersion 15
-        targetSdkVersion 26
+        targetSdkVersion 27
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -21,12 +21,11 @@
 }
 
 dependencies {
-    implementation fileTree(dir: 'libs', include: ['*.jar'])
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
-    implementation 'com.android.support:appcompat-v7:26.1.0'
+    implementation 'com.android.support:appcompat-v7:27.1.1'
     implementation 'com.android.support.constraint:constraint-layout:1.0.2'
-    implementation 'com.android.support:design:26.1.0'
-    implementation "android.arch.lifecycle:extensions:1.0.0"
+    implementation 'com.android.support:design:27.1.1'
+    implementation "android.arch.lifecycle:extensions:1.1.1"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
 
diff --git a/ui/kotlinx-coroutines-android/animation-app/build.gradle b/ui/kotlinx-coroutines-android/animation-app/build.gradle
index cd617a0..53e4101 100644
--- a/ui/kotlinx-coroutines-android/animation-app/build.gradle
+++ b/ui/kotlinx-coroutines-android/animation-app/build.gradle
@@ -6,7 +6,7 @@
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.0.0'
+        classpath 'com.android.tools.build:gradle:3.1.0'
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 
         // NOTE: Do not place your application dependencies here; they belong
diff --git a/ui/kotlinx-coroutines-android/animation-app/gradle.properties b/ui/kotlinx-coroutines-android/animation-app/gradle.properties
index dae0861..843a982 100644
--- a/ui/kotlinx-coroutines-android/animation-app/gradle.properties
+++ b/ui/kotlinx-coroutines-android/animation-app/gradle.properties
@@ -18,6 +18,6 @@
 
 kotlin.coroutines=enable
 
-kotlin_version = 1.2.21
+kotlin_version = 1.2.31
 coroutines_version = 0.22.5
 
diff --git a/ui/kotlinx-coroutines-android/example-app/app/build.gradle b/ui/kotlinx-coroutines-android/example-app/app/build.gradle
index ef715c4..e643075 100644
--- a/ui/kotlinx-coroutines-android/example-app/app/build.gradle
+++ b/ui/kotlinx-coroutines-android/example-app/app/build.gradle
@@ -3,12 +3,12 @@
 apply plugin: 'kotlin-android-extensions'
 
 android {
-    compileSdkVersion 25
-    buildToolsVersion '26.0.2'
+    compileSdkVersion 27
+    buildToolsVersion '27.0.3'
     defaultConfig {
         applicationId "com.example.app"
-        minSdkVersion 9
-        targetSdkVersion 25
+        minSdkVersion 14
+        targetSdkVersion 27
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -22,14 +22,13 @@
 }
 
 dependencies {
-    compile fileTree(dir: 'libs', include: ['*.jar'])
+    compile 'com.android.support:appcompat-v7:27.1.1'
+    compile 'com.android.support.constraint:constraint-layout:1.0.2'
+    compile 'com.android.support:design:27.1.1'
+    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+    compile "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
+    testCompile 'junit:junit:4.12'
     androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
         exclude group: 'com.android.support', module: 'support-annotations'
     })
-    compile 'com.android.support:appcompat-v7:25.4.0'
-    compile 'com.android.support.constraint:constraint-layout:1.0.2'
-    compile 'com.android.support:design:25.4.0'
-    testCompile 'junit:junit:4.12'
-    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
-    compile "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
 }
diff --git a/ui/kotlinx-coroutines-android/example-app/app/src/main/java/com/example/app/MainActivity.kt b/ui/kotlinx-coroutines-android/example-app/app/src/main/java/com/example/app/MainActivity.kt
index 9f04427..fc1cdbf 100644
--- a/ui/kotlinx-coroutines-android/example-app/app/src/main/java/com/example/app/MainActivity.kt
+++ b/ui/kotlinx-coroutines-android/example-app/app/src/main/java/com/example/app/MainActivity.kt
@@ -10,6 +10,7 @@
 import kotlinx.android.synthetic.main.content_main.*
 
 class MainActivity : AppCompatActivity() {
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_main)
diff --git a/ui/kotlinx-coroutines-android/example-app/build.gradle b/ui/kotlinx-coroutines-android/example-app/build.gradle
index cd617a0..53e4101 100644
--- a/ui/kotlinx-coroutines-android/example-app/build.gradle
+++ b/ui/kotlinx-coroutines-android/example-app/build.gradle
@@ -6,7 +6,7 @@
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.0.0'
+        classpath 'com.android.tools.build:gradle:3.1.0'
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 
         // NOTE: Do not place your application dependencies here; they belong
diff --git a/ui/kotlinx-coroutines-android/example-app/gradle.properties b/ui/kotlinx-coroutines-android/example-app/gradle.properties
index dae0861..843a982 100644
--- a/ui/kotlinx-coroutines-android/example-app/gradle.properties
+++ b/ui/kotlinx-coroutines-android/example-app/gradle.properties
@@ -18,6 +18,6 @@
 
 kotlin.coroutines=enable
 
-kotlin_version = 1.2.21
+kotlin_version = 1.2.31
 coroutines_version = 0.22.5
 
diff --git a/ui/kotlinx-coroutines-android/example-app/gradle/wrapper/gradle-wrapper.properties b/ui/kotlinx-coroutines-android/example-app/gradle/wrapper/gradle-wrapper.properties
index 9a0efbe..485ca2c 100644
--- a/ui/kotlinx-coroutines-android/example-app/gradle/wrapper/gradle-wrapper.properties
+++ b/ui/kotlinx-coroutines-android/example-app/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sun Nov 05 23:56:59 MSK 2017
+#Sun Apr 08 03:14:27 CEST 2018
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip