react-native-windows 0.68.1 → 0.69.0-preview.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (392) hide show
  1. package/.flowconfig +1 -3
  2. package/Chakra/ChakraHelpers.cpp +0 -1
  3. package/Directory.Build.props +3 -0
  4. package/Directory.Build.targets +1 -1
  5. package/Folly/TEMP_UntilFollyUpdate/dynamic-inl.h +1411 -0
  6. package/Folly/TEMP_UntilFollyUpdate/lang/ToAscii.cpp +336 -0
  7. package/Folly/TEMP_UntilFollyUpdate/lang/ToAscii.h +182 -0
  8. package/Libraries/ActionSheetIOS/ActionSheetIOS.js +7 -0
  9. package/Libraries/ActionSheetIOS/NativeActionSheetManager.js +1 -0
  10. package/Libraries/Alert/Alert.windows.js +2 -2
  11. package/Libraries/Animated/AnimatedImplementation.js +1 -1
  12. package/Libraries/Animated/NativeAnimatedHelper.js +55 -9
  13. package/Libraries/Animated/NativeAnimatedModule.js +1 -0
  14. package/Libraries/Animated/NativeAnimatedTurboModule.js +1 -0
  15. package/Libraries/Animated/animations/TimingAnimation.js +6 -11
  16. package/Libraries/Animated/createAnimatedComponent.js +2 -2
  17. package/Libraries/Animated/nodes/AnimatedColor.js +95 -29
  18. package/Libraries/Animated/nodes/AnimatedInterpolation.js +19 -22
  19. package/Libraries/Animated/nodes/AnimatedNode.js +2 -2
  20. package/Libraries/Animated/nodes/AnimatedValue.js +1 -1
  21. package/Libraries/AppState/AppState.js +1 -1
  22. package/Libraries/Blob/URL.js +7 -1
  23. package/Libraries/Components/Button.js +3 -0
  24. package/Libraries/Components/Button.windows.js +4 -0
  25. package/Libraries/Components/DatePickerAndroid/NativeDatePickerAndroid.js +5 -0
  26. package/Libraries/Components/Pressable/Pressable.js +3 -3
  27. package/Libraries/Components/Pressable/Pressable.windows.js +3 -3
  28. package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +47 -38
  29. package/Libraries/Components/ScrollView/ScrollContentViewNativeComponent.js +15 -7
  30. package/Libraries/Components/ScrollView/ScrollView.js +1 -1
  31. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +16 -3
  32. package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +3 -1
  33. package/Libraries/Components/Slider/Slider.js +0 -2
  34. package/Libraries/Components/Slider/SliderNativeComponent.js +0 -1
  35. package/Libraries/Components/StatusBar/StatusBar.js +6 -1
  36. package/Libraries/Components/Switch/Switch.js +11 -1
  37. package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +114 -109
  38. package/Libraries/Components/TextInput/RCTMultilineTextInputNativeComponent.js +17 -9
  39. package/Libraries/Components/TextInput/RCTSingelineTextInputNativeComponent.js +13 -5
  40. package/Libraries/Components/TextInput/RCTTextInputViewConfig.js +10 -0
  41. package/Libraries/Components/TextInput/TextInput.js +1 -8
  42. package/Libraries/Components/TextInput/TextInput.windows.js +4 -9
  43. package/Libraries/Components/TextInput/TextInputState.js +10 -2
  44. package/Libraries/Components/TextInput/TextInputState.windows.js +10 -3
  45. package/Libraries/Components/TextInput/WindowsTextInputNativeComponent.js +1 -1
  46. package/Libraries/Components/Touchable/TouchableBounce.js +1 -0
  47. package/Libraries/Components/Touchable/TouchableHighlight.js +1 -0
  48. package/Libraries/Components/Touchable/TouchableHighlight.windows.js +6 -5
  49. package/Libraries/Components/Touchable/TouchableNativeFeedback.js +1 -0
  50. package/Libraries/Components/Touchable/TouchableOpacity.js +7 -1
  51. package/Libraries/Components/Touchable/TouchableOpacity.windows.js +11 -5
  52. package/Libraries/Components/Touchable/TouchableWithoutFeedback.js +2 -0
  53. package/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js +2 -0
  54. package/Libraries/Components/View/ReactNativeViewAttributes.js +1 -0
  55. package/Libraries/Components/View/ReactNativeViewAttributes.windows.js +1 -0
  56. package/Libraries/Components/View/View.windows.js +33 -1
  57. package/Libraries/Components/View/ViewNativeComponent.js +68 -8
  58. package/Libraries/Components/View/ViewPropTypes.js +36 -4
  59. package/Libraries/Components/View/ViewPropTypes.windows.js +36 -4
  60. package/Libraries/Core/Devtools/parseHermesStack.js +1 -1
  61. package/Libraries/Core/ExceptionsManager.js +1 -1
  62. package/Libraries/Core/RawEventEmitter.js +38 -0
  63. package/Libraries/Core/ReactNativeVersion.js +2 -2
  64. package/Libraries/Core/polyfillPromise.js +32 -0
  65. package/Libraries/Core/setUpReactDevTools.js +3 -2
  66. package/Libraries/EventEmitter/NativeEventEmitter.js +3 -3
  67. package/Libraries/EventEmitter/RCTDeviceEventEmitter.js +2 -1
  68. package/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js +3 -3
  69. package/Libraries/Events/CustomEvent.js +32 -0
  70. package/Libraries/Events/EventPolyfill.js +239 -0
  71. package/Libraries/Image/Image.android.js +0 -6
  72. package/Libraries/Image/Image.ios.js +0 -6
  73. package/Libraries/Image/Image.windows.js +2 -8
  74. package/Libraries/Image/ImageViewNativeComponent.js +18 -3
  75. package/Libraries/Image/TextInlineImageNativeComponent.js +23 -15
  76. package/Libraries/Inspector/Inspector.js +2 -4
  77. package/Libraries/Interaction/BridgeSpyStallHandler.js +4 -3
  78. package/Libraries/Interaction/InteractionManager.js +1 -12
  79. package/Libraries/Interaction/TaskQueue.js +5 -4
  80. package/Libraries/LayoutAnimation/LayoutAnimation.js +13 -0
  81. package/Libraries/Linking/Linking.js +1 -1
  82. package/Libraries/Lists/FlatList.js +27 -6
  83. package/Libraries/Lists/VirtualizedList.js +71 -55
  84. package/Libraries/Lists/VirtualizedListContext.js +7 -3
  85. package/Libraries/Lists/VirtualizedSectionList.js +2 -2
  86. package/Libraries/Lists/__tests__/{FillRateHelper-test.windows.js → FillRateHelper-test.js} +2 -2
  87. package/Libraries/Lists/__tests__/{FlatList-test.windows.js → FlatList-test.js} +2 -2
  88. package/Libraries/Lists/__tests__/{SectionList-test.windows.js → SectionList-test.js} +14 -14
  89. package/Libraries/Lists/__tests__/{VirtualizeUtils-test.windows.js → VirtualizeUtils-test.js} +3 -3
  90. package/Libraries/Lists/__tests__/{VirtualizedList-test.windows.js → VirtualizedList-test.js} +91 -42
  91. package/Libraries/Lists/__tests__/{VirtualizedSectionList-test.windows.js → VirtualizedSectionList-test.js} +13 -13
  92. package/Libraries/LogBox/Data/LogBoxData.js +2 -2
  93. package/Libraries/LogBox/Data/LogBoxLog.js +1 -1
  94. package/Libraries/LogBox/Data/LogBoxSymbolication.js +1 -1
  95. package/Libraries/LogBox/Data/parseLogBoxLog.js +1 -1
  96. package/Libraries/LogBox/LogBox.js +2 -21
  97. package/Libraries/LogBox/UI/LogBoxInspectorFooter.js +1 -0
  98. package/Libraries/LogBox/UI/LogBoxInspectorHeader.js +2 -1
  99. package/Libraries/NativeComponent/BaseViewConfig.android.js +295 -0
  100. package/Libraries/NativeComponent/BaseViewConfig.ios.js +333 -0
  101. package/Libraries/NativeComponent/BaseViewConfig.windows.js +334 -0
  102. package/Libraries/NativeComponent/NativeComponentRegistry.js +0 -2
  103. package/Libraries/NativeComponent/PlatformBaseViewConfig.js +24 -0
  104. package/Libraries/NativeComponent/StaticViewConfigValidator.js +7 -42
  105. package/Libraries/NativeComponent/ViewConfig.js +4 -4
  106. package/Libraries/NativeComponent/ViewConfigIgnore.js +54 -0
  107. package/Libraries/Network/FormData.js +7 -1
  108. package/Libraries/Pressability/Pressability.js +115 -46
  109. package/Libraries/Pressability/Pressability.windows.js +190 -74
  110. package/Libraries/Pressability/PressabilityDebug.js +5 -9
  111. package/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js +1 -0
  112. package/Libraries/ReactNative/AppContainer.js +1 -1
  113. package/Libraries/ReactNative/{DummyUIManager.js → BridgelessUIManager.js} +62 -40
  114. package/Libraries/ReactNative/PaperUIManager.windows.js +5 -5
  115. package/Libraries/ReactNative/ReactNativeFeatureFlags.js +39 -0
  116. package/Libraries/ReactNative/UIManager.js +2 -3
  117. package/Libraries/ReactNative/renderApplication.js +4 -0
  118. package/Libraries/ReactPrivate/ReactNativePrivateInterface.js +8 -0
  119. package/Libraries/Renderer/implementations/ReactFabric-dev.js +5908 -4906
  120. package/Libraries/Renderer/implementations/ReactFabric-prod.js +2100 -1918
  121. package/Libraries/Renderer/implementations/ReactFabric-profiling.js +2567 -2352
  122. package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +5610 -4844
  123. package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +1710 -1556
  124. package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +1830 -1639
  125. package/Libraries/Renderer/shims/ReactNativeTypes.js +2 -1
  126. package/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +2 -1
  127. package/Libraries/StyleSheet/EdgeInsetsPropType.js +4 -1
  128. package/Libraries/StyleSheet/StyleSheetTypes.js +59 -66
  129. package/Libraries/StyleSheet/normalizeColor.js +1 -1
  130. package/Libraries/StyleSheet/private/_StyleSheetTypesOverrides.js +15 -0
  131. package/Libraries/StyleSheet/private/_TransformStyle.js +53 -0
  132. package/Libraries/StyleSheet/processTransform.windows.js +272 -0
  133. package/Libraries/Text/Text.js +13 -7
  134. package/Libraries/Text/Text.windows.js +16 -7
  135. package/Libraries/Text/TextNativeComponent.js +2 -0
  136. package/Libraries/Text/TextProps.js +10 -0
  137. package/Libraries/Types/CoreEventTypes.js +13 -1
  138. package/Libraries/Types/CoreEventTypes.windows.js +26 -1
  139. package/Libraries/Utilities/Appearance.js +0 -8
  140. package/Libraries/Utilities/HMRClient.js +1 -1
  141. package/Libraries/Utilities/ReactNativeTestTools.js +1 -0
  142. package/Libraries/Utilities/codegenNativeComponent.js +17 -6
  143. package/Libraries/Utilities/stringifySafe.js +4 -1
  144. package/Libraries/Utilities/verifyComponentAttributeEquivalence.js +3 -3
  145. package/Libraries/WebSocket/WebSocket.js +1 -1
  146. package/Libraries/vendor/emitter/_EmitterSubscription.js +1 -1
  147. package/Libraries/vendor/emitter/_EventEmitter.js +1 -1
  148. package/Libraries/vendor/emitter/_EventSubscription.js +1 -1
  149. package/Microsoft.ReactNative/Base/CoreNativeModules.cpp +1 -4
  150. package/Microsoft.ReactNative/DynamicReader.cpp +3 -3
  151. package/Microsoft.ReactNative/Fabric/ComponentView.h +1 -0
  152. package/Microsoft.ReactNative/Fabric/ComponentViewRegistry.cpp +36 -2
  153. package/Microsoft.ReactNative/Fabric/ComponentViewRegistry.h +1 -0
  154. package/Microsoft.ReactNative/Fabric/DWriteHelpers.cpp +19 -0
  155. package/Microsoft.ReactNative/Fabric/DWriteHelpers.h +13 -0
  156. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +65 -19
  157. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +2 -0
  158. package/Microsoft.ReactNative/Fabric/ParagraphComponentView.cpp +36 -10
  159. package/Microsoft.ReactNative/Fabric/ScrollViewComponentView.cpp +2 -0
  160. package/Microsoft.ReactNative/Fabric/SliderComponentView.cpp +107 -0
  161. package/Microsoft.ReactNative/Fabric/SliderComponentView.h +51 -0
  162. package/Microsoft.ReactNative/Fabric/SwitchComponentView.cpp +109 -0
  163. package/Microsoft.ReactNative/Fabric/SwitchComponentView.h +52 -0
  164. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputComponentDescriptor.h +197 -0
  165. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputComponentView.cpp +308 -0
  166. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputComponentView.h +52 -0
  167. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputEventEmitter.cpp +31 -0
  168. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputEventEmitter.h +33 -0
  169. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputProps.cpp +81 -0
  170. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputProps.h +132 -0
  171. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputShadowNode.cpp +193 -0
  172. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputShadowNode.h +85 -0
  173. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputState.cpp +76 -0
  174. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputState.h +99 -0
  175. package/Microsoft.ReactNative/Fabric/ViewComponentView.cpp +35 -3
  176. package/Microsoft.ReactNative/Fabric/ViewComponentView.h +1 -0
  177. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/rncore/EventEmitters.h +5 -0
  178. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/rncore/Props.h +5 -0
  179. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/slider/SliderMeasurementsManager.cpp +46 -0
  180. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/slider/SliderMeasurementsManager.h +30 -0
  181. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/Color.cpp +2 -0
  182. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/conversions.h +1 -9
  183. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/platform/cxx/react/renderer/graphics/Color.h +3 -1
  184. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +119 -57
  185. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h +18 -1
  186. package/Microsoft.ReactNative/IViewManager.idl +3 -3
  187. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +13 -107
  188. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +2 -2
  189. package/Microsoft.ReactNative/Modules/AppStateModule.cpp +2 -0
  190. package/Microsoft.ReactNative/Modules/AppStateModule.h +2 -0
  191. package/Microsoft.ReactNative/Modules/CreateModules.cpp +3 -3
  192. package/Microsoft.ReactNative/Modules/NativeUIManager.cpp +7 -5
  193. package/Microsoft.ReactNative/Modules/TimingModule.cpp +2 -2
  194. package/Microsoft.ReactNative/Modules/TimingModule.h +2 -2
  195. package/Microsoft.ReactNative/ReactHost/{ReactContext.cpp → MsoReactContext.cpp} +1 -1
  196. package/Microsoft.ReactNative/ReactHost/{ReactContext.h → MsoReactContext.h} +0 -0
  197. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +15 -2
  198. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +1 -1
  199. package/Microsoft.ReactNative/ReactHost/ReactNativeHeaders.h +1 -1
  200. package/Microsoft.ReactNative/ReactInstanceSettings.idl +12 -2
  201. package/Microsoft.ReactNative/ReactPackageBuilder.cpp +1 -1
  202. package/Microsoft.ReactNative/ReactRootView.cpp +2 -1
  203. package/Microsoft.ReactNative/RedBox.cpp +3 -2
  204. package/Microsoft.ReactNative/TurboModulesProvider.cpp +3 -2
  205. package/Microsoft.ReactNative/TurboModulesProvider.h +4 -1
  206. package/Microsoft.ReactNative/Utils/LocalBundleReader.cpp +41 -0
  207. package/Microsoft.ReactNative/Utils/ValueUtils.cpp +3 -2
  208. package/Microsoft.ReactNative/Views/ControlViewManager.cpp +32 -0
  209. package/Microsoft.ReactNative/Views/ControlViewManager.h +11 -0
  210. package/Microsoft.ReactNative/Views/DevMenu.cpp +2 -2
  211. package/Microsoft.ReactNative/Views/FrameworkElementTransferProperties.cpp +13 -2
  212. package/Microsoft.ReactNative/Views/FrameworkElementViewManager.cpp +149 -22
  213. package/Microsoft.ReactNative/Views/Image/ImageViewManager.cpp +1 -1
  214. package/Microsoft.ReactNative/Views/Image/Microsoft.UI.Composition.Effects_Impl.h +5 -11
  215. package/Microsoft.ReactNative/Views/Image/ReactImage.cpp +2 -1
  216. package/Microsoft.ReactNative/Views/SliderViewManager.cpp +12 -4
  217. package/Microsoft.ReactNative/Views/TextInputViewManager.cpp +1 -1
  218. package/Microsoft.ReactNative/Views/TextViewManager.cpp +2 -2
  219. package/Microsoft.ReactNative/Views/TouchEventHandler.cpp +163 -37
  220. package/Microsoft.ReactNative/Views/TouchEventHandler.h +11 -4
  221. package/Microsoft.ReactNative/Views/ViewPanel.cpp +3 -23
  222. package/Microsoft.ReactNative/Views/ViewPanel.h +2 -3
  223. package/Microsoft.ReactNative/Views/ViewViewManager.cpp +21 -0
  224. package/Microsoft.ReactNative/XamlUIService.cpp +1 -1
  225. package/Microsoft.ReactNative/XamlView.h +8 -3
  226. package/Microsoft.ReactNative.Cxx/CppWinRTIncludes.h +3 -5
  227. package/Microsoft.ReactNative.Cxx/DesktopWindowBridge.h +1 -1
  228. package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.cpp +11 -2
  229. package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.h +1 -0
  230. package/Microsoft.ReactNative.Cxx/JSI/NodeApiJsiRuntime.cpp +19 -14
  231. package/Microsoft.ReactNative.Cxx/JSI/NodeApiJsiRuntime.h +4 -0
  232. package/Microsoft.ReactNative.Cxx/JSValueReader.h +2 -2
  233. package/Microsoft.ReactNative.Cxx/JSValueWriter.h +5 -5
  234. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +5 -1
  235. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems.filters +2 -3
  236. package/Microsoft.ReactNative.Cxx/NativeModules.h +3 -3
  237. package/Microsoft.ReactNative.Cxx/ReactContext.h +3 -3
  238. package/Microsoft.ReactNative.Cxx/ReactNonAbiValue.h +3 -3
  239. package/Microsoft.ReactNative.Cxx/XamlUtils.h +44 -5
  240. package/Microsoft.ReactNative.Managed/Microsoft.ReactNative.Managed.csproj +0 -6
  241. package/Mso/activeObject/activeObject.h +2 -2
  242. package/Mso/compilerAdapters/cppMacros.h +3 -5
  243. package/Mso/errorCode/errorProvider.h +2 -2
  244. package/Mso/errorCode/maybe.h +4 -4
  245. package/Mso/functional/functor.h +6 -6
  246. package/Mso/functional/functorRef.h +2 -2
  247. package/Mso/future/details/executor.h +2 -2
  248. package/Mso/future/details/futureFuncInl.h +4 -4
  249. package/Mso/future/details/ifuture.h +3 -3
  250. package/Mso/future/details/maybeInvoker.h +6 -6
  251. package/Mso/future/details/promiseGroupInl.h +4 -4
  252. package/Mso/future/details/promiseInl.h +4 -4
  253. package/Mso/future/details/resultTraits.h +4 -4
  254. package/Mso/future/details/whenAllInl.h +1 -1
  255. package/Mso/future/future.h +13 -13
  256. package/Mso/guid/msoGuidDetails.h +1 -1
  257. package/Mso/memoryApi/memoryApi.h +13 -7
  258. package/Mso/motifCpp/gTestAdapter.h +1 -1
  259. package/Mso/motifCpp/testInfo.h +7 -9
  260. package/Mso/object/make.h +8 -8
  261. package/Mso/object/objectRefCount.h +3 -5
  262. package/Mso/object/objectWithWeakRef.h +10 -14
  263. package/Mso/object/queryCast.h +4 -4
  264. package/Mso/object/refCountedObject.h +4 -4
  265. package/Mso/object/unknownObject.h +7 -7
  266. package/Mso/platformAdapters/windowsFirst.h +1 -1
  267. package/Mso/smartPtr/cntPtr.h +8 -8
  268. package/Mso/src/dispatchQueue/threadPoolScheduler_win.cpp +96 -4
  269. package/Mso/src/dispatchQueue/uiScheduler_winrt.cpp +2 -2
  270. package/Mso/src/future/futureImpl.h +1 -1
  271. package/Mso/src/memoryApi/memoryApi.cpp +4 -4
  272. package/PropertySheets/CppAppConsumeCSharpModule.props +3 -0
  273. package/PropertySheets/External/Microsoft.ReactNative.WinAppSDK.CSharpApp.props +26 -0
  274. package/PropertySheets/External/Microsoft.ReactNative.WinAppSDK.Common.props +12 -0
  275. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  276. package/PropertySheets/JSEngine.props +1 -1
  277. package/PropertySheets/React.Cpp.props +13 -0
  278. package/PropertySheets/WinUI.props +3 -6
  279. package/ReactCommon/ReactCommon.vcxproj +2 -4
  280. package/ReactCommon/ReactCommon.vcxproj.filters +4 -1
  281. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/JSCRuntime.cpp +1480 -0
  282. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/jsi/decorator.h +753 -0
  283. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/jsi/jsi.h +1331 -0
  284. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/jsi/test/testlib.cpp +1431 -0
  285. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/bridging/CallbackWrapper.h +103 -0
  286. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModule.h +87 -0
  287. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModuleUtils.h +61 -0
  288. package/ReactCommon/Yoga.cpp +1 -1
  289. package/Scripts/{Microsoft.ReactNative.ProjectReunion.nuspec → Microsoft.ReactNative.WindowsAppSDK.nuspec} +7 -9
  290. package/Scripts/OfficeReact.Win32.nuspec +1 -3
  291. package/Scripts/Tfs/Layout-MSRN-Headers.ps1 +2 -1
  292. package/Scripts/copyRNLibraries.js +8 -8
  293. package/Scripts/just.js +1 -1
  294. package/Scripts/rnw-dependencies.ps1 +41 -10
  295. package/Scripts/run-desktop-integration-tests.js +6 -6
  296. package/Shared/AbiSafe.h +3 -3
  297. package/Shared/BaseScriptStoreImpl.cpp +1 -1
  298. package/Shared/CppRuntimeOptions.h +50 -0
  299. package/Shared/CreateModules.h +4 -0
  300. package/Shared/DevSupportManager.cpp +34 -33
  301. package/Shared/DevSupportManager.h +1 -2
  302. package/Shared/HermesRuntimeHolder.cpp +23 -14
  303. package/Shared/HermesRuntimeHolder.h +8 -2
  304. package/Shared/IDevSupportManager.h +1 -2
  305. package/Shared/InspectorPackagerConnection.cpp +7 -5
  306. package/Shared/InspectorPackagerConnection.h +2 -2
  307. package/Shared/JSI/ChakraApi.cpp +0 -1
  308. package/Shared/JSI/ChakraRuntime.cpp +1 -2
  309. package/Shared/JSI/NapiJsiV8RuntimeHolder.h +1 -1
  310. package/Shared/JSI/RuntimeHolder.h +2 -0
  311. package/Shared/Modules/HttpModule.cpp +198 -0
  312. package/Shared/Modules/HttpModule.h +53 -0
  313. package/Shared/Modules/WebSocketModule.cpp +5 -1
  314. package/Shared/Modules/WebSocketModule.h +8 -5
  315. package/Shared/Networking/IHttpResource.h +53 -0
  316. package/Shared/{IWebSocketResource.h → Networking/IWebSocketResource.h} +3 -3
  317. package/Shared/Networking/OriginPolicy.h +15 -0
  318. package/Shared/Networking/OriginPolicyHttpFilter.cpp +746 -0
  319. package/Shared/Networking/OriginPolicyHttpFilter.h +112 -0
  320. package/Shared/Networking/WinRTHttpResource.cpp +347 -0
  321. package/Shared/Networking/WinRTHttpResource.h +67 -0
  322. package/Shared/Networking/WinRTTypes.h +30 -0
  323. package/Shared/{WinRTWebSocketResource.cpp → Networking/WinRTWebSocketResource.cpp} +31 -22
  324. package/Shared/{WinRTWebSocketResource.h → Networking/WinRTWebSocketResource.h} +3 -3
  325. package/Shared/OInstance.cpp +37 -11
  326. package/Shared/RuntimeOptions.cpp +93 -15
  327. package/Shared/RuntimeOptions.h +22 -9
  328. package/Shared/Shared.vcxitems +126 -5
  329. package/Shared/Shared.vcxitems.filters +55 -15
  330. package/Shared/Threading/BatchingQueueThread.cpp +1 -1
  331. package/Shared/Utils/WinRTConversions.cpp +22 -0
  332. package/Shared/Utils/WinRTConversions.h +15 -0
  333. package/Shared/tracing/fbsystrace.h +2 -2
  334. package/codegen/NativeActionSheetManagerSpec.g.h +6 -0
  335. package/codegen/NativeAnimatedModuleSpec.g.h +43 -37
  336. package/codegen/NativeAnimatedTurboModuleSpec.g.h +43 -37
  337. package/codegen/NativePushNotificationManagerIOSSpec.g.h +2 -0
  338. package/codegen/react/components/rnwcore/ComponentDescriptors.h +0 -1
  339. package/codegen/react/components/rnwcore/EventEmitters.cpp +133 -0
  340. package/codegen/react/components/rnwcore/EventEmitters.h +0 -18
  341. package/codegen/react/components/rnwcore/Props.cpp +0 -13
  342. package/codegen/react/components/rnwcore/Props.h +0 -16
  343. package/codegen/react/components/rnwcore/ShadowNodes.cpp +0 -1
  344. package/codegen/react/components/rnwcore/ShadowNodes.h +0 -10
  345. package/include/Shared/cdebug.h +9 -9
  346. package/index.js +30 -25
  347. package/index.windows.js +30 -25
  348. package/jest/preprocessor.js +24 -107
  349. package/jest/preprocessor_DO_NOT_USE.js +122 -0
  350. package/metro.config.js +3 -70
  351. package/package.json +29 -28
  352. package/react-native.config.js +40 -6
  353. package/rntypes/index.d.ts +19 -7
  354. package/stubs/glog/logging.h +1 -1
  355. package/template/cpp-app/src/App.h +0 -4
  356. package/template/cs-app/src/App.xaml.cs +0 -5
  357. package/template/cs-app/src/MainPage.xaml.cs +1 -10
  358. package/template/cs-app-WinAppSDK/MyApp/App.xaml +16 -0
  359. package/template/cs-app-WinAppSDK/MyApp/App.xaml.cs +70 -0
  360. package/template/cs-app-WinAppSDK/MyApp/MainWindow.xaml +14 -0
  361. package/template/cs-app-WinAppSDK/MyApp/MainWindow.xaml.cs +38 -0
  362. package/template/cs-app-WinAppSDK/MyApp/Package.appxmanifest +48 -0
  363. package/template/cs-app-WinAppSDK/MyApp/Properties/PublishProfiles/win10-arm64.pubxml +19 -0
  364. package/template/cs-app-WinAppSDK/MyApp/Properties/PublishProfiles/win10-x64.pubxml +19 -0
  365. package/template/cs-app-WinAppSDK/MyApp/Properties/PublishProfiles/win10-x86.pubxml +19 -0
  366. package/template/cs-app-WinAppSDK/MyApp/Properties/launchSettings.json +10 -0
  367. package/template/cs-app-WinAppSDK/MyApp/app.manifest +15 -0
  368. package/template/cs-app-WinAppSDK/proj/ExperimentalFeatures.props +23 -0
  369. package/template/cs-app-WinAppSDK/proj/MyApp.csproj +49 -0
  370. package/template/cs-app-WinAppSDK/proj/MyApp.sln +43 -0
  371. package/template/cs-app-WinAppSDK/proj/NuGet.Config +17 -0
  372. package/template/metro.devMode.config.js +2 -51
  373. package/typings-index.js +5 -1
  374. package/typings-index.js.map +1 -1
  375. package/Libraries/Components/SegmentedControlIOS/RCTSegmentedControlNativeComponent.js +0 -44
  376. package/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.android.js +0 -45
  377. package/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js +0 -123
  378. package/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.windows.js +0 -45
  379. package/Libraries/Components/View/ReactNativeViewViewConfig.js +0 -360
  380. package/Libraries/Components/View/ReactNativeViewViewConfig.windows.js +0 -390
  381. package/Libraries/Components/View/ReactNativeViewViewConfigAndroid.js +0 -83
  382. package/Libraries/ReactNative/UIManagerInjection.js +0 -15
  383. package/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +0 -24527
  384. package/Libraries/Renderer/implementations/ReactFabric-prod.fb.js +0 -8309
  385. package/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js +0 -8961
  386. package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +0 -24948
  387. package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js +0 -8400
  388. package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js +0 -9049
  389. package/PropertySheets/CppEnablePackageReferences.props +0 -13
  390. package/Shared/IHttpResource.h +0 -34
  391. package/Shared/cdebug.cpp +0 -6
  392. package/include/Shared/ViewManager.h +0 -34
