react-native-worklets 0.7.2 → 0.8.0-bundle-mode-preview-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Common/cpp/worklets/NativeModules/JSIWorkletsModuleProxy.cpp +32 -28
- package/Common/cpp/worklets/NativeModules/JSIWorkletsModuleProxy.h +13 -5
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp +7 -5
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h +5 -4
- package/Common/cpp/worklets/Resources/SynchronizableUnpacker.cpp +5 -5
- package/Common/cpp/worklets/RunLoop/AsyncQueueImpl.cpp +42 -19
- package/Common/cpp/worklets/RunLoop/AsyncQueueImpl.h +2 -0
- package/Common/cpp/worklets/Tools/Defs.h +2 -2
- package/Common/cpp/worklets/Tools/ScriptBuffer.h +34 -0
- package/Common/cpp/worklets/WorkletRuntime/RuntimeBindings.h +24 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp +11 -6
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp +82 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.h +12 -0
- package/RNWorklets.podspec +15 -14
- package/android/CMakeLists.txt +8 -2
- package/android/build.gradle +92 -56
- package/android/src/main/cpp/worklets/android/JScriptBufferWrapper.cpp +67 -0
- package/android/src/main/cpp/worklets/android/JScriptBufferWrapper.h +48 -0
- package/android/src/main/cpp/worklets/android/JWorkletRuntimeWrapper.cpp +52 -0
- package/android/src/main/cpp/worklets/android/JWorkletRuntimeWrapper.h +43 -0
- package/android/src/main/cpp/worklets/android/WorkletsModule.cpp +115 -19
- package/android/src/main/cpp/worklets/android/WorkletsModule.h +11 -13
- package/android/src/main/cpp/worklets/android/WorkletsOnLoad.cpp +6 -0
- package/android/src/main/java/com/swmansion/worklets/ScriptBufferWrapper.java +88 -0
- package/android/src/networking/com/swmansion/worklets/WorkletRuntimeWrapper.kt +23 -0
- package/android/src/networking/com/swmansion/worklets/WorkletsHeaderUtil.kt +30 -0
- package/android/src/{legacyBundling → networking}/com/swmansion/worklets/WorkletsModule.java +52 -2
- package/android/src/networking/com/swmansion/worklets/WorkletsNetworkEventUtil.kt +268 -0
- package/android/src/networking/com/swmansion/worklets/WorkletsNetworking.kt +1084 -0
- package/android/src/networking/com/swmansion/worklets/WorkletsOkHttpCallUtil.kt +37 -0
- package/android/src/networking/com/swmansion/worklets/WorkletsProgressListener.kt +9 -0
- package/android/src/networking/com/swmansion/worklets/WorkletsProgressRequestBody.kt +98 -0
- package/android/src/networking/com/swmansion/worklets/WorkletsProgressResponseBody.kt +57 -0
- package/android/src/networking/com/swmansion/worklets/WorkletsProgressiveStringDecoder.kt +82 -0
- package/android/src/networking/com/swmansion/worklets/WorkletsRequestBodyUtil.kt +177 -0
- package/android/src/{experimentalBundling → no-networking}/com/swmansion/worklets/WorkletsModule.java +10 -15
- package/apple/worklets/apple/Networking/WorkletsNetworking.h +22 -0
- package/apple/worklets/apple/Networking/WorkletsNetworking.mm +706 -0
- package/apple/worklets/apple/WorkletsModule.mm +56 -17
- package/bundleMode/index.js +2 -6
- package/compatibility.json +4 -1
- package/lib/module/WorkletsModule/NativeWorklets.native.js +8 -2
- package/lib/module/WorkletsModule/NativeWorklets.native.js.map +1 -1
- package/lib/module/bundleMode/metroOverrides.native.js +115 -0
- package/lib/module/bundleMode/metroOverrides.native.js.map +1 -0
- package/lib/module/bundleMode/network.native.js +41 -0
- package/lib/module/bundleMode/network.native.js.map +1 -0
- package/lib/module/debug/jsVersion.js +1 -1
- package/lib/module/debug/jsVersion.js.map +1 -1
- package/lib/module/featureFlags/staticFlags.json +2 -0
- package/lib/module/featureFlags/types.js +3 -1
- package/lib/module/featureFlags/types.js.map +1 -1
- package/lib/module/index.js +4 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/initializers/initializers.native.js +24 -50
- package/lib/module/initializers/initializers.native.js.map +1 -1
- package/lib/module/initializers/workletRuntimeEntry.native.js +3 -3
- package/lib/module/initializers/workletRuntimeEntry.native.js.map +1 -1
- package/lib/module/memory/bundleUnpacker.native.js +2 -2
- package/lib/module/memory/bundleUnpacker.native.js.map +1 -1
- package/lib/module/memory/serializable.native.js +3 -3
- package/lib/module/memory/serializable.native.js.map +1 -1
- package/lib/module/memory/synchronizableUnpacker.native.js +3 -3
- package/lib/module/memory/synchronizableUnpacker.native.js.map +1 -1
- package/lib/module/platformChecker.js +2 -2
- package/lib/module/platformChecker.js.map +1 -1
- package/lib/module/runtimeKind.js +51 -0
- package/lib/module/runtimeKind.js.map +1 -1
- package/lib/module/runtimes.js +3 -0
- package/lib/module/runtimes.js.map +1 -1
- package/lib/module/runtimes.native.js +34 -3
- package/lib/module/runtimes.native.js.map +1 -1
- package/lib/module/threads.native.js +2 -2
- package/lib/module/threads.native.js.map +1 -1
- package/lib/typescript/WorkletsModule/NativeWorklets.native.d.ts.map +1 -1
- package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts +2 -1
- package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts.map +1 -1
- package/lib/typescript/bundleMode/metroOverrides.native.d.ts +28 -0
- package/lib/typescript/bundleMode/metroOverrides.native.d.ts.map +1 -0
- package/lib/typescript/bundleMode/network.native.d.ts +7 -0
- package/lib/typescript/bundleMode/network.native.d.ts.map +1 -0
- package/lib/typescript/debug/jsVersion.d.ts +1 -1
- package/lib/typescript/debug/jsVersion.d.ts.map +1 -1
- package/lib/typescript/featureFlags/types.d.ts +3 -1
- package/lib/typescript/featureFlags/types.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/initializers/initializers.native.d.ts +1 -0
- package/lib/typescript/initializers/initializers.native.d.ts.map +1 -1
- package/lib/typescript/initializers/workletRuntimeEntry.native.d.ts +1 -1
- package/lib/typescript/memory/bundleUnpacker.native.d.ts.map +1 -1
- package/lib/typescript/memory/synchronizableUnpacker.native.d.ts.map +1 -1
- package/lib/typescript/platformChecker.d.ts.map +1 -1
- package/lib/typescript/runtimeKind.d.ts +31 -0
- package/lib/typescript/runtimeKind.d.ts.map +1 -1
- package/lib/typescript/runtimes.d.ts +1 -0
- package/lib/typescript/runtimes.d.ts.map +1 -1
- package/lib/typescript/runtimes.native.d.ts +20 -2
- package/lib/typescript/runtimes.native.d.ts.map +1 -1
- package/lib/typescript/threads.native.d.ts +1 -1
- package/package.json +8 -6
- package/plugin/index.d.ts +109 -0
- package/plugin/index.js +59 -9
- package/scripts/worklets_utils.rb +21 -5
- package/src/WorkletsModule/NativeWorklets.native.ts +14 -4
- package/src/WorkletsModule/workletsModuleProxy.ts +6 -3
- package/src/bundleMode/metroOverrides.native.ts +151 -0
- package/src/bundleMode/network.native.ts +59 -0
- package/src/debug/jsVersion.ts +1 -1
- package/src/featureFlags/staticFlags.json +2 -0
- package/src/featureFlags/types.ts +3 -1
- package/src/index.ts +10 -1
- package/src/initializers/initializers.native.ts +29 -70
- package/src/initializers/workletRuntimeEntry.native.ts +3 -3
- package/src/memory/bundleUnpacker.native.ts +2 -4
- package/src/memory/serializable.native.ts +3 -3
- package/src/memory/synchronizableUnpacker.native.ts +6 -12
- package/src/platformChecker.ts +3 -2
- package/src/privateGlobals.d.ts +7 -2
- package/src/runtimeKind.ts +47 -0
- package/src/runtimes.native.ts +43 -2
- package/src/runtimes.ts +10 -0
- package/src/threads.native.ts +2 -2
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on OkHttpCallUtil.kt from React Native
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
@file:Suppress("DEPRECATION_ERROR") // Conflicting okhttp versions
|
|
6
|
+
|
|
7
|
+
package com.swmansion.worklets
|
|
8
|
+
|
|
9
|
+
import okhttp3.OkHttpClient
|
|
10
|
+
/*
|
|
11
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
12
|
+
*
|
|
13
|
+
* This source code is licensed under the MIT license found in the
|
|
14
|
+
* LICENSE file in the root directory of this source tree.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Helper class that provides the necessary methods for canceling queued and running OkHttp calls
|
|
19
|
+
*/
|
|
20
|
+
internal object WorkletsOkHttpCallUtil {
|
|
21
|
+
@JvmStatic
|
|
22
|
+
fun cancelTag(client: OkHttpClient, tag: Any) {
|
|
23
|
+
val dispatcher = client.dispatcher()
|
|
24
|
+
for (call in dispatcher.queuedCalls()) {
|
|
25
|
+
if (tag == call.request().tag()) {
|
|
26
|
+
call.cancel()
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
for (call in dispatcher.runningCalls()) {
|
|
31
|
+
if (tag == call.request().tag()) {
|
|
32
|
+
call.cancel()
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on ProgressRequestBody.kt from React Native
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
@file:Suppress("DEPRECATION_ERROR") // Conflicting okio versions
|
|
6
|
+
|
|
7
|
+
package com.swmansion.worklets
|
|
8
|
+
|
|
9
|
+
import java.io.FilterOutputStream
|
|
10
|
+
import java.io.IOException
|
|
11
|
+
import okhttp3.MediaType
|
|
12
|
+
import okhttp3.RequestBody
|
|
13
|
+
import okio.BufferedSink
|
|
14
|
+
import okio.Okio
|
|
15
|
+
import okio.Sink
|
|
16
|
+
|
|
17
|
+
internal class WorkletsProgressRequestBody(
|
|
18
|
+
private val requestBody: RequestBody,
|
|
19
|
+
private val progressListener: WorkletsProgressListener,
|
|
20
|
+
) : RequestBody() {
|
|
21
|
+
private var contentLength = 0L
|
|
22
|
+
|
|
23
|
+
companion object {
|
|
24
|
+
private const val MAX_BODY_PREVIEW_SIZE = 1024 * 1024 // 1MB
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
override fun contentType(): MediaType? {
|
|
28
|
+
return requestBody.contentType()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Throws(IOException::class)
|
|
32
|
+
override fun contentLength(): Long {
|
|
33
|
+
if (contentLength == 0L) {
|
|
34
|
+
contentLength = requestBody.contentLength()
|
|
35
|
+
}
|
|
36
|
+
return contentLength
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@Throws(IOException::class)
|
|
40
|
+
override fun writeTo(sink: BufferedSink) {
|
|
41
|
+
// In 99% of cases, this method is called strictly once.
|
|
42
|
+
// The only case when it is called more than once is internal okhttp upload re-try.
|
|
43
|
+
// We need to re-create CountingOutputStream in this case as progress should be re-evaluated.
|
|
44
|
+
val sinkWrapper = Okio.buffer(outputStreamSink(sink))
|
|
45
|
+
|
|
46
|
+
// contentLength changes for input streams, since we're using inputStream.available(),
|
|
47
|
+
// so get the length before writing to the sink
|
|
48
|
+
contentLength()
|
|
49
|
+
|
|
50
|
+
requestBody.writeTo(sinkWrapper)
|
|
51
|
+
sinkWrapper.flush()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private fun outputStreamSink(sink: BufferedSink): Sink {
|
|
55
|
+
return Okio.sink(
|
|
56
|
+
object : FilterOutputStream(sink.outputStream()) {
|
|
57
|
+
private var count: Long = 0
|
|
58
|
+
|
|
59
|
+
@Throws(IOException::class)
|
|
60
|
+
override fun write(data: ByteArray, offset: Int, byteCount: Int) {
|
|
61
|
+
super.write(data, offset, byteCount)
|
|
62
|
+
count += byteCount.toLong()
|
|
63
|
+
sendProgressUpdate()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@Throws(IOException::class)
|
|
67
|
+
override fun write(data: Int) {
|
|
68
|
+
super.write(data)
|
|
69
|
+
count++
|
|
70
|
+
sendProgressUpdate()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@Throws(IOException::class)
|
|
74
|
+
fun sendProgressUpdate() {
|
|
75
|
+
val bytesWritten = count
|
|
76
|
+
val contentLength = contentLength()
|
|
77
|
+
progressListener.onProgress(bytesWritten, contentLength, bytesWritten == contentLength)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
fun getBodyPreview(): String {
|
|
84
|
+
return try {
|
|
85
|
+
val buffer = okio.Buffer()
|
|
86
|
+
requestBody.writeTo(buffer)
|
|
87
|
+
val size = buffer.size()
|
|
88
|
+
if (size <= MAX_BODY_PREVIEW_SIZE) {
|
|
89
|
+
buffer.readUtf8()
|
|
90
|
+
} else {
|
|
91
|
+
buffer.readUtf8(MAX_BODY_PREVIEW_SIZE.toLong()) +
|
|
92
|
+
"\n... [truncated, showing $MAX_BODY_PREVIEW_SIZE of $size bytes]"
|
|
93
|
+
}
|
|
94
|
+
} catch (e: Exception) {
|
|
95
|
+
""
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on ProgressResponseBody.kt from React Native
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
@file:Suppress("DEPRECATION_ERROR") // Conflicting okhttp versions
|
|
6
|
+
|
|
7
|
+
package com.swmansion.worklets
|
|
8
|
+
|
|
9
|
+
import java.io.IOException
|
|
10
|
+
import okhttp3.MediaType
|
|
11
|
+
import okhttp3.ResponseBody
|
|
12
|
+
import okio.Buffer
|
|
13
|
+
import okio.BufferedSource
|
|
14
|
+
import okio.ForwardingSource
|
|
15
|
+
import okio.Okio
|
|
16
|
+
import okio.Source
|
|
17
|
+
|
|
18
|
+
public class WorkletsProgressResponseBody
|
|
19
|
+
public constructor(
|
|
20
|
+
private val responseBody: ResponseBody,
|
|
21
|
+
private val progressListener: WorkletsProgressListener,
|
|
22
|
+
) : ResponseBody() {
|
|
23
|
+
private lateinit var bufferedSource: BufferedSource
|
|
24
|
+
private var totalBytesRead = 0L
|
|
25
|
+
|
|
26
|
+
public override fun contentType(): MediaType? = responseBody.contentType()
|
|
27
|
+
|
|
28
|
+
override fun contentLength(): Long = responseBody.contentLength()
|
|
29
|
+
|
|
30
|
+
public fun totalBytesRead(): Long = totalBytesRead
|
|
31
|
+
|
|
32
|
+
public override fun source(): BufferedSource {
|
|
33
|
+
if (!::bufferedSource.isInitialized) {
|
|
34
|
+
bufferedSource = Okio.buffer(source(responseBody.source()))
|
|
35
|
+
}
|
|
36
|
+
return bufferedSource
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private fun source(source: Source): Source {
|
|
40
|
+
return object : ForwardingSource(source) {
|
|
41
|
+
@Throws(IOException::class)
|
|
42
|
+
override fun read(sink: Buffer, byteCount: Long): Long {
|
|
43
|
+
// read() returns the number of bytes read, or -1 if this source is exhausted.
|
|
44
|
+
return super.read(sink, byteCount).also { bytesRead ->
|
|
45
|
+
if (bytesRead != -1L) {
|
|
46
|
+
totalBytesRead += bytesRead
|
|
47
|
+
}
|
|
48
|
+
progressListener.onProgress(
|
|
49
|
+
totalBytesRead,
|
|
50
|
+
responseBody.contentLength(),
|
|
51
|
+
bytesRead == -1L,
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on ProgressiveStringDecoder.kt from React Native
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
package com.swmansion.worklets
|
|
6
|
+
|
|
7
|
+
import com.facebook.common.logging.FLog
|
|
8
|
+
import com.facebook.react.common.ReactConstants
|
|
9
|
+
import java.nio.ByteBuffer
|
|
10
|
+
import java.nio.CharBuffer
|
|
11
|
+
import java.nio.charset.Charset
|
|
12
|
+
import java.nio.charset.CharsetDecoder
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Class to decode encoded strings from byte array chunks. As in different encodings single
|
|
16
|
+
* character could take up to 4 characters byte array passed to decode could have parts of the
|
|
17
|
+
* characters which can't be correctly decoded.
|
|
18
|
+
*
|
|
19
|
+
* This class is designed in assumption that original byte stream is correctly formatted string in
|
|
20
|
+
* given encoding. Otherwise some parts of the data won't be decoded.
|
|
21
|
+
*/
|
|
22
|
+
internal class WorkletsProgressiveStringDecoder(charset: Charset) {
|
|
23
|
+
private val decoder: CharsetDecoder = charset.newDecoder()
|
|
24
|
+
private var remainder: ByteArray? = null
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Parses data to String If there is a partial multi-byte symbol on the edge of the String it get
|
|
28
|
+
* saved to the reminder and added to the string on the decodeNext call.
|
|
29
|
+
*
|
|
30
|
+
* @param data The byte array containing the encoded string data.
|
|
31
|
+
* @param initialLength The number of valid bytes in the provided data array that should be
|
|
32
|
+
* decoded.
|
|
33
|
+
* @return The decoded string. If decoding fails, an empty string is returned.
|
|
34
|
+
*/
|
|
35
|
+
fun decodeNext(data: ByteArray, initialLength: Int): String {
|
|
36
|
+
var length = initialLength
|
|
37
|
+
var decodeData: ByteArray = data
|
|
38
|
+
|
|
39
|
+
remainder?.let { r ->
|
|
40
|
+
decodeData = ByteArray(r.size + length)
|
|
41
|
+
System.arraycopy(r, 0, decodeData, 0, r.size)
|
|
42
|
+
System.arraycopy(data, 0, decodeData, r.size, length)
|
|
43
|
+
length += r.size
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
var decodeBuffer = ByteBuffer.wrap(decodeData, 0, length)
|
|
47
|
+
var result: CharBuffer? = null
|
|
48
|
+
var decoded = false
|
|
49
|
+
var remainderLength = 0
|
|
50
|
+
|
|
51
|
+
while (!decoded && (remainderLength < 4)) {
|
|
52
|
+
try {
|
|
53
|
+
result = decoder.decode(decodeBuffer)
|
|
54
|
+
decoded = true
|
|
55
|
+
} catch (e: CharacterCodingException) {
|
|
56
|
+
remainderLength++
|
|
57
|
+
decodeBuffer = ByteBuffer.wrap(decodeData, 0, length - remainderLength)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
val hasRemainder = decoded && remainderLength > 0
|
|
62
|
+
remainder =
|
|
63
|
+
if (hasRemainder) {
|
|
64
|
+
ByteArray(remainderLength).apply {
|
|
65
|
+
System.arraycopy(decodeData, length - remainderLength, this, 0, remainderLength)
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
null
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!decoded) {
|
|
72
|
+
FLog.w(ReactConstants.TAG, "failed to decode string from byte array")
|
|
73
|
+
return EMPTY_STRING
|
|
74
|
+
} else {
|
|
75
|
+
return result?.let { String(it.array(), 0, it.length) } ?: EMPTY_STRING
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
companion object {
|
|
80
|
+
private const val EMPTY_STRING = ""
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on RequestBodyUtil.kt from React Native
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
@file:Suppress("DEPRECATION_ERROR") // Conflicting okio versions
|
|
6
|
+
|
|
7
|
+
package com.swmansion.worklets
|
|
8
|
+
|
|
9
|
+
import android.content.Context
|
|
10
|
+
import android.net.Uri
|
|
11
|
+
import android.util.Base64
|
|
12
|
+
import com.facebook.common.logging.FLog
|
|
13
|
+
import com.facebook.react.common.ReactConstants
|
|
14
|
+
import java.io.ByteArrayInputStream
|
|
15
|
+
import java.io.ByteArrayOutputStream
|
|
16
|
+
import java.io.File
|
|
17
|
+
import java.io.FileInputStream
|
|
18
|
+
import java.io.FileOutputStream
|
|
19
|
+
import java.io.IOException
|
|
20
|
+
import java.io.InputStream
|
|
21
|
+
import java.io.OutputStream
|
|
22
|
+
import java.net.URL
|
|
23
|
+
import java.nio.channels.Channels
|
|
24
|
+
import java.util.zip.GZIPOutputStream
|
|
25
|
+
import okhttp3.MediaType
|
|
26
|
+
import okhttp3.RequestBody
|
|
27
|
+
import okio.BufferedSink
|
|
28
|
+
import okio.ByteString
|
|
29
|
+
import okio.Okio
|
|
30
|
+
import okio.Source
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Helper class that provides the necessary methods for creating the [RequestBody] from a file
|
|
34
|
+
* specification, such as a contentUri.
|
|
35
|
+
*/
|
|
36
|
+
internal object WorkletsRequestBodyUtil {
|
|
37
|
+
private const val CONTENT_ENCODING_GZIP = "gzip"
|
|
38
|
+
private const val NAME = "RequestBodyUtil"
|
|
39
|
+
private const val TEMP_FILE_SUFFIX = "temp"
|
|
40
|
+
|
|
41
|
+
/** Returns whether encode type indicates the body needs to be gzip-ed. */
|
|
42
|
+
@JvmStatic
|
|
43
|
+
fun isGzipEncoding(encodingType: String?): Boolean {
|
|
44
|
+
return CONTENT_ENCODING_GZIP.equals(encodingType, ignoreCase = true)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Returns the input stream for a file given by its contentUri. Returns null if the file has not
|
|
49
|
+
* been found or if an error as occurred.
|
|
50
|
+
*/
|
|
51
|
+
@JvmStatic
|
|
52
|
+
fun getFileInputStream(context: Context, fileContentUriStr: String): InputStream? {
|
|
53
|
+
try {
|
|
54
|
+
val fileContentUri = Uri.parse(fileContentUriStr)
|
|
55
|
+
|
|
56
|
+
if (fileContentUri.scheme?.startsWith("http") == true) {
|
|
57
|
+
return getDownloadFileInputStream(context, fileContentUri)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (fileContentUriStr.startsWith("data:")) {
|
|
61
|
+
val decodedDataUrString =
|
|
62
|
+
Base64.decode(
|
|
63
|
+
fileContentUriStr
|
|
64
|
+
.split(",".toRegex())
|
|
65
|
+
.dropLastWhile { it.isEmpty() }
|
|
66
|
+
.toTypedArray()[1],
|
|
67
|
+
Base64.DEFAULT,
|
|
68
|
+
)
|
|
69
|
+
return ByteArrayInputStream(decodedDataUrString)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return context.contentResolver.openInputStream(fileContentUri)
|
|
73
|
+
} catch (e: Exception) {
|
|
74
|
+
FLog.e(ReactConstants.TAG, "Could not retrieve file for contentUri $fileContentUriStr", e)
|
|
75
|
+
return null
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Download and cache a file locally. This should be used when document picker returns a URI that
|
|
81
|
+
* points to a file on the network. Returns input stream for the downloaded file.
|
|
82
|
+
*/
|
|
83
|
+
@Throws(IOException::class)
|
|
84
|
+
private fun getDownloadFileInputStream(context: Context, uri: Uri): InputStream {
|
|
85
|
+
val outputDir = context.applicationContext.cacheDir
|
|
86
|
+
val file = File.createTempFile(NAME, TEMP_FILE_SUFFIX, outputDir)
|
|
87
|
+
file.deleteOnExit()
|
|
88
|
+
|
|
89
|
+
val url = URL(uri.toString())
|
|
90
|
+
FileOutputStream(file).use { stream ->
|
|
91
|
+
url.openStream().use { `is` ->
|
|
92
|
+
Channels.newChannel(`is`).use { channel ->
|
|
93
|
+
stream.channel.transferFrom(channel, 0, Long.MAX_VALUE)
|
|
94
|
+
return FileInputStream(file)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Creates a [RequestBody] from a mediaType and gzip-ed body string. */
|
|
101
|
+
@JvmStatic
|
|
102
|
+
fun createGzip(mediaType: MediaType?, body: String): RequestBody? {
|
|
103
|
+
val gzipByteArrayOutputStream = ByteArrayOutputStream()
|
|
104
|
+
try {
|
|
105
|
+
val gzipOutputStream: OutputStream = GZIPOutputStream(gzipByteArrayOutputStream)
|
|
106
|
+
gzipOutputStream.write(body.toByteArray())
|
|
107
|
+
gzipOutputStream.close()
|
|
108
|
+
} catch (e: IOException) {
|
|
109
|
+
return null
|
|
110
|
+
}
|
|
111
|
+
@Suppress("DEPRECATION")
|
|
112
|
+
return RequestBody.create(mediaType, gzipByteArrayOutputStream.toByteArray())
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Reference:
|
|
117
|
+
* https://github.com/square/okhttp/blob/8c8c3dbcfa91e28de2e13975ec414e07f153fde4/okhttp/src/commonMain/kotlin/okhttp3/internal/-UtilCommon.kt#L281-L288
|
|
118
|
+
* Checked exceptions will be ignored
|
|
119
|
+
*/
|
|
120
|
+
private fun closeQuietly(source: Source) {
|
|
121
|
+
try {
|
|
122
|
+
source.close()
|
|
123
|
+
} catch (e: RuntimeException) {
|
|
124
|
+
throw e
|
|
125
|
+
} catch (e: Exception) {
|
|
126
|
+
// no-op
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Creates a [RequestBody] from a mediaType and inputStream given. */
|
|
131
|
+
@JvmStatic
|
|
132
|
+
fun create(mediaType: MediaType?, inputStream: InputStream): RequestBody {
|
|
133
|
+
return object : RequestBody() {
|
|
134
|
+
override fun contentType(): MediaType? {
|
|
135
|
+
return mediaType
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
override fun contentLength(): Long {
|
|
139
|
+
return try {
|
|
140
|
+
inputStream.available().toLong()
|
|
141
|
+
} catch (e: IOException) {
|
|
142
|
+
0
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@Throws(IOException::class)
|
|
147
|
+
override fun writeTo(sink: BufferedSink) {
|
|
148
|
+
var source: Source? = null
|
|
149
|
+
try {
|
|
150
|
+
source = Okio.source(inputStream)
|
|
151
|
+
sink.writeAll(source)
|
|
152
|
+
} finally {
|
|
153
|
+
source?.let { closeQuietly(it) }
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Creates a [ProgressRequestBody] that can be used for showing uploading progress. */
|
|
160
|
+
@JvmStatic
|
|
161
|
+
fun createProgressRequest(
|
|
162
|
+
requestBody: RequestBody,
|
|
163
|
+
listener: WorkletsProgressListener,
|
|
164
|
+
): WorkletsProgressRequestBody {
|
|
165
|
+
return WorkletsProgressRequestBody(requestBody, listener)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Creates an empty [RequestBody] if required by the http method spec, otherwise use null. */
|
|
169
|
+
@JvmStatic
|
|
170
|
+
fun getEmptyBody(method: String): RequestBody? {
|
|
171
|
+
return if (method == "POST" || method == "PUT" || method == "PATCH") {
|
|
172
|
+
@Suppress("DEPRECATION") RequestBody.create(null, ByteString.EMPTY)
|
|
173
|
+
} else {
|
|
174
|
+
null
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -8,7 +8,6 @@ import com.facebook.react.bridge.ReactApplicationContext;
|
|
|
8
8
|
import com.facebook.react.bridge.ReactMethod;
|
|
9
9
|
import com.facebook.react.bridge.queue.MessageQueueThread;
|
|
10
10
|
import com.facebook.react.common.annotations.FrameworkAPI;
|
|
11
|
-
import com.facebook.react.fabric.BundleWrapper;
|
|
12
11
|
import com.facebook.react.module.annotations.ReactModule;
|
|
13
12
|
import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
|
|
14
13
|
import com.facebook.soloader.SoLoader;
|
|
@@ -37,8 +36,6 @@ public class WorkletsModule extends NativeWorkletsModuleSpec implements Lifecycl
|
|
|
37
36
|
private final AndroidUIScheduler mAndroidUIScheduler;
|
|
38
37
|
private final AnimationFrameQueue mAnimationFrameQueue;
|
|
39
38
|
private boolean mSlowAnimationsEnabled;
|
|
40
|
-
private BundleWrapper mBundleWrapper = null;
|
|
41
|
-
private String mSourceURL = null;
|
|
42
39
|
|
|
43
40
|
/**
|
|
44
41
|
* Invalidating concurrently could be fatal. It shouldn't happen in a normal flow, but it doesn't
|
|
@@ -52,15 +49,12 @@ public class WorkletsModule extends NativeWorkletsModuleSpec implements Lifecycl
|
|
|
52
49
|
MessageQueueThread messageQueueThread,
|
|
53
50
|
CallInvokerHolderImpl jsCallInvokerHolder,
|
|
54
51
|
AndroidUIScheduler androidUIScheduler,
|
|
55
|
-
|
|
56
|
-
String sourceURL);
|
|
52
|
+
ScriptBufferWrapper scriptBufferWrapper);
|
|
57
53
|
|
|
58
54
|
public WorkletsModule(ReactApplicationContext reactContext) {
|
|
59
55
|
super(reactContext);
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
reactContext.assertOnJSQueueThread();
|
|
63
|
-
}
|
|
57
|
+
reactContext.assertOnJSQueueThread();
|
|
64
58
|
|
|
65
59
|
mAndroidUIScheduler = new AndroidUIScheduler(reactContext);
|
|
66
60
|
mAnimationFrameQueue = new AnimationFrameQueue(reactContext);
|
|
@@ -71,15 +65,17 @@ public class WorkletsModule extends NativeWorkletsModuleSpec implements Lifecycl
|
|
|
71
65
|
public boolean installTurboModule() {
|
|
72
66
|
var context = getReactApplicationContext();
|
|
73
67
|
|
|
74
|
-
|
|
75
|
-
context.assertOnNativeModulesQueueThread();
|
|
76
|
-
}
|
|
68
|
+
context.assertOnJSQueueThread();
|
|
77
69
|
|
|
78
70
|
var jsContext = Objects.requireNonNull(context.getJavaScriptContextHolder()).get();
|
|
79
71
|
var jsCallInvokerHolder = JSCallInvokerResolver.getJSCallInvokerHolder(context);
|
|
80
72
|
|
|
81
|
-
|
|
82
|
-
|
|
73
|
+
var sourceURL = context.getSourceURL();
|
|
74
|
+
|
|
75
|
+
ScriptBufferWrapper scriptBufferWrapper = null;
|
|
76
|
+
if (BuildConfig.BUNDLE_MODE_ENABLED) {
|
|
77
|
+
scriptBufferWrapper = new ScriptBufferWrapper(sourceURL, context.getAssets());
|
|
78
|
+
}
|
|
83
79
|
|
|
84
80
|
mHybridData =
|
|
85
81
|
initHybrid(
|
|
@@ -87,8 +83,7 @@ public class WorkletsModule extends NativeWorkletsModuleSpec implements Lifecycl
|
|
|
87
83
|
mMessageQueueThread,
|
|
88
84
|
jsCallInvokerHolder,
|
|
89
85
|
mAndroidUIScheduler,
|
|
90
|
-
|
|
91
|
-
mSourceURL);
|
|
86
|
+
scriptBufferWrapper);
|
|
92
87
|
return true;
|
|
93
88
|
}
|
|
94
89
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#if defined(WORKLETS_BUNDLE_MODE_ENABLED) && defined(WORKLETS_FETCH_PREVIEW_ENABLED)
|
|
2
|
+
/*
|
|
3
|
+
* This file is based on RCTNetworking.h from React Native.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#import <React/RCTNetworking.h>
|
|
7
|
+
|
|
8
|
+
using namespace facebook;
|
|
9
|
+
|
|
10
|
+
@interface WorkletsNetworking : NSObject
|
|
11
|
+
- (instancetype)init:(RCTNetworking *)rctNetworking;
|
|
12
|
+
|
|
13
|
+
- (void)jsiSendRequest:(jsi::Runtime &)rt
|
|
14
|
+
jquery:(const jsi::Value &)jquery
|
|
15
|
+
responseSender:(jsi::Function &&)responseSender;
|
|
16
|
+
|
|
17
|
+
- (void)jsiAbortRequest:(double)requestID;
|
|
18
|
+
|
|
19
|
+
- (void)jsiClearCookies:(jsi::Runtime &)rt responseSender:(jsi::Function &&)responseSender;
|
|
20
|
+
|
|
21
|
+
@end
|
|
22
|
+
#endif // defined(WORKLETS_BUNDLE_MODE_ENABLED) && defined(WORKLETS_FETCH_PREVIEW_ENABLED)
|