uws-react-native 0.0.10 → 0.1.0-beta.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/README.md +108 -3
- package/cpp/UwsReactNativeModule.cpp +4 -0
- package/cpp/app/HttpResponseObject.h +116 -40
- package/cpp/app/RecognizedString.h +20 -14
- package/cpp/app/TemplatedAppObject.h +61 -36
- package/cpp/app/WebSocketBehaviorImpl.h +269 -11
- package/cpp/app/WebSocketObject.h +354 -16
- package/cpp/app/WebSocketUserData.h +227 -0
- package/lib/commonjs/modules/WebSocketSendStatus.js +22 -0
- package/lib/commonjs/modules/WebSocketSendStatus.js.map +1 -0
- package/lib/commonjs/modules/index.js +22 -0
- package/lib/commonjs/modules/index.js.map +1 -1
- package/lib/commonjs/types/WebSocketUserData.js +2 -0
- package/lib/commonjs/types/WebSocketUserData.js.map +1 -0
- package/lib/module/modules/WebSocketSendStatus.js +18 -0
- package/lib/module/modules/WebSocketSendStatus.js.map +1 -0
- package/lib/module/modules/index.js +2 -1
- package/lib/module/modules/index.js.map +1 -1
- package/lib/module/types/WebSocketUserData.js +2 -0
- package/lib/module/types/WebSocketUserData.js.map +1 -0
- package/lib/typescript/commonjs/modules/WebSocketSendStatus.d.ts +15 -0
- package/lib/typescript/commonjs/modules/WebSocketSendStatus.d.ts.map +1 -0
- package/lib/typescript/commonjs/modules/index.d.ts +2 -0
- package/lib/typescript/commonjs/modules/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/types/HttpResponse.d.ts +39 -4
- package/lib/typescript/commonjs/types/HttpResponse.d.ts.map +1 -1
- package/lib/typescript/commonjs/types/HttpRouterOptions.d.ts +1 -1
- package/lib/typescript/commonjs/types/TemplatedApp.d.ts +5 -0
- package/lib/typescript/commonjs/types/TemplatedApp.d.ts.map +1 -1
- package/lib/typescript/commonjs/types/WebSocket.d.ts +18 -8
- package/lib/typescript/commonjs/types/WebSocket.d.ts.map +1 -1
- package/lib/typescript/commonjs/types/WebSocketBehavior.d.ts +9 -9
- package/lib/typescript/commonjs/types/WebSocketBehavior.d.ts.map +1 -1
- package/lib/typescript/commonjs/types/WebSocketUserData.d.ts +9 -0
- package/lib/typescript/commonjs/types/WebSocketUserData.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/index.d.ts +3 -0
- package/lib/typescript/commonjs/types/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/types/us_socket_context_t.d.ts +2 -3
- package/lib/typescript/commonjs/types/us_socket_context_t.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +2 -2
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/modules/App.d.ts +1 -1
- package/lib/typescript/module/modules/App.d.ts.map +1 -1
- package/lib/typescript/module/modules/WebSocketSendStatus.d.ts +15 -0
- package/lib/typescript/module/modules/WebSocketSendStatus.d.ts.map +1 -0
- package/lib/typescript/module/modules/getParts.d.ts +1 -1
- package/lib/typescript/module/modules/getParts.d.ts.map +1 -1
- package/lib/typescript/module/modules/index.d.ts +7 -5
- package/lib/typescript/module/modules/index.d.ts.map +1 -1
- package/lib/typescript/module/types/HttpRequest.d.ts +1 -1
- package/lib/typescript/module/types/HttpRequest.d.ts.map +1 -1
- package/lib/typescript/module/types/HttpResponse.d.ts +40 -5
- package/lib/typescript/module/types/HttpResponse.d.ts.map +1 -1
- package/lib/typescript/module/types/HttpRouterOptions.d.ts +1 -1
- package/lib/typescript/module/types/TemplatedApp.d.ts +10 -5
- package/lib/typescript/module/types/TemplatedApp.d.ts.map +1 -1
- package/lib/typescript/module/types/WebSocket.d.ts +19 -9
- package/lib/typescript/module/types/WebSocket.d.ts.map +1 -1
- package/lib/typescript/module/types/WebSocketBehavior.d.ts +14 -14
- package/lib/typescript/module/types/WebSocketBehavior.d.ts.map +1 -1
- package/lib/typescript/module/types/WebSocketUserData.d.ts +9 -0
- package/lib/typescript/module/types/WebSocketUserData.d.ts.map +1 -0
- package/lib/typescript/module/types/index.d.ts +8 -5
- package/lib/typescript/module/types/index.d.ts.map +1 -1
- package/lib/typescript/module/types/us_socket_context_t.d.ts +2 -3
- package/lib/typescript/module/types/us_socket_context_t.d.ts.map +1 -1
- package/lib/typescript/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -3
- package/src/modules/WebSocketSendStatus.ts +14 -0
- package/src/modules/index.ts +2 -1
- package/src/types/HttpResponse.ts +50 -33
- package/src/types/HttpRouterOptions.ts +1 -1
- package/src/types/TemplatedApp.ts +10 -10
- package/src/types/WebSocket.ts +24 -8
- package/src/types/WebSocketBehavior.ts +9 -9
- package/src/types/WebSocketUserData.ts +28 -0
- package/src/types/index.ts +3 -2
- package/src/types/us_socket_context_t.ts +2 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# uws-react-native
|
|
2
2
|
|
|
3
|
-
The port of [**uWebSockets**](https://github.com/uNetworking/uWebSockets) library for React Native. Inspired by the [**uWebSockets.js**](https://github.com/uNetworking/uWebSockets.js) for Node.js and tailored for React Native app.
|
|
3
|
+
The port of [**uWebSockets**](https://github.com/uNetworking/uWebSockets) server library for React Native. Inspired by the [**uWebSockets.js**](https://github.com/uNetworking/uWebSockets.js) for Node.js and tailored for React Native app.
|
|
4
4
|
|
|
5
5
|
- **uWebSockets** is simple, secure & standards compliant web server for the most demanding of applications. See [**uWebSockets**](https://github.com/uNetworking/uWebSockets) for more information
|
|
6
6
|
- **uws-react-native** is library that allows you to easily use **uWebSockets** in your React Native through new architecture with JSI to the native C++
|
|
@@ -9,6 +9,7 @@ The port of [**uWebSockets**](https://github.com/uNetworking/uWebSockets) librar
|
|
|
9
9
|
|
|
10
10
|
- [Installation](#installation)
|
|
11
11
|
- [From NPM Registry](#from-npm-registry)
|
|
12
|
+
- [From GitHub Release](#from-github-release)
|
|
12
13
|
- [From GitHub Packages](#from-github-packages)
|
|
13
14
|
- [Usage](#usage)
|
|
14
15
|
- [Compatibility](#compatibility)
|
|
@@ -20,7 +21,7 @@ The port of [**uWebSockets**](https://github.com/uNetworking/uWebSockets) librar
|
|
|
20
21
|
|
|
21
22
|
## Installation
|
|
22
23
|
|
|
23
|
-
We provide
|
|
24
|
+
We provide three registry homes where this library is available for use in your project. You can use either it is from NPM registry, or GitHub Release, or GitHub Packages. It has absolutely **no external JavaScript dependencies**
|
|
24
25
|
|
|
25
26
|
### From NPM Registry
|
|
26
27
|
|
|
@@ -39,6 +40,31 @@ pnpm
|
|
|
39
40
|
pnpm install uws-react-native
|
|
40
41
|
```
|
|
41
42
|
|
|
43
|
+
### From GitHub Release
|
|
44
|
+
|
|
45
|
+
To install this library from GitHub release
|
|
46
|
+
|
|
47
|
+
1. Go to this project's [GitHub Release](https://github.com/RakaDoank/uws-react-native/releases)
|
|
48
|
+
2. Find the `uws-react-native-X.X.X.tgz` asset from one of the release versions
|
|
49
|
+
3. Copy the asset URL or link (Right click at the asset file name in your browser)
|
|
50
|
+
|
|
51
|
+
Finally, do the regular installation with the CLI, but with the asset URL
|
|
52
|
+
|
|
53
|
+
npm
|
|
54
|
+
```
|
|
55
|
+
npm install https://github.com/.../uws-react-native-X.X.X.tgz
|
|
56
|
+
```
|
|
57
|
+
yarn
|
|
58
|
+
```
|
|
59
|
+
yarn add https://github.com/.../uws-react-native-X.X.X.tgz
|
|
60
|
+
```
|
|
61
|
+
pnpm
|
|
62
|
+
```
|
|
63
|
+
pnpm install https://github.com/.../uws-react-native-X.X.X.tgz
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
> You can also do an offline installation by downloading the tarball file first, and do the regular installation with the CLI, but with the local file path.
|
|
67
|
+
|
|
42
68
|
### From GitHub Packages
|
|
43
69
|
|
|
44
70
|
First, create your GitHub personal token (classic) with `read:packages` access
|
|
@@ -77,10 +103,89 @@ pnpm install @rakadoank/uws-react-native
|
|
|
77
103
|
## Usage
|
|
78
104
|
|
|
79
105
|
Since uws-react-native is a port of uWebSockets library for JavaScript, this library is really similar of how to use the [uWebSockets](https://github.com/uNetworking/uWebSockets) in C++, or the [uWebSockets.js](https://github.com/uNetworking/uWebSockets.js) for Node.js.
|
|
80
|
-
You can refer to the [uWebSockets.js](https://github.com/uNetworking/uWebSockets.js) example
|
|
106
|
+
You can refer to the [uWebSockets.js](https://github.com/uNetworking/uWebSockets.js) example, but **we recommend to create a server in `useEffect`**.
|
|
81
107
|
|
|
82
108
|
This repository does also contain the [server example](https://github.com/RakaDoank/uws-react-native/blob/main/examples/app/src/screens/home/_use-server.ts). You can also refer to it, but it is currently for library development playground rather than proper example.
|
|
83
109
|
|
|
110
|
+
A simple server example
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { useEffect } from "react"
|
|
114
|
+
import * as uWS from "uws-react-native"
|
|
115
|
+
|
|
116
|
+
export function Component() {
|
|
117
|
+
|
|
118
|
+
// useEffect is perfect tool for production and even in development mode.
|
|
119
|
+
// In the development mode, any changes below will restart the server automatically because of the useEffect cycle
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
const app = uWS.App()
|
|
122
|
+
|
|
123
|
+
app.get("/data/:foo/:bar", (res, req) => {
|
|
124
|
+
const fooSlug = req.getParameter("foo")
|
|
125
|
+
const barSlug = req.getParameter("bar")
|
|
126
|
+
|
|
127
|
+
res.writeHeader("content-type", "application/json")
|
|
128
|
+
res.end(
|
|
129
|
+
JSON.stringify({
|
|
130
|
+
foo: fooSlug,
|
|
131
|
+
bar: barSlug,
|
|
132
|
+
});
|
|
133
|
+
)
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
app.get("/about", res => {
|
|
137
|
+
res.write("<html><body>")
|
|
138
|
+
res.write("<h2>Hello World</h2>")
|
|
139
|
+
res.end("</body></html>")
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
app.post("/data", (res, req) => {
|
|
143
|
+
let isAborted = false
|
|
144
|
+
res.onAborted(() => {
|
|
145
|
+
isAborted = true
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
res.onFullData(data => {
|
|
149
|
+
const textDecoder = new TextDecoder("utf-8")
|
|
150
|
+
const text = textDecoder.decode(data)
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
const json = JSON.parse(text)
|
|
154
|
+
|
|
155
|
+
if(!isAborted) {
|
|
156
|
+
// send the json back
|
|
157
|
+
res.writeHeader("content-type", "application/json")
|
|
158
|
+
res.end(
|
|
159
|
+
JSON.stringify(json)
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
} catch {
|
|
163
|
+
// not a valid json
|
|
164
|
+
res.end(
|
|
165
|
+
JSON.stringify({
|
|
166
|
+
message: "Something went wrong",
|
|
167
|
+
})
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
app.listen("127.0.0.1", 5000, token => {
|
|
174
|
+
if(token) {
|
|
175
|
+
console.log("Listening at port 5000")
|
|
176
|
+
} else {
|
|
177
|
+
console.log("Failed to listen")
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
return () => {
|
|
182
|
+
app.close()
|
|
183
|
+
}
|
|
184
|
+
}, [])
|
|
185
|
+
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
84
189
|
## Compatibility
|
|
85
190
|
|
|
86
191
|
`uws-react-native` is only compatible for new architecture of React Native.
|
|
@@ -87,6 +87,10 @@ facebook::jsi::Object UwsReactNativeModule::getParts(facebook::jsi::Runtime &rt,
|
|
|
87
87
|
|
|
88
88
|
auto parts = std::vector<facebook::jsi::Object>();
|
|
89
89
|
|
|
90
|
+
/// Using jsi Array with zero element and "push" it later
|
|
91
|
+
/// is only supported in React Native >= 0.86
|
|
92
|
+
// auto parts = facebook::jsi::Array(rt, 0);
|
|
93
|
+
|
|
90
94
|
while(true) {
|
|
91
95
|
std::optional<std::string_view> optionalPart = mp.getNextPart(headers);
|
|
92
96
|
if(!optionalPart.has_value()) {
|
|
@@ -3,11 +3,38 @@
|
|
|
3
3
|
#include <ReactCommon/CallInvoker.h>
|
|
4
4
|
#include <jsi/Buffer.h>
|
|
5
5
|
#include <jsi/jsi.h>
|
|
6
|
+
#include <react/bridging/Function.h>
|
|
6
7
|
#include <utility>
|
|
7
|
-
#include "RecognizedString.h"
|
|
8
8
|
#include "HttpResponseObjectProvider.h"
|
|
9
|
+
#include "RecognizedString.h"
|
|
10
|
+
#include "WebSocketUserData.h"
|
|
9
11
|
#include "uWebSockets/App.h"
|
|
10
12
|
|
|
13
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
14
|
+
namespace {
|
|
15
|
+
|
|
16
|
+
thread_local int insideCorkCallback = 0;
|
|
17
|
+
|
|
18
|
+
void assumeCorked(facebook::jsi::Runtime &rt) {
|
|
19
|
+
if(!insideCorkCallback) {
|
|
20
|
+
auto console = rt.global().getProperty(rt, "console");
|
|
21
|
+
if(!console.isObject()) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
auto warning = console.asObject(rt).getProperty(rt, "warning");
|
|
26
|
+
if(!warning.isObject()) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
auto fn = warning.asObject(rt).asFunction(rt);
|
|
31
|
+
fn.call(rt, "Warning: uWS.HttpResponse writes must be made from within a corked callback. See documentation for uWS.HttpResponse.cork and consult the user manual.");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
} // namespace
|
|
36
|
+
#endif
|
|
37
|
+
|
|
11
38
|
namespace uws_react_native {
|
|
12
39
|
|
|
13
40
|
/// Only use this in the JavaScript thread
|
|
@@ -41,7 +68,15 @@ public:
|
|
|
41
68
|
const facebook::jsi::Value *arguments,
|
|
42
69
|
size_t count) -> facebook::jsi::Value {
|
|
43
70
|
provider->res->cork([&rt_1, callback = arguments[0].asObject(rt_1).asFunction(rt_1)]() {
|
|
71
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
72
|
+
insideCorkCallback++;
|
|
73
|
+
#endif
|
|
74
|
+
|
|
44
75
|
callback.call(rt_1);
|
|
76
|
+
|
|
77
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
78
|
+
insideCorkCallback--;
|
|
79
|
+
#endif
|
|
45
80
|
});
|
|
46
81
|
|
|
47
82
|
return {rt_1, thisValue};
|
|
@@ -65,7 +100,12 @@ public:
|
|
|
65
100
|
}
|
|
66
101
|
|
|
67
102
|
auto body = RecognizedString(rt_1, arguments[0]).getStringView();
|
|
103
|
+
|
|
104
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
105
|
+
assumeCorked(rt_1);
|
|
106
|
+
#endif
|
|
68
107
|
provider->res->end(body);
|
|
108
|
+
|
|
69
109
|
return {rt_1, thisValue};
|
|
70
110
|
}));
|
|
71
111
|
|
|
@@ -103,6 +143,9 @@ public:
|
|
|
103
143
|
closeConnection = arguments[1].asBool();
|
|
104
144
|
}
|
|
105
145
|
|
|
146
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
147
|
+
assumeCorked(rt_1);
|
|
148
|
+
#endif
|
|
106
149
|
provider->res->endWithoutBody(reportedContentLength, closeConnection);
|
|
107
150
|
|
|
108
151
|
return {rt_1, thisValue};
|
|
@@ -354,50 +397,71 @@ public:
|
|
|
354
397
|
auto fullBodyOrChunk = RecognizedString(rt_1, arguments[0]).getStringView();
|
|
355
398
|
auto totalSize = arguments[1].asNumber();
|
|
356
399
|
|
|
400
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
401
|
+
assumeCorked(rt_1);
|
|
402
|
+
#endif
|
|
357
403
|
auto tryEndResult = provider->res->tryEnd(fullBodyOrChunk, static_cast<uintmax_t>(totalSize));
|
|
358
404
|
|
|
359
405
|
return facebook::jsi::Array::createWithElements(rt_1, {tryEndResult.first, tryEndResult.second});
|
|
360
406
|
}));
|
|
361
407
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
408
|
+
this->setProperty(rt, "upgrade", facebook::jsi::Function::createFromHostFunction(rt,
|
|
409
|
+
facebook::jsi::PropNameID::forUtf8(rt, "upgrade"),
|
|
410
|
+
5,
|
|
411
|
+
[provider](facebook::jsi::Runtime &rt_1,
|
|
412
|
+
const facebook::jsi::Value &thisValue,
|
|
413
|
+
const facebook::jsi::Value *arguments,
|
|
414
|
+
size_t count) -> facebook::jsi::Value {
|
|
415
|
+
if(!arguments || count != 5 ||
|
|
416
|
+
!arguments[1].isString() ||
|
|
417
|
+
!arguments[2].isString() ||
|
|
418
|
+
!arguments[3].isString() ||
|
|
419
|
+
!arguments[4].isBigInt()) {
|
|
420
|
+
return facebook::jsi::Value::undefined();
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if(!arguments[0].isObject()) {
|
|
424
|
+
return facebook::jsi::Value::undefined();
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
auto userDataFnObj = arguments[0].asObject(rt_1);
|
|
428
|
+
if(!userDataFnObj.isFunction(rt_1)) {
|
|
429
|
+
return facebook::jsi::Value::undefined();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/// We are not supposed to store the user data object inside of singleton member,
|
|
433
|
+
/// such as map, vector, or any else.
|
|
434
|
+
///
|
|
435
|
+
/// See this manual
|
|
436
|
+
/// https://github.com/uNetworking/uWebSockets/blob/master/misc/READMORE.md#the-appws-route
|
|
437
|
+
///
|
|
438
|
+
/// Not like uWebSockets.js, there is no equivalent of v8::UniquePersistent in JSI.
|
|
439
|
+
/// So, instead of holding an JS object,
|
|
440
|
+
/// we store user data as facebook::jsi::HostObject.
|
|
441
|
+
/// See WebSocketUserData.h
|
|
442
|
+
auto userDataFn = userDataFnObj.asFunction(rt_1);
|
|
443
|
+
auto userData = std::make_shared<WebSocketUserData>();
|
|
444
|
+
userDataFn.call(rt_1,
|
|
445
|
+
facebook::jsi::Object::createFromHostObject(rt_1, userData));
|
|
446
|
+
|
|
447
|
+
auto secWebSocketKey = arguments[1].asString(rt_1).utf8(rt_1);
|
|
448
|
+
auto secWebSocketProtocol = arguments[2].asString(rt_1).utf8(rt_1);
|
|
449
|
+
auto secWebSocketExtensions = arguments[3].asString(rt_1).utf8(rt_1);
|
|
450
|
+
auto context = arguments[4].asBigInt(rt_1).asUint64(rt_1);
|
|
451
|
+
|
|
452
|
+
auto *usSocketContext = reinterpret_cast<us_socket_context_t *>(context);
|
|
453
|
+
|
|
454
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
455
|
+
assumeCorked(rt_1);
|
|
456
|
+
#endif
|
|
457
|
+
provider->res->upgrade(std::move(userData),
|
|
458
|
+
std::string_view(secWebSocketKey),
|
|
459
|
+
std::string_view(secWebSocketProtocol),
|
|
460
|
+
std::string_view(secWebSocketExtensions),
|
|
461
|
+
usSocketContext);
|
|
462
|
+
|
|
463
|
+
return facebook::jsi::Value::undefined();
|
|
464
|
+
}));
|
|
401
465
|
|
|
402
466
|
this->setProperty(rt,
|
|
403
467
|
"write",
|
|
@@ -409,6 +473,10 @@ public:
|
|
|
409
473
|
const facebook::jsi::Value *arguments,
|
|
410
474
|
size_t count) -> facebook::jsi::Value {
|
|
411
475
|
auto chunk = RecognizedString(rt_1, arguments[0]).getStringView();
|
|
476
|
+
|
|
477
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
478
|
+
assumeCorked(rt_1);
|
|
479
|
+
#endif
|
|
412
480
|
return provider->res->write(chunk);
|
|
413
481
|
}));
|
|
414
482
|
|
|
@@ -423,6 +491,10 @@ public:
|
|
|
423
491
|
size_t count) -> facebook::jsi::Value {
|
|
424
492
|
auto headerKey = RecognizedString(rt_1, arguments[0]).getStringView();
|
|
425
493
|
auto headerVal = RecognizedString(rt_1, arguments[1]).getStringView();
|
|
494
|
+
|
|
495
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
496
|
+
assumeCorked(rt_1);
|
|
497
|
+
#endif
|
|
426
498
|
provider->res->writeHeader(headerKey, headerVal);
|
|
427
499
|
|
|
428
500
|
return {rt_1, thisValue};
|
|
@@ -438,6 +510,10 @@ public:
|
|
|
438
510
|
const facebook::jsi::Value *arguments,
|
|
439
511
|
size_t count) -> facebook::jsi::Value {
|
|
440
512
|
auto status = RecognizedString(rt_1, arguments[0]).getStringView();
|
|
513
|
+
|
|
514
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
515
|
+
assumeCorked(rt_1);
|
|
516
|
+
#endif
|
|
441
517
|
provider->res->writeStatus(status);
|
|
442
518
|
|
|
443
519
|
return {rt_1, thisValue};
|
|
@@ -19,10 +19,17 @@ private:
|
|
|
19
19
|
|
|
20
20
|
bool valid = false;
|
|
21
21
|
|
|
22
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
23
|
+
void check(facebook::jsi::Runtime &rt) const {
|
|
24
|
+
if(!this->valid) {
|
|
25
|
+
throw facebook::jsi::JSError(rt, "The value is not known by RecognizedString which only recognizes string and ArrayBuffer");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
#endif
|
|
29
|
+
|
|
22
30
|
public:
|
|
23
31
|
RecognizedString(facebook::jsi::Runtime &rt,
|
|
24
|
-
const facebook::jsi::Value &value
|
|
25
|
-
std::optional<bool> withCheck = true) {
|
|
32
|
+
const facebook::jsi::Value &value) {
|
|
26
33
|
if(value.isString()) {
|
|
27
34
|
std::function<void (bool ascii, const void *pData, size_t num)> handler = [this](bool ascii, const void *pData, size_t num) {
|
|
28
35
|
if(ascii) {
|
|
@@ -42,19 +49,13 @@ public:
|
|
|
42
49
|
}
|
|
43
50
|
}
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
public:
|
|
51
|
-
void check(facebook::jsi::Runtime &rt) const {
|
|
52
|
-
if(!this->valid) {
|
|
53
|
-
throw facebook::jsi::JSError(rt, "Text and data can only be passed by string or ArrayBuffer");
|
|
54
|
-
}
|
|
52
|
+
#ifdef REACT_NATIVE_DEBUG
|
|
53
|
+
this->check(rt);
|
|
54
|
+
#endif
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
// Check if the Value is recognized as string
|
|
58
|
+
[[nodiscard]] bool isValid() const {
|
|
58
59
|
return this->valid;
|
|
59
60
|
}
|
|
60
61
|
|
|
@@ -66,6 +67,11 @@ public:
|
|
|
66
67
|
return {this->data, this->length};
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
static bool isValid(facebook::jsi::Runtime &rt,
|
|
71
|
+
const facebook::jsi::Value &value) {
|
|
72
|
+
return value.isString() || (value.isObject() && value.asObject(rt).isArrayBuffer(rt));
|
|
73
|
+
}
|
|
74
|
+
|
|
69
75
|
};
|
|
70
76
|
|
|
71
|
-
}
|
|
77
|
+
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#include <ReactCommon/CallInvoker.h>
|
|
4
4
|
#include <ReactCommon/SchedulerPriority.h>
|
|
5
5
|
#include <jsi/jsi.h>
|
|
6
|
+
#include <react/bridging/Function.h>
|
|
6
7
|
#include "AppRunner.h"
|
|
7
8
|
#include "HttpRequestObject.h"
|
|
8
9
|
#include "HttpResponseObject.h"
|
|
@@ -88,6 +89,7 @@ private:
|
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
// AppRunner thread
|
|
91
93
|
std::function<void (uWS::HttpResponse<false> *res, uWS::HttpRequest *req)> uwsRouteHandler = [&jsInvoker, disableBodyRead, maxBodySize, asyncCallback = facebook::react::AsyncCallback(rt, std::move(callback), jsInvoker)](uWS::HttpResponse<false> *res, uWS::HttpRequest *req) {
|
|
92
94
|
// auto httpResponseObject = std::make_shared<HttpResponseObject>(rt,
|
|
93
95
|
// res,
|
|
@@ -99,6 +101,7 @@ private:
|
|
|
99
101
|
auto sharedRequest = std::make_shared<uWS::HttpRequest>(*req);
|
|
100
102
|
|
|
101
103
|
asyncCallback.callWithPriority(facebook::react::SchedulerPriority::ImmediatePriority, [httpResponseObjectProvider, sharedRequest, &jsInvoker](facebook::jsi::Runtime &rt_1, facebook::jsi::Function &cb) {
|
|
104
|
+
// React Native JS runtime
|
|
102
105
|
if(httpResponseObjectProvider && sharedRequest) {
|
|
103
106
|
cb.call(rt_1,
|
|
104
107
|
HttpResponseObject(rt_1, httpResponseObjectProvider, jsInvoker),
|
|
@@ -248,7 +251,16 @@ public:
|
|
|
248
251
|
const facebook::jsi::Value &thisValue,
|
|
249
252
|
const facebook::jsi::Value *arguments,
|
|
250
253
|
size_t count) -> facebook::jsi::Value {
|
|
251
|
-
|
|
254
|
+
if(!arguments || !arguments[0].isObject()) {
|
|
255
|
+
return {rt_1, thisValue};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
auto obj = arguments[0].asObject(rt_1);
|
|
259
|
+
if(!obj.isFunction(rt_1)) {
|
|
260
|
+
return {rt_1, thisValue};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
auto callback = obj.asFunction(rt_1);
|
|
252
264
|
|
|
253
265
|
appRunner.app.filter([&jsInvoker, asyncCallback = facebook::react::AsyncCallback(rt_1, std::move(callback), jsInvoker)](auto *res, int count) {
|
|
254
266
|
auto httpResponseObjectProvider = std::make_shared<HttpResponseObjectProvider>(res);
|
|
@@ -299,7 +311,7 @@ public:
|
|
|
299
311
|
std::optional<int> options = std::nullopt;
|
|
300
312
|
|
|
301
313
|
if(arguments[0].isString()) {
|
|
302
|
-
host =
|
|
314
|
+
host = arguments[0].asString(rt_1).utf8(rt_1);
|
|
303
315
|
if(arguments[1].isNumber()) {
|
|
304
316
|
port = arguments[1].asNumber();
|
|
305
317
|
}
|
|
@@ -338,8 +350,12 @@ public:
|
|
|
338
350
|
const facebook::jsi::Value &thisValue,
|
|
339
351
|
const facebook::jsi::Value *arguments,
|
|
340
352
|
size_t count) -> facebook::jsi::Value {
|
|
341
|
-
auto topic = RecognizedString(rt_1, arguments[0])
|
|
342
|
-
|
|
353
|
+
auto topic = RecognizedString(rt_1, arguments[0]);
|
|
354
|
+
if(!topic.isValid()) {
|
|
355
|
+
return {rt_1, int(0)};
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return static_cast<int>(appRunner.app.numSubscribers(topic.getStringView()));
|
|
343
359
|
}));
|
|
344
360
|
|
|
345
361
|
this->setProperty(rt,
|
|
@@ -351,8 +367,15 @@ public:
|
|
|
351
367
|
const facebook::jsi::Value &thisValue,
|
|
352
368
|
const facebook::jsi::Value *arguments,
|
|
353
369
|
size_t count) -> facebook::jsi::Value {
|
|
354
|
-
auto topic = RecognizedString(rt_1, arguments[0])
|
|
355
|
-
|
|
370
|
+
auto topic = RecognizedString(rt_1, arguments[0]);
|
|
371
|
+
if(!topic.isValid()) {
|
|
372
|
+
return {rt_1, false};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
auto message = RecognizedString(rt_1, arguments[1]);
|
|
376
|
+
if(!message.isValid()) {
|
|
377
|
+
return {rt_1, false};
|
|
378
|
+
}
|
|
356
379
|
|
|
357
380
|
bool isBinary = false;
|
|
358
381
|
if(arguments[2].isBool()) {
|
|
@@ -364,38 +387,40 @@ public:
|
|
|
364
387
|
compress = arguments[3].asBool();
|
|
365
388
|
}
|
|
366
389
|
|
|
367
|
-
return appRunner.app.publish(topic,
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
390
|
+
return appRunner.app.publish(topic.getStringView(),
|
|
391
|
+
message.getStringView(),
|
|
392
|
+
isBinary ? uWS::OpCode::BINARY : uWS::TEXT,
|
|
393
|
+
compress);
|
|
371
394
|
}));
|
|
372
395
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
396
|
+
this->setProperty(rt,
|
|
397
|
+
"ws",
|
|
398
|
+
facebook::jsi::Function::createFromHostFunction(rt,
|
|
399
|
+
facebook::jsi::PropNameID::forUtf8(rt, "ws"),
|
|
400
|
+
2,
|
|
401
|
+
[&appRunner, &jsInvoker](facebook::jsi::Runtime &rt_1,
|
|
402
|
+
const facebook::jsi::Value &thisValue,
|
|
403
|
+
const facebook::jsi::Value *arguments,
|
|
404
|
+
size_t count) -> facebook::jsi::Value {
|
|
405
|
+
if(!arguments) {
|
|
406
|
+
return {rt_1, thisValue};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
auto pattern = RecognizedString(rt_1, arguments[0]);
|
|
410
|
+
if(!pattern.isValid()) {
|
|
411
|
+
return {rt_1, thisValue};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if(!arguments[1].isObject()) {
|
|
415
|
+
return {rt_1, thisValue};
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
auto behavior = WebSocketBehaviorImpl(rt_1, jsInvoker, arguments[1].asObject(rt_1));
|
|
419
|
+
|
|
420
|
+
appRunner.app.ws(pattern.getString(), std::move(behavior));
|
|
421
|
+
|
|
422
|
+
return {rt_1, thisValue};
|
|
423
|
+
}));
|
|
399
424
|
|
|
400
425
|
// +++++ ROUTER +++++
|
|
401
426
|
|