@@ -0,0 +1,1431 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #include <jsi/test/testlib.h>
9
+
10
+ #include <gtest/gtest.h>
11
+ #include <jsi/decorator.h>
12
+ #include <jsi/jsi.h>
13
+
14
+ #include <stdlib.h>
15
+ #include <chrono>
16
+ #include <functional>
17
+ #include <thread>
18
+ #include <unordered_map>
19
+ #include <unordered_set>
20
+
21
+ using namespace facebook::jsi;
22
+
23
+ class JSITest : public JSITestBase {};
24
+
25
+ TEST_P(JSITest, RuntimeTest) {
26
+ auto v = rt.evaluateJavaScript(std::make_unique<StringBuffer>("1"), "");
27
+ EXPECT_EQ(v.getNumber(), 1);
28
+
29
+ rt.evaluateJavaScript(std::make_unique<StringBuffer>("x = 1"), "");
30
+ EXPECT_EQ(rt.global().getProperty(rt, "x").getNumber(), 1);
31
+ }
32
+
33
+ TEST_P(JSITest, PropNameIDTest) {
34
+ // This is a little weird to test, because it doesn't really exist
35
+ // in JS yet. All I can do is create them, compare them, and
36
+ // receive one as an argument to a HostObject.
37
+
38
+ PropNameID quux = PropNameID::forAscii(rt, "quux1", 4);
39
+ PropNameID movedQuux = std::move(quux);
40
+ EXPECT_EQ(movedQuux.utf8(rt), "quux");
41
+ movedQuux = PropNameID::forAscii(rt, "quux2");
42
+ EXPECT_EQ(movedQuux.utf8(rt), "quux2");
43
+ PropNameID copiedQuux = PropNameID(rt, movedQuux);
44
+ EXPECT_TRUE(PropNameID::compare(rt, movedQuux, copiedQuux));
45
+
46
+ EXPECT_TRUE(PropNameID::compare(rt, movedQuux, movedQuux));
47
+ EXPECT_TRUE(PropNameID::compare(
48
+ rt, movedQuux, PropNameID::forAscii(rt, std::string("quux2"))));
49
+ EXPECT_FALSE(PropNameID::compare(
50
+ rt, movedQuux, PropNameID::forAscii(rt, std::string("foo"))));
51
+ uint8_t utf8[] = {0xF0, 0x9F, 0x86, 0x97};
52
+ PropNameID utf8PropNameID = PropNameID::forUtf8(rt, utf8, sizeof(utf8));
53
+ EXPECT_EQ(utf8PropNameID.utf8(rt), u8"\U0001F197");
54
+ EXPECT_TRUE(PropNameID::compare(
55
+ rt, utf8PropNameID, PropNameID::forUtf8(rt, utf8, sizeof(utf8))));
56
+ PropNameID nonUtf8PropNameID = PropNameID::forUtf8(rt, "meow");
57
+ EXPECT_TRUE(PropNameID::compare(
58
+ rt, nonUtf8PropNameID, PropNameID::forAscii(rt, "meow")));
59
+ EXPECT_EQ(nonUtf8PropNameID.utf8(rt), "meow");
60
+ PropNameID strPropNameID =
61
+ PropNameID::forString(rt, String::createFromAscii(rt, "meow"));
62
+ EXPECT_TRUE(PropNameID::compare(rt, nonUtf8PropNameID, strPropNameID));
63
+
64
+ auto names = PropNameID::names(
65
+ rt, "Ala", std::string("ma"), PropNameID::forAscii(rt, "kota"));
66
+ EXPECT_EQ(names.size(), 3);
67
+ EXPECT_TRUE(
68
+ PropNameID::compare(rt, names[0], PropNameID::forAscii(rt, "Ala")));
69
+ EXPECT_TRUE(
70
+ PropNameID::compare(rt, names[1], PropNameID::forAscii(rt, "ma")));
71
+ EXPECT_TRUE(
72
+ PropNameID::compare(rt, names[2], PropNameID::forAscii(rt, "kota")));
73
+ }
74
+
75
+ TEST_P(JSITest, StringTest) {
76
+ EXPECT_TRUE(checkValue(String::createFromAscii(rt, "foobar", 3), "'foo'"));
77
+ EXPECT_TRUE(checkValue(String::createFromAscii(rt, "foobar"), "'foobar'"));
78
+
79
+ std::string baz = "baz";
80
+ EXPECT_TRUE(checkValue(String::createFromAscii(rt, baz), "'baz'"));
81
+
82
+ uint8_t utf8[] = {0xF0, 0x9F, 0x86, 0x97};
83
+ EXPECT_TRUE(checkValue(
84
+ String::createFromUtf8(rt, utf8, sizeof(utf8)), "'\\uD83C\\uDD97'"));
85
+
86
+ EXPECT_EQ(eval("'quux'").getString(rt).utf8(rt), "quux");
87
+ EXPECT_EQ(eval("'\\u20AC'").getString(rt).utf8(rt), "\xe2\x82\xac");
88
+
89
+ String quux = String::createFromAscii(rt, "quux");
90
+ String movedQuux = std::move(quux);
91
+ EXPECT_EQ(movedQuux.utf8(rt), "quux");
92
+ movedQuux = String::createFromAscii(rt, "quux2");
93
+ EXPECT_EQ(movedQuux.utf8(rt), "quux2");
94
+ }
95
+
96
+ TEST_P(JSITest, ObjectTest) {
97
+ eval("x = {1:2, '3':4, 5:'six', 'seven':['eight', 'nine']}");
98
+ Object x = rt.global().getPropertyAsObject(rt, "x");
99
+ EXPECT_EQ(x.getPropertyNames(rt).size(rt), 4);
100
+ EXPECT_TRUE(x.hasProperty(rt, "1"));
101
+ EXPECT_TRUE(x.hasProperty(rt, PropNameID::forAscii(rt, "1")));
102
+ EXPECT_FALSE(x.hasProperty(rt, "2"));
103
+ EXPECT_FALSE(x.hasProperty(rt, PropNameID::forAscii(rt, "2")));
104
+ EXPECT_TRUE(x.hasProperty(rt, "3"));
105
+ EXPECT_TRUE(x.hasProperty(rt, PropNameID::forAscii(rt, "3")));
106
+ EXPECT_TRUE(x.hasProperty(rt, "seven"));
107
+ EXPECT_TRUE(x.hasProperty(rt, PropNameID::forAscii(rt, "seven")));
108
+ EXPECT_EQ(x.getProperty(rt, "1").getNumber(), 2);
109
+ EXPECT_EQ(x.getProperty(rt, PropNameID::forAscii(rt, "1")).getNumber(), 2);
110
+ EXPECT_EQ(x.getProperty(rt, "3").getNumber(), 4);
111
+ Value five = 5;
112
+ EXPECT_EQ(
113
+ x.getProperty(rt, PropNameID::forString(rt, five.toString(rt)))
114
+ .getString(rt)
115
+ .utf8(rt),
116
+ "six");
117
+
118
+ x.setProperty(rt, "ten", 11);
119
+ EXPECT_EQ(x.getPropertyNames(rt).size(rt), 5);
120
+ EXPECT_TRUE(eval("x.ten == 11").getBool());
121
+
122
+ x.setProperty(rt, "e_as_float", 2.71f);
123
+ EXPECT_TRUE(eval("Math.abs(x.e_as_float - 2.71) < 0.001").getBool());
124
+
125
+ x.setProperty(rt, "e_as_double", 2.71);
126
+ EXPECT_TRUE(eval("x.e_as_double == 2.71").getBool());
127
+
128
+ uint8_t utf8[] = {0xF0, 0x9F, 0x86, 0x97};
129
+ String nonAsciiName = String::createFromUtf8(rt, utf8, sizeof(utf8));
130
+ x.setProperty(rt, PropNameID::forString(rt, nonAsciiName), "emoji");
131
+ EXPECT_EQ(x.getPropertyNames(rt).size(rt), 8);
132
+ EXPECT_TRUE(eval("x['\\uD83C\\uDD97'] == 'emoji'").getBool());
133
+
134
+ Object seven = x.getPropertyAsObject(rt, "seven");
135
+ EXPECT_TRUE(seven.isArray(rt));
136
+ Object evalf = rt.global().getPropertyAsObject(rt, "eval");
137
+ EXPECT_TRUE(evalf.isFunction(rt));
138
+
139
+ Object movedX = Object(rt);
140
+ movedX = std::move(x);
141
+ EXPECT_EQ(movedX.getPropertyNames(rt).size(rt), 8);
142
+ EXPECT_EQ(movedX.getProperty(rt, "1").getNumber(), 2);
143
+
144
+ Object obj = Object(rt);
145
+ obj.setProperty(rt, "roses", "red");
146
+ obj.setProperty(rt, "violets", "blue");
147
+ Object oprop = Object(rt);
148
+ obj.setProperty(rt, "oprop", oprop);
149
+ obj.setProperty(rt, "aprop", Array(rt, 1));
150
+
151
+ EXPECT_TRUE(function("function (obj) { return "
152
+ "obj.roses == 'red' && "
153
+ "obj['violets'] == 'blue' && "
154
+ "typeof obj.oprop == 'object' && "
155
+ "Array.isArray(obj.aprop); }")
156
+ .call(rt, obj)
157
+ .getBool());
158
+
159
+ // Check that getPropertyNames doesn't return non-enumerable
160
+ // properties.
161
+ obj = function(
162
+ "function () {"
163
+ " obj = {};"
164
+ " obj.a = 1;"
165
+ " Object.defineProperty(obj, 'b', {"
166
+ " enumerable: false,"
167
+ " value: 2"
168
+ " });"
169
+ " return obj;"
170
+ "}")
171
+ .call(rt)
172
+ .getObject(rt);
173
+ EXPECT_EQ(obj.getProperty(rt, "a").getNumber(), 1);
174
+ EXPECT_EQ(obj.getProperty(rt, "b").getNumber(), 2);
175
+ Array names = obj.getPropertyNames(rt);
176
+ EXPECT_EQ(names.size(rt), 1);
177
+ EXPECT_EQ(names.getValueAtIndex(rt, 0).getString(rt).utf8(rt), "a");
178
+ }
179
+
180
+ TEST_P(JSITest, HostObjectTest) {
181
+ class ConstantHostObject : public HostObject {
182
+ Value get(Runtime&, const PropNameID& sym) override {
183
+ return 9000;
184
+ }
185
+
186
+ void set(Runtime&, const PropNameID&, const Value&) override {}
187
+ };
188
+
189
+ Object cho =
190
+ Object::createFromHostObject(rt, std::make_shared<ConstantHostObject>());
191
+ EXPECT_TRUE(function("function (obj) { return obj.someRandomProp == 9000; }")
192
+ .call(rt, cho)
193
+ .getBool());
194
+ EXPECT_TRUE(cho.isHostObject(rt));
195
+ EXPECT_TRUE(cho.getHostObject<ConstantHostObject>(rt).get() != nullptr);
196
+
197
+ struct SameRuntimeHostObject : HostObject {
198
+ SameRuntimeHostObject(Runtime& rt) : rt_(rt){};
199
+
200
+ Value get(Runtime& rt, const PropNameID& sym) override {
201
+ EXPECT_EQ(&rt, &rt_);
202
+ return Value();
203
+ }
204
+
205
+ void set(Runtime& rt, const PropNameID& name, const Value& value) override {
206
+ EXPECT_EQ(&rt, &rt_);
207
+ }
208
+
209
+ std::vector<PropNameID> getPropertyNames(Runtime& rt) override {
210
+ EXPECT_EQ(&rt, &rt_);
211
+ return {};
212
+ }
213
+
214
+ Runtime& rt_;
215
+ };
216
+
217
+ Object srho = Object::createFromHostObject(
218
+ rt, std::make_shared<SameRuntimeHostObject>(rt));
219
+ // Test get's Runtime is as expected
220
+ function("function (obj) { return obj.isSame; }").call(rt, srho);
221
+ // ... and set
222
+ function("function (obj) { obj['k'] = 'v'; }").call(rt, srho);
223
+ // ... and getPropertyNames
224
+ function("function (obj) { for (k in obj) {} }").call(rt, srho);
225
+
226
+ class TwiceHostObject : public HostObject {
227
+ Value get(Runtime& rt, const PropNameID& sym) override {
228
+ return String::createFromUtf8(rt, sym.utf8(rt) + sym.utf8(rt));
229
+ }
230
+
231
+ void set(Runtime&, const PropNameID&, const Value&) override {}
232
+ };
233
+
234
+ Object tho =
235
+ Object::createFromHostObject(rt, std::make_shared<TwiceHostObject>());
236
+ EXPECT_TRUE(function("function (obj) { return obj.abc == 'abcabc'; }")
237
+ .call(rt, tho)
238
+ .getBool());
239
+ EXPECT_TRUE(function("function (obj) { return obj['def'] == 'defdef'; }")
240
+ .call(rt, tho)
241
+ .getBool());
242
+ EXPECT_TRUE(function("function (obj) { return obj[12] === '1212'; }")
243
+ .call(rt, tho)
244
+ .getBool());
245
+ EXPECT_TRUE(tho.isHostObject(rt));
246
+ EXPECT_TRUE(
247
+ std::dynamic_pointer_cast<ConstantHostObject>(tho.getHostObject(rt)) ==
248
+ nullptr);
249
+ EXPECT_TRUE(tho.getHostObject<TwiceHostObject>(rt).get() != nullptr);
250
+
251
+ class PropNameIDHostObject : public HostObject {
252
+ Value get(Runtime& rt, const PropNameID& sym) override {
253
+ if (PropNameID::compare(rt, sym, PropNameID::forAscii(rt, "undef"))) {
254
+ return Value::undefined();
255
+ } else {
256
+ return PropNameID::compare(
257
+ rt, sym, PropNameID::forAscii(rt, "somesymbol"));
258
+ }
259
+ }
260
+
261
+ void set(Runtime&, const PropNameID&, const Value&) override {}
262
+ };
263
+
264
+ Object sho = Object::createFromHostObject(
265
+ rt, std::make_shared<PropNameIDHostObject>());
266
+ EXPECT_TRUE(sho.isHostObject(rt));
267
+ EXPECT_TRUE(function("function (obj) { return obj.undef; }")
268
+ .call(rt, sho)
269
+ .isUndefined());
270
+ EXPECT_TRUE(function("function (obj) { return obj.somesymbol; }")
271
+ .call(rt, sho)
272
+ .getBool());
273
+ EXPECT_FALSE(function("function (obj) { return obj.notsomuch; }")
274
+ .call(rt, sho)
275
+ .getBool());
276
+
277
+ class BagHostObject : public HostObject {
278
+ public:
279
+ const std::string& getThing() {
280
+ return bag_["thing"];
281
+ }
282
+
283
+ private:
284
+ Value get(Runtime& rt, const PropNameID& sym) override {
285
+ if (sym.utf8(rt) == "thing") {
286
+ return String::createFromUtf8(rt, bag_[sym.utf8(rt)]);
287
+ }
288
+ return Value::undefined();
289
+ }
290
+
291
+ void set(Runtime& rt, const PropNameID& sym, const Value& val) override {
292
+ std::string key(sym.utf8(rt));
293
+ if (key == "thing") {
294
+ bag_[key] = val.toString(rt).utf8(rt);
295
+ }
296
+ }
297
+
298
+ std::unordered_map<std::string, std::string> bag_;
299
+ };
300
+
301
+ std::shared_ptr<BagHostObject> shbho = std::make_shared<BagHostObject>();
302
+ Object bho = Object::createFromHostObject(rt, shbho);
303
+ EXPECT_TRUE(bho.isHostObject(rt));
304
+ EXPECT_TRUE(function("function (obj) { return obj.undef; }")
305
+ .call(rt, bho)
306
+ .isUndefined());
307
+ EXPECT_EQ(
308
+ function("function (obj) { obj.thing = 'hello'; return obj.thing; }")
309
+ .call(rt, bho)
310
+ .toString(rt)
311
+ .utf8(rt),
312
+ "hello");
313
+ EXPECT_EQ(shbho->getThing(), "hello");
314
+
315
+ class ThrowingHostObject : public HostObject {
316
+ Value get(Runtime& rt, const PropNameID& sym) override {
317
+ throw std::runtime_error("Cannot get");
318
+ }
319
+
320
+ void set(Runtime& rt, const PropNameID& sym, const Value& val) override {
321
+ throw std::runtime_error("Cannot set");
322
+ }
323
+ };
324
+
325
+ Object thro =
326
+ Object::createFromHostObject(rt, std::make_shared<ThrowingHostObject>());
327
+ EXPECT_TRUE(thro.isHostObject(rt));
328
+ std::string exc;
329
+ try {
330
+ function("function (obj) { return obj.thing; }").call(rt, thro);
331
+ } catch (const JSError& ex) {
332
+ exc = ex.what();
333
+ }
334
+ EXPECT_NE(exc.find("Cannot get"), std::string::npos);
335
+ exc = "";
336
+ try {
337
+ function("function (obj) { obj.thing = 'hello'; }").call(rt, thro);
338
+ } catch (const JSError& ex) {
339
+ exc = ex.what();
340
+ }
341
+ EXPECT_NE(exc.find("Cannot set"), std::string::npos);
342
+
343
+ class NopHostObject : public HostObject {};
344
+ Object nopHo =
345
+ Object::createFromHostObject(rt, std::make_shared<NopHostObject>());
346
+ EXPECT_TRUE(nopHo.isHostObject(rt));
347
+ EXPECT_TRUE(function("function (obj) { return obj.thing; }")
348
+ .call(rt, nopHo)
349
+ .isUndefined());
350
+
351
+ std::string nopExc;
352
+ try {
353
+ function("function (obj) { obj.thing = 'pika'; }").call(rt, nopHo);
354
+ } catch (const JSError& ex) {
355
+ nopExc = ex.what();
356
+ }
357
+ EXPECT_NE(nopExc.find("TypeError: "), std::string::npos);
358
+
359
+ class HostObjectWithPropertyNames : public HostObject {
360
+ std::vector<PropNameID> getPropertyNames(Runtime& rt) override {
361
+ return PropNameID::names(
362
+ rt, "a_prop", "1", "false", "a_prop", "3", "c_prop");
363
+ }
364
+ };
365
+
366
+ Object howpn = Object::createFromHostObject(
367
+ rt, std::make_shared<HostObjectWithPropertyNames>());
368
+ EXPECT_TRUE(
369
+ function(
370
+ "function (o) { return Object.getOwnPropertyNames(o).length == 5 }")
371
+ .call(rt, howpn)
372
+ .getBool());
373
+
374
+ auto hasOwnPropertyName = function(
375
+ "function (o, p) {"
376
+ " return Object.getOwnPropertyNames(o).indexOf(p) >= 0"
377
+ "}");
378
+ EXPECT_TRUE(
379
+ hasOwnPropertyName.call(rt, howpn, String::createFromAscii(rt, "a_prop"))
380
+ .getBool());
381
+ EXPECT_TRUE(
382
+ hasOwnPropertyName.call(rt, howpn, String::createFromAscii(rt, "1"))
383
+ .getBool());
384
+ EXPECT_TRUE(
385
+ hasOwnPropertyName.call(rt, howpn, String::createFromAscii(rt, "false"))
386
+ .getBool());
387
+ EXPECT_TRUE(
388
+ hasOwnPropertyName.call(rt, howpn, String::createFromAscii(rt, "3"))
389
+ .getBool());
390
+ EXPECT_TRUE(
391
+ hasOwnPropertyName.call(rt, howpn, String::createFromAscii(rt, "c_prop"))
392
+ .getBool());
393
+ EXPECT_FALSE(hasOwnPropertyName
394
+ .call(rt, howpn, String::createFromAscii(rt, "not_existing"))
395
+ .getBool());
396
+ }
397
+
398
+ TEST_P(JSITest, HostObjectProtoTest) {
399
+ class ProtoHostObject : public HostObject {
400
+ Value get(Runtime& rt, const PropNameID&) override {
401
+ return String::createFromAscii(rt, "phoprop");
402
+ }
403
+ };
404
+
405
+ rt.global().setProperty(
406
+ rt,
407
+ "pho",
408
+ Object::createFromHostObject(rt, std::make_shared<ProtoHostObject>()));
409
+
410
+ EXPECT_EQ(
411
+ eval("({__proto__: pho})[Symbol.toPrimitive]").getString(rt).utf8(rt),
412
+ "phoprop");
413
+ }
414
+
415
+ TEST_P(JSITest, ArrayTest) {
416
+ eval("x = {1:2, '3':4, 5:'six', 'seven':['eight', 'nine']}");
417
+
418
+ Object x = rt.global().getPropertyAsObject(rt, "x");
419
+ Array names = x.getPropertyNames(rt);
420
+ EXPECT_EQ(names.size(rt), 4);
421
+ std::unordered_set<std::string> strNames;
422
+ for (size_t i = 0; i < names.size(rt); ++i) {
423
+ Value n = names.getValueAtIndex(rt, i);
424
+ EXPECT_TRUE(n.isString());
425
+ strNames.insert(n.getString(rt).utf8(rt));
426
+ }
427
+
428
+ EXPECT_EQ(strNames.size(), 4);
429
+ EXPECT_EQ(strNames.count("1"), 1);
430
+ EXPECT_EQ(strNames.count("3"), 1);
431
+ EXPECT_EQ(strNames.count("5"), 1);
432
+ EXPECT_EQ(strNames.count("seven"), 1);
433
+
434
+ Object seven = x.getPropertyAsObject(rt, "seven");
435
+ Array arr = seven.getArray(rt);
436
+
437
+ EXPECT_EQ(arr.size(rt), 2);
438
+ EXPECT_EQ(arr.getValueAtIndex(rt, 0).getString(rt).utf8(rt), "eight");
439
+ EXPECT_EQ(arr.getValueAtIndex(rt, 1).getString(rt).utf8(rt), "nine");
440
+ // TODO: test out of range
441
+
442
+ EXPECT_EQ(x.getPropertyAsObject(rt, "seven").getArray(rt).size(rt), 2);
443
+
444
+ // Check that property access with both symbols and strings can access
445
+ // array values.
446
+ EXPECT_EQ(seven.getProperty(rt, "0").getString(rt).utf8(rt), "eight");
447
+ EXPECT_EQ(seven.getProperty(rt, "1").getString(rt).utf8(rt), "nine");
448
+ seven.setProperty(rt, "1", "modified");
449
+ EXPECT_EQ(seven.getProperty(rt, "1").getString(rt).utf8(rt), "modified");
450
+ EXPECT_EQ(arr.getValueAtIndex(rt, 1).getString(rt).utf8(rt), "modified");
451
+ EXPECT_EQ(
452
+ seven.getProperty(rt, PropNameID::forAscii(rt, "0"))
453
+ .getString(rt)
454
+ .utf8(rt),
455
+ "eight");
456
+ seven.setProperty(rt, PropNameID::forAscii(rt, "0"), "modified2");
457
+ EXPECT_EQ(arr.getValueAtIndex(rt, 0).getString(rt).utf8(rt), "modified2");
458
+
459
+ Array alpha = Array(rt, 4);
460
+ EXPECT_TRUE(alpha.getValueAtIndex(rt, 0).isUndefined());
461
+ EXPECT_TRUE(alpha.getValueAtIndex(rt, 3).isUndefined());
462
+ EXPECT_EQ(alpha.size(rt), 4);
463
+ alpha.setValueAtIndex(rt, 0, "a");
464
+ alpha.setValueAtIndex(rt, 1, "b");
465
+ EXPECT_EQ(alpha.length(rt), 4);
466
+ alpha.setValueAtIndex(rt, 2, "c");
467
+ alpha.setValueAtIndex(rt, 3, "d");
468
+ EXPECT_EQ(alpha.size(rt), 4);
469
+
470
+ EXPECT_TRUE(
471
+ function(
472
+ "function (arr) { return "
473
+ "arr.length == 4 && "
474
+ "['a','b','c','d'].every(function(v,i) { return v === arr[i]}); }")
475
+ .call(rt, alpha)
476
+ .getBool());
477
+
478
+ Array alpha2 = Array(rt, 1);
479
+ alpha2 = std::move(alpha);
480
+ EXPECT_EQ(alpha2.size(rt), 4);
481
+ }
482
+
483
+ TEST_P(JSITest, FunctionTest) {
484
+ // test move ctor
485
+ Function fmove = function("function() { return 1 }");
486
+ {
487
+ Function g = function("function() { return 2 }");
488
+ fmove = std::move(g);
489
+ }
490
+ EXPECT_EQ(fmove.call(rt).getNumber(), 2);
491
+
492
+ // This tests all the function argument converters, and all the
493
+ // non-lvalue overloads of call().
494
+ Function f = function(
495
+ "function(n, b, d, df, i, s1, s2, s3, s_sun, s_bad, o, a, f, v) { "
496
+ "return "
497
+ "n === null && "
498
+ "b === true && "
499
+ "d === 3.14 && "
500
+ "Math.abs(df - 2.71) < 0.001 && "
501
+ "i === 17 && "
502
+ "s1 == 's1' && "
503
+ "s2 == 's2' && "
504
+ "s3 == 's3' && "
505
+ "s_sun == 's\\u2600' && "
506
+ "typeof s_bad == 'string' && "
507
+ "typeof o == 'object' && "
508
+ "Array.isArray(a) && "
509
+ "typeof f == 'function' && "
510
+ "v == 42 }");
511
+ EXPECT_TRUE(f.call(
512
+ rt,
513
+ nullptr,
514
+ true,
515
+ 3.14,
516
+ 2.71f,
517
+ 17,
518
+ "s1",
519
+ String::createFromAscii(rt, "s2"),
520
+ std::string{"s3"},
521
+ std::string{u8"s\u2600"},
522
+ // invalid UTF8 sequence due to unexpected continuation byte
523
+ std::string{"s\x80"},
524
+ Object(rt),
525
+ Array(rt, 1),
526
+ function("function(){}"),
527
+ Value(42))
528
+ .getBool());
529
+
530
+ // lvalue overloads of call()
531
+ Function flv = function(
532
+ "function(s, o, a, f, v) { return "
533
+ "s == 's' && "
534
+ "typeof o == 'object' && "
535
+ "Array.isArray(a) && "
536
+ "typeof f == 'function' && "
537
+ "v == 42 }");
538
+
539
+ String s = String::createFromAscii(rt, "s");
540
+ Object o = Object(rt);
541
+ Array a = Array(rt, 1);
542
+ Value v = 42;
543
+ EXPECT_TRUE(flv.call(rt, s, o, a, f, v).getBool());
544
+
545
+ Function f1 = function("function() { return 1; }");
546
+ Function f2 = function("function() { return 2; }");
547
+ f2 = std::move(f1);
548
+ EXPECT_EQ(f2.call(rt).getNumber(), 1);
549
+ }
550
+
551
+ TEST_P(JSITest, FunctionThisTest) {
552
+ Function checkPropertyFunction =
553
+ function("function() { return this.a === 'a_property' }");
554
+
555
+ Object jsObject = Object(rt);
556
+ jsObject.setProperty(rt, "a", String::createFromUtf8(rt, "a_property"));
557
+
558
+ class APropertyHostObject : public HostObject {
559
+ Value get(Runtime& rt, const PropNameID& sym) override {
560
+ return String::createFromUtf8(rt, "a_property");
561
+ }
562
+
563
+ void set(Runtime&, const PropNameID&, const Value&) override {}
564
+ };
565
+ Object hostObject =
566
+ Object::createFromHostObject(rt, std::make_shared<APropertyHostObject>());
567
+
568
+ EXPECT_TRUE(checkPropertyFunction.callWithThis(rt, jsObject).getBool());
569
+ EXPECT_TRUE(checkPropertyFunction.callWithThis(rt, hostObject).getBool());
570
+ EXPECT_FALSE(checkPropertyFunction.callWithThis(rt, Array(rt, 5)).getBool());
571
+ EXPECT_FALSE(checkPropertyFunction.call(rt).getBool());
572
+ }
573
+
574
+ TEST_P(JSITest, FunctionConstructorTest) {
575
+ Function ctor = function(
576
+ "function (a) {"
577
+ " if (typeof a !== 'undefined') {"
578
+ " this.pika = a;"
579
+ " }"
580
+ "}");
581
+ ctor.getProperty(rt, "prototype")
582
+ .getObject(rt)
583
+ .setProperty(rt, "pika", "chu");
584
+ auto empty = ctor.callAsConstructor(rt);
585
+ EXPECT_TRUE(empty.isObject());
586
+ auto emptyObj = std::move(empty).getObject(rt);
587
+ EXPECT_EQ(emptyObj.getProperty(rt, "pika").getString(rt).utf8(rt), "chu");
588
+ auto who = ctor.callAsConstructor(rt, "who");
589
+ EXPECT_TRUE(who.isObject());
590
+ auto whoObj = std::move(who).getObject(rt);
591
+ EXPECT_EQ(whoObj.getProperty(rt, "pika").getString(rt).utf8(rt), "who");
592
+
593
+ auto instanceof = function("function (o, b) { return o instanceof b; }");
594
+ EXPECT_TRUE(instanceof.call(rt, emptyObj, ctor).getBool());
595
+ EXPECT_TRUE(instanceof.call(rt, whoObj, ctor).getBool());
596
+
597
+ auto dateCtor = rt.global().getPropertyAsFunction(rt, "Date");
598
+ auto date = dateCtor.callAsConstructor(rt);
599
+ EXPECT_TRUE(date.isObject());
600
+ EXPECT_TRUE(instanceof.call(rt, date, dateCtor).getBool());
601
+ // Sleep for 50 milliseconds
602
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
603
+ EXPECT_GE(
604
+ function("function (d) { return (new Date()).getTime() - d.getTime(); }")
605
+ .call(rt, date)
606
+ .getNumber(),
607
+ 50);
608
+ }
609
+
610
+ TEST_P(JSITest, InstanceOfTest) {
611
+ auto ctor = function("function Rick() { this.say = 'wubalubadubdub'; }");
612
+ auto newObj = function("function (ctor) { return new ctor(); }");
613
+ auto instance = newObj.call(rt, ctor).getObject(rt);
614
+ EXPECT_TRUE(instance.instanceOf(rt, ctor));
615
+ EXPECT_EQ(
616
+ instance.getProperty(rt, "say").getString(rt).utf8(rt), "wubalubadubdub");
617
+ EXPECT_FALSE(Object(rt).instanceOf(rt, ctor));
618
+ EXPECT_TRUE(ctor.callAsConstructor(rt, nullptr, 0)
619
+ .getObject(rt)
620
+ .instanceOf(rt, ctor));
621
+ }
622
+
623
+ TEST_P(JSITest, HostFunctionTest) {
624
+ auto one = std::make_shared<int>(1);
625
+ Function plusOne = Function::createFromHostFunction(
626
+ rt,
627
+ PropNameID::forAscii(rt, "plusOne"),
628
+ 2,
629
+ [one, savedRt = &rt](
630
+ Runtime& rt, const Value& thisVal, const Value* args, size_t count) {
631
+ EXPECT_EQ(savedRt, &rt);
632
+ // We don't know if we're in strict mode or not, so it's either global
633
+ // or undefined.
634
+ EXPECT_TRUE(
635
+ Value::strictEquals(rt, thisVal, rt.global()) ||
636
+ thisVal.isUndefined());
637
+ return *one + args[0].getNumber() + args[1].getNumber();
638
+ });
639
+
640
+ EXPECT_EQ(plusOne.call(rt, 1, 2).getNumber(), 4);
641
+ EXPECT_TRUE(checkValue(plusOne.call(rt, 3, 5), "9"));
642
+ rt.global().setProperty(rt, "plusOne", plusOne);
643
+ EXPECT_TRUE(eval("plusOne(20, 300) == 321").getBool());
644
+
645
+ Function dot = Function::createFromHostFunction(
646
+ rt,
647
+ PropNameID::forAscii(rt, "dot"),
648
+ 2,
649
+ [](Runtime& rt, const Value& thisVal, const Value* args, size_t count) {
650
+ EXPECT_TRUE(
651
+ Value::strictEquals(rt, thisVal, rt.global()) ||
652
+ thisVal.isUndefined());
653
+ if (count != 2) {
654
+ throw std::runtime_error("expected 2 args");
655
+ }
656
+ std::string ret = args[0].getString(rt).utf8(rt) + "." +
657
+ args[1].getString(rt).utf8(rt);
658
+ return String::createFromUtf8(
659
+ rt, reinterpret_cast<const uint8_t*>(ret.data()), ret.size());
660
+ });
661
+
662
+ rt.global().setProperty(rt, "cons", dot);
663
+ EXPECT_TRUE(eval("cons('left', 'right') == 'left.right'").getBool());
664
+ EXPECT_TRUE(eval("cons.name == 'dot'").getBool());
665
+ EXPECT_TRUE(eval("cons.length == 2").getBool());
666
+ EXPECT_TRUE(eval("cons instanceof Function").getBool());
667
+
668
+ EXPECT_TRUE(eval("(function() {"
669
+ " try {"
670
+ " cons('fail'); return false;"
671
+ " } catch (e) {"
672
+ " return ((e instanceof Error) &&"
673
+ " (e.message == 'Exception in HostFunction: ' +"
674
+ " 'expected 2 args'));"
675
+ " }})()")
676
+ .getBool());
677
+
678
+ Function coolify = Function::createFromHostFunction(
679
+ rt,
680
+ PropNameID::forAscii(rt, "coolify"),
681
+ 0,
682
+ [](Runtime& rt, const Value& thisVal, const Value* args, size_t count) {
683
+ EXPECT_EQ(count, 0);
684
+ std::string ret = thisVal.toString(rt).utf8(rt) + " is cool";
685
+ return String::createFromUtf8(
686
+ rt, reinterpret_cast<const uint8_t*>(ret.data()), ret.size());
687
+ });
688
+ rt.global().setProperty(rt, "coolify", coolify);
689
+ EXPECT_TRUE(eval("coolify.name == 'coolify'").getBool());
690
+ EXPECT_TRUE(eval("coolify.length == 0").getBool());
691
+ EXPECT_TRUE(eval("coolify.bind('R&M')() == 'R&M is cool'").getBool());
692
+ EXPECT_TRUE(eval("(function() {"
693
+ " var s = coolify.bind(function(){})();"
694
+ " return s.lastIndexOf(' is cool') == (s.length - 8);"
695
+ "})()")
696
+ .getBool());
697
+
698
+ Function lookAtMe = Function::createFromHostFunction(
699
+ rt,
700
+ PropNameID::forAscii(rt, "lookAtMe"),
701
+ 0,
702
+ [](Runtime& rt, const Value& thisVal, const Value* args, size_t count)
703
+ -> Value {
704
+ EXPECT_TRUE(thisVal.isObject());
705
+ EXPECT_EQ(
706
+ thisVal.getObject(rt)
707
+ .getProperty(rt, "name")
708
+ .getString(rt)
709
+ .utf8(rt),
710
+ "mr.meeseeks");
711
+ return Value();
712
+ });
713
+ rt.global().setProperty(rt, "lookAtMe", lookAtMe);
714
+ EXPECT_TRUE(eval("lookAtMe.bind({'name': 'mr.meeseeks'})()").isUndefined());
715
+
716
+ struct Callable {
717
+ Callable(std::string s) : str(s) {}
718
+
719
+ Value
720
+ operator()(Runtime& rt, const Value&, const Value* args, size_t count) {
721
+ if (count != 1) {
722
+ return Value();
723
+ }
724
+ return String::createFromUtf8(
725
+ rt, args[0].toString(rt).utf8(rt) + " was called with " + str);
726
+ }
727
+
728
+ std::string str;
729
+ };
730
+
731
+ Function callable = Function::createFromHostFunction(
732
+ rt,
733
+ PropNameID::forAscii(rt, "callable"),
734
+ 1,
735
+ Callable("std::function::target"));
736
+ EXPECT_EQ(
737
+ function("function (f) { return f('A cat'); }")
738
+ .call(rt, callable)
739
+ .getString(rt)
740
+ .utf8(rt),
741
+ "A cat was called with std::function::target");
742
+ EXPECT_TRUE(callable.isHostFunction(rt));
743
+ EXPECT_NE(callable.getHostFunction(rt).target<Callable>(), nullptr);
744
+
745
+ std::string strval = "strval1";
746
+ auto getter = Object(rt);
747
+ getter.setProperty(
748
+ rt,
749
+ "get",
750
+ Function::createFromHostFunction(
751
+ rt,
752
+ PropNameID::forAscii(rt, "getter"),
753
+ 1,
754
+ [&strval](
755
+ Runtime& rt,
756
+ const Value& thisVal,
757
+ const Value* args,
758
+ size_t count) -> Value {
759
+ return String::createFromUtf8(rt, strval);
760
+ }));
761
+ auto obj = Object(rt);
762
+ rt.global()
763
+ .getPropertyAsObject(rt, "Object")
764
+ .getPropertyAsFunction(rt, "defineProperty")
765
+ .call(rt, obj, "prop", getter);
766
+ EXPECT_TRUE(function("function(value) { return value.prop == 'strval1'; }")
767
+ .call(rt, obj)
768
+ .getBool());
769
+ strval = "strval2";
770
+ EXPECT_TRUE(function("function(value) { return value.prop == 'strval2'; }")
771
+ .call(rt, obj)
772
+ .getBool());
773
+ }
774
+
775
+ TEST_P(JSITest, ValueTest) {
776
+ EXPECT_TRUE(checkValue(Value::undefined(), "undefined"));
777
+ EXPECT_TRUE(checkValue(Value(), "undefined"));
778
+ EXPECT_TRUE(checkValue(Value::null(), "null"));
779
+ EXPECT_TRUE(checkValue(nullptr, "null"));
780
+
781
+ EXPECT_TRUE(checkValue(Value(false), "false"));
782
+ EXPECT_TRUE(checkValue(false, "false"));
783
+ EXPECT_TRUE(checkValue(true, "true"));
784
+
785
+ EXPECT_TRUE(checkValue(Value(1.5), "1.5"));
786
+ EXPECT_TRUE(checkValue(2.5, "2.5"));
787
+
788
+ EXPECT_TRUE(checkValue(Value(10), "10"));
789
+ EXPECT_TRUE(checkValue(20, "20"));
790
+ EXPECT_TRUE(checkValue(30, "30"));
791
+
792
+ // rvalue implicit conversion
793
+ EXPECT_TRUE(checkValue(String::createFromAscii(rt, "one"), "'one'"));
794
+ // lvalue explicit copy
795
+ String s = String::createFromAscii(rt, "two");
796
+ EXPECT_TRUE(checkValue(Value(rt, s), "'two'"));
797
+
798
+ {
799
+ // rvalue assignment of trivial value
800
+ Value v1 = 100;
801
+ Value v2 = String::createFromAscii(rt, "hundred");
802
+ v2 = std::move(v1);
803
+ EXPECT_TRUE(v2.isNumber());
804
+ EXPECT_EQ(v2.getNumber(), 100);
805
+ }
806
+
807
+ {
808
+ // rvalue assignment of js heap value
809
+ Value v1 = String::createFromAscii(rt, "hundred");
810
+ Value v2 = 100;
811
+ v2 = std::move(v1);
812
+ EXPECT_TRUE(v2.isString());
813
+ EXPECT_EQ(v2.getString(rt).utf8(rt), "hundred");
814
+ }
815
+
816
+ Object o = Object(rt);
817
+ EXPECT_TRUE(function("function(value) { return typeof(value) == 'object'; }")
818
+ .call(rt, Value(rt, o))
819
+ .getBool());
820
+
821
+ uint8_t utf8[] = "[null, 2, \"c\", \"emoji: \xf0\x9f\x86\x97\", {}]";
822
+
823
+ EXPECT_TRUE(
824
+ function("function (arr) { return "
825
+ "Array.isArray(arr) && "
826
+ "arr.length == 5 && "
827
+ "arr[0] === null && "
828
+ "arr[1] == 2 && "
829
+ "arr[2] == 'c' && "
830
+ "arr[3] == 'emoji: \\uD83C\\uDD97' && "
831
+ "typeof arr[4] == 'object'; }")
832
+ .call(rt, Value::createFromJsonUtf8(rt, utf8, sizeof(utf8) - 1))
833
+ .getBool());
834
+
835
+ EXPECT_TRUE(eval("undefined").isUndefined());
836
+ EXPECT_TRUE(eval("null").isNull());
837
+ EXPECT_TRUE(eval("true").isBool());
838
+ EXPECT_TRUE(eval("false").isBool());
839
+ EXPECT_TRUE(eval("123").isNumber());
840
+ EXPECT_TRUE(eval("123.4").isNumber());
841
+ EXPECT_TRUE(eval("'str'").isString());
842
+ // "{}" returns undefined. empty code block?
843
+ EXPECT_TRUE(eval("({})").isObject());
844
+ EXPECT_TRUE(eval("[]").isObject());
845
+ EXPECT_TRUE(eval("(function(){})").isObject());
846
+
847
+ EXPECT_EQ(eval("123").getNumber(), 123);
848
+ EXPECT_EQ(eval("123.4").getNumber(), 123.4);
849
+ EXPECT_EQ(eval("'str'").getString(rt).utf8(rt), "str");
850
+ EXPECT_TRUE(eval("[]").getObject(rt).isArray(rt));
851
+
852
+ EXPECT_TRUE(eval("true").asBool());
853
+ EXPECT_THROW(eval("123").asBool(), JSIException);
854
+ EXPECT_EQ(eval("456").asNumber(), 456);
855
+ EXPECT_THROW(eval("'word'").asNumber(), JSIException);
856
+ EXPECT_EQ(
857
+ eval("({1:2, 3:4})").asObject(rt).getProperty(rt, "1").getNumber(), 2);
858
+ EXPECT_THROW(eval("'oops'").asObject(rt), JSIException);
859
+
860
+ EXPECT_EQ(eval("['zero',1,2,3]").toString(rt).utf8(rt), "zero,1,2,3");
861
+ }
862
+
863
+ TEST_P(JSITest, EqualsTest) {
864
+ EXPECT_TRUE(Object::strictEquals(rt, rt.global(), rt.global()));
865
+ EXPECT_TRUE(Value::strictEquals(rt, 1, 1));
866
+ EXPECT_FALSE(Value::strictEquals(rt, true, 1));
867
+ EXPECT_FALSE(Value::strictEquals(rt, true, false));
868
+ EXPECT_TRUE(Value::strictEquals(rt, false, false));
869
+ EXPECT_FALSE(Value::strictEquals(rt, nullptr, 1));
870
+ EXPECT_TRUE(Value::strictEquals(rt, nullptr, nullptr));
871
+ EXPECT_TRUE(Value::strictEquals(rt, Value::undefined(), Value()));
872
+ EXPECT_TRUE(Value::strictEquals(rt, rt.global(), Value(rt.global())));
873
+ EXPECT_FALSE(Value::strictEquals(
874
+ rt,
875
+ std::numeric_limits<double>::quiet_NaN(),
876
+ std::numeric_limits<double>::quiet_NaN()));
877
+ EXPECT_FALSE(Value::strictEquals(
878
+ rt,
879
+ std::numeric_limits<double>::signaling_NaN(),
880
+ std::numeric_limits<double>::signaling_NaN()));
881
+ EXPECT_TRUE(Value::strictEquals(rt, +0.0, -0.0));
882
+ EXPECT_TRUE(Value::strictEquals(rt, -0.0, +0.0));
883
+
884
+ Function noop = Function::createFromHostFunction(
885
+ rt,
886
+ PropNameID::forAscii(rt, "noop"),
887
+ 0,
888
+ [](const Runtime&, const Value&, const Value*, size_t) {
889
+ return Value();
890
+ });
891
+ auto noopDup = Value(rt, noop).getObject(rt);
892
+ EXPECT_TRUE(Object::strictEquals(rt, noop, noopDup));
893
+ EXPECT_TRUE(Object::strictEquals(rt, noopDup, noop));
894
+ EXPECT_FALSE(Object::strictEquals(rt, noop, rt.global()));
895
+ EXPECT_TRUE(Object::strictEquals(rt, noop, noop));
896
+ EXPECT_TRUE(Value::strictEquals(rt, Value(rt, noop), Value(rt, noop)));
897
+
898
+ String str = String::createFromAscii(rt, "rick");
899
+ String strDup = String::createFromAscii(rt, "rick");
900
+ String otherStr = String::createFromAscii(rt, "morty");
901
+ EXPECT_TRUE(String::strictEquals(rt, str, str));
902
+ EXPECT_TRUE(String::strictEquals(rt, str, strDup));
903
+ EXPECT_TRUE(String::strictEquals(rt, strDup, str));
904
+ EXPECT_FALSE(String::strictEquals(rt, str, otherStr));
905
+ EXPECT_TRUE(Value::strictEquals(rt, Value(rt, str), Value(rt, str)));
906
+ EXPECT_FALSE(Value::strictEquals(rt, Value(rt, str), Value(rt, noop)));
907
+ EXPECT_FALSE(Value::strictEquals(rt, Value(rt, str), 1.0));
908
+ }
909
+
910
+ TEST_P(JSITest, ExceptionStackTraceTest) {
911
+ static const char invokeUndefinedScript[] =
912
+ "function hello() {"
913
+ " var a = {}; a.log(); }"
914
+ "function world() { hello(); }"
915
+ "world()";
916
+ std::string stack;
917
+ try {
918
+ rt.evaluateJavaScript(
919
+ std::make_unique<StringBuffer>(invokeUndefinedScript), "");
920
+ } catch (JSError& e) {
921
+ stack = e.getStack();
922
+ }
923
+ EXPECT_NE(stack.find("world"), std::string::npos);
924
+ }
925
+
926
+ TEST_P(JSITest, PreparedJavaScriptSourceTest) {
927
+ rt.evaluateJavaScript(std::make_unique<StringBuffer>("var q = 0;"), "");
928
+ auto prep = rt.prepareJavaScript(std::make_unique<StringBuffer>("q++;"), "");
929
+ EXPECT_EQ(rt.global().getProperty(rt, "q").getNumber(), 0);
930
+ rt.evaluatePreparedJavaScript(prep);
931
+ EXPECT_EQ(rt.global().getProperty(rt, "q").getNumber(), 1);
932
+ rt.evaluatePreparedJavaScript(prep);
933
+ EXPECT_EQ(rt.global().getProperty(rt, "q").getNumber(), 2);
934
+ }
935
+
936
+ TEST_P(JSITest, PreparedJavaScriptURLInBacktrace) {
937
+ std::string sourceURL = "//PreparedJavaScriptURLInBacktrace/Test/URL";
938
+ std::string throwingSource =
939
+ "function thrower() { throw new Error('oops')}"
940
+ "thrower();";
941
+ auto prep = rt.prepareJavaScript(
942
+ std::make_unique<StringBuffer>(throwingSource), sourceURL);
943
+ try {
944
+ rt.evaluatePreparedJavaScript(prep);
945
+ FAIL() << "prepareJavaScript should have thrown an exception";
946
+ } catch (facebook::jsi::JSError err) {
947
+ EXPECT_NE(std::string::npos, err.getStack().find(sourceURL))
948
+ << "Backtrace should contain source URL";
949
+ }
950
+ }
951
+
952
+ namespace {
953
+
954
+ unsigned countOccurences(const std::string& of, const std::string& in) {
955
+ unsigned occurences = 0;
956
+ std::string::size_type lastOccurence = -1;
957
+ while ((lastOccurence = in.find(of, lastOccurence + 1)) !=
958
+ std::string::npos) {
959
+ occurences++;
960
+ }
961
+ return occurences;
962
+ }
963
+
964
+ } // namespace
965
+
966
+ TEST_P(JSITest, JSErrorsArePropagatedNicely) {
967
+ unsigned callsBeforeError = 5;
968
+
969
+ Function sometimesThrows = function(
970
+ "function sometimesThrows(shouldThrow, callback) {"
971
+ " if (shouldThrow) {"
972
+ " throw Error('Omg, what a nasty exception')"
973
+ " }"
974
+ " callback(callback);"
975
+ "}");
976
+
977
+ Function callback = Function::createFromHostFunction(
978
+ rt,
979
+ PropNameID::forAscii(rt, "callback"),
980
+ 0,
981
+ [&sometimesThrows, &callsBeforeError](
982
+ Runtime& rt, const Value& thisVal, const Value* args, size_t count) {
983
+ return sometimesThrows.call(rt, --callsBeforeError == 0, args[0]);
984
+ });
985
+
986
+ try {
987
+ sometimesThrows.call(rt, false, callback);
988
+ } catch (JSError& error) {
989
+ EXPECT_EQ(error.getMessage(), "Omg, what a nasty exception");
990
+ EXPECT_EQ(countOccurences("sometimesThrows", error.getStack()), 6);
991
+
992
+ // system JSC JSI does not implement host function names
993
+ // EXPECT_EQ(countOccurences("callback", error.getStack(rt)), 5);
994
+ }
995
+ }
996
+
997
+ TEST_P(JSITest, JSErrorsCanBeConstructedWithStack) {
998
+ auto err = JSError(rt, "message", "stack");
999
+ EXPECT_EQ(err.getMessage(), "message");
1000
+ EXPECT_EQ(err.getStack(), "stack");
1001
+ }
1002
+
1003
+ TEST_P(JSITest, JSErrorDoesNotInfinitelyRecurse) {
1004
+ Value globalError = rt.global().getProperty(rt, "Error");
1005
+ rt.global().setProperty(rt, "Error", Value::undefined());
1006
+ try {
1007
+ rt.global().getPropertyAsFunction(rt, "NotAFunction");
1008
+ FAIL() << "expected exception";
1009
+ } catch (const JSError& ex) {
1010
+ EXPECT_EQ(
1011
+ ex.getMessage(),
1012
+ "callGlobalFunction: JS global property 'Error' is undefined, "
1013
+ "expected a Function (while raising getPropertyAsObject: "
1014
+ "property 'NotAFunction' is undefined, expected an Object)");
1015
+ }
1016
+
1017
+ // If Error is missing, this is fundamentally a problem with JS code
1018
+ // messing up the global object, so it should present in JS code as
1019
+ // a catchable string. Not an Error (because that's broken), or as
1020
+ // a C++ failure.
1021
+
1022
+ auto fails = [](Runtime& rt, const Value&, const Value*, size_t) -> Value {
1023
+ return rt.global().getPropertyAsObject(rt, "NotAProperty");
1024
+ };
1025
+ EXPECT_EQ(
1026
+ function("function (f) { try { f(); return 'undefined'; }"
1027
+ "catch (e) { return typeof e; } }")
1028
+ .call(
1029
+ rt,
1030
+ Function::createFromHostFunction(
1031
+ rt, PropNameID::forAscii(rt, "fails"), 0, fails))
1032
+ .getString(rt)
1033
+ .utf8(rt),
1034
+ "string");
1035
+
1036
+ rt.global().setProperty(rt, "Error", globalError);
1037
+ }
1038
+
1039
+ TEST_P(JSITest, JSErrorStackOverflowHandling) {
1040
+ rt.global().setProperty(
1041
+ rt,
1042
+ "callSomething",
1043
+ Function::createFromHostFunction(
1044
+ rt,
1045
+ PropNameID::forAscii(rt, "callSomething"),
1046
+ 0,
1047
+ [this](
1048
+ Runtime& rt2,
1049
+ const Value& thisVal,
1050
+ const Value* args,
1051
+ size_t count) {
1052
+ EXPECT_EQ(&rt, &rt2);
1053
+ return function("function() { return 0; }").call(rt);
1054
+ }));
1055
+ try {
1056
+ eval("(function f() { callSomething(); f.apply(); })()");
1057
+ FAIL();
1058
+ } catch (const JSError& ex) {
1059
+ EXPECT_NE(std::string(ex.what()).find("exceeded"), std::string::npos);
1060
+ }
1061
+ }
1062
+
1063
+ TEST_P(JSITest, ScopeDoesNotCrashTest) {
1064
+ Scope scope(rt);
1065
+ Object o(rt);
1066
+ }
1067
+
1068
+ TEST_P(JSITest, ScopeDoesNotCrashWhenValueEscapes) {
1069
+ Value v;
1070
+ Scope::callInNewScope(rt, [&]() {
1071
+ Object o(rt);
1072
+ o.setProperty(rt, "a", 5);
1073
+ v = std::move(o);
1074
+ });
1075
+ EXPECT_EQ(v.getObject(rt).getProperty(rt, "a").getNumber(), 5);
1076
+ }
1077
+
1078
+ // Verifies you can have a host object that emulates a normal object
1079
+ TEST_P(JSITest, HostObjectWithValueMembers) {
1080
+ class Bag : public HostObject {
1081
+ public:
1082
+ Bag() = default;
1083
+
1084
+ const Value& operator[](const std::string& name) const {
1085
+ auto iter = data_.find(name);
1086
+ if (iter == data_.end()) {
1087
+ return undef_;
1088
+ }
1089
+ return iter->second;
1090
+ }
1091
+
1092
+ protected:
1093
+ Value get(Runtime& rt, const PropNameID& name) override {
1094
+ return Value(rt, (*this)[name.utf8(rt)]);
1095
+ }
1096
+
1097
+ void set(Runtime& rt, const PropNameID& name, const Value& val) override {
1098
+ data_.emplace(name.utf8(rt), Value(rt, val));
1099
+ }
1100
+
1101
+ Value undef_;
1102
+ std::map<std::string, Value> data_;
1103
+ };
1104
+
1105
+ auto sharedBag = std::make_shared<Bag>();
1106
+ auto& bag = *sharedBag;
1107
+ Object jsbag = Object::createFromHostObject(rt, std::move(sharedBag));
1108
+ auto set = function(
1109
+ "function (o) {"
1110
+ " o.foo = 'bar';"
1111
+ " o.count = 37;"
1112
+ " o.nul = null;"
1113
+ " o.iscool = true;"
1114
+ " o.obj = { 'foo': 'bar' };"
1115
+ "}");
1116
+ set.call(rt, jsbag);
1117
+ auto checkFoo = function("function (o) { return o.foo === 'bar'; }");
1118
+ auto checkCount = function("function (o) { return o.count === 37; }");
1119
+ auto checkNul = function("function (o) { return o.nul === null; }");
1120
+ auto checkIsCool = function("function (o) { return o.iscool === true; }");
1121
+ auto checkObj = function(
1122
+ "function (o) {"
1123
+ " return (typeof o.obj) === 'object' && o.obj.foo === 'bar';"
1124
+ "}");
1125
+ // Check this looks good from js
1126
+ EXPECT_TRUE(checkFoo.call(rt, jsbag).getBool());
1127
+ EXPECT_TRUE(checkCount.call(rt, jsbag).getBool());
1128
+ EXPECT_TRUE(checkNul.call(rt, jsbag).getBool());
1129
+ EXPECT_TRUE(checkIsCool.call(rt, jsbag).getBool());
1130
+ EXPECT_TRUE(checkObj.call(rt, jsbag).getBool());
1131
+
1132
+ // Check this looks good from c++
1133
+ EXPECT_EQ(bag["foo"].getString(rt).utf8(rt), "bar");
1134
+ EXPECT_EQ(bag["count"].getNumber(), 37);
1135
+ EXPECT_TRUE(bag["nul"].isNull());
1136
+ EXPECT_TRUE(bag["iscool"].getBool());
1137
+ EXPECT_EQ(
1138
+ bag["obj"].getObject(rt).getProperty(rt, "foo").getString(rt).utf8(rt),
1139
+ "bar");
1140
+ }
1141
+
1142
+ TEST_P(JSITest, DecoratorTest) {
1143
+ struct Count {
1144
+ // init here is just to show that a With type does not need to be
1145
+ // default constructible.
1146
+ explicit Count(int init) : count(init) {}
1147
+
1148
+ // Test optional before method.
1149
+
1150
+ void after() {
1151
+ ++count;
1152
+ }
1153
+
1154
+ int count;
1155
+ };
1156
+
1157
+ static constexpr int kInit = 17;
1158
+
1159
+ class CountRuntime final : public WithRuntimeDecorator<Count> {
1160
+ public:
1161
+ explicit CountRuntime(std::unique_ptr<Runtime> rt)
1162
+ : WithRuntimeDecorator<Count>(*rt, count_),
1163
+ rt_(std::move(rt)),
1164
+ count_(kInit) {}
1165
+
1166
+ int count() {
1167
+ return count_.count;
1168
+ }
1169
+
1170
+ private:
1171
+ std::unique_ptr<Runtime> rt_;
1172
+ Count count_;
1173
+ };
1174
+
1175
+ CountRuntime crt(factory());
1176
+
1177
+ crt.description();
1178
+ EXPECT_EQ(crt.count(), kInit + 1);
1179
+
1180
+ crt.global().setProperty(crt, "o", Object(crt));
1181
+ EXPECT_EQ(crt.count(), kInit + 6);
1182
+ }
1183
+
1184
+ TEST_P(JSITest, MultiDecoratorTest) {
1185
+ struct Inc {
1186
+ void before() {
1187
+ ++count;
1188
+ }
1189
+
1190
+ // Test optional after method.
1191
+
1192
+ int count = 0;
1193
+ };
1194
+
1195
+ struct Nest {
1196
+ void before() {
1197
+ ++nest;
1198
+ }
1199
+
1200
+ void after() {
1201
+ --nest;
1202
+ }
1203
+
1204
+ int nest = 0;
1205
+ };
1206
+
1207
+ class MultiRuntime final
1208
+ : public WithRuntimeDecorator<std::tuple<Inc, Nest>> {
1209
+ public:
1210
+ explicit MultiRuntime(std::unique_ptr<Runtime> rt)
1211
+ : WithRuntimeDecorator<std::tuple<Inc, Nest>>(*rt, tuple_),
1212
+ rt_(std::move(rt)) {}
1213
+
1214
+ int count() {
1215
+ return std::get<0>(tuple_).count;
1216
+ }
1217
+ int nest() {
1218
+ return std::get<1>(tuple_).nest;
1219
+ }
1220
+
1221
+ private:
1222
+ std::unique_ptr<Runtime> rt_;
1223
+ std::tuple<Inc, Nest> tuple_;
1224
+ };
1225
+
1226
+ MultiRuntime mrt(factory());
1227
+
1228
+ Function expectNestOne = Function::createFromHostFunction(
1229
+ mrt,
1230
+ PropNameID::forAscii(mrt, "expectNestOne"),
1231
+ 0,
1232
+ [](Runtime& rt, const Value& thisVal, const Value* args, size_t count) {
1233
+ MultiRuntime* funcmrt = dynamic_cast<MultiRuntime*>(&rt);
1234
+ EXPECT_NE(funcmrt, nullptr);
1235
+ EXPECT_EQ(funcmrt->count(), 3);
1236
+ EXPECT_EQ(funcmrt->nest(), 1);
1237
+ return Value::undefined();
1238
+ });
1239
+
1240
+ expectNestOne.call(mrt);
1241
+
1242
+ EXPECT_EQ(mrt.count(), 3);
1243
+ EXPECT_EQ(mrt.nest(), 0);
1244
+ }
1245
+
1246
+ TEST_P(JSITest, SymbolTest) {
1247
+ if (!rt.global().hasProperty(rt, "Symbol")) {
1248
+ // Symbol is an es6 feature which doesn't exist in older VMs. So
1249
+ // the tests which might be elsewhere are all here so they can be
1250
+ // skipped.
1251
+ return;
1252
+ }
1253
+
1254
+ // ObjectTest
1255
+ eval("x = {1:2, 'three':Symbol('four')}");
1256
+ Object x = rt.global().getPropertyAsObject(rt, "x");
1257
+ EXPECT_EQ(x.getPropertyNames(rt).size(rt), 2);
1258
+ EXPECT_TRUE(x.hasProperty(rt, "three"));
1259
+ EXPECT_EQ(
1260
+ x.getProperty(rt, "three").getSymbol(rt).toString(rt), "Symbol(four)");
1261
+
1262
+ // ValueTest
1263
+ EXPECT_TRUE(eval("Symbol('sym')").isSymbol());
1264
+ EXPECT_EQ(eval("Symbol('sym')").getSymbol(rt).toString(rt), "Symbol(sym)");
1265
+
1266
+ // EqualsTest
1267
+ EXPECT_FALSE(Symbol::strictEquals(
1268
+ rt,
1269
+ eval("Symbol('a')").getSymbol(rt),
1270
+ eval("Symbol('a')").getSymbol(rt)));
1271
+ EXPECT_TRUE(Symbol::strictEquals(
1272
+ rt,
1273
+ eval("Symbol.for('a')").getSymbol(rt),
1274
+ eval("Symbol.for('a')").getSymbol(rt)));
1275
+ EXPECT_FALSE(
1276
+ Value::strictEquals(rt, eval("Symbol('a')"), eval("Symbol('a')")));
1277
+ EXPECT_TRUE(Value::strictEquals(
1278
+ rt, eval("Symbol.for('a')"), eval("Symbol.for('a')")));
1279
+ EXPECT_FALSE(Value::strictEquals(rt, eval("Symbol('a')"), eval("'a'")));
1280
+ }
1281
+
1282
+ TEST_P(JSITest, JSErrorTest) {
1283
+ // JSError creation can lead to further errors. Make sure these
1284
+ // cases are handled and don't cause weird crashes or other issues.
1285
+ //
1286
+ // Getting message property can throw
1287
+
1288
+ EXPECT_THROW(
1289
+ eval("var GetMessageThrows = {get message() { throw Error('ex'); }};"
1290
+ "throw GetMessageThrows;"),
1291
+ JSIException);
1292
+
1293
+ EXPECT_THROW(
1294
+ eval("var GetMessageThrows = {get message() { throw GetMessageThrows; }};"
1295
+ "throw GetMessageThrows;"),
1296
+ JSIException);
1297
+
1298
+ // Converting exception message to String can throw
1299
+
1300
+ EXPECT_THROW(
1301
+ eval(
1302
+ "Object.defineProperty("
1303
+ " globalThis, 'String', {configurable:true, get() { var e = Error(); e.message = 23; throw e; }});"
1304
+ "var e = Error();"
1305
+ "e.message = 17;"
1306
+ "throw e;"),
1307
+ JSIException);
1308
+
1309
+ EXPECT_THROW(
1310
+ eval(
1311
+ "var e = Error();"
1312
+ "Object.defineProperty("
1313
+ " e, 'message', {configurable:true, get() { throw Error('getter'); }});"
1314
+ "throw e;"),
1315
+ JSIException);
1316
+
1317
+ EXPECT_THROW(
1318
+ eval("var e = Error();"
1319
+ "String = function() { throw Error('ctor'); };"
1320
+ "throw e;"),
1321
+ JSIException);
1322
+
1323
+ // Converting an exception message to String can return a non-String
1324
+
1325
+ EXPECT_THROW(
1326
+ eval("String = function() { return 42; };"
1327
+ "var e = Error();"
1328
+ "e.message = 17;"
1329
+ "throw e;"),
1330
+ JSIException);
1331
+
1332
+ // Exception can be non-Object
1333
+
1334
+ EXPECT_THROW(eval("throw 17;"), JSIException);
1335
+
1336
+ EXPECT_THROW(eval("throw undefined;"), JSIException);
1337
+
1338
+ // Converting exception with no message or stack property to String can throw
1339
+
1340
+ EXPECT_THROW(
1341
+ eval("var e = {toString() { throw new Error('errstr'); }};"
1342
+ "throw e;"),
1343
+ JSIException);
1344
+ }
1345
+
1346
+ //----------------------------------------------------------------------
1347
+ // Test that multiple levels of delegation in DecoratedHostObjects works.
1348
+
1349
+ class RD1 : public RuntimeDecorator<Runtime, Runtime> {
1350
+ public:
1351
+ RD1(Runtime& plain) : RuntimeDecorator(plain) {}
1352
+
1353
+ Object createObject(std::shared_ptr<HostObject> ho) {
1354
+ class DHO1 : public DecoratedHostObject {
1355
+ public:
1356
+ using DecoratedHostObject::DecoratedHostObject;
1357
+
1358
+ Value get(Runtime& rt, const PropNameID& name) override {
1359
+ numGets++;
1360
+ return DecoratedHostObject::get(rt, name);
1361
+ }
1362
+ };
1363
+ return Object::createFromHostObject(
1364
+ plain(), std::make_shared<DHO1>(*this, ho));
1365
+ }
1366
+
1367
+ static unsigned numGets;
1368
+ };
1369
+
1370
+ class RD2 : public RuntimeDecorator<Runtime, Runtime> {
1371
+ public:
1372
+ RD2(Runtime& plain) : RuntimeDecorator(plain) {}
1373
+
1374
+ Object createObject(std::shared_ptr<HostObject> ho) {
1375
+ class DHO2 : public DecoratedHostObject {
1376
+ public:
1377
+ using DecoratedHostObject::DecoratedHostObject;
1378
+
1379
+ Value get(Runtime& rt, const PropNameID& name) override {
1380
+ numGets++;
1381
+ return DecoratedHostObject::get(rt, name);
1382
+ }
1383
+ };
1384
+ return Object::createFromHostObject(
1385
+ plain(), std::make_shared<DHO2>(*this, ho));
1386
+ }
1387
+
1388
+ static unsigned numGets;
1389
+ };
1390
+
1391
+ class HO : public HostObject {
1392
+ public:
1393
+ explicit HO(Runtime* expectedRT) : expectedRT_(expectedRT) {}
1394
+
1395
+ Value get(Runtime& rt, const PropNameID& name) override {
1396
+ EXPECT_EQ(expectedRT_, &rt);
1397
+ return Value(17.0);
1398
+ }
1399
+
1400
+ private:
1401
+ // The runtime we expect to be called with.
1402
+ Runtime* expectedRT_;
1403
+ };
1404
+
1405
+ unsigned RD1::numGets = 0;
1406
+ unsigned RD2::numGets = 0;
1407
+
1408
+ TEST_P(JSITest, MultilevelDecoratedHostObject) {
1409
+ // This test will be run for various test instantiations, so initialize these
1410
+ // counters.
1411
+ RD1::numGets = 0;
1412
+ RD2::numGets = 0;
1413
+
1414
+ RD1 rd1(rt);
1415
+ RD2 rd2(rd1);
1416
+ // We expect the "get" operation of ho to be called with rd2.
1417
+ auto ho = std::make_shared<HO>(&rd2);
1418
+ auto obj = Object::createFromHostObject(rd2, ho);
1419
+ Value v = obj.getProperty(rd2, "p");
1420
+ EXPECT_TRUE(v.isNumber());
1421
+ EXPECT_EQ(17.0, v.asNumber());
1422
+ auto ho2 = obj.getHostObject(rd2);
1423
+ EXPECT_EQ(ho, ho2);
1424
+ EXPECT_EQ(1, RD1::numGets);
1425
+ EXPECT_EQ(1, RD2::numGets);
1426
+ }
1427
+
1428
+ INSTANTIATE_TEST_CASE_P(
1429
+ Runtimes,
1430
+ JSITest,
1431
+ ::testing::ValuesIn(runtimeGenerators()));