/*
 * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

@file:OptIn(ExperimentalWasmJsInterop::class)

package kotlin.wasm.internal

@Suppress("unused") // references could be presented in a code generated by the compiler
internal fun throwValue(t: Throwable): Nothing {
    val v = if (t is JsException) t.thrownValue else t.jsError
    jsThrow(v)
    throw0(v)
}

// If WebAssembly.JSTag is going to be used for wasm exceptions, use a helper function throwing an exception from JS.
// It's required to work around [an issue in JavaScriptCore](https://bugs.webkit.org/show_bug.cgi?id=297134)
// Otherwise, an empty function is provided, and exceptions will be thrown from wasm code.
@JsFun("typeof wasmJsTag !== 'undefined' && wasmTag === wasmJsTag ? (e) => { throw e; } : () => {}")
internal external fun jsThrow(e: JsAny?)

@ExcludedFromCodegen
internal fun throw0(v: JsAny?): Nothing = implementedAsIntrinsic

@Suppress("unused") // references could be presented in a code generated by the compiler
internal fun getKotlinException(v: JsAny?): Throwable {
    return (v as? JsError)?.kotlinException?.get() ?: JsException(v)
}

@Deprecated("Don't use. To be removed after bootstrap.", level = DeprecationLevel.ERROR)
@Suppress("UNUSED_PARAMETER") // TODO: Remove after bootstrap update
private fun throwJsError(message: String?, wasmTypeName: String?, stack: ExternalInterfaceType?): Nothing {
    js("""
    const error = new Error();
    error.message = message;
    error.name = wasmTypeName;
    error.stack = stack;
    throw error;
    """)
}

@Deprecated("Don't use. To be removed after bootstrap.", level = DeprecationLevel.ERROR)
@Suppress("DEPRECATION_ERROR")
internal fun throwAsJsException(t: Throwable): Nothing {
    throwJsError(t.message, getSimpleName(wasmGetObjectRtti(t)), t.jsStack)
}

@Deprecated("Don't use. To be removed after bootstrap.", level = DeprecationLevel.ERROR)
internal fun createJsException(jsError: JsAny) = JsException(jsError)
