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.
- package/.flowconfig +1 -3
- package/Chakra/ChakraHelpers.cpp +0 -1
- package/Directory.Build.props +3 -0
- package/Directory.Build.targets +1 -1
- package/Folly/TEMP_UntilFollyUpdate/dynamic-inl.h +1411 -0
- package/Folly/TEMP_UntilFollyUpdate/lang/ToAscii.cpp +336 -0
- package/Folly/TEMP_UntilFollyUpdate/lang/ToAscii.h +182 -0
- package/Libraries/ActionSheetIOS/ActionSheetIOS.js +7 -0
- package/Libraries/ActionSheetIOS/NativeActionSheetManager.js +1 -0
- package/Libraries/Alert/Alert.windows.js +2 -2
- package/Libraries/Animated/AnimatedImplementation.js +1 -1
- package/Libraries/Animated/NativeAnimatedHelper.js +55 -9
- package/Libraries/Animated/NativeAnimatedModule.js +1 -0
- package/Libraries/Animated/NativeAnimatedTurboModule.js +1 -0
- package/Libraries/Animated/animations/TimingAnimation.js +6 -11
- package/Libraries/Animated/createAnimatedComponent.js +2 -2
- package/Libraries/Animated/nodes/AnimatedColor.js +95 -29
- package/Libraries/Animated/nodes/AnimatedInterpolation.js +19 -22
- package/Libraries/Animated/nodes/AnimatedNode.js +2 -2
- package/Libraries/Animated/nodes/AnimatedValue.js +1 -1
- package/Libraries/AppState/AppState.js +1 -1
- package/Libraries/Blob/URL.js +7 -1
- package/Libraries/Components/Button.js +3 -0
- package/Libraries/Components/Button.windows.js +4 -0
- package/Libraries/Components/DatePickerAndroid/NativeDatePickerAndroid.js +5 -0
- package/Libraries/Components/Pressable/Pressable.js +3 -3
- package/Libraries/Components/Pressable/Pressable.windows.js +3 -3
- package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +47 -38
- package/Libraries/Components/ScrollView/ScrollContentViewNativeComponent.js +15 -7
- package/Libraries/Components/ScrollView/ScrollView.js +1 -1
- package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +16 -3
- package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +3 -1
- package/Libraries/Components/Slider/Slider.js +0 -2
- package/Libraries/Components/Slider/SliderNativeComponent.js +0 -1
- package/Libraries/Components/StatusBar/StatusBar.js +6 -1
- package/Libraries/Components/Switch/Switch.js +11 -1
- package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +114 -109
- package/Libraries/Components/TextInput/RCTMultilineTextInputNativeComponent.js +17 -9
- package/Libraries/Components/TextInput/RCTSingelineTextInputNativeComponent.js +13 -5
- package/Libraries/Components/TextInput/RCTTextInputViewConfig.js +10 -0
- package/Libraries/Components/TextInput/TextInput.js +1 -8
- package/Libraries/Components/TextInput/TextInput.windows.js +4 -9
- package/Libraries/Components/TextInput/TextInputState.js +10 -2
- package/Libraries/Components/TextInput/TextInputState.windows.js +10 -3
- package/Libraries/Components/TextInput/WindowsTextInputNativeComponent.js +1 -1
- package/Libraries/Components/Touchable/TouchableBounce.js +1 -0
- package/Libraries/Components/Touchable/TouchableHighlight.js +1 -0
- package/Libraries/Components/Touchable/TouchableHighlight.windows.js +6 -5
- package/Libraries/Components/Touchable/TouchableNativeFeedback.js +1 -0
- package/Libraries/Components/Touchable/TouchableOpacity.js +7 -1
- package/Libraries/Components/Touchable/TouchableOpacity.windows.js +11 -5
- package/Libraries/Components/Touchable/TouchableWithoutFeedback.js +2 -0
- package/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js +2 -0
- package/Libraries/Components/View/ReactNativeViewAttributes.js +1 -0
- package/Libraries/Components/View/ReactNativeViewAttributes.windows.js +1 -0
- package/Libraries/Components/View/View.windows.js +33 -1
- package/Libraries/Components/View/ViewNativeComponent.js +68 -8
- package/Libraries/Components/View/ViewPropTypes.js +36 -4
- package/Libraries/Components/View/ViewPropTypes.windows.js +36 -4
- package/Libraries/Core/Devtools/parseHermesStack.js +1 -1
- package/Libraries/Core/ExceptionsManager.js +1 -1
- package/Libraries/Core/RawEventEmitter.js +38 -0
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/Libraries/Core/polyfillPromise.js +32 -0
- package/Libraries/Core/setUpReactDevTools.js +3 -2
- package/Libraries/EventEmitter/NativeEventEmitter.js +3 -3
- package/Libraries/EventEmitter/RCTDeviceEventEmitter.js +2 -1
- package/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js +3 -3
- package/Libraries/Events/CustomEvent.js +32 -0
- package/Libraries/Events/EventPolyfill.js +239 -0
- package/Libraries/Image/Image.android.js +0 -6
- package/Libraries/Image/Image.ios.js +0 -6
- package/Libraries/Image/Image.windows.js +2 -8
- package/Libraries/Image/ImageViewNativeComponent.js +18 -3
- package/Libraries/Image/TextInlineImageNativeComponent.js +23 -15
- package/Libraries/Inspector/Inspector.js +2 -4
- package/Libraries/Interaction/BridgeSpyStallHandler.js +4 -3
- package/Libraries/Interaction/InteractionManager.js +1 -12
- package/Libraries/Interaction/TaskQueue.js +5 -4
- package/Libraries/LayoutAnimation/LayoutAnimation.js +13 -0
- package/Libraries/Linking/Linking.js +1 -1
- package/Libraries/Lists/FlatList.js +27 -6
- package/Libraries/Lists/VirtualizedList.js +71 -55
- package/Libraries/Lists/VirtualizedListContext.js +7 -3
- package/Libraries/Lists/VirtualizedSectionList.js +2 -2
- package/Libraries/Lists/__tests__/{FillRateHelper-test.windows.js → FillRateHelper-test.js} +2 -2
- package/Libraries/Lists/__tests__/{FlatList-test.windows.js → FlatList-test.js} +2 -2
- package/Libraries/Lists/__tests__/{SectionList-test.windows.js → SectionList-test.js} +14 -14
- package/Libraries/Lists/__tests__/{VirtualizeUtils-test.windows.js → VirtualizeUtils-test.js} +3 -3
- package/Libraries/Lists/__tests__/{VirtualizedList-test.windows.js → VirtualizedList-test.js} +91 -42
- package/Libraries/Lists/__tests__/{VirtualizedSectionList-test.windows.js → VirtualizedSectionList-test.js} +13 -13
- package/Libraries/LogBox/Data/LogBoxData.js +2 -2
- package/Libraries/LogBox/Data/LogBoxLog.js +1 -1
- package/Libraries/LogBox/Data/LogBoxSymbolication.js +1 -1
- package/Libraries/LogBox/Data/parseLogBoxLog.js +1 -1
- package/Libraries/LogBox/LogBox.js +2 -21
- package/Libraries/LogBox/UI/LogBoxInspectorFooter.js +1 -0
- package/Libraries/LogBox/UI/LogBoxInspectorHeader.js +2 -1
- package/Libraries/NativeComponent/BaseViewConfig.android.js +295 -0
- package/Libraries/NativeComponent/BaseViewConfig.ios.js +333 -0
- package/Libraries/NativeComponent/BaseViewConfig.windows.js +334 -0
- package/Libraries/NativeComponent/NativeComponentRegistry.js +0 -2
- package/Libraries/NativeComponent/PlatformBaseViewConfig.js +24 -0
- package/Libraries/NativeComponent/StaticViewConfigValidator.js +7 -42
- package/Libraries/NativeComponent/ViewConfig.js +4 -4
- package/Libraries/NativeComponent/ViewConfigIgnore.js +54 -0
- package/Libraries/Network/FormData.js +7 -1
- package/Libraries/Pressability/Pressability.js +115 -46
- package/Libraries/Pressability/Pressability.windows.js +190 -74
- package/Libraries/Pressability/PressabilityDebug.js +5 -9
- package/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js +1 -0
- package/Libraries/ReactNative/AppContainer.js +1 -1
- package/Libraries/ReactNative/{DummyUIManager.js → BridgelessUIManager.js} +62 -40
- package/Libraries/ReactNative/PaperUIManager.windows.js +5 -5
- package/Libraries/ReactNative/ReactNativeFeatureFlags.js +39 -0
- package/Libraries/ReactNative/UIManager.js +2 -3
- package/Libraries/ReactNative/renderApplication.js +4 -0
- package/Libraries/ReactPrivate/ReactNativePrivateInterface.js +8 -0
- package/Libraries/Renderer/implementations/ReactFabric-dev.js +5908 -4906
- package/Libraries/Renderer/implementations/ReactFabric-prod.js +2100 -1918
- package/Libraries/Renderer/implementations/ReactFabric-profiling.js +2567 -2352
- package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +5610 -4844
- package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +1710 -1556
- package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +1830 -1639
- package/Libraries/Renderer/shims/ReactNativeTypes.js +2 -1
- package/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +2 -1
- package/Libraries/StyleSheet/EdgeInsetsPropType.js +4 -1
- package/Libraries/StyleSheet/StyleSheetTypes.js +59 -66
- package/Libraries/StyleSheet/normalizeColor.js +1 -1
- package/Libraries/StyleSheet/private/_StyleSheetTypesOverrides.js +15 -0
- package/Libraries/StyleSheet/private/_TransformStyle.js +53 -0
- package/Libraries/StyleSheet/processTransform.windows.js +272 -0
- package/Libraries/Text/Text.js +13 -7
- package/Libraries/Text/Text.windows.js +16 -7
- package/Libraries/Text/TextNativeComponent.js +2 -0
- package/Libraries/Text/TextProps.js +10 -0
- package/Libraries/Types/CoreEventTypes.js +13 -1
- package/Libraries/Types/CoreEventTypes.windows.js +26 -1
- package/Libraries/Utilities/Appearance.js +0 -8
- package/Libraries/Utilities/HMRClient.js +1 -1
- package/Libraries/Utilities/ReactNativeTestTools.js +1 -0
- package/Libraries/Utilities/codegenNativeComponent.js +17 -6
- package/Libraries/Utilities/stringifySafe.js +4 -1
- package/Libraries/Utilities/verifyComponentAttributeEquivalence.js +3 -3
- package/Libraries/WebSocket/WebSocket.js +1 -1
- package/Libraries/vendor/emitter/_EmitterSubscription.js +1 -1
- package/Libraries/vendor/emitter/_EventEmitter.js +1 -1
- package/Libraries/vendor/emitter/_EventSubscription.js +1 -1
- package/Microsoft.ReactNative/Base/CoreNativeModules.cpp +1 -4
- package/Microsoft.ReactNative/DynamicReader.cpp +3 -3
- package/Microsoft.ReactNative/Fabric/ComponentView.h +1 -0
- package/Microsoft.ReactNative/Fabric/ComponentViewRegistry.cpp +36 -2
- package/Microsoft.ReactNative/Fabric/ComponentViewRegistry.h +1 -0
- package/Microsoft.ReactNative/Fabric/DWriteHelpers.cpp +19 -0
- package/Microsoft.ReactNative/Fabric/DWriteHelpers.h +13 -0
- package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +65 -19
- package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +2 -0
- package/Microsoft.ReactNative/Fabric/ParagraphComponentView.cpp +36 -10
- package/Microsoft.ReactNative/Fabric/ScrollViewComponentView.cpp +2 -0
- package/Microsoft.ReactNative/Fabric/SliderComponentView.cpp +107 -0
- package/Microsoft.ReactNative/Fabric/SliderComponentView.h +51 -0
- package/Microsoft.ReactNative/Fabric/SwitchComponentView.cpp +109 -0
- package/Microsoft.ReactNative/Fabric/SwitchComponentView.h +52 -0
- package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputComponentDescriptor.h +197 -0
- package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputComponentView.cpp +308 -0
- package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputComponentView.h +52 -0
- package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputEventEmitter.cpp +31 -0
- package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputEventEmitter.h +33 -0
- package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputProps.cpp +81 -0
- package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputProps.h +132 -0
- package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputShadowNode.cpp +193 -0
- package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputShadowNode.h +85 -0
- package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputState.cpp +76 -0
- package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputState.h +99 -0
- package/Microsoft.ReactNative/Fabric/ViewComponentView.cpp +35 -3
- package/Microsoft.ReactNative/Fabric/ViewComponentView.h +1 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/rncore/EventEmitters.h +5 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/rncore/Props.h +5 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/slider/SliderMeasurementsManager.cpp +46 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/slider/SliderMeasurementsManager.h +30 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/Color.cpp +2 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/conversions.h +1 -9
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/platform/cxx/react/renderer/graphics/Color.h +3 -1
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +119 -57
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h +18 -1
- package/Microsoft.ReactNative/IViewManager.idl +3 -3
- package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +13 -107
- package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +2 -2
- package/Microsoft.ReactNative/Modules/AppStateModule.cpp +2 -0
- package/Microsoft.ReactNative/Modules/AppStateModule.h +2 -0
- package/Microsoft.ReactNative/Modules/CreateModules.cpp +3 -3
- package/Microsoft.ReactNative/Modules/NativeUIManager.cpp +7 -5
- package/Microsoft.ReactNative/Modules/TimingModule.cpp +2 -2
- package/Microsoft.ReactNative/Modules/TimingModule.h +2 -2
- package/Microsoft.ReactNative/ReactHost/{ReactContext.cpp → MsoReactContext.cpp} +1 -1
- package/Microsoft.ReactNative/ReactHost/{ReactContext.h → MsoReactContext.h} +0 -0
- package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +15 -2
- package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +1 -1
- package/Microsoft.ReactNative/ReactHost/ReactNativeHeaders.h +1 -1
- package/Microsoft.ReactNative/ReactInstanceSettings.idl +12 -2
- package/Microsoft.ReactNative/ReactPackageBuilder.cpp +1 -1
- package/Microsoft.ReactNative/ReactRootView.cpp +2 -1
- package/Microsoft.ReactNative/RedBox.cpp +3 -2
- package/Microsoft.ReactNative/TurboModulesProvider.cpp +3 -2
- package/Microsoft.ReactNative/TurboModulesProvider.h +4 -1
- package/Microsoft.ReactNative/Utils/LocalBundleReader.cpp +41 -0
- package/Microsoft.ReactNative/Utils/ValueUtils.cpp +3 -2
- package/Microsoft.ReactNative/Views/ControlViewManager.cpp +32 -0
- package/Microsoft.ReactNative/Views/ControlViewManager.h +11 -0
- package/Microsoft.ReactNative/Views/DevMenu.cpp +2 -2
- package/Microsoft.ReactNative/Views/FrameworkElementTransferProperties.cpp +13 -2
- package/Microsoft.ReactNative/Views/FrameworkElementViewManager.cpp +149 -22
- package/Microsoft.ReactNative/Views/Image/ImageViewManager.cpp +1 -1
- package/Microsoft.ReactNative/Views/Image/Microsoft.UI.Composition.Effects_Impl.h +5 -11
- package/Microsoft.ReactNative/Views/Image/ReactImage.cpp +2 -1
- package/Microsoft.ReactNative/Views/SliderViewManager.cpp +12 -4
- package/Microsoft.ReactNative/Views/TextInputViewManager.cpp +1 -1
- package/Microsoft.ReactNative/Views/TextViewManager.cpp +2 -2
- package/Microsoft.ReactNative/Views/TouchEventHandler.cpp +163 -37
- package/Microsoft.ReactNative/Views/TouchEventHandler.h +11 -4
- package/Microsoft.ReactNative/Views/ViewPanel.cpp +3 -23
- package/Microsoft.ReactNative/Views/ViewPanel.h +2 -3
- package/Microsoft.ReactNative/Views/ViewViewManager.cpp +21 -0
- package/Microsoft.ReactNative/XamlUIService.cpp +1 -1
- package/Microsoft.ReactNative/XamlView.h +8 -3
- package/Microsoft.ReactNative.Cxx/CppWinRTIncludes.h +3 -5
- package/Microsoft.ReactNative.Cxx/DesktopWindowBridge.h +1 -1
- package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.cpp +11 -2
- package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.h +1 -0
- package/Microsoft.ReactNative.Cxx/JSI/NodeApiJsiRuntime.cpp +19 -14
- package/Microsoft.ReactNative.Cxx/JSI/NodeApiJsiRuntime.h +4 -0
- package/Microsoft.ReactNative.Cxx/JSValueReader.h +2 -2
- package/Microsoft.ReactNative.Cxx/JSValueWriter.h +5 -5
- package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +5 -1
- package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems.filters +2 -3
- package/Microsoft.ReactNative.Cxx/NativeModules.h +3 -3
- package/Microsoft.ReactNative.Cxx/ReactContext.h +3 -3
- package/Microsoft.ReactNative.Cxx/ReactNonAbiValue.h +3 -3
- package/Microsoft.ReactNative.Cxx/XamlUtils.h +44 -5
- package/Microsoft.ReactNative.Managed/Microsoft.ReactNative.Managed.csproj +0 -6
- package/Mso/activeObject/activeObject.h +2 -2
- package/Mso/compilerAdapters/cppMacros.h +3 -5
- package/Mso/errorCode/errorProvider.h +2 -2
- package/Mso/errorCode/maybe.h +4 -4
- package/Mso/functional/functor.h +6 -6
- package/Mso/functional/functorRef.h +2 -2
- package/Mso/future/details/executor.h +2 -2
- package/Mso/future/details/futureFuncInl.h +4 -4
- package/Mso/future/details/ifuture.h +3 -3
- package/Mso/future/details/maybeInvoker.h +6 -6
- package/Mso/future/details/promiseGroupInl.h +4 -4
- package/Mso/future/details/promiseInl.h +4 -4
- package/Mso/future/details/resultTraits.h +4 -4
- package/Mso/future/details/whenAllInl.h +1 -1
- package/Mso/future/future.h +13 -13
- package/Mso/guid/msoGuidDetails.h +1 -1
- package/Mso/memoryApi/memoryApi.h +13 -7
- package/Mso/motifCpp/gTestAdapter.h +1 -1
- package/Mso/motifCpp/testInfo.h +7 -9
- package/Mso/object/make.h +8 -8
- package/Mso/object/objectRefCount.h +3 -5
- package/Mso/object/objectWithWeakRef.h +10 -14
- package/Mso/object/queryCast.h +4 -4
- package/Mso/object/refCountedObject.h +4 -4
- package/Mso/object/unknownObject.h +7 -7
- package/Mso/platformAdapters/windowsFirst.h +1 -1
- package/Mso/smartPtr/cntPtr.h +8 -8
- package/Mso/src/dispatchQueue/threadPoolScheduler_win.cpp +96 -4
- package/Mso/src/dispatchQueue/uiScheduler_winrt.cpp +2 -2
- package/Mso/src/future/futureImpl.h +1 -1
- package/Mso/src/memoryApi/memoryApi.cpp +4 -4
- package/PropertySheets/CppAppConsumeCSharpModule.props +3 -0
- package/PropertySheets/External/Microsoft.ReactNative.WinAppSDK.CSharpApp.props +26 -0
- package/PropertySheets/External/Microsoft.ReactNative.WinAppSDK.Common.props +12 -0
- package/PropertySheets/Generated/PackageVersion.g.props +3 -3
- package/PropertySheets/JSEngine.props +1 -1
- package/PropertySheets/React.Cpp.props +13 -0
- package/PropertySheets/WinUI.props +3 -6
- package/ReactCommon/ReactCommon.vcxproj +2 -4
- package/ReactCommon/ReactCommon.vcxproj.filters +4 -1
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/JSCRuntime.cpp +1480 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/jsi/decorator.h +753 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/jsi/jsi.h +1331 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/jsi/test/testlib.cpp +1431 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/bridging/CallbackWrapper.h +103 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModule.h +87 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModuleUtils.h +61 -0
- package/ReactCommon/Yoga.cpp +1 -1
- package/Scripts/{Microsoft.ReactNative.ProjectReunion.nuspec → Microsoft.ReactNative.WindowsAppSDK.nuspec} +7 -9
- package/Scripts/OfficeReact.Win32.nuspec +1 -3
- package/Scripts/Tfs/Layout-MSRN-Headers.ps1 +2 -1
- package/Scripts/copyRNLibraries.js +8 -8
- package/Scripts/just.js +1 -1
- package/Scripts/rnw-dependencies.ps1 +41 -10
- package/Scripts/run-desktop-integration-tests.js +6 -6
- package/Shared/AbiSafe.h +3 -3
- package/Shared/BaseScriptStoreImpl.cpp +1 -1
- package/Shared/CppRuntimeOptions.h +50 -0
- package/Shared/CreateModules.h +4 -0
- package/Shared/DevSupportManager.cpp +34 -33
- package/Shared/DevSupportManager.h +1 -2
- package/Shared/HermesRuntimeHolder.cpp +23 -14
- package/Shared/HermesRuntimeHolder.h +8 -2
- package/Shared/IDevSupportManager.h +1 -2
- package/Shared/InspectorPackagerConnection.cpp +7 -5
- package/Shared/InspectorPackagerConnection.h +2 -2
- package/Shared/JSI/ChakraApi.cpp +0 -1
- package/Shared/JSI/ChakraRuntime.cpp +1 -2
- package/Shared/JSI/NapiJsiV8RuntimeHolder.h +1 -1
- package/Shared/JSI/RuntimeHolder.h +2 -0
- package/Shared/Modules/HttpModule.cpp +198 -0
- package/Shared/Modules/HttpModule.h +53 -0
- package/Shared/Modules/WebSocketModule.cpp +5 -1
- package/Shared/Modules/WebSocketModule.h +8 -5
- package/Shared/Networking/IHttpResource.h +53 -0
- package/Shared/{IWebSocketResource.h → Networking/IWebSocketResource.h} +3 -3
- package/Shared/Networking/OriginPolicy.h +15 -0
- package/Shared/Networking/OriginPolicyHttpFilter.cpp +746 -0
- package/Shared/Networking/OriginPolicyHttpFilter.h +112 -0
- package/Shared/Networking/WinRTHttpResource.cpp +347 -0
- package/Shared/Networking/WinRTHttpResource.h +67 -0
- package/Shared/Networking/WinRTTypes.h +30 -0
- package/Shared/{WinRTWebSocketResource.cpp → Networking/WinRTWebSocketResource.cpp} +31 -22
- package/Shared/{WinRTWebSocketResource.h → Networking/WinRTWebSocketResource.h} +3 -3
- package/Shared/OInstance.cpp +37 -11
- package/Shared/RuntimeOptions.cpp +93 -15
- package/Shared/RuntimeOptions.h +22 -9
- package/Shared/Shared.vcxitems +126 -5
- package/Shared/Shared.vcxitems.filters +55 -15
- package/Shared/Threading/BatchingQueueThread.cpp +1 -1
- package/Shared/Utils/WinRTConversions.cpp +22 -0
- package/Shared/Utils/WinRTConversions.h +15 -0
- package/Shared/tracing/fbsystrace.h +2 -2
- package/codegen/NativeActionSheetManagerSpec.g.h +6 -0
- package/codegen/NativeAnimatedModuleSpec.g.h +43 -37
- package/codegen/NativeAnimatedTurboModuleSpec.g.h +43 -37
- package/codegen/NativePushNotificationManagerIOSSpec.g.h +2 -0
- package/codegen/react/components/rnwcore/ComponentDescriptors.h +0 -1
- package/codegen/react/components/rnwcore/EventEmitters.cpp +133 -0
- package/codegen/react/components/rnwcore/EventEmitters.h +0 -18
- package/codegen/react/components/rnwcore/Props.cpp +0 -13
- package/codegen/react/components/rnwcore/Props.h +0 -16
- package/codegen/react/components/rnwcore/ShadowNodes.cpp +0 -1
- package/codegen/react/components/rnwcore/ShadowNodes.h +0 -10
- package/include/Shared/cdebug.h +9 -9
- package/index.js +30 -25
- package/index.windows.js +30 -25
- package/jest/preprocessor.js +24 -107
- package/jest/preprocessor_DO_NOT_USE.js +122 -0
- package/metro.config.js +3 -70
- package/package.json +29 -28
- package/react-native.config.js +40 -6
- package/rntypes/index.d.ts +19 -7
- package/stubs/glog/logging.h +1 -1
- package/template/cpp-app/src/App.h +0 -4
- package/template/cs-app/src/App.xaml.cs +0 -5
- package/template/cs-app/src/MainPage.xaml.cs +1 -10
- package/template/cs-app-WinAppSDK/MyApp/App.xaml +16 -0
- package/template/cs-app-WinAppSDK/MyApp/App.xaml.cs +70 -0
- package/template/cs-app-WinAppSDK/MyApp/MainWindow.xaml +14 -0
- package/template/cs-app-WinAppSDK/MyApp/MainWindow.xaml.cs +38 -0
- package/template/cs-app-WinAppSDK/MyApp/Package.appxmanifest +48 -0
- package/template/cs-app-WinAppSDK/MyApp/Properties/PublishProfiles/win10-arm64.pubxml +19 -0
- package/template/cs-app-WinAppSDK/MyApp/Properties/PublishProfiles/win10-x64.pubxml +19 -0
- package/template/cs-app-WinAppSDK/MyApp/Properties/PublishProfiles/win10-x86.pubxml +19 -0
- package/template/cs-app-WinAppSDK/MyApp/Properties/launchSettings.json +10 -0
- package/template/cs-app-WinAppSDK/MyApp/app.manifest +15 -0
- package/template/cs-app-WinAppSDK/proj/ExperimentalFeatures.props +23 -0
- package/template/cs-app-WinAppSDK/proj/MyApp.csproj +49 -0
- package/template/cs-app-WinAppSDK/proj/MyApp.sln +43 -0
- package/template/cs-app-WinAppSDK/proj/NuGet.Config +17 -0
- package/template/metro.devMode.config.js +2 -51
- package/typings-index.js +5 -1
- package/typings-index.js.map +1 -1
- package/Libraries/Components/SegmentedControlIOS/RCTSegmentedControlNativeComponent.js +0 -44
- package/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.android.js +0 -45
- package/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js +0 -123
- package/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.windows.js +0 -45
- package/Libraries/Components/View/ReactNativeViewViewConfig.js +0 -360
- package/Libraries/Components/View/ReactNativeViewViewConfig.windows.js +0 -390
- package/Libraries/Components/View/ReactNativeViewViewConfigAndroid.js +0 -83
- package/Libraries/ReactNative/UIManagerInjection.js +0 -15
- package/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +0 -24527
- package/Libraries/Renderer/implementations/ReactFabric-prod.fb.js +0 -8309
- package/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js +0 -8961
- package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +0 -24948
- package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js +0 -8400
- package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js +0 -9049
- package/PropertySheets/CppEnablePackageReferences.props +0 -13
- package/Shared/IHttpResource.h +0 -34
- package/Shared/cdebug.cpp +0 -6
- 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()));
|