react-native-windows 0.80.1 → 0.80.6

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.
Files changed (74) hide show
  1. package/Directory.Build.props +1 -1
  2. package/Microsoft.ReactNative/Fabric/Composition/DebuggerUIIsland.cpp +169 -0
  3. package/Microsoft.ReactNative/Fabric/Composition/DebuggerUIIsland.h +42 -0
  4. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +1 -1
  5. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +60 -33
  6. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +68 -1
  7. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +9 -0
  8. package/Microsoft.ReactNative/Fabric/Composition/UriImageManager.cpp +5 -3
  9. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +6 -1
  10. package/Microsoft.ReactNative/Fabric/WindowsImageManager.cpp +14 -1
  11. package/Microsoft.ReactNative/Fabric/platform/react/threading/TaskDispatchThread.cpp +75 -24
  12. package/Microsoft.ReactNative/Fabric/platform/react/threading/TaskDispatchThread.h +4 -25
  13. package/Microsoft.ReactNative/JsiApi.cpp +1 -1
  14. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +1 -0
  15. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +3 -0
  16. package/Microsoft.ReactNative/ReactHost/DebuggerNotifications.h +54 -0
  17. package/Microsoft.ReactNative/ReactHost/React.h +11 -4
  18. package/Microsoft.ReactNative/ReactHost/ReactHost.cpp +195 -29
  19. package/Microsoft.ReactNative/ReactHost/ReactHost.h +22 -4
  20. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +24 -5
  21. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +1 -1
  22. package/Microsoft.ReactNative/ReactRootView.cpp +108 -0
  23. package/Microsoft.ReactNative/ReactRootView.h +6 -0
  24. package/Microsoft.ReactNative/Views/DevMenu.cpp +1 -1
  25. package/Microsoft.ReactNative.Cxx/JSI/decorator.h +41 -0
  26. package/Microsoft.ReactNative.Cxx/JSI/jsi-inl.h +16 -0
  27. package/Microsoft.ReactNative.Cxx/JSI/jsi.cpp +125 -0
  28. package/Microsoft.ReactNative.Cxx/JSI/jsi.h +167 -1
  29. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +1 -1
  30. package/Microsoft.ReactNative.Cxx/NodeApiJsiRuntime.cpp +110 -38
  31. package/Microsoft.ReactNative.Cxx/node-api/js_native_api.h +44 -31
  32. package/Microsoft.ReactNative.Cxx/node-api/js_native_api_types.h +13 -14
  33. package/Microsoft.ReactNative.Cxx/node-api/js_runtime_api.h +19 -4
  34. package/Microsoft.ReactNative.Cxx/node-api/node_api.h +270 -0
  35. package/Microsoft.ReactNative.Cxx/node-api/node_api_types.h +52 -0
  36. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  37. package/PropertySheets/JSEngine.props +1 -1
  38. package/PropertySheets/React.Cpp.props +2 -2
  39. package/ReactCommon/ReactCommon.vcxproj +18 -1
  40. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/NativeToJsBridge.cpp +1 -1
  41. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/jsi/test/testlib.cpp +4 -4
  42. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsinspector-modern/NetworkIOAgent.cpp +23 -9
  43. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsinspector-modern/NetworkIOAgent.h +16 -0
  44. package/ReactCommon/cgmanifest.json +1 -1
  45. package/Scripts/Tfs/Layout-MSRN-Headers.ps1 +2 -0
  46. package/Shared/DevServerHelper.h +13 -3
  47. package/Shared/DevSettings.h +7 -0
  48. package/Shared/DevSupportManager.cpp +79 -20
  49. package/Shared/DevSupportManager.h +7 -19
  50. package/Shared/Hermes/HermesRuntimeAgentDelegate.cpp +99 -0
  51. package/Shared/Hermes/HermesRuntimeAgentDelegate.h +81 -0
  52. package/Shared/Hermes/HermesRuntimeTargetDelegate.cpp +263 -0
  53. package/Shared/Hermes/HermesRuntimeTargetDelegate.h +77 -0
  54. package/Shared/HermesRuntimeHolder.cpp +29 -111
  55. package/Shared/HermesRuntimeHolder.h +214 -32
  56. package/Shared/IDevSupportManager.h +5 -2
  57. package/Shared/Inspector/ReactInspectorPackagerConnectionDelegate.cpp +108 -0
  58. package/Shared/Inspector/ReactInspectorPackagerConnectionDelegate.h +19 -0
  59. package/Shared/Inspector/ReactInspectorThread.h +18 -0
  60. package/Shared/JSI/RuntimeHolder.h +5 -2
  61. package/Shared/OInstance.cpp +44 -27
  62. package/Shared/Shared.vcxitems +27 -17
  63. package/Shared/Shared.vcxitems.filters +33 -15
  64. package/package.json +5 -5
  65. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.cpp +0 -78
  66. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.h +0 -196
  67. package/ReactCommon/TEMP_UntilReactCommonUpdate/jserrorhandler/JsErrorHandler.cpp +0 -429
  68. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsitooling/react/runtime/JSRuntimeFactory.cpp +0 -45
  69. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsitooling/react/runtime/JSRuntimeFactory.h +0 -91
  70. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp +0 -670
  71. package/Shared/InspectorPackagerConnection.cpp +0 -232
  72. package/Shared/InspectorPackagerConnection.h +0 -61
  73. /package/Shared/{HermesSamplingProfiler.cpp → Hermes/HermesSamplingProfiler.cpp} +0 -0
  74. /package/Shared/{HermesSamplingProfiler.h → Hermes/HermesSamplingProfiler.h} +0 -0
