js_utils.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. //go:build js && wasm
  4. // +build js,wasm
  5. package webrtc
  6. import (
  7. "fmt"
  8. "syscall/js"
  9. )
  10. // awaitPromise accepts a js.Value representing a Promise. If the promise
  11. // resolves, it returns (result, nil). If the promise rejects, it returns
  12. // (js.Undefined, error). awaitPromise has a synchronous-like API but does not
  13. // block the JavaScript event loop.
  14. func awaitPromise(promise js.Value) (js.Value, error) {
  15. resultsChan := make(chan js.Value)
  16. errChan := make(chan js.Error)
  17. thenFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  18. go func() {
  19. resultsChan <- args[0]
  20. }()
  21. return js.Undefined()
  22. })
  23. defer thenFunc.Release()
  24. catchFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  25. go func() {
  26. errChan <- js.Error{args[0]}
  27. }()
  28. return js.Undefined()
  29. })
  30. defer catchFunc.Release()
  31. promise.Call("then", thenFunc).Call("catch", catchFunc)
  32. select {
  33. case result := <-resultsChan:
  34. return result, nil
  35. case err := <-errChan:
  36. return js.Undefined(), err
  37. }
  38. }
  39. func valueToUint16Pointer(val js.Value) *uint16 {
  40. if val.IsNull() || val.IsUndefined() {
  41. return nil
  42. }
  43. convertedVal := uint16(val.Int())
  44. return &convertedVal
  45. }
  46. func valueToStringPointer(val js.Value) *string {
  47. if val.IsNull() || val.IsUndefined() {
  48. return nil
  49. }
  50. stringVal := val.String()
  51. return &stringVal
  52. }
  53. func stringToValueOrUndefined(val string) js.Value {
  54. if val == "" {
  55. return js.Undefined()
  56. }
  57. return js.ValueOf(val)
  58. }
  59. func uint8ToValueOrUndefined(val uint8) js.Value {
  60. if val == 0 {
  61. return js.Undefined()
  62. }
  63. return js.ValueOf(val)
  64. }
  65. func interfaceToValueOrUndefined(val interface{}) js.Value {
  66. if val == nil {
  67. return js.Undefined()
  68. }
  69. return js.ValueOf(val)
  70. }
  71. func valueToStringOrZero(val js.Value) string {
  72. if val.IsUndefined() || val.IsNull() {
  73. return ""
  74. }
  75. return val.String()
  76. }
  77. func valueToUint8OrZero(val js.Value) uint8 {
  78. if val.IsUndefined() || val.IsNull() {
  79. return 0
  80. }
  81. return uint8(val.Int())
  82. }
  83. func valueToUint16OrZero(val js.Value) uint16 {
  84. if val.IsNull() || val.IsUndefined() {
  85. return 0
  86. }
  87. return uint16(val.Int())
  88. }
  89. func valueToUint32OrZero(val js.Value) uint32 {
  90. if val.IsNull() || val.IsUndefined() {
  91. return 0
  92. }
  93. return uint32(val.Int())
  94. }
  95. func valueToStrings(val js.Value) []string {
  96. result := make([]string, val.Length())
  97. for i := 0; i < val.Length(); i++ {
  98. result[i] = val.Index(i).String()
  99. }
  100. return result
  101. }
  102. func stringPointerToValue(val *string) js.Value {
  103. if val == nil {
  104. return js.Undefined()
  105. }
  106. return js.ValueOf(*val)
  107. }
  108. func uint16PointerToValue(val *uint16) js.Value {
  109. if val == nil {
  110. return js.Undefined()
  111. }
  112. return js.ValueOf(*val)
  113. }
  114. func boolPointerToValue(val *bool) js.Value {
  115. if val == nil {
  116. return js.Undefined()
  117. }
  118. return js.ValueOf(*val)
  119. }
  120. func stringsToValue(strings []string) js.Value {
  121. val := make([]interface{}, len(strings))
  122. for i, s := range strings {
  123. val[i] = s
  124. }
  125. return js.ValueOf(val)
  126. }
  127. func stringEnumToValueOrUndefined(s string) js.Value {
  128. if s == "unknown" {
  129. return js.Undefined()
  130. }
  131. return js.ValueOf(s)
  132. }
  133. // Converts the return value of recover() to an error.
  134. func recoveryToError(e interface{}) error {
  135. switch e := e.(type) {
  136. case error:
  137. return e
  138. default:
  139. return fmt.Errorf("recovered with non-error value: (%T) %s", e, e)
  140. }
  141. }
  142. func uint8ArrayValueToBytes(val js.Value) []byte {
  143. result := make([]byte, val.Length())
  144. js.CopyBytesToGo(result, val)
  145. return result
  146. }