react-native-windows 0.0.0-canary.460 → 0.0.0-canary.461

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.
@@ -25,6 +25,7 @@
25
25
  #include "ScrollViewComponentView.h"
26
26
  #include "TextComponentView.h"
27
27
  #include "ViewComponentView.h"
28
+ #include "XamlView.h"
28
29
 
29
30
  namespace Microsoft::ReactNative {
30
31
 
@@ -60,7 +61,7 @@ ComponentViewDescriptor const &ComponentViewRegistry::dequeueComponentViewWithCo
60
61
  view = std::make_shared<ViewComponentView>();
61
62
  }
62
63
 
63
- view->Element().Tag(winrt::box_value(tag));
64
+ SetTag(view->Element(), tag);
64
65
  auto it = m_registry.insert({tag, ComponentViewDescriptor{view}});
65
66
  return it.first->second;
66
67
  }
@@ -79,6 +80,6 @@ void ComponentViewRegistry::enqueueComponentViewWithComponentHandle(
79
80
  assert(m_registry.find(tag) != m_registry.end());
80
81
 
81
82
  m_registry.erase(tag);
82
- static_cast<ViewComponentView &>(*componentViewDescriptor.view).Element().Tag(nullptr);
83
+ SetTag(static_cast<ViewComponentView &>(*componentViewDescriptor.view).Element(), nullptr);
83
84
  }
84
85
  } // namespace Microsoft::ReactNative
@@ -0,0 +1,101 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ #include "pch.h"
5
+ #include "JSDispatcherWriter.h"
6
+ #include <JSI/JSIDynamic.h>
7
+ #include <crash/verifyElseCrash.h>
8
+
9
+ namespace winrt::Microsoft::ReactNative {
10
+
11
+ //===========================================================================
12
+ // JSDispatcherWriter implementation
13
+ //===========================================================================
14
+
15
+ JSDispatcherWriter::JSDispatcherWriter(
16
+ IReactDispatcher const &jsDispatcher,
17
+ facebook::jsi::Runtime &jsiRuntime) noexcept
18
+ : m_jsDispatcher(jsDispatcher), m_jsiRuntime(jsiRuntime) {}
19
+
20
+ void JSDispatcherWriter::WithResultArgs(
21
+ Mso::Functor<void(facebook::jsi::Runtime &rt, facebook::jsi::Value const *args, size_t argCount)>
22
+ handler) noexcept {
23
+ if (m_jsDispatcher.HasThreadAccess()) {
24
+ VerifyElseCrash(!m_dynamicWriter);
25
+ const facebook::jsi::Value *args{nullptr};
26
+ size_t argCount{0};
27
+ m_jsiWriter->AccessResultAsArgs(args, argCount);
28
+ handler(m_jsiRuntime, args, argCount);
29
+ } else {
30
+ VerifyElseCrash(!m_jsiWriter);
31
+ folly::dynamic dynValue = m_dynamicWriter->TakeValue();
32
+ m_jsDispatcher.Post([handler, dynValue, &runtime = m_jsiRuntime]() {
33
+ VerifyElseCrash(dynValue.isArray());
34
+ std::vector<facebook::jsi::Value> args;
35
+ args.reserve(dynValue.size());
36
+ for (auto const &item : dynValue) {
37
+ args.emplace_back(facebook::jsi::valueFromDynamic(runtime, item));
38
+ }
39
+ handler(runtime, args.data(), args.size());
40
+ });
41
+ }
42
+ }
43
+
44
+ void JSDispatcherWriter::WriteNull() noexcept {
45
+ GetWriter().WriteNull();
46
+ }
47
+
48
+ void JSDispatcherWriter::WriteBoolean(bool value) noexcept {
49
+ GetWriter().WriteBoolean(value);
50
+ }
51
+
52
+ void JSDispatcherWriter::WriteInt64(int64_t value) noexcept {
53
+ GetWriter().WriteInt64(value);
54
+ }
55
+
56
+ void JSDispatcherWriter::WriteDouble(double value) noexcept {
57
+ GetWriter().WriteDouble(value);
58
+ }
59
+
60
+ void JSDispatcherWriter::WriteString(const winrt::hstring &value) noexcept {
61
+ GetWriter().WriteString(value);
62
+ }
63
+
64
+ void JSDispatcherWriter::WriteObjectBegin() noexcept {
65
+ GetWriter().WriteObjectBegin();
66
+ }
67
+
68
+ void JSDispatcherWriter::WritePropertyName(const winrt::hstring &name) noexcept {
69
+ GetWriter().WritePropertyName(name);
70
+ }
71
+
72
+ void JSDispatcherWriter::WriteObjectEnd() noexcept {
73
+ GetWriter().WriteObjectEnd();
74
+ }
75
+
76
+ void JSDispatcherWriter::WriteArrayBegin() noexcept {
77
+ GetWriter().WriteArrayBegin();
78
+ }
79
+
80
+ void JSDispatcherWriter::WriteArrayEnd() noexcept {
81
+ GetWriter().WriteArrayEnd();
82
+ }
83
+
84
+ IJSValueWriter JSDispatcherWriter::GetWriter() noexcept {
85
+ if (m_jsDispatcher.HasThreadAccess()) {
86
+ VerifyElseCrash(!m_dynamicWriter);
87
+ if (!m_jsiWriter) {
88
+ m_jsiWriter = winrt::make_self<JsiWriter>(m_jsiRuntime);
89
+ m_writer = m_jsiWriter.as<IJSValueWriter>();
90
+ }
91
+ } else {
92
+ VerifyElseCrash(!m_jsiWriter);
93
+ if (!m_dynamicWriter) {
94
+ m_dynamicWriter = winrt::make_self<DynamicWriter>();
95
+ m_writer = m_dynamicWriter.as<IJSValueWriter>();
96
+ }
97
+ }
98
+ return m_writer;
99
+ }
100
+
101
+ } // namespace winrt::Microsoft::ReactNative
@@ -0,0 +1,44 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ #pragma once
4
+
5
+ #include <functional/functor.h>
6
+ #include "DynamicWriter.h"
7
+ #include "JsiWriter.h"
8
+ #include "folly/dynamic.h"
9
+ #include "winrt/Microsoft.ReactNative.h"
10
+
11
+ namespace winrt::Microsoft::ReactNative {
12
+
13
+ // IJSValueWriter to ensure that JsiWriter is always used from JSDispatcher.
14
+ // In case if writing is done outside of JSDispatcher, it uses DynamicWriter to create
15
+ // folly::dynamic which then is written to JsiWriter in JSDispatcher.
16
+ struct JSDispatcherWriter : winrt::implements<JSDispatcherWriter, IJSValueWriter> {
17
+ JSDispatcherWriter(IReactDispatcher const &jsDispatcher, facebook::jsi::Runtime &jsiRuntime) noexcept;
18
+ void WithResultArgs(Mso::Functor<void(facebook::jsi::Runtime &rt, facebook::jsi::Value const *args, size_t argCount)>
19
+ handler) noexcept;
20
+
21
+ public: // IJSValueWriter
22
+ void WriteNull() noexcept;
23
+ void WriteBoolean(bool value) noexcept;
24
+ void WriteInt64(int64_t value) noexcept;
25
+ void WriteDouble(double value) noexcept;
26
+ void WriteString(const winrt::hstring &value) noexcept;
27
+ void WriteObjectBegin() noexcept;
28
+ void WritePropertyName(const winrt::hstring &name) noexcept;
29
+ void WriteObjectEnd() noexcept;
30
+ void WriteArrayBegin() noexcept;
31
+ void WriteArrayEnd() noexcept;
32
+
33
+ private:
34
+ IJSValueWriter GetWriter() noexcept;
35
+
36
+ private:
37
+ IReactDispatcher m_jsDispatcher;
38
+ facebook::jsi::Runtime &m_jsiRuntime;
39
+ winrt::com_ptr<DynamicWriter> m_dynamicWriter;
40
+ winrt::com_ptr<JsiWriter> m_jsiWriter;
41
+ IJSValueWriter m_writer;
42
+ };
43
+
44
+ } // namespace winrt::Microsoft::ReactNative
@@ -61,7 +61,7 @@ void JsiWriter::WriteDouble(double value) noexcept {
61
61
  }
