• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.coroutines
6 
7 import kotlin.browser.*
8 import kotlin.coroutines.*
9 
10 private external val navigator: dynamic
11 private const val UNDEFINED = "undefined"
12 internal external val process: dynamic
13 
createDefaultDispatchernull14 internal actual fun createDefaultDispatcher(): CoroutineDispatcher = when {
15     // Check if we are running under ReactNative. We have to use NodeDispatcher under it.
16     // The problem is that ReactNative has a `window` object with `addEventListener`, but it does not  really work.
17     // For details see https://github.com/Kotlin/kotlinx.coroutines/issues/236
18     // The check for ReactNative is based on https://github.com/facebook/react-native/commit/3c65e62183ce05893be0822da217cb803b121c61
19     jsTypeOf(navigator) != UNDEFINED && navigator != null && navigator.product == "ReactNative" ->
20         NodeDispatcher
21     // Check if we are running under jsdom. WindowDispatcher doesn't work under jsdom because it accesses MessageEvent#source.
22     // It is not implemented in jsdom, see https://github.com/jsdom/jsdom/blob/master/Changelog.md
23     // "It's missing a few semantics, especially around origins, as well as MessageEvent source."
24     isJsdom() -> NodeDispatcher
25     // Check if we are in the browser and must use window.postMessage to avoid setTimeout throttling
26     jsTypeOf(window) != UNDEFINED && window.asDynamic() != null && jsTypeOf(window.asDynamic().addEventListener) != UNDEFINED ->
27         window.asCoroutineDispatcher()
28     // If process is undefined (e.g. in NativeScript, #1404), use SetTimeout-based dispatcher
29     jsTypeOf(process) == UNDEFINED -> SetTimeoutDispatcher
30     // Fallback to NodeDispatcher when browser environment is not detected
31     else -> NodeDispatcher
32 }
33 
isJsdomnull34 private fun isJsdom() = jsTypeOf(navigator) != UNDEFINED &&
35     navigator != null &&
36     navigator.userAgent != null &&
37     jsTypeOf(navigator.userAgent) != UNDEFINED &&
38     jsTypeOf(navigator.userAgent.match) != UNDEFINED &&
39     navigator.userAgent.match("\\bjsdom\\b")
40 
41 internal actual val DefaultDelay: Delay
42     get() = Dispatchers.Default as Delay
43 
44 public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext {
45     val combined = coroutineContext + context
46     return if (combined !== Dispatchers.Default && combined[ContinuationInterceptor] == null)
47         combined + Dispatchers.Default else combined
48 }
49 
50 // No debugging facilities on JS
withCoroutineContextnull51 internal actual inline fun <T> withCoroutineContext(context: CoroutineContext, countOrElement: Any?, block: () -> T): T = block()
52 internal actual fun Continuation<*>.toDebugString(): String = toString()
53 internal actual val CoroutineContext.coroutineName: String? get() = null // not supported on JS
54