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 createDefaultDispatchernull14internal 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 isJsdomnull34private 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 withCoroutineContextnull51internal 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