@@ -28,7 +28,7 @@
28
28
 
29
29
  #ifndef JSI_VERSION
30
30
  // Use the latest version by default
31
- #define JSI_VERSION 19
31
+ #define JSI_VERSION 20
32
32
  #endif
33
33
 
34
34
  #if JSI_VERSION >= 3
@@ -65,6 +65,109 @@ class FBJSRuntime;
65
65
  namespace facebook {
66
66
  namespace jsi {
67
67
 
68
+ #if JSI_VERSION >= 20
69
+ /// UUID version 1 implementation. This should be constructed with constant
70
+ /// arguments to identify fixed UUIDs.
71
+ class JSI_EXPORT UUID {
72
+ public:
73
+ // Construct from raw parts
74
+ constexpr UUID(
75
+ uint32_t timeLow,
76
+ uint16_t timeMid,
77
+ uint16_t timeHighAndVersion,
78
+ uint16_t variantAndClockSeq,
79
+ uint64_t node)
80
+ : high(
81
+ ((uint64_t)(timeLow) << 32) | ((uint64_t)(timeMid) << 16) |
82
+ ((uint64_t)(timeHighAndVersion))),
83
+ low(((uint64_t)(variantAndClockSeq) << 48) | node) {}
84
+
85
+ // Default constructor (zero UUID)
86
+ constexpr UUID() : high(0), low(0) {}
87
+
88
+ constexpr UUID(const UUID&) = default;
89
+ constexpr UUID& operator=(const UUID&) = default;
90
+
91
+ constexpr bool operator==(const UUID& other) const {
92
+ return high == other.high && low == other.low;
93
+ }
94
+ constexpr bool operator!=(const UUID& other) const {
95
+ return !(*this == other);
96
+ }
97
+
98
+ // Ordering (for std::map, sorting, etc.)
99
+ constexpr bool operator<(const UUID& other) const {
100
+ return (high < other.high) || (high == other.high && low < other.low);
101
+ }
102
+
103
+ // Hash support for UUID (for unordered_map compatibility)
104
+ struct Hash {
105
+ std::size_t operator()(const UUID& uuid) const noexcept {
106
+ return std::hash<uint64_t>{}(uuid.high) ^
107
+ (std::hash<uint64_t>{}(uuid.low) << 1);
108
+ }
109
+ };
110
+
111
+ // UUID format: 8-4-4-4-12
112
+ std::string toString() const {
113
+ std::string buffer(36, ' ');
114
+ std::snprintf(
115
+ buffer.data(),
116
+ buffer.size() + 1,
117
+ "%08x-%04x-%04x-%04x-%012llx",
118
+ getTimeLow(),
119
+ getTimeMid(),
120
+ getTimeHighAndVersion(),
121
+ getVariantAndClockSeq(),
122
+ (unsigned long long)getNode());
123
+ return buffer;
124
+ }
125
+
126
+ constexpr uint32_t getTimeLow() const {
127
+ return (uint32_t)(high >> 32);
128
+ }
129
+
130
+ constexpr uint16_t getTimeMid() const {
131
+ return (uint16_t)(high >> 16);
132
+ }
133
+
134
+ constexpr uint16_t getTimeHighAndVersion() const {
135
+ return (uint16_t)high;
136
+ }
137
+
138
+ constexpr uint16_t getVariantAndClockSeq() const {
139
+ return (uint16_t)(low >> 48);
140
+ }
141
+
142
+ constexpr uint64_t getNode() const {
143
+ return low & 0xFFFFFFFFFFFF;
144
+ }
145
+
146
+ private:
147
+ uint64_t high;
148
+ uint64_t low;
149
+ };
150
+
151
+ /// Base interface that all JSI interfaces inherit from. Users should not try to
152
+ /// manipulate this base type directly, and should use castInterface to get the
153
+ /// appropriate subtype.
154
+ struct JSI_EXPORT ICast {
155
+ /// If the current object can be cast into the interface specified by \p
156
+ /// interfaceUUID, return a pointer to the object. Otherwise, return a null
157
+ /// pointer.
158
+ /// The returned interface has the same lifetime as the underlying object. It
159
+ /// does not need to be released when not needed.
160
+ virtual ICast* castInterface(const UUID& interfaceUUID) = 0;
161
+
162
+ protected:
163
+ /// Interfaces are not destructible, thus the destructor is intentionally
164
+ /// protected to prevent delete calls on the interface.
165
+ /// Additionally, the destructor is non-virtual to reduce the vtable
166
+ /// complexity from inheritance.
167
+ ~ICast() = default;
168
+ };
169
+ #endif
170
+
68
171
  /// Base class for buffers of data or bytecode that need to be passed to the
69
172
  /// runtime. The buffer is expected to be fully immutable, so the result of
70
173
  /// size(), data(), and the contents of the pointer returned by data() must not
@@ -209,10 +312,18 @@ class JSI_EXPORT NativeState {
209
312
  /// in a non-Runtime-managed object, and not clean it up before the Runtime
210
313
  /// is shut down. If your lifecycle is such that avoiding this is hard,
211
314
  /// you will probably need to do use your own locks.
315
+ #if JSI_VERSION >= 20
316
+ class JSI_EXPORT Runtime : public ICast {
317
+ #else
212
318
  class JSI_EXPORT Runtime {
319
+ #endif
213
320
  public:
214
321
  virtual ~Runtime();
215
322
 
323
+ #if JSI_VERSION >= 20
324
+ ICast* castInterface(const UUID& interfaceUUID) override;
325
+ #endif
326
+
216
327
  /// Evaluates the given JavaScript \c buffer. \c sourceURL is used
217
328
  /// to annotate the stack trace if there is an exception. The
218
329
  /// contents may be utf8-encoded JS source code, or binary bytecode
@@ -310,6 +421,18 @@ class JSI_EXPORT Runtime {
310
421
  /// implementation of this function returns an \c Instrumentation instance
311
422
  /// which returns no metrics.
312
423
  virtual Instrumentation& instrumentation();
424
+
425
+ #if JSI_VERSION >= 20
426
+ /// Stores the pointer \p data with the \p uuid in the runtime. This can be
427
+ /// used to store some custom data within the runtime. When the runtime is
428
+ /// destroyed, or if an entry at an existing key is overwritten, the runtime
429
+ /// will release its ownership of the held object.
430
+ void setRuntimeData(const UUID& uuid, const std::shared_ptr<void>& data);
431
+
432
+ /// Returns the data associated with the \p uuid in the runtime. If there's no
433
+ /// data associated with the uuid, return a null pointer.
434
+ std::shared_ptr<void> getRuntimeData(const UUID& uuid);
435
+ #endif
313
436
 
314
437
  protected:
315
438
  friend class Pointer;
@@ -327,6 +450,21 @@ class JSI_EXPORT Runtime {
327
450
  friend class Value;
328
451
  friend class Scope;
329
452
  friend class JSError;
453
+
454
+ #if JSI_VERSION >= 20
455
+ /// Stores the pointer \p data with the \p uuid in the runtime. This can be
456
+ /// used to store some custom data within the runtime. When the runtime is
457
+ /// destroyed, or if an entry at an existing key is overwritten, the runtime
458
+ /// will release its ownership by calling \p deleter.
459
+ virtual void setRuntimeDataImpl(
460
+ const UUID& uuid,
461
+ const void* data,
462
+ void (*deleter)(const void* data));
463
+
464
+ /// Returns the data associated with the \p uuid in the runtime. If there's no
465
+ /// data associated with the uuid, return a null pointer.
466
+ virtual const void* getRuntimeDataImpl(const UUID& uuid);
467
+ #endif
330
468
 
331
469
  // Potential optimization: avoid the cloneFoo() virtual dispatch,
332
470
  // and instead just fix the number of fields, and copy them, since
@@ -1793,6 +1931,34 @@ class JSI_EXPORT JSError : public JSIException {
1793
1931
  std::string stack_;
1794
1932
  };
1795
1933
 
1934
+ /// Helper function to cast the object pointed to by \p ptr into an interface
1935
+ /// specified by \c U. If cast is successful, return a pointer to the object
1936
+ /// as a raw pointer of \c U. Otherwise, return nullptr.
1937
+ /// The returned interface same lifetime as the object referenced by \p ptr.
1938
+ #if JSI_VERSION >= 20
1939
+ template <typename U, typename T>
1940
+ U* castInterface(T* ptr) {
1941
+ if (ptr) {
1942
+ return static_cast<U*>(ptr->castInterface(U::uuid));
1943
+ }
1944
+ return nullptr;
1945
+ };
1946
+
1947
+ /// Helper function to cast the object managed by the shared_ptr \p ptr into an
1948
+ /// interface specified by \c U. If the cast is successful, return a shared_ptr
1949
+ /// of type \c U to the object. Otherwise, return an empty pointer.
1950
+ /// The returned shared_ptr shares ownership of the object with \p ptr.
1951
+ template <typename U, typename T>
1952
+ std::shared_ptr<U> dynamicInterfaceCast(T&& ptr) {
1953
+ auto* p = ptr->castInterface(U::uuid);
1954
+ U* res = static_cast<U*>(p);
1955
+ if (res) {
1956
+ return std::shared_ptr<U>(std::forward<T>(ptr), res);
1957
+ }
1958
+ return nullptr;
1959
+ }
1960
+ #endif
1961
+
1796
1962
  } // namespace jsi
1797
1963
  } // namespace facebook
1798
1964
 
@@ -14,7 +14,7 @@
14
14
  <!-- If your project is using glog, then GLog_IncludeDir could be set to include the actual location of glog -->
15
15
  <GLog_IncludeDir Condition="'$(GLog_IncludeDir)' == '' AND Exists('$(MSBuildThisFileDirectory)stubs\glog\logging.h')">$(MSBuildThisFileDirectory)stubs</GLog_IncludeDir>
16
16
 
17
- <NodeApiJsiCommitHash>980cb60d7911237d0f647fc566543ef627adac70</NodeApiJsiCommitHash>
17
+ <NodeApiJsiCommitHash>21b47f08b762b21b1d4d970940ab23f59f43249c</NodeApiJsiCommitHash>
18
18
  <NodeApiJsiLocal Condition="Exists('$(MSBuildThisFileDirectory)NodeApiJsiRuntime.cpp')">true</NodeApiJsiLocal>
19
19
  <NodeApiJsiDir Condition="'$(NodeApiJsiDir)' == '' AND '$(NodeApiJsiLocal)' == 'true'">$(MSBuildThisFileDirectory)</NodeApiJsiDir>
20
20
  <NodeApiJsiDir Condition="'$(NodeApiJsiDir)' == '' AND '$(ReactNativeDir)' != ''">$(ReactNativeDir)\..\..\node_modules\.node-api-jsi\node-api-jsi-$(NodeApiJsiCommitHash)\</NodeApiJsiDir>
@@ -44,12 +44,21 @@ using namespace std::string_view_literals;
44
44
  // We use macros to report errors.
45
45
  // Macros provide more flexibility to show assert and provide failure context.
46
46
 
47
+ #if defined(__clang__) || defined(__GNUC__)
48
+ #define CRASH_NOW() __builtin_trap()
49
+ #elif defined(_MSC_VER)
50
+ #include <intrin.h>
51
+ #define CRASH_NOW() __fastfail(/*FAST_FAIL_FATAL_APP_EXIT*/ 7)
52
+ #else
53
+ #define CRASH_NOW() *((volatile int *)0) = 1
54
+ #endif
55
+
47
56
  // Check condition and crash process if it fails.
48
57
  #define CHECK_ELSE_CRASH(condition, message) \
49
58
  do { \
50
59
  if (!(condition)) { \
51
60
  assert(false && "Failed: " #condition && (message)); \
52
- *((int *)0) = 1; \
61
+ CRASH_NOW(); \
53
62
  } \
54
63
  } while (false)
55
64
 
@@ -286,7 +295,7 @@ class NodeApiJsiRuntime : public jsi::Runtime {
286
295
  jsi::Array createArray(size_t length) override;
287
296
  #if JSI_VERSION >= 9
288
297
  jsi::ArrayBuffer createArrayBuffer(
289
- std::shared_ptr<jsi::MutableBuffer> buffer);
298
+ std::shared_ptr<jsi::MutableBuffer> buffer) override;
290
299
  #endif
291
300
  size_t size(const jsi::Array &arr) override;
292
301
  size_t size(const jsi::ArrayBuffer &arrBuf) override;
@@ -1628,8 +1637,8 @@ jsi::Object NodeApiJsiRuntime::createObject(
1628
1637
  // access to the hostObject's get, set, and getPropertyNames methods. There is
1629
1638
  // a special symbol property ID, 'hostObjectSymbol', used to access the
1630
1639
  // hostObjectWrapper from the Proxy.
1631
- napi_value hostObjectHolder =
1632
- createExternalObject(std::make_unique<std::shared_ptr<jsi::HostObject>>(
1640
+ napi_value hostObjectHolder = createExternalObject(
1641
+ std::make_unique<std::shared_ptr<jsi::HostObject>>(
1633
1642
  std::move(hostObject)));
1634
1643
  napi_value obj = createNodeApiObject();
1635
1644
  setProperty(
@@ -2420,31 +2429,89 @@ jsi::JSError NodeApiJsiRuntime::makeJSError(Args &&...args) {
2420
2429
  return jsi::JSError(*this, errorStream.str());
2421
2430
  }
2422
2431
 
2423
- // Throws jsi::JSError or jsi::JSINativeException from Node-API error.
2424
2432
  [[noreturn]] void NodeApiJsiRuntime::throwJSException(
2425
2433
  napi_status status) const {
2434
+ auto formatStatusError = [](napi_status status) -> std::string {
2435
+ // TODO: (vmoroz) use a more sophisticated error formatting.
2436
+ std::ostringstream errorStream;
2437
+ errorStream << "A call to Node-API returned error code 0x" << std::hex
2438
+ << static_cast<int>(status) << '.';
2439
+ return errorStream.str();
2440
+ };
2441
+
2442
+ NodeApiScope scope{*this};
2443
+ // Retrieve the exception value and clear as we will rethrow it as a C++
2444
+ // exception.
2426
2445
  napi_value jsError{};
2427
2446
  CHECK_NAPI_ELSE_CRASH(
2428
2447
  jsrApi_->napi_get_and_clear_last_exception(env_, &jsError));
2429
2448
  napi_valuetype jsErrorType;
2430
2449
  CHECK_NAPI_ELSE_CRASH(jsrApi_->napi_typeof(env_, jsError, &jsErrorType));
2450
+ if (jsErrorType == napi_undefined) {
2451
+ throw jsi::JSINativeException(formatStatusError(status).c_str());
2452
+ }
2453
+ jsi::Value jsiJSError = toJsiValue(jsError);
2454
+
2455
+ std::string msg = "No message";
2456
+ std::string stack = "No stack";
2457
+ if (jsErrorType == napi_string) {
2458
+ // If the exception is a string, use it as the message.
2459
+ msg = stringToStdString(jsError);
2460
+ } else if (jsErrorType == napi_object) {
2461
+ // If the exception is an object try to retrieve its message and stack
2462
+ // properties.
2463
+
2464
+ /// Attempt to retrieve a string property \p sym from \c jsError and store
2465
+ /// it in \p out. Ignore any catchable errors and non-string properties.
2466
+ auto getStrProp = [this, jsError](const char *sym, std::string &out) {
2467
+ napi_value value{};
2468
+ napi_status propStatus =
2469
+ jsrApi_->napi_get_named_property(env_, jsError, sym, &value);
2470
+ if (propStatus != napi_ok) {
2471
+ // An exception was thrown while retrieving the property, if it is
2472
+ // catchable, suppress it. Otherwise, rethrow this exception without
2473
+ // trying to invoke any more JavaScript.
2474
+ napi_value newJSError{};
2475
+ CHECK_NAPI_ELSE_CRASH(
2476
+ jsrApi_->napi_get_and_clear_last_exception(env_, &newJSError));
2477
+ napi_valuetype newJSErrorType;
2478
+ CHECK_NAPI_ELSE_CRASH(
2479
+ jsrApi_->napi_typeof(env_, newJSError, &newJSErrorType));
2480
+
2481
+ if (propStatus != napi_cannot_run_js)
2482
+ return;
2431
2483
 
2432
- if (!hasPendingJSError_ &&
2433
- (status == napi_pending_exception || jsErrorType != napi_undefined)) {
2434
- AutoRestore<bool> setValue(
2435
- const_cast<NodeApiJsiRuntime *>(this)->hasPendingJSError_, true);
2436
- if (jsErrorType == napi_object &&
2437
- instanceOf(jsError, getNodeApiValue(cachedValue_.Error))) {
2438
- rewriteErrorMessage(jsError);
2439
- }
2440
- throw jsi::JSError(
2441
- *const_cast<NodeApiJsiRuntime *>(this), toJsiValue(jsError));
2442
- } else {
2443
- std::ostringstream errorStream;
2444
- errorStream << "A call to Node-API returned error code 0x" << std::hex
2445
- << status << '.';
2446
- throw jsi::JSINativeException(errorStream.str().c_str());
2484
+ // An uncatchable error occurred, it is unsafe to do anything that
2485
+ // might execute more JavaScript.
2486
+ if (newJSErrorType != napi_undefined) {
2487
+ throw jsi::JSError(
2488
+ toJsiValue(newJSError),
2489
+ "Uncatchable exception thrown while creating error",
2490
+ "No stack");
2491
+ } else {
2492
+ std::ostringstream errorStream;
2493
+ errorStream << "A call to Node-API returned error code 0x" << std::hex
2494
+ << propStatus << '.';
2495
+ throw jsi::JSINativeException(errorStream.str().c_str());
2496
+ }
2497
+ }
2498
+
2499
+ // If the property is a string, update out. Otherwise ignore it.
2500
+ napi_valuetype valueType;
2501
+ CHECK_NAPI_ELSE_CRASH(jsrApi_->napi_typeof(env_, value, &valueType));
2502
+ if (valueType == napi_string) {
2503
+ out = stringToStdString(value);
2504
+ }
2505
+ };
2506
+
2507
+ getStrProp("message", msg);
2508
+ getStrProp("stack", stack);
2447
2509
  }
2510
+
2511
+ // Use the constructor of jsi::JSError that cannot run additional
2512
+ // JS, since that may then result in additional exceptions and infinite
2513
+ // recursion.
2514
+ throw jsi::JSError(std::move(jsiJSError), msg, stack);
2448
2515
  }
2449
2516
 
2450
2517
  // Throws jsi::JSINativeException with a message.
@@ -2467,7 +2534,9 @@ void NodeApiJsiRuntime::rewriteErrorMessage(napi_value jsError) const {
2467
2534
  jsrApi_->napi_get_and_clear_last_exception(env_, &ignoreJSError);
2468
2535
  } else if (typeOf(message) == napi_string) {
2469
2536
  // JSI unit tests expect V8- or JSC-like messages for the stack overflow.
2470
- if (stringToStdString(message) == "Out of stack space") {
2537
+ std::string messageStr = stringToStdString(message);
2538
+ if (messageStr == "Out of stack space" ||
2539
+ messageStr.find("Maximum call stack") != std::string::npos) {
2471
2540
  setProperty(
2472
2541
  jsError,
2473
2542
  getNodeApiValue(propertyId_.message),
@@ -2594,7 +2663,7 @@ napi_value NodeApiJsiRuntime::getBoolean(bool value) const {
2594
2663
 
2595
2664
  // Gets value of the Boolean napi_value.
2596
2665
  bool NodeApiJsiRuntime::getValueBool(napi_value value) const {
2597
- bool result{nullptr};
2666
+ bool result{false};
2598
2667
  CHECK_NAPI(jsrApi_->napi_get_value_bool(env_, value, &result));
2599
2668
  return result;
2600
2669
  }
@@ -2848,13 +2917,14 @@ void NodeApiJsiRuntime::setElement(
2848
2917
  napi_callback_info info) noexcept {
2849
2918
  HostFunctionWrapper *hostFuncWrapper{};
2850
2919
  size_t argc{};
2851
- CHECK_NAPI_ELSE_CRASH(JSRuntimeApi::current()->napi_get_cb_info(
2852
- env,
2853
- info,
2854
- &argc,
2855
- nullptr,
2856
- nullptr,
2857
- reinterpret_cast<void **>(&hostFuncWrapper)));
2920
+ CHECK_NAPI_ELSE_CRASH(
2921
+ JSRuntimeApi::current()->napi_get_cb_info(
2922
+ env,
2923
+ info,
2924
+ &argc,
2925
+ nullptr,
2926
+ nullptr,
2927
+ reinterpret_cast<void **>(&hostFuncWrapper)));
2858
2928
  CHECK_ELSE_CRASH(hostFuncWrapper, "Cannot find the host function");
2859
2929
  NodeApiJsiRuntime &runtime = hostFuncWrapper->runtime();
2860
2930
  NodeApiPointerValueScope scope{runtime};
@@ -2863,8 +2933,9 @@ void NodeApiJsiRuntime::setElement(
2863
2933
  [&env, &info, &argc, &runtime, &hostFuncWrapper]() {
2864
2934
  SmallBuffer<napi_value, MaxStackArgCount> napiArgs(argc);
2865
2935
  napi_value thisArg{};
2866
- CHECK_NAPI_ELSE_CRASH(JSRuntimeApi::current()->napi_get_cb_info(
2867
- env, info, &argc, napiArgs.data(), &thisArg, nullptr));
2936
+ CHECK_NAPI_ELSE_CRASH(
2937
+ JSRuntimeApi::current()->napi_get_cb_info(
2938
+ env, info, &argc, napiArgs.data(), &thisArg, nullptr));
2868
2939
  CHECK_ELSE_CRASH(napiArgs.size() == argc, "Wrong argument count");
2869
2940
  const JsiValueView jsiThisArg{&runtime, thisArg};
2870
2941
  JsiValueViewArgs jsiArgs(
@@ -2986,13 +3057,14 @@ void NodeApiJsiRuntime::setProxyTrap(
2986
3057
  NodeApiJsiRuntime *runtime{};
2987
3058
  napi_value args[argCount]{};
2988
3059
  size_t actualArgCount{argCount};
2989
- CHECK_NAPI_ELSE_CRASH(JSRuntimeApi::current()->napi_get_cb_info(
2990
- env,
2991
- info,
2992
- &actualArgCount,
2993
- args,
2994
- nullptr,
2995
- reinterpret_cast<void **>(&runtime)));
3060
+ CHECK_NAPI_ELSE_CRASH(
3061
+ JSRuntimeApi::current()->napi_get_cb_info(
3062
+ env,
3063
+ info,
3064
+ &actualArgCount,
3065
+ args,
3066
+ nullptr,
3067
+ reinterpret_cast<void **>(&runtime)));
2996
3068
  CHECK_ELSE_CRASH(
2997
3069
  actualArgCount == argCount, "proxy trap requires argCount arguments.");
2998
3070
  NodeApiPointerValueScope scope{*runtime};
@@ -21,6 +21,18 @@
21
21
  #endif
22
22
  #endif
23
23
 
24
+ #if defined(NAPI_EXPERIMENTAL) && \
25
+ !defined(NODE_API_EXPERIMENTAL_NO_WARNING) && \
26
+ !defined(NODE_WANT_INTERNALS)
27
+ #ifdef _MSC_VER
28
+ #pragma message("NAPI_EXPERIMENTAL is enabled. " \
29
+ "Experimental features may be unstable.")
30
+ #else
31
+ #warning "NAPI_EXPERIMENTAL is enabled. " \
32
+ "Experimental features may be unstable."
33
+ #endif
34
+ #endif
35
+
24
36
  #include "js_native_api_types.h"
25
37
 
26
38
  // If you need __declspec(dllimport), either include <node_api.h> instead, or
@@ -50,7 +62,7 @@
50
62
  EXTERN_C_START
51
63
 
52
64
  NAPI_EXTERN napi_status NAPI_CDECL napi_get_last_error_info(
53
- node_api_nogc_env env, const napi_extended_error_info** result);
65
+ node_api_basic_env env, const napi_extended_error_info** result);
54
66
 
55
67
  // Getters for defined singletons
56
68
  NAPI_EXTERN napi_status NAPI_CDECL napi_get_undefined(napi_env env,
@@ -92,31 +104,31 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_create_string_utf16(napi_env env,
92
104
  const char16_t* str,
93
105
  size_t length,
94
106
  napi_value* result);
95
- #ifdef NAPI_EXPERIMENTAL
96
- #define NODE_API_EXPERIMENTAL_HAS_EXTERNAL_STRINGS
97
- NAPI_EXTERN napi_status NAPI_CDECL
98
- node_api_create_external_string_latin1(napi_env env,
99
- char* str,
100
- size_t length,
101
- node_api_nogc_finalize finalize_callback,
102
- void* finalize_hint,
103
- napi_value* result,
104
- bool* copied);
107
+ #if NAPI_VERSION >= 10
108
+ NAPI_EXTERN napi_status NAPI_CDECL node_api_create_external_string_latin1(
109
+ napi_env env,
110
+ char* str,
111
+ size_t length,
112
+ node_api_basic_finalize finalize_callback,
113
+ void* finalize_hint,
114
+ napi_value* result,
115
+ bool* copied);
105
116
  NAPI_EXTERN napi_status NAPI_CDECL
106
117
  node_api_create_external_string_utf16(napi_env env,
107
118
  char16_t* str,
108
119
  size_t length,
109
- node_api_nogc_finalize finalize_callback,
120
+ node_api_basic_finalize finalize_callback,
110
121
  void* finalize_hint,
111
122
  napi_value* result,
112
123
  bool* copied);
113
- #endif // NAPI_EXPERIMENTAL
114
124
 
115
- #ifdef NAPI_EXPERIMENTAL
116
- #define NODE_API_EXPERIMENTAL_HAS_PROPERTY_KEYS
125
+ NAPI_EXTERN napi_status NAPI_CDECL node_api_create_property_key_latin1(
126
+ napi_env env, const char* str, size_t length, napi_value* result);
127
+ NAPI_EXTERN napi_status NAPI_CDECL node_api_create_property_key_utf8(
128
+ napi_env env, const char* str, size_t length, napi_value* result);
117
129
  NAPI_EXTERN napi_status NAPI_CDECL node_api_create_property_key_utf16(
118
130
  napi_env env, const char16_t* str, size_t length, napi_value* result);
119
- #endif // NAPI_EXPERIMENTAL
131
+ #endif // NAPI_VERSION >= 10
120
132
 
121
133
  NAPI_EXTERN napi_status NAPI_CDECL napi_create_symbol(napi_env env,
122
134
  napi_value description,
@@ -318,12 +330,13 @@ napi_define_class(napi_env env,
318
330
  napi_value* result);
319
331
 
320
332
  // Methods to work with external data objects
321
- NAPI_EXTERN napi_status NAPI_CDECL napi_wrap(napi_env env,
322
- napi_value js_object,
323
- void* native_object,
324
- node_api_nogc_finalize finalize_cb,
325
- void* finalize_hint,
326
- napi_ref* result);
333
+ NAPI_EXTERN napi_status NAPI_CDECL
334
+ napi_wrap(napi_env env,
335
+ napi_value js_object,
336
+ void* native_object,
337
+ node_api_basic_finalize finalize_cb,
338
+ void* finalize_hint,
339
+ napi_ref* result);
327
340
  NAPI_EXTERN napi_status NAPI_CDECL napi_unwrap(napi_env env,
328
341
  napi_value js_object,
329
342
  void** result);
@@ -333,7 +346,7 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_remove_wrap(napi_env env,
333
346
  NAPI_EXTERN napi_status NAPI_CDECL
334
347
  napi_create_external(napi_env env,
335
348
  void* data,
336
- node_api_nogc_finalize finalize_cb,
349
+ node_api_basic_finalize finalize_cb,
337
350
  void* finalize_hint,
338
351
  napi_value* result);
339
352
  NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_external(napi_env env,
@@ -432,7 +445,7 @@ NAPI_EXTERN napi_status NAPI_CDECL
432
445
  napi_create_external_arraybuffer(napi_env env,
433
446
  void* external_data,
434
447
  size_t byte_length,
435
- node_api_nogc_finalize finalize_cb,
448
+ node_api_basic_finalize finalize_cb,
436
449
  void* finalize_hint,
437
450
  napi_value* result);
438
451
  #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
@@ -474,7 +487,7 @@ napi_get_dataview_info(napi_env env,
474
487
  size_t* byte_offset);
475
488
 
476
489
  // version management
477
- NAPI_EXTERN napi_status NAPI_CDECL napi_get_version(node_api_nogc_env env,
490
+ NAPI_EXTERN napi_status NAPI_CDECL napi_get_version(node_api_basic_env env,
478
491
  uint32_t* result);
479
492
 
480
493
  // Promises
@@ -498,7 +511,7 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_run_script(napi_env env,
498
511
 
499
512
  // Memory management
500
513
  NAPI_EXTERN napi_status NAPI_CDECL napi_adjust_external_memory(
501
- node_api_nogc_env env, int64_t change_in_bytes, int64_t* adjusted_value);
514
+ node_api_basic_env env, int64_t change_in_bytes, int64_t* adjusted_value);
502
515
 
503
516
  #if NAPI_VERSION >= 5
504
517
 
@@ -520,7 +533,7 @@ NAPI_EXTERN napi_status NAPI_CDECL
520
533
  napi_add_finalizer(napi_env env,
521
534
  napi_value js_object,
522
535
  void* finalize_data,
523
- node_api_nogc_finalize finalize_cb,
536
+ node_api_basic_finalize finalize_cb,
524
537
  void* finalize_hint,
525
538
  napi_ref* result);
526
539
 
@@ -530,7 +543,7 @@ napi_add_finalizer(napi_env env,
530
543
  #define NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
531
544
 
532
545
  NAPI_EXTERN napi_status NAPI_CDECL
533
- node_api_post_finalizer(node_api_nogc_env env,
546
+ node_api_post_finalizer(node_api_basic_env env,
534
547
  napi_finalize finalize_cb,
535
548
  void* finalize_data,
536
549
  void* finalize_hint);
@@ -575,13 +588,13 @@ napi_get_all_property_names(napi_env env,
575
588
 
576
589
  // Instance data
577
590
  NAPI_EXTERN napi_status NAPI_CDECL
578
- napi_set_instance_data(node_api_nogc_env env,
591
+ napi_set_instance_data(node_api_basic_env env,
579
592
  void* data,
580
593
  napi_finalize finalize_cb,
581
594
  void* finalize_hint);
582
595
 
583
- NAPI_EXTERN napi_status NAPI_CDECL napi_get_instance_data(node_api_nogc_env env,
584
- void** data);
596
+ NAPI_EXTERN napi_status NAPI_CDECL
597
+ napi_get_instance_data(node_api_basic_env env, void** data);
585
598
  #endif // NAPI_VERSION >= 6
586
599
 
587
600
  #if NAPI_VERSION >= 7
@@ -7,11 +7,6 @@
7
7
  #include <stddef.h> // NOLINT(modernize-deprecated-headers)
8
8
  #include <stdint.h> // NOLINT(modernize-deprecated-headers)
9
9
 
10
- // TODO: (vmoroz) NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT is not part of this
11
- // Node-API file. It is here temporary to enable compilation. Remove it after
12
- // updating tests.
13
- #define NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT
14
-
15
10
  #if !defined __cplusplus || (defined(_MSC_VER) && _MSC_VER < 1900)
16
11
  typedef uint16_t char16_t;
17
12
  #endif
@@ -32,7 +27,7 @@ typedef struct napi_env__* napi_env;
32
27
  // meaning that they do not affect the state of the JS engine, and can
33
28
  // therefore be called synchronously from a finalizer that itself runs
34
29
  // synchronously during GC. Such APIs can receive either a `napi_env` or a
35
- // `node_api_nogc_env` as their first parameter, because we should be able to
30
+ // `node_api_basic_env` as their first parameter, because we should be able to
36
31
  // also call them during normal, non-garbage-collecting operations, whereas
37
32
  // APIs that affect the state of the JS engine can only receive a `napi_env` as
38
33
  // their first parameter, because we must not call them during GC. In lieu of
@@ -42,19 +37,21 @@ typedef struct napi_env__* napi_env;
42
37
  // expecting a non-const value.
43
38
  //
44
39
  // In conjunction with appropriate CFLAGS to warn us if we're passing a const
45
- // (nogc) environment into an API that expects a non-const environment, and the
46
- // definition of nogc finalizer function pointer types below, which receive a
47
- // nogc environment as their first parameter, and can thus only call nogc APIs
48
- // (unless the user explicitly casts the environment), we achieve the ability
49
- // to ensure at compile time that we do not call APIs that affect the state of
50
- // the JS engine from a synchronous (nogc) finalizer.
40
+ // (basic) environment into an API that expects a non-const environment, and
41
+ // the definition of basic finalizer function pointer types below, which
42
+ // receive a basic environment as their first parameter, and can thus only call
43
+ // basic APIs (unless the user explicitly casts the environment), we achieve
44
+ // the ability to ensure at compile time that we do not call APIs that affect
45
+ // the state of the JS engine from a synchronous (basic) finalizer.
51
46
  #if !defined(NAPI_EXPERIMENTAL) || \
52
47
  (defined(NAPI_EXPERIMENTAL) && \
53
- defined(NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT))
48
+ (defined(NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT) || \
49
+ defined(NODE_API_EXPERIMENTAL_BASIC_ENV_OPT_OUT)))
54
50
  typedef struct napi_env__* node_api_nogc_env;
55
51
  #else
56
52
  typedef const struct napi_env__* node_api_nogc_env;
57
53
  #endif
54
+ typedef node_api_nogc_env node_api_basic_env;
58
55
 
59
56
  typedef struct napi_value__* napi_value;
60
57
  typedef struct napi_ref__* napi_ref;
@@ -152,13 +149,15 @@ typedef void(NAPI_CDECL* napi_finalize)(napi_env env,
152
149
 
153
150
  #if !defined(NAPI_EXPERIMENTAL) || \
154
151
  (defined(NAPI_EXPERIMENTAL) && \
155
- defined(NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT))
152
+ (defined(NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT) || \
153
+ defined(NODE_API_EXPERIMENTAL_BASIC_ENV_OPT_OUT)))
156
154
  typedef napi_finalize node_api_nogc_finalize;
157
155
  #else
158
156
  typedef void(NAPI_CDECL* node_api_nogc_finalize)(node_api_nogc_env env,
159
157
  void* finalize_data,
160
158
  void* finalize_hint);
161
159
  #endif
160
+ typedef node_api_nogc_finalize node_api_basic_finalize;
162
161
 
163
162
  typedef struct {
164
163
  // One of utf8name or name should be NULL.