react-native-windows 0.72.0-preview.7 → 0.72.0-preview.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/Directory.Build.props +24 -19
- package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +0 -1
- package/Libraries/Components/TextInput/TextInput.d.ts +121 -86
- package/Libraries/Components/TextInput/TextInput.flow.js +121 -135
- package/Libraries/Components/TextInput/TextInput.js +126 -155
- package/Libraries/Components/TextInput/TextInput.windows.js +126 -155
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/PermissionsAndroid/PermissionsAndroid.js +0 -2
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +1 -13
- package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +2 -4
- package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +2 -57
- package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +22 -17
- package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +0 -2
- package/Microsoft.ReactNative.Cxx/JSI/NodeApiJsiLoader.cpp +16 -0
- package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +41 -12
- package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems.filters +17 -6
- package/Microsoft.ReactNative.Managed/packages.lock.json +6 -6
- package/PropertySheets/External/Microsoft.ReactNative.Uwp.CSharpApp.targets +1 -1
- package/PropertySheets/External/Microsoft.ReactNative.Uwp.CppApp.targets +1 -1
- package/PropertySheets/External/Microsoft.ReactNative.WinAppSDK.CSharpApp.targets +1 -1
- package/PropertySheets/Generated/PackageVersion.g.props +2 -2
- package/PropertySheets/JSEngine.props +4 -4
- package/PropertySheets/Warnings.props +6 -0
- package/ReactCommon/ReactCommon.vcxproj +53 -1
- package/ReactCommon/cgmanifest.json +15 -0
- package/Scripts/Tfs/Layout-MSRN-Headers.ps1 +36 -0
- package/Shared/DevSupportManager.cpp +2 -9
- package/Shared/DevSupportManager.h +2 -6
- package/Shared/HermesRuntimeHolder.cpp +318 -81
- package/Shared/HermesRuntimeHolder.h +15 -19
- package/Shared/HermesSamplingProfiler.cpp +5 -6
- package/Shared/InspectorPackagerConnection.cpp +62 -108
- package/Shared/InspectorPackagerConnection.h +9 -21
- package/Shared/JSI/ScriptStore.h +18 -20
- package/Shared/JSI/V8RuntimeHolder.cpp +262 -0
- package/Shared/JSI/V8RuntimeHolder.h +37 -0
- package/Shared/OInstance.cpp +16 -36
- package/Shared/SafeLoadLibrary.cpp +41 -0
- package/Shared/SafeLoadLibrary.h +15 -0
- package/Shared/Shared.vcxitems +21 -10
- package/Shared/Shared.vcxitems.filters +23 -30
- package/codegen/rnwcoreJSI.h +2 -2
- package/package.json +15 -14
- package/template/cs-app-WinAppSDK/proj/ExperimentalFeatures.props +1 -1
- package/Microsoft.ReactNative.Cxx/JSI/NodeApiJsiRuntime.cpp +0 -2105
- package/Microsoft.ReactNative.Cxx/JSI/NodeApiJsiRuntime.h +0 -73
- package/Shared/HermesShim.cpp +0 -122
- package/Shared/HermesShim.h +0 -41
- package/Shared/JSI/NapiJsiV8RuntimeHolder.cpp +0 -209
- package/Shared/JSI/NapiJsiV8RuntimeHolder.h +0 -46
- package/Shared/V8JSIRuntimeHolder.cpp +0 -71
- package/Shared/V8JSIRuntimeHolder.h +0 -58
|
@@ -3,18 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
#include "pch.h"
|
|
5
5
|
|
|
6
|
-
#ifdef HERMES_ENABLE_DEBUGGER
|
|
7
|
-
|
|
8
6
|
#include <folly/json.h>
|
|
9
7
|
#include <tracing/tracing.h>
|
|
10
8
|
#include "InspectorPackagerConnection.h"
|
|
11
9
|
|
|
12
|
-
namespace facebook {
|
|
13
|
-
namespace react {
|
|
14
|
-
IDestructible::~IDestructible() {}
|
|
15
|
-
} // namespace react
|
|
16
|
-
} // namespace facebook
|
|
17
|
-
|
|
18
10
|
namespace Microsoft::ReactNative {
|
|
19
11
|
|
|
20
12
|
namespace {
|
|
@@ -80,35 +72,16 @@ struct InspectorProtocol {
|
|
|
80
72
|
}
|
|
81
73
|
|
|
82
74
|
static folly::dynamic constructGetPagesResponsePayloadForPackager(
|
|
83
|
-
const std::vector<facebook::react::
|
|
84
|
-
InspectorPackagerConnection::BundleStatus bundleStatus) {
|
|
85
|
-
folly::dynamic payload = folly::dynamic::array;
|
|
86
|
-
for (const facebook::react::InspectorPage2 &page : pages) {
|
|
87
|
-
folly::dynamic pageDyn = folly::dynamic::object;
|
|
88
|
-
pageDyn["id"] = page.id;
|
|
89
|
-
pageDyn["title"] = page.title;
|
|
90
|
-
pageDyn["vm"] = page.vm;
|
|
91
|
-
|
|
92
|
-
pageDyn["isLastBundleDownloadSuccess"] = bundleStatus.m_isLastDownloadSucess;
|
|
93
|
-
pageDyn["bundleUpdateTimestamp"] = bundleStatus.m_updateTimestamp;
|
|
94
|
-
|
|
95
|
-
payload.push_back(pageDyn);
|
|
96
|
-
}
|
|
97
|
-
return payload;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
static folly::dynamic constructGetPagesResponsePayloadForPackager(
|
|
101
|
-
std::unique_ptr<facebook::react::IInspectorPages> pages,
|
|
75
|
+
const std::vector<facebook::react::InspectorPage> &pages,
|
|
102
76
|
InspectorPackagerConnection::BundleStatus bundleStatus) {
|
|
103
77
|
folly::dynamic payload = folly::dynamic::array;
|
|
104
|
-
for (
|
|
105
|
-
const facebook::react::InspectorPage2 page = pages->getPage(p);
|
|
78
|
+
for (const facebook::react::InspectorPage &page : pages) {
|
|
106
79
|
folly::dynamic pageDyn = folly::dynamic::object;
|
|
107
80
|
pageDyn["id"] = page.id;
|
|
108
81
|
pageDyn["title"] = page.title;
|
|
109
82
|
pageDyn["vm"] = page.vm;
|
|
110
83
|
|
|
111
|
-
pageDyn["isLastBundleDownloadSuccess"] = bundleStatus.
|
|
84
|
+
pageDyn["isLastBundleDownloadSuccess"] = bundleStatus.m_isLastDownloadSuccess;
|
|
112
85
|
pageDyn["bundleUpdateTimestamp"] = bundleStatus.m_updateTimestamp;
|
|
113
86
|
|
|
114
87
|
payload.push_back(pageDyn);
|
|
@@ -116,14 +89,14 @@ struct InspectorProtocol {
|
|
|
116
89
|
return payload;
|
|
117
90
|
}
|
|
118
91
|
|
|
119
|
-
static folly::dynamic constructVMResponsePayloadForPackager(
|
|
92
|
+
static folly::dynamic constructVMResponsePayloadForPackager(int32_t pageId, std::string &&messageFromVM) {
|
|
120
93
|
folly::dynamic payload = folly::dynamic::object;
|
|
121
94
|
payload[InspectorProtocol::Message_eventName_wrappedEvent] = messageFromVM;
|
|
122
95
|
payload[InspectorProtocol::Message_PAGEID] = pageId;
|
|
123
96
|
return payload;
|
|
124
97
|
}
|
|
125
98
|
|
|
126
|
-
static folly::dynamic constructVMResponsePayloadOnDisconnectForPackager(
|
|
99
|
+
static folly::dynamic constructVMResponsePayloadOnDisconnectForPackager(int32_t pageId) {
|
|
127
100
|
folly::dynamic payload = folly::dynamic::object;
|
|
128
101
|
payload[InspectorProtocol::Message_PAGEID] = pageId;
|
|
129
102
|
return payload;
|
|
@@ -132,7 +105,7 @@ struct InspectorProtocol {
|
|
|
132
105
|
|
|
133
106
|
} // namespace
|
|
134
107
|
|
|
135
|
-
RemoteConnection::RemoteConnection(
|
|
108
|
+
RemoteConnection::RemoteConnection(int32_t pageId, const InspectorPackagerConnection &packagerConnection)
|
|
136
109
|
: m_packagerConnection(packagerConnection), m_pageId(pageId) {}
|
|
137
110
|
|
|
138
111
|
void RemoteConnection::onMessage(std::string message) {
|
|
@@ -152,26 +125,6 @@ void RemoteConnection::onDisconnect() {
|
|
|
152
125
|
m_packagerConnection.sendMessageToPackager(std::move(responsestr));
|
|
153
126
|
}
|
|
154
127
|
|
|
155
|
-
RemoteConnection2::RemoteConnection2(int64_t pageId, const InspectorPackagerConnection &packagerConnection)
|
|
156
|
-
: m_packagerConnection(packagerConnection), m_pageId(pageId) {}
|
|
157
|
-
|
|
158
|
-
void RemoteConnection2::onMessage(std::string message) {
|
|
159
|
-
folly::dynamic response = InspectorProtocol::constructResponseForPackager(
|
|
160
|
-
InspectorProtocol::EventType::WrappedEvent,
|
|
161
|
-
InspectorProtocol::constructVMResponsePayloadForPackager(m_pageId, std::move(message)));
|
|
162
|
-
std::string responsestr = folly::toJson(response);
|
|
163
|
-
m_packagerConnection.sendMessageToPackager(std::move(responsestr));
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
void RemoteConnection2::onDisconnect() {
|
|
167
|
-
folly::dynamic response = InspectorProtocol::constructResponseForPackager(
|
|
168
|
-
InspectorProtocol::EventType::Disconnect,
|
|
169
|
-
InspectorProtocol::constructVMResponsePayloadOnDisconnectForPackager(m_pageId));
|
|
170
|
-
|
|
171
|
-
std::string responsestr = folly::toJson(response);
|
|
172
|
-
m_packagerConnection.sendMessageToPackager(std::move(responsestr));
|
|
173
|
-
}
|
|
174
|
-
|
|
175
128
|
winrt::fire_and_forget InspectorPackagerConnection::sendMessageToPackagerAsync(std::string &&message) const {
|
|
176
129
|
std::string message_(std::move(message));
|
|
177
130
|
co_await winrt::resume_background();
|
|
@@ -183,7 +136,7 @@ void InspectorPackagerConnection::sendMessageToPackager(std::string &&message) c
|
|
|
183
136
|
sendMessageToPackagerAsync(std::move(message));
|
|
184
137
|
}
|
|
185
138
|
|
|
186
|
-
void InspectorPackagerConnection::sendMessageToVM(
|
|
139
|
+
void InspectorPackagerConnection::sendMessageToVM(int32_t pageId, std::string &&message) {
|
|
187
140
|
m_localConnections[pageId]->sendMessage(std::move(message));
|
|
188
141
|
}
|
|
189
142
|
|
|
@@ -214,59 +167,62 @@ winrt::fire_and_forget InspectorPackagerConnection::connectAsync() {
|
|
|
214
167
|
m_packagerWebSocketConnection->SetOnConnect(
|
|
215
168
|
[]() { facebook::react::tracing::log("Inspector: Websocket connection succeeded."); });
|
|
216
169
|
|
|
217
|
-
m_packagerWebSocketConnection->SetOnMessage(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
std::string wrappedEvent = payload[InspectorProtocol::Message_eventName_wrappedEvent].getString();
|
|
244
|
-
self->sendMessageToVM(pageId, std::move(wrappedEvent));
|
|
245
|
-
} break;
|
|
246
|
-
|
|
247
|
-
case InspectorProtocol::EventType::Connect: {
|
|
248
|
-
folly::dynamic payload = messageDyn[InspectorProtocol::Message_PAYLOAD];
|
|
249
|
-
int64_t pageId = payload[InspectorProtocol::Message_PAGEID].asInt();
|
|
250
|
-
|
|
251
|
-
if (self->m_localConnections.find(pageId) != self->m_localConnections.end()) {
|
|
252
|
-
break;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
self->m_localConnections[pageId] = facebook::react::connectInspectorPage(
|
|
256
|
-
static_cast<int>(pageId), std::make_unique<RemoteConnection2>(pageId, *self));
|
|
257
|
-
} break;
|
|
258
|
-
|
|
259
|
-
case InspectorProtocol::EventType::Disconnect: {
|
|
260
|
-
folly::dynamic payload = messageDyn[InspectorProtocol::Message_PAYLOAD];
|
|
261
|
-
int64_t pageId = payload[InspectorProtocol::Message_PAGEID].asInt();
|
|
262
|
-
if (self->m_localConnections.find(pageId) != self->m_localConnections.end()) {
|
|
263
|
-
self->m_localConnections[pageId]->disconnect();
|
|
264
|
-
self->m_localConnections.erase(pageId);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
} break;
|
|
170
|
+
m_packagerWebSocketConnection->SetOnMessage([self = shared_from_this()](
|
|
171
|
+
size_t /*length*/, const std::string &message, bool isBinary) {
|
|
172
|
+
assert(!isBinary && "We don't expect any binary messages !");
|
|
173
|
+
folly::dynamic messageDyn = folly::parseJson(message);
|
|
174
|
+
|
|
175
|
+
InspectorProtocol::EventType eventType = InspectorProtocol::getEventType(messageDyn);
|
|
176
|
+
switch (eventType) {
|
|
177
|
+
case InspectorProtocol::EventType::GetPages: {
|
|
178
|
+
std::vector<facebook::react::InspectorPage> inspectorPages = facebook::react::getInspectorInstance().getPages();
|
|
179
|
+
folly::dynamic response = InspectorProtocol::constructResponseForPackager(
|
|
180
|
+
InspectorProtocol::EventType::GetPages,
|
|
181
|
+
InspectorProtocol::constructGetPagesResponsePayloadForPackager(
|
|
182
|
+
inspectorPages, self->m_bundleStatusProvider->getBundleStatus()));
|
|
183
|
+
|
|
184
|
+
std::string responsestr = folly::toJson(response);
|
|
185
|
+
self->sendMessageToPackager(std::move(responsestr));
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
case InspectorProtocol::EventType::WrappedEvent: {
|
|
190
|
+
folly::dynamic payload = messageDyn[InspectorProtocol::Message_PAYLOAD];
|
|
191
|
+
int32_t pageId = static_cast<int32_t>(payload[InspectorProtocol::Message_PAGEID].asInt());
|
|
192
|
+
|
|
193
|
+
if (self->m_localConnections.find(pageId) == self->m_localConnections.end()) {
|
|
194
|
+
break;
|
|
268
195
|
}
|
|
269
|
-
|
|
196
|
+
|
|
197
|
+
std::string wrappedEvent = payload[InspectorProtocol::Message_eventName_wrappedEvent].getString();
|
|
198
|
+
self->sendMessageToVM(pageId, std::move(wrappedEvent));
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
case InspectorProtocol::EventType::Connect: {
|
|
203
|
+
folly::dynamic payload = messageDyn[InspectorProtocol::Message_PAYLOAD];
|
|
204
|
+
int32_t pageId = static_cast<int32_t>(payload[InspectorProtocol::Message_PAGEID].asInt());
|
|
205
|
+
|
|
206
|
+
if (self->m_localConnections.find(pageId) != self->m_localConnections.end()) {
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
self->m_localConnections[pageId] =
|
|
211
|
+
facebook::react::getInspectorInstance().connect(pageId, std::make_unique<RemoteConnection>(pageId, *self));
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
case InspectorProtocol::EventType::Disconnect: {
|
|
216
|
+
folly::dynamic payload = messageDyn[InspectorProtocol::Message_PAYLOAD];
|
|
217
|
+
int32_t pageId = static_cast<int32_t>(payload[InspectorProtocol::Message_PAGEID].asInt());
|
|
218
|
+
if (self->m_localConnections.find(pageId) != self->m_localConnections.end()) {
|
|
219
|
+
self->m_localConnections[pageId]->disconnect();
|
|
220
|
+
self->m_localConnections.erase(pageId);
|
|
221
|
+
}
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
});
|
|
270
226
|
|
|
271
227
|
Microsoft::React::Networking::IWebSocketResource::Protocols protocols;
|
|
272
228
|
Microsoft::React::Networking::IWebSocketResource::Options options;
|
|
@@ -276,5 +232,3 @@ winrt::fire_and_forget InspectorPackagerConnection::connectAsync() {
|
|
|
276
232
|
}
|
|
277
233
|
|
|
278
234
|
} // namespace Microsoft::ReactNative
|
|
279
|
-
|
|
280
|
-
#endif
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
|
|
4
4
|
#pragma once
|
|
5
5
|
|
|
6
|
-
#include <InspectorProxy.h>
|
|
7
6
|
#include <Networking/WinRTWebSocketResource.h>
|
|
8
7
|
#include <jsinspector/InspectorInterfaces.h>
|
|
9
8
|
|
|
@@ -16,12 +15,12 @@ class InspectorPackagerConnection final : public std::enable_shared_from_this<In
|
|
|
16
15
|
|
|
17
16
|
class BundleStatus {
|
|
18
17
|
public:
|
|
19
|
-
bool
|
|
18
|
+
bool m_isLastDownloadSuccess;
|
|
20
19
|
int64_t m_updateTimestamp = -1;
|
|
21
20
|
|
|
22
21
|
BundleStatus(bool isLastDownloadSucess, long updateTimestamp)
|
|
23
|
-
:
|
|
24
|
-
BundleStatus() :
|
|
22
|
+
: m_isLastDownloadSuccess(isLastDownloadSucess), m_updateTimestamp(updateTimestamp) {}
|
|
23
|
+
BundleStatus() : m_isLastDownloadSuccess(false), m_updateTimestamp(-1) {}
|
|
25
24
|
};
|
|
26
25
|
|
|
27
26
|
struct IBundleStatusProvider {
|
|
@@ -32,16 +31,16 @@ class InspectorPackagerConnection final : public std::enable_shared_from_this<In
|
|
|
32
31
|
|
|
33
32
|
private:
|
|
34
33
|
friend class RemoteConnection;
|
|
35
|
-
friend class RemoteConnection2;
|
|
36
34
|
|
|
37
35
|
winrt::fire_and_forget sendMessageToPackagerAsync(std::string &&message) const;
|
|
38
36
|
void sendMessageToPackager(std::string &&message) const;
|
|
39
37
|
|
|
40
|
-
// Note:: VM side Inspector processes the messages
|
|
38
|
+
// Note:: VM side Inspector processes the messages asynchronously in a sequential executor with dedicated thread.
|
|
41
39
|
// Hence, we don't bother invoking the inspector asynchronously.
|
|
42
|
-
void sendMessageToVM(
|
|
40
|
+
void sendMessageToVM(int32_t pageId, std::string &&message);
|
|
43
41
|
|
|
44
|
-
|
|
42
|
+
private:
|
|
43
|
+
std::unordered_map<int32_t, std::unique_ptr<facebook::react::ILocalConnection>> m_localConnections;
|
|
45
44
|
std::shared_ptr<Microsoft::React::Networking::WinRTWebSocketResource> m_packagerWebSocketConnection;
|
|
46
45
|
std::shared_ptr<IBundleStatusProvider> m_bundleStatusProvider;
|
|
47
46
|
std::string m_url;
|
|
@@ -49,23 +48,12 @@ class InspectorPackagerConnection final : public std::enable_shared_from_this<In
|
|
|
49
48
|
|
|
50
49
|
class RemoteConnection final : public facebook::react::IRemoteConnection {
|
|
51
50
|
public:
|
|
52
|
-
RemoteConnection(
|
|
53
|
-
void onMessage(std::string message) override;
|
|
54
|
-
void onDisconnect() override;
|
|
55
|
-
|
|
56
|
-
private:
|
|
57
|
-
int64_t m_pageId;
|
|
58
|
-
const InspectorPackagerConnection &m_packagerConnection;
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
class RemoteConnection2 final : public facebook::react::IRemoteConnection2 {
|
|
62
|
-
public:
|
|
63
|
-
RemoteConnection2(int64_t pageId, const InspectorPackagerConnection &packagerConnection);
|
|
51
|
+
RemoteConnection(int32_t pageId, const InspectorPackagerConnection &packagerConnection);
|
|
64
52
|
void onMessage(std::string message) override;
|
|
65
53
|
void onDisconnect() override;
|
|
66
54
|
|
|
67
55
|
private:
|
|
68
|
-
|
|
56
|
+
int32_t m_pageId;
|
|
69
57
|
const InspectorPackagerConnection &m_packagerConnection;
|
|
70
58
|
};
|
|
71
59
|
|
package/Shared/JSI/ScriptStore.h
CHANGED
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
#include <jsi/jsi.h>
|
|
6
6
|
#include <memory>
|
|
7
7
|
|
|
8
|
-
namespace facebook {
|
|
9
|
-
namespace jsi {
|
|
8
|
+
namespace facebook::jsi {
|
|
10
9
|
|
|
11
|
-
// Integer type as it's persist
|
|
12
|
-
using ScriptVersion_t = uint64_t; // It
|
|
13
|
-
// then, 0 implies versioning not available.
|
|
10
|
+
// Integer type as it's persist friendly.
|
|
11
|
+
using ScriptVersion_t = uint64_t; // It should be std::optional<uint64_t> once we have c++17 available everywhere.
|
|
12
|
+
// Until then, 0 implies versioning not available.
|
|
14
13
|
using JSRuntimeVersion_t = uint64_t; // 0 implies version can't be computed. We assert whenever that happens.
|
|
15
14
|
|
|
16
15
|
struct VersionedBuffer {
|
|
@@ -30,14 +29,14 @@ struct JSRuntimeSignature {
|
|
|
30
29
|
|
|
31
30
|
// Most JSI::Runtime implementation offer some form of prepared JavaScript which offers better performance
|
|
32
31
|
// characteristics when loading comparing to plain JavaScript. Embedders can provide an instance of this interface
|
|
33
|
-
// (through JSI::Runtime implementation's factory method), to enable
|
|
34
|
-
// subsequent evaluation of a script.
|
|
32
|
+
// (through JSI::Runtime implementation's factory method), to enable persistence of the prepared script
|
|
33
|
+
// and retrieval on subsequent evaluation of a script.
|
|
35
34
|
struct PreparedScriptStore {
|
|
36
35
|
virtual ~PreparedScriptStore() = default;
|
|
37
36
|
|
|
38
|
-
// Try to retrieve the prepared
|
|
39
|
-
// scriptSignature :
|
|
40
|
-
// RuntimeSignature :
|
|
37
|
+
// Try to retrieve the prepared JavaScript for a given combination of script & runtime.
|
|
38
|
+
// scriptSignature : JavaScript URL and version
|
|
39
|
+
// RuntimeSignature : JavaScript engine type and version
|
|
41
40
|
// prepareTag : Custom tag to uniquely identify JS engine specific preparation schemes. It is usually useful while
|
|
42
41
|
// experimentation and can be null. It is possible that no prepared script is available for a given script & runtime
|
|
43
42
|
// signature. This method should null if so
|
|
@@ -47,12 +46,12 @@ struct PreparedScriptStore {
|
|
|
47
46
|
const char *prepareTag // Optional tag. For e.g. eagerly evaluated vs lazy cache.
|
|
48
47
|
) noexcept = 0;
|
|
49
48
|
|
|
50
|
-
// Persist the
|
|
51
|
-
// scriptSignature :
|
|
52
|
-
// RuntimeSignature :
|
|
49
|
+
// Persist the prepared JavaScript for a given combination of script & runtime.
|
|
50
|
+
// scriptSignature : JavaScript URL and version
|
|
51
|
+
// RuntimeSignature : JavaScript engine type and version
|
|
53
52
|
// prepareTag : Custom tag to uniquely identify JS engine specific preparation schemes. It is usually useful while
|
|
54
53
|
// experimentation and can be null. It is possible that no prepared script is available for a given script & runtime
|
|
55
|
-
// signature. This method should null if so Any failure in
|
|
54
|
+
// signature. This method should null if so Any failure in persistence should be identified during the subsequent
|
|
56
55
|
// retrieval through the integrity mechanism which must be put into the storage.
|
|
57
56
|
virtual void persistPreparedScript(
|
|
58
57
|
std::shared_ptr<const facebook::jsi::Buffer> preparedScript,
|
|
@@ -63,17 +62,16 @@ struct PreparedScriptStore {
|
|
|
63
62
|
};
|
|
64
63
|
|
|
65
64
|
// JSI::Runtime implementation must be provided an instance on this interface to enable version sensitive capabilities
|
|
66
|
-
// such as usage of
|
|
67
|
-
//
|
|
65
|
+
// such as usage of prepared JavaScript script. Alternatively, this entity can be used to directly provide the
|
|
66
|
+
// JavaScript buffer and rich meta data to the JSI::Runtime instance.
|
|
68
67
|
struct ScriptStore {
|
|
69
68
|
virtual ~ScriptStore() = default;
|
|
70
69
|
|
|
71
|
-
// Return the
|
|
70
|
+
// Return the JavaScript buffer and version corresponding to a given URL.
|
|
72
71
|
virtual VersionedBuffer getVersionedScript(const std::string &url) noexcept = 0;
|
|
73
72
|
|
|
74
|
-
// Return the version of the
|
|
73
|
+
// Return the version of the JavaScript buffer corresponding to a given URL.
|
|
75
74
|
virtual ScriptVersion_t getScriptVersion(const std::string &url) noexcept = 0;
|
|
76
75
|
};
|
|
77
76
|
|
|
78
|
-
} // namespace jsi
|
|
79
|
-
} // namespace facebook
|
|
77
|
+
} // namespace facebook::jsi
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#include "V8RuntimeHolder.h"
|
|
5
|
+
#include <ApiLoaders/V8Api.h>
|
|
6
|
+
#include <NodeApiJsiRuntime.h>
|
|
7
|
+
#include <crash/verifyElseCrash.h>
|
|
8
|
+
#include "SafeLoadLibrary.h"
|
|
9
|
+
|
|
10
|
+
using namespace Microsoft::NodeApiJsi;
|
|
11
|
+
|
|
12
|
+
#define CRASH_ON_ERROR(result) VerifyElseCrash(result == napi_ok);
|
|
13
|
+
|
|
14
|
+
namespace Microsoft::ReactNative {
|
|
15
|
+
namespace {
|
|
16
|
+
|
|
17
|
+
class V8FuncResolver : public IFuncResolver {
|
|
18
|
+
public:
|
|
19
|
+
V8FuncResolver() : libHandle_(SafeLoadLibrary(L"v8jsi.dll")) {}
|
|
20
|
+
|
|
21
|
+
FuncPtr getFuncPtr(const char *funcName) override {
|
|
22
|
+
return reinterpret_cast<FuncPtr>(GetProcAddress(libHandle_, funcName));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private:
|
|
26
|
+
HMODULE libHandle_;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
V8Api &initV8Api() noexcept {
|
|
30
|
+
static V8FuncResolver funcResolver;
|
|
31
|
+
static V8Api s_v8Api(&funcResolver);
|
|
32
|
+
V8Api::setCurrent(&s_v8Api);
|
|
33
|
+
return s_v8Api;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
V8Api &getV8Api() noexcept {
|
|
37
|
+
static V8Api &s_v8Api = initV8Api();
|
|
38
|
+
return s_v8Api;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class V8Task {
|
|
42
|
+
public:
|
|
43
|
+
V8Task(void *taskData, jsr_task_run_cb taskRunCallback, jsr_data_delete_cb taskDataDeleteCallback, void *deleterData)
|
|
44
|
+
: taskData_(taskData),
|
|
45
|
+
taskRunCallback_(taskRunCallback),
|
|
46
|
+
taskDataDeleteCallback_(taskDataDeleteCallback),
|
|
47
|
+
deleterData_(deleterData) {}
|
|
48
|
+
|
|
49
|
+
V8Task(const V8Task &other) = delete;
|
|
50
|
+
V8Task &operator=(const V8Task &other) = delete;
|
|
51
|
+
|
|
52
|
+
~V8Task() {
|
|
53
|
+
if (taskDataDeleteCallback_ != nullptr) {
|
|
54
|
+
taskDataDeleteCallback_(taskData_, deleterData_);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
void Run() const {
|
|
59
|
+
if (taskRunCallback_ != nullptr) {
|
|
60
|
+
taskRunCallback_(taskData_);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private:
|
|
65
|
+
void *taskData_;
|
|
66
|
+
jsr_task_run_cb taskRunCallback_;
|
|
67
|
+
jsr_data_delete_cb taskDataDeleteCallback_;
|
|
68
|
+
void *deleterData_;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
class V8TaskRunner {
|
|
72
|
+
public:
|
|
73
|
+
static void Create(jsr_config config, std::shared_ptr<facebook::react::MessageQueueThread> queue) {
|
|
74
|
+
CRASH_ON_ERROR(
|
|
75
|
+
getV8Api().jsr_config_set_task_runner(config, new V8TaskRunner(std::move(queue)), &PostTask, &Delete, nullptr));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private:
|
|
79
|
+
V8TaskRunner(std::shared_ptr<facebook::react::MessageQueueThread> queue) : queue_(std::move(queue)) {}
|
|
80
|
+
|
|
81
|
+
static void NAPI_CDECL PostTask(
|
|
82
|
+
void *taskRunnerData,
|
|
83
|
+
void *taskData,
|
|
84
|
+
jsr_task_run_cb taskRunCallback,
|
|
85
|
+
jsr_data_delete_cb taskDataDeleteCallback,
|
|
86
|
+
void *deleterData) {
|
|
87
|
+
auto task = std::make_shared<V8Task>(taskData, taskRunCallback, taskDataDeleteCallback, deleterData);
|
|
88
|
+
reinterpret_cast<V8TaskRunner *>(taskRunnerData)->queue_->runOnQueue([task = std::move(task)] { task->Run(); });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static void NAPI_CDECL Delete(void *taskRunner, void * /*deleterData*/) {
|
|
92
|
+
delete reinterpret_cast<V8TaskRunner *>(taskRunner);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private:
|
|
96
|
+
std::shared_ptr<facebook::react::MessageQueueThread> queue_;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
struct V8JsiBuffer : facebook::jsi::Buffer {
|
|
100
|
+
static std::shared_ptr<const facebook::jsi::Buffer>
|
|
101
|
+
Create(const uint8_t *buffer, size_t bufferSize, jsr_data_delete_cb bufferDeleteCallback, void *deleterData) {
|
|
102
|
+
return std::shared_ptr<const facebook::jsi::Buffer>(
|
|
103
|
+
new V8JsiBuffer(buffer, bufferSize, bufferDeleteCallback, deleterData));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
V8JsiBuffer(
|
|
107
|
+
const uint8_t *buffer,
|
|
108
|
+
size_t bufferSize,
|
|
109
|
+
jsr_data_delete_cb bufferDeleteCallback,
|
|
110
|
+
void *deleterData) noexcept
|
|
111
|
+
: buffer_(buffer),
|
|
112
|
+
bufferSize_(bufferSize),
|
|
113
|
+
bufferDeleteCallback_(bufferDeleteCallback),
|
|
114
|
+
deleterData_(deleterData) {}
|
|
115
|
+
|
|
116
|
+
~V8JsiBuffer() override {
|
|
117
|
+
if (bufferDeleteCallback_) {
|
|
118
|
+
bufferDeleteCallback_(const_cast<uint8_t *>(buffer_), deleterData_);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const uint8_t *data() const override {
|
|
123
|
+
return buffer_;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
size_t size() const override {
|
|
127
|
+
return bufferSize_;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private:
|
|
131
|
+
const uint8_t *buffer_;
|
|
132
|
+
size_t bufferSize_;
|
|
133
|
+
jsr_data_delete_cb bufferDeleteCallback_;
|
|
134
|
+
void *deleterData_;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
class V8ScriptCache {
|
|
138
|
+
public:
|
|
139
|
+
static void Create(jsr_config config, std::shared_ptr<facebook::jsi::PreparedScriptStore> scriptStore) {
|
|
140
|
+
CRASH_ON_ERROR(getV8Api().jsr_config_set_script_cache(
|
|
141
|
+
config, new V8ScriptCache(std::move(scriptStore)), &LoadScript, &StoreScript, &Delete, nullptr));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private:
|
|
145
|
+
V8ScriptCache(std::shared_ptr<facebook::jsi::PreparedScriptStore> scriptStore)
|
|
146
|
+
: scriptStore_(std::move(scriptStore)) {}
|
|
147
|
+
|
|
148
|
+
static void NAPI_CDECL LoadScript(
|
|
149
|
+
void *scriptCache,
|
|
150
|
+
const char *sourceUrl,
|
|
151
|
+
uint64_t sourceHash,
|
|
152
|
+
const char *runtimeName,
|
|
153
|
+
uint64_t runtimeVersion,
|
|
154
|
+
const char *cacheTag,
|
|
155
|
+
const uint8_t **buffer,
|
|
156
|
+
size_t *bufferSize,
|
|
157
|
+
jsr_data_delete_cb *bufferDeleteCallback,
|
|
158
|
+
void **deleterData) {
|
|
159
|
+
auto &scriptStore = reinterpret_cast<V8ScriptCache *>(scriptCache)->scriptStore_;
|
|
160
|
+
std::shared_ptr<const facebook::jsi::Buffer> preparedScript = scriptStore->tryGetPreparedScript(
|
|
161
|
+
facebook::jsi::ScriptSignature{sourceUrl, sourceHash},
|
|
162
|
+
facebook::jsi::JSRuntimeSignature{runtimeName, runtimeVersion},
|
|
163
|
+
cacheTag);
|
|
164
|
+
if (preparedScript) {
|
|
165
|
+
*buffer = preparedScript->data();
|
|
166
|
+
*bufferSize = preparedScript->size();
|
|
167
|
+
*bufferDeleteCallback = [](void * /*data*/, void *deleterData) noexcept {
|
|
168
|
+
delete reinterpret_cast<std::shared_ptr<const facebook::jsi::Buffer> *>(deleterData);
|
|
169
|
+
};
|
|
170
|
+
*deleterData = new std::shared_ptr<const facebook::jsi::Buffer>(std::move(preparedScript));
|
|
171
|
+
} else {
|
|
172
|
+
*buffer = nullptr;
|
|
173
|
+
*bufferSize = 0;
|
|
174
|
+
*bufferDeleteCallback = nullptr;
|
|
175
|
+
*deleterData = nullptr;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
static void NAPI_CDECL StoreScript(
|
|
180
|
+
void *scriptCache,
|
|
181
|
+
const char *sourceUrl,
|
|
182
|
+
uint64_t sourceHash,
|
|
183
|
+
const char *runtimeName,
|
|
184
|
+
uint64_t runtimeVersion,
|
|
185
|
+
const char *cacheTag,
|
|
186
|
+
const uint8_t *buffer,
|
|
187
|
+
size_t bufferSize,
|
|
188
|
+
jsr_data_delete_cb bufferDeleteCallback,
|
|
189
|
+
void *deleterData) {
|
|
190
|
+
auto &scriptStore = reinterpret_cast<V8ScriptCache *>(scriptCache)->scriptStore_;
|
|
191
|
+
scriptStore->persistPreparedScript(
|
|
192
|
+
V8JsiBuffer::Create(buffer, bufferSize, bufferDeleteCallback, deleterData),
|
|
193
|
+
facebook::jsi::ScriptSignature{sourceUrl, sourceHash},
|
|
194
|
+
facebook::jsi::JSRuntimeSignature{runtimeName, runtimeVersion},
|
|
195
|
+
cacheTag);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
static void NAPI_CDECL Delete(void *scriptCache, void * /*deleterData*/) {
|
|
199
|
+
delete reinterpret_cast<V8ScriptCache *>(scriptCache);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private:
|
|
203
|
+
std::shared_ptr<facebook::jsi::PreparedScriptStore> scriptStore_;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
} // namespace
|
|
207
|
+
|
|
208
|
+
V8RuntimeHolder::V8RuntimeHolder(
|
|
209
|
+
std::shared_ptr<facebook::react::DevSettings> devSettings,
|
|
210
|
+
std::shared_ptr<facebook::react::MessageQueueThread> jsQueue,
|
|
211
|
+
std::shared_ptr<facebook::jsi::PreparedScriptStore> preparedScriptStore,
|
|
212
|
+
bool enableMultiThreadingSupport) noexcept
|
|
213
|
+
: m_weakDevSettings(devSettings),
|
|
214
|
+
m_jsQueue(std::move(jsQueue)),
|
|
215
|
+
m_preparedScriptStore(std::move(preparedScriptStore)),
|
|
216
|
+
m_enableMultiThreadingSupport(enableMultiThreadingSupport) {}
|
|
217
|
+
|
|
218
|
+
void V8RuntimeHolder::initRuntime() noexcept {
|
|
219
|
+
std::shared_ptr<facebook::react::DevSettings> devSettings = m_weakDevSettings.lock();
|
|
220
|
+
VerifyElseCrash(devSettings);
|
|
221
|
+
|
|
222
|
+
V8Api &api = getV8Api();
|
|
223
|
+
V8Api::setCurrent(&api);
|
|
224
|
+
jsr_config config{};
|
|
225
|
+
CRASH_ON_ERROR(api.jsr_create_config(&config));
|
|
226
|
+
CRASH_ON_ERROR(api.jsr_config_enable_inspector(config, devSettings->useDirectDebugger));
|
|
227
|
+
CRASH_ON_ERROR(api.jsr_config_set_inspector_runtime_name(config, devSettings->debuggerRuntimeName.c_str()));
|
|
228
|
+
CRASH_ON_ERROR(api.jsr_config_set_inspector_port(config, devSettings->debuggerPort));
|
|
229
|
+
CRASH_ON_ERROR(api.jsr_config_set_inspector_break_on_start(config, devSettings->debuggerBreakOnNextLine));
|
|
230
|
+
CRASH_ON_ERROR(api.v8_config_enable_multithreading(config, m_enableMultiThreadingSupport));
|
|
231
|
+
|
|
232
|
+
if (m_jsQueue) {
|
|
233
|
+
V8TaskRunner::Create(config, m_jsQueue);
|
|
234
|
+
}
|
|
235
|
+
if (m_preparedScriptStore) {
|
|
236
|
+
V8ScriptCache::Create(config, m_preparedScriptStore);
|
|
237
|
+
}
|
|
238
|
+
jsr_runtime runtime{};
|
|
239
|
+
CRASH_ON_ERROR(api.jsr_create_runtime(config, &runtime));
|
|
240
|
+
CRASH_ON_ERROR(api.jsr_delete_config(config));
|
|
241
|
+
|
|
242
|
+
CRASH_ON_ERROR(api.jsr_create_runtime(config, &runtime));
|
|
243
|
+
|
|
244
|
+
napi_env env{};
|
|
245
|
+
CRASH_ON_ERROR(api.jsr_runtime_get_node_api_env(runtime, &env));
|
|
246
|
+
|
|
247
|
+
m_jsiRuntime =
|
|
248
|
+
makeNodeApiJsiRuntime(env, &api, [runtime]() { CRASH_ON_ERROR(V8Api::current()->jsr_delete_runtime(runtime)); });
|
|
249
|
+
m_ownThreadId = std::this_thread::get_id();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
facebook::react::JSIEngineOverride V8RuntimeHolder::getRuntimeType() noexcept {
|
|
253
|
+
return facebook::react::JSIEngineOverride::V8NodeApi;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
std::shared_ptr<facebook::jsi::Runtime> V8RuntimeHolder::getRuntime() noexcept {
|
|
257
|
+
std::call_once(m_onceFlag, [this]() { initRuntime(); });
|
|
258
|
+
VerifyElseCrash(m_jsiRuntime);
|
|
259
|
+
return m_jsiRuntime;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
} // namespace Microsoft::ReactNative
|