62
62
 
63
63
  void JsiWriter::WriteString(const winrt::hstring &value) noexcept {
64
- WriteValue({m_runtime, facebook::jsi::String::createFromUtf8(m_runtime, winrt::to_string(value))});
64
+ WriteValue({facebook::jsi::String::createFromUtf8(m_runtime, winrt::to_string(value))});
65
65
  }
66
66
 
67
67
  void JsiWriter::WriteObjectBegin() noexcept {
@@ -163,16 +163,4 @@ void JsiWriter::Push(Container &&container) noexcept {
163
163
  m_containers.push_back(std::move(container));
164
164
  }
165
165
 
166
- /*static*/ facebook::jsi::Value JsiWriter::ToJsiValue(
167
- facebook::jsi::Runtime &runtime,
168
- JSValueArgWriter const &argWriter) noexcept {
169
- if (argWriter) {
170
- IJSValueWriter jsiWriter = winrt::make<JsiWriter>(runtime);
171
- argWriter(jsiWriter);
172
- return jsiWriter.as<JsiWriter>()->MoveResult();
173
- }
174
-
175
- return {};
176
- }
177
-
178
166
  } // namespace winrt::Microsoft::ReactNative
@@ -35,9 +35,6 @@ struct JsiWriter : winrt::implements<JsiWriter, IJSValueWriter> {
35
35
  void WriteArrayBegin() noexcept;
36
36
  void WriteArrayEnd() noexcept;
37
37
 
38
- public:
39
- static facebook::jsi::Value ToJsiValue(facebook::jsi::Runtime &runtime, JSValueArgWriter const &argWriter) noexcept;
40
-
41
38
  private:
42
39
  enum class ContainerState {
43
40
  AcceptValueAndFinish,
@@ -191,6 +191,9 @@
191
191
  <ClInclude Include="DynamicWriter.h">
192
192
  <DependentUpon>IJSValueWriter.idl</DependentUpon>
193
193
  </ClInclude>
194
+ <ClInclude Include="JSDispatcherWriter.h">
195
+ <DependentUpon>IJSValueWriter.idl</DependentUpon>
196
+ </ClInclude>
194
197
  <ClInclude Include="GlyphViewManager.h" />
195
198
  <ClInclude Include="HResult.h" />
196
199
  <ClInclude Include="IReactDispatcher.h">
@@ -523,6 +526,9 @@
523
526
  <ClCompile Include="DynamicWriter.cpp">
524
527
  <DependentUpon>IJSValueWriter.idl</DependentUpon>
525
528
  </ClCompile>
529
+ <ClCompile Include="JSDispatcherWriter.cpp">
530
+ <DependentUpon>IJSValueWriter.idl</DependentUpon>
531
+ </ClCompile>
526
532
  <ClCompile Include="GlyphViewManager.cpp" />
527
533
  <ClCompile Include="IReactDispatcher.cpp">
528
534
  <DependentUpon>IReactDispatcher.idl</DependentUpon>
@@ -236,7 +236,7 @@ void NativeUIManager::AddRootView(ShadowNode &shadowNode, facebook::react::IReac
236
236
  m_tagsToYogaNodes.emplace(shadowNode.m_tag, make_yoga_node(m_yogaConfig));
237
237
 
238
238
  auto element = view.as<xaml::FrameworkElement>();
239
- element.Tag(winrt::PropertyValue::CreateInt64(shadowNode.m_tag));
239
+ Microsoft::ReactNative::SetTag(element, shadowNode.m_tag);
240
240
 
241
241
  // Add listener to size change so we can redo the layout when that happens
242
242
  m_sizeChangedVector.push_back(
@@ -980,7 +980,7 @@ void NativeUIManager::measure(
980
980
  int64_t childTag = rootTag;
981
981
  while (true) {
982
982
  auto &currNode = m_host->GetShadowNodeForTag(rootTag);
983
- if (currNode.m_parent == -1)
983
+ if (currNode.m_parent == InvalidTag)
984
984
  break;
985
985
  ShadowNodeBase &rootNode = static_cast<ShadowNodeBase &>(currNode);
986
986
  if (rootNode.IsWindowed()) {
@@ -1094,9 +1094,9 @@ void NativeUIManager::findSubviewIn(
1094
1094
 
1095
1095
  for (const auto &elem : hitTestElements) {
1096
1096
  if (foundElement = elem.try_as<xaml::FrameworkElement>()) {
1097
- auto tag = foundElement.Tag();
1098
- if (tag != nullptr) {
1099
- foundTag = tag.as<winrt::IPropertyValue>().GetInt64();
1097
+ auto tag = GetTag(foundElement);
1098
+ if (tag != InvalidTag) {
1099
+ foundTag = tag;
1100
1100
  break;
1101
1101
  }
1102
1102
  }
@@ -7,6 +7,7 @@
7
7
  #include "pch.h"
8
8
  #include "TurboModulesProvider.h"
9
9
  #include <ReactCommon/TurboModuleUtils.h>
10
+ #include "JSDispatcherWriter.h"
10
11
  #include "JsiApi.h"
11
12
  #include "JsiReader.h"
12
13
  #include "JsiWriter.h"
@@ -58,7 +59,7 @@ struct TurboModuleBuilder : winrt::implements<TurboModuleBuilder, IReactModuleBu
58
59
  std::unordered_map<std::string, TurboModuleMethodInfo> m_methods;
59
60
  std::unordered_map<std::string, SyncMethodDelegate> m_syncMethods;
60
61
  std::vector<ConstantProviderDelegate> m_constantProviders;
61
- bool m_constantsEvaluated = false;
62
+ bool m_constantsEvaluated{false};
62
63
 
63
64
  private:
64
65
  void EnsureMemberNotSet(const std::string &key, bool checkingMethod) noexcept {
@@ -82,11 +83,13 @@ class TurboModuleImpl : public facebook::react::TurboModule {
82
83
  TurboModuleImpl(
83
84
  const IReactContext &reactContext,
84
85
  const std::string &name,
85
- std::shared_ptr<facebook::react::CallInvoker> jsInvoker,
86
- ReactModuleProvider reactModuleProvider)
87
- : facebook::react::TurboModule(name, jsInvoker), m_moduleBuilder(winrt::make<TurboModuleBuilder>(reactContext)) {
88
- providedModule = reactModuleProvider(m_moduleBuilder);
89
- if (auto hostObject = providedModule.try_as<IJsiHostObject>()) {
86
+ const std::shared_ptr<facebook::react::CallInvoker> &jsInvoker,
87
+ const ReactModuleProvider &reactModuleProvider)
88
+ : facebook::react::TurboModule(name, jsInvoker),
89
+ m_reactContext(reactContext),
90
+ m_moduleBuilder(winrt::make<TurboModuleBuilder>(reactContext)),
91
+ m_providedModule(reactModuleProvider(m_moduleBuilder)) {
92
+ if (auto hostObject = m_providedModule.try_as<IJsiHostObject>()) {
90
93
  m_hostObjectWrapper = std::make_shared<implementation::HostObjectWrapper>(hostObject);
91
94
  }
92
95
  }
@@ -96,12 +99,13 @@ class TurboModuleImpl : public facebook::react::TurboModule {
96
99
  return m_hostObjectWrapper->getPropertyNames(rt);
97
100
  }
98
101
 
99
- std::vector<facebook::jsi::PropNameID> props;
100
- auto tmb = m_moduleBuilder.as<TurboModuleBuilder>();
101
- for (auto &it : tmb->m_methods) {
102
- props.push_back(facebook::jsi::PropNameID::forAscii(rt, it.first));
102
+ auto turboModuleBuilder = m_moduleBuilder.as<TurboModuleBuilder>();
103
+ std::vector<facebook::jsi::PropNameID> propertyNames;
104
+ propertyNames.reserve(turboModuleBuilder->m_methods.size());
105
+ for (auto &methodInfo : turboModuleBuilder->m_methods) {
106
+ propertyNames.push_back(facebook::jsi::PropNameID::forAscii(rt, methodInfo.first));
103
107
  }
104
- return props;
108
+ return propertyNames;
105
109
  };
106
110
 
107
111
  facebook::jsi::Value get(facebook::jsi::Runtime &runtime, const facebook::jsi::PropNameID &propName) override {
@@ -110,25 +114,25 @@ class TurboModuleImpl : public facebook::react::TurboModule {
110
114
  }
111
115
 
112
116
  // it is not safe to assume that "runtime" never changes, so members are not cached here
113
- auto tmb = m_moduleBuilder.as<TurboModuleBuilder>();
114
- auto key = propName.utf8(runtime);
117
+ auto moduleBuilder = m_moduleBuilder.as<TurboModuleBuilder>();
118
+ std::string key = propName.utf8(runtime);
115
119
 
116
- if (key == "getConstants" && tmb->m_constantProviders.size() > 0) {
120
+ if (key == "getConstants" && !moduleBuilder->m_constantProviders.empty()) {
117
121
  // try to find getConstants if there is any constant
118
122
  return facebook::jsi::Function::createFromHostFunction(
119
123
  runtime,
120
124
  propName,
121
125
  0,
122
- [&runtime, tmb](
126
+ [moduleBuilder](
123
127
  facebook::jsi::Runtime &rt,
124
128
  const facebook::jsi::Value &thisVal,
125
129
  const facebook::jsi::Value *args,
126
130
  size_t count) {
127
131
  // collect all constants to an object
128
- auto writer = winrt::make<JsiWriter>(runtime);
132
+ auto writer = winrt::make<JsiWriter>(rt);
129
133
  writer.WriteObjectBegin();
130
- for (auto cp : tmb->m_constantProviders) {
131
- cp(writer);
134
+ for (auto constantProvider : moduleBuilder->m_constantProviders) {
135
+ constantProvider(writer);
132
136
  }
133
137
  writer.WriteObjectEnd();
134
138
  return writer.as<JsiWriter>()->MoveResult();
@@ -137,150 +141,134 @@ class TurboModuleImpl : public facebook::react::TurboModule {
137
141
 
138
142
  {
139
143
  // try to find a Method
140
- auto it = tmb->m_methods.find(key);
141
- if (it != tmb->m_methods.end()) {
142
- return facebook::jsi::Function::createFromHostFunction(
143
- runtime,
144
- propName,
145
- 0,
146
- [&runtime, method = it->second](
147
- facebook::jsi::Runtime &rt,
148
- const facebook::jsi::Value &thisVal,
149
- const facebook::jsi::Value *args,
150
- size_t count) {
151
- // prepare input arguments
152
- size_t serializableArgumentCount = count;
153
- switch (method.ReturnType) {
154
- case MethodReturnType::Callback:
155
- VerifyElseCrash(count >= 1);
156
- VerifyElseCrash(args[count - 1].isObject() && args[count - 1].asObject(runtime).isFunction(runtime));
157
- serializableArgumentCount -= 1;
158
- break;
159
- case MethodReturnType::TwoCallbacks:
160
- VerifyElseCrash(count >= 2);
161
- VerifyElseCrash(args[count - 1].isObject() && args[count - 1].asObject(runtime).isFunction(runtime));
162
- VerifyElseCrash(args[count - 2].isObject() && args[count - 2].asObject(runtime).isFunction(runtime));
163
- serializableArgumentCount -= 2;
164
- break;
165
- case MethodReturnType::Void:
166
- case MethodReturnType::Promise:
167
- // handled below
168
- break;
169
- }
170
- auto argReader = winrt::make<JsiReader>(runtime, args, serializableArgumentCount);
171
-
172
- // prepare output value
173
- // TODO: it is no reason to pass a argWriter just to receive [undefined] for void, should be optimized
174
- auto argWriter = winrt::make<JsiWriter>(runtime);
175
-
176
- // call the function
177
- switch (method.ReturnType) {
178
- case MethodReturnType::Void: {
179
- method.Method(argReader, argWriter, nullptr, nullptr);
144
+ auto it = moduleBuilder->m_methods.find(key);
145
+ if (it != moduleBuilder->m_methods.end()) {
146
+ TurboModuleMethodInfo methodInfo = it->second;
147
+ switch (methodInfo.ReturnType) {
148
+ case MethodReturnType::Void:
149
+ return facebook::jsi::Function::createFromHostFunction(
150
+ runtime,
151
+ propName,
152
+ 0,
153
+ [methodInfo](
154
+ facebook::jsi::Runtime &rt,
155
+ const facebook::jsi::Value & /*thisVal*/,
156
+ const facebook::jsi::Value *args,
157
+ size_t argCount) {
158
+ methodInfo.Method(winrt::make<JsiReader>(rt, args, argCount), nullptr, nullptr, nullptr);
159
+ return facebook::jsi::Value::undefined();
160
+ });
161
+ case MethodReturnType::Callback:
162
+ return facebook::jsi::Function::createFromHostFunction(
163
+ runtime,
164
+ propName,
165
+ 0,
166
+ [jsDispatcher = m_reactContext.JSDispatcher(), methodInfo](
167
+ facebook::jsi::Runtime &rt,
168
+ const facebook::jsi::Value & /*thisVal*/,
169
+ const facebook::jsi::Value *args,
170
+ size_t argCount) {
171
+ VerifyElseCrash(argCount > 0);
172
+ methodInfo.Method(
173
+ winrt::make<JsiReader>(rt, args, argCount - 1),
174
+ winrt::make<JSDispatcherWriter>(jsDispatcher, rt),
175
+ MakeCallback(rt, {rt, args[argCount - 1]}),
176
+ nullptr);
177
+ return facebook::jsi::Value::undefined();
178
+ });
179
+ case MethodReturnType::TwoCallbacks:
180
+ return facebook::jsi::Function::createFromHostFunction(
181
+ runtime,
182
+ propName,
183
+ 0,
184
+ [jsDispatcher = m_reactContext.JSDispatcher(), methodInfo](
185
+ facebook::jsi::Runtime &rt,
186
+ const facebook::jsi::Value & /*thisVal*/,
187
+ const facebook::jsi::Value *args,
188
+ size_t argCount) {
189
+ VerifyElseCrash(argCount > 1);
190
+ methodInfo.Method(
191
+ winrt::make<JsiReader>(rt, args, argCount - 2),
192
+ winrt::make<JSDispatcherWriter>(jsDispatcher, rt),
193
+ MakeCallback(rt, {rt, args[argCount - 2]}),
194
+ MakeCallback(rt, {rt, args[argCount - 1]}));
180
195
  return facebook::jsi::Value::undefined();
181
- }
182
- case MethodReturnType::Promise: {
196
+ });
197
+ case MethodReturnType::Promise:
198
+ return facebook::jsi::Function::createFromHostFunction(
199
+ runtime,
200
+ propName,
201
+ 0,
202
+ [jsDispatcher = m_reactContext.JSDispatcher(), methodInfo](
203
+ facebook::jsi::Runtime &rt,
204
+ const facebook::jsi::Value & /*thisVal*/,
205
+ const facebook::jsi::Value *args,
206
+ size_t count) {
207
+ auto argReader = winrt::make<JsiReader>(rt, args, count);
208
+ auto argWriter = winrt::make<JSDispatcherWriter>(jsDispatcher, rt);
183
209
  return facebook::react::createPromiseAsJSIValue(
184
- runtime, [=](facebook::jsi::Runtime &runtime, std::shared_ptr<facebook::react::Promise> promise) {
185
- method.Method(
210
+ rt,
211
+ [methodInfo, argReader, argWriter](
212
+ facebook::jsi::Runtime &runtime, std::shared_ptr<facebook::react::Promise> promise) {
213
+ methodInfo.Method(
186
214
  argReader,
187
215
  argWriter,
188
- [promise, &runtime](const IJSValueWriter &writer) {
189
- auto result = writer.as<JsiWriter>()->MoveResult();
190
- if (result.isObject()) {
191
- auto resultArrayObject = result.getObject(runtime);
192
- VerifyElseCrash(resultArrayObject.isArray(runtime));
193
- auto resultArray = resultArrayObject.getArray(runtime);
194
- VerifyElseCrash(resultArray.length(runtime) == 1);
195
- auto resultItem = resultArray.getValueAtIndex(runtime, 0);
196
- promise->resolve(resultItem);
197
- } else {
198
- VerifyElseCrash(false);
199
- }
216
+ [promise](const IJSValueWriter &writer) {
217
+ writer.as<JSDispatcherWriter>()->WithResultArgs([promise](
218
+ facebook::jsi::Runtime &runtime,
219
+ facebook::jsi::Value const *args,
220
+ size_t argCount) {
221
+ VerifyElseCrash(argCount == 1);
222
+ promise->resolve(args[0]);
223
+ });
200
224
  },
201
- [promise, &runtime](const IJSValueWriter &writer) {
202
- auto result = writer.as<JsiWriter>()->MoveResult();
203
- if (result.isString()) {
204
- promise->reject(result.getString(runtime).utf8(runtime));
205
- } else if (result.isObject()) {
206
- auto errorArrayObject = result.getObject(runtime);
207
- VerifyElseCrash(errorArrayObject.isArray(runtime));
208
- auto errorArray = errorArrayObject.getArray(runtime);
209
- VerifyElseCrash(errorArray.length(runtime) == 1);
210
- auto errorObjectValue = errorArray.getValueAtIndex(runtime, 0);
211
- VerifyElseCrash(errorObjectValue.isObject());
212
- auto errorObject = errorObjectValue.getObject(runtime);
213
- VerifyElseCrash(errorObject.hasProperty(runtime, "message"));
214
- auto errorMessage = errorObject.getProperty(runtime, "message");
215
- VerifyElseCrash(errorMessage.isString());
216
- promise->reject(errorMessage.getString(runtime).utf8(runtime));
217
- } else {
218
- VerifyElseCrash(false);
219
- }
225
+ [promise](const IJSValueWriter &writer) {
226
+ writer.as<JSDispatcherWriter>()->WithResultArgs([promise](
227
+ facebook::jsi::Runtime &runtime,
228
+ facebook::jsi::Value const *args,
229
+ size_t argCount) {
230
+ VerifyElseCrash(argCount == 1);
231
+ // To match the Android and iOS TurboModule behavior we create the Error object for
232
+ // the Promise rejection the same way as in updateErrorWithErrorData method.
233
+ // See react-native/Libraries/BatchedBridge/NativeModules.js for details.
234
+ auto error = runtime.global()
235
+ .getPropertyAsFunction(runtime, "Error")
236
+ .callAsConstructor(runtime, {});
237
+ auto &errorData = args[0];
238
+ if (errorData.isObject()) {
239
+ runtime.global()
240
+ .getPropertyAsObject(runtime, "Object")
241
+ .getPropertyAsFunction(runtime, "assign")
242
+ .call(runtime, error, errorData.getObject(runtime));
243
+ }
244
+ promise->reject_.call(runtime, error);
245
+ });
220
246
  });
221
247
  });
222
- }
223
- case MethodReturnType::Callback:
224
- case MethodReturnType::TwoCallbacks: {
225
- facebook::jsi::Value resolveFunction;
226
- facebook::jsi::Value rejectFunction;
227
- if (method.ReturnType == MethodReturnType::Callback) {
228
- resolveFunction = {runtime, args[count - 1]};
229
- } else {
230
- resolveFunction = {runtime, args[count - 2]};
231
- rejectFunction = {runtime, args[count - 1]};
232
- }
233
-
234
- auto makeCallback =
235
- [&runtime](const facebook::jsi::Value &callbackValue) noexcept -> MethodResultCallback {
236
- // workaround: xcode doesn't accept a captured value with only rvalue copy constructor
237
- auto functionObject =
238
- std::make_shared<facebook::jsi::Function>(callbackValue.asObject(runtime).asFunction(runtime));
239
- return [&runtime, callbackFunction = functionObject](const IJSValueWriter &writer) noexcept {
240
- const facebook::jsi::Value *resultArgs = nullptr;
241
- size_t resultCount = 0;
242
- writer.as<JsiWriter>()->AccessResultAsArgs(resultArgs, resultCount);
243
- callbackFunction->call(runtime, resultArgs, resultCount);
244
- };
245
- };
246
-
247
- method.Method(
248
- argReader,
249
- argWriter,
250
- makeCallback(resolveFunction),
251
- (method.ReturnType == MethodReturnType::Callback ? nullptr : makeCallback(rejectFunction)));
252
- return facebook::jsi::Value::undefined();
253
- }
254
- default:
255
- VerifyElseCrash(false);
256
- }
257
- });
248
+ });
249
+ default:
250
+ VerifyElseCrash(false);
251
+ }
258
252
  }
259
253
  }
260
254
 
261
255
  {
262
256
  // try to find a SyncMethod
263
- auto it = tmb->m_syncMethods.find(key);
264
- if (it != tmb->m_syncMethods.end()) {
257
+ auto it = moduleBuilder->m_syncMethods.find(key);
258
+ if (it != moduleBuilder->m_syncMethods.end()) {
265
259
  return facebook::jsi::Function::createFromHostFunction(
266
260
  runtime,
267
261
  propName,
268
262
  0,
269
- [&runtime, method = it->second](
263
+ [method = it->second](
270
264
  facebook::jsi::Runtime &rt,
271
265
  const facebook::jsi::Value &thisVal,
272
266
  const facebook::jsi::Value *args,
273
267
  size_t count) {
274
- // prepare input arguments
275
- auto argReader = winrt::make<JsiReader>(runtime, args, count);
276
-
277
- // prepare output value
278
- auto writer = winrt::make<JsiWriter>(runtime);
279
-
280
- // call the function
281
- method(argReader, writer);
282
-
283
- return writer.as<JsiWriter>()->MoveResult();
268
+ auto argReader = winrt::make<JsiReader>(rt, args, count);
269
+ auto argWriter = winrt::make<JsiWriter>(rt);
270
+ method(argReader, argWriter);
271
+ return argWriter.as<JsiWriter>()->MoveResult();
284
272
  });
285
273
  }
286
274
  }
@@ -299,17 +287,30 @@ class TurboModuleImpl : public facebook::react::TurboModule {
299
287
  }
300
288
 
301
289
  private:
290
+ static MethodResultCallback MakeCallback(facebook::jsi::Runtime &runtime, facebook::jsi::Value callback) noexcept {
291
+ auto sharedCallback =
292
+ std::make_shared<facebook::jsi::Function>(std::move(callback).asObject(runtime).asFunction(runtime));
293
+ return [sharedCallback = std::move(sharedCallback)](const IJSValueWriter &writer) noexcept {
294
+ writer.as<JSDispatcherWriter>()->WithResultArgs(
295
+ [sharedCallback](facebook::jsi::Runtime &rt, facebook::jsi::Value const *args, size_t count) {
296
+ sharedCallback->call(rt, args, count);
297
+ });
298
+ };
299
+ }
300
+
301
+ private:
302
+ IReactContext m_reactContext;
302
303
  IReactModuleBuilder m_moduleBuilder;
303
- IInspectable providedModule;
304
+ IInspectable m_providedModule;
304
305
  std::shared_ptr<implementation::HostObjectWrapper> m_hostObjectWrapper;
305
306
  };
306
307
 
307
308
  /*-------------------------------------------------------------------------------
308
309
  TurboModulesProvider
309
310
  -------------------------------------------------------------------------------*/
310
- TurboModulesProvider::TurboModulePtr TurboModulesProvider::getModule(
311
+ std::shared_ptr<facebook::react::TurboModule> TurboModulesProvider::getModule(
311
312
  const std::string &moduleName,
312
- const CallInvokerPtr &callInvoker) noexcept {
313
+ const std::shared_ptr<facebook::react::CallInvoker> &callInvoker) noexcept {
313
314
  // fail if the expected turbo module has not been registered
314
315
  auto it = m_moduleProviders.find(moduleName);
315
316
  if (it == m_moduleProviders.end()) {
@@ -13,16 +13,11 @@
13
13
  namespace winrt::Microsoft::ReactNative {
14
14
 
15
15
  class TurboModulesProvider final : public facebook::react::TurboModuleRegistry {
16
- private:
17
- using TurboModule = facebook::react::TurboModule;
18
- using CallInvoker = facebook::react::CallInvoker;
19
-
20
- using TurboModulePtr = std::shared_ptr<TurboModule>;
21
- using CallInvokerPtr = std::shared_ptr<CallInvoker>;
22
-
23
- public:
24
- virtual TurboModulePtr getModule(const std::string &moduleName, const CallInvokerPtr &callInvoker) noexcept override;
25
- virtual std::vector<std::string> getEagerInitModuleNames() noexcept override;
16
+ public: // TurboModuleRegistry implementation
17
+ std::shared_ptr<facebook::react::TurboModule> getModule(
18
+ const std::string &moduleName,
19
+ const std::shared_ptr<facebook::react::CallInvoker> &callInvoker) noexcept override;
20
+ std::vector<std::string> getEagerInitModuleNames() noexcept override;
26
21
 
27
22
  public:
28
23
  void SetReactContext(const IReactContext &reactContext) noexcept;
@@ -167,7 +167,7 @@ bool ImageViewManager::UpdateProperty(
167
167
  }
168
168
 
169
169
  void ImageViewManager::EmitImageEvent(winrt::Grid grid, const char *eventName, ReactImageSource &source) {
170
- int64_t tag = grid.Tag().as<winrt::IPropertyValue>().GetInt64();
170
+ int64_t tag = GetTag(grid);
171
171
  folly::dynamic imageSource =
172
172
  folly::dynamic::object()("uri", source.uri)("width", source.width)("height", source.height);
173
173
 
@@ -3,9 +3,7 @@
3
3
 
4
4
  #include "pch.h"
5
5
 
6
- #include <DynamicReader.h>
7
6
  #include <JSValueWriter.h>
8
- #include <JsiWriter.h>
9
7
  #include <Views/SIPEventHandler.h>
10
8
  #include <Views/ShadowNodeBase.h>
11
9
  #include "Impl/ScrollViewUWPImplementation.h"
@@ -46,7 +46,7 @@ TouchEventHandler::~TouchEventHandler() {
46
46
  }
47
47
 
48
48
  void TouchEventHandler::AddTouchHandlers(XamlView xamlView, XamlView rootView, bool handledEventsToo) {
49
- auto uiElement(xamlView.as<xaml::UIElement>());
49
+ auto uiElement(xamlView.try_as<xaml::UIElement>());
50
50
  if (uiElement == nullptr) {
51
51
  assert(false);
52
52
  return;
@@ -329,7 +329,7 @@ void TouchEventHandler::UpdatePointersInViews(
329
329
  } else {
330
330
  // newViews is empty when UpdatePointersInViews is called from outside
331
331
  // the root view, in this case use -1 for the JS event pointer target
332
- const auto tag = !newViews.empty() ? newViews.front() : -1;
332
+ const auto tag = !newViews.empty() ? newViews.front() : InvalidTag;
333
333
  pointer = CreateReactPointer(args, tag, sourceElement);
334
334
  }
335
335
 
@@ -409,9 +409,9 @@ facebook::react::SharedEventEmitter EventEmitterForElement(
409
409
  auto element = view->Element();
410
410
  while (auto parent = element.Parent()) {
411
411
  if (element = parent.try_as<xaml::FrameworkElement>()) {
412
- auto boxedTag = element.Tag();
413
- if (boxedTag) {
414
- if (tag = winrt::unbox_value<facebook::react::Tag>(element.Tag()))
412
+ auto elementTag = GetTag(element);
413
+ if (elementTag != InvalidTag) {
414
+ if ((tag = static_cast<facebook::react::Tag>(elementTag)) != InvalidTag)
415
415
  return EventEmitterForElement(uimanager, tag);
416
416
  }
417
417
  }
@@ -806,7 +806,7 @@ std::vector<int64_t> GetTagsForBranch(INativeUIManagerHost *host, int64_t tag, i
806
806
  std::vector<int64_t> tags;
807
807
 
808
808
  auto *shadowNode = host->FindShadowNodeForTag(tag);
809
- while (shadowNode != nullptr && tag != -1) {
809
+ while (shadowNode != nullptr && tag != InvalidTag) {
810
810
  if (tag == rootTag) {
811
811
  break;
812
812
  }
@@ -37,7 +37,7 @@ void XamlUIService::DispatchEvent(
37
37
  JSValueArgWriter const &eventDataArgWriter) noexcept {
38
38
  auto paramsWriter = winrt::make_self<DynamicWriter>();
39
39
  paramsWriter->WriteArrayBegin();
40
- paramsWriter->WriteInt64(unbox_value<int64_t>(view.Tag()));
40
+ paramsWriter->WriteInt64(::Microsoft::ReactNative::GetTag(view));
41
41
  paramsWriter->WriteString(eventName);
42
42
  if (eventDataArgWriter) {
43
43
  eventDataArgWriter(*paramsWriter);
@@ -8,14 +8,19 @@
8
8
  namespace Microsoft::ReactNative {
9
9
 
10
10
  using XamlView = xaml::DependencyObject;
11
+ constexpr int64_t InvalidTag = -1;
11
12
 
12
13
  inline int64_t GetTag(XamlView view) {
13
14
  auto tagValue = view.ReadLocalValue(xaml::FrameworkElement::TagProperty());
14
15
  if (tagValue != xaml::DependencyProperty::UnsetValue()) {
15
- return tagValue.as<winrt::IPropertyValue>().GetInt64();
16
- } else {
17
- return -1;
16
+ if (auto tagValueInt = tagValue.try_as<winrt::IPropertyValue>()) {
17
+ if (tagValueInt.Type() == winrt::PropertyType::Int64) {
18
+ return tagValueInt.GetInt64();
19
+ }
20
+ }
18
21
  }
22
+
23
+ return InvalidTag;
19
24
  }
20
25
 
21
26
  inline void SetTag(XamlView view, int64_t tag) {
@@ -10,7 +10,7 @@
10
10
  -->
11
11
  <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
12
12
  <PropertyGroup>
13
- <ReactNativeWindowsVersion>0.0.0-canary.460</ReactNativeWindowsVersion>
13
+ <ReactNativeWindowsVersion>0.0.0-canary.461</ReactNativeWindowsVersion>
14
14
  <ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
15
15
  <ReactNativeWindowsMinor>0</ReactNativeWindowsMinor>
16
16
  <ReactNativeWindowsPatch>0</ReactNativeWindowsPatch>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-windows",
3
- "version": "0.0.0-canary.460",
3
+ "version": "0.0.0-canary.461",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",