react-native-windows 0.66.5 → 0.66.9
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/CHANGELOG.json +61 -1
- package/CHANGELOG.md +36 -4
- package/Libraries/Components/Pressable/Pressable.windows.js +33 -0
- package/Libraries/Pressability/HoverState.js +4 -0
- package/Microsoft.ReactNative/Modules/CreateModules.cpp +2 -2
- package/Microsoft.ReactNative/ReactCoreInjection.cpp +4 -11
- package/Microsoft.ReactNative/ReactHost/ReactHost.cpp +6 -1
- package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +17 -10
- package/Mso/future/futureWinRT.h +7 -5
- package/Shared/IWebSocketResource.h +6 -6
- package/Shared/InspectorPackagerConnection.cpp +2 -3
- package/Shared/Modules/WebSocketModule.cpp +133 -120
- package/Shared/Modules/WebSocketModule.h +22 -12
- package/Shared/OInstance.cpp +3 -92
- package/Shared/WinRTWebSocketResource.cpp +55 -46
- package/Shared/WinRTWebSocketResource.h +2 -9
- package/package.json +5 -5
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,67 @@
|
|
|
2
2
|
"name": "react-native-windows",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "Mon,
|
|
5
|
+
"date": "Mon, 31 Jan 2022 16:12:08 GMT",
|
|
6
|
+
"tag": "react-native-windows_v0.66.9",
|
|
7
|
+
"version": "0.66.9",
|
|
8
|
+
"comments": {
|
|
9
|
+
"patch": [
|
|
10
|
+
{
|
|
11
|
+
"comment": "Better reporting of failures to load the bundle file",
|
|
12
|
+
"author": "30809111+acoates-ms@users.noreply.github.com",
|
|
13
|
+
"commit": "0951f3da2e746f1feb0bd7e96d3dd8d5d936d6fb",
|
|
14
|
+
"package": "react-native-windows"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"date": "Mon, 24 Jan 2022 16:11:33 GMT",
|
|
21
|
+
"tag": "react-native-windows_v0.66.8",
|
|
22
|
+
"version": "0.66.8",
|
|
23
|
+
"comments": {
|
|
24
|
+
"patch": [
|
|
25
|
+
{
|
|
26
|
+
"comment": "Promote 0.66 to legacy",
|
|
27
|
+
"author": "ngerlem@microsoft.com",
|
|
28
|
+
"commit": "919d91a3e9845f9a60417fb8e47a36d7caedbc28",
|
|
29
|
+
"package": "react-native-windows"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"date": "Mon, 17 Jan 2022 16:12:35 GMT",
|
|
36
|
+
"tag": "react-native-windows_v0.66.7",
|
|
37
|
+
"version": "0.66.7",
|
|
38
|
+
"comments": {
|
|
39
|
+
"patch": [
|
|
40
|
+
{
|
|
41
|
+
"comment": "Fork HoverState.js to allow hover events on Pressable",
|
|
42
|
+
"author": "saadnajmi2@gmail.com",
|
|
43
|
+
"commit": "1a70a3b499a0e695597e8669439b856d41096170",
|
|
44
|
+
"package": "react-native-windows"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"date": "Mon, 03 Jan 2022 16:10:55 GMT",
|
|
51
|
+
"tag": "react-native-windows_v0.66.6",
|
|
52
|
+
"version": "0.66.6",
|
|
53
|
+
"comments": {
|
|
54
|
+
"patch": [
|
|
55
|
+
{
|
|
56
|
+
"comment": "[0.66] Avoid capturing raw this pointer in WebSocket module",
|
|
57
|
+
"author": "julio.rocha@microsoft.com",
|
|
58
|
+
"commit": "1a0cec7754fdff58dad91fb15c483e884ef70aee",
|
|
59
|
+
"package": "react-native-windows"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"date": "Mon, 22 Nov 2021 16:09:58 GMT",
|
|
6
66
|
"tag": "react-native-windows_v0.66.5",
|
|
7
67
|
"version": "0.66.5",
|
|
8
68
|
"comments": {
|
package/CHANGELOG.md
CHANGED
|
@@ -1,17 +1,49 @@
|
|
|
1
1
|
# Change Log - react-native-windows
|
|
2
2
|
|
|
3
|
-
This log was last generated on Mon,
|
|
3
|
+
This log was last generated on Mon, 31 Jan 2022 16:12:08 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
-
## 0.66.
|
|
7
|
+
## 0.66.9
|
|
8
8
|
|
|
9
|
-
Mon,
|
|
9
|
+
Mon, 31 Jan 2022 16:12:08 GMT
|
|
10
10
|
|
|
11
11
|
### Patches
|
|
12
12
|
|
|
13
|
-
-
|
|
13
|
+
- Better reporting of failures to load the bundle file (30809111+acoates-ms@users.noreply.github.com)
|
|
14
14
|
|
|
15
|
+
## 0.66.8
|
|
16
|
+
|
|
17
|
+
Mon, 24 Jan 2022 16:11:33 GMT
|
|
18
|
+
|
|
19
|
+
### Patches
|
|
20
|
+
|
|
21
|
+
- Promote 0.66 to legacy (ngerlem@microsoft.com)
|
|
22
|
+
|
|
23
|
+
## 0.66.7
|
|
24
|
+
|
|
25
|
+
Mon, 17 Jan 2022 16:12:35 GMT
|
|
26
|
+
|
|
27
|
+
### Patches
|
|
28
|
+
|
|
29
|
+
- Fork HoverState.js to allow hover events on Pressable (saadnajmi2@gmail.com)
|
|
30
|
+
|
|
31
|
+
## 0.66.6
|
|
32
|
+
|
|
33
|
+
Mon, 03 Jan 2022 16:10:55 GMT
|
|
34
|
+
|
|
35
|
+
### Patches
|
|
36
|
+
|
|
37
|
+
- [0.66] Avoid capturing raw this pointer in WebSocket module (julio.rocha@microsoft.com)
|
|
38
|
+
|
|
39
|
+
## 0.66.5
|
|
40
|
+
|
|
41
|
+
Mon, 22 Nov 2021 16:09:58 GMT
|
|
42
|
+
|
|
43
|
+
### Patches
|
|
44
|
+
|
|
45
|
+
- Fix C# Module Event invocation (vmorozov@microsoft.com)
|
|
46
|
+
|
|
15
47
|
## 0.66.4
|
|
16
48
|
|
|
17
49
|
Mon, 15 Nov 2021 16:09:53 GMT
|
|
@@ -25,6 +25,7 @@ import usePressability from '../../Pressability/usePressability';
|
|
|
25
25
|
import {normalizeRect, type RectOrSize} from '../../StyleSheet/Rect';
|
|
26
26
|
import type {
|
|
27
27
|
LayoutEvent,
|
|
28
|
+
MouseEvent,
|
|
28
29
|
PressEvent,
|
|
29
30
|
// [Windows
|
|
30
31
|
BlurEvent,
|
|
@@ -72,6 +73,16 @@ type Props = $ReadOnly<{|
|
|
|
72
73
|
*/
|
|
73
74
|
children: React.Node | ((state: StateCallbackType) => React.Node),
|
|
74
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Duration to wait after hover in before calling `onHoverIn`.
|
|
78
|
+
*/
|
|
79
|
+
delayHoverIn?: ?number,
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Duration to wait after hover out before calling `onHoverOut`.
|
|
83
|
+
*/
|
|
84
|
+
delayHoverOut?: ?number,
|
|
85
|
+
|
|
75
86
|
/**
|
|
76
87
|
* Duration (in milliseconds) from `onPressIn` before `onLongPress` is called.
|
|
77
88
|
*/
|
|
@@ -98,6 +109,16 @@ type Props = $ReadOnly<{|
|
|
|
98
109
|
*/
|
|
99
110
|
onLayout?: ?(event: LayoutEvent) => mixed,
|
|
100
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Called when the hover is activated to provide visual feedback.
|
|
114
|
+
*/
|
|
115
|
+
onHoverIn?: ?(event: MouseEvent) => mixed,
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Called when the hover is deactivated to undo visual feedback.
|
|
119
|
+
*/
|
|
120
|
+
onHoverOut?: ?(event: MouseEvent) => mixed,
|
|
121
|
+
|
|
101
122
|
/**
|
|
102
123
|
* Called when a long-tap gesture is detected.
|
|
103
124
|
*/
|
|
@@ -201,9 +222,13 @@ function Pressable(props: Props, forwardedRef): React.Node {
|
|
|
201
222
|
android_ripple,
|
|
202
223
|
cancelable,
|
|
203
224
|
children,
|
|
225
|
+
delayHoverIn,
|
|
226
|
+
delayHoverOut,
|
|
204
227
|
delayLongPress,
|
|
205
228
|
disabled,
|
|
206
229
|
focusable,
|
|
230
|
+
onHoverIn,
|
|
231
|
+
onHoverOut,
|
|
207
232
|
onLongPress,
|
|
208
233
|
onPress,
|
|
209
234
|
onPressIn,
|
|
@@ -267,8 +292,12 @@ function Pressable(props: Props, forwardedRef): React.Node {
|
|
|
267
292
|
hitSlop,
|
|
268
293
|
pressRectOffset: pressRetentionOffset,
|
|
269
294
|
android_disableSound,
|
|
295
|
+
delayHoverIn,
|
|
296
|
+
delayHoverOut,
|
|
270
297
|
delayLongPress,
|
|
271
298
|
delayPressIn: unstable_pressDelay,
|
|
299
|
+
onHoverIn,
|
|
300
|
+
onHoverOut,
|
|
272
301
|
onLongPress,
|
|
273
302
|
onPress,
|
|
274
303
|
onPressIn(event: PressEvent): void {
|
|
@@ -301,9 +330,13 @@ function Pressable(props: Props, forwardedRef): React.Node {
|
|
|
301
330
|
android_disableSound,
|
|
302
331
|
android_rippleConfig,
|
|
303
332
|
cancelable,
|
|
333
|
+
delayHoverIn,
|
|
334
|
+
delayHoverOut,
|
|
304
335
|
delayLongPress,
|
|
305
336
|
disabled,
|
|
306
337
|
hitSlop,
|
|
338
|
+
onHoverIn,
|
|
339
|
+
onHoverOut,
|
|
307
340
|
onLongPress,
|
|
308
341
|
onPress,
|
|
309
342
|
onPressIn,
|
|
@@ -49,6 +49,10 @@ if (Platform.OS === 'web') {
|
|
|
49
49
|
document.addEventListener('touchmove', disableHover, true);
|
|
50
50
|
document.addEventListener('mousemove', enableHover, true);
|
|
51
51
|
}
|
|
52
|
+
// [Windows
|
|
53
|
+
} else if (Platform.OS === 'windows') {
|
|
54
|
+
isEnabled = true;
|
|
55
|
+
// Windows]
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
export function isHoverEnabled(): boolean {
|
|
@@ -19,9 +19,9 @@ using winrt::Microsoft::ReactNative::implementation::QuirkSettings;
|
|
|
19
19
|
|
|
20
20
|
namespace Microsoft::React {
|
|
21
21
|
|
|
22
|
-
std::shared_ptr<IWebSocketResource> IWebSocketResource::Make(
|
|
22
|
+
std::shared_ptr<IWebSocketResource> IWebSocketResource::Make() {
|
|
23
23
|
std::vector<winrt::Windows::Security::Cryptography::Certificates::ChainValidationResult> certExceptions;
|
|
24
|
-
return std::make_shared<WinRTWebSocketResource>(std::move(
|
|
24
|
+
return std::make_shared<WinRTWebSocketResource>(std::move(certExceptions));
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
} // namespace Microsoft::React
|
|
@@ -139,14 +139,9 @@ struct ReactViewInstance : public Mso::UnknownObject<Mso::RefCountStrategy::Weak
|
|
|
139
139
|
inline Mso::Future<void> PostInUIQueue(winrt::delegate<ReactNative::IReactViewInstance> const &action) noexcept {
|
|
140
140
|
Mso::Promise<void> promise;
|
|
141
141
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
action(strongThis->m_rootControl);
|
|
146
|
-
promise.SetValue();
|
|
147
|
-
} else {
|
|
148
|
-
promise.TryCancel();
|
|
149
|
-
}
|
|
142
|
+
m_uiDispatcher.Post([control = m_rootControl, promise, action{std::move(action)}]() mutable noexcept {
|
|
143
|
+
action(control);
|
|
144
|
+
promise.SetValue();
|
|
150
145
|
});
|
|
151
146
|
return promise.AsFuture();
|
|
152
147
|
}
|
|
@@ -159,9 +154,7 @@ winrt::Windows::Foundation::IAsyncAction ReactViewHost::AttachViewInstance(
|
|
|
159
154
|
}
|
|
160
155
|
|
|
161
156
|
winrt::Windows::Foundation::IAsyncAction ReactViewHost::DetachViewInstance() noexcept {
|
|
162
|
-
Mso::
|
|
163
|
-
promise.SetValue();
|
|
164
|
-
return make<Mso::AsyncActionFutureAdapter>(promise.AsFuture());
|
|
157
|
+
return make<Mso::AsyncActionFutureAdapter>(m_viewHost->DetachViewInstance());
|
|
165
158
|
}
|
|
166
159
|
|
|
167
160
|
} // namespace winrt::Microsoft::ReactNative::implementation
|
|
@@ -379,8 +379,13 @@ Mso::Future<void> ReactHost::LoadInQueue(ReactOptions &&options) noexcept {
|
|
|
379
379
|
}
|
|
380
380
|
}
|
|
381
381
|
|
|
382
|
-
return whenLoaded.AsFuture().Then(m_executor, [this](Mso::Maybe<void> &&
|
|
382
|
+
return whenLoaded.AsFuture().Then(m_executor, [this](Mso::Maybe<void> &&value) noexcept {
|
|
383
383
|
std::vector<Mso::Future<void>> loadCompletionList;
|
|
384
|
+
|
|
385
|
+
if (value.IsError()) {
|
|
386
|
+
return Mso::MakeFailedFuture<void>(std::move(value.TakeError()));
|
|
387
|
+
}
|
|
388
|
+
|
|
384
389
|
ForEachViewHost([&loadCompletionList](auto &viewHost) noexcept {
|
|
385
390
|
loadCompletionList.push_back(viewHost.UpdateViewInstanceInQueue());
|
|
386
391
|
});
|
|
@@ -224,9 +224,11 @@ ReactInstanceWin::ReactInstanceWin(
|
|
|
224
224
|
m_whenLoaded.AsFuture()
|
|
225
225
|
.Then<Mso::Executors::Inline>(
|
|
226
226
|
[onLoaded = m_options.OnInstanceLoaded, reactContext = m_reactContext](Mso::Maybe<void> &&value) noexcept {
|
|
227
|
+
auto errCode = value.IsError() ? value.TakeError() : Mso::ErrorCode();
|
|
227
228
|
if (onLoaded) {
|
|
228
|
-
onLoaded.Get()->Invoke(reactContext,
|
|
229
|
+
onLoaded.Get()->Invoke(reactContext, errCode);
|
|
229
230
|
}
|
|
231
|
+
return Mso::Maybe<void>(errCode);
|
|
230
232
|
})
|
|
231
233
|
.Then(Queue(), [whenLoaded = std::move(whenLoaded)](Mso::Maybe<void> &&value) noexcept {
|
|
232
234
|
whenLoaded.SetValue(std::move(value));
|
|
@@ -468,7 +470,7 @@ void ReactInstanceWin::Initialize() noexcept {
|
|
|
468
470
|
m_options.TurboModuleProvider,
|
|
469
471
|
std::make_unique<BridgeUIBatchInstanceCallback>(weakThis),
|
|
470
472
|
m_jsMessageThread.Load(),
|
|
471
|
-
|
|
473
|
+
m_nativeMessageThread.Load(),
|
|
472
474
|
std::move(devSettings));
|
|
473
475
|
|
|
474
476
|
m_instanceWrapper.Exchange(std::move(instanceWrapper));
|
|
@@ -483,6 +485,16 @@ void ReactInstanceWin::Initialize() noexcept {
|
|
|
483
485
|
}
|
|
484
486
|
#endif
|
|
485
487
|
|
|
488
|
+
// The InstanceCreated event can be used to augment the JS environment for all JS code. So it needs to be
|
|
489
|
+
// triggered before any platform JS code is run. Using m_jsMessageThread instead of jsDispatchQueue avoids
|
|
490
|
+
// waiting for the JSCaller which can delay the event until after certain JS code has already run
|
|
491
|
+
m_jsMessageThread.Load()->runOnQueue(
|
|
492
|
+
[onCreated = m_options.OnInstanceCreated, reactContext = m_reactContext]() noexcept {
|
|
493
|
+
if (onCreated) {
|
|
494
|
+
onCreated.Get()->Invoke(reactContext);
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
|
|
486
498
|
LoadJSBundles();
|
|
487
499
|
|
|
488
500
|
if (UseDeveloperSupport() && State() != ReactInstanceState::HasError) {
|
|
@@ -558,7 +570,9 @@ void ReactInstanceWin::LoadJSBundles() noexcept {
|
|
|
558
570
|
|
|
559
571
|
try {
|
|
560
572
|
instanceWrapper->loadBundleSync(Mso::Copy(strongThis->JavaScriptBundleFile()));
|
|
561
|
-
strongThis->
|
|
573
|
+
if (strongThis->State() != ReactInstanceState::HasError) {
|
|
574
|
+
strongThis->OnReactInstanceLoaded(Mso::ErrorCode{});
|
|
575
|
+
}
|
|
562
576
|
} catch (...) {
|
|
563
577
|
strongThis->OnReactInstanceLoaded(Mso::ExceptionErrorProvider().MakeErrorCode(std::current_exception()));
|
|
564
578
|
}
|
|
@@ -629,13 +643,6 @@ void ReactInstanceWin::InitJSMessageThread() noexcept {
|
|
|
629
643
|
Mso::Copy(m_whenDestroyed));
|
|
630
644
|
auto jsDispatchQueue = Mso::DispatchQueue::MakeCustomQueue(Mso::CntPtr(scheduler));
|
|
631
645
|
|
|
632
|
-
// This work item will be processed as a first item in JS queue when the react instance is created.
|
|
633
|
-
jsDispatchQueue.Post([onCreated = m_options.OnInstanceCreated, reactContext = m_reactContext]() noexcept {
|
|
634
|
-
if (onCreated) {
|
|
635
|
-
onCreated.Get()->Invoke(reactContext);
|
|
636
|
-
}
|
|
637
|
-
});
|
|
638
|
-
|
|
639
646
|
auto jsDispatcher =
|
|
640
647
|
winrt::make<winrt::Microsoft::ReactNative::implementation::ReactDispatcher>(Mso::Copy(jsDispatchQueue));
|
|
641
648
|
m_options.Properties.Set(ReactDispatcherHelper::JSDispatcherProperty(), jsDispatcher);
|
package/Mso/future/futureWinRT.h
CHANGED
|
@@ -27,18 +27,20 @@ struct AsyncActionFutureAdapter : winrt::implements<
|
|
|
27
27
|
if (strongThis->m_status == AsyncStatus::Started) {
|
|
28
28
|
if (result.IsValue()) {
|
|
29
29
|
strongThis->m_status = AsyncStatus::Completed;
|
|
30
|
-
if (strongThis->m_completedAssigned) {
|
|
31
|
-
handler = std::move(strongThis->m_completed);
|
|
32
|
-
}
|
|
33
30
|
} else {
|
|
34
|
-
strongThis->m_status = AsyncStatus::Error;
|
|
35
31
|
strongThis->m_error = result.GetError();
|
|
32
|
+
strongThis->m_status = Mso::CancellationErrorProvider().TryGetErrorInfo(strongThis->m_error, false)
|
|
33
|
+
? AsyncStatus::Canceled
|
|
34
|
+
: AsyncStatus::Error;
|
|
35
|
+
}
|
|
36
|
+
if (strongThis->m_completedAssigned) {
|
|
37
|
+
handler = std::move(strongThis->m_completed);
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
if (handler) {
|
|
41
|
-
invoke(handler, *strongThis,
|
|
43
|
+
invoke(handler, *strongThis, strongThis->m_status);
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
});
|
|
@@ -79,17 +79,17 @@ struct IWebSocketResource {
|
|
|
79
79
|
/// <summary>
|
|
80
80
|
/// Creates an <c>IWebSocketResource</c> instance.
|
|
81
81
|
/// </summary>
|
|
82
|
-
|
|
83
|
-
/// WebSocket URL address the instance will connect to.
|
|
84
|
-
/// The address's scheme can be either ws:// or wss://.
|
|
85
|
-
/// </param>
|
|
86
|
-
static std::shared_ptr<IWebSocketResource> Make(std::string &&url);
|
|
82
|
+
static std::shared_ptr<IWebSocketResource> Make();
|
|
87
83
|
|
|
88
84
|
virtual ~IWebSocketResource() noexcept {}
|
|
89
85
|
|
|
90
86
|
/// <summary>
|
|
91
87
|
/// Establishes a continuous connection with the remote endpoint.
|
|
92
88
|
/// </summary>
|
|
89
|
+
/// <param name="url">
|
|
90
|
+
/// WebSocket URL address the instance will connect to.
|
|
91
|
+
/// The address's scheme can be either ws:// or wss://.
|
|
92
|
+
/// </param>
|
|
93
93
|
/// <param name="protocols">
|
|
94
94
|
/// Currently unused
|
|
95
95
|
/// </param>
|
|
@@ -97,7 +97,7 @@ struct IWebSocketResource {
|
|
|
97
97
|
/// HTTP header fields passed by the remote endpoint, to be used in the
|
|
98
98
|
/// handshake process.
|
|
99
99
|
/// </param>
|
|
100
|
-
virtual void Connect(const Protocols &protocols = {}, const Options &options = {}) noexcept = 0;
|
|
100
|
+
virtual void Connect(std::string &&url, const Protocols &protocols = {}, const Options &options = {}) noexcept = 0;
|
|
101
101
|
|
|
102
102
|
/// <summary>
|
|
103
103
|
/// Sends a ping frame to the remote endpoint.
|
|
@@ -204,8 +204,7 @@ winrt::fire_and_forget InspectorPackagerConnection::connectAsync() {
|
|
|
204
204
|
co_await winrt::resume_background();
|
|
205
205
|
|
|
206
206
|
std::vector<winrt::Windows::Security::Cryptography::Certificates::ChainValidationResult> certExceptions;
|
|
207
|
-
m_packagerWebSocketConnection =
|
|
208
|
-
std::make_shared<Microsoft::React::WinRTWebSocketResource>(m_url, std::move(certExceptions));
|
|
207
|
+
m_packagerWebSocketConnection = std::make_shared<Microsoft::React::WinRTWebSocketResource>(std::move(certExceptions));
|
|
209
208
|
|
|
210
209
|
m_packagerWebSocketConnection->SetOnError([](const Microsoft::React::IWebSocketResource::Error &err) {
|
|
211
210
|
facebook::react::tracing::error(err.Message.c_str());
|
|
@@ -270,7 +269,7 @@ winrt::fire_and_forget InspectorPackagerConnection::connectAsync() {
|
|
|
270
269
|
|
|
271
270
|
Microsoft::React::IWebSocketResource::Protocols protocols;
|
|
272
271
|
Microsoft::React::IWebSocketResource::Options options;
|
|
273
|
-
m_packagerWebSocketConnection->Connect(protocols, options);
|
|
272
|
+
m_packagerWebSocketConnection->Connect(std::string{m_url}, protocols, options);
|
|
274
273
|
|
|
275
274
|
co_return;
|
|
276
275
|
}
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
#include <iomanip>
|
|
15
15
|
|
|
16
16
|
using namespace facebook::xplat;
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
using facebook::react::Instance;
|
|
19
|
+
using folly::dynamic;
|
|
18
20
|
|
|
19
21
|
using Microsoft::Common::Unicode::Utf16ToUtf8;
|
|
20
22
|
using Microsoft::Common::Unicode::Utf8ToUtf16;
|
|
@@ -24,17 +26,111 @@ using std::string;
|
|
|
24
26
|
using std::weak_ptr;
|
|
25
27
|
|
|
26
28
|
namespace {
|
|
29
|
+
using Microsoft::React::IWebSocketResource;
|
|
30
|
+
using Microsoft::React::WebSocketModule;
|
|
31
|
+
|
|
27
32
|
constexpr char moduleName[] = "WebSocketModule";
|
|
33
|
+
|
|
34
|
+
static void SendEvent(weak_ptr<Instance> weakInstance, string &&eventName, dynamic &&args) {
|
|
35
|
+
if (auto instance = weakInstance.lock()) {
|
|
36
|
+
instance->callJSFunction("RCTDeviceEventEmitter", "emit", dynamic::array(std::move(eventName), std::move(args)));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static shared_ptr<IWebSocketResource>
|
|
41
|
+
GetOrCreateWebSocket(int64_t id, string &&url, weak_ptr<WebSocketModule::SharedState> weakState) {
|
|
42
|
+
auto state = weakState.lock();
|
|
43
|
+
if (!state) {
|
|
44
|
+
return nullptr;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
auto itr = state->ResourceMap.find(id);
|
|
48
|
+
if (itr == state->ResourceMap.end()) {
|
|
49
|
+
if (!state->Module) {
|
|
50
|
+
return nullptr;
|
|
51
|
+
}
|
|
52
|
+
auto weakInstance = state->Module->getInstance();
|
|
53
|
+
|
|
54
|
+
shared_ptr<IWebSocketResource> ws;
|
|
55
|
+
try {
|
|
56
|
+
ws = state->ResourceFactory(std::move(url));
|
|
57
|
+
} catch (const winrt::hresult_error &e) {
|
|
58
|
+
std::stringstream ss;
|
|
59
|
+
ss << "[" << std::hex << std::showbase << std::setw(8) << static_cast<uint32_t>(e.code()) << "] "
|
|
60
|
+
<< winrt::to_string(e.message());
|
|
61
|
+
|
|
62
|
+
SendEvent(weakInstance, "webSocketFailed", dynamic::object("id", id)("message", std::move(ss.str())));
|
|
63
|
+
|
|
64
|
+
return nullptr;
|
|
65
|
+
} catch (const std::exception &e) {
|
|
66
|
+
SendEvent(weakInstance, "webSocketFailed", dynamic::object("id", id)("message", e.what()));
|
|
67
|
+
|
|
68
|
+
return nullptr;
|
|
69
|
+
} catch (...) {
|
|
70
|
+
SendEvent(
|
|
71
|
+
weakInstance,
|
|
72
|
+
"webSocketFailed",
|
|
73
|
+
dynamic::object("id", id)("message", "Unidentified error creating IWebSocketResource"));
|
|
74
|
+
|
|
75
|
+
return nullptr;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
ws->SetOnError([id, weakInstance](const IWebSocketResource::Error &err) {
|
|
79
|
+
auto strongInstance = weakInstance.lock();
|
|
80
|
+
if (!strongInstance)
|
|
81
|
+
return;
|
|
82
|
+
|
|
83
|
+
auto errorObj = dynamic::object("id", id)("message", err.Message);
|
|
84
|
+
SendEvent(weakInstance, "websocketFailed", std::move(errorObj));
|
|
85
|
+
});
|
|
86
|
+
ws->SetOnConnect([id, weakInstance]() {
|
|
87
|
+
auto strongInstance = weakInstance.lock();
|
|
88
|
+
if (!strongInstance)
|
|
89
|
+
return;
|
|
90
|
+
|
|
91
|
+
auto args = dynamic::object("id", id);
|
|
92
|
+
SendEvent(weakInstance, "websocketOpen", std::move(args));
|
|
93
|
+
});
|
|
94
|
+
ws->SetOnMessage([id, weakInstance](size_t length, const string &message, bool isBinary) {
|
|
95
|
+
auto strongInstance = weakInstance.lock();
|
|
96
|
+
if (!strongInstance)
|
|
97
|
+
return;
|
|
98
|
+
|
|
99
|
+
auto args = dynamic::object("id", id)("data", message)("type", isBinary ? "binary" : "text");
|
|
100
|
+
SendEvent(weakInstance, "websocketMessage", std::move(args));
|
|
101
|
+
});
|
|
102
|
+
ws->SetOnClose([id, weakInstance](IWebSocketResource::CloseCode code, const string &reason) {
|
|
103
|
+
auto strongInstance = weakInstance.lock();
|
|
104
|
+
if (!strongInstance)
|
|
105
|
+
return;
|
|
106
|
+
|
|
107
|
+
auto args = dynamic::object("id", id)("code", static_cast<uint16_t>(code))("reason", reason);
|
|
108
|
+
SendEvent(weakInstance, "websocketClosed", std::move(args));
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
state->ResourceMap.emplace(id, ws);
|
|
112
|
+
return ws;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return itr->second;
|
|
116
|
+
}
|
|
117
|
+
|
|
28
118
|
} // anonymous namespace
|
|
29
119
|
|
|
30
120
|
namespace Microsoft::React {
|
|
31
121
|
|
|
32
|
-
WebSocketModule::WebSocketModule()
|
|
33
|
-
|
|
122
|
+
WebSocketModule::WebSocketModule() : m_sharedState{std::make_shared<SharedState>()} {
|
|
123
|
+
m_sharedState->ResourceFactory = [](string &&url) { return IWebSocketResource::Make(); };
|
|
124
|
+
m_sharedState->Module = this;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
WebSocketModule::~WebSocketModule() noexcept /*override*/ {
|
|
128
|
+
m_sharedState->Module = nullptr;
|
|
129
|
+
}
|
|
34
130
|
|
|
35
131
|
void WebSocketModule::SetResourceFactory(
|
|
36
132
|
std::function<shared_ptr<IWebSocketResource>(const string &)> &&resourceFactory) {
|
|
37
|
-
|
|
133
|
+
m_sharedState->ResourceFactory = std::move(resourceFactory);
|
|
38
134
|
}
|
|
39
135
|
|
|
40
136
|
string WebSocketModule::getName() {
|
|
@@ -50,9 +146,9 @@ std::vector<facebook::xplat::module::CxxModule::Method> WebSocketModule::getMeth
|
|
|
50
146
|
{
|
|
51
147
|
return
|
|
52
148
|
{
|
|
53
|
-
|
|
149
|
+
{
|
|
54
150
|
"connect",
|
|
55
|
-
[
|
|
151
|
+
[weakState = weak_ptr<SharedState>(m_sharedState)](dynamic args) // const string& url, dynamic protocols, dynamic options, int64_t id
|
|
56
152
|
{
|
|
57
153
|
IWebSocketResource::Protocols protocols;
|
|
58
154
|
dynamic protocolsDynamic = jsArgAsDynamic(args, 1);
|
|
@@ -75,20 +171,21 @@ std::vector<facebook::xplat::module::CxxModule::Method> WebSocketModule::getMeth
|
|
|
75
171
|
}
|
|
76
172
|
}
|
|
77
173
|
|
|
78
|
-
weak_ptr weakWs =
|
|
174
|
+
weak_ptr weakWs = GetOrCreateWebSocket(jsArgAsInt(args, 3), jsArgAsString(args, 0), weakState);
|
|
79
175
|
if (auto sharedWs = weakWs.lock())
|
|
80
176
|
{
|
|
81
|
-
sharedWs->Connect(protocols, options);
|
|
177
|
+
sharedWs->Connect(jsArgAsString(args, 0), protocols, options);
|
|
82
178
|
}
|
|
83
|
-
}
|
|
84
|
-
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
{
|
|
85
182
|
"close",
|
|
86
|
-
[
|
|
183
|
+
[weakState = weak_ptr<SharedState>(m_sharedState)](dynamic args) // [int64_t code, string reason,] int64_t id
|
|
87
184
|
{
|
|
88
185
|
// See react-native\Libraries\WebSocket\WebSocket.js:_close
|
|
89
186
|
if (args.size() == 3) // WebSocketModule.close(statusCode, closeReason, this._socketId);
|
|
90
187
|
{
|
|
91
|
-
weak_ptr weakWs =
|
|
188
|
+
weak_ptr weakWs = GetOrCreateWebSocket(jsArgAsInt(args, 2), {}, weakState);
|
|
92
189
|
if (auto sharedWs = weakWs.lock())
|
|
93
190
|
{
|
|
94
191
|
sharedWs->Close(static_cast<IWebSocketResource::CloseCode>(jsArgAsInt(args, 0)), jsArgAsString(args, 1));
|
|
@@ -96,7 +193,7 @@ std::vector<facebook::xplat::module::CxxModule::Method> WebSocketModule::getMeth
|
|
|
96
193
|
}
|
|
97
194
|
else if (args.size() == 1) // WebSocketModule.close(this._socketId);
|
|
98
195
|
{
|
|
99
|
-
weak_ptr weakWs =
|
|
196
|
+
weak_ptr weakWs = GetOrCreateWebSocket(jsArgAsInt(args, 0), {}, weakState);
|
|
100
197
|
if (auto sharedWs = weakWs.lock())
|
|
101
198
|
{
|
|
102
199
|
sharedWs->Close(IWebSocketResource::CloseCode::Normal, {});
|
|
@@ -104,137 +201,53 @@ std::vector<facebook::xplat::module::CxxModule::Method> WebSocketModule::getMeth
|
|
|
104
201
|
}
|
|
105
202
|
else
|
|
106
203
|
{
|
|
107
|
-
auto
|
|
108
|
-
|
|
204
|
+
auto state = weakState.lock();
|
|
205
|
+
if (state && state->Module) {
|
|
206
|
+
auto errorObj = dynamic::object("id", -1)("message", "Incorrect number of parameters");
|
|
207
|
+
SendEvent(state->Module->getInstance(), "websocketFailed", std::move(errorObj));
|
|
208
|
+
}
|
|
109
209
|
}
|
|
110
|
-
}
|
|
111
|
-
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
{
|
|
112
213
|
"send",
|
|
113
|
-
[
|
|
214
|
+
[weakState = weak_ptr<SharedState>(m_sharedState)](dynamic args) // const string& message, int64_t id
|
|
114
215
|
{
|
|
115
|
-
weak_ptr weakWs =
|
|
216
|
+
weak_ptr weakWs = GetOrCreateWebSocket(jsArgAsInt(args, 1), {}, weakState);
|
|
116
217
|
if (auto sharedWs = weakWs.lock())
|
|
117
218
|
{
|
|
118
219
|
sharedWs->Send(jsArgAsString(args, 0));
|
|
119
220
|
}
|
|
120
|
-
}
|
|
121
|
-
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
{
|
|
122
224
|
"sendBinary",
|
|
123
|
-
[
|
|
225
|
+
[weakState = weak_ptr<SharedState>(m_sharedState)](dynamic args) // const string& base64String, int64_t id
|
|
124
226
|
{
|
|
125
|
-
weak_ptr weakWs =
|
|
227
|
+
weak_ptr weakWs = GetOrCreateWebSocket(jsArgAsInt(args, 1), {}, weakState);
|
|
126
228
|
if (auto sharedWs = weakWs.lock())
|
|
127
229
|
{
|
|
128
230
|
sharedWs->SendBinary(jsArgAsString(args, 0));
|
|
129
231
|
}
|
|
130
|
-
}
|
|
131
|
-
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
{
|
|
132
235
|
"ping",
|
|
133
|
-
[
|
|
236
|
+
[weakState = weak_ptr<SharedState>(m_sharedState)](dynamic args) // int64_t id
|
|
134
237
|
{
|
|
135
|
-
weak_ptr weakWs =
|
|
238
|
+
weak_ptr weakWs = GetOrCreateWebSocket(jsArgAsInt(args, 0), {}, weakState);
|
|
136
239
|
if (auto sharedWs = weakWs.lock())
|
|
137
240
|
{
|
|
138
241
|
sharedWs->Ping();
|
|
139
242
|
}
|
|
140
|
-
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
141
245
|
};
|
|
142
246
|
} // getMethods
|
|
143
247
|
// clang-format on
|
|
144
248
|
|
|
145
|
-
#pragma region private members
|
|
146
|
-
|
|
147
|
-
void WebSocketModule::SendEvent(string &&eventName, dynamic &&args) {
|
|
148
|
-
auto weakInstance = this->getInstance();
|
|
149
|
-
if (auto instance = weakInstance.lock()) {
|
|
150
|
-
instance->callJSFunction("RCTDeviceEventEmitter", "emit", dynamic::array(std::move(eventName), std::move(args)));
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// clang-format off
|
|
155
|
-
shared_ptr<IWebSocketResource> WebSocketModule::GetOrCreateWebSocket(int64_t id, string&& url)
|
|
156
|
-
{
|
|
157
|
-
auto itr = m_webSockets.find(id);
|
|
158
|
-
if (itr == m_webSockets.end())
|
|
159
|
-
{
|
|
160
|
-
shared_ptr<IWebSocketResource> ws;
|
|
161
|
-
try
|
|
162
|
-
{
|
|
163
|
-
ws = m_resourceFactory(std::move(url));
|
|
164
|
-
}
|
|
165
|
-
catch (const winrt::hresult_error& e)
|
|
166
|
-
{
|
|
167
|
-
std::stringstream ss;
|
|
168
|
-
ss << "[" << std::hex << std::showbase << std::setw(8) << static_cast<uint32_t>(e.code()) << "] " <<
|
|
169
|
-
winrt::to_string(e.message());
|
|
170
|
-
|
|
171
|
-
SendEvent("webSocketFailed", dynamic::object("id", id)("message", std::move(ss.str())));
|
|
172
|
-
|
|
173
|
-
return nullptr;
|
|
174
|
-
}
|
|
175
|
-
catch (const std::exception& e)
|
|
176
|
-
{
|
|
177
|
-
SendEvent("webSocketFailed", dynamic::object("id", id)("message", e.what()));
|
|
178
|
-
|
|
179
|
-
return nullptr;
|
|
180
|
-
}
|
|
181
|
-
catch (...)
|
|
182
|
-
{
|
|
183
|
-
SendEvent("webSocketFailed", dynamic::object("id", id)("message", "Unidentified error creating IWebSocketResource"));
|
|
184
|
-
|
|
185
|
-
return nullptr;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
auto weakInstance = this->getInstance();
|
|
189
|
-
ws->SetOnError([this, id, weakInstance](const IWebSocketResource::Error& err)
|
|
190
|
-
{
|
|
191
|
-
auto strongInstance = weakInstance.lock();
|
|
192
|
-
if (!strongInstance)
|
|
193
|
-
return;
|
|
194
|
-
|
|
195
|
-
auto errorObj = dynamic::object("id", id)("message", err.Message);
|
|
196
|
-
this->SendEvent("websocketFailed", std::move(errorObj));
|
|
197
|
-
});
|
|
198
|
-
ws->SetOnConnect([this, id, weakInstance]()
|
|
199
|
-
{
|
|
200
|
-
auto strongInstance = weakInstance.lock();
|
|
201
|
-
if (!strongInstance)
|
|
202
|
-
return;
|
|
203
|
-
|
|
204
|
-
auto args = dynamic::object("id", id);
|
|
205
|
-
this->SendEvent("websocketOpen", std::move(args));
|
|
206
|
-
});
|
|
207
|
-
ws->SetOnMessage([this, id, weakInstance](size_t length, const string& message, bool isBinary)
|
|
208
|
-
{
|
|
209
|
-
auto strongInstance = weakInstance.lock();
|
|
210
|
-
if (!strongInstance)
|
|
211
|
-
return;
|
|
212
|
-
|
|
213
|
-
auto args = dynamic::object("id", id)("data", message)("type", isBinary ? "binary" : "text");
|
|
214
|
-
this->SendEvent("websocketMessage", std::move(args));
|
|
215
|
-
});
|
|
216
|
-
ws->SetOnClose([this, id, weakInstance](IWebSocketResource::CloseCode code, const string& reason)
|
|
217
|
-
{
|
|
218
|
-
auto strongInstance = weakInstance.lock();
|
|
219
|
-
if (!strongInstance)
|
|
220
|
-
return;
|
|
221
|
-
|
|
222
|
-
auto args = dynamic::object("id", id)("code", static_cast<uint16_t>(code))("reason", reason);
|
|
223
|
-
this->SendEvent("websocketClosed", std::move(args));
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
m_webSockets.emplace(id, ws);
|
|
227
|
-
return ws;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return itr->second;
|
|
231
|
-
}
|
|
232
|
-
// clang-format on
|
|
233
|
-
|
|
234
|
-
#pragma endregion private members
|
|
235
|
-
|
|
236
249
|
/*extern*/ std::unique_ptr<facebook::xplat::module::CxxModule> CreateWebSocketModule() noexcept {
|
|
237
|
-
return make_unique<WebSocketModule>();
|
|
250
|
+
return std::make_unique<WebSocketModule>();
|
|
238
251
|
}
|
|
239
252
|
|
|
240
253
|
} // namespace Microsoft::React
|
|
@@ -18,6 +18,26 @@ class WebSocketModule : public facebook::xplat::module::CxxModule {
|
|
|
18
18
|
|
|
19
19
|
WebSocketModule();
|
|
20
20
|
|
|
21
|
+
~WebSocketModule() noexcept override;
|
|
22
|
+
|
|
23
|
+
struct SharedState {
|
|
24
|
+
/// <summary>
|
|
25
|
+
/// Keeps <c>IWebSocketResource</c> instances identified by <c>id</c>.
|
|
26
|
+
/// As defined in WebSocket.js.
|
|
27
|
+
/// </summary>
|
|
28
|
+
std::map<int64_t, std::shared_ptr<IWebSocketResource>> ResourceMap{};
|
|
29
|
+
|
|
30
|
+
/// <summary>
|
|
31
|
+
/// Generates IWebSocketResource instances, defaulting to IWebSocketResource::Make.
|
|
32
|
+
/// </summary>
|
|
33
|
+
std::function<std::shared_ptr<IWebSocketResource>(std::string &&)> ResourceFactory;
|
|
34
|
+
|
|
35
|
+
/// <summary>
|
|
36
|
+
/// Keeps a raw reference to the module object to lazily retrieve the React Instance as needed.
|
|
37
|
+
/// </summary>
|
|
38
|
+
CxxModule *Module{nullptr};
|
|
39
|
+
};
|
|
40
|
+
|
|
21
41
|
#pragma region CxxModule overrides
|
|
22
42
|
|
|
23
43
|
/// <summary>
|
|
@@ -41,16 +61,6 @@ class WebSocketModule : public facebook::xplat::module::CxxModule {
|
|
|
41
61
|
void SetResourceFactory(std::function<std::shared_ptr<IWebSocketResource>(const std::string &)> &&resourceFactory);
|
|
42
62
|
|
|
43
63
|
private:
|
|
44
|
-
/// <summary>
|
|
45
|
-
/// Notifies an event to the current React Instance.
|
|
46
|
-
/// </summary>
|
|
47
|
-
void SendEvent(std::string &&eventName, folly::dynamic &¶meters);
|
|
48
|
-
|
|
49
|
-
/// <summary>
|
|
50
|
-
/// Creates or retrieves a raw <c>IWebSocketResource</c> pointer.
|
|
51
|
-
/// </summary>
|
|
52
|
-
std::shared_ptr<IWebSocketResource> GetOrCreateWebSocket(std::int64_t id, std::string &&url = {});
|
|
53
|
-
|
|
54
64
|
/// <summary>
|
|
55
65
|
/// Keeps <c>IWebSocketResource</c> instances identified by <c>id</c>.
|
|
56
66
|
/// As defined in WebSocket.js.
|
|
@@ -58,9 +68,9 @@ class WebSocketModule : public facebook::xplat::module::CxxModule {
|
|
|
58
68
|
std::map<int64_t, std::shared_ptr<IWebSocketResource>> m_webSockets;
|
|
59
69
|
|
|
60
70
|
/// <summary>
|
|
61
|
-
///
|
|
71
|
+
/// Keeps members that can be accessed threads other than this module's owner accessible.
|
|
62
72
|
/// </summary>
|
|
63
|
-
std::
|
|
73
|
+
std::shared_ptr<SharedState> m_sharedState;
|
|
64
74
|
};
|
|
65
75
|
|
|
66
76
|
} // namespace Microsoft::React
|
package/Shared/OInstance.cpp
CHANGED
|
@@ -61,86 +61,6 @@
|
|
|
61
61
|
#include <tracing/tracing.h>
|
|
62
62
|
namespace fs = std::filesystem;
|
|
63
63
|
|
|
64
|
-
namespace {
|
|
65
|
-
|
|
66
|
-
#if (defined(_MSC_VER) && !defined(WINRT))
|
|
67
|
-
|
|
68
|
-
std::string GetJSBundleDirectory(
|
|
69
|
-
const std::string &jsBundleBasePath,
|
|
70
|
-
const std::string &jsBundleRelativePath) noexcept {
|
|
71
|
-
// If there is a base path, use that to calculate the absolute path.
|
|
72
|
-
if (jsBundleBasePath.length() > 0) {
|
|
73
|
-
std::string jsBundleDirectory = jsBundleBasePath;
|
|
74
|
-
if (jsBundleDirectory.back() != '\\')
|
|
75
|
-
jsBundleDirectory += '\\';
|
|
76
|
-
|
|
77
|
-
return jsBundleDirectory += jsBundleRelativePath;
|
|
78
|
-
} else if (!PathIsRelativeA(jsBundleRelativePath.c_str())) {
|
|
79
|
-
// If the given path is an absolute path, return it as-is
|
|
80
|
-
return jsBundleRelativePath;
|
|
81
|
-
}
|
|
82
|
-
// Otherwise use the path of the executable file to construct the absolute
|
|
83
|
-
// path.
|
|
84
|
-
else {
|
|
85
|
-
wchar_t modulePath[MAX_PATH];
|
|
86
|
-
|
|
87
|
-
auto len = GetModuleFileNameW(nullptr, modulePath, _countof(modulePath));
|
|
88
|
-
|
|
89
|
-
if (len == 0 || (len == _countof(modulePath) && GetLastError() == ERROR_INSUFFICIENT_BUFFER))
|
|
90
|
-
return jsBundleRelativePath;
|
|
91
|
-
|
|
92
|
-
// remove the trailing filename as we are interested in only the path
|
|
93
|
-
auto succeeded = PathRemoveFileSpecW(modulePath);
|
|
94
|
-
if (!succeeded)
|
|
95
|
-
return jsBundleRelativePath;
|
|
96
|
-
|
|
97
|
-
std::string jsBundlePath = Microsoft::Common::Unicode::Utf16ToUtf8(modulePath, wcslen(modulePath));
|
|
98
|
-
if (!jsBundlePath.empty() && jsBundlePath.back() != '\\')
|
|
99
|
-
jsBundlePath += '\\';
|
|
100
|
-
|
|
101
|
-
return jsBundlePath += jsBundleRelativePath;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
std::string GetJSBundleFilePath(const std::string &jsBundleBasePath, const std::string &jsBundleRelativePath) {
|
|
106
|
-
auto jsBundleFilePath = GetJSBundleDirectory(jsBundleBasePath, jsBundleRelativePath);
|
|
107
|
-
|
|
108
|
-
// Usually, the module name: "module name" + "." + "platform name", for
|
|
109
|
-
// example "lpc.win32". If we can not find the the bundle.js file under the
|
|
110
|
-
// normal folder, we are trying to find it under the folder without the dot
|
|
111
|
-
// (e.g. "lpcwin32"). VSO:1997035 remove this code after we have better name
|
|
112
|
-
// convension
|
|
113
|
-
if (PathFileExistsA((jsBundleFilePath + "\\bundle.js").c_str())) {
|
|
114
|
-
jsBundleFilePath += "\\bundle.js";
|
|
115
|
-
} else {
|
|
116
|
-
// remove the dot only if is belongs to the bundle file name.
|
|
117
|
-
size_t lastDotPosition = jsBundleFilePath.find_last_of('.');
|
|
118
|
-
size_t bundleFilePosition = jsBundleFilePath.find_last_of('\\');
|
|
119
|
-
if (lastDotPosition != std::string::npos &&
|
|
120
|
-
(bundleFilePosition == std::string::npos || lastDotPosition > bundleFilePosition)) {
|
|
121
|
-
jsBundleFilePath.erase(lastDotPosition, 1);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
jsBundleFilePath += "\\bundle.js";
|
|
125
|
-
|
|
126
|
-
// Back before we have base path plumbed through, we made win32 force a
|
|
127
|
-
// seperate folder for each bundle by appending bundle.js Now that we have
|
|
128
|
-
// base path, we can handle multiple SDXs with the same index name so we
|
|
129
|
-
// should switch to using the same scheme as all the other platforms (and
|
|
130
|
-
// the bundle server)
|
|
131
|
-
// TODO: We should remove all the previous logic and use the same names as
|
|
132
|
-
// the other platforms...
|
|
133
|
-
if (!PathFileExistsA(jsBundleFilePath.c_str())) {
|
|
134
|
-
jsBundleFilePath = GetJSBundleDirectory(jsBundleBasePath, jsBundleRelativePath) + ".bundle";
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return jsBundleFilePath;
|
|
139
|
-
}
|
|
140
|
-
#endif
|
|
141
|
-
|
|
142
|
-
} // namespace
|
|
143
|
-
|
|
144
64
|
using namespace facebook;
|
|
145
65
|
using namespace Microsoft::JSI;
|
|
146
66
|
|
|
@@ -560,22 +480,13 @@ void InstanceImpl::loadBundleInternal(std::string &&jsBundleRelativePath, bool s
|
|
|
560
480
|
}
|
|
561
481
|
} else {
|
|
562
482
|
#if (defined(_MSC_VER) && !defined(WINRT))
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
// If fullBundleFilePath exists, load User bundle.
|
|
566
|
-
// Otherwise all bundles (User and Platform) are loaded through
|
|
567
|
-
// platformBundles.
|
|
568
|
-
if (PathFileExistsA(fullBundleFilePath.c_str())) {
|
|
569
|
-
auto bundleString = FileMappingBigString::fromPath(fullBundleFilePath);
|
|
570
|
-
m_innerInstance->loadScriptFromString(std::move(bundleString), std::move(fullBundleFilePath), synchronously);
|
|
571
|
-
}
|
|
572
|
-
|
|
483
|
+
std::string bundlePath = (fs::path(m_devSettings->bundleRootPath) / jsBundleRelativePath).string();
|
|
484
|
+
auto bundleString = FileMappingBigString::fromPath(bundlePath);
|
|
573
485
|
#else
|
|
574
486
|
std::string bundlePath = (fs::path(m_devSettings->bundleRootPath) / (jsBundleRelativePath + ".bundle")).string();
|
|
575
|
-
|
|
576
487
|
auto bundleString = std::make_unique<::Microsoft::ReactNative::StorageFileBigString>(bundlePath);
|
|
577
|
-
m_innerInstance->loadScriptFromString(std::move(bundleString), jsBundleRelativePath, synchronously);
|
|
578
488
|
#endif
|
|
489
|
+
m_innerInstance->loadScriptFromString(std::move(bundleString), std::move(jsBundleRelativePath), synchronously);
|
|
579
490
|
}
|
|
580
491
|
} catch (const std::exception &e) {
|
|
581
492
|
m_devSettings->errorCallback(e.what());
|
|
@@ -90,29 +90,21 @@ namespace Microsoft::React {
|
|
|
90
90
|
// private
|
|
91
91
|
WinRTWebSocketResource::WinRTWebSocketResource(
|
|
92
92
|
IMessageWebSocket &&socket,
|
|
93
|
-
Uri &&uri,
|
|
94
93
|
vector<ChainValidationResult> &&certExceptions)
|
|
95
|
-
: WinRTWebSocketResource(
|
|
96
|
-
std::move(socket),
|
|
97
|
-
DataWriter{socket.OutputStream()},
|
|
98
|
-
std::move(uri),
|
|
99
|
-
std::move(certExceptions)) {}
|
|
94
|
+
: WinRTWebSocketResource(std::move(socket), DataWriter{socket.OutputStream()}, std::move(certExceptions)) {}
|
|
100
95
|
|
|
101
96
|
WinRTWebSocketResource::WinRTWebSocketResource(
|
|
102
97
|
IMessageWebSocket &&socket,
|
|
103
98
|
IDataWriter &&writer,
|
|
104
|
-
Uri &&uri,
|
|
105
99
|
vector<ChainValidationResult> &&certExceptions)
|
|
106
|
-
:
|
|
107
|
-
m_socket.MessageReceived({this, &WinRTWebSocketResource::OnMessageReceived});
|
|
108
|
-
|
|
100
|
+
: m_socket{std::move(socket)}, m_writer{std::move(writer)} {
|
|
109
101
|
for (const auto &certException : certExceptions) {
|
|
110
102
|
m_socket.Control().IgnorableServerCertificateErrors().Append(certException);
|
|
111
103
|
}
|
|
112
104
|
}
|
|
113
105
|
|
|
114
|
-
WinRTWebSocketResource::WinRTWebSocketResource(
|
|
115
|
-
: WinRTWebSocketResource(MessageWebSocket{},
|
|
106
|
+
WinRTWebSocketResource::WinRTWebSocketResource(vector<ChainValidationResult> &&certExceptions)
|
|
107
|
+
: WinRTWebSocketResource(MessageWebSocket{}, std::move(certExceptions)) {}
|
|
116
108
|
|
|
117
109
|
WinRTWebSocketResource::~WinRTWebSocketResource() noexcept /*override*/
|
|
118
110
|
{
|
|
@@ -123,13 +115,14 @@ WinRTWebSocketResource::~WinRTWebSocketResource() noexcept /*override*/
|
|
|
123
115
|
|
|
124
116
|
#pragma region Private members
|
|
125
117
|
|
|
126
|
-
IAsyncAction WinRTWebSocketResource::PerformConnect() noexcept {
|
|
118
|
+
IAsyncAction WinRTWebSocketResource::PerformConnect(Uri &&uri) noexcept {
|
|
127
119
|
auto self = shared_from_this();
|
|
120
|
+
auto coUri = std::move(uri);
|
|
128
121
|
|
|
129
122
|
co_await resume_background();
|
|
130
123
|
|
|
131
124
|
try {
|
|
132
|
-
auto async = self->m_socket.ConnectAsync(
|
|
125
|
+
auto async = self->m_socket.ConnectAsync(coUri);
|
|
133
126
|
|
|
134
127
|
co_await lessthrow_await_adapter<IAsyncAction>{async};
|
|
135
128
|
|
|
@@ -293,36 +286,6 @@ fire_and_forget WinRTWebSocketResource::PerformClose() noexcept {
|
|
|
293
286
|
m_closePerformed.Set();
|
|
294
287
|
}
|
|
295
288
|
|
|
296
|
-
void WinRTWebSocketResource::OnMessageReceived(
|
|
297
|
-
IWebSocket const &sender,
|
|
298
|
-
IMessageWebSocketMessageReceivedEventArgs const &args) {
|
|
299
|
-
try {
|
|
300
|
-
string response;
|
|
301
|
-
IDataReader reader = args.GetDataReader();
|
|
302
|
-
auto len = reader.UnconsumedBufferLength();
|
|
303
|
-
if (args.MessageType() == SocketMessageType::Utf8) {
|
|
304
|
-
reader.UnicodeEncoding(UnicodeEncoding::Utf8);
|
|
305
|
-
vector<uint8_t> data(len);
|
|
306
|
-
reader.ReadBytes(data);
|
|
307
|
-
|
|
308
|
-
response = string(CheckedReinterpretCast<char *>(data.data()), data.size());
|
|
309
|
-
} else {
|
|
310
|
-
auto buffer = reader.ReadBuffer(len);
|
|
311
|
-
winrt::hstring data = CryptographicBuffer::EncodeToBase64String(buffer);
|
|
312
|
-
|
|
313
|
-
response = winrt::to_string(std::wstring_view(data));
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (m_readHandler) {
|
|
317
|
-
m_readHandler(response.length(), response, args.MessageType() == SocketMessageType::Binary);
|
|
318
|
-
}
|
|
319
|
-
} catch (hresult_error const &e) {
|
|
320
|
-
if (m_errorHandler) {
|
|
321
|
-
m_errorHandler({HResultToString(e), ErrorType::Receive});
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
289
|
void WinRTWebSocketResource::Synchronize() noexcept {
|
|
327
290
|
// Ensure sequence of other operations
|
|
328
291
|
if (m_connectRequested) {
|
|
@@ -334,7 +297,36 @@ void WinRTWebSocketResource::Synchronize() noexcept {
|
|
|
334
297
|
|
|
335
298
|
#pragma region IWebSocketResource
|
|
336
299
|
|
|
337
|
-
void WinRTWebSocketResource::Connect(const Protocols &protocols, const Options &options) noexcept {
|
|
300
|
+
void WinRTWebSocketResource::Connect(string &&url, const Protocols &protocols, const Options &options) noexcept {
|
|
301
|
+
m_socket.MessageReceived(
|
|
302
|
+
[self = shared_from_this()](IWebSocket const &sender, IMessageWebSocketMessageReceivedEventArgs const &args) {
|
|
303
|
+
try {
|
|
304
|
+
string response;
|
|
305
|
+
IDataReader reader = args.GetDataReader();
|
|
306
|
+
auto len = reader.UnconsumedBufferLength();
|
|
307
|
+
if (args.MessageType() == SocketMessageType::Utf8) {
|
|
308
|
+
reader.UnicodeEncoding(UnicodeEncoding::Utf8);
|
|
309
|
+
vector<uint8_t> data(len);
|
|
310
|
+
reader.ReadBytes(data);
|
|
311
|
+
|
|
312
|
+
response = string(CheckedReinterpretCast<char *>(data.data()), data.size());
|
|
313
|
+
} else {
|
|
314
|
+
auto buffer = reader.ReadBuffer(len);
|
|
315
|
+
winrt::hstring data = CryptographicBuffer::EncodeToBase64String(buffer);
|
|
316
|
+
|
|
317
|
+
response = winrt::to_string(std::wstring_view(data));
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (self->m_readHandler) {
|
|
321
|
+
self->m_readHandler(response.length(), response, args.MessageType() == SocketMessageType::Binary);
|
|
322
|
+
}
|
|
323
|
+
} catch (hresult_error const &e) {
|
|
324
|
+
if (self->m_errorHandler) {
|
|
325
|
+
self->m_errorHandler({HResultToString(e), ErrorType::Receive});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
|
|
338
330
|
m_readyState = ReadyState::Connecting;
|
|
339
331
|
|
|
340
332
|
for (const auto &header : options) {
|
|
@@ -348,7 +340,24 @@ void WinRTWebSocketResource::Connect(const Protocols &protocols, const Options &
|
|
|
348
340
|
}
|
|
349
341
|
|
|
350
342
|
m_connectRequested = true;
|
|
351
|
-
|
|
343
|
+
|
|
344
|
+
Uri uri{nullptr};
|
|
345
|
+
try {
|
|
346
|
+
uri = Uri{winrt::to_hstring(url)};
|
|
347
|
+
} catch (hresult_error const &e) {
|
|
348
|
+
if (m_errorHandler) {
|
|
349
|
+
m_errorHandler({HResultToString(e), ErrorType::Connection});
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Abort - Mark connection as concluded.
|
|
353
|
+
SetEvent(m_connectPerformed.get());
|
|
354
|
+
m_connectPerformedPromise.set_value();
|
|
355
|
+
m_connectRequested = false;
|
|
356
|
+
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
PerformConnect(std::move(uri));
|
|
352
361
|
}
|
|
353
362
|
|
|
354
363
|
void WinRTWebSocketResource::Ping() noexcept {
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
namespace Microsoft::React {
|
|
18
18
|
|
|
19
19
|
class WinRTWebSocketResource : public IWebSocketResource, public std::enable_shared_from_this<WinRTWebSocketResource> {
|
|
20
|
-
winrt::Windows::Foundation::Uri m_uri;
|
|
21
20
|
winrt::Windows::Networking::Sockets::IMessageWebSocket m_socket;
|
|
22
21
|
// TODO: Use or remove.
|
|
23
22
|
winrt::Windows::Networking::Sockets::IMessageWebSocket::MessageReceived_revoker m_revoker;
|
|
@@ -45,28 +44,22 @@ class WinRTWebSocketResource : public IWebSocketResource, public std::enable_sha
|
|
|
45
44
|
|
|
46
45
|
WinRTWebSocketResource(
|
|
47
46
|
winrt::Windows::Networking::Sockets::IMessageWebSocket &&socket,
|
|
48
|
-
winrt::Windows::Foundation::Uri &&uri,
|
|
49
47
|
std::vector<winrt::Windows::Security::Cryptography::Certificates::ChainValidationResult> &&certExceptions);
|
|
50
48
|
|
|
51
|
-
winrt::Windows::Foundation::IAsyncAction PerformConnect() noexcept;
|
|
49
|
+
winrt::Windows::Foundation::IAsyncAction PerformConnect(winrt::Windows::Foundation::Uri &&uri) noexcept;
|
|
52
50
|
winrt::fire_and_forget PerformPing() noexcept;
|
|
53
51
|
winrt::fire_and_forget PerformWrite(std::string &&message, bool isBinary) noexcept;
|
|
54
52
|
winrt::fire_and_forget PerformClose() noexcept;
|
|
55
53
|
|
|
56
|
-
void OnMessageReceived(
|
|
57
|
-
winrt::Windows::Networking::Sockets::IWebSocket const &sender,
|
|
58
|
-
winrt::Windows::Networking::Sockets::IMessageWebSocketMessageReceivedEventArgs const &args);
|
|
59
54
|
void Synchronize() noexcept;
|
|
60
55
|
|
|
61
56
|
public:
|
|
62
57
|
WinRTWebSocketResource(
|
|
63
58
|
winrt::Windows::Networking::Sockets::IMessageWebSocket &&socket,
|
|
64
59
|
winrt::Windows::Storage::Streams::IDataWriter &&writer,
|
|
65
|
-
winrt::Windows::Foundation::Uri &&uri,
|
|
66
60
|
std::vector<winrt::Windows::Security::Cryptography::Certificates::ChainValidationResult> &&certExceptions);
|
|
67
61
|
|
|
68
62
|
WinRTWebSocketResource(
|
|
69
|
-
const std::string &urlString,
|
|
70
63
|
std::vector<winrt::Windows::Security::Cryptography::Certificates::ChainValidationResult> &&certExceptions);
|
|
71
64
|
|
|
72
65
|
~WinRTWebSocketResource() noexcept override;
|
|
@@ -76,7 +69,7 @@ class WinRTWebSocketResource : public IWebSocketResource, public std::enable_sha
|
|
|
76
69
|
/// <summary>
|
|
77
70
|
/// <see cref="IWebSocketResource::Connect" />
|
|
78
71
|
/// </summary>
|
|
79
|
-
void Connect(const Protocols &protocols, const Options &options) noexcept override;
|
|
72
|
+
void Connect(std::string &&url, const Protocols &protocols, const Options &options) noexcept override;
|
|
80
73
|
|
|
81
74
|
/// <summary>
|
|
82
75
|
/// <see cref="IWebSocketResource::Ping" />
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-windows",
|
|
3
|
-
"version": "0.66.
|
|
3
|
+
"version": "0.66.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"@react-native-community/cli": "^6.0.0",
|
|
27
27
|
"@react-native-community/cli-platform-android": "^6.0.0",
|
|
28
28
|
"@react-native-community/cli-platform-ios": "^6.0.0",
|
|
29
|
-
"@react-native-windows/cli": "0.66.
|
|
30
|
-
"@react-native-windows/virtualized-list": "0.66.
|
|
29
|
+
"@react-native-windows/cli": "0.66.2",
|
|
30
|
+
"@react-native-windows/virtualized-list": "0.66.1",
|
|
31
31
|
"@react-native/assets": "1.0.0",
|
|
32
32
|
"@react-native/normalize-color": "1.0.0",
|
|
33
33
|
"@react-native/polyfills": "2.0.0",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"ws": "^6.1.4"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@react-native-windows/codegen": "0.66.
|
|
61
|
+
"@react-native-windows/codegen": "0.66.1",
|
|
62
62
|
"@rnw-scripts/eslint-config": "1.1.7",
|
|
63
63
|
"@rnw-scripts/jest-out-of-tree-snapshot-resolver": "^1.0.1",
|
|
64
64
|
"@rnx-kit/jest-preset": "^0.1.0",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"react-native": "^0.66.0"
|
|
85
85
|
},
|
|
86
86
|
"beachball": {
|
|
87
|
-
"defaultNpmTag": "
|
|
87
|
+
"defaultNpmTag": "v0.66-stable",
|
|
88
88
|
"gitTags": true,
|
|
89
89
|
"disallowedChangeTypes": [
|
|
90
90
|
"major",
|