From 51368d02d2d0961411707c40901bf8d1bb20e1c4 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Mon, 27 Apr 2020 09:41:44 -0700 Subject: [PATCH 001/209] Added C# ReactContext for Module Initialize method (#4722) * Added C# ReactContext for Module Initialize method * Change files * Fixed sample project compilation --- ...020-04-26-21-09-42-MS_Cs_ReactContext.json | 8 + .../windows/SampleLibraryCS/SampleModuleCS.cs | 2 +- .../Microsoft.ReactNative.Cxx/NativeModules.h | 4 + .../Microsoft.ReactNative.Cxx/ReactContext.h | 6 + .../NativeModuleTest.cs | 2 +- .../NoAttributeNativeModuleTest.cs | 19 +- .../AttributedViewManager.cs | 5 +- .../JSValueGenerator.cs | 67 +++---- ...rosoft.ReactNative.SharedManaged.projitems | 2 +- .../ReactConstantProvider.cs | 10 +- .../ReactContext.cs | 176 ++++++++++++++++++ .../ReactContextExtensions.cs | 145 --------------- .../ReactContextGenerator.cs | 17 +- .../ReactEventInfo.cs | 6 +- .../ReactFunctionInfo.cs | 6 +- .../ReactInitializerInfo.cs | 7 +- 16 files changed, 258 insertions(+), 224 deletions(-) create mode 100644 change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json create mode 100644 vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs delete mode 100644 vnext/Microsoft.ReactNative.SharedManaged/ReactContextExtensions.cs diff --git a/change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json b/change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json new file mode 100644 index 00000000000..76cefbe6c3f --- /dev/null +++ b/change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Added C# ReactContext for Module Initialize method", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-27T04:09:42.583Z" +} diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs index 44a7d049b27..cd40e29bd09 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs @@ -25,7 +25,7 @@ internal sealed class SampleModuleCS #region Initializer [ReactInitializer] - public void Initialize(IReactContext _) + public void Initialize(ReactContext _) { _timer = ThreadPoolTimer.CreatePeriodicTimer(new TimerElapsedHandler((timer) => { diff --git a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h index 65d82ca9ba2..d7ab009b8c5 100644 --- a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h +++ b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h @@ -694,6 +694,10 @@ struct ReactConstantProvider { WriteProperty(m_writer, name, value); } + IJSValueWriter const &Writer() const noexcept { + return m_writer; + } + private: IJSValueWriter m_writer; }; diff --git a/vnext/Microsoft.ReactNative.Cxx/ReactContext.h b/vnext/Microsoft.ReactNative.Cxx/ReactContext.h index eee48e1569d..72dd33e5bda 100644 --- a/vnext/Microsoft.ReactNative.Cxx/ReactContext.h +++ b/vnext/Microsoft.ReactNative.Cxx/ReactContext.h @@ -17,6 +17,8 @@ namespace winrt::Microsoft::ReactNative { struct ReactContext { ReactContext(IReactContext const &context) noexcept; + IReactContext const &ContextAbi() const noexcept; + explicit operator bool() noexcept; template @@ -56,6 +58,10 @@ struct ReactContext { inline ReactContext::ReactContext(IReactContext const &context) noexcept : m_context{context} {} +inline IReactContext const &ReactContext::ContextAbi() const noexcept { + return m_context; +} + inline ReactContext::operator bool() noexcept { return m_context != nullptr; } diff --git a/vnext/Microsoft.ReactNative.Managed.UnitTests/NativeModuleTest.cs b/vnext/Microsoft.ReactNative.Managed.UnitTests/NativeModuleTest.cs index 98f48a7127d..06ab0e8a6db 100644 --- a/vnext/Microsoft.ReactNative.Managed.UnitTests/NativeModuleTest.cs +++ b/vnext/Microsoft.ReactNative.Managed.UnitTests/NativeModuleTest.cs @@ -20,7 +20,7 @@ public struct Point class SimpleNativeModule { [ReactInitializer] - public void Initialize(IReactContext context) + public void Initialize(ReactContext context) { IsInitialized = true; Assert.IsNotNull(context); diff --git a/vnext/Microsoft.ReactNative.Managed.UnitTests/NoAttributeNativeModuleTest.cs b/vnext/Microsoft.ReactNative.Managed.UnitTests/NoAttributeNativeModuleTest.cs index 43ccc114a80..f1863b1fd59 100644 --- a/vnext/Microsoft.ReactNative.Managed.UnitTests/NoAttributeNativeModuleTest.cs +++ b/vnext/Microsoft.ReactNative.Managed.UnitTests/NoAttributeNativeModuleTest.cs @@ -687,43 +687,48 @@ public void AddConstantProvider(Func> get public void AddJSEvent(string eventEmitterName, string name, Action setEventHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setEventHandler(m_module, () => reactContext.EmitJSEvent(eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name)); + setEventHandler(m_module, () => new ReactContext(reactContext).EmitJSEvent( + eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name)); }); } public void AddJSEvent(string eventEmitterName, string name, Action> setEventHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setEventHandler(m_module, (T1 arg1) => reactContext.EmitJSEvent(eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name, arg1)); + setEventHandler(m_module, (T1 arg1) => new ReactContext(reactContext).EmitJSEvent( + eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name, arg1)); }); } public void AddJSEvent(string eventEmitterName, string name, Action> setEventHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setEventHandler(m_module, (T1 arg1, T2 arg2) => - reactContext.EmitJSEvent(eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name, arg1, arg2)); + setEventHandler(m_module, (T1 arg1, T2 arg2) => new ReactContext(reactContext).EmitJSEvent( + eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name, arg1, arg2)); }); } public void AddJSFunction(string moduleName, string name, Action setFunctionHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setFunctionHandler(m_module, () => reactContext.CallJSFunction(moduleName ?? ModuleName, name)); + setFunctionHandler(m_module, () => new ReactContext(reactContext).CallJSFunction( + moduleName ?? ModuleName, name)); }); } public void AddJSFunction(string moduleName, string name, Action> setFunctionHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setFunctionHandler(m_module, (T1 arg1) => reactContext.CallJSFunction(moduleName ?? ModuleName, name, arg1)); + setFunctionHandler(m_module, (T1 arg1) => new ReactContext(reactContext).CallJSFunction( + moduleName ?? ModuleName, name, arg1)); }); } public void AddJSFunction(string moduleName, string name, Action> setFunctionHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setFunctionHandler(m_module, (T1 arg1, T2 arg2) => reactContext.CallJSFunction(moduleName ?? ModuleName, name, arg1, arg2)); + setFunctionHandler(m_module, (T1 arg1, T2 arg2) => new ReactContext(reactContext).CallJSFunction( + moduleName ?? ModuleName, name, arg1, arg2)); }); } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs b/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs index 56691b2be2f..ab835d574ae 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs @@ -402,8 +402,9 @@ private Delegate MakeEventDelegate(string eventName, Type memberType, Type event ParameterExpression eventDataParameter = Expression.Parameter(eventDataType, "eventData"); MemberExpression thisReactContext = Expression.Property(Expression.Constant(this), "ReactContext"); - MethodCallExpression dispatchCall = Expression.Call(DispatchEventOf(eventDataType), - thisReactContext, + NewExpression reactContext = Expression.New(ReactContextConstructor(), thisReactContext); + MethodCallExpression dispatchCall = Expression.Call(reactContext, + DispatchEventOf(eventDataType), viewParameter, Expression.Constant(eventName, typeof(string)), eventDataParameter); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/JSValueGenerator.cs b/vnext/Microsoft.ReactNative.SharedManaged/JSValueGenerator.cs index 13e1db92ca9..eaa35d5c61a 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/JSValueGenerator.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/JSValueGenerator.cs @@ -212,66 +212,41 @@ public Expression Assign(Expression value) return Expression.Assign(AsExpression, value); } - public Expression Call(MethodInfo method, params Expression[] args) + // This method allows us to expand the argument array that may use parameters that are + // Expressions, VariableWrappers, or arrays of them. + // The argument expressions are added to the args list. + private void ExpandArgArray(IList args, object[] argObjects) { - return Expression.Call(AsExpression, method, args); - } - - public Expression Call(string methodName, params Expression[] args) - { - return Call(Type.GetMethod(methodName), args); - } - - public Expression CallExt(MethodInfo method) - { - return Expression.Call(method, AsExpression); - } - - public Expression CallExt(MethodInfo method, Expression arg0) - { - return Expression.Call(method, AsExpression, arg0); - } - - public Expression CallExt(MethodInfo method, Expression arg0, Expression arg1) - { - return Expression.Call(method, AsExpression, arg0, arg1); - } - - public Expression CallExt(MethodInfo method, params Expression[] args) - { - return Expression.Call(method, Enumerable.Repeat(AsExpression, 1).Concat(args)); + foreach (var arg in argObjects) + { + switch (arg) + { + case object[] items: ExpandArgArray(args, items); break; + case VariableWrapper variable: args.Add(variable.AsExpression); break; + case Expression expr: args.Add(expr); break; + } + } } - public Expression CallExt(MethodInfo method, params VariableWrapper[] args) + public MethodCallExpression Call(MethodInfo method, params object[] arguments) { - return Expression.Call(method, - Enumerable.Repeat(this, 1).Concat(args).Select(v => v.AsExpression)); + var args = new List(); + ExpandArgArray(args, arguments); + return Expression.Call(AsExpression, method, args); } public MethodCallExpression CallExt(MethodInfo method, params object[] arguments) { var args = new List { AsExpression }; - - void ParseArgs(object[] argObjects) - { - foreach (var arg in argObjects) - { - switch (arg) - { - case object[] items: ParseArgs(items); break; - case VariableWrapper variable: args.Add(variable.AsExpression); break; - case Expression expr: args.Add(expr); break; - } - } - } - - ParseArgs(arguments); + ExpandArgArray(args, arguments); return Expression.Call(method, args); } // It can be used only for delegate types - public Expression Invoke(params Expression[] args) + public Expression Invoke(params object[] arguments) { + var args = new List(); + ExpandArgArray(args, arguments); return Expression.Invoke(AsExpression, args); } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems b/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems index 20a1c82159a..49a4f0ca31b 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems +++ b/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems @@ -11,7 +11,7 @@ - + diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs index 87e65ed1e54..2d6a048cb79 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs @@ -3,18 +3,18 @@ namespace Microsoft.ReactNative.Managed { - class ReactConstantProvider + struct ReactConstantProvider { public ReactConstantProvider(IJSValueWriter writer) { - m_writer = writer; + Writer = writer; } + public IJSValueWriter Writer { get; } + public void Add(string constantName, T value) { - m_writer.WriteObjectProperty(constantName, value); + Writer.WriteObjectProperty(constantName, value); } - - private readonly IJSValueWriter m_writer; } } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs new file mode 100644 index 00000000000..bfd8098550f --- /dev/null +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs @@ -0,0 +1,176 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Windows.UI.Xaml; + +namespace Microsoft.ReactNative.Managed +{ + struct ReactContext + { + public ReactContext(IReactContext context) + { + ContextAbi = context; + } + + public IReactContext ContextAbi { get; } + + public void DispatchEvent(FrameworkElement view, string eventName, T arg) + { + var argWriter = arg as JSValueArgWriter; + if (argWriter != null) + { + ContextAbi.DispatchEvent(view, eventName, argWriter); + } + else + { + ContextAbi.DispatchEvent(view, eventName, (IJSValueWriter writer) => writer.WriteValue(arg)); + } + } + + public void CallJSFunction(string moduleName, string methodName) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs()); + } + + public void CallJSFunction(string moduleName, string methodName, T1 arg1) + { + var argWriter = arg1 as JSValueArgWriter; + if (argWriter != null) + { + ContextAbi.CallJSFunction(moduleName, methodName, argWriter); + } + else + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1)); + } + } + + public void CallJSFunction(string moduleName, string methodName, T1 arg1, T2 arg2) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2)); + } + + public void CallJSFunction(string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3)); + } + + public void CallJSFunction( + string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4)); + } + + public void CallJSFunction( + string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5)); + } + + public void CallJSFunction( + string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6)); + } + + public void CallJSFunction( + string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6, arg7)); + } + + public void EmitJSEvent(string eventEmitterName, string eventName) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter _) => { }); + } + + public void EmitJSEvent(string eventEmitterName, string eventName, T1 arg1) + { + var argWriter = arg1 as JSValueArgWriter; + if (argWriter != null) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, argWriter); + } + else + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + }); + } + } + + public void EmitJSEvent(string eventEmitterName, string eventName, T1 arg1, T2 arg2) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + }); + } + + public void EmitJSEvent(string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + writer.WriteValue(arg3); + }); + } + + public void EmitJSEvent( + string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + writer.WriteValue(arg3); + writer.WriteValue(arg4); + }); + } + + public void EmitJSEvent( + string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + writer.WriteValue(arg3); + writer.WriteValue(arg4); + writer.WriteValue(arg5); + }); + } + + public void EmitJSEvent( + string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + writer.WriteValue(arg3); + writer.WriteValue(arg4); + writer.WriteValue(arg5); + writer.WriteValue(arg6); + }); + } + + public void EmitJSEvent( + string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + writer.WriteValue(arg3); + writer.WriteValue(arg4); + writer.WriteValue(arg5); + writer.WriteValue(arg6); + writer.WriteValue(arg7); + }); + } + } +} diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextExtensions.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactContextExtensions.cs deleted file mode 100644 index 9f1484be724..00000000000 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextExtensions.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Windows.UI.Xaml; - -namespace Microsoft.ReactNative.Managed -{ - static class ReactContextExtensions - { - public static void DispatchEvent(this IReactContext reactContext, FrameworkElement view, string eventName, T arg) - { - reactContext.DispatchEvent(view, eventName, (IJSValueWriter writer) => writer.WriteValue(arg)); - } - - public static void CallJSFunction(this IReactContext reactContext, string moduleName, string methodName) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs()); - } - - public static void CallJSFunction(this IReactContext reactContext, string moduleName, string methodName, T1 arg1) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1)); - } - - public static void CallJSFunction(this IReactContext reactContext, string moduleName, string methodName, T1 arg1, T2 arg2) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2)); - } - - public static void CallJSFunction(this IReactContext reactContext, string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3)); - } - - public static void CallJSFunction(this IReactContext reactContext, - string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4)); - } - - public static void CallJSFunction(this IReactContext reactContext, - string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5)); - } - - public static void CallJSFunction(this IReactContext reactContext, - string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6)); - } - - public static void CallJSFunction(this IReactContext reactContext, - string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6, arg7)); - } - - public static void EmitJSEvent(this IReactContext reactContext, string eventEmitterName, string eventName) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => {}); - } - - public static void EmitJSEvent(this IReactContext reactContext, string eventEmitterName, string eventName, T1 arg1) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, string eventEmitterName, string eventName, T1 arg1, T2 arg2) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - writer.WriteValue(arg3); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, - string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - writer.WriteValue(arg3); - writer.WriteValue(arg4); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, - string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - writer.WriteValue(arg3); - writer.WriteValue(arg4); - writer.WriteValue(arg5); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, - string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - writer.WriteValue(arg3); - writer.WriteValue(arg4); - writer.WriteValue(arg5); - writer.WriteValue(arg6); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, - string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - writer.WriteValue(arg3); - writer.WriteValue(arg4); - writer.WriteValue(arg5); - writer.WriteValue(arg6); - writer.WriteValue(arg7); - }); - } - } -} diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs index e9f5fd6767e..f2a7f3a094b 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs @@ -11,14 +11,13 @@ namespace Microsoft.ReactNative.Managed { static class ReactContextGenerator { - private static MethodInfo GetExtensionMethod(string methodName, Type[] typeArgs, params Type[] requiredArgTypes) + private static MethodInfo GetMethod(string methodName, Type[] typeArgs, params Type[] requiredArgTypes) { var extMethod = - from member in typeof(ReactContextExtensions).GetMember(methodName, BindingFlags.Static | BindingFlags.Public) + from member in typeof(ReactContext).GetMember(methodName, BindingFlags.Instance | BindingFlags.Public) let method = member as MethodInfo let isGeneric = method.IsGenericMethod where method != null - && method.IsDefined(typeof(ExtensionAttribute), inherit: false) let parameters = method.GetParameters() where parameters.Length == typeArgs.Length + requiredArgTypes.Length && Enumerable.Range(0, requiredArgTypes.Length).All(i => parameters[i].ParameterType == requiredArgTypes[i]) @@ -26,22 +25,22 @@ from member in typeof(ReactContextExtensions).GetMember(methodName, BindingFlags return extMethod.First(); } + public static ConstructorInfo ReactContextConstructor() => + typeof(ReactContext).GetConstructor(new Type[] { typeof(IReactContext) }); + public static MethodInfo DispatchEventOf(params Type[] typeArgs) { - return GetExtensionMethod(nameof(ReactContextExtensions.DispatchEvent), typeArgs, - typeof(IReactContext), typeof(FrameworkElement), typeof(string)); + return GetMethod(nameof(ReactContext.DispatchEvent), typeArgs, typeof(FrameworkElement), typeof(string)); } public static MethodInfo CallJSFunctionOf(params Type[] typeArgs) { - return GetExtensionMethod(nameof(ReactContextExtensions.CallJSFunction), typeArgs, - typeof(IReactContext), typeof(string), typeof(string)); + return GetMethod(nameof(ReactContext.CallJSFunction), typeArgs, typeof(string), typeof(string)); } public static MethodInfo EmitJSEventOf(params Type[] typeArgs) { - return GetExtensionMethod(nameof(ReactContextExtensions.EmitJSEvent), typeArgs, - typeof(IReactContext), typeof(string), typeof(string)); + return GetMethod(nameof(ReactContext.EmitJSEvent), typeArgs, typeof(string), typeof(string)); } } } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs index f73f2a57c53..858fc886069 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs @@ -65,7 +65,8 @@ private ReactEventImpl MakeEvent(PropertyInfo propertyInfo, string eventEmitterN module.CastTo(propertyInfo.DeclaringType).SetProperty(propertyInfo, AutoLambda(propertyInfo.PropertyType, Parameters(eventArgTypes, out var args), - reactContext.CallExt(EmitJSEventOf(eventArgTypes), Constant(eventEmitterName), Constant(eventName), args)))); + New(ReactContextConstructor(), reactContext).Call( + EmitJSEventOf(eventArgTypes), Constant(eventEmitterName), Constant(eventName), args)))); } private ReactEventImpl MakeEvent(FieldInfo fieldInfo, string eventEmitterName, string eventName, Type[] eventArgTypes) @@ -84,7 +85,8 @@ private ReactEventImpl MakeEvent(FieldInfo fieldInfo, string eventEmitterName, s module.CastTo(fieldInfo.DeclaringType).SetField(fieldInfo, AutoLambda(fieldInfo.FieldType, Parameters(eventArgTypes, out var args), - reactContext.CallExt(EmitJSEventOf(eventArgTypes), Constant(eventEmitterName), Constant(eventName), args)))); + New(ReactContextConstructor(), reactContext).Call( + EmitJSEventOf(eventArgTypes), Constant(eventEmitterName), Constant(eventName), args)))); } public delegate void ReactEventImpl(object module, IReactContext reactContext); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs index faf617e684b..777ef64f0bf 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs @@ -65,7 +65,8 @@ private ReactFunctionImpl MakeFunction(PropertyInfo propertyInfo, string moduleN module.CastTo(propertyInfo.DeclaringType).SetProperty(propertyInfo, AutoLambda(propertyInfo.PropertyType, Parameters(functionArgTypes, out var args), - reactContext.CallExt(CallJSFunctionOf(functionArgTypes), Constant(moduleName), Constant(functionName), args)))); + New(ReactContextConstructor(), reactContext).Call( + CallJSFunctionOf(functionArgTypes), Constant(moduleName), Constant(functionName), args)))); } private ReactFunctionImpl MakeFunction(FieldInfo fieldInfo, string moduleName, string functionName, Type[] functionArgTypes) @@ -84,7 +85,8 @@ private ReactFunctionImpl MakeFunction(FieldInfo fieldInfo, string moduleName, s module.CastTo(fieldInfo.DeclaringType).SetField(fieldInfo, AutoLambda(fieldInfo.FieldType, Parameters(functionArgTypes, out var args), - reactContext.CallExt(CallJSFunctionOf(functionArgTypes), Constant(moduleName), Constant(functionName), args)))); + New(ReactContextConstructor(), reactContext).Call( + CallJSFunctionOf(functionArgTypes), Constant(moduleName), Constant(functionName), args)))); } public delegate void ReactFunctionImpl(object module, IReactContext reactContext); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs index 7cb1a9aa062..9e8c23cd2c7 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Threading; using static Microsoft.ReactNative.Managed.JSValueGenerator; +using static Microsoft.ReactNative.Managed.ReactContextGenerator; using static System.Linq.Expressions.Expression; namespace Microsoft.ReactNative.Managed @@ -14,7 +15,7 @@ class ReactInitializerInfo public ReactInitializerInfo(MethodInfo methodInfo) { ParameterInfo[] parameters = methodInfo.GetParameters(); - if (parameters.Length != 1 || parameters[0].ParameterType != typeof(IReactContext)) + if (parameters.Length != 1 || parameters[0].ParameterType != typeof(ReactContext)) { throw new ArgumentException($"Initializer method must have one parameter of IReactContext type." + $" Module: {methodInfo.DeclaringType.FullName} Method: {methodInfo.Name}"); @@ -29,13 +30,13 @@ private ReactInitializerImpl MakeInitializer(MethodInfo methodInfo) // // (object module, IReactContext reactContext) => // { - // (module as MyModule).initializerMethod(reactContext); + // (module as MyModule).initializerMethod(new ReactContext(reactContext)); // }); return CompileLambda( Parameter(typeof(object), out var module), Parameter(typeof(IReactContext), out var reactContext), - Call(module.CastTo(methodInfo.DeclaringType), methodInfo, reactContext)); + Call(module.CastTo(methodInfo.DeclaringType), methodInfo, New(ReactContextConstructor(), reactContext))); } public delegate void ReactInitializerImpl(object module, IReactContext reactConext); From fc72e04428dff1c31acdb9183f3ce95a0a5a53c1 Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Mon, 27 Apr 2020 10:46:12 -0700 Subject: [PATCH 002/209] Update rex-win32 version to something more recent (#4725) * Update rex-win32 version to something more recent * Change files --- ...-iss-react-native-win32-2020-04-27-09-42-09-uprex.json | 8 ++++++++ packages/react-native-win32/package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 change/@office-iss-react-native-win32-2020-04-27-09-42-09-uprex.json diff --git a/change/@office-iss-react-native-win32-2020-04-27-09-42-09-uprex.json b/change/@office-iss-react-native-win32-2020-04-27-09-42-09-uprex.json new file mode 100644 index 00000000000..6cb87e75fcd --- /dev/null +++ b/change/@office-iss-react-native-win32-2020-04-27-09-42-09-uprex.json @@ -0,0 +1,8 @@ +{ + "type": "none", + "comment": "Update rex-win32 version to something more recent", + "packageName": "@office-iss/react-native-win32", + "email": "acoates@microsoft.com", + "dependentChangeType": "none", + "date": "2020-04-27T16:42:09.664Z" +} diff --git a/packages/react-native-win32/package.json b/packages/react-native-win32/package.json index 9f18e975354..275c1c1d759 100644 --- a/packages/react-native-win32/package.json +++ b/packages/react-native-win32/package.json @@ -43,7 +43,7 @@ "whatwg-fetch": "^3.0.0" }, "devDependencies": { - "@office-iss/rex-win32": "0.0.33", + "@office-iss/rex-win32": "0.0.0-devmain.12823.10000", "@types/es6-collections": "^0.5.29", "@types/es6-promise": "0.0.32", "@types/node": "^12.11.2", diff --git a/yarn.lock b/yarn.lock index b910fbb87ac..0ad06fd74de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2552,10 +2552,10 @@ universal-user-agent "^3.0.0" url-template "^2.0.8" -"@office-iss/rex-win32@0.0.33": - version "0.0.33" - resolved "https://registry.yarnpkg.com/@office-iss/rex-win32/-/rex-win32-0.0.33.tgz#960ed52275c827df58aede4819d39927bdf2ae70" - integrity sha512-Eh4orZ3F4P03IJAn509H7rXPcA8/6iXIEJbBTrNdO0RK6gVIRQ/5GVVPg3BA3QrFN7GDJeXOqjN1/9daV4O8ag== +"@office-iss/rex-win32@0.0.0-devmain.12823.10000": + version "0.0.0-devmain.12823.10000" + resolved "https://registry.yarnpkg.com/@office-iss/rex-win32/-/rex-win32-0.0.0-devmain.12823.10000.tgz#ad4e1cf040fc02e51fcc5f6ba926a3b6f2c14bb0" + integrity sha512-rAjjiSgUFcB0ogHSKklHF+CaDZd7OXCXrv0zkfDM4XY2xfJykOtnr6rT0OqRgZvInDT9RSxi0yuQ4ck1HV+Bdw== dependencies: command-line-args "^5.0.2" command-line-usage "^5.0.5" From 793ec2523ab10db23def810a2f41f68957766941 Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Mon, 27 Apr 2020 10:46:37 -0700 Subject: [PATCH 003/209] Remove rnpm-plugin-windows pacakge (#4724) * Remove rnpm-plugin-windows * Change files --- ...react-native-windows--vnext--bug-report.md | 1 - .github/workflows/pr.yml | 3 - ...e-windows-2020-04-27-09-14-14-delrnpm.json | 8 + packages/E2ETest/package.json | 3 +- .../package.json | 3 +- packages/rnpm-plugin-windows/CHANGELOG.json | 187 ----------------- packages/rnpm-plugin-windows/CHANGELOG.md | 70 ------- packages/rnpm-plugin-windows/README.md | 52 ----- packages/rnpm-plugin-windows/index.js | 43 ---- packages/rnpm-plugin-windows/package.json | 33 --- .../react-native.config.js | 5 - packages/rnpm-plugin-windows/src/common.js | 196 ------------------ packages/rnpm-plugin-windows/src/windows.js | 96 --------- packages/rnpm-plugin-windows/src/wpf.js | 42 ---- vnext/local-cli/runWindows/utils/info.js | 1 - 15 files changed, 10 insertions(+), 733 deletions(-) create mode 100644 change/react-native-windows-2020-04-27-09-14-14-delrnpm.json delete mode 100644 packages/rnpm-plugin-windows/CHANGELOG.json delete mode 100644 packages/rnpm-plugin-windows/CHANGELOG.md delete mode 100644 packages/rnpm-plugin-windows/README.md delete mode 100644 packages/rnpm-plugin-windows/index.js delete mode 100644 packages/rnpm-plugin-windows/package.json delete mode 100644 packages/rnpm-plugin-windows/react-native.config.js delete mode 100644 packages/rnpm-plugin-windows/src/common.js delete mode 100644 packages/rnpm-plugin-windows/src/windows.js delete mode 100644 packages/rnpm-plugin-windows/src/wpf.js diff --git a/.github/ISSUE_TEMPLATE/react-native-windows--vnext--bug-report.md b/.github/ISSUE_TEMPLATE/react-native-windows--vnext--bug-report.md index e04f2dbda25..6549797d05f 100644 --- a/.github/ISSUE_TEMPLATE/react-native-windows--vnext--bug-report.md +++ b/.github/ISSUE_TEMPLATE/react-native-windows--vnext--bug-report.md @@ -19,7 +19,6 @@ If you are using latest version: Otherwise if `--info` doesn't exist: 1. `react-native -v`: -2. `npm ls rnpm-plugin-windows`: 3. `npm ls react-native-windows`: 4. `node -v`: 5. `npm -v`: diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e5a532a2b3e..6788ff5d38b 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -163,9 +163,6 @@ jobs: - name: Init new project run: cd ${{ runner.temp }} && react-native init testcli --version 0.60.6 - - name: Install rnpm-plugin-windows - run: cd ${{ runner.temp }}\testcli && yarn add rnpm-plugin-windows@file:${{ runner.workspace }}\react-native-windows\current\local-cli\rnpm\windows - - name: Apply windows template run: cd ${{ runner.temp }}\testcli && react-native windows --template vnext --windowsVersion file:${{ runner.workspace }}\react-native-windows\vnext diff --git a/change/react-native-windows-2020-04-27-09-14-14-delrnpm.json b/change/react-native-windows-2020-04-27-09-14-14-delrnpm.json new file mode 100644 index 00000000000..4b5933ed081 --- /dev/null +++ b/change/react-native-windows-2020-04-27-09-14-14-delrnpm.json @@ -0,0 +1,8 @@ +{ + "type": "none", + "comment": "Remove rnpm-plugin-windows", + "packageName": "react-native-windows", + "email": "acoates@microsoft.com", + "dependentChangeType": "none", + "date": "2020-04-27T16:14:12.892Z" +} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index 46abc09dd84..4f080c7ea22 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,8 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.9.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.50", - "rnpm-plugin-windows": "^0.6.1" + "react-native-windows": "0.0.0-master.50" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 85f228c1c27..7889e67990c 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,8 +16,7 @@ "dependencies": { "react": "16.9.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.50", - "rnpm-plugin-windows": "^0.6.1" + "react-native-windows": "0.0.0-master.50" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/rnpm-plugin-windows/CHANGELOG.json b/packages/rnpm-plugin-windows/CHANGELOG.json deleted file mode 100644 index 54132a5ce53..00000000000 --- a/packages/rnpm-plugin-windows/CHANGELOG.json +++ /dev/null @@ -1,187 +0,0 @@ -{ - "name": "rnpm-plugin-windows", - "entries": [ - { - "date": "Wed, 25 Mar 2020 20:04:59 GMT", - "tag": "rnpm-plugin-windows_v0.6.1", - "version": "0.6.1", - "comments": { - "patch": [ - { - "comment": "allow CLI to install from file:", - "author": "kmelmon@microsoft.com", - "commit": "407c0834ada43cd9d42c24cb6ddfe7c91ddf960a" - } - ] - } - }, - { - "date": "Tue, 24 Mar 2020 22:51:22 GMT", - "tag": "rnpm-plugin-windows_v0.6.0", - "version": "0.6.0", - "comments": { - "minor": [ - { - "comment": "Teach React Native CLI about master and 0.61 versions", - "author": "ngerlem@microsoft.com", - "commit": "407c0834ada43cd9d42c24cb6ddfe7c91ddf960a" - } - ] - } - }, - { - "date": "Thu, 27 Feb 2020 18:38:20 GMT", - "tag": "rnpm-plugin-windows_v0.5.1-0", - "version": "0.5.1-0", - "comments": { - "none": [ - { - "comment": "Move rnpm-plugin-windows package out of current", - "author": "acoates@microsoft.com", - "commit": "2a2bf8556317d97b52c8339b038943b484864f77" - } - ] - } - }, - { - "date": "Tue, 11 Feb 2020 01:21:44 GMT", - "tag": "rnpm-plugin-windows_v0.5.1-0", - "version": "0.5.1-0", - "comments": { - "prerelease": [ - { - "comment": "Fix CLI dependency", - "author": "acoates@microsoft.com", - "commit": "33f9509e627c111fa5582e11c78d0b00a3b6ce05" - } - ] - } - }, - { - "date": "Tue, 17 Dec 2019 23:33:28 GMT", - "tag": "rnpm-plugin-windows_v0.4.0", - "version": "0.4.0", - "comments": { - "minor": [ - { - "comment": "add prompt to CLI", - "author": "kmelmon@microsoft.com", - "commit": "364e3cd867a026a9f57f0cb526be03bd5300a39d" - } - ] - } - }, - { - "date": "Tue, 17 Dec 2019 21:45:01 GMT", - "tag": "rnpm-plugin-windows_v0.3.9", - "version": "0.3.9", - "comments": { - "patch": [ - { - "comment": "CLI detect project name from app.json", - "author": "licanhua@live.com", - "commit": "ed24ef5033bac55fb8f0db6ee727051521e4682c" - } - ] - } - }, - { - "date": "Wed, 06 Nov 2019 13:58:14 GMT", - "tag": "rnpm-plugin-windows_v0.3.8", - "version": "0.3.8", - "comments": { - "patch": [ - { - "comment": "This change enables consuming JSI implementations where the referenced JSI headers differs from the JSI headers in react-native.", - "author": "anandrag@microsoft.com", - "commit": "04b58d679ba04baca23348928fad5250a34d31b9" - } - ] - } - }, - { - "date": "Thu, 17 Oct 2019 20:58:22 GMT", - "tag": "rnpm-plugin-windows_v0.3.7", - "version": "0.3.7", - "comments": { - "patch": [ - { - "comment": "Fix two issues: 1) you cannot animated 2 subchannels of the same property with different animations. to fix this we animated yet another property set for translation and scale owned by the props nodes and use one animation to animate all of the subchannels for the uiElement. 2) Reference parameter names which started with a multi digit number are unsupported so i added an n to the start of each name, which was previously just the node's tag.", - "author": "stpete@microsoft.com", - "commit": "62049fdbd667fc71ae09b09f074446d8593d826d" - } - ] - } - }, - { - "date": "Tue, 15 Oct 2019 13:59:27 GMT", - "tag": "rnpm-plugin-windows_v0.3.6", - "version": "0.3.6", - "comments": { - "patch": [ - { - "comment": "Updates logic for `wpf` command to install correct dependency", - "author": "erozell@outlook.com", - "commit": "2325263a2cd4bd66ae7f78f2fa01650aee280345" - } - ] - } - }, - { - "date": "Thu, 03 Oct 2019 22:17:13 GMT", - "tag": "rnpm-plugin-windows_v0.3.5", - "version": "0.3.5", - "comments": { - "none": [ - { - "comment": "Support contextMenuHidden", - "author": "dida@ntdev.microsoft.com", - "commit": "18b68810d1f1687889909782e47750afe6f06b24" - } - ] - } - }, - { - "date": "Tue, 01 Oct 2019 18:17:42 GMT", - "tag": "rnpm-plugin-windows_v0.3.5", - "version": "0.3.5", - "comments": { - "patch": [ - { - "comment": "The customer provided examples revealed a few of issues. One, we were dubble counding the starting value of animatiosn in some cases. Two we were incorrectly relying on JS to tell us to flatten our animated values. Three we were detaching the expression animations that tied the property to the UIElement and in certain cases the JS thread does not inform us that we need to rebuild this cuppling. There is an open issue with this final part #3280", - "author": "stpete@microsoft.com", - "commit": "87e54197b92a06e15acc0d3da7c4016eb3c95448" - } - ] - } - }, - { - "date": "Sat, 28 Sep 2019 01:21:33 GMT", - "tag": "rnpm-plugin-windows_v0.3.0", - "version": "0.3.0", - "comments": { - "minor": [ - { - "comment": "add support for cpp", - "author": "email not defined", - "commit": "10233b95839d33eb57d32eaa6b67462f643884c4" - } - ] - } - }, - { - "date": "Tue, 24 Sep 2019 19:11:20 GMT", - "tag": "rnpm-plugin-windows_v0.2.13", - "version": "0.2.13", - "comments": { - "patch": [ - { - "comment": "Support latest react-native-cli", - "author": "acoates@microsoft.com", - "commit": "704b5b46704d5638293c3f6ff0f3bd09e6bfa809" - } - ] - } - } - ] -} \ No newline at end of file diff --git a/packages/rnpm-plugin-windows/CHANGELOG.md b/packages/rnpm-plugin-windows/CHANGELOG.md deleted file mode 100644 index 3e9ac981f07..00000000000 --- a/packages/rnpm-plugin-windows/CHANGELOG.md +++ /dev/null @@ -1,70 +0,0 @@ -# Change Log - rnpm-plugin-windows - -This log was last generated on Wed, 25 Mar 2020 20:04:59 GMT and should not be manually modified. - -## 0.6.1 -Wed, 25 Mar 2020 20:04:59 GMT - -### Patches - -- allow CLI to install from file: (kmelmon@microsoft.com) -## 0.6.0 -Tue, 24 Mar 2020 22:51:22 GMT - -### Minor changes - -- Teach React Native CLI about master and 0.61 versions (ngerlem@microsoft.com) -## 0.5.1-0 -Tue, 11 Feb 2020 01:21:44 GMT - -### Changes - -- Fix CLI dependency (acoates@microsoft.com) -## 0.4.0 -Tue, 17 Dec 2019 23:33:28 GMT - -### Minor changes - -- add prompt to CLI (kmelmon@microsoft.com) -## 0.3.9 -Tue, 17 Dec 2019 21:45:01 GMT - -### Patches - -- CLI detect project name from app.json (licanhua@live.com) -## 0.3.8 -Wed, 06 Nov 2019 13:58:14 GMT - -### Patches - -- This change enables consuming JSI implementations where the referenced JSI headers differs from the JSI headers in react-native. (anandrag@microsoft.com) -## 0.3.7 -Thu, 17 Oct 2019 20:58:22 GMT - -### Patches - -- Fix two issues: 1) you cannot animated 2 subchannels of the same property with different animations. to fix this we animated yet another property set for translation and scale owned by the props nodes and use one animation to animate all of the subchannels for the uiElement. 2) Reference parameter names which started with a multi digit number are unsupported so i added an n to the start of each name, which was previously just the node's tag. (stpete@microsoft.com) -## 0.3.6 -Tue, 15 Oct 2019 13:59:27 GMT - -### Patches - -- Updates logic for `wpf` command to install correct dependency (erozell@outlook.com) -## 0.3.5 -Tue, 01 Oct 2019 18:17:42 GMT - -### Patches - -- The customer provided examples revealed a few of issues. One, we were dubble counding the starting value of animatiosn in some cases. Two we were incorrectly relying on JS to tell us to flatten our animated values. Three we were detaching the expression animations that tied the property to the UIElement and in certain cases the JS thread does not inform us that we need to rebuild this cuppling. There is an open issue with this final part #3280 (stpete@microsoft.com) -## 0.3.0 -Sat, 28 Sep 2019 01:21:33 GMT - -### Minor changes - -- add support for cpp (email not defined) -## 0.2.13 -Tue, 24 Sep 2019 19:11:20 GMT - -### Patches - -- Support latest react-native-cli (acoates@microsoft.com) \ No newline at end of file diff --git a/packages/rnpm-plugin-windows/README.md b/packages/rnpm-plugin-windows/README.md deleted file mode 100644 index e55920a0a16..00000000000 --- a/packages/rnpm-plugin-windows/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# RNPM Plugin for Universal Windows - -To bootstrap the creation of Windows projects for React Native, we've published `rnpm-plugin-windows`. The purpose of this plugin is to provide project init functionality comparable to `react-native init` and `react-native android`, and to allow users to build and run React Windows applications from the command line. - -## Project Initialization - -To start, make sure you have the react-native CLI installed globally. - -``` -npm install -g react-native-cli -``` - -Once the CLI is installed, install rnpm-plugin-windows and initialize your project. Note: if you have Yarn installed, the react-native-cli will prefer to use that instead of npm, so use yarn to install `rnpm-plugin-windows`. - -``` -npm install --save-dev rnpm-plugin-windows -react-native windows -``` - -The `windows` command will do the following: -- Install `react-native-windows` from [NPM](https://www.npmjs.com/package/react-native-windows) -- Read the name of your project from `package.json` -- Use [Yeoman](http://yeoman.io/) to generate the Windows project files. - -### Usage - -``` -react-native windows [name] [--namespace ] [--windowsVersion ] -``` - -The `windows` command takes an optional command line argument. -- `name` - The name of the project, which will be used for both file names and the name of the component that is registered in the React Native [AppRegistry](https://facebook.github.io/react-native/docs/appregistry.html). Default value is the name given in the root-level `package.json`. - -The `windows` command accepts two optional flags. -- `--namepace` - The namespace that will be used in the generated native C# code. Default value is `name`. -- `--windowsVersion` - The version of `react-native-windows` that will be used. Default value is matches the major and minor version of `react-native` if installed, otherwise the latest version. - -### React Native 0.27.* -> 0.30.* - -For versions of react-native prior to 0.31.0, you'll need to use the [rnpm](http://github.com/rnpm/rnpm) global CLI to run the `windows` command. Since the RNPM plugin syntax for the react-native CLI is not backward compatibile with rnpm, you'll need to use an older version of `rnpm-plugin-windows`: - -``` -npm install --save-dev rnpm-plugin-windows@0.1.* -``` - -## Running React Windows Applications - -Once `react-native-windows` is installed in your project, an additional RNPM plugin for running Windows apps is exposed to the `react-native-cli`. To deploy your app to Desktop, execute: -``` -react-native run-windows -``` -For more information on the kinds of options and flags available for deploying to devices and emulators, use the `--help` flag to get the command usage information. diff --git a/packages/rnpm-plugin-windows/index.js b/packages/rnpm-plugin-windows/index.js deleted file mode 100644 index bdd2e8b364c..00000000000 --- a/packages/rnpm-plugin-windows/index.js +++ /dev/null @@ -1,43 +0,0 @@ -module.exports = [{ - func: require('./src/windows'), - description: 'Generate React Native Windows template project', - name: 'windows [name]', - options: [{ - command: '--windowsVersion [version]', - description: 'The version of react-native-windows to use.', - }, { - command: '--namespace [namespace]', - description: 'The native project namespace.', - }, { - command: '--verbose', - description: 'Enables logging.', - default: false, - }, { - command: '--template [template]', - description: 'Template to install. E.g., `vnext`.', - }, { - command: '--language [language]', - description: 'Which language the template app is written in. Possible values are cs and cpp', - default: 'cpp', - }, { - command: '--overwrite', - description: 'Overwrite any existing files without prompting', - default: false, - }], -},{ - func: require('./src/wpf'), - description: 'Generate React Native Windows template project on WPF', - name: 'wpf [name]', - options: [{ - command: '--windowsVersion [version]', - description: 'The version of react-native-wpf to use.', - }, { - command: '--namespace [namespace]', - description: 'The native project namespace.', - }, { - command: '--verbose', - description: 'Enables logging', - default: false, - }], -}, -]; diff --git a/packages/rnpm-plugin-windows/package.json b/packages/rnpm-plugin-windows/package.json deleted file mode 100644 index e1a1366e3c9..00000000000 --- a/packages/rnpm-plugin-windows/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "rnpm-plugin-windows", - "version": "0.6.1", - "description": "rnpm plugin that generates a Windows template project", - "main": "index.js", - "keywords": [ - "rnpm", - "react-native", - "react-native-windows", - "rnpm windows" - ], - "repository": { - "type": "git", - "url": "https://github.com/Microsoft/react-native-windows.git" - }, - "engines": { - "node": ">= 4.0.0" - }, - "license": "MIT", - "peerDependencies": { - "react-native": ">=0.31.0" - }, - "dependencies": { - "chalk": "^1.1.3", - "extract-zip": "^1.6.7", - "fs-extra": "^7.0.1", - "npm-registry": "^0.1.13", - "prompts": "^2.3.0", - "request": "^2.88.0", - "semver": "^6.1.1", - "valid-url": "^1.0.9" - } -} diff --git a/packages/rnpm-plugin-windows/react-native.config.js b/packages/rnpm-plugin-windows/react-native.config.js deleted file mode 100644 index 0ab8a95efe9..00000000000 --- a/packages/rnpm-plugin-windows/react-native.config.js +++ /dev/null @@ -1,5 +0,0 @@ -// @ts-check - -module.exports = { - commands: require('./index'), -}; diff --git a/packages/rnpm-plugin-windows/src/common.js b/packages/rnpm-plugin-windows/src/common.js deleted file mode 100644 index 653f6a25762..00000000000 --- a/packages/rnpm-plugin-windows/src/common.js +++ /dev/null @@ -1,196 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - */ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const semver = require('semver'); -const Registry = require('npm-registry'); -const child_process = require('child_process'); -const validUrl = require('valid-url'); - -let npmConfReg = child_process.execSync('npm config get registry').toString().trim(); -let NPM_REGISTRY_URL = validUrl.is_uri(npmConfReg) ? npmConfReg : 'http://registry.npmjs.org'; - -const REACT_NATIVE_PACKAGE_JSON_PATH = function() { - return path.resolve( - process.cwd(), - 'node_modules', - 'react-native', - 'package.json' - ); -}; - -const npm = new Registry({registry: NPM_REGISTRY_URL}); - -function getLatestVersion() { - return new Promise(function (resolve, reject) { - npm.packages.release('react-native-windows', 'latest', (err, releases) => { - if (err) { - reject(err); - } else if (!releases || releases.length === 0) { - reject(new Error('Could not find react-native-windows@latest.')); - } else { - resolve(releases[0].version); - } - }); - }); -} - -function isTagMatch(packageVersion, requestTag) { - const prerelease = semver.prerelease(packageVersion); - if (prerelease === null && !requestTag) { - return true; - } else { - return prerelease && prerelease[0] === requestTag; - } -} - -function isVersionMatch(packageVersion, requestVersion, requestTag) { - if (semver.parse(packageVersion) === null) { - return false; - } - - const { major, minor } = semver.parse(packageVersion); - const minVersion = semver.minVersion(requestVersion); - return major === minVersion.major && - minor === minVersion.minor && - isTagMatch(packageVersion, requestTag); -} - -function getLatestMatchingVersion(versionRange, tag) { - return new Promise((resolve, reject) => { - // Ignore the version range of React Native if asking for master, since our - // RNW version may not align. - if (tag === 'master') { - npm.packages.release('react-native-windows', 'master', (err, rel) => { - if (err) { - reject(err); - } else { - resolve(rel[0].version); - } - }); - } else { - npm.packages.releases('react-native-windows', (err, rels) => { - if (err) { - reject(err); - } else { - const matchingVersions = Object.keys(rels) - .filter(v => isVersionMatch(v, versionRange, tag)) - .sort(semver.rcompare); - - if (matchingVersions.length > 0) { - resolve(matchingVersions[0]); - } else { - reject(); - } - } - }); - } - }); -} - -/** - * Matches a version range to a version of react-native-windows to install. This is a hairy process - * with a few different cases. Note that we will not run this at all if an exact version was given - * for --windowsVersion. - * - * - If no version was specified we are passed a range based on React Native version. E.g. "0.61.*". - * We will try to match this against available packages, but need special rules for prerelease - * tags since we use them for even stable releases for several versions. Because of that we cannot - * use the semver range directly. - * - * - If our tag is "master", we grab the latest master label builds, since our RN version may not - * correspond to our RNW version. This will change once we're aligned to Facebook's master builds. - * - * - Users can pass in a range to --windowsVersion and we will try to respect it according to above - * matching logic. We likely do not do the right thing here in many cases sine we do not query the - * registry for the range directly, instead using custom logic to also ensure tag matches. - */ -async function getMatchingVersion(versionRange, tag) { - const versionStr = tag === 'master' ? 'master' : versionRange; - console.log(`Checking for react-native-windows version matching ${versionStr}...`); - - try { - return await getLatestMatchingVersion(versionRange, tag); - } catch (ex) { - const latestVersion = await getLatestVersion(); - throw new Error(`Could not find react-native-windows@${versionStr}. ` + - `Latest version of react-native-windows is ${latestVersion}, try switching to ` + - `react-native@${semver.major(latestVersion)}.${semver.minor(latestVersion)}.*.`); - } -} - -const isSupportedVersion = function(validVersion, validRange) { - // Allow 0.0.0-x master builds - if (validVersion) { - return semver.lt(validVersion, '0.0.0') || semver.gte(validVersion, '0.27.0'); - } else if (validRange) { - return semver.gtr('0.0.0', validRange) || semver.ltr('0.27.0', validRange); - } else { - return false; - } -}; - -const getInstallPackage = function (version, tag) { - const packageToInstall = 'react-native-windows'; - const validVersion = semver.valid(version); - const validRange = semver.validRange(version); - - if (!isSupportedVersion(validVersion, validRange)) { - console.error( - 'Please upgrade react-native to ^0.27 or specify a --windowsVersion that is >=0.27.0' - ); - process.exit(1); - } - - if (validVersion) { - return Promise.resolve(`${packageToInstall}@${version}`); - } else { - return getMatchingVersion(version, tag) - .then(resultVersion => `${packageToInstall}@${resultVersion}`); - } -}; - -const getReactNativeVersion = function () { - console.log('Reading react-native version from node_modules...'); - if (fs.existsSync(REACT_NATIVE_PACKAGE_JSON_PATH())) { - const version = JSON.parse(fs.readFileSync(REACT_NATIVE_PACKAGE_JSON_PATH(), 'utf-8')).version; - return `${semver.major(version)}.${semver.minor(version)}.*`; - } -}; - -const getReactNativeAppName = function () { - console.log('Reading application name from package.json...'); - let name = JSON.parse(fs.readFileSync('package.json', 'utf8')).name; - if (!name) { - if (fs.existsSync('app.json')) { - console.log('Reading application name from app.json...'); - name = JSON.parse(fs.readFileSync('app.json', 'utf8')).name; - } - } - if (!name) { - console.error('Please specify name in package.json or app.json'); - } - return name; -}; - -/** - * Check that 'react-native init' itself used yarn to install React Native. - * When using an old global react-native-cli@1.0.0 (or older), we don't want - * to install React Native with npm, and React + Jest with yarn. - * Let's be safe and not mix yarn and npm in a single project. - * @param projectDir e.g. /Users/martin/AwesomeApp - */ -const isGlobalCliUsingYarn = function(projectDir) { - return fs.existsSync(path.join(projectDir, 'yarn.lock')); -}; - -module.exports = { - getInstallPackage, - getReactNativeVersion, - getReactNativeAppName, - isGlobalCliUsingYarn, -}; diff --git a/packages/rnpm-plugin-windows/src/windows.js b/packages/rnpm-plugin-windows/src/windows.js deleted file mode 100644 index 502ce3640de..00000000000 --- a/packages/rnpm-plugin-windows/src/windows.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - */ -'use strict'; - -const Common = require('./common'); -const chalk = require('chalk'); -const execSync = require('child_process').execSync; -const path = require('path'); -const prompts = require('prompts'); -const semver = require('semver'); - -const REACT_NATIVE_WINDOWS_GENERATE_PATH = function() { - return path.resolve( - process.cwd(), - 'node_modules', - 'react-native-windows', - 'local-cli', - 'generate-windows.js' - ); -}; - -async function getDefaultVersionTag(version) { - const validVersion = semver.valid(version); - const validRange = semver.validRange(version); - if (!validVersion && !validRange) { - console.error(chalk.red(`'${version}' is not a valid version`)); - process.exit(1); - } - - // 0.57 and below had stable untagged releases - if ((validVersion && semver.lt(validVersion, '0.58.0')) - || (validRange && semver.gtr('0.58.0', validRange))) { - return null; - } - - // 0.58 went to RC (See #2559) - if ((validVersion && semver.lt(validVersion, '0.59.0')) - || (validRange && semver.gtr('0.59.0', validRange))) { - return 'rc'; - } - - // 0.59 tags releases as "legacy" or "vnext" - if ((validVersion && semver.lt(validVersion, '0.60.0')) - || (validRange && semver.gtr('0.60.0', validRange))) { - return (await prompts({ - type: 'select', - name: 'template', - message: 'What version of react-native-windows would you like to install?', - choices: [ - { value: 'vnext', title: ' Latest - High performance react-native-windows built on a shared C++ core from facebook (supports C++ or C#).' }, - { value: 'legacy', title: ' Legacy - Older react-native-windows implementation - (C# only, react-native <= 0.59 only)' }, - ], - })).template; - } - - // 0.60 releases all use the vnext tag - if ((validVersion && semver.lt(validVersion, '0.61.0')) - || (validRange && semver.gtr('0.61.0', validRange))) { - return 'vnext'; - } - - // 0.61 and after don't tag stable releases - return null; -} - -module.exports = async function (config, args, options) { - try { - const name = args[0] || Common.getReactNativeAppName(); - const ns = options.namespace || name; - const version = options.windowsVersion || Common.getReactNativeVersion(); - let rnwPackage = version; - // If the version is a file: link, there's no need to compute what package to install. - // This is useful when testing local changes to the repo that haven't been published yet. - if (!version.startsWith("file:")) { - const versionTag = options.template || await getDefaultVersionTag(version); - - rnwPackage = await Common.getInstallPackage(version, versionTag); - } - - console.log(`Installing ${rnwPackage}...`); - const pkgmgr = Common.isGlobalCliUsingYarn(process.cwd()) ? 'yarn add' : 'npm install --save'; - - const execOptions = options.verbose ? { stdio: 'inherit' } : {}; - execSync(`${pkgmgr} ${rnwPackage}`, execOptions); - console.log(chalk.green(`${rnwPackage} successfully installed.`)); - - const generateWindows = require(REACT_NATIVE_WINDOWS_GENERATE_PATH()); - generateWindows(process.cwd(), name, ns, options); - } catch (error) { - console.error(chalk.red(error.message)); - console.error(error); - process.exit(1); - } -}; diff --git a/packages/rnpm-plugin-windows/src/wpf.js b/packages/rnpm-plugin-windows/src/wpf.js deleted file mode 100644 index 3a6821c2e30..00000000000 --- a/packages/rnpm-plugin-windows/src/wpf.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - */ -'use strict'; - -const Common = require('./common'); -const chalk = require('chalk'); -const execSync = require('child_process').execSync; -const path = require('path'); - -const REACT_NATIVE_WPF_GENERATE_PATH = function() { - return path.resolve( - process.cwd(), - 'node_modules', - 'react-native-windows', - 'local-cli', - 'generate-wpf.js' - ); -}; - -module.exports = function (config, args, options) { - const name = args[0] ? args[0] : Common.getReactNativeAppName(); - const ns = options.namespace ? options.namespace : name; - const version = options.windowsVersion ? options.windowsVersion : Common.getReactNativeVersion(); - - // If the template is not set, look for a stable or 'rc' version - const template = options.template ? options.template : 'rc'; - - return Common.getInstallPackage(version, template) - .then(rnwPackage => { - console.log(`Installing ${rnwPackage}...`); - const pkgmgr = Common.isGlobalCliUsingYarn(process.cwd()) ? 'yarn add' : 'npm install --save'; - - const execOptions = options.verbose ? { stdio: 'inherit' } : {}; - execSync(`${pkgmgr} ${rnwPackage}`, execOptions); - console.log(chalk.green(`${rnwPackage} successfully installed.`)); - - const generateWPF = require(REACT_NATIVE_WPF_GENERATE_PATH()); - generateWPF(process.cwd(), name, ns, options); - }).catch(error => console.error(chalk.red(error.message))); -}; diff --git a/vnext/local-cli/runWindows/utils/info.js b/vnext/local-cli/runWindows/utils/info.js index cf87af941c0..dd13c6d2e2a 100644 --- a/vnext/local-cli/runWindows/utils/info.js +++ b/vnext/local-cli/runWindows/utils/info.js @@ -16,7 +16,6 @@ async function getEnvironmentInfo() { 'react-native', 'react-native-windows', '@react-native-community/cli', - 'rnpm-plugin-windows', 'react-native-cli', ], npmGlobalPackages: ['*react-native*'], From edc1b872aff9646fe24e66ca7c2fefbf31738541 Mon Sep 17 00:00:00 2001 From: Jon Thysell Date: Mon, 27 Apr 2020 10:56:45 -0700 Subject: [PATCH 004/209] Fixes husky missing error (#4727) Closes #4726. --- package.json | 1 + yarn.lock | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 5974c76d111..93cabef865c 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ }, "devDependencies": { "beachball": "^1.13.4", + "husky": "^4.2.5", "lerna": "^3.16.1" }, "resolutions": { diff --git a/yarn.lock b/yarn.lock index 0ad06fd74de..ac94a5d1e08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4952,6 +4952,14 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3 escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" + integrity sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" @@ -5299,6 +5307,11 @@ compare-versions@^3.4.0: resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.5.1.tgz#26e1f5cf0d48a77eced5046b9f67b6b61075a393" integrity sha512-9fGPIB7C6AyM18CJJBHt5EnCZDG3oiTJYy0NjfIAGjKpzv0tkxWko7TNQHF5ymqm7IH03tqmeuBxtvD+Izh6mg== +compare-versions@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" + integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -6906,7 +6919,7 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.1.0: +find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -6914,6 +6927,13 @@ find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-versions@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" + integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww== + dependencies: + semver-regex "^2.0.0" + fkill@^6.0.0: version "6.2.0" resolved "https://registry.yarnpkg.com/fkill/-/fkill-6.2.0.tgz#a5c0ab65e0469578d0b648a86ac8526fc5ab5fa2" @@ -7598,6 +7618,22 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +husky@^4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/husky/-/husky-4.2.5.tgz#2b4f7622673a71579f901d9885ed448394b5fa36" + integrity sha512-SYZ95AjKcX7goYVZtVZF2i6XiZcHknw50iXvY7b0MiGoj5RwdgRQNEHdb+gPDPCXKlzwrybjFjkL6FOj8uRhZQ== + dependencies: + chalk "^4.0.0" + ci-info "^2.0.0" + compare-versions "^3.6.0" + cosmiconfig "^6.0.0" + find-versions "^3.2.0" + opencollective-postinstall "^2.0.2" + pkg-dir "^4.2.0" + please-upgrade-node "^3.2.0" + slash "^3.0.0" + which-pm-runs "^1.0.0" + iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -10684,6 +10720,11 @@ open@^6.2.0: dependencies: is-wsl "^1.1.0" +opencollective-postinstall@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" + integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw== + openssl-wrapper@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/openssl-wrapper/-/openssl-wrapper-0.3.4.tgz#c01ec98e4dcd2b5dfe0b693f31827200e3b81b07" @@ -11163,6 +11204,20 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +please-upgrade-node@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" + integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== + dependencies: + semver-compare "^1.0.0" + plist@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" @@ -12250,6 +12305,16 @@ selenium-webdriver@3.x: tmp "0.0.30" xml2js "^0.4.17" +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + +semver-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" + integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== + "semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -13829,6 +13894,11 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= +which-pm-runs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" + integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= + which@1, which@^1.2.4, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" From 5034ff3a75a3381117714d805290776ff498597f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:01:26 +0000 Subject: [PATCH 005/209] Bump semver from 7.1.3 to 7.3.2 (#4730) --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index ac94a5d1e08..62232f1c43e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6661,7 +6661,7 @@ extract-github@0.0.x: resolved "https://registry.yarnpkg.com/extract-github/-/extract-github-0.0.5.tgz#f542536db8c19b983a3bec9db96d2ef2a5ff1a86" integrity sha1-9UJTbbjBm5g6O+yduW0u8qX/GoY= -extract-zip@^1.6.0, extract-zip@^1.6.7: +extract-zip@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== @@ -12336,9 +12336,9 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semve integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== semver@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.3.tgz#e4345ce73071c53f336445cfc19efb1c311df2a6" - integrity sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA== + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== semver@~5.3.0: version "5.3.0" From ac3e39f11d2a6d614783cfbe82002946e81813e7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:01:37 +0000 Subject: [PATCH 006/209] Bump fp-ts from 2.5.3 to 2.5.4 (#4729) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 62232f1c43e..ac0d93b847d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7018,9 +7018,9 @@ forwarded@~0.1.2: integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= fp-ts@^2.5.0: - version "2.5.3" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.5.3.tgz#7f09cc7f3e09623c6ade303d98a2cccdb2cc861f" - integrity sha512-lQd+hahLd8cygNoXbEHDjH/cbF6XVWlEPb8h5GXXlozjCSDxWgclvkpOoTRfBA0P+r69l9VvW1nEsSGIJRQpWw== + version "2.5.4" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.5.4.tgz#f184079aaa78403ea66458517be7787e0d593429" + integrity sha512-cZlLeEneRYypc2dOzB9h8+bd9mQhJVyt2g0Dny2gKR7uWNgA4EmLSJyguLYsTU44nJSSG9EjurUalEc0wQqeKw== fragment-cache@^0.2.1: version "0.2.1" From a8ab5f4663454a13bd0b4fd58e7f9e50d473f9fa Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:01:49 +0000 Subject: [PATCH 007/209] Bump envinfo from 7.5.0 to 7.5.1 (#4728) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ac0d93b847d..298a946aa6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6116,9 +6116,9 @@ env-variable@0.0.x: integrity sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA== envinfo@^7.1.0, envinfo@^7.3.1, envinfo@^7.5.0: - version "7.5.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.5.0.tgz#91410bb6db262fb4f1409bd506e9ff57e91023f4" - integrity sha512-jDgnJaF/Btomk+m3PZDTTCb5XIIIX3zYItnCRfF73zVgvinLoRomuhi75Y4su0PtQxWz4v66XnLLckyvyJTOIQ== + version "7.5.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.5.1.tgz#93c26897225a00457c75e734d354ea9106a72236" + integrity sha512-hQBkDf2iO4Nv0CNHpCuSBeaSrveU6nThVxFGTrq/eDlV716UQk09zChaJae4mZRsos1x4YLY2TaH3LHUae3ZmQ== err-code@^1.0.0: version "1.1.2" From c440b35fa8bb9dd608a7a48cb84019655f75629d Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Mon, 27 Apr 2020 16:47:25 -0700 Subject: [PATCH 008/209] Delete vnext\README.md and create a build task to copy the root one to vnext\ (#4731) * Use readme file from root of repo for react-native-windows * Change files --- README.md | 4 +-- ...ve-windows-2020-04-27-11-58-10-readme.json | 8 +++++ vnext/.gitignore | 3 ++ vnext/README.md | 33 ------------------- vnext/just-task.js | 9 +++++ 5 files changed, 22 insertions(+), 35 deletions(-) create mode 100644 change/react-native-windows-2020-04-27-11-58-10-readme.json delete mode 100644 vnext/README.md diff --git a/README.md b/README.md index cbc480fc7b1..5145a32ee2f 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@

-![Hero Image with Logo](./.github/hero2.png) +![Hero Image with Logo](https://github.com/microsoft/react-native-windows/raw/master/.github/hero2.png) > See the official [React Native website](https://reactnative.dev/) for an introduction to React Native. @@ -57,7 +57,7 @@ Search the [existing issues](https://github.com/microsoft/react-native-windows/i The GitHub issues are intended for bug reports and feature requests. For help and questions with using the React Native Windows plugin please make use of the resources listed our main README's the [Getting Help](https://github.com/microsoft/react-native-windows#getting-help) section. ## Contributing -See [Contributing guidelines](./docs/contributing.md) for how to setup your fork of the repo and start a PR to contribute to React Native for Windows. +See [Contributing guidelines](https://github.com/microsoft/react-native-windows/blob/master/docs/contributing.md) for how to setup your fork of the repo and start a PR to contribute to React Native for Windows. [Good First Task](https://github.com/microsoft/react-native-windows/labels/Good%20First%20Task) and [help wanted](https://github.com/microsoft/react-native-windows/labels/help%20wanted) are great starting points for PRs. diff --git a/change/react-native-windows-2020-04-27-11-58-10-readme.json b/change/react-native-windows-2020-04-27-11-58-10-readme.json new file mode 100644 index 00000000000..2ca20ee2410 --- /dev/null +++ b/change/react-native-windows-2020-04-27-11-58-10-readme.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Use readme file from root of repo for react-native-windows", + "packageName": "react-native-windows", + "email": "acoates@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-27T18:58:10.453Z" +} diff --git a/vnext/.gitignore b/vnext/.gitignore index 6377e5c79c4..30a7d146fa2 100644 --- a/vnext/.gitignore +++ b/vnext/.gitignore @@ -85,3 +85,6 @@ temp /coverage /third-party /packages/ + +# Copied from root as part of build +/README.md \ No newline at end of file diff --git a/vnext/README.md b/vnext/README.md deleted file mode 100644 index eed88ab92d0..00000000000 --- a/vnext/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# ReactNative for Windows -![Hero Image with Logo](https://raw.githubusercontent.com/microsoft/react-native-windows/master/.github/hero2.png) - -> See the official [React Native website](https://facebook.github.io/react-native/) for an introduction to React Native. See [main landing page](https://github.com/microsoft/react-native-windows) for more details on overall direction of `react-native-windows`. - -[React Native](https://reactnative.dev) is a framework developed by Facebook that enables you to build world-class application experiences on native platforms using a consistent developer experience based on JavaScript and [React](https://reactjs.org/). The focus of React Native is on developer efficiency across all the platforms you care about - learn once, write anywhere. - -This repository adds support for the [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads), which allows you to build apps for [all devices supported by Windows 10](https://developer.microsoft.com/en-us/windows/get-started-windows-10) including PCs, tablets, 2-in-1s, Xbox, Mixed reality devices etc. - -## Status and roadmap -[Check out our blog](https://microsoft.github.io/react-native-windows/blog/) If you'd like to stay up to date on the status of React Native for Windows and check out current and past roadmaps, We will post all new releases, updates and general news about the project there. - -## Documentation -[React Native already has great documentation](https://reactnative.dev/docs/getting-started.html) and we're working to ensure the React Native Windows is part of that documentation story. - -[React Native for Windows](https://microsoft.github.io/react-native-windows/) has it's own separate documentation site where Windows and Mac specific information, like API docs and blog updates live. - -## Getting Started -See [Getting Started Guide for React Native Windows C++](https://microsoft.github.io/react-native-windows/docs/getting-started). - -## Opening issues -If you encounter a bug with the React Native Windows plugin, we would like to hear about it! - -Search the [existing issues](https://github.com/microsoft/react-native-windows/issues) and try to make sure your problem doesn’t already exist before opening a new issue. If your issue doesn't exist yet, try to make sure you provide as much information as possible to us so we can help you sooner. It’s helpful if you include information like: - -- The version of Windows, React Native, React Native Windows plugin, and device family (i.e., mobile, desktop, Xbox, etc.) where you ran into the issue. -- A stack trace and reduced repro case when possible. -- Ensure the [appropriate template](https://github.com/microsoft/react-native-windows/issues/new?labels=vnext&template=vnext.md) is used when filing your issue(s). - -The GitHub issues are intended for bug reports and feature requests. For help and questions with using the React Native Windows plugin please make use of the resources listed our main README's the [Getting Help](https://github.com/microsoft/react-native-windows#getting-help) section. - -## Contributing -See [Contributing guidelines](./docs/CONTRIBUTING.md) for how to setup your fork of the repo and start a PR to contribute to React Native Windows vNext. diff --git a/vnext/just-task.js b/vnext/just-task.js index dc0c2e9a25e..bf440f6c14f 100644 --- a/vnext/just-task.js +++ b/vnext/just-task.js @@ -20,6 +20,7 @@ const { cleanTask, } = require('just-scripts'); const {execSync} = require('child_process'); +const fs = require('fs'); const libPath = path.resolve(process.cwd(), 'lib'); const srcPath = path.resolve(process.cwd(), 'src'); @@ -61,6 +62,13 @@ task('initRNLibraries', () => { require('./Scripts/copyRNLibraries').copyRNLibraries(__dirname); }); +task('copyReadmeFromRoot', () => { + fs.copyFileSync( + path.resolve(__dirname, '../README.md'), + path.resolve(__dirname, 'README.md'), + ); +}); + task('ts', () => { return tscTask({ pretty: true, @@ -86,6 +94,7 @@ task( condition('clean', () => true || argv().clean), 'initRNLibraries', 'copyFlowFiles', + 'copyReadmeFromRoot', 'ts', 'codegen', condition('apiExtractorVerify', () => argv().ci), From 2453f8e8ea999c28912a23a0838d2505629c3098 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Tue, 28 Apr 2020 00:04:13 +0000 Subject: [PATCH 009/209] applying package updates ***NO_CI*** --- ...ative-win32-2020-04-27-09-42-09-uprex.json | 8 ----- ...020-04-26-21-09-42-MS_Cs_ReactContext.json | 8 ----- ...e-windows-2020-04-27-09-14-14-delrnpm.json | 8 ----- ...ve-windows-2020-04-27-11-58-10-readme.json | 8 ----- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- packages/react-native-win32/CHANGELOG.json | 15 ++++++++++ vnext/CHANGELOG.json | 29 +++++++++++++++++++ vnext/CHANGELOG.md | 11 ++++++- vnext/package.json | 2 +- 11 files changed, 58 insertions(+), 37 deletions(-) delete mode 100644 change/@office-iss-react-native-win32-2020-04-27-09-42-09-uprex.json delete mode 100644 change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json delete mode 100644 change/react-native-windows-2020-04-27-09-14-14-delrnpm.json delete mode 100644 change/react-native-windows-2020-04-27-11-58-10-readme.json diff --git a/change/@office-iss-react-native-win32-2020-04-27-09-42-09-uprex.json b/change/@office-iss-react-native-win32-2020-04-27-09-42-09-uprex.json deleted file mode 100644 index 6cb87e75fcd..00000000000 --- a/change/@office-iss-react-native-win32-2020-04-27-09-42-09-uprex.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "none", - "comment": "Update rex-win32 version to something more recent", - "packageName": "@office-iss/react-native-win32", - "email": "acoates@microsoft.com", - "dependentChangeType": "none", - "date": "2020-04-27T16:42:09.664Z" -} diff --git a/change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json b/change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json deleted file mode 100644 index 76cefbe6c3f..00000000000 --- a/change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Added C# ReactContext for Module Initialize method", - "packageName": "react-native-windows", - "email": "vmorozov@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-27T04:09:42.583Z" -} diff --git a/change/react-native-windows-2020-04-27-09-14-14-delrnpm.json b/change/react-native-windows-2020-04-27-09-14-14-delrnpm.json deleted file mode 100644 index 4b5933ed081..00000000000 --- a/change/react-native-windows-2020-04-27-09-14-14-delrnpm.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "none", - "comment": "Remove rnpm-plugin-windows", - "packageName": "react-native-windows", - "email": "acoates@microsoft.com", - "dependentChangeType": "none", - "date": "2020-04-27T16:14:12.892Z" -} diff --git a/change/react-native-windows-2020-04-27-11-58-10-readme.json b/change/react-native-windows-2020-04-27-11-58-10-readme.json deleted file mode 100644 index 2ca20ee2410..00000000000 --- a/change/react-native-windows-2020-04-27-11-58-10-readme.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Use readme file from root of repo for react-native-windows", - "packageName": "react-native-windows", - "email": "acoates@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-27T18:58:10.453Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index 4f080c7ea22..fa480484cbd 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.9.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.50" + "react-native-windows": "0.0.0-master.51" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 7889e67990c..7f23d6ee126 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.9.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.50" + "react-native-windows": "0.0.0-master.51" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index 098dc6aed60..e94fc798c83 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.9.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.50" + "react-native-windows": "0.0.0-master.51" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/react-native-win32/CHANGELOG.json b/packages/react-native-win32/CHANGELOG.json index 3c83cf0780f..8ee394f3883 100644 --- a/packages/react-native-win32/CHANGELOG.json +++ b/packages/react-native-win32/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@office-iss/react-native-win32", "entries": [ + { + "date": "Tue, 28 Apr 2020 00:04:13 GMT", + "tag": "@office-iss/react-native-win32_v0.0.0-master.6", + "version": "0.0.0-master.6", + "comments": { + "none": [ + { + "comment": "Update rex-win32 version to something more recent", + "author": "acoates@microsoft.com", + "commit": "fc72e04428dff1c31acdb9183f3ce95a0a5a53c1", + "package": "@office-iss/react-native-win32" + } + ] + } + }, { "date": "Sat, 18 Apr 2020 00:04:34 GMT", "tag": "@office-iss/react-native-win32_v0.0.0-master.6", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index 30b3eccd58f..33b68acc93c 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,35 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Tue, 28 Apr 2020 00:04:13 GMT", + "tag": "react-native-windows_v0.0.0-master.51", + "version": "0.0.0-master.51", + "comments": { + "prerelease": [ + { + "comment": "Added C# ReactContext for Module Initialize method", + "author": "vmorozov@microsoft.com", + "commit": "51368d02d2d0961411707c40901bf8d1bb20e1c4", + "package": "react-native-windows" + }, + { + "comment": "Use readme file from root of repo for react-native-windows", + "author": "acoates@microsoft.com", + "commit": "c440b35fa8bb9dd608a7a48cb84019655f75629d", + "package": "react-native-windows" + } + ], + "none": [ + { + "comment": "Remove rnpm-plugin-windows", + "author": "acoates@microsoft.com", + "commit": "793ec2523ab10db23def810a2f41f68957766941", + "package": "react-native-windows" + } + ] + } + }, { "date": "Mon, 27 Apr 2020 00:04:59 GMT", "tag": "react-native-windows_v0.0.0-master.50", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 8ecfa6664aa..5a00ceb2719 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,18 @@ # Change Log - react-native-windows -This log was last generated on Mon, 27 Apr 2020 00:04:59 GMT and should not be manually modified. +This log was last generated on Tue, 28 Apr 2020 00:04:13 GMT and should not be manually modified. +## 0.0.0-master.51 + +Tue, 28 Apr 2020 00:04:13 GMT + +### Changes + +- Added C# ReactContext for Module Initialize method (vmorozov@microsoft.com) +- Use readme file from root of repo for react-native-windows (acoates@microsoft.com) + ## 0.0.0-master.50 Mon, 27 Apr 2020 00:04:59 GMT diff --git a/vnext/package.json b/vnext/package.json index d4769198121..78e485fc0a1 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.50", + "version": "0.0.0-master.51", "license": "MIT", "repository": { "type": "git", From 567fc48cf6858ece96ff60fcd52e20cded72cbfc Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Mon, 27 Apr 2020 21:34:15 -0700 Subject: [PATCH 010/209] =?UTF-8?q?Start=20migrating=20WUX=20=F0=9F=91=89?= =?UTF-8?q?=20MUX=20(#4715)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Start forking namespace and includes for WUX->MUX move * move C++/WinRT code to use xaml instead of winrt::Windows::UI::Xaml * move to comp instead of winrt::Windows::UI::Composition * . * Change files * fix merge * Redirect IDL types too * format and fix jsvaluexaml * use XAML_NAMESPACE macro in IDL * PR feedback * format * convert include to forward slashes --- ...ve-windows-2020-04-25-00-45-24-wuxmux.json | 8 + .../ReactModuleBuilderMock.h | 5 +- vnext/Microsoft.ReactNative.Cxx/JSValueXaml.h | 4 +- .../Microsoft.ReactNative/ABIViewManager.cpp | 31 +- vnext/Microsoft.ReactNative/ABIViewManager.h | 19 +- vnext/Microsoft.ReactNative/IReactContext.cpp | 2 +- vnext/Microsoft.ReactNative/IReactContext.h | 2 +- vnext/Microsoft.ReactNative/IReactContext.idl | 4 +- vnext/Microsoft.ReactNative/IViewManager.idl | 16 +- .../Modules/AppStateData.cpp | 2 +- .../Modules/AppStateData.h | 5 +- .../ReactApplication.cpp | 7 +- .../Microsoft.ReactNative/ReactApplication.h | 2 +- .../ReactApplication.idl | 3 +- .../ReactApplicationDelegate.cpp | 2 +- .../ReactApplicationDelegate.h | 6 +- .../ReactApplicationDelegate.idl | 5 +- .../Microsoft.ReactNative/ReactNativeHost.cpp | 4 +- vnext/Microsoft.ReactNative/ReactRootView.idl | 3 +- vnext/Microsoft.ReactNative/RedBox.cpp | 10 +- .../Views/ReactRootControl.cpp | 85 ++- .../Views/ReactRootControl.h | 13 +- vnext/Microsoft.ReactNative/XamlHelper.cpp | 2 +- vnext/Microsoft.ReactNative/XamlHelper.h | 2 +- vnext/Microsoft.ReactNative/XamlHelper.idl | 3 +- vnext/Microsoft.ReactNative/pch.h | 12 +- vnext/ReactUWP/ABI/ReactControl_rt.cpp | 3 +- vnext/ReactUWP/Modules/AlertModuleUwp.cpp | 5 +- .../Modules/Animated/AdditionAnimatedNode.cpp | 2 +- .../Modules/Animated/AnimationDriver.h | 6 +- .../Animated/CalculatedAnimationDriver.cpp | 6 +- .../Animated/CalculatedAnimationDriver.h | 2 +- .../Animated/DiffClampAnimatedNode.cpp | 2 +- .../Modules/Animated/DivisionAnimatedNode.cpp | 2 +- .../Modules/Animated/FrameAnimationDriver.cpp | 6 +- .../Modules/Animated/FrameAnimationDriver.h | 2 +- .../Animated/InterpolationAnimatedNode.cpp | 6 +- .../Animated/InterpolationAnimatedNode.h | 6 +- .../Modules/Animated/ModulusAnimatedNode.cpp | 2 +- .../Animated/MultiplicationAnimatedNode.cpp | 2 +- .../Modules/Animated/PropsAnimatedNode.cpp | 14 +- .../Modules/Animated/PropsAnimatedNode.h | 12 +- .../Animated/SubtractionAnimatedNode.cpp | 2 +- .../Modules/Animated/ValueAnimatedNode.cpp | 4 +- .../Modules/Animated/ValueAnimatedNode.h | 6 +- vnext/ReactUWP/Modules/AppStateModuleUwp.cpp | 10 +- vnext/ReactUWP/Modules/AppStateModuleUwp.h | 5 +- vnext/ReactUWP/Modules/AppThemeModuleUwp.cpp | 2 +- vnext/ReactUWP/Modules/AppThemeModuleUwp.h | 2 +- vnext/ReactUWP/Modules/AppearanceModule.cpp | 4 +- vnext/ReactUWP/Modules/AppearanceModule.h | 2 +- vnext/ReactUWP/Modules/DeviceInfoModule.cpp | 4 +- vnext/ReactUWP/Modules/DeviceInfoModule.h | 1 - .../Modules/ImageViewManagerModule.cpp | 4 +- vnext/ReactUWP/Modules/NativeUIManager.cpp | 56 +- vnext/ReactUWP/Modules/NativeUIManager.h | 8 +- vnext/ReactUWP/Modules/TimingModule.cpp | 5 +- vnext/ReactUWP/Modules/TimingModule.h | 4 +- vnext/ReactUWP/Pch/pch.h | 8 +- .../Polyester/ButtonContentViewManager.cpp | 22 +- .../ReactUWP/Polyester/ButtonViewManager.cpp | 3 - vnext/ReactUWP/Polyester/ButtonViewManager.h | 2 +- .../Polyester/ContentControlViewManager.cpp | 26 +- .../Polyester/HyperlinkViewManager.cpp | 11 +- vnext/ReactUWP/Polyester/IconViewManager.cpp | 11 +- vnext/ReactUWP/Utils/AccessibilityUtils.cpp | 21 +- vnext/ReactUWP/Utils/Helpers.cpp | 11 +- vnext/ReactUWP/Utils/ResourceBrushUtils.cpp | 69 +-- vnext/ReactUWP/Utils/ValueUtils.cpp | 46 +- .../Views/ActivityIndicatorViewManager.cpp | 6 +- vnext/ReactUWP/Views/CheckboxViewManager.cpp | 16 +- vnext/ReactUWP/Views/ControlViewManager.cpp | 39 +- .../ReactUWP/Views/DatePickerViewManager.cpp | 24 +- .../ReactUWP/Views/DynamicAutomationPeer.cpp | 21 +- vnext/ReactUWP/Views/DynamicAutomationPeer.h | 35 +- .../Views/DynamicAutomationProperties.cpp | 115 ++-- .../Views/DynamicAutomationProperties.h | 72 ++- .../Views/ExpressionAnimationStore.cpp | 15 +- .../ReactUWP/Views/ExpressionAnimationStore.h | 10 +- vnext/ReactUWP/Views/FlyoutViewManager.cpp | 43 +- .../Views/FrameworkElementViewManager.cpp | 109 ++-- .../ReactUWP/Views/Image/ImageViewManager.cpp | 3 +- vnext/ReactUWP/Views/Image/ImageViewManager.h | 4 +- vnext/ReactUWP/Views/Image/ReactImage.cpp | 8 +- vnext/ReactUWP/Views/Image/ReactImage.h | 24 +- .../ReactUWP/Views/Image/ReactImageBrush.cpp | 46 +- vnext/ReactUWP/Views/Image/ReactImageBrush.h | 19 +- .../Impl/ScrollViewUWPImplementation.cpp | 2 +- .../Views/Impl/ScrollViewUWPImplementation.h | 7 +- .../Impl/SnapPointManagingContentControl.cpp | 4 +- .../Impl/SnapPointManagingContentControl.h | 16 +- vnext/ReactUWP/Views/KeyboardEventHandler.cpp | 542 +++++++++--------- vnext/ReactUWP/Views/PickerViewManager.cpp | 23 +- vnext/ReactUWP/Views/PopupViewManager.cpp | 34 +- vnext/ReactUWP/Views/RawTextViewManager.cpp | 10 +- vnext/ReactUWP/Views/ReactControl.cpp | 39 +- vnext/ReactUWP/Views/ReactControl.h | 13 +- vnext/ReactUWP/Views/ReactRootView.cpp | 12 +- .../ReactUWP/Views/RefreshControlManager.cpp | 6 +- vnext/ReactUWP/Views/RootViewManager.cpp | 8 +- vnext/ReactUWP/Views/SIPEventHandler.cpp | 11 +- vnext/ReactUWP/Views/SIPEventHandler.h | 2 +- vnext/ReactUWP/Views/ScrollViewManager.cpp | 6 +- vnext/ReactUWP/Views/ShadowNodeBase.cpp | 13 +- vnext/ReactUWP/Views/SliderViewManager.cpp | 10 +- vnext/ReactUWP/Views/SwitchViewManager.cpp | 9 +- vnext/ReactUWP/Views/TextInputViewManager.cpp | 319 ++++++----- vnext/ReactUWP/Views/TextViewManager.cpp | 59 +- vnext/ReactUWP/Views/TouchEventHandler.cpp | 40 +- vnext/ReactUWP/Views/TouchEventHandler.h | 22 +- vnext/ReactUWP/Views/ViewControl.cpp | 10 +- vnext/ReactUWP/Views/ViewControl.h | 5 +- vnext/ReactUWP/Views/ViewManagerBase.cpp | 16 +- vnext/ReactUWP/Views/ViewPanel.cpp | 89 ++- vnext/ReactUWP/Views/ViewPanel.h | 69 +-- vnext/ReactUWP/Views/ViewViewManager.cpp | 36 +- vnext/ReactUWP/Views/ViewViewManager.h | 4 - .../ReactUWP/Views/VirtualTextViewManager.cpp | 8 +- .../Views/cppwinrt/DynamicAutomationPeer.idl | 225 ++++---- vnext/ReactUWP/Views/cppwinrt/ViewPanel.idl | 80 +-- .../UniversalTestInstance.cpp | 22 +- .../UniversalTestRunner.cpp | 8 +- vnext/include/CppWinRTIncludes.h | 61 +- vnext/include/Include.vcxitems | 3 + vnext/include/Include.vcxitems.filters | 3 + vnext/include/NamespaceRedirect.h | 7 + .../ReactUWP/Utils/AccessibilityUtils.h | 12 +- vnext/include/ReactUWP/Utils/Helpers.h | 7 +- vnext/include/ReactUWP/Utils/PropertyUtils.h | 54 +- .../ReactUWP/Utils/ResourceBrushUtils.h | 32 +- vnext/include/ReactUWP/Utils/ValueUtils.h | 15 +- .../Views/FrameworkElementViewManager.h | 14 +- .../ReactUWP/Views/KeyboardEventHandler.h | 41 +- vnext/include/ReactUWP/Views/ShadowNodeBase.h | 4 +- vnext/include/ReactUWP/XamlView.h | 19 +- 135 files changed, 1605 insertions(+), 1739 deletions(-) create mode 100644 change/react-native-windows-2020-04-25-00-45-24-wuxmux.json create mode 100644 vnext/include/NamespaceRedirect.h diff --git a/change/react-native-windows-2020-04-25-00-45-24-wuxmux.json b/change/react-native-windows-2020-04-25-00-45-24-wuxmux.json new file mode 100644 index 00000000000..3bcc1973610 --- /dev/null +++ b/change/react-native-windows-2020-04-25-00-45-24-wuxmux.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Start forking namespace and includes for WUX->MUX move", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-25T07:45:23.932Z" +} diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h index 88ec6935f02..f610d8df4d1 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h @@ -7,13 +7,12 @@ #include "future/future.h" #include +#include "../include/CppWinRTIncludes.h" #include "JSValue.h" #undef GetCurrentTime -#include "Windows.UI.Xaml.h" using namespace winrt; -using namespace Windows::UI::Xaml; namespace winrt::Microsoft::ReactNative { @@ -122,7 +121,7 @@ struct ReactContextMock : implements { ReactContextMock(ReactModuleBuilderMock *builderMock) noexcept; void DispatchEvent( - FrameworkElement const & /*view*/, + xaml::FrameworkElement const & /*view*/, hstring const & /*eventName*/, JSValueArgWriter const & /*eventDataArgWriter*/) noexcept {} diff --git a/vnext/Microsoft.ReactNative.Cxx/JSValueXaml.h b/vnext/Microsoft.ReactNative.Cxx/JSValueXaml.h index 4e98754e53f..ea2ccde92c3 100644 --- a/vnext/Microsoft.ReactNative.Cxx/JSValueXaml.h +++ b/vnext/Microsoft.ReactNative.Cxx/JSValueXaml.h @@ -4,14 +4,14 @@ #pragma once #ifndef MICROSOFT_REACTNATIVE_JSVALUEXAML #define MICROSOFT_REACTNATIVE_JSVALUEXAML - +#include "../include/CppWinRTIncludes.h" #include "JSValue.h" namespace winrt::Microsoft::ReactNative { #ifndef CXXUNITTESTS -inline void ReadValue(JSValue const &jsValue, Windows::UI::Xaml::Media::Brush &value) noexcept { +inline void ReadValue(JSValue const &jsValue, xaml::Media::Brush &value) noexcept { value = XamlHelper::BrushFrom([&jsValue](IJSValueWriter const &writer) noexcept { jsValue.WriteTo(writer); }); } diff --git a/vnext/Microsoft.ReactNative/ABIViewManager.cpp b/vnext/Microsoft.ReactNative/ABIViewManager.cpp index 907d4365c4e..5cecd2ec457 100644 --- a/vnext/Microsoft.ReactNative/ABIViewManager.cpp +++ b/vnext/Microsoft.ReactNative/ABIViewManager.cpp @@ -38,7 +38,7 @@ const char *ABIViewManager::GetName() const { return m_name.c_str(); } -winrt::Windows::UI::Xaml::DependencyObject ABIViewManager::CreateViewCore(int64_t) { +xaml::DependencyObject ABIViewManager::CreateViewCore(int64_t) { auto view = m_viewManager.CreateView(); return view; } @@ -102,7 +102,7 @@ folly::dynamic ABIViewManager::GetNativeProps() const { void ABIViewManager::UpdateProperties(react::uwp::ShadowNodeBase *nodeToUpdate, const folly::dynamic &reactDiffMap) { if (m_viewManagerWithNativeProperties) { - auto view = nodeToUpdate->GetView().as(); + auto view = nodeToUpdate->GetView().as(); IJSValueReader propertyMapReader = winrt::make(reactDiffMap); @@ -132,11 +132,11 @@ folly::dynamic ABIViewManager::GetCommands() const { } void ABIViewManager::DispatchCommand( - const winrt::Windows::UI::Xaml::DependencyObject &viewToUpdate, + const xaml::DependencyObject &viewToUpdate, const std::string &commandId, const folly::dynamic &commandArgs) { if (m_viewManagerWithCommands) { - auto view = viewToUpdate.as(); + auto view = viewToUpdate.as(); IJSValueReader argReader = winrt::make(commandArgs); m_viewManagerWithCommands.DispatchCommand(view, to_hstring(commandId), argReader); @@ -186,40 +186,37 @@ folly::dynamic ABIViewManager::GetExportedCustomDirectEventTypeConstants() const return parent; } -void ABIViewManager::AddView( - const winrt::Windows::UI::Xaml::DependencyObject &parent, - const winrt::Windows::UI::Xaml::DependencyObject &child, - int64_t index) { +void ABIViewManager::AddView(const xaml::DependencyObject &parent, const xaml::DependencyObject &child, int64_t index) { if (m_viewManagerWithChildren) { - m_viewManagerWithChildren.AddView(parent.as(), child.as(), index); + m_viewManagerWithChildren.AddView(parent.as(), child.as(), index); } else { Super::AddView(parent, child, index); } } -void ABIViewManager::RemoveAllChildren(const winrt::Windows::UI::Xaml::DependencyObject &parent) { +void ABIViewManager::RemoveAllChildren(const xaml::DependencyObject &parent) { if (m_viewManagerWithChildren) { - m_viewManagerWithChildren.RemoveAllChildren(parent.as()); + m_viewManagerWithChildren.RemoveAllChildren(parent.as()); } else { Super::RemoveAllChildren(parent); } } -void ABIViewManager::RemoveChildAt(const winrt::Windows::UI::Xaml::DependencyObject &parent, int64_t index) { +void ABIViewManager::RemoveChildAt(const xaml::DependencyObject &parent, int64_t index) { if (m_viewManagerWithChildren) { - m_viewManagerWithChildren.RemoveChildAt(parent.as(), index); + m_viewManagerWithChildren.RemoveChildAt(parent.as(), index); } else { Super::RemoveChildAt(parent, index); } } void ABIViewManager::ReplaceChild( - const winrt::Windows::UI::Xaml::DependencyObject &parent, - const winrt::Windows::UI::Xaml::DependencyObject &oldChild, - const winrt::Windows::UI::Xaml::DependencyObject &newChild) { + const xaml::DependencyObject &parent, + const xaml::DependencyObject &oldChild, + const xaml::DependencyObject &newChild) { if (m_viewManagerWithChildren) { m_viewManagerWithChildren.ReplaceChild( - parent.as(), oldChild.as(), newChild.as()); + parent.as(), oldChild.as(), newChild.as()); } else { Super::ReplaceChild(parent, oldChild, newChild); } diff --git a/vnext/Microsoft.ReactNative/ABIViewManager.h b/vnext/Microsoft.ReactNative/ABIViewManager.h index 4709e00bba7..0f2e8feb2a3 100644 --- a/vnext/Microsoft.ReactNative/ABIViewManager.h +++ b/vnext/Microsoft.ReactNative/ABIViewManager.h @@ -39,7 +39,7 @@ class ABIViewManager : public react::uwp::FrameworkElementViewManager { folly::dynamic GetCommands() const override; void DispatchCommand( - const winrt::Windows::UI::Xaml::DependencyObject &viewToUpdate, + const xaml::DependencyObject &viewToUpdate, const std::string &commandId, const folly::dynamic &commandArgs) override; @@ -47,19 +47,16 @@ class ABIViewManager : public react::uwp::FrameworkElementViewManager { folly::dynamic GetExportedCustomDirectEventTypeConstants() const override; - void AddView( - const winrt::Windows::UI::Xaml::DependencyObject &parent, - const winrt::Windows::UI::Xaml::DependencyObject &child, - int64_t index) override; - void RemoveAllChildren(const winrt::Windows::UI::Xaml::DependencyObject &parent) override; - void RemoveChildAt(const winrt::Windows::UI::Xaml::DependencyObject &parent, int64_t index) override; + void AddView(const xaml::DependencyObject &parent, const xaml::DependencyObject &child, int64_t index) override; + void RemoveAllChildren(const xaml::DependencyObject &parent) override; + void RemoveChildAt(const xaml::DependencyObject &parent, int64_t index) override; void ReplaceChild( - const winrt::Windows::UI::Xaml::DependencyObject &parent, - const winrt::Windows::UI::Xaml::DependencyObject &oldChild, - const winrt::Windows::UI::Xaml::DependencyObject &newChild) override; + const xaml::DependencyObject &parent, + const xaml::DependencyObject &oldChild, + const xaml::DependencyObject &newChild) override; protected: - winrt::Windows::UI::Xaml::DependencyObject CreateViewCore(int64_t) override; + xaml::DependencyObject CreateViewCore(int64_t) override; std::string m_name; ReactNative::IViewManager m_viewManager; diff --git a/vnext/Microsoft.ReactNative/IReactContext.cpp b/vnext/Microsoft.ReactNative/IReactContext.cpp index 9c959208fec..1215bea4d59 100644 --- a/vnext/Microsoft.ReactNative/IReactContext.cpp +++ b/vnext/Microsoft.ReactNative/IReactContext.cpp @@ -10,7 +10,7 @@ namespace winrt::Microsoft::ReactNative { ReactContext::ReactContext(Mso::CntPtr &&context) noexcept : m_context{std::move(context)} {} void ReactContext::DispatchEvent( - winrt::Windows::UI::Xaml::FrameworkElement const &view, + xaml::FrameworkElement const &view, hstring const &eventName, JSValueArgWriter const &eventDataArgWriter) noexcept { folly::dynamic eventData; // default to NULLT diff --git a/vnext/Microsoft.ReactNative/IReactContext.h b/vnext/Microsoft.ReactNative/IReactContext.h index ffe1e0c48ae..018619414c8 100644 --- a/vnext/Microsoft.ReactNative/IReactContext.h +++ b/vnext/Microsoft.ReactNative/IReactContext.h @@ -13,7 +13,7 @@ struct ReactContext : winrt::implements { public: // IReactContext void DispatchEvent( - winrt::Windows::UI::Xaml::FrameworkElement const &view, + xaml::FrameworkElement const &view, hstring const &eventName, JSValueArgWriter const &eventDataArgWriter) noexcept; void CallJSFunction( diff --git a/vnext/Microsoft.ReactNative/IReactContext.idl b/vnext/Microsoft.ReactNative/IReactContext.idl index 36a7297dc7e..b2b85ce3bc0 100644 --- a/vnext/Microsoft.ReactNative/IReactContext.idl +++ b/vnext/Microsoft.ReactNative/IReactContext.idl @@ -3,11 +3,13 @@ import "IJSValueWriter.idl"; +#include "../Include/NamespaceRedirect.h" + namespace Microsoft.ReactNative { [webhosthidden] interface IReactContext { - void DispatchEvent(Windows.UI.Xaml.FrameworkElement view, String eventName, JSValueArgWriter eventDataArgWriter); + void DispatchEvent(XAML_NAMESPACE.FrameworkElement view, String eventName, JSValueArgWriter eventDataArgWriter); void CallJSFunction(String moduleName, String methodName, JSValueArgWriter paramsArgWriter); void EmitJSEvent(String eventEmitterName, String eventName, JSValueArgWriter paramsArgWriter); } diff --git a/vnext/Microsoft.ReactNative/IViewManager.idl b/vnext/Microsoft.ReactNative/IViewManager.idl index 226bcf9703d..e1d877dcb4d 100644 --- a/vnext/Microsoft.ReactNative/IViewManager.idl +++ b/vnext/Microsoft.ReactNative/IViewManager.idl @@ -4,6 +4,8 @@ import "IReactModuleBuilder.idl"; import "IReactContext.idl"; +#include "../Include/NamespaceRedirect.h" + namespace Microsoft.ReactNative { [webhosthidden] @@ -22,7 +24,7 @@ namespace Microsoft.ReactNative { String Name { get; }; - Windows.UI.Xaml.FrameworkElement CreateView(); + XAML_NAMESPACE.FrameworkElement CreateView(); } [webhosthidden] @@ -42,7 +44,7 @@ namespace Microsoft.ReactNative { IMapView NativeProps { get; }; - void UpdateProperties(Windows.UI.Xaml.FrameworkElement view, IJSValueReader propertyMapReader); + void UpdateProperties(XAML_NAMESPACE.FrameworkElement view, IJSValueReader propertyMapReader); } [webhosthidden] @@ -50,7 +52,7 @@ namespace Microsoft.ReactNative { IVectorView Commands { get; }; - void DispatchCommand(Windows.UI.Xaml.FrameworkElement view, String commandId, IJSValueReader commandArgsReader); + void DispatchCommand(XAML_NAMESPACE.FrameworkElement view, String commandId, IJSValueReader commandArgsReader); } [webhosthidden] @@ -64,12 +66,12 @@ namespace Microsoft.ReactNative [webhosthidden] interface IViewManagerWithChildren { - void AddView(Windows.UI.Xaml.FrameworkElement parent, Windows.UI.Xaml.UIElement child, Int64 index); + void AddView(XAML_NAMESPACE.FrameworkElement parent, XAML_NAMESPACE.UIElement child, Int64 index); - void RemoveAllChildren(Windows.UI.Xaml.FrameworkElement parent); + void RemoveAllChildren(XAML_NAMESPACE.FrameworkElement parent); - void RemoveChildAt(Windows.UI.Xaml.FrameworkElement parent, Int64 index); + void RemoveChildAt(XAML_NAMESPACE.FrameworkElement parent, Int64 index); - void ReplaceChild(Windows.UI.Xaml.FrameworkElement parent, Windows.UI.Xaml.UIElement oldChild, Windows.UI.Xaml.UIElement newChild); + void ReplaceChild(XAML_NAMESPACE.FrameworkElement parent, XAML_NAMESPACE.UIElement oldChild, XAML_NAMESPACE.UIElement newChild); } } // namespace Microsoft.ReactNative diff --git a/vnext/Microsoft.ReactNative/Modules/AppStateData.cpp b/vnext/Microsoft.ReactNative/Modules/AppStateData.cpp index 97de89ded5c..3f980dcbd45 100644 --- a/vnext/Microsoft.ReactNative/Modules/AppStateData.cpp +++ b/vnext/Microsoft.ReactNative/Modules/AppStateData.cpp @@ -7,7 +7,7 @@ using namespace winrt; using namespace Windows::Foundation; using namespace Windows::ApplicationModel; -using namespace Windows::UI::Xaml; +using namespace xaml; namespace react::uwp { diff --git a/vnext/Microsoft.ReactNative/Modules/AppStateData.h b/vnext/Microsoft.ReactNative/Modules/AppStateData.h index 9c446b8897f..ff400f8af81 100644 --- a/vnext/Microsoft.ReactNative/Modules/AppStateData.h +++ b/vnext/Microsoft.ReactNative/Modules/AppStateData.h @@ -6,7 +6,6 @@ #include #include #include -#include #include "ReactHost/React.h" #include "activeObject/activeObject.h" @@ -30,8 +29,8 @@ struct AppStateData : Mso::ActiveObject<> { std::mutex m_stateMutex; char const *m_lastState{nullptr}; Mso::CntPtr m_reactContext; - winrt::Windows::UI::Xaml::Application::EnteredBackground_revoker m_enteredBackgroundRevoker; - winrt::Windows::UI::Xaml::Application::LeavingBackground_revoker m_leavingBackgroundRevoker; + xaml::Application::EnteredBackground_revoker m_enteredBackgroundRevoker; + xaml::Application::LeavingBackground_revoker m_leavingBackgroundRevoker; }; // It is a temporary class that we need to keep until we remove ReactUWP diff --git a/vnext/Microsoft.ReactNative/ReactApplication.cpp b/vnext/Microsoft.ReactNative/ReactApplication.cpp index 89a51d7f44e..38c271ddb6c 100644 --- a/vnext/Microsoft.ReactNative/ReactApplication.cpp +++ b/vnext/Microsoft.ReactNative/ReactApplication.cpp @@ -9,7 +9,6 @@ #include #include -#include using namespace winrt; using namespace Windows::ApplicationModel; @@ -17,9 +16,9 @@ using namespace Windows::ApplicationModel::Activation; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Windows::UI::Core; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Navigation; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Navigation; namespace winrt::Microsoft::ReactNative::implementation { diff --git a/vnext/Microsoft.ReactNative/ReactApplication.h b/vnext/Microsoft.ReactNative/ReactApplication.h index 7b5ba195e9f..1bb0e357aa8 100644 --- a/vnext/Microsoft.ReactNative/ReactApplication.h +++ b/vnext/Microsoft.ReactNative/ReactApplication.h @@ -38,7 +38,7 @@ struct ReactApplication : ReactApplicationT { void OnActivated(Windows::ApplicationModel::Activation::IActivatedEventArgs const &e); void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const &e); void OnSuspending(IInspectable const &, Windows::ApplicationModel::SuspendingEventArgs const &); - void OnNavigationFailed(IInspectable const &, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs const &); + void OnNavigationFailed(IInspectable const &, xaml::Navigation::NavigationFailedEventArgs const &); protected: virtual ReactApplicationDelegate __stdcall CreateReactApplicationDelegate(); diff --git a/vnext/Microsoft.ReactNative/ReactApplication.idl b/vnext/Microsoft.ReactNative/ReactApplication.idl index 2cb38257cf7..b554783f0bb 100644 --- a/vnext/Microsoft.ReactNative/ReactApplication.idl +++ b/vnext/Microsoft.ReactNative/ReactApplication.idl @@ -2,12 +2,13 @@ // Licensed under the MIT License. import "ReactNativeHost.idl"; +#include "../include/NamespaceRedirect.h" namespace Microsoft.ReactNative { [webhosthidden] [default_interface] - unsealed runtimeclass ReactApplication : Windows.UI.Xaml.Application { + unsealed runtimeclass ReactApplication : XAML_NAMESPACE.Application { ReactApplication(); ReactInstanceSettings InstanceSettings { get; set; }; diff --git a/vnext/Microsoft.ReactNative/ReactApplicationDelegate.cpp b/vnext/Microsoft.ReactNative/ReactApplicationDelegate.cpp index d4619d9d879..4413345823c 100644 --- a/vnext/Microsoft.ReactNative/ReactApplicationDelegate.cpp +++ b/vnext/Microsoft.ReactNative/ReactApplicationDelegate.cpp @@ -14,7 +14,7 @@ using namespace winrt; using namespace Windows::Foundation; -using namespace Windows::UI::Xaml; +using namespace xaml; using namespace Windows::ApplicationModel; using namespace Windows::ApplicationModel::Activation; diff --git a/vnext/Microsoft.ReactNative/ReactApplicationDelegate.h b/vnext/Microsoft.ReactNative/ReactApplicationDelegate.h index 1550ea53679..4aadc8b89c2 100644 --- a/vnext/Microsoft.ReactNative/ReactApplicationDelegate.h +++ b/vnext/Microsoft.ReactNative/ReactApplicationDelegate.h @@ -9,10 +9,10 @@ namespace winrt::Microsoft::ReactNative::implementation { struct ReactApplicationDelegate : ReactApplicationDelegateT { ReactApplicationDelegate() = default; - ReactApplicationDelegate(Windows::UI::Xaml::Application const &application) noexcept; + ReactApplicationDelegate(xaml::Application const &application) noexcept; void OnActivated(Windows::ApplicationModel::Activation::IActivatedEventArgs const &args) noexcept; - Windows::UI::Xaml::UIElement OnCreate(hstring const &args) noexcept; + xaml::UIElement OnCreate(hstring const &args) noexcept; private: void OnResuming(IInspectable const &sender, IInspectable const &args) noexcept; @@ -25,7 +25,7 @@ struct ReactApplicationDelegate : ReactApplicationDelegateT m_reactRootView{nullptr}; }; diff --git a/vnext/Microsoft.ReactNative/ReactApplicationDelegate.idl b/vnext/Microsoft.ReactNative/ReactApplicationDelegate.idl index 6799920264b..a7bf51ddbff 100644 --- a/vnext/Microsoft.ReactNative/ReactApplicationDelegate.idl +++ b/vnext/Microsoft.ReactNative/ReactApplicationDelegate.idl @@ -2,14 +2,15 @@ // Licensed under the MIT License. import "ReactApplication.idl"; +#include "../include/NamespaceRedirect.h" namespace Microsoft.ReactNative { [webhosthidden] unsealed runtimeclass ReactApplicationDelegate { ReactApplicationDelegate(); - ReactApplicationDelegate(Windows.UI.Xaml.Application application); + ReactApplicationDelegate(XAML_NAMESPACE.Application application); void OnActivated(Windows.ApplicationModel.Activation.IActivatedEventArgs args); - Windows.UI.Xaml.UIElement OnCreate(String args); + XAML_NAMESPACE.UIElement OnCreate(String args); } } diff --git a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp index 89e3e986ce9..61ed3d4e4a4 100644 --- a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp +++ b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp @@ -9,8 +9,8 @@ using namespace winrt; using namespace Windows::Foundation::Collections; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; +using namespace xaml; +using namespace xaml::Controls; namespace winrt::Microsoft::ReactNative::implementation { diff --git a/vnext/Microsoft.ReactNative/ReactRootView.idl b/vnext/Microsoft.ReactNative/ReactRootView.idl index 3e3b31120a3..8e572f8464a 100644 --- a/vnext/Microsoft.ReactNative/ReactRootView.idl +++ b/vnext/Microsoft.ReactNative/ReactRootView.idl @@ -3,12 +3,13 @@ import "IJSValueWriter.idl"; import "ReactNativeHost.idl"; +#include "../include/NamespaceRedirect.h" namespace Microsoft.ReactNative { [default_interface] [webhosthidden] - runtimeclass ReactRootView : Windows.UI.Xaml.Controls.Grid { + runtimeclass ReactRootView : XAML_NAMESPACE.Controls.Grid { ReactRootView(); ReactNativeHost ReactNativeHost { get; set; }; diff --git a/vnext/Microsoft.ReactNative/RedBox.cpp b/vnext/Microsoft.ReactNative/RedBox.cpp index d71808072cf..90279a135e7 100644 --- a/vnext/Microsoft.ReactNative/RedBox.cpp +++ b/vnext/Microsoft.ReactNative/RedBox.cpp @@ -2,22 +2,16 @@ // Licensed under the MIT License. #include "pch.h" #include "RedBox.h" +#include #include #include #include #include -#include -#include -#include -#include -#include #include - -#include #include +#include "CppWinRTIncludes.h" #include "Unicode.h" -namespace xaml = winrt::Windows::UI::Xaml; using namespace winrt::Windows::Foundation; namespace Mso::React { diff --git a/vnext/Microsoft.ReactNative/Views/ReactRootControl.cpp b/vnext/Microsoft.ReactNative/Views/ReactRootControl.cpp index 7b73c9bc060..d61d17c6bf1 100644 --- a/vnext/Microsoft.ReactNative/Views/ReactRootControl.cpp +++ b/vnext/Microsoft.ReactNative/Views/ReactRootControl.cpp @@ -21,12 +21,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include #include @@ -104,7 +98,7 @@ std::string ReactRootControl::JSComponentName() const noexcept { int64_t ReactRootControl::GetActualHeight() const noexcept { if (auto xamlRootView = m_weakXamlRootView.get()) { - if (auto element = xamlRootView.as()) { + if (auto element = xamlRootView.as()) { return static_cast(element.ActualHeight()); } } @@ -114,7 +108,7 @@ int64_t ReactRootControl::GetActualHeight() const noexcept { int64_t ReactRootControl::GetActualWidth() const noexcept { if (auto xamlRootView = m_weakXamlRootView.get()) { - if (auto element = xamlRootView.as()) { + if (auto element = xamlRootView.as()) { return static_cast(element.ActualWidth()); } } @@ -138,9 +132,9 @@ void ReactRootControl::blur(XamlView const &xamlView) noexcept { EnsureFocusSafeHarbor(); if (m_focusSafeHarbor) { m_focusSafeHarbor.IsTabStop(true); - winrt::FocusManager::TryFocusAsync(m_focusSafeHarbor, winrt::FocusState::Pointer); + xaml::Input::FocusManager::TryFocusAsync(m_focusSafeHarbor, winrt::FocusState::Pointer); } else - winrt::FocusManager::TryFocusAsync(xamlView, winrt::FocusState::Pointer); + xaml::Input::FocusManager::TryFocusAsync(xamlView, winrt::FocusState::Pointer); } void ReactRootControl::InitRootView( @@ -292,9 +286,9 @@ void ReactRootControl::ShowInstanceWaiting(Mso::React::IReactInstance & /*reactI if (m_waitingTextBlock == nullptr) { m_waitingTextBlock = winrt::TextBlock(); m_greenBoxGrid = winrt::Grid{}; - m_greenBoxGrid.Background(winrt::SolidColorBrush(winrt::ColorHelper::FromArgb(0xff, 0x03, 0x59, 0))); + m_greenBoxGrid.Background(xaml::Media::SolidColorBrush(winrt::ColorHelper::FromArgb(0xff, 0x03, 0x59, 0))); m_greenBoxGrid.Children().Append(m_waitingTextBlock); - m_greenBoxGrid.VerticalAlignment(winrt::Windows::UI::Xaml::VerticalAlignment::Center); + m_greenBoxGrid.VerticalAlignment(xaml::VerticalAlignment::Center); } // Add box grid to root view @@ -306,9 +300,9 @@ void ReactRootControl::ShowInstanceWaiting(Mso::React::IReactInstance & /*reactI // Format TextBlock m_waitingTextBlock.TextAlignment(winrt::TextAlignment::Center); - m_waitingTextBlock.TextWrapping(winrt::TextWrapping::Wrap); + m_waitingTextBlock.TextWrapping(xaml::TextWrapping::Wrap); m_waitingTextBlock.FontFamily(winrt::FontFamily(L"Consolas")); - m_waitingTextBlock.Foreground(winrt::SolidColorBrush(winrt::Colors::White())); + m_waitingTextBlock.Foreground(xaml::Media::SolidColorBrush(winrt::Colors::White())); winrt::Thickness margin = {10.0f, 10.0f, 10.0f, 10.0f}; m_waitingTextBlock.Margin(margin); } @@ -328,9 +322,9 @@ void ReactRootControl::ShowInstanceLoading(Mso::React::IReactInstance & /*reactI if (m_waitingTextBlock == nullptr) { m_waitingTextBlock = winrt::TextBlock(); m_greenBoxGrid = winrt::Grid{}; - m_greenBoxGrid.Background(winrt::SolidColorBrush(winrt::ColorHelper::FromArgb(0xff, 0x03, 0x59, 0))); + m_greenBoxGrid.Background(xaml::Media::SolidColorBrush(winrt::ColorHelper::FromArgb(0xff, 0x03, 0x59, 0))); m_greenBoxGrid.Children().Append(m_waitingTextBlock); - m_greenBoxGrid.VerticalAlignment(winrt::Windows::UI::Xaml::VerticalAlignment::Center); + m_greenBoxGrid.VerticalAlignment(xaml::VerticalAlignment::Center); } // Add box grid to root view @@ -342,9 +336,9 @@ void ReactRootControl::ShowInstanceLoading(Mso::React::IReactInstance & /*reactI // Format TextBlock m_waitingTextBlock.TextAlignment(winrt::TextAlignment::Center); - m_waitingTextBlock.TextWrapping(winrt::TextWrapping::Wrap); + m_waitingTextBlock.TextWrapping(xaml::TextWrapping::Wrap); m_waitingTextBlock.FontFamily(winrt::FontFamily(L"Consolas")); - m_waitingTextBlock.Foreground(winrt::SolidColorBrush(winrt::Colors::White())); + m_waitingTextBlock.Foreground(xaml::Media::SolidColorBrush(winrt::Colors::White())); winrt::Thickness margin = {10.0f, 10.0f, 10.0f, 10.0f}; m_waitingTextBlock.Margin(margin); } @@ -365,9 +359,9 @@ void ReactRootControl::PrepareXamlRootView(XamlView const &rootView) noexcept { // Xaml's default projection in 3D is orthographic (all lines are parallel) // However React Native's default projection is a one-point perspective. // Set a default perspective projection on the main control to mimic this. - auto perspectiveTransform3D = winrt::Windows::UI::Xaml::Media::Media3D::PerspectiveTransform3D(); + auto perspectiveTransform3D = xaml::Media::Media3D::PerspectiveTransform3D(); perspectiveTransform3D.Depth(850); - winrt::Windows::UI::Xaml::Media::Media3D::Transform3D t3d(perspectiveTransform3D); + xaml::Media::Media3D::Transform3D t3d(perspectiveTransform3D); newRootView.Transform3D(t3d); children.Append(newRootView); m_weakXamlRootView = newRootView.try_as(); @@ -384,7 +378,7 @@ void ReactRootControl::EnsureFocusSafeHarbor() noexcept { auto panel = rootView.try_as(); VerifyElseCrash(panel.Children().Size() == 1); - m_focusSafeHarbor = winrt::ContentControl{}; + m_focusSafeHarbor = xaml::Controls::ContentControl{}; m_focusSafeHarbor.Width(0.0); m_focusSafeHarbor.IsTabStop(false); panel.Children().InsertAt(0, m_focusSafeHarbor); @@ -404,9 +398,10 @@ void ReactRootControl::InitializeDeveloperMenu() noexcept { m_coreDispatcherAKARevoker = coreWindow.Dispatcher().AcceleratorKeyActivated( winrt::auto_revoke, [this](const auto & /*sender*/, const winrt::AcceleratorKeyEventArgs &args) { if ((args.VirtualKey() == winrt::Windows::System::VirtualKey::D) && - KeyboardHelper::IsModifiedKeyPressed(winrt::CoreWindow::GetForCurrentThread(), winrt::VirtualKey::Shift) && KeyboardHelper::IsModifiedKeyPressed( - winrt::CoreWindow::GetForCurrentThread(), winrt::VirtualKey::Control)) { + winrt::CoreWindow::GetForCurrentThread(), winrt::Windows::System::VirtualKey::Shift) && + KeyboardHelper::IsModifiedKeyPressed( + winrt::CoreWindow::GetForCurrentThread(), winrt::Windows::System::VirtualKey::Control)) { if (!IsDeveloperMenuShowing()) { ShowDeveloperMenu(); } @@ -629,45 +624,45 @@ void ReactRootControl::AttachBackHandlers(XamlView const &rootView) noexcept { // In addition to handling the BackRequested event, UWP suggests that we listen for other user inputs that should // trigger back navigation that don't fire that event: // https://docs.microsoft.com/en-us/windows/uwp/design/basics/navigation-history-and-backwards-navigation - auto rootElement(rootView.try_as()); + auto rootElement(rootView.try_as()); if (rootElement == nullptr) { assert(false); return; } // Handle keyboard "back" button press - winrt::KeyboardAccelerator goBack{}; - goBack.Key(winrt::VirtualKey::GoBack); - goBack.Invoked( - [weakThis]( - winrt::KeyboardAccelerator const & /*sender*/, winrt::KeyboardAcceleratorInvokedEventArgs const &args) { - if (auto self = weakThis.lock()) { - args.Handled(self->OnBackRequested()); - } - }); + xaml::Input::KeyboardAccelerator goBack{}; + goBack.Key(winrt::Windows::System::VirtualKey::GoBack); + goBack.Invoked([weakThis]( + xaml::Input::KeyboardAccelerator const & /*sender*/, + xaml::Input::KeyboardAcceleratorInvokedEventArgs const &args) { + if (auto self = weakThis.lock()) { + args.Handled(self->OnBackRequested()); + } + }); rootElement.KeyboardAccelerators().Append(goBack); // Handle Alt+Left keyboard shortcut - winrt::KeyboardAccelerator altLeft{}; - altLeft.Key(winrt::VirtualKey::Left); - altLeft.Invoked( - [weakThis]( - winrt::KeyboardAccelerator const & /*sender*/, winrt::KeyboardAcceleratorInvokedEventArgs const &args) { - if (auto self = weakThis.lock()) { - args.Handled(self->OnBackRequested()); - } - }); + xaml::Input::KeyboardAccelerator altLeft{}; + altLeft.Key(winrt::Windows::System::VirtualKey::Left); + altLeft.Invoked([weakThis]( + xaml::Input::KeyboardAccelerator const & /*sender*/, + xaml::Input::KeyboardAcceleratorInvokedEventArgs const &args) { + if (auto self = weakThis.lock()) { + args.Handled(self->OnBackRequested()); + } + }); rootElement.KeyboardAccelerators().Append(altLeft); - altLeft.Modifiers(winrt::VirtualKeyModifiers::Menu); + altLeft.Modifiers(winrt::Windows::System::VirtualKeyModifiers::Menu); // Hide keyboard accelerator tooltips - rootElement.KeyboardAcceleratorPlacementMode(winrt::KeyboardAcceleratorPlacementMode::Hidden); + rootElement.KeyboardAcceleratorPlacementMode(xaml::Input::KeyboardAcceleratorPlacementMode::Hidden); } void ReactRootControl::RemoveBackHandlers() noexcept { m_backRequestedRevoker.revoke(); if (auto rootView = m_weakRootView.get()) { - if (auto element = rootView.try_as()) { + if (auto element = rootView.try_as()) { element.KeyboardAccelerators().Clear(); } } diff --git a/vnext/Microsoft.ReactNative/Views/ReactRootControl.h b/vnext/Microsoft.ReactNative/Views/ReactRootControl.h index 26bb5948cc2..85d27b74c63 100644 --- a/vnext/Microsoft.ReactNative/Views/ReactRootControl.h +++ b/vnext/Microsoft.ReactNative/Views/ReactRootControl.h @@ -6,7 +6,6 @@ #include #include -#include #include "IXamlRootView.h" #include "ReactHost/React.h" #include "SIPEventHandler.h" @@ -16,11 +15,11 @@ namespace winrt { using namespace Windows::UI; using namespace Windows::UI::Core; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Input; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Input; using namespace Windows::Foundation; -using namespace Windows::UI::Xaml::Media; +using namespace xaml::Media; } // namespace winrt namespace react::uwp { @@ -120,8 +119,8 @@ struct ReactRootControl final : std::enable_shared_from_this, winrt::weak_ref m_weakRootView{nullptr}; winrt::weak_ref m_weakXamlRootView{nullptr}; - winrt::ContentControl m_focusSafeHarbor{nullptr}; - winrt::ContentControl::LosingFocus_revoker m_focusSafeHarborLosingFocusRevoker{}; + xaml::Controls::ContentControl m_focusSafeHarbor{nullptr}; + xaml::Controls::ContentControl::LosingFocus_revoker m_focusSafeHarborLosingFocusRevoker{}; winrt::Grid m_redBoxGrid{nullptr}; winrt::Grid m_greenBoxGrid{nullptr}; winrt::TextBlock m_errorTextBlock{nullptr}; diff --git a/vnext/Microsoft.ReactNative/XamlHelper.cpp b/vnext/Microsoft.ReactNative/XamlHelper.cpp index 36f415099d0..6c6ad98e720 100644 --- a/vnext/Microsoft.ReactNative/XamlHelper.cpp +++ b/vnext/Microsoft.ReactNative/XamlHelper.cpp @@ -10,7 +10,7 @@ namespace winrt::Microsoft::ReactNative::implementation { -Windows::UI::Xaml::Media::Brush XamlHelper::BrushFrom(JSValueArgWriter const &valueProvider) noexcept { +xaml::Media::Brush XamlHelper::BrushFrom(JSValueArgWriter const &valueProvider) noexcept { auto value = GetFollyDynamicFromValueProvider(valueProvider); return react::uwp::IsValidColorValue(value) ? react::uwp::BrushFrom(value) : nullptr; } diff --git a/vnext/Microsoft.ReactNative/XamlHelper.h b/vnext/Microsoft.ReactNative/XamlHelper.h index 834f50e05c5..8b50c5d7a0c 100644 --- a/vnext/Microsoft.ReactNative/XamlHelper.h +++ b/vnext/Microsoft.ReactNative/XamlHelper.h @@ -9,7 +9,7 @@ namespace winrt::Microsoft::ReactNative::implementation { struct XamlHelper : XamlHelperT { XamlHelper() = default; - static Windows::UI::Xaml::Media::Brush BrushFrom(JSValueArgWriter const &valueProvider) noexcept; + static xaml::Media::Brush BrushFrom(JSValueArgWriter const &valueProvider) noexcept; static Windows::UI::Color ColorFrom(JSValueArgWriter const &valueProvider) noexcept; static folly::dynamic GetFollyDynamicFromValueProvider(JSValueArgWriter const &valueProvider) noexcept; diff --git a/vnext/Microsoft.ReactNative/XamlHelper.idl b/vnext/Microsoft.ReactNative/XamlHelper.idl index f3dacb3fa4c..3f24e28ad94 100644 --- a/vnext/Microsoft.ReactNative/XamlHelper.idl +++ b/vnext/Microsoft.ReactNative/XamlHelper.idl @@ -2,6 +2,7 @@ // Licensed under the MIT License. import "IJSValueWriter.idl"; +#include "../include/NamespaceRedirect.h" namespace Microsoft.ReactNative { @@ -9,7 +10,7 @@ namespace Microsoft.ReactNative { [default_interface] runtimeclass XamlHelper { XamlHelper(); - static Windows.UI.Xaml.Media.Brush BrushFrom(JSValueArgWriter valueProvider); + static XAML_NAMESPACE.Media.Brush BrushFrom(JSValueArgWriter valueProvider); static Windows.UI.Color ColorFrom(JSValueArgWriter valueProvider); }; diff --git a/vnext/Microsoft.ReactNative/pch.h b/vnext/Microsoft.ReactNative/pch.h index 9ab80562a42..c339ff1e823 100644 --- a/vnext/Microsoft.ReactNative/pch.h +++ b/vnext/Microsoft.ReactNative/pch.h @@ -21,17 +21,7 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "CppWinRTIncludes.h" #include "HResult.h" #include "Base/CxxReactIncludes.h" diff --git a/vnext/ReactUWP/ABI/ReactControl_rt.cpp b/vnext/ReactUWP/ABI/ReactControl_rt.cpp index 1f0a3d30b38..3d0c1887966 100644 --- a/vnext/ReactUWP/ABI/ReactControl_rt.cpp +++ b/vnext/ReactUWP/ABI/ReactControl_rt.cpp @@ -111,8 +111,7 @@ void ReactControl::CreateInnerInstance() { Microsoft::WRL::ComPtr spThis(this); Microsoft::WRL::ComPtr spFrameworkElementABI; spThis.As(&spFrameworkElementABI); - ::react::uwp::XamlView pXamlView = - reinterpret_cast(spFrameworkElementABI); + ::react::uwp::XamlView pXamlView = reinterpret_cast(spFrameworkElementABI); m_pInnerControl = std::make_shared<::react::uwp::ReactControl>(this, pXamlView); m_pInnerControl->SetJSComponentName(std::string(m_jsComponentName)); diff --git a/vnext/ReactUWP/Modules/AlertModuleUwp.cpp b/vnext/ReactUWP/Modules/AlertModuleUwp.cpp index ce5b750037a..806a1bc9a26 100644 --- a/vnext/ReactUWP/Modules/AlertModuleUwp.cpp +++ b/vnext/ReactUWP/Modules/AlertModuleUwp.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT License. #include "pch.h" #include "AlertModuleUwp.h" -#include #include @@ -11,8 +10,8 @@ #include #pragma warning(pop) namespace winrt { -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; +using namespace xaml; +using namespace xaml::Controls; } // namespace winrt #if _MSC_VER <= 1913 diff --git a/vnext/ReactUWP/Modules/Animated/AdditionAnimatedNode.cpp b/vnext/ReactUWP/Modules/Animated/AdditionAnimatedNode.cpp index 0ede5a34661..d2857ddad0e 100644 --- a/vnext/ReactUWP/Modules/Animated/AdditionAnimatedNode.cpp +++ b/vnext/ReactUWP/Modules/Animated/AdditionAnimatedNode.cpp @@ -18,7 +18,7 @@ AdditionAnimatedNode::AdditionAnimatedNode( } m_propertySet.StartAnimation(s_valueName, [nodes = m_inputNodes, manager]() { - const auto anim = winrt::Window::Current().Compositor().CreateExpressionAnimation(); + const auto anim = xaml::Window::Current().Compositor().CreateExpressionAnimation(); anim.Expression([nodes, manager, anim]() { winrt::hstring expr = L"0"; diff --git a/vnext/ReactUWP/Modules/Animated/AnimationDriver.h b/vnext/ReactUWP/Modules/Animated/AnimationDriver.h index 3ae0c03db64..ceee7e6bd9e 100644 --- a/vnext/ReactUWP/Modules/Animated/AnimationDriver.h +++ b/vnext/ReactUWP/Modules/Animated/AnimationDriver.h @@ -23,7 +23,7 @@ class AnimationDriver { void StartAnimation(); void StopAnimation(bool ignoreCompletedHandlers = false); - virtual std::tuple MakeAnimation( + virtual std::tuple MakeAnimation( const folly::dynamic & /*config*/) { return std::make_tuple(nullptr, nullptr); }; @@ -61,8 +61,8 @@ class AnimationDriver { folly::dynamic m_config{}; std::weak_ptr m_manager{}; - winrt::Windows::UI::Composition::CompositionAnimation m_animation{nullptr}; - winrt::Windows::UI::Composition::CompositionScopedBatch m_scopedBatch{nullptr}; + comp::CompositionAnimation m_animation{nullptr}; + comp::CompositionScopedBatch m_scopedBatch{nullptr}; // auto revoker for scopedBatch.Completed is broken, tracked by internal bug // #22399779 winrt::event_token m_scopedBatchCompletedToken{}; diff --git a/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp index 060269517dc..09dd8d47fcf 100644 --- a/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp +++ b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp @@ -9,12 +9,12 @@ namespace react { namespace uwp { -std::tuple CalculatedAnimationDriver::MakeAnimation( +std::tuple CalculatedAnimationDriver::MakeAnimation( const folly::dynamic & /*config*/) { const auto [scopedBatch, animation, easingFunction] = []() { - const auto compositor = winrt::Window::Current().Compositor(); + const auto compositor = xaml::Window::Current().Compositor(); return std::make_tuple( - compositor.CreateScopedBatch(winrt::CompositionBatchTypes::AllAnimations), + compositor.CreateScopedBatch(comp::CompositionBatchTypes::AllAnimations), compositor.CreateScalarKeyFrameAnimation(), compositor.CreateLinearEasingFunction()); }(); diff --git a/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h index 267fa69c95f..30f6dda0ca3 100644 --- a/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h +++ b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h @@ -13,7 +13,7 @@ class CalculatedAnimationDriver : public AnimationDriver { public: using AnimationDriver::AnimationDriver; - std::tuple MakeAnimation( + std::tuple MakeAnimation( const folly::dynamic &config) override; protected: diff --git a/vnext/ReactUWP/Modules/Animated/DiffClampAnimatedNode.cpp b/vnext/ReactUWP/Modules/Animated/DiffClampAnimatedNode.cpp index da13343f92a..ecb188e2602 100644 --- a/vnext/ReactUWP/Modules/Animated/DiffClampAnimatedNode.cpp +++ b/vnext/ReactUWP/Modules/Animated/DiffClampAnimatedNode.cpp @@ -18,7 +18,7 @@ DiffClampAnimatedNode::DiffClampAnimatedNode( m_max = config.find(s_maxName).dereference().second.asDouble(); m_propertySet.StartAnimation(s_valueName, [node = m_inputNodeTag, min = m_min, max = m_max, manager]() { - const auto anim = winrt::Window::Current().Compositor().CreateExpressionAnimation(); + const auto anim = xaml::Window::Current().Compositor().CreateExpressionAnimation(); anim.SetReferenceParameter(s_inputParameterName, manager->GetValueAnimatedNode(node)->PropertySet()); anim.SetScalarParameter(s_minParameterName, static_cast(min)); anim.SetScalarParameter(s_maxParameterName, static_cast(max)); diff --git a/vnext/ReactUWP/Modules/Animated/DivisionAnimatedNode.cpp b/vnext/ReactUWP/Modules/Animated/DivisionAnimatedNode.cpp index 905acf8a1f8..6efb28c5eec 100644 --- a/vnext/ReactUWP/Modules/Animated/DivisionAnimatedNode.cpp +++ b/vnext/ReactUWP/Modules/Animated/DivisionAnimatedNode.cpp @@ -22,7 +22,7 @@ DivisionAnimatedNode::DivisionAnimatedNode( } m_propertySet.StartAnimation(s_valueName, [firstNode = m_firstInput, nodes = m_inputNodes, manager]() { - const auto anim = winrt::Window::Current().Compositor().CreateExpressionAnimation(); + const auto anim = xaml::Window::Current().Compositor().CreateExpressionAnimation(); anim.Expression([firstNode, nodes, manager, anim]() { anim.SetReferenceParameter(s_baseName, manager->GetValueAnimatedNode(firstNode)->PropertySet()); diff --git a/vnext/ReactUWP/Modules/Animated/FrameAnimationDriver.cpp b/vnext/ReactUWP/Modules/Animated/FrameAnimationDriver.cpp index 8667605bb25..5bfa2f3adae 100644 --- a/vnext/ReactUWP/Modules/Animated/FrameAnimationDriver.cpp +++ b/vnext/ReactUWP/Modules/Animated/FrameAnimationDriver.cpp @@ -20,12 +20,12 @@ FrameAnimationDriver::FrameAnimationDriver( m_toValue = config.find("toValue").dereference().second.asDouble(); } -std::tuple FrameAnimationDriver::MakeAnimation( +std::tuple FrameAnimationDriver::MakeAnimation( const folly::dynamic & /*config*/) { const auto [scopedBatch, animation] = []() { - const auto compositor = winrt::Window::Current().Compositor(); + const auto compositor = xaml::Window::Current().Compositor(); return std::make_tuple( - compositor.CreateScopedBatch(winrt::CompositionBatchTypes::AllAnimations), + compositor.CreateScopedBatch(comp::CompositionBatchTypes::AllAnimations), compositor.CreateScalarKeyFrameAnimation()); }(); diff --git a/vnext/ReactUWP/Modules/Animated/FrameAnimationDriver.h b/vnext/ReactUWP/Modules/Animated/FrameAnimationDriver.h index 373c417fb1e..5d218764a94 100644 --- a/vnext/ReactUWP/Modules/Animated/FrameAnimationDriver.h +++ b/vnext/ReactUWP/Modules/Animated/FrameAnimationDriver.h @@ -17,7 +17,7 @@ class FrameAnimationDriver : public AnimationDriver { const folly::dynamic &config, const std::shared_ptr &manager); - std::tuple MakeAnimation( + std::tuple MakeAnimation( const folly::dynamic &config) override; double ToValue() override; diff --git a/vnext/ReactUWP/Modules/Animated/InterpolationAnimatedNode.cpp b/vnext/ReactUWP/Modules/Animated/InterpolationAnimatedNode.cpp index 95a5e24b5c6..93d8261fbf6 100644 --- a/vnext/ReactUWP/Modules/Animated/InterpolationAnimatedNode.cpp +++ b/vnext/ReactUWP/Modules/Animated/InterpolationAnimatedNode.cpp @@ -43,7 +43,7 @@ void InterpolationAnimatedNode::OnAttachToNode(int64_t animatedNodeTag) { const auto [rawValueAnimation, offsetAnimation] = [this]() { if (const auto manager = m_manager.lock()) { if (const auto parent = manager->GetValueAnimatedNode(m_parentTag)) { - const auto compositor = winrt::Window::Current().Compositor(); + const auto compositor = xaml::Window::Current().Compositor(); const auto rawValueAnimation = CreateExpressionAnimation(compositor, *parent); rawValueAnimation.Expression( @@ -60,7 +60,7 @@ void InterpolationAnimatedNode::OnAttachToNode(int64_t animatedNodeTag) { return std::make_tuple(rawValueAnimation, offsetAnimation); } } - return std::tuple(nullptr, nullptr); + return std::tuple(nullptr, nullptr); }(); m_propertySet.StartAnimation(s_valueName, rawValueAnimation); @@ -70,7 +70,7 @@ void InterpolationAnimatedNode::OnAttachToNode(int64_t animatedNodeTag) { m_offsetAnimation = offsetAnimation; } -winrt::ExpressionAnimation InterpolationAnimatedNode::CreateExpressionAnimation( +comp::ExpressionAnimation InterpolationAnimatedNode::CreateExpressionAnimation( const winrt::Compositor &compositor, ValueAnimatedNode &parent) { const auto animation = compositor.CreateExpressionAnimation(); diff --git a/vnext/ReactUWP/Modules/Animated/InterpolationAnimatedNode.h b/vnext/ReactUWP/Modules/Animated/InterpolationAnimatedNode.h index af414719fd6..629d1800b1f 100644 --- a/vnext/ReactUWP/Modules/Animated/InterpolationAnimatedNode.h +++ b/vnext/ReactUWP/Modules/Animated/InterpolationAnimatedNode.h @@ -24,7 +24,7 @@ class InterpolationAnimatedNode : public ValueAnimatedNode { static constexpr std::wstring_view ExtrapolateTypeExtend = L"extend"; private: - winrt::ExpressionAnimation CreateExpressionAnimation(const winrt::Compositor &compositor, ValueAnimatedNode &parent); + comp::ExpressionAnimation CreateExpressionAnimation(const winrt::Compositor &compositor, ValueAnimatedNode &parent); winrt::hstring GetExpression(const winrt::hstring &value); winrt::hstring GetInterpolateExpression( @@ -36,8 +36,8 @@ class InterpolationAnimatedNode : public ValueAnimatedNode { winrt::hstring GetLeftExpression(const winrt::hstring &value, const winrt::hstring &leftInterpolateExpression); winrt::hstring GetRightExpression(const winrt::hstring &, const winrt::hstring &rightInterpolateExpression); - winrt::ExpressionAnimation m_rawValueAnimation{nullptr}; - winrt::ExpressionAnimation m_offsetAnimation{nullptr}; + comp::ExpressionAnimation m_rawValueAnimation{nullptr}; + comp::ExpressionAnimation m_offsetAnimation{nullptr}; std::vector m_inputRanges; std::vector m_outputRanges; std::string m_extrapolateLeft; diff --git a/vnext/ReactUWP/Modules/Animated/ModulusAnimatedNode.cpp b/vnext/ReactUWP/Modules/Animated/ModulusAnimatedNode.cpp index f246980c7d0..f75e88612fb 100644 --- a/vnext/ReactUWP/Modules/Animated/ModulusAnimatedNode.cpp +++ b/vnext/ReactUWP/Modules/Animated/ModulusAnimatedNode.cpp @@ -17,7 +17,7 @@ ModulusAnimatedNode::ModulusAnimatedNode( m_modulus = static_cast(config.find(s_modulusName).dereference().second.asDouble()); m_propertySet.StartAnimation(s_valueName, [node = m_inputNodeTag, mod = m_modulus, manager]() { - const auto anim = winrt::Window::Current().Compositor().CreateExpressionAnimation(); + const auto anim = xaml::Window::Current().Compositor().CreateExpressionAnimation(); anim.SetReferenceParameter(s_inputParameterName, manager->GetValueAnimatedNode(node)->PropertySet()); anim.SetScalarParameter(s_modName, static_cast(mod)); anim.Expression( diff --git a/vnext/ReactUWP/Modules/Animated/MultiplicationAnimatedNode.cpp b/vnext/ReactUWP/Modules/Animated/MultiplicationAnimatedNode.cpp index 0f1f8db2dce..0412abf1693 100644 --- a/vnext/ReactUWP/Modules/Animated/MultiplicationAnimatedNode.cpp +++ b/vnext/ReactUWP/Modules/Animated/MultiplicationAnimatedNode.cpp @@ -18,7 +18,7 @@ MultiplicationAnimatedNode::MultiplicationAnimatedNode( } m_propertySet.StartAnimation(s_valueName, [nodes = m_inputNodes, manager]() { - const auto anim = winrt::Window::Current().Compositor().CreateExpressionAnimation(); + const auto anim = xaml::Window::Current().Compositor().CreateExpressionAnimation(); anim.Expression([nodes, manager, anim]() { winrt::hstring expr = L"1"; diff --git a/vnext/ReactUWP/Modules/Animated/PropsAnimatedNode.cpp b/vnext/ReactUWP/Modules/Animated/PropsAnimatedNode.cpp index f3faa5bd2eb..47e4a78023f 100644 --- a/vnext/ReactUWP/Modules/Animated/PropsAnimatedNode.cpp +++ b/vnext/ReactUWP/Modules/Animated/PropsAnimatedNode.cpp @@ -22,18 +22,18 @@ PropsAnimatedNode::PropsAnimatedNode( m_propMapping.insert({entry.first.getString(), static_cast(entry.second.asDouble())}); } - m_subchannelPropertySet = winrt::Window::Current().Compositor().CreatePropertySet(); + m_subchannelPropertySet = xaml::Window::Current().Compositor().CreatePropertySet(); m_subchannelPropertySet.InsertScalar(L"TranslationX", 0.0f); m_subchannelPropertySet.InsertScalar(L"TranslationY", 0.0f); m_subchannelPropertySet.InsertScalar(L"ScaleX", 1.0f); m_subchannelPropertySet.InsertScalar(L"ScaleY", 1.0f); - m_translationCombined = winrt::Window::Current().Compositor().CreateExpressionAnimation( + m_translationCombined = xaml::Window::Current().Compositor().CreateExpressionAnimation( L"Vector3(subchannels.TranslationX, subchannels.TranslationY, 0.0)"); m_translationCombined.SetReferenceParameter(L"subchannels", m_subchannelPropertySet); m_translationCombined.Target(L"Translation"); - m_scaleCombined = winrt::Window::Current().Compositor().CreateExpressionAnimation( + m_scaleCombined = xaml::Window::Current().Compositor().CreateExpressionAnimation( L"Vector3(subchannels.ScaleX, subchannels.ScaleY, 1.0)"); m_scaleCombined.SetReferenceParameter(L"subchannels", m_subchannelPropertySet); m_scaleCombined.Target(L"Scale"); @@ -120,7 +120,7 @@ void PropsAnimatedNode::StartAnimations() { } if (m_needsCenterPointAnimation) { if (!m_centerPointAnimation) { - m_centerPointAnimation = winrt::Window::Current().Compositor().CreateExpressionAnimation(); + m_centerPointAnimation = xaml::Window::Current().Compositor().CreateExpressionAnimation(); m_centerPointAnimation.Target(L"CenterPoint"); m_centerPointAnimation.SetReferenceParameter( L"centerPointPropertySet", GetShadowNodeBase()->EnsureTransformPS()); @@ -171,7 +171,7 @@ void PropsAnimatedNode::ResumeSuspendedAnimations(int64_t valueTag) { void PropsAnimatedNode::MakeAnimation(int64_t valueNodeTag, FacadeType facadeType) { if (const auto manager = m_manager.lock()) { if (const auto valueNode = manager->GetValueAnimatedNode(valueNodeTag)) { - const auto animation = winrt::Window::Current().Compositor().CreateExpressionAnimation(); + const auto animation = xaml::Window::Current().Compositor().CreateExpressionAnimation(); animation.SetReferenceParameter(L"ValuePropSet", valueNode->PropertySet()); animation.Expression( static_cast(L"ValuePropSet.") + ValueAnimatedNode::s_valueName + L" + ValuePropSet." + @@ -250,10 +250,10 @@ ShadowNodeBase *PropsAnimatedNode::GetShadowNodeBase() { return nullptr; } -winrt::UIElement PropsAnimatedNode::GetUIElement() { +xaml::UIElement PropsAnimatedNode::GetUIElement() { if (const auto shadowNodeBase = GetShadowNodeBase()) { if (const auto shadowNodeView = shadowNodeBase->GetView()) { - return shadowNodeView.as(); + return shadowNodeView.as(); } } return nullptr; diff --git a/vnext/ReactUWP/Modules/Animated/PropsAnimatedNode.h b/vnext/ReactUWP/Modules/Animated/PropsAnimatedNode.h index 6ca5710c52b..751dc4e9307 100644 --- a/vnext/ReactUWP/Modules/Animated/PropsAnimatedNode.h +++ b/vnext/ReactUWP/Modules/Animated/PropsAnimatedNode.h @@ -29,21 +29,21 @@ class PropsAnimatedNode : public AnimatedNode { private: void MakeAnimation(int64_t valueNodeTag, FacadeType facadeType); ShadowNodeBase *GetShadowNodeBase(); - winrt::UIElement GetUIElement(); + xaml::UIElement GetUIElement(); std::weak_ptr m_instance{}; std::map m_propMapping{}; folly::dynamic m_propMap{}; int64_t m_connectedViewTag{s_connectedViewTagUnset}; - std::unordered_map m_expressionAnimations{}; + std::unordered_map m_expressionAnimations{}; std::vector m_suspendedExpressionAnimationTags{}; - winrt::Windows::UI::Composition::ExpressionAnimation m_centerPointAnimation{nullptr}; + comp::ExpressionAnimation m_centerPointAnimation{nullptr}; winrt::Numerics::float3 m_rotationAxis{0, 0, 1}; bool m_needsCenterPointAnimation{false}; - winrt::CompositionPropertySet m_subchannelPropertySet{nullptr}; - winrt::CompositionAnimation m_translationCombined{nullptr}; - winrt::CompositionAnimation m_scaleCombined{nullptr}; + comp::CompositionPropertySet m_subchannelPropertySet{nullptr}; + comp::CompositionAnimation m_translationCombined{nullptr}; + comp::CompositionAnimation m_scaleCombined{nullptr}; static constexpr int64_t s_connectedViewTagUnset{-1}; }; diff --git a/vnext/ReactUWP/Modules/Animated/SubtractionAnimatedNode.cpp b/vnext/ReactUWP/Modules/Animated/SubtractionAnimatedNode.cpp index d043085de7d..b52454e7553 100644 --- a/vnext/ReactUWP/Modules/Animated/SubtractionAnimatedNode.cpp +++ b/vnext/ReactUWP/Modules/Animated/SubtractionAnimatedNode.cpp @@ -22,7 +22,7 @@ SubtractionAnimatedNode::SubtractionAnimatedNode( } m_propertySet.StartAnimation(s_valueName, [firstNode = m_firstInput, nodes = m_inputNodes, manager]() { - const auto anim = winrt::Window::Current().Compositor().CreateExpressionAnimation(); + const auto anim = xaml::Window::Current().Compositor().CreateExpressionAnimation(); anim.Expression([firstNode, nodes, manager, anim]() { anim.SetReferenceParameter(s_baseName, manager->GetValueAnimatedNode(firstNode)->PropertySet()); diff --git a/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.cpp b/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.cpp index 488e09cae37..b133acacd73 100644 --- a/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.cpp +++ b/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.cpp @@ -13,7 +13,7 @@ ValueAnimatedNode::ValueAnimatedNode( const folly::dynamic &config, const std::shared_ptr &manager) : AnimatedNode(tag, manager) { - m_propertySet = winrt::Window::Current().Compositor().CreatePropertySet(); + m_propertySet = xaml::Window::Current().Compositor().CreatePropertySet(); m_propertySet.InsertScalar( s_valueName, static_cast(config.find(s_jsValueName).dereference().second.asDouble())); m_propertySet.InsertScalar( @@ -22,7 +22,7 @@ ValueAnimatedNode::ValueAnimatedNode( ValueAnimatedNode::ValueAnimatedNode(int64_t tag, const std::shared_ptr &manager) : AnimatedNode(tag, manager) { - m_propertySet = winrt::Window::Current().Compositor().CreatePropertySet(); + m_propertySet = xaml::Window::Current().Compositor().CreatePropertySet(); m_propertySet.InsertScalar(s_valueName, 0.0); m_propertySet.InsertScalar(s_offsetName, 0.0); } diff --git a/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.h b/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.h index 19867e9a20b..7130a48284c 100644 --- a/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.h +++ b/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.h @@ -6,7 +6,7 @@ #include "AnimatedNode.h" namespace winrt { -using namespace winrt::Windows::UI::Composition; +using namespace comp; } namespace react { @@ -25,7 +25,7 @@ class ValueAnimatedNode : public AnimatedNode { void Offset(double offset); void FlattenOffset(); void ExtractOffset(); - winrt::CompositionPropertySet PropertySet() { + comp::CompositionPropertySet PropertySet() { return m_propertySet; }; @@ -40,7 +40,7 @@ class ValueAnimatedNode : public AnimatedNode { static constexpr std::wstring_view s_offsetName{L"o"}; protected: - winrt::CompositionPropertySet m_propertySet{nullptr}; + comp::CompositionPropertySet m_propertySet{nullptr}; static constexpr std::string_view s_inputName{"input"}; diff --git a/vnext/ReactUWP/Modules/AppStateModuleUwp.cpp b/vnext/ReactUWP/Modules/AppStateModuleUwp.cpp index 92b40a92a3f..4fef382b46a 100644 --- a/vnext/ReactUWP/Modules/AppStateModuleUwp.cpp +++ b/vnext/ReactUWP/Modules/AppStateModuleUwp.cpp @@ -5,8 +5,6 @@ #include "AppStateModuleUwp.h" -#include - namespace react { namespace uwp { @@ -18,10 +16,10 @@ AppState::AppState(const std::shared_ptr &reactInstance) : facebook::react::AppState(), m_wkReactInstance(reactInstance) { m_lastState = "active"; - m_enteredBackgroundRevoker = winrt::Windows::UI::Xaml::Application::Current().EnteredBackground( - winrt::auto_revoke, {this, &AppState::EnteredBackground}); - m_leavingBackgroundRevoker = winrt::Windows::UI::Xaml::Application::Current().LeavingBackground( - winrt::auto_revoke, {this, &AppState::LeavingBackground}); + m_enteredBackgroundRevoker = + xaml::Application::Current().EnteredBackground(winrt::auto_revoke, {this, &AppState::EnteredBackground}); + m_leavingBackgroundRevoker = + xaml::Application::Current().LeavingBackground(winrt::auto_revoke, {this, &AppState::LeavingBackground}); } AppState::~AppState() = default; diff --git a/vnext/ReactUWP/Modules/AppStateModuleUwp.h b/vnext/ReactUWP/Modules/AppStateModuleUwp.h index fecee52f16d..102df7836e3 100644 --- a/vnext/ReactUWP/Modules/AppStateModuleUwp.h +++ b/vnext/ReactUWP/Modules/AppStateModuleUwp.h @@ -8,7 +8,6 @@ #include #include -#include namespace react { namespace uwp { @@ -32,8 +31,8 @@ class AppState : public facebook::react::AppState { const char *m_lastState; std::weak_ptr m_wkReactInstance; - winrt::Windows::UI::Xaml::Application::EnteredBackground_revoker m_enteredBackgroundRevoker; - winrt::Windows::UI::Xaml::Application::LeavingBackground_revoker m_leavingBackgroundRevoker; + xaml::Application::EnteredBackground_revoker m_enteredBackgroundRevoker; + xaml::Application::LeavingBackground_revoker m_leavingBackgroundRevoker; }; } // namespace uwp diff --git a/vnext/ReactUWP/Modules/AppThemeModuleUwp.cpp b/vnext/ReactUWP/Modules/AppThemeModuleUwp.cpp index 95775bde17d..af68cec0ce7 100644 --- a/vnext/ReactUWP/Modules/AppThemeModuleUwp.cpp +++ b/vnext/ReactUWP/Modules/AppThemeModuleUwp.cpp @@ -13,7 +13,7 @@ #endif namespace winrt { -using namespace Windows::UI::Xaml; +using namespace xaml; using namespace Windows::UI::ViewManagement; } // namespace winrt diff --git a/vnext/ReactUWP/Modules/AppThemeModuleUwp.h b/vnext/ReactUWP/Modules/AppThemeModuleUwp.h index d8742ccd9cf..15aa3e6f881 100644 --- a/vnext/ReactUWP/Modules/AppThemeModuleUwp.h +++ b/vnext/ReactUWP/Modules/AppThemeModuleUwp.h @@ -30,7 +30,7 @@ class AppTheme { std::weak_ptr m_wkReactInstance; std::shared_ptr m_queueThread; - winrt::Windows::UI::Xaml::ApplicationTheme m_currentTheme{winrt::Windows::UI::Xaml::ApplicationTheme::Light}; + xaml::ApplicationTheme m_currentTheme{xaml::ApplicationTheme::Light}; bool m_isHighContrast; folly::dynamic m_highContrastColors; diff --git a/vnext/ReactUWP/Modules/AppearanceModule.cpp b/vnext/ReactUWP/Modules/AppearanceModule.cpp index 5235c110976..8f4bba5fa6e 100644 --- a/vnext/ReactUWP/Modules/AppearanceModule.cpp +++ b/vnext/ReactUWP/Modules/AppearanceModule.cpp @@ -6,8 +6,8 @@ #include -using Application = winrt::Windows::UI::Xaml::Application; -using ApplicationTheme = winrt::Windows::UI::Xaml::ApplicationTheme; +using Application = xaml::Application; +using ApplicationTheme = xaml::ApplicationTheme; using UISettings = winrt::Windows::UI::ViewManagement::UISettings; using Method = facebook::xplat::module::CxxModule::Method; diff --git a/vnext/ReactUWP/Modules/AppearanceModule.h b/vnext/ReactUWP/Modules/AppearanceModule.h index b4bed580b1a..275c36a3819 100644 --- a/vnext/ReactUWP/Modules/AppearanceModule.h +++ b/vnext/ReactUWP/Modules/AppearanceModule.h @@ -13,7 +13,7 @@ namespace react::uwp { // Listens for the current theme on the UI thread, storing the most recent. Will emit JS events on Appearance change. class AppearanceChangeListener final : public Mso::ActiveObject<> { - using ApplicationTheme = winrt::Windows::UI::Xaml::ApplicationTheme; + using ApplicationTheme = xaml::ApplicationTheme; using UISettings = winrt::Windows::UI::ViewManagement::UISettings; public: diff --git a/vnext/ReactUWP/Modules/DeviceInfoModule.cpp b/vnext/ReactUWP/Modules/DeviceInfoModule.cpp index 222690abecc..ba738f5bffe 100644 --- a/vnext/ReactUWP/Modules/DeviceInfoModule.cpp +++ b/vnext/ReactUWP/Modules/DeviceInfoModule.cpp @@ -21,7 +21,7 @@ DeviceInfo::DeviceInfo(const std::shared_ptr &reactInstance) : m void DeviceInfo::listenToUpdates() { auto const &displayInfo = winrt::Windows::Graphics::Display::DisplayInformation::GetForCurrentView(); - auto const &window = winrt::Windows::UI::Xaml::Window::Current().CoreWindow(); + auto const &window = xaml::Window::Current().CoreWindow(); m_sizeChangedRevoker = window.SizeChanged(winrt::auto_revoke, [this](auto &&, auto &&) { update(); @@ -40,7 +40,7 @@ void DeviceInfo::update() { winrt::Windows::UI::ViewManagement::UISettings uiSettings; - auto const &window = winrt::Windows::UI::Xaml::Window::Current().CoreWindow(); + auto const &window = xaml::Window::Current().CoreWindow(); m_dimensions = folly::dynamic::object( "windowPhysicalPixels", diff --git a/vnext/ReactUWP/Modules/DeviceInfoModule.h b/vnext/ReactUWP/Modules/DeviceInfoModule.h index 813d84b9d42..c938adb571c 100644 --- a/vnext/ReactUWP/Modules/DeviceInfoModule.h +++ b/vnext/ReactUWP/Modules/DeviceInfoModule.h @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff --git a/vnext/ReactUWP/Modules/ImageViewManagerModule.cpp b/vnext/ReactUWP/Modules/ImageViewManagerModule.cpp index 697a70f0f84..8fdee37a63d 100644 --- a/vnext/ReactUWP/Modules/ImageViewManagerModule.cpp +++ b/vnext/ReactUWP/Modules/ImageViewManagerModule.cpp @@ -10,8 +10,6 @@ #include "ImageViewManagerModule.h" -#include - #include #include @@ -26,7 +24,7 @@ namespace winrt { using namespace Windows::Foundation; using namespace Windows::Storage::Streams; -using namespace Windows::UI::Xaml::Media::Imaging; +using namespace xaml::Media::Imaging; } // namespace winrt namespace react { diff --git a/vnext/ReactUWP/Modules/NativeUIManager.cpp b/vnext/ReactUWP/Modules/NativeUIManager.cpp index 64b9183f940..39fde0f6657 100644 --- a/vnext/ReactUWP/Modules/NativeUIManager.cpp +++ b/vnext/ReactUWP/Modules/NativeUIManager.cpp @@ -8,17 +8,15 @@ #include #include -#include -#include -#include +#include "CppWinRTIncludes.h" #include "Unicode.h" namespace winrt { using namespace Windows::Foundation; using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Media; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Media; } // namespace winrt namespace react { @@ -98,7 +96,7 @@ winrt::XamlRoot NativeUIManager::tryGetXamlRoot() { if (m_host) { for (auto const tag : m_host->GetAllRootTags()) { if (auto shadowNode = static_cast(m_host->FindShadowNodeForTag(tag))) { - if (auto uiElement10 = shadowNode->GetView().try_as()) { + if (auto uiElement10 = shadowNode->GetView().try_as()) { if (auto xamlRoot = uiElement10.XamlRoot()) return xamlRoot; } @@ -108,7 +106,7 @@ winrt::XamlRoot NativeUIManager::tryGetXamlRoot() { return nullptr; } -XamlView NativeUIManager::reactPeerOrContainerFrom(winrt::FrameworkElement fe) { +XamlView NativeUIManager::reactPeerOrContainerFrom(xaml::FrameworkElement fe) { if (m_host) { while (fe) { if (auto value = GetTagAsPropertyValue(fe)) { @@ -121,7 +119,7 @@ XamlView NativeUIManager::reactPeerOrContainerFrom(winrt::FrameworkElement fe) { } } } - fe = fe.Parent().try_as(); + fe = fe.Parent().try_as(); } } return nullptr; @@ -159,7 +157,7 @@ struct RootShadowNode final : public ShadowNodeBase { void AddView(facebook::react::ShadowNode &child, int64_t index) override { auto panel(GetView().as()); if (panel != nullptr) { - auto childView = static_cast(child).GetView().as(); + auto childView = static_cast(child).GetView().as(); panel.Children().InsertAt(static_cast(index), childView); } } @@ -189,12 +187,12 @@ void NativeUIManager::AddRootView( m_tagsToYogaNodes.emplace(shadowNode.m_tag, make_yoga_node()); - auto element = view.as(); + auto element = view.as(); element.Tag(winrt::PropertyValue::CreateInt64(shadowNode.m_tag)); // Add listener to size change so we can redo the layout when that happens m_sizeChangedVector.push_back( - view.as().SizeChanged(winrt::auto_revoke, [this](auto &&, auto &&) { DoLayout(); })); + view.as().SizeChanged(winrt::auto_revoke, [this](auto &&, auto &&) { DoLayout(); })); } void NativeUIManager::destroy() { @@ -837,7 +835,7 @@ void NativeUIManager::DoLayout() { const auto extraLayoutNodes = m_extraLayoutNodes; for (const int64_t tag : extraLayoutNodes) { ShadowNodeBase &node = static_cast(m_host->GetShadowNodeForTag(tag)); - auto element = node.GetView().as(); + auto element = node.GetView().as(); element.UpdateLayout(); } // Values need to be cleared from the vector before next call to DoLayout. @@ -848,7 +846,7 @@ void NativeUIManager::DoLayout() { ShadowNodeBase &rootShadowNode = static_cast(m_host->GetShadowNodeForTag(rootTag)); YGNodeRef rootNode = GetYogaNode(rootTag); - auto rootElement = rootShadowNode.GetView().as(); + auto rootElement = rootShadowNode.GetView().as(); float actualWidth = static_cast(rootElement.ActualWidth()); float actualHeight = static_cast(rootElement.ActualHeight()); @@ -878,8 +876,8 @@ void NativeUIManager::DoLayout() { } winrt::Windows::Foundation::Rect GetRectOfElementInParentCoords( - winrt::FrameworkElement element, - winrt::UIElement parent) { + xaml::FrameworkElement element, + xaml::UIElement parent) { if (parent == nullptr) { assert(false); return winrt::Windows::Foundation::Rect(); @@ -907,7 +905,7 @@ void NativeUIManager::measure( ShadowNodeBase &node = static_cast(shadowNode); auto view = node.GetView(); - auto feView = view.try_as(); + auto feView = view.try_as(); if (feView == nullptr) { callback(args); return; @@ -915,7 +913,7 @@ void NativeUIManager::measure( // Traverse up the react node tree to find any windowed popups. // If there are none, then we use the top-level root provided by our caller. - winrt::FrameworkElement feRootView = nullptr; + xaml::FrameworkElement feRootView = nullptr; int64_t rootTag = shadowNode.m_tag; int64_t childTag = rootTag; while (true) { @@ -925,7 +923,7 @@ void NativeUIManager::measure( ShadowNodeBase &rootNode = static_cast(currNode); if (rootNode.IsWindowed()) { ShadowNodeBase &childNode = static_cast(m_host->GetShadowNodeForTag(childTag)); - feRootView = childNode.GetView().try_as(); + feRootView = childNode.GetView().try_as(); break; } childTag = currNode.m_tag; @@ -935,7 +933,7 @@ void NativeUIManager::measure( if (feRootView == nullptr) { // Retrieve the XAML element for the root view containing this view if (auto xamlRootView = static_cast(shadowRoot).GetView()) { - feRootView = xamlRootView.as(); + feRootView = xamlRootView.as(); } if (feRootView == nullptr) { callback(args); @@ -969,8 +967,8 @@ void NativeUIManager::measureInWindow( std::vector args; ShadowNodeBase &node = static_cast(shadowNode); - if (auto view = node.GetView().try_as()) { - auto windowTransform = view.TransformToVisual(winrt::Window::Current().Content()); + if (auto view = node.GetView().try_as()) { + auto windowTransform = view.TransformToVisual(xaml::Window::Current().Content()); auto positionInWindow = windowTransform.TransformPoint({0, 0}); // x, y @@ -994,8 +992,8 @@ void NativeUIManager::measureLayout( try { const auto &target = static_cast(shadowNode); const auto &ancestor = static_cast(ancestorNode); - const auto targetElement = target.GetView().as(); - const auto ancenstorElement = ancestor.GetView().as(); + const auto targetElement = target.GetView().as(); + const auto ancenstorElement = ancestor.GetView().as(); const auto ancestorTransform = targetElement.TransformToVisual(ancenstorElement); const auto width = static_cast(targetElement.ActualWidth()); @@ -1025,7 +1023,7 @@ void NativeUIManager::findSubviewIn( ShadowNodeBase &node = static_cast(shadowNode); auto view = node.GetView(); - auto rootUIView = view.as(); + auto rootUIView = view.as(); if (rootUIView == nullptr) { callback({}); return; @@ -1043,10 +1041,10 @@ void NativeUIManager::findSubviewIn( auto hitTestElements = winrt::VisualTreeHelper::FindElementsInHostCoordinates(pointInAppWindow, rootUIView); int64_t foundTag{}; - winrt::FrameworkElement foundElement = nullptr; + xaml::FrameworkElement foundElement = nullptr; for (const auto &elem : hitTestElements) { - if (foundElement = elem.try_as()) { + if (foundElement = elem.try_as()) { auto tag = foundElement.Tag(); if (tag != nullptr) { foundTag = tag.as().GetInt64(); @@ -1074,7 +1072,7 @@ void NativeUIManager::findSubviewIn( void NativeUIManager::focus(int64_t reactTag) { if (auto shadowNode = static_cast(m_host->FindShadowNodeForTag(reactTag))) { - winrt::FocusManager::TryFocusAsync(shadowNode->GetView(), winrt::FocusState::Programmatic); + xaml::Input::FocusManager::TryFocusAsync(shadowNode->GetView(), winrt::FocusState::Programmatic); } } @@ -1083,7 +1081,7 @@ void NativeUIManager::blur(int64_t reactTag) { if (auto shadowNode = static_cast(m_host->FindShadowNodeForTag(reactTag))) { auto view = shadowNode->GetView(); // Only blur if current UI is focused to avoid problem described in PR #2687 - if (view == winrt::FocusManager::GetFocusedElement().try_as()) { + if (view == xaml::Input::FocusManager::GetFocusedElement().try_as()) { if (auto reactControl = GetParentXamlReactControl(reactTag).lock()) { reactControl->blur(shadowNode->GetView()); } else { diff --git a/vnext/ReactUWP/Modules/NativeUIManager.h b/vnext/ReactUWP/Modules/NativeUIManager.h index 9a8b78491f3..7c1ebbf18a6 100644 --- a/vnext/ReactUWP/Modules/NativeUIManager.h +++ b/vnext/ReactUWP/Modules/NativeUIManager.h @@ -7,8 +7,6 @@ #include #include -#include - #include #include @@ -85,11 +83,11 @@ class NativeUIManager : public facebook::react::INativeUIManager { // XamlIsland/AppWindow scenarios. Since it doesn't have parent, and all nodes // in the tree should have the same XamlRoot, this function iterates all roots // and try to get a valid XamlRoot. - winrt::XamlRoot tryGetXamlRoot(); + xaml::XamlRoot tryGetXamlRoot(); // Searches itself and its parent to get a valid XamlView. // Like Mouse/Keyboard, the event source may not have matched XamlView. - XamlView reactPeerOrContainerFrom(winrt::FrameworkElement fe); + XamlView reactPeerOrContainerFrom(xaml::FrameworkElement fe); private: void DoLayout(); @@ -104,7 +102,7 @@ class NativeUIManager : public facebook::react::INativeUIManager { std::map m_tagsToYogaNodes; std::map> m_tagsToYogaContext; - std::vector m_sizeChangedVector; + std::vector m_sizeChangedVector; std::vector> m_batchCompletedCallbacks; std::vector m_extraLayoutNodes; diff --git a/vnext/ReactUWP/Modules/TimingModule.cpp b/vnext/ReactUWP/Modules/TimingModule.cpp index b1f7856632a..e86efc7d88a 100644 --- a/vnext/ReactUWP/Modules/TimingModule.cpp +++ b/vnext/ReactUWP/Modules/TimingModule.cpp @@ -18,13 +18,12 @@ #pragma warning(pop) #include -#include using namespace facebook::xplat; using namespace folly; namespace winrt { using namespace Windows::Foundation; -using namespace Windows::UI::Xaml::Media; +using namespace xaml::Media; } // namespace winrt using namespace std; @@ -133,7 +132,7 @@ void Timing::createTimer(int64_t id, double duration, double jsSchedulingTime, b if (m_timerQueue.IsEmpty()) { m_rendering.revoke(); - m_rendering = winrt::Windows::UI::Xaml::Media::CompositionTarget::Rendering( + m_rendering = xaml::Media::CompositionTarget::Rendering( winrt::auto_revoke, [wkThis = std::weak_ptr(this->shared_from_this())]( const winrt::IInspectable &, const winrt::IInspectable & /*args*/) { diff --git a/vnext/ReactUWP/Modules/TimingModule.h b/vnext/ReactUWP/Modules/TimingModule.h index b0e3697886d..8577433e633 100644 --- a/vnext/ReactUWP/Modules/TimingModule.h +++ b/vnext/ReactUWP/Modules/TimingModule.h @@ -11,8 +11,6 @@ #include #include -#include - namespace react { namespace uwp { @@ -74,7 +72,7 @@ class Timing : public std::enable_shared_from_this { private: TimingModule *m_parent; TimerQueue m_timerQueue; - winrt::Windows::UI::Xaml::Media::CompositionTarget::Rendering_revoker m_rendering; + xaml::Media::CompositionTarget::Rendering_revoker m_rendering; }; class TimingModule : public facebook::xplat::module::CxxModule { diff --git a/vnext/ReactUWP/Pch/pch.h b/vnext/ReactUWP/Pch/pch.h index 4920153fd4b..e5c6ee216e5 100644 --- a/vnext/ReactUWP/Pch/pch.h +++ b/vnext/ReactUWP/Pch/pch.h @@ -29,11 +29,7 @@ #include #include #include -#include -#include -#include -#include -#include +#include "CppWinRTIncludes.h" #include #include @@ -64,4 +60,4 @@ #include #include #include -#include \ No newline at end of file +#include diff --git a/vnext/ReactUWP/Polyester/ButtonContentViewManager.cpp b/vnext/ReactUWP/Polyester/ButtonContentViewManager.cpp index e3464862c15..a9374a9da53 100644 --- a/vnext/ReactUWP/Polyester/ButtonContentViewManager.cpp +++ b/vnext/ReactUWP/Polyester/ButtonContentViewManager.cpp @@ -7,16 +7,6 @@ #include -#include -#include - -using namespace winrt; -using namespace ::Windows::Foundation; -using namespace ::Windows::UI; -using namespace ::Windows::UI::Xaml; -using namespace ::Windows::UI::Xaml::Controls; -using namespace ::Windows::UI::Xaml::Media; - namespace react { namespace uwp { namespace polyester { @@ -25,14 +15,14 @@ ButtonContentViewManager::ButtonContentViewManager(const std::shared_ptr()); + auto stackPanel(parent.as()); if (stackPanel != nullptr) { - stackPanel.Children().InsertAt(static_cast(index), child.as()); + stackPanel.Children().InsertAt(static_cast(index), child.as()); } } void ButtonContentViewManager::RemoveAllChildren(const XamlView &parent) { - auto stackPanel(parent.as()); + auto stackPanel(parent.as()); if (stackPanel != nullptr) { stackPanel.Children().Clear(); stackPanel.InvalidateMeasure(); @@ -41,7 +31,7 @@ void ButtonContentViewManager::RemoveAllChildren(const XamlView &parent) { } void ButtonContentViewManager::RemoveChildAt(const XamlView &parent, int64_t index) { - auto stackPanel(parent.as()); + auto stackPanel(parent.as()); if (stackPanel != nullptr) { stackPanel.Children().RemoveAt(static_cast(index)); stackPanel.InvalidateMeasure(); @@ -54,8 +44,8 @@ const char *ButtonContentViewManager::GetName() const { } XamlView ButtonContentViewManager::CreateViewCore(int64_t /*tag*/) { - auto stackPanel = StackPanel(); - stackPanel.Orientation(Orientation::Horizontal); + auto stackPanel = xaml::Controls::StackPanel(); + stackPanel.Orientation(xaml::Controls::Orientation::Horizontal); return stackPanel; } diff --git a/vnext/ReactUWP/Polyester/ButtonViewManager.cpp b/vnext/ReactUWP/Polyester/ButtonViewManager.cpp index 573ac85bda4..4137b60871e 100644 --- a/vnext/ReactUWP/Polyester/ButtonViewManager.cpp +++ b/vnext/ReactUWP/Polyester/ButtonViewManager.cpp @@ -10,9 +10,6 @@ #include -#include -#include - namespace react { namespace uwp { namespace polyester { diff --git a/vnext/ReactUWP/Polyester/ButtonViewManager.h b/vnext/ReactUWP/Polyester/ButtonViewManager.h index d3a3f28c714..1e58938a23a 100644 --- a/vnext/ReactUWP/Polyester/ButtonViewManager.h +++ b/vnext/ReactUWP/Polyester/ButtonViewManager.h @@ -6,7 +6,7 @@ #include "ContentControlViewManager.h" namespace winrt { -using Button = winrt::Windows::UI::Xaml::Controls::Button; +using Button = xaml::Controls::Button; } namespace react { diff --git a/vnext/ReactUWP/Polyester/ContentControlViewManager.cpp b/vnext/ReactUWP/Polyester/ContentControlViewManager.cpp index 2b6ab39f8a4..8cd4011c790 100644 --- a/vnext/ReactUWP/Polyester/ContentControlViewManager.cpp +++ b/vnext/ReactUWP/Polyester/ContentControlViewManager.cpp @@ -8,14 +8,12 @@ #include -#include - namespace winrt { using namespace Windows::Foundation; using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Media; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Media; } // namespace winrt namespace react { @@ -28,7 +26,7 @@ void ContentControlShadowNode::DoExtraLayoutPrep(YGNodeRef yogaNode) { m_paddingDirty = false; - auto contentControl = GetView().try_as(); + auto contentControl = GetView().try_as(); auto padding = contentControl.Padding(); YGNodeStyleSetPadding(yogaNode, YGEdgeLeft, static_cast(padding.Left)); @@ -40,14 +38,14 @@ void ContentControlShadowNode::DoExtraLayoutPrep(YGNodeRef yogaNode) { void ContentControlShadowNode::createView() { Super::createView(); - auto obj = GetView().try_as(); + auto obj = GetView().try_as(); if (obj != nullptr) { // Button styles may have padding Yoga is not aware of obj.RegisterPropertyChangedCallback( - winrt::Windows::UI::Xaml::Controls::Control::PaddingProperty(), - [this]( - winrt::Windows::UI::Xaml::DependencyObject const & /*sender*/, - winrt::Windows::UI::Xaml::DependencyProperty const & /*dp*/) { m_paddingDirty = true; }); + xaml::Controls::Control::PaddingProperty(), + [this](xaml::DependencyObject const & /*sender*/, xaml::DependencyProperty const & /*dp*/) { + m_paddingDirty = true; + }); } } @@ -67,13 +65,13 @@ void ContentControlViewManager::AddView(const XamlView &parent, const XamlView & return; } - auto contentControl(parent.as()); + auto contentControl(parent.as()); if (contentControl != nullptr) contentControl.Content(child.as()); } void ContentControlViewManager::RemoveAllChildren(const XamlView &parent) { - auto contentControl(parent.as()); + auto contentControl(parent.as()); if (contentControl != nullptr) contentControl.Content(nullptr); } @@ -82,7 +80,7 @@ void ContentControlViewManager::RemoveChildAt(const XamlView &parent, int64_t in if (index != 0) return; - auto contentControl(parent.as()); + auto contentControl(parent.as()); if (contentControl != nullptr) contentControl.Content(nullptr); } diff --git a/vnext/ReactUWP/Polyester/HyperlinkViewManager.cpp b/vnext/ReactUWP/Polyester/HyperlinkViewManager.cpp index 3754b765de2..d8dd2cc9b7f 100644 --- a/vnext/ReactUWP/Polyester/HyperlinkViewManager.cpp +++ b/vnext/ReactUWP/Polyester/HyperlinkViewManager.cpp @@ -10,16 +10,13 @@ #include -#include -#include - namespace winrt { using namespace Windows::Foundation; using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Xaml::Media; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Controls::Primitives; +using namespace xaml::Media; } // namespace winrt namespace react { diff --git a/vnext/ReactUWP/Polyester/IconViewManager.cpp b/vnext/ReactUWP/Polyester/IconViewManager.cpp index 0dc85e9d501..10a43507480 100644 --- a/vnext/ReactUWP/Polyester/IconViewManager.cpp +++ b/vnext/ReactUWP/Polyester/IconViewManager.cpp @@ -13,14 +13,13 @@ #include #include -#include namespace winrt { using namespace Windows::Foundation; using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Documents; -using namespace Windows::UI::Xaml::Media; +using namespace xaml; +using namespace xaml::Documents; +using namespace xaml::Media; } // namespace winrt namespace react { @@ -40,7 +39,7 @@ class IconShadowNode : public ShadowNodeBase { void updateProperties(const folly::dynamic &&props) override; private: - static void UpdateFontColorProps(winrt::Windows::UI::Xaml::Documents::Glyphs glyphs); + static void UpdateFontColorProps(xaml::Documents::Glyphs glyphs); std::optional m_emSize; double m_height = 24; @@ -129,7 +128,7 @@ void IconShadowNode::updateProperties(const folly::dynamic &&props) { if (appDictionary.HasKey(winrt::box_value(L"SystemAccentColor"))) color = winrt::unbox_value(appDictionary.Lookup(winrt::box_value(L"SystemAccentColor"))); - glyphs.Fill(winrt::SolidColorBrush(color)); + glyphs.Fill(xaml::Media::SolidColorBrush(color)); } // diff --git a/vnext/ReactUWP/Utils/AccessibilityUtils.cpp b/vnext/ReactUWP/Utils/AccessibilityUtils.cpp index 1f4d5497bba..83a02432f3e 100644 --- a/vnext/ReactUWP/Utils/AccessibilityUtils.cpp +++ b/vnext/ReactUWP/Utils/AccessibilityUtils.cpp @@ -7,29 +7,24 @@ #include -namespace winrt { -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Automation; -using namespace Windows::UI::Xaml::Automation::Peers; -} // namespace winrt - namespace react { namespace uwp { REACTWINDOWS_API_(void) -AnnounceLiveRegionChangedIfNeeded(const winrt::FrameworkElement &element) { - if (winrt::AutomationProperties::GetLiveSetting(element) != winrt::AutomationLiveSetting::Off && - !winrt::AutomationProperties::GetName(element).empty()) { - auto peer = winrt::FrameworkElementAutomationPeer::FromElement(element); +AnnounceLiveRegionChangedIfNeeded(const xaml::FrameworkElement &element) { + if (xaml::Automation::AutomationProperties::GetLiveSetting(element) != + xaml::Automation::Peers::AutomationLiveSetting::Off && + !xaml::Automation::AutomationProperties::GetName(element).empty()) { + auto peer = xaml::Automation::Peers::FrameworkElementAutomationPeer::FromElement(element); if (nullptr != peer) { - peer.RaiseAutomationEvent(winrt::AutomationEvents::LiveRegionChanged); + peer.RaiseAutomationEvent(xaml::Automation::Peers::AutomationEvents::LiveRegionChanged); } } } REACTWINDOWS_API_(bool) -HasDynamicAutomationProperties(const winrt::Windows::UI::Xaml::UIElement &element) { - static auto unsetValue = winrt::DependencyProperty::UnsetValue(); +HasDynamicAutomationProperties(const xaml::UIElement &element) { + static auto unsetValue = xaml::DependencyProperty::UnsetValue(); if (element) { return (unsetValue != element.ReadLocalValue(DynamicAutomationProperties::AccessibilityRoleProperty())); diff --git a/vnext/ReactUWP/Utils/Helpers.cpp b/vnext/ReactUWP/Utils/Helpers.cpp index 7877ac62f2a..b2fcad03c61 100644 --- a/vnext/ReactUWP/Utils/Helpers.cpp +++ b/vnext/ReactUWP/Utils/Helpers.cpp @@ -6,11 +6,10 @@ #include #include #include -#include namespace winrt { -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Xaml::Media; +using namespace xaml::Controls::Primitives; +using namespace xaml::Media; using namespace Windows::Foundation::Metadata; } // namespace winrt @@ -27,7 +26,7 @@ namespace uwp { // // Instead of deduce view id directly from FrameworkElement.Tag, this do // additional check by uimanager. -ReactId getViewId(_In_ IReactInstance *instance, winrt::FrameworkElement const &fe) { +ReactId getViewId(_In_ IReactInstance *instance, xaml::FrameworkElement const &fe) { ReactId reactId; if (auto uiManager = static_cast(instance->NativeUIManager())) { if (auto peer = uiManager->reactPeerOrContainerFrom(fe)) { @@ -41,8 +40,8 @@ ReactId getViewId(_In_ IReactInstance *instance, winrt::FrameworkElement const & std::int32_t CountOpenPopups() { // TODO: Use VisualTreeHelper::GetOpenPopupsFromXamlRoot when running against // RS6 - winrt::Windows::Foundation::Collections::IVectorView popups = - winrt::VisualTreeHelper::GetOpenPopups(winrt::Window::Current()); + winrt::Windows::Foundation::Collections::IVectorView popups = + xaml::Media::VisualTreeHelper::GetOpenPopups(xaml::Window::Current()); return (int32_t)popups.Size(); } diff --git a/vnext/ReactUWP/Utils/ResourceBrushUtils.cpp b/vnext/ReactUWP/Utils/ResourceBrushUtils.cpp index 32cfc32537f..d63c55e818c 100644 --- a/vnext/ReactUWP/Utils/ResourceBrushUtils.cpp +++ b/vnext/ReactUWP/Utils/ResourceBrushUtils.cpp @@ -6,20 +6,13 @@ #include #include -#include - -namespace winrt { -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -} // namespace winrt - namespace react { namespace uwp { void UpdateResourceBrush( - const winrt::FrameworkElement &element, + const xaml::FrameworkElement &element, const std::wstring &resourceName, - const winrt::Brush brush) { + const xaml::Media::Brush brush) { const auto resources = element.Resources(); if (resources != nullptr) { if (brush != nullptr) { @@ -30,7 +23,7 @@ void UpdateResourceBrush( } } -void UpdateTextControlBackgroundResourceBrushes(const winrt::FrameworkElement &element, const winrt::Brush brush) { +void UpdateTextControlBackgroundResourceBrushes(const xaml::FrameworkElement &element, const xaml::Media::Brush brush) { UpdateResourceBrush(element, c_textControlBackground, brush); UpdateResourceBrush(element, c_textControlBackgroundPointerOver, brush); UpdateResourceBrush(element, c_textControlBackgroundFocused, brush); @@ -39,7 +32,7 @@ void UpdateTextControlBackgroundResourceBrushes(const winrt::FrameworkElement &e UpdateResourceBrush(element, c_textControlButtonForegroundPressed, brush); } -void UpdateCheckBoxBackgroundResourceBrushes(const winrt::FrameworkElement &element, const winrt::Brush brush) { +void UpdateCheckBoxBackgroundResourceBrushes(const xaml::FrameworkElement &element, const xaml::Media::Brush brush) { UpdateResourceBrush(element, c_checkBoxBackgroundUnchecked, brush); UpdateResourceBrush(element, c_checkBoxBackgroundUncheckedPointerOver, brush); UpdateResourceBrush(element, c_checkBoxBackgroundUncheckedPressed, brush); @@ -54,7 +47,7 @@ void UpdateCheckBoxBackgroundResourceBrushes(const winrt::FrameworkElement &elem UpdateResourceBrush(element, c_checkBoxBackgroundIndeterminateDisabled, brush); } -void UpdateTextControlForegroundResourceBrushes(const winrt::FrameworkElement element, const winrt::Brush brush) { +void UpdateTextControlForegroundResourceBrushes(const xaml::FrameworkElement element, const xaml::Media::Brush brush) { UpdateResourceBrush(element, c_textControlForeground, brush); UpdateResourceBrush(element, c_textControlForegroundPointerOver, brush); UpdateResourceBrush(element, c_textControlForegroundFocused, brush); @@ -65,12 +58,12 @@ void UpdateTextControlForegroundResourceBrushes(const winrt::FrameworkElement el UpdateResourceBrush(element, c_textControlButtonBackgroundPressed, brush); } -void UpdateTextControlBorderResourceBrushes(const winrt::FrameworkElement &element, const winrt::Brush b) { +void UpdateTextControlBorderResourceBrushes(const xaml::FrameworkElement &element, const xaml::Media::Brush &b) { // Workaround for bug https://microsoft.visualstudio.com/OS/_workitems/edit/26118890. // Remove when the bug gets fixed. - winrt::Brush brush = b; - if (auto solidBrush = b.as()) { - brush = winrt::SolidColorBrush{solidBrush.Color()}; + xaml::Media::Brush brush = b; + if (auto solidBrush = b.as()) { + brush = xaml::Media::SolidColorBrush{solidBrush.Color()}; } UpdateResourceBrush(element, c_textControlBorderBrush, brush); @@ -79,7 +72,9 @@ void UpdateTextControlBorderResourceBrushes(const winrt::FrameworkElement &eleme UpdateResourceBrush(element, c_textControlBorderBrushDisabled, brush); } -void UpdateToggleSwitchBorderResourceBrushes(const winrt::ToggleSwitch &toggleSwitch, const winrt::Brush brush) { +void UpdateToggleSwitchBorderResourceBrushes( + const xaml::Controls::ToggleSwitch &toggleSwitch, + const xaml::Media::Brush brush) { UpdateResourceBrush(toggleSwitch, c_toggleSwitchStrokeOff, brush); UpdateResourceBrush(toggleSwitch, c_toggleSwitchStrokeOffPointerOver, brush); UpdateResourceBrush(toggleSwitch, c_toggleSwitchStrokeOffPressed, brush); @@ -90,7 +85,7 @@ void UpdateToggleSwitchBorderResourceBrushes(const winrt::ToggleSwitch &toggleSw UpdateResourceBrush(toggleSwitch, c_toggleSwitchStrokeOnDisabled, brush); } -void UpdateCheckBoxBorderResourceBrushes(const winrt::CheckBox &checkBox, const winrt::Brush brush) { +void UpdateCheckBoxBorderResourceBrushes(const xaml::Controls::CheckBox &checkBox, const xaml::Media::Brush brush) { UpdateResourceBrush(checkBox, c_checkBoxBorderBrushUnchecked, brush); UpdateResourceBrush(checkBox, c_checkBoxBorderBrushUncheckedPointerOver, brush); UpdateResourceBrush(checkBox, c_checkBoxBorderBrushUncheckedPressed, brush); @@ -105,7 +100,9 @@ void UpdateCheckBoxBorderResourceBrushes(const winrt::CheckBox &checkBox, const UpdateResourceBrush(checkBox, c_checkBoxBorderBrushIndeterminateDisabled, brush); } -void UpdateToggleSwitchThumbResourceBrushes(const winrt::ToggleSwitch &toggleSwitch, const winrt::Brush thumbBrush) { +void UpdateToggleSwitchThumbResourceBrushes( + const xaml::Controls::ToggleSwitch &toggleSwitch, + const xaml::Media::Brush thumbBrush) { UpdateResourceBrush(toggleSwitch, c_toggleSwitchKnobFillOff, thumbBrush); UpdateResourceBrush(toggleSwitch, c_toggleSwitchKnobFillOffPointerOver, thumbBrush); UpdateResourceBrush(toggleSwitch, c_toggleSwitchKnobFillOffPressed, thumbBrush); @@ -117,9 +114,9 @@ void UpdateToggleSwitchThumbResourceBrushes(const winrt::ToggleSwitch &toggleSwi } void UpdateToggleSwitchTrackResourceBrushes( - const winrt::ToggleSwitch &toggleSwitch, - const winrt::Brush onTrackBrush, - const winrt::Brush offTrackBrush) { + const xaml::Controls::ToggleSwitch &toggleSwitch, + const xaml::Media::Brush onTrackBrush, + const xaml::Media::Brush offTrackBrush) { UpdateResourceBrush(toggleSwitch, c_toggleSwitchFillOn, onTrackBrush); UpdateResourceBrush(toggleSwitch, c_toggleSwitchFillOnPointerOver, onTrackBrush); UpdateResourceBrush(toggleSwitch, c_toggleSwitchFillOnPressed, onTrackBrush); @@ -131,38 +128,34 @@ void UpdateToggleSwitchTrackResourceBrushes( UpdateResourceBrush(toggleSwitch, c_toggleSwitchFillOffDisabled, offTrackBrush); } -bool IsObjectATextControl(const winrt::DependencyObject &object) { - return object.try_as() != nullptr || object.try_as() != nullptr || - object.try_as() != nullptr || object.try_as() != nullptr; +bool IsObjectATextControl(const xaml::DependencyObject &object) { + return object.try_as() != nullptr || + object.try_as() != nullptr || + object.try_as() != nullptr || + object.try_as() != nullptr; } -void UpdateControlBackgroundResourceBrushes( - const winrt::Windows::UI::Xaml::FrameworkElement &element, - const winrt::Media::Brush brush) { +void UpdateControlBackgroundResourceBrushes(const xaml::FrameworkElement &element, const xaml::Media::Brush brush) { if (IsObjectATextControl(element)) { UpdateTextControlBackgroundResourceBrushes(element, brush); - } else if (const auto checkBox = element.try_as()) { + } else if (const auto checkBox = element.try_as()) { UpdateCheckBoxBackgroundResourceBrushes(checkBox, brush); } } -void UpdateControlForegroundResourceBrushes( - const winrt::Windows::UI::Xaml::DependencyObject object, - const winrt::Media::Brush brush) { +void UpdateControlForegroundResourceBrushes(const xaml::DependencyObject object, const xaml::Media::Brush brush) { if (IsObjectATextControl(object)) { - const auto element = object.try_as(); + const auto element = object.try_as(); UpdateTextControlForegroundResourceBrushes(element, brush); } } -void UpdateControlBorderResourceBrushes( - const winrt::Windows::UI::Xaml::FrameworkElement &element, - const winrt::Media::Brush brush) { +void UpdateControlBorderResourceBrushes(const xaml::FrameworkElement &element, const xaml::Media::Brush brush) { if (IsObjectATextControl(element)) { UpdateTextControlBorderResourceBrushes(element, brush); - } else if (const auto toggleSwitch = element.try_as()) { + } else if (const auto toggleSwitch = element.try_as()) { UpdateToggleSwitchBorderResourceBrushes(toggleSwitch, brush); - } else if (const auto checkBox = element.try_as()) { + } else if (const auto checkBox = element.try_as()) { UpdateCheckBoxBorderResourceBrushes(checkBox, brush); } } diff --git a/vnext/ReactUWP/Utils/ValueUtils.cpp b/vnext/ReactUWP/Utils/ValueUtils.cpp index 2b2a4c54c99..9ce91c8da29 100644 --- a/vnext/ReactUWP/Utils/ValueUtils.cpp +++ b/vnext/ReactUWP/Utils/ValueUtils.cpp @@ -4,7 +4,6 @@ #include "pch.h" #include -#include #include "Unicode.h" #include @@ -18,9 +17,9 @@ namespace winrt { using namespace Windows::Foundation; using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::UI::Xaml::Media; +using namespace xaml; +using namespace xaml::Input; +using namespace xaml::Media; } // namespace winrt namespace react { @@ -47,10 +46,10 @@ struct ColorComp { } }; -winrt::Windows::UI::Xaml::Media::Brush BrushFromColorObject(const folly::dynamic &d) { +xaml::Media::Brush BrushFromColorObject(const folly::dynamic &d) { winrt::hstring resourceName{winrt::to_hstring(d.find("windowsbrush")->second.asString())}; - thread_local static std::map> accentColorMap = { + thread_local static std::map> accentColorMap = { {L"SystemAccentColor", {nullptr}}, {L"SystemAccentColorLight1", {nullptr}}, {L"SystemAccentColorLight2", {nullptr}}, @@ -82,7 +81,7 @@ winrt::Windows::UI::Xaml::Media::Brush BrushFromColorObject(const folly::dynamic auto dictionary{winrt::unbox_value(winrt::Markup::XamlReader::Load(xamlString))}; - auto brush{winrt::unbox_value(dictionary.Lookup(winrt::box_value(resourceName)))}; + auto brush{winrt::unbox_value(dictionary.Lookup(winrt::box_value(resourceName)))}; accentColorMap[resourceName] = winrt::make_weak(brush); @@ -99,13 +98,14 @@ REACTWINDOWS_API_(winrt::Color) ColorFrom(const folly::dynamic &d) { return winrt::ColorHelper::FromArgb(GetAFromArgb(argb), GetRFromArgb(argb), GetGFromArgb(argb), GetBFromArgb(argb)); } -REACTWINDOWS_API_(winrt::SolidColorBrush) +REACTWINDOWS_API_(xaml::Media::SolidColorBrush) SolidColorBrushFrom(const folly::dynamic &d) { if (d.isObject()) { - return BrushFromColorObject(d).as(); + return BrushFromColorObject(d).as(); } - thread_local static std::map, ColorComp> solidColorBrushCache; + thread_local static std::map, ColorComp> + solidColorBrushCache; const auto color = d.isNumber() ? ColorFrom(d) : winrt::Colors::Transparent(); if (solidColorBrushCache.count(color) != 0) { @@ -114,7 +114,7 @@ SolidColorBrushFrom(const folly::dynamic &d) { } } - winrt::SolidColorBrush brush(color); + xaml::Media::SolidColorBrush brush(color); solidColorBrushCache[color] = winrt::make_weak(brush); return brush; } @@ -127,38 +127,38 @@ REACTWINDOWS_API_(winrt::Brush) BrushFrom(const folly::dynamic &d) { return SolidColorBrushFrom(d); } -REACTWINDOWS_API_(winrt::HorizontalAlignment) +REACTWINDOWS_API_(xaml::HorizontalAlignment) HorizontalAlignmentFrom(const folly::dynamic &d) { auto valueString = d.asString(); if (valueString == "center") - return winrt::HorizontalAlignment::Center; + return xaml::HorizontalAlignment::Center; else if (valueString == "left") - return winrt::HorizontalAlignment::Left; + return xaml::HorizontalAlignment::Left; else if (valueString == "right") - return winrt::HorizontalAlignment::Right; + return xaml::HorizontalAlignment::Right; else if (valueString == "stretch") - return winrt::HorizontalAlignment::Stretch; + return xaml::HorizontalAlignment::Stretch; // ASSERT: Invalid value for VerticalAlignment. Shouldn't get this far. assert(false); - return winrt::HorizontalAlignment::Stretch; + return xaml::HorizontalAlignment::Stretch; } -REACTWINDOWS_API_(winrt::VerticalAlignment) +REACTWINDOWS_API_(xaml::VerticalAlignment) VerticalAlignmentFrom(const folly::dynamic &d) { auto valueString = d.asString(); if (valueString == "bottom") - return winrt::VerticalAlignment::Bottom; + return xaml::VerticalAlignment::Bottom; else if (valueString == "center") - return winrt::VerticalAlignment::Center; + return xaml::VerticalAlignment::Center; else if (valueString == "stretch") - return winrt::VerticalAlignment::Stretch; + return xaml::VerticalAlignment::Stretch; else if (valueString == "top") - return winrt::VerticalAlignment::Top; + return xaml::VerticalAlignment::Top; // ASSERT: Invalid value for VerticalAlignment. Shouldn't get this far. assert(false); - return winrt::VerticalAlignment::Stretch; + return xaml::VerticalAlignment::Stretch; } REACTWINDOWS_API_(winrt::DateTime) diff --git a/vnext/ReactUWP/Views/ActivityIndicatorViewManager.cpp b/vnext/ReactUWP/Views/ActivityIndicatorViewManager.cpp index dee000c547d..e05fe855097 100644 --- a/vnext/ReactUWP/Views/ActivityIndicatorViewManager.cpp +++ b/vnext/ReactUWP/Views/ActivityIndicatorViewManager.cpp @@ -27,7 +27,7 @@ folly::dynamic ActivityIndicatorViewManager::GetNativeProps() const { } XamlView ActivityIndicatorViewManager::CreateViewCore(int64_t /*tag*/) { - auto progressRing = winrt::ProgressRing(); + auto progressRing = xaml::Controls::ProgressRing(); return progressRing; } @@ -35,7 +35,7 @@ bool ActivityIndicatorViewManager::UpdateProperty( ShadowNodeBase *nodeToUpdate, const std::string &propertyName, const folly::dynamic &propertyValue) { - auto progressRing = nodeToUpdate->GetView().as(); + auto progressRing = nodeToUpdate->GetView().as(); if (progressRing == nullptr) return true; @@ -43,7 +43,7 @@ bool ActivityIndicatorViewManager::UpdateProperty( if (propertyValue.isBool()) progressRing.IsActive(propertyValue.asBool()); else if (propertyValue.isNull()) - progressRing.ClearValue(winrt::ProgressRing::IsActiveProperty()); + progressRing.ClearValue(xaml::Controls::ProgressRing::IsActiveProperty()); } else { return Super::UpdateProperty(nodeToUpdate, propertyName, propertyValue); } diff --git a/vnext/ReactUWP/Views/CheckboxViewManager.cpp b/vnext/ReactUWP/Views/CheckboxViewManager.cpp index 7710229b8ff..e24fe036628 100644 --- a/vnext/ReactUWP/Views/CheckboxViewManager.cpp +++ b/vnext/ReactUWP/Views/CheckboxViewManager.cpp @@ -10,10 +10,8 @@ #include -#include - namespace winrt { -using ToggleButton = Windows::UI::Xaml::Controls::Primitives::ToggleButton; +using ToggleButton = xaml::Controls::Primitives::ToggleButton; } namespace react { @@ -30,14 +28,14 @@ class CheckBoxShadowNode : public ShadowNodeBase { private: static void OnCheckedChanged(IReactInstance &instance, int64_t tag, bool newValue); - winrt::CheckBox::Checked_revoker m_checkBoxCheckedRevoker{}; - winrt::CheckBox::Unchecked_revoker m_checkBoxUncheckedRevoker{}; + xaml::Controls::CheckBox::Checked_revoker m_checkBoxCheckedRevoker{}; + xaml::Controls::CheckBox::Unchecked_revoker m_checkBoxUncheckedRevoker{}; }; void CheckBoxShadowNode::createView() { Super::createView(); - auto checkbox = GetView().as(); + auto checkbox = GetView().as(); auto wkinstance = GetViewManager()->GetReactInstance(); m_checkBoxCheckedRevoker = checkbox.Checked(winrt::auto_revoke, [=](auto &&, auto &&) { auto instance = wkinstance.lock(); @@ -81,7 +79,7 @@ facebook::react::ShadowNode *CheckBoxViewManager::createShadow() const { } XamlView CheckBoxViewManager::CreateViewCore(int64_t /*tag*/) { - auto checkbox = winrt::CheckBox(); + auto checkbox = xaml::Controls::CheckBox(); return checkbox; } @@ -89,7 +87,7 @@ bool CheckBoxViewManager::UpdateProperty( ShadowNodeBase *nodeToUpdate, const std::string &propertyName, const folly::dynamic &propertyValue) { - auto checkbox = nodeToUpdate->GetView().as(); + auto checkbox = nodeToUpdate->GetView().as(); if (checkbox == nullptr) return true; @@ -97,7 +95,7 @@ bool CheckBoxViewManager::UpdateProperty( if (propertyValue.isBool()) checkbox.IsEnabled(!propertyValue.asBool()); else if (propertyValue.isNull()) - checkbox.ClearValue(winrt::Control::IsEnabledProperty()); + checkbox.ClearValue(xaml::Controls::Control::IsEnabledProperty()); } else if (propertyName == "value") { if (propertyValue.isBool()) checkbox.IsChecked(propertyValue.asBool()); diff --git a/vnext/ReactUWP/Views/ControlViewManager.cpp b/vnext/ReactUWP/Views/ControlViewManager.cpp index ebdff121de5..a2679f44c04 100644 --- a/vnext/ReactUWP/Views/ControlViewManager.cpp +++ b/vnext/ReactUWP/Views/ControlViewManager.cpp @@ -19,22 +19,21 @@ folly::dynamic ControlViewManager::GetNativeProps() const { return props; } void ControlViewManager::TransferProperties(const XamlView &oldView, const XamlView &newView) { - TransferProperty(oldView, newView, winrt::Control::FontSizeProperty()); - TransferProperty(oldView, newView, winrt::Control::FontFamilyProperty()); - TransferProperty(oldView, newView, winrt::Control::FontWeightProperty()); - TransferProperty(oldView, newView, winrt::Control::FontStyleProperty()); - TransferProperty(oldView, newView, winrt::Control::CharacterSpacingProperty()); - TransferProperty(oldView, newView, winrt::Control::IsTextScaleFactorEnabledProperty()); - TransferProperty(oldView, newView, winrt::Control::BackgroundProperty()); - TransferProperty(oldView, newView, winrt::Control::BorderBrushProperty()); - TransferProperty(oldView, newView, winrt::Control::BorderThicknessProperty()); - TransferProperty(oldView, newView, winrt::Control::PaddingProperty()); - TransferProperty(oldView, newView, winrt::Control::ForegroundProperty()); - TransferProperty(oldView, newView, winrt::Control::TabIndexProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::FontSizeProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::FontFamilyProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::FontWeightProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::FontStyleProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::CharacterSpacingProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::IsTextScaleFactorEnabledProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::BackgroundProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::BorderBrushProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::BorderThicknessProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::PaddingProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::ForegroundProperty()); + TransferProperty(oldView, newView, xaml::Controls::Control::TabIndexProperty()); // Control.CornerRadius is only supported on >= RS5 - if (oldView.try_as() && - newView.try_as()) { - TransferProperty(oldView, newView, winrt::Control::CornerRadiusProperty()); + if (oldView.try_as() && newView.try_as()) { + TransferProperty(oldView, newView, xaml::Controls::Control::CornerRadiusProperty()); } Super::TransferProperties(oldView, newView); } @@ -43,7 +42,7 @@ bool ControlViewManager::UpdateProperty( ShadowNodeBase *nodeToUpdate, const std::string &propertyName, const folly::dynamic &propertyValue) { - auto control(nodeToUpdate->GetView().as()); + auto control(nodeToUpdate->GetView().as()); bool implementsPadding = nodeToUpdate->ImplementsPadding(); bool finalizeBorderRadius{false}; @@ -62,21 +61,21 @@ bool ControlViewManager::UpdateProperty( if (tabIndex == static_cast(tabIndex)) { if (tabIndex < 0) { control.IsTabStop(false); - control.ClearValue(winrt::Control::TabIndexProperty()); + control.ClearValue(xaml::Controls::Control::TabIndexProperty()); } else { control.IsTabStop(true); control.TabIndex(static_cast(tabIndex)); } } } else if (propertyValue.isNull()) { - control.ClearValue(winrt::Control::TabIndexProperty()); + control.ClearValue(xaml::Controls::Control::TabIndexProperty()); } } else { ret = Super::UpdateProperty(nodeToUpdate, propertyName, propertyValue); } } - if (finalizeBorderRadius && control.try_as()) { + if (finalizeBorderRadius && control.try_as()) { // Control.CornerRadius is only supported on >= RS5, setting borderRadius on Controls have no effect < RS5 UpdateCornerRadiusOnElement(nodeToUpdate, control); } @@ -86,7 +85,7 @@ bool ControlViewManager::UpdateProperty( void ControlViewManager::OnViewCreated(XamlView view) { // Set the default cornerRadius to 0 for Control: WinUI usually default cornerRadius to 2 // Only works on >= RS5 becuase Control.CornerRadius is only supported >= RS5 - if (auto control = view.try_as()) { + if (auto control = view.try_as()) { control.CornerRadius({0}); } } diff --git a/vnext/ReactUWP/Views/DatePickerViewManager.cpp b/vnext/ReactUWP/Views/DatePickerViewManager.cpp index 0c40b5761cf..04dfa0c3991 100644 --- a/vnext/ReactUWP/Views/DatePickerViewManager.cpp +++ b/vnext/ReactUWP/Views/DatePickerViewManager.cpp @@ -32,18 +32,18 @@ class DatePickerShadowNode : public ShadowNodeBase { m_minTime; // These values are expected to be in milliseconds int64_t m_timeZoneOffsetInSeconds = 0; // Timezone offset is expected to be in seconds - winrt::CalendarDatePicker::DateChanged_revoker m_dataPickerDateChangedRevoker{}; + xaml::Controls::CalendarDatePicker::DateChanged_revoker m_dataPickerDateChangedRevoker{}; }; void DatePickerShadowNode::createView() { Super::createView(); - auto datePicker = GetView().as(); + auto datePicker = GetView().as(); auto wkinstance = GetViewManager()->GetReactInstance(); m_dataPickerDateChangedRevoker = datePicker.DateChanged( winrt::auto_revoke, - [=](winrt::CalendarDatePicker /*picker*/, winrt::CalendarDatePickerDateChangedEventArgs args) { + [=](xaml::Controls::CalendarDatePicker /*picker*/, xaml::Controls::CalendarDatePickerDateChangedEventArgs args) { auto instance = wkinstance.lock(); if (!m_updating && instance != nullptr && args.NewDate() != nullptr) OnDateChanged(*instance, m_tag, args.NewDate().Value()); @@ -53,7 +53,7 @@ void DatePickerShadowNode::createView() { void DatePickerShadowNode::updateProperties(const folly::dynamic &&props) { m_updating = true; - auto datePicker = GetView().as(); + auto datePicker = GetView().as(); if (datePicker == nullptr) return; @@ -69,42 +69,42 @@ void DatePickerShadowNode::updateProperties(const folly::dynamic &&props) { if (propertyValue.isString()) datePicker.DayOfWeekFormat(asHstring(propertyValue)); else if (propertyValue.isNull()) - datePicker.ClearValue(winrt::CalendarDatePicker::DayOfWeekFormatProperty()); + datePicker.ClearValue(xaml::Controls::CalendarDatePicker::DayOfWeekFormatProperty()); } else if (propertyName == "dateFormat") { if (propertyValue.isString()) datePicker.DateFormat(asHstring(propertyValue)); else if (propertyValue.isNull()) - datePicker.ClearValue(winrt::CalendarDatePicker::DateFormatProperty()); + datePicker.ClearValue(xaml::Controls::CalendarDatePicker::DateFormatProperty()); } else if (propertyName == "firstDayOfWeek") { if (propertyValue.isNumber()) datePicker.FirstDayOfWeek(static_cast(static_cast(propertyValue.asDouble()))); else if (propertyValue.isNull()) - datePicker.ClearValue(winrt::CalendarDatePicker::FirstDayOfWeekProperty()); + datePicker.ClearValue(xaml::Controls::CalendarDatePicker::FirstDayOfWeekProperty()); } else if (propertyName == "maxDate") { if (propertyValue.isNumber()) { m_maxTime = static_cast(propertyValue.asDouble()); updateMaxDate = true; } else if (propertyValue.isNull()) { - datePicker.ClearValue(winrt::CalendarDatePicker::MaxDateProperty()); + datePicker.ClearValue(xaml::Controls::CalendarDatePicker::MaxDateProperty()); } } else if (propertyName == "minDate") { if (propertyValue.isNumber()) { m_minTime = static_cast(propertyValue.asDouble()); updateMinDate = true; } else if (propertyValue.isNull()) { - datePicker.ClearValue(winrt::CalendarDatePicker::MinDateProperty()); + datePicker.ClearValue(xaml::Controls::CalendarDatePicker::MinDateProperty()); } } else if (propertyName == "placeholderText") { if (propertyValue.isString()) datePicker.PlaceholderText(asHstring(propertyValue)); else if (propertyValue.isNull()) - datePicker.ClearValue(winrt::CalendarDatePicker::PlaceholderTextProperty()); + datePicker.ClearValue(xaml::Controls::CalendarDatePicker::PlaceholderTextProperty()); } else if (propertyName == "selectedDate") { if (propertyValue.isNumber()) { m_selectedTime = static_cast(propertyValue.asDouble()); updateSelectedDate = true; } else if (propertyValue.isNull()) { - datePicker.ClearValue(winrt::CalendarDatePicker::DateProperty()); + datePicker.ClearValue(xaml::Controls::CalendarDatePicker::DateProperty()); } } else if (propertyName == "timeZoneOffsetInSeconds") { if (propertyValue.isNumber()) @@ -157,7 +157,7 @@ facebook::react::ShadowNode *DatePickerViewManager::createShadow() const { } XamlView DatePickerViewManager::CreateViewCore(int64_t /*tag*/) { - auto datePicker = winrt::CalendarDatePicker(); + auto datePicker = xaml::Controls::CalendarDatePicker(); return datePicker; } diff --git a/vnext/ReactUWP/Views/DynamicAutomationPeer.cpp b/vnext/ReactUWP/Views/DynamicAutomationPeer.cpp index 2b2ef36bdba..f4d91f2b453 100644 --- a/vnext/ReactUWP/Views/DynamicAutomationPeer.cpp +++ b/vnext/ReactUWP/Views/DynamicAutomationPeer.cpp @@ -6,9 +6,6 @@ #include "DynamicAutomationPeer.h" #include "DynamicAutomationProperties.h" -#include -#include - // Needed for latest versions of C++/WinRT #if __has_include("DynamicAutomationPeer.g.cpp") #include "DynamicAutomationPeer.g.cpp" @@ -16,18 +13,18 @@ namespace winrt { using namespace Windows::Foundation; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Automation; -using namespace Windows::UI::Xaml::Automation::Peers; -using namespace Windows::UI::Xaml::Automation::Provider; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Interop; -using namespace Windows::UI::Xaml::Media; +using namespace xaml; +using namespace xaml::Automation; +using namespace xaml::Automation::Peers; +using namespace xaml::Automation::Provider; +using namespace xaml::Controls; +using namespace xaml::Interop; +using namespace xaml::Media; } // namespace winrt namespace winrt::PROJECT_ROOT_NAMESPACE::implementation { -DynamicAutomationPeer::DynamicAutomationPeer(winrt::FrameworkElement const &owner) : Super(owner) {} +DynamicAutomationPeer::DynamicAutomationPeer(xaml::FrameworkElement const &owner) : Super(owner) {} winrt::hstring DynamicAutomationPeer::GetClassNameCore() const { return L"DynamicAutomationPeer"; @@ -312,7 +309,7 @@ bool DynamicAutomationPeer::HasAccessibilityState(winrt::PROJECT_ROOT_NAMESPACE: value = owner.ReadLocalValue(DynamicAutomationProperties::AccessibilityStateCollapsedProperty()); break; } - return (value != winrt::DependencyProperty::UnsetValue()); + return (value != xaml::DependencyProperty::UnsetValue()); } } catch (...) { } diff --git a/vnext/ReactUWP/Views/DynamicAutomationPeer.h b/vnext/ReactUWP/Views/DynamicAutomationPeer.h index c3e1c88ca7d..dd607b58730 100644 --- a/vnext/ReactUWP/Views/DynamicAutomationPeer.h +++ b/vnext/ReactUWP/Views/DynamicAutomationPeer.h @@ -4,11 +4,6 @@ #pragma once #include -#include -#include -#include -#include -#include #include "DynamicAutomationProperties.h" @@ -24,14 +19,14 @@ struct DynamicAutomationPeer : DynamicAutomationPeerT { using Super = DynamicAutomationPeerT; DynamicAutomationPeer() = delete; - DynamicAutomationPeer(winrt::Windows::UI::Xaml::FrameworkElement const &owner); + DynamicAutomationPeer(xaml::FrameworkElement const &owner); winrt::hstring GetClassNameCore() const; winrt::hstring GetNameCore() const; - winrt::Windows::UI::Xaml::Automation::Peers::AutomationControlType GetAutomationControlTypeCore() const; + xaml::Automation::Peers::AutomationControlType GetAutomationControlTypeCore() const; winrt::Windows::Foundation::IInspectable GetPatternCore( - winrt::Windows::UI::Xaml::Automation::Peers::PatternInterface const &patternInterface) const; + xaml::Automation::Peers::PatternInterface const &patternInterface) const; bool IsEnabledCore() const; @@ -47,21 +42,21 @@ struct DynamicAutomationPeer : DynamicAutomationPeerT { bool IsSelectionRequired() const { return false; } - winrt::com_array GetSelection() const; + winrt::com_array GetSelection() const; // ISelectionItemProvider bool IsSelected() const; - winrt::Windows::UI::Xaml::Automation::Provider::IRawElementProviderSimple SelectionContainer() const; + xaml::Automation::Provider::IRawElementProviderSimple SelectionContainer() const; void AddToSelection() const; void RemoveFromSelection() const; void Select() const; // IToggleProvider - winrt::Windows::UI::Xaml::Automation::ToggleState ToggleState() const; + xaml::Automation::ToggleState ToggleState() const; void Toggle() const; // IExpandCollapseProvider - winrt::Windows::UI::Xaml::Automation::ExpandCollapseState ExpandCollapseState() const; + xaml::Automation::ExpandCollapseState ExpandCollapseState() const; void Expand() const; void Collapse() const; @@ -72,21 +67,19 @@ struct DynamicAutomationPeer : DynamicAutomationPeerT { bool GetAccessibilityState(winrt::PROJECT_ROOT_NAMESPACE::AccessibilityStates state) const; winrt::PROJECT_ROOT_NAMESPACE::AccessibilityInvokeEventHandler GetAccessibilityInvokeEventHandler() const; - static winrt::Windows::UI::Xaml::DependencyProperty AccessibilityActionsProperty(); + static xaml::DependencyProperty AccessibilityActionsProperty(); static void SetAccessibilityActions( - Windows::UI::Xaml::UIElement const &element, + xaml::UIElement const &element, Windows::Foundation::Collections::IVector const &value); static Windows::Foundation::Collections::IVector GetAccessibilityActions( - Windows::UI::Xaml::UIElement const &element); - static void DispatchAccessibilityAction( - Windows::UI::Xaml::UIElement const &element, - std::wstring_view const &actionName); - static winrt::Windows::UI::Xaml::DependencyProperty AccessibilityActionEventHandlerProperty(); + xaml::UIElement const &element); + static void DispatchAccessibilityAction(xaml::UIElement const &element, std::wstring_view const &actionName); + static xaml::DependencyProperty AccessibilityActionEventHandlerProperty(); static void SetAccessibilityActionEventHandler( - Windows::UI::Xaml::UIElement const &element, + xaml::UIElement const &element, winrt::PROJECT_ROOT_NAMESPACE::AccessibilityActionEventHandler const &value); static winrt::PROJECT_ROOT_NAMESPACE::AccessibilityActionEventHandler GetAccessibilityActionEventHandler( - winrt::Windows::UI::Xaml::UIElement const &element); + xaml::UIElement const &element); }; } // namespace winrt::PROJECT_ROOT_NAMESPACE::implementation diff --git a/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp b/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp index 29580019967..495759e25d2 100644 --- a/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp +++ b/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp @@ -5,9 +5,6 @@ #include "DynamicAutomationProperties.h" -#include -#include - // Needed for latest versions of C++/WinRT #if __has_include("DynamicAutomationProperties.g.cpp") #include "DynamicAutomationProperties.g.cpp" @@ -16,8 +13,8 @@ namespace winrt { using namespace Windows::Foundation; using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Interop; +using namespace xaml; +using namespace xaml::Interop; } // namespace winrt namespace winrt::PROJECT_ROOT_NAMESPACE::implementation { @@ -25,8 +22,8 @@ namespace winrt::PROJECT_ROOT_NAMESPACE::implementation { const winrt::TypeName dynamicAutomationTypeName{winrt::hstring{L"DynamicAutomationProperties"}, winrt::TypeKind::Metadata}; -winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::AccessibilityRoleProperty() { - static winrt::DependencyProperty s_AccessibilityRoleProperty = winrt::DependencyProperty::RegisterAttached( +xaml::DependencyProperty DynamicAutomationProperties::AccessibilityRoleProperty() { + static xaml::DependencyProperty s_AccessibilityRoleProperty = xaml::DependencyProperty::RegisterAttached( L"AccessibilityRole", winrt::xaml_typename(), dynamicAutomationTypeName, @@ -36,19 +33,19 @@ winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::Access } void DynamicAutomationProperties::SetAccessibilityRole( - winrt::Windows::UI::Xaml::UIElement const &element, + xaml::UIElement const &element, winrt::PROJECT_ROOT_NAMESPACE::AccessibilityRoles const &value) { element.SetValue(AccessibilityRoleProperty(), winrt::box_value(value)); } winrt::PROJECT_ROOT_NAMESPACE::AccessibilityRoles DynamicAutomationProperties::GetAccessibilityRole( - winrt::Windows::UI::Xaml::UIElement const &element) { + xaml::UIElement const &element) { return winrt::unbox_value( element.GetValue(AccessibilityRoleProperty())); } -winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateSelectedProperty() { - static winrt::DependencyProperty s_AccessibilityStateSelectedProperty = winrt::DependencyProperty::RegisterAttached( +xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateSelectedProperty() { + static xaml::DependencyProperty s_AccessibilityStateSelectedProperty = xaml::DependencyProperty::RegisterAttached( L"AccessibilityStateSelected", winrt::xaml_typename(), dynamicAutomationTypeName, @@ -57,18 +54,16 @@ winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::Access return s_AccessibilityStateSelectedProperty; } -void DynamicAutomationProperties::SetAccessibilityStateSelected( - winrt::Windows::UI::Xaml::UIElement const &element, - bool value) { +void DynamicAutomationProperties::SetAccessibilityStateSelected(xaml::UIElement const &element, bool value) { element.SetValue(AccessibilityStateSelectedProperty(), winrt::box_value(value)); } -bool DynamicAutomationProperties::GetAccessibilityStateSelected(winrt::Windows::UI::Xaml::UIElement const &element) { +bool DynamicAutomationProperties::GetAccessibilityStateSelected(xaml::UIElement const &element) { return winrt::unbox_value(element.GetValue(AccessibilityStateSelectedProperty())); } -winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateDisabledProperty() { - static winrt::DependencyProperty s_AccessibilityStateDisabledProperty = winrt::DependencyProperty::RegisterAttached( +xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateDisabledProperty() { + static xaml::DependencyProperty s_AccessibilityStateDisabledProperty = xaml::DependencyProperty::RegisterAttached( L"AccessibilityStateDisabled", winrt::xaml_typename(), dynamicAutomationTypeName, @@ -77,18 +72,16 @@ winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::Access return s_AccessibilityStateDisabledProperty; } -void DynamicAutomationProperties::SetAccessibilityStateDisabled( - winrt::Windows::UI::Xaml::UIElement const &element, - bool value) { +void DynamicAutomationProperties::SetAccessibilityStateDisabled(xaml::UIElement const &element, bool value) { element.SetValue(AccessibilityStateDisabledProperty(), winrt::box_value(value)); } -bool DynamicAutomationProperties::GetAccessibilityStateDisabled(winrt::Windows::UI::Xaml::UIElement const &element) { +bool DynamicAutomationProperties::GetAccessibilityStateDisabled(xaml::UIElement const &element) { return winrt::unbox_value(element.GetValue(AccessibilityStateDisabledProperty())); } -winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateCheckedProperty() { - static winrt::DependencyProperty s_AccessibilityStateCheckedProperty = winrt::DependencyProperty::RegisterAttached( +xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateCheckedProperty() { + static xaml::DependencyProperty s_AccessibilityStateCheckedProperty = xaml::DependencyProperty::RegisterAttached( L"AccessibilityStateChecked", winrt::xaml_typename(), dynamicAutomationTypeName, @@ -97,18 +90,16 @@ winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::Access return s_AccessibilityStateCheckedProperty; } -void DynamicAutomationProperties::SetAccessibilityStateChecked( - winrt::Windows::UI::Xaml::UIElement const &element, - bool value) { +void DynamicAutomationProperties::SetAccessibilityStateChecked(xaml::UIElement const &element, bool value) { element.SetValue(AccessibilityStateCheckedProperty(), winrt::box_value(value)); } -bool DynamicAutomationProperties::GetAccessibilityStateChecked(winrt::Windows::UI::Xaml::UIElement const &element) { +bool DynamicAutomationProperties::GetAccessibilityStateChecked(xaml::UIElement const &element) { return winrt::unbox_value(element.GetValue(AccessibilityStateCheckedProperty())); } -winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateUncheckedProperty() { - static winrt::DependencyProperty s_AccessibilityStateUncheckedProperty = winrt::DependencyProperty::RegisterAttached( +xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateUncheckedProperty() { + static xaml::DependencyProperty s_AccessibilityStateUncheckedProperty = xaml::DependencyProperty::RegisterAttached( L"AccessibilityStateUnchecked", winrt::xaml_typename(), dynamicAutomationTypeName, @@ -117,18 +108,16 @@ winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::Access return s_AccessibilityStateUncheckedProperty; } -void DynamicAutomationProperties::SetAccessibilityStateUnchecked( - winrt::Windows::UI::Xaml::UIElement const &element, - bool value) { +void DynamicAutomationProperties::SetAccessibilityStateUnchecked(xaml::UIElement const &element, bool value) { element.SetValue(AccessibilityStateUncheckedProperty(), winrt::box_value(value)); } -bool DynamicAutomationProperties::GetAccessibilityStateUnchecked(winrt::Windows::UI::Xaml::UIElement const &element) { +bool DynamicAutomationProperties::GetAccessibilityStateUnchecked(xaml::UIElement const &element) { return winrt::unbox_value(element.GetValue(AccessibilityStateUncheckedProperty())); } -winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateBusyProperty() { - static winrt::DependencyProperty s_AccessibilityStateBusyProperty = winrt::DependencyProperty::RegisterAttached( +xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateBusyProperty() { + static xaml::DependencyProperty s_AccessibilityStateBusyProperty = xaml::DependencyProperty::RegisterAttached( L"AccessibilityStateBusy", winrt::xaml_typename(), dynamicAutomationTypeName, @@ -137,18 +126,16 @@ winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::Access return s_AccessibilityStateBusyProperty; } -void DynamicAutomationProperties::SetAccessibilityStateBusy( - winrt::Windows::UI::Xaml::UIElement const &element, - bool value) { +void DynamicAutomationProperties::SetAccessibilityStateBusy(xaml::UIElement const &element, bool value) { element.SetValue(AccessibilityStateBusyProperty(), winrt::box_value(value)); } -bool DynamicAutomationProperties::GetAccessibilityStateBusy(winrt::Windows::UI::Xaml::UIElement const &element) { +bool DynamicAutomationProperties::GetAccessibilityStateBusy(xaml::UIElement const &element) { return winrt::unbox_value(element.GetValue(AccessibilityStateBusyProperty())); } -winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateExpandedProperty() { - static winrt::DependencyProperty s_AccessibilityStateExpandedProperty = winrt::DependencyProperty::RegisterAttached( +xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateExpandedProperty() { + static xaml::DependencyProperty s_AccessibilityStateExpandedProperty = xaml::DependencyProperty::RegisterAttached( L"AccessibilityStateExpanded", winrt::xaml_typename(), dynamicAutomationTypeName, @@ -157,18 +144,16 @@ winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::Access return s_AccessibilityStateExpandedProperty; } -void DynamicAutomationProperties::SetAccessibilityStateExpanded( - winrt::Windows::UI::Xaml::UIElement const &element, - bool value) { +void DynamicAutomationProperties::SetAccessibilityStateExpanded(xaml::UIElement const &element, bool value) { element.SetValue(AccessibilityStateExpandedProperty(), winrt::box_value(value)); } -bool DynamicAutomationProperties::GetAccessibilityStateExpanded(winrt::Windows::UI::Xaml::UIElement const &element) { +bool DynamicAutomationProperties::GetAccessibilityStateExpanded(xaml::UIElement const &element) { return winrt::unbox_value(element.GetValue(AccessibilityStateExpandedProperty())); } -winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateCollapsedProperty() { - static winrt::DependencyProperty s_AccessibilityStateCollapsedProperty = winrt::DependencyProperty::RegisterAttached( +xaml::DependencyProperty DynamicAutomationProperties::AccessibilityStateCollapsedProperty() { + static xaml::DependencyProperty s_AccessibilityStateCollapsedProperty = xaml::DependencyProperty::RegisterAttached( L"AccessibilityStateCollapsed", winrt::xaml_typename(), dynamicAutomationTypeName, @@ -177,19 +162,17 @@ winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::Access return s_AccessibilityStateCollapsedProperty; } -void DynamicAutomationProperties::SetAccessibilityStateCollapsed( - winrt::Windows::UI::Xaml::UIElement const &element, - bool value) { +void DynamicAutomationProperties::SetAccessibilityStateCollapsed(xaml::UIElement const &element, bool value) { element.SetValue(AccessibilityStateCollapsedProperty(), winrt::box_value(value)); } -bool DynamicAutomationProperties::GetAccessibilityStateCollapsed(winrt::Windows::UI::Xaml::UIElement const &element) { +bool DynamicAutomationProperties::GetAccessibilityStateCollapsed(xaml::UIElement const &element) { return winrt::unbox_value(element.GetValue(AccessibilityStateCollapsedProperty())); } -winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::AccessibilityInvokeEventHandlerProperty() { - static winrt::DependencyProperty s_AccessibilityInvokeEventHandlerProperty = - winrt::DependencyProperty::RegisterAttached( +xaml::DependencyProperty DynamicAutomationProperties::AccessibilityInvokeEventHandlerProperty() { + static xaml::DependencyProperty s_AccessibilityInvokeEventHandlerProperty = + xaml::DependencyProperty::RegisterAttached( L"AccessibilityInvokeEventHandler", winrt::xaml_typename(), dynamicAutomationTypeName, @@ -200,7 +183,7 @@ winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::Access } void DynamicAutomationProperties::SetAccessibilityInvokeEventHandler( - winrt::Windows::UI::Xaml::UIElement const &element, + xaml::UIElement const &element, winrt::PROJECT_ROOT_NAMESPACE::AccessibilityInvokeEventHandler const &value) { element.SetValue( AccessibilityInvokeEventHandlerProperty(), @@ -208,13 +191,13 @@ void DynamicAutomationProperties::SetAccessibilityInvokeEventHandler( } winrt::PROJECT_ROOT_NAMESPACE::AccessibilityInvokeEventHandler -DynamicAutomationProperties::GetAccessibilityInvokeEventHandler(winrt::Windows::UI::Xaml::UIElement const &element) { +DynamicAutomationProperties::GetAccessibilityInvokeEventHandler(xaml::UIElement const &element) { return winrt::unbox_value( element.GetValue(AccessibilityInvokeEventHandlerProperty())); } -winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::AccessibilityActionsProperty() { - static winrt::DependencyProperty s_AccessibilityActionsProperty = winrt::DependencyProperty::RegisterAttached( +xaml::DependencyProperty DynamicAutomationProperties::AccessibilityActionsProperty() { + static xaml::DependencyProperty s_AccessibilityActionsProperty = xaml::DependencyProperty::RegisterAttached( L"AccessibilityActions", winrt::xaml_typename>(), dynamicAutomationTypeName, @@ -224,19 +207,19 @@ winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::Access } void DynamicAutomationProperties::SetAccessibilityActions( - Windows::UI::Xaml::UIElement const &element, + xaml::UIElement const &element, Windows::Foundation::Collections::IVector const &value) { return element.SetValue(AccessibilityActionsProperty(), winrt::box_value(value)); } Windows::Foundation::Collections::IVector -DynamicAutomationProperties::GetAccessibilityActions(Windows::UI::Xaml::UIElement const &element) { +DynamicAutomationProperties::GetAccessibilityActions(xaml::UIElement const &element) { return winrt::unbox_value>( element.GetValue(AccessibilityActionsProperty())); } void DynamicAutomationProperties::DispatchAccessibilityAction( - Windows::UI::Xaml::UIElement const &element, + xaml::UIElement const &element, std::wstring_view const &actionName) { if (element) { auto vector = GetAccessibilityActions(element); @@ -254,9 +237,9 @@ void DynamicAutomationProperties::DispatchAccessibilityAction( } } -winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::AccessibilityActionEventHandlerProperty() { - static winrt::DependencyProperty s_AccessibilityActionEventHandlerProperty = - winrt::DependencyProperty::RegisterAttached( +xaml::DependencyProperty DynamicAutomationProperties::AccessibilityActionEventHandlerProperty() { + static xaml::DependencyProperty s_AccessibilityActionEventHandlerProperty = + xaml::DependencyProperty::RegisterAttached( L"AccessibilityActionEventHandler", winrt::xaml_typename(), dynamicAutomationTypeName, @@ -267,7 +250,7 @@ winrt::Windows::UI::Xaml::DependencyProperty DynamicAutomationProperties::Access } void DynamicAutomationProperties::SetAccessibilityActionEventHandler( - winrt::Windows::UI::Xaml::UIElement const &element, + xaml::UIElement const &element, winrt::PROJECT_ROOT_NAMESPACE::AccessibilityActionEventHandler const &value) { element.SetValue( AccessibilityActionEventHandlerProperty(), @@ -275,7 +258,7 @@ void DynamicAutomationProperties::SetAccessibilityActionEventHandler( } winrt::PROJECT_ROOT_NAMESPACE::AccessibilityActionEventHandler -DynamicAutomationProperties::GetAccessibilityActionEventHandler(winrt::Windows::UI::Xaml::UIElement const &element) { +DynamicAutomationProperties::GetAccessibilityActionEventHandler(xaml::UIElement const &element) { return winrt::unbox_value( element.GetValue(AccessibilityActionEventHandlerProperty())); } diff --git a/vnext/ReactUWP/Views/DynamicAutomationProperties.h b/vnext/ReactUWP/Views/DynamicAutomationProperties.h index 7e6fd46fa78..0f4e6702fd6 100644 --- a/vnext/ReactUWP/Views/DynamicAutomationProperties.h +++ b/vnext/ReactUWP/Views/DynamicAutomationProperties.h @@ -3,8 +3,6 @@ #pragma once -#include - #include "DynamicAutomationProperties.g.h" #ifndef PROJECT_ROOT_NAMESPACE @@ -31,66 +29,64 @@ struct DynamicAutomationProperties : DynamicAutomationPropertiesT const &value); static Windows::Foundation::Collections::IVector GetAccessibilityActions( - Windows::UI::Xaml::UIElement const &element); + xaml::UIElement const &element); - static void DispatchAccessibilityAction( - Windows::UI::Xaml::UIElement const &element, - std::wstring_view const &actionName); + static void DispatchAccessibilityAction(xaml::UIElement const &element, std::wstring_view const &actionName); - static winrt::Windows::UI::Xaml::DependencyProperty AccessibilityActionEventHandlerProperty(); + static xaml::DependencyProperty AccessibilityActionEventHandlerProperty(); static void SetAccessibilityActionEventHandler( - Windows::UI::Xaml::UIElement const &element, + xaml::UIElement const &element, winrt::PROJECT_ROOT_NAMESPACE::AccessibilityActionEventHandler const &value); static winrt::PROJECT_ROOT_NAMESPACE::AccessibilityActionEventHandler GetAccessibilityActionEventHandler( - winrt::Windows::UI::Xaml::UIElement const &element); + xaml::UIElement const &element); }; } // namespace winrt::PROJECT_ROOT_NAMESPACE::implementation diff --git a/vnext/ReactUWP/Views/ExpressionAnimationStore.cpp b/vnext/ReactUWP/Views/ExpressionAnimationStore.cpp index cb04b289249..d14b494bd51 100644 --- a/vnext/ReactUWP/Views/ExpressionAnimationStore.cpp +++ b/vnext/ReactUWP/Views/ExpressionAnimationStore.cpp @@ -6,17 +6,12 @@ #include "ExpressionAnimationStore.h" #include "XamlFeatures.h" -namespace winrt { -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Composition; -} // namespace winrt - namespace react { namespace uwp { // Expression for computing the center point of a UIElement, produces a vector3 // with 2D translation to center. -winrt::ExpressionAnimation ExpressionAnimationStore::GetElementCenterPointExpression() { +comp::ExpressionAnimation ExpressionAnimationStore::GetElementCenterPointExpression() { /* // Because of a bug in the Composition system, we cannot cache this @@ -30,7 +25,7 @@ winrt::ExpressionAnimation ExpressionAnimationStore::GetElementCenterPointExpres if (m_elementCenterPointExpression == nullptr) { m_elementCenterPointExpression = - winrt::Window::Current().Compositor().CreateExpressionAnimation( + xaml::Window::Current().Compositor().CreateExpressionAnimation( L"vector3(0.5 * uielement.ActualSize.x, 0.5 * uielement.ActualSize.y, 0)"); } @@ -45,7 +40,7 @@ winrt::ExpressionAnimation ExpressionAnimationStore::GetElementCenterPointExpres // The way we obtain the center of an element is by using the ActualSize façade. However this was only added in 19h1 // An expression animation that refers to a non-existent property (e.g. in RS5) will crash, so use the CenterPoint as // a fallback. This might be wrong but at least we won't crash. - return winrt::Window::Current().Compositor().CreateExpressionAnimation( + return xaml::Window::Current().Compositor().CreateExpressionAnimation( g_HasActualSizeProperty == TriBit::Set ? L"vector3(0.5 * uielement.ActualSize.x, 0.5 * uielement.ActualSize.y, 0)" : L"vector3(uielement.CenterPoint.X, uielement.CenterPoint.Y, uielement.CenterPoint.Z)"); @@ -53,9 +48,9 @@ winrt::ExpressionAnimation ExpressionAnimationStore::GetElementCenterPointExpres // Expression for applying a TransformMatrix about the centerpoint of a // UIElement, produces a Matrix4x4 with overall transform. -winrt::ExpressionAnimation ExpressionAnimationStore::GetTransformCenteringExpression() { +comp::ExpressionAnimation ExpressionAnimationStore::GetTransformCenteringExpression() { if (m_transformCenteringExpression == nullptr) { - m_transformCenteringExpression = winrt::Window::Current().Compositor().CreateExpressionAnimation( + m_transformCenteringExpression = xaml::Window::Current().Compositor().CreateExpressionAnimation( L"Matrix4x4.CreateFromTranslation(-PS.center) * PS.transform * Matrix4x4.CreateFromTranslation(PS.center)"); } diff --git a/vnext/ReactUWP/Views/ExpressionAnimationStore.h b/vnext/ReactUWP/Views/ExpressionAnimationStore.h index 55dd42fa0fe..044b75788f7 100644 --- a/vnext/ReactUWP/Views/ExpressionAnimationStore.h +++ b/vnext/ReactUWP/Views/ExpressionAnimationStore.h @@ -3,8 +3,6 @@ #pragma once -#include - namespace react { namespace uwp { @@ -16,14 +14,14 @@ namespace uwp { // resolved, so they can be reused. class ExpressionAnimationStore { public: - winrt::Windows::UI::Composition::ExpressionAnimation GetElementCenterPointExpression(); - winrt::Windows::UI::Composition::ExpressionAnimation GetTransformCenteringExpression(); + comp::ExpressionAnimation GetElementCenterPointExpression(); + comp::ExpressionAnimation GetTransformCenteringExpression(); private: // Compositor bug, see notes in GetElementCenterPointExpression() - // winrt::Windows::UI::Composition::ExpressionAnimation + // comp::ExpressionAnimation // m_elementCenterPointExpression{nullptr}; - winrt::Windows::UI::Composition::ExpressionAnimation m_transformCenteringExpression{nullptr}; + comp::ExpressionAnimation m_transformCenteringExpression{nullptr}; }; } // namespace uwp diff --git a/vnext/ReactUWP/Views/FlyoutViewManager.cpp b/vnext/ReactUWP/Views/FlyoutViewManager.cpp index 6d38e26f655..0f1f1c7560a 100644 --- a/vnext/ReactUWP/Views/FlyoutViewManager.cpp +++ b/vnext/ReactUWP/Views/FlyoutViewManager.cpp @@ -11,12 +11,11 @@ #include #include #include -#include namespace winrt { -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Xaml::Interop; +using namespace xaml::Controls; +using namespace xaml::Controls::Primitives; +using namespace xaml::Interop; } // namespace winrt static const std::unordered_map placementModeMinVersion = { @@ -91,7 +90,7 @@ class FlyoutShadowNode : public ShadowNodeBase { winrt::Popup GetFlyoutParentPopup() const; winrt::FlyoutPresenter GetFlyoutPresenter() const; - winrt::FrameworkElement m_targetElement = nullptr; + xaml::FrameworkElement m_targetElement = nullptr; winrt::Flyout m_flyout = nullptr; bool m_isLightDismissEnabled = true; bool m_isOpen = false; @@ -121,7 +120,7 @@ void FlyoutShadowNode::AddView(ShadowNode &child, int64_t /*index*/) { m_previewKeyboardEventHandlerOnRoot->hook(childView); if (m_flyout != nullptr) { - m_flyout.Content(childView.as()); + m_flyout.Content(childView.as()); if (winrt::FlyoutPlacementMode::Full == m_flyout.Placement()) { // When using FlyoutPlacementMode::Full on a Flyout with an embedded // Picker, the flyout is not centered correctly. Below is a temporary @@ -129,7 +128,7 @@ void FlyoutShadowNode::AddView(ShadowNode &child, int64_t /*index*/) { // content by adjusting the flyout presenter max size settings prior to // layout. This will unblock those scenarios while the work on a more // exhaustive fix proceeds. Tracked by Issue #2969 - if (auto fe = m_flyout.Content().try_as()) { + if (auto fe = m_flyout.Content().try_as()) { AdjustDefaultFlyoutStyle((float)fe.Width(), (float)fe.Height()); } } @@ -165,7 +164,7 @@ void FlyoutShadowNode::createView() { // its anchor element to prevent cases where focus can land on // an outer flyout content and therefore trigger a unexpected flyout // dismissal - winrt::FocusManager::TryFocusAsync(m_targetElement, winrt::FocusState::Programmatic); + xaml::Input::FocusManager::TryFocusAsync(m_targetElement, winrt::FocusState::Programmatic); } OnFlyoutClosed(*instance, m_tag, false); @@ -191,7 +190,7 @@ void FlyoutShadowNode::createView() { // z-index translation based on an elevation derived from the count // of open popups/flyouts. We apply this translation on open of the // flyout. (Translation is only supported on RS5+, eg. IUIElement9) - if (auto uiElement9 = GetView().try_as()) { + if (auto uiElement9 = GetView().try_as()) { auto numOpenPopups = CountOpenPopups(); if (numOpenPopups > 0) { winrt::Numerics::float3 translation{0, 0, (float)16 * numOpenPopups}; @@ -210,10 +209,10 @@ void FlyoutShadowNode::createView() { // expected, AllowFocusOnInteraction is turned on the content element when // the Content property is updated. m_tokenContentPropertyChangeCallback = m_flyout.RegisterPropertyChangedCallback( - winrt::Flyout::ContentProperty(), [=](winrt::DependencyObject sender, winrt::DependencyProperty dp) { + winrt::Flyout::ContentProperty(), [=](xaml::DependencyObject sender, xaml::DependencyProperty dp) { if (auto flyout = sender.try_as()) { if (auto content = flyout.Content()) { - if (auto fe = content.try_as()) { + if (auto fe = content.try_as()) { fe.AllowFocusOnInteraction(true); } } @@ -361,24 +360,24 @@ void FlyoutShadowNode::SetTargetFrameworkElement() { if (pShadowNodeChild != nullptr) { auto targetView = pShadowNodeChild->GetView(); - m_targetElement = targetView.as(); + m_targetElement = targetView.as(); } } else { - m_targetElement = winrt::Window::Current().Content().as(); + m_targetElement = xaml::Window::Current().Content().as(); } } void FlyoutShadowNode::AdjustDefaultFlyoutStyle(float maxWidth, float maxHeight) { - winrt::Style flyoutStyle({L"Windows.UI.Xaml.Controls.FlyoutPresenter", winrt::TypeKind::Metadata}); - flyoutStyle.Setters().Append(winrt::Setter(winrt::FrameworkElement::MaxWidthProperty(), winrt::box_value(maxWidth))); + winrt::Style flyoutStyle({XAML_NAMESPACE_STR L".Controls.FlyoutPresenter", winrt::TypeKind::Metadata}); + flyoutStyle.Setters().Append(winrt::Setter(xaml::FrameworkElement::MaxWidthProperty(), winrt::box_value(maxWidth))); + flyoutStyle.Setters().Append(winrt::Setter(xaml::FrameworkElement::MaxHeightProperty(), winrt::box_value(maxHeight))); + flyoutStyle.Setters().Append(winrt::Setter(xaml::Controls::Control::PaddingProperty(), winrt::box_value(0))); + flyoutStyle.Setters().Append(winrt::Setter(xaml::Controls::Control::BorderThicknessProperty(), winrt::box_value(0))); flyoutStyle.Setters().Append( - winrt::Setter(winrt::FrameworkElement::MaxHeightProperty(), winrt::box_value(maxHeight))); - flyoutStyle.Setters().Append(winrt::Setter(winrt::Control::PaddingProperty(), winrt::box_value(0))); - flyoutStyle.Setters().Append(winrt::Setter(winrt::Control::BorderThicknessProperty(), winrt::box_value(0))); - flyoutStyle.Setters().Append( - winrt::Setter(winrt::FrameworkElement::AllowFocusOnInteractionProperty(), winrt::box_value(false))); + winrt::Setter(xaml::FrameworkElement::AllowFocusOnInteractionProperty(), winrt::box_value(false))); flyoutStyle.Setters().Append(winrt::Setter( - winrt::Control::BackgroundProperty(), winrt::box_value(winrt::SolidColorBrush{winrt::Colors::Transparent()}))); + xaml::Controls::Control::BackgroundProperty(), + winrt::box_value(xaml::Media::SolidColorBrush{winrt::Colors::Transparent()}))); m_flyout.FlyoutPresenterStyle(flyoutStyle); } @@ -386,7 +385,7 @@ winrt::Popup FlyoutShadowNode::GetFlyoutParentPopup() const { // TODO: Use VisualTreeHelper::GetOpenPopupsFromXamlRoot when running against // RS6 winrt::Windows::Foundation::Collections::IVectorView popups = - winrt::VisualTreeHelper::GetOpenPopups(winrt::Window::Current()); + winrt::VisualTreeHelper::GetOpenPopups(xaml::Window::Current()); if (popups.Size() > 0) return popups.GetAt(0); return nullptr; diff --git a/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp b/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp index 5b2a2700db2..0e9802f7c43 100644 --- a/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp +++ b/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp @@ -15,11 +15,6 @@ #include #include #include -#include -#include -#include -#include -#include #include "Utils/PropertyHandlerUtils.h" @@ -28,10 +23,10 @@ #include namespace winrt { -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Automation; -using namespace Windows::UI::Xaml::Automation::Peers; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Automation; +using namespace xaml::Automation::Peers; using namespace Windows::Foundation::Collections; } // namespace winrt @@ -77,15 +72,15 @@ FrameworkElementViewManager::FrameworkElementViewManager(const std::shared_ptr(); - if (oldElement && oldElement.try_as()) { + auto oldElement = oldView.try_as(); + if (oldElement && oldElement.try_as()) { oldElement.TransformMatrix(winrt::Windows::Foundation::Numerics::float4x4::identity()); } } @@ -165,7 +160,7 @@ bool FrameworkElementViewManager::UpdateProperty( ShadowNodeBase *nodeToUpdate, const std::string &propertyName, const folly::dynamic &propertyValue) { - auto element(nodeToUpdate->GetView().as()); + auto element(nodeToUpdate->GetView().as()); if (element != nullptr) { if (propertyName == "opacity") { if (propertyValue.isNumber()) { @@ -175,10 +170,10 @@ bool FrameworkElementViewManager::UpdateProperty( // else // TODO report error } else if (propertyValue.isNull()) { - element.ClearValue(winrt::UIElement::OpacityProperty()); + element.ClearValue(xaml::UIElement::OpacityProperty()); } } else if (propertyName == "transform") { - if (element.try_as()) // Works on 19H1+ + if (element.try_as()) // Works on 19H1+ { if (propertyValue.isArray()) { assert(propertyValue.size() == 16); @@ -213,7 +208,7 @@ bool FrameworkElementViewManager::UpdateProperty( // else // TODO report error } else if (propertyValue.isNull()) { - element.ClearValue(winrt::FrameworkElement::WidthProperty()); + element.ClearValue(xaml::FrameworkElement::WidthProperty()); } } else if (propertyName == "height") { @@ -224,7 +219,7 @@ bool FrameworkElementViewManager::UpdateProperty( // else // TODO report error } else if (propertyValue.isNull()) { - element.ClearValue(winrt::FrameworkElement::HeightProperty()); + element.ClearValue(xaml::FrameworkElement::HeightProperty()); } } else if (propertyName == "minWidth") { if (propertyValue.isNumber()) { @@ -234,7 +229,7 @@ bool FrameworkElementViewManager::UpdateProperty( // else // TODO report error } else if (propertyValue.isNull()) { - element.ClearValue(winrt::FrameworkElement::MinWidthProperty()); + element.ClearValue(xaml::FrameworkElement::MinWidthProperty()); } } else if (propertyName == "maxWidth") { if (propertyValue.isNumber()) { @@ -244,7 +239,7 @@ bool FrameworkElementViewManager::UpdateProperty( // else // TODO report error } else if (propertyValue.isNull()) { - element.ClearValue(winrt::FrameworkElement::MaxWidthProperty()); + element.ClearValue(xaml::FrameworkElement::MaxWidthProperty()); } } else if (propertyName == "minHeight") { @@ -255,7 +250,7 @@ bool FrameworkElementViewManager::UpdateProperty( // else // TODO report error } else if (propertyValue.isNull()) { - element.ClearValue(winrt::FrameworkElement::MinHeightProperty()); + element.ClearValue(xaml::FrameworkElement::MinHeightProperty()); } } else if (propertyName == "maxHeight") { if (propertyValue.isNumber()) { @@ -265,7 +260,7 @@ bool FrameworkElementViewManager::UpdateProperty( // else // TODO report error } else if (propertyValue.isNull()) { - element.ClearValue(winrt::FrameworkElement::MaxHeightProperty()); + element.ClearValue(xaml::FrameworkElement::MaxHeightProperty()); } } else if (propertyName == "accessibilityHint") { @@ -273,24 +268,24 @@ bool FrameworkElementViewManager::UpdateProperty( auto value = react::uwp::asHstring(propertyValue); auto boxedValue = winrt::Windows::Foundation::PropertyValue::CreateString(value); - element.SetValue(winrt::AutomationProperties::HelpTextProperty(), boxedValue); + element.SetValue(xaml::Automation::AutomationProperties::HelpTextProperty(), boxedValue); } else if (propertyValue.isNull()) { - element.ClearValue(winrt::AutomationProperties::HelpTextProperty()); + element.ClearValue(xaml::Automation::AutomationProperties::HelpTextProperty()); } } else if (propertyName == "accessibilityLabel") { if (propertyValue.isString()) { auto value = react::uwp::asHstring(propertyValue); auto boxedValue = winrt::Windows::Foundation::PropertyValue::CreateString(value); - element.SetValue(winrt::AutomationProperties::NameProperty(), boxedValue); + element.SetValue(xaml::Automation::AutomationProperties::NameProperty(), boxedValue); } else if (propertyValue.isNull()) { - element.ClearValue(winrt::AutomationProperties::NameProperty()); + element.ClearValue(xaml::Automation::AutomationProperties::NameProperty()); } AnnounceLiveRegionChangedIfNeeded(element); } else if (propertyName == "accessible") { if (propertyValue.isBool()) { if (!propertyValue.asBool()) - winrt::AutomationProperties::SetAccessibilityView(element, winrt::Peers::AccessibilityView::Raw); + xaml::Automation::AutomationProperties::SetAccessibilityView(element, winrt::Peers::AccessibilityView::Raw); } } else if (propertyName == "accessibilityLiveRegion") { if (propertyValue.isString()) { @@ -304,9 +299,9 @@ bool FrameworkElementViewManager::UpdateProperty( liveSetting = winrt::AutomationLiveSetting::Assertive; } - element.SetValue(winrt::AutomationProperties::LiveSettingProperty(), winrt::box_value(liveSetting)); + element.SetValue(xaml::Automation::AutomationProperties::LiveSettingProperty(), winrt::box_value(liveSetting)); } else if (propertyValue.isNull()) { - element.ClearValue(winrt::AutomationProperties::LiveSettingProperty()); + element.ClearValue(xaml::Automation::AutomationProperties::LiveSettingProperty()); } AnnounceLiveRegionChangedIfNeeded(element); } else if (propertyName == "accessibilityPosInSet") { @@ -314,18 +309,18 @@ bool FrameworkElementViewManager::UpdateProperty( auto value = static_cast(propertyValue.asDouble()); auto boxedValue = winrt::Windows::Foundation::PropertyValue::CreateInt32(value); - element.SetValue(winrt::AutomationProperties::PositionInSetProperty(), boxedValue); + element.SetValue(xaml::Automation::AutomationProperties::PositionInSetProperty(), boxedValue); } else if (propertyValue.isNull()) { - element.ClearValue(winrt::AutomationProperties::PositionInSetProperty()); + element.ClearValue(xaml::Automation::AutomationProperties::PositionInSetProperty()); } } else if (propertyName == "accessibilitySetSize") { if (propertyValue.isNumber()) { auto value = static_cast(propertyValue.asDouble()); auto boxedValue = winrt::Windows::Foundation::PropertyValue::CreateInt32(value); - element.SetValue(winrt::AutomationProperties::SizeOfSetProperty(), boxedValue); + element.SetValue(xaml::Automation::AutomationProperties::SizeOfSetProperty(), boxedValue); } else if (propertyValue.isNull()) { - element.ClearValue(winrt::AutomationProperties::SizeOfSetProperty()); + element.ClearValue(xaml::Automation::AutomationProperties::SizeOfSetProperty()); } } else if (propertyName == "accessibilityRole") { if (propertyValue.isString()) { @@ -444,9 +439,9 @@ bool FrameworkElementViewManager::UpdateProperty( auto value = react::uwp::asHstring(propertyValue); auto boxedValue = winrt::Windows::Foundation::PropertyValue::CreateString(value); - element.SetValue(winrt::AutomationProperties::AutomationIdProperty(), boxedValue); + element.SetValue(xaml::Automation::AutomationProperties::AutomationIdProperty(), boxedValue); } else if (propertyValue.isNull()) { - element.ClearValue(winrt::AutomationProperties::AutomationIdProperty()); + element.ClearValue(xaml::Automation::AutomationProperties::AutomationIdProperty()); } } else if (propertyName == "tooltip") { if (propertyValue.isString()) { @@ -489,7 +484,7 @@ bool FrameworkElementViewManager::UpdateProperty( // pick up the new value. // 3) Create an ExpressionAnimation to multiply everything together. void FrameworkElementViewManager::ApplyTransformMatrix( - winrt::UIElement uielement, + xaml::UIElement uielement, ShadowNodeBase *shadowNode, winrt::Windows::Foundation::Numerics::float4x4 transformMatrix) { // Get our PropertySet from the ShadowNode and insert the TransformMatrix as @@ -504,8 +499,8 @@ void FrameworkElementViewManager::ApplyTransformMatrix( // Starts ExpressionAnimation targeting UIElement.TransformMatrix with centered // transform void FrameworkElementViewManager::StartTransformAnimation( - winrt::UIElement uielement, - winrt::Windows::UI::Composition::CompositionPropertySet transformPS) { + xaml::UIElement uielement, + comp::CompositionPropertySet transformPS) { auto instance = GetReactInstance().lock(); assert(instance != nullptr); auto expression = instance->GetExpressionAnimationStore().GetTransformCenteringExpression(); @@ -520,7 +515,7 @@ void FrameworkElementViewManager::RefreshTransformMatrix(ShadowNodeBase *shadowN // First we need to update the reference parameter on the centering // expression to point to the new backing UIElement. shadowNode->UpdateTransformPS(); - auto uielement = shadowNode->GetView().try_as(); + auto uielement = shadowNode->GetView().try_as(); assert(uielement != nullptr); // Start a new ExpressionAnimation targeting the new diff --git a/vnext/ReactUWP/Views/Image/ImageViewManager.cpp b/vnext/ReactUWP/Views/Image/ImageViewManager.cpp index a0571d5b94b..993162dc1de 100644 --- a/vnext/ReactUWP/Views/Image/ImageViewManager.cpp +++ b/vnext/ReactUWP/Views/Image/ImageViewManager.cpp @@ -9,7 +9,6 @@ #include "ImageViewManager.h" #include -#include #include #include @@ -19,7 +18,7 @@ namespace winrt { using namespace Windows::Foundation; -using namespace Windows::UI::Xaml::Controls; +using namespace xaml::Controls; } // namespace winrt // Such code is better to move to a seperate parser layer diff --git a/vnext/ReactUWP/Views/Image/ImageViewManager.h b/vnext/ReactUWP/Views/Image/ImageViewManager.h index 88f49a1adf4..95e222290e2 100644 --- a/vnext/ReactUWP/Views/Image/ImageViewManager.h +++ b/vnext/ReactUWP/Views/Image/ImageViewManager.h @@ -18,7 +18,7 @@ class ImageViewManager : public FrameworkElementViewManager { folly::dynamic GetExportedCustomDirectEventTypeConstants() const override; folly::dynamic GetNativeProps() const override; facebook::react::ShadowNode *createShadow() const override; - void EmitImageEvent(winrt::Windows::UI::Xaml::Controls::Grid grid, const char *eventName, ReactImageSource &source); + void EmitImageEvent(xaml::Controls::Grid grid, const char *eventName, ReactImageSource &source); protected: bool UpdateProperty( @@ -29,7 +29,7 @@ class ImageViewManager : public FrameworkElementViewManager { XamlView CreateViewCore(int64_t tag) override; private: - void setSource(winrt::Windows::UI::Xaml::Controls::Grid grid, const folly::dynamic &sources); + void setSource(xaml::Controls::Grid grid, const folly::dynamic &sources); }; } // namespace uwp } // namespace react diff --git a/vnext/ReactUWP/Views/Image/ReactImage.cpp b/vnext/ReactUWP/Views/Image/ReactImage.cpp index ee00397e9e9..b8ac25c6780 100644 --- a/vnext/ReactUWP/Views/Image/ReactImage.cpp +++ b/vnext/ReactUWP/Views/Image/ReactImage.cpp @@ -15,9 +15,9 @@ namespace winrt { using namespace Windows::Foundation; using namespace Windows::Storage::Streams; using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Media; -using namespace Windows::UI::Xaml::Media::Imaging; +using namespace xaml; +using namespace xaml::Media; +using namespace xaml::Media::Imaging; using namespace Windows::Web::Http; } // namespace winrt @@ -35,7 +35,7 @@ namespace uwp { auto reactImage = winrt::make_self(); // Grid inheirts the layout direction from parent and mirrors the background image in RTL mode. // Forcing the container to LTR mode to avoid the unexpected mirroring behavior. - reactImage->FlowDirection(winrt::FlowDirection::LeftToRight); + reactImage->FlowDirection(xaml::FlowDirection::LeftToRight); return reactImage; } diff --git a/vnext/ReactUWP/Views/Image/ReactImage.h b/vnext/ReactUWP/Views/Image/ReactImage.h index a27b910177b..4a8ac619460 100644 --- a/vnext/ReactUWP/Views/Image/ReactImage.h +++ b/vnext/ReactUWP/Views/Image/ReactImage.h @@ -7,10 +7,6 @@ #include #include -#include -#include -#include -#include #include @@ -31,8 +27,8 @@ struct ReactImageSource { ImageSourceType sourceType = ImageSourceType::Uri; }; -struct ReactImage : winrt::Windows::UI::Xaml::Controls::GridT { - using Super = winrt::Windows::UI::Xaml::Controls::GridT; +struct ReactImage : xaml::Controls::GridT { + using Super = xaml::Controls::GridT; ReactImage() = default; @@ -58,7 +54,7 @@ struct ReactImage : winrt::Windows::UI::Xaml::Controls::GridT { void ResizeMode(react::uwp::ResizeMode value); private: - winrt::Windows::UI::Xaml::Media::Stretch ResizeModeToStretch(react::uwp::ResizeMode value); + xaml::Media::Stretch ResizeModeToStretch(react::uwp::ResizeMode value); winrt::Windows::Foundation::IAsyncOperation GetImageMemoryStreamAsync(ReactImageSource source); winrt::fire_and_forget SetBackground(bool fireLoadEndEvent); @@ -68,13 +64,13 @@ struct ReactImage : winrt::Windows::UI::Xaml::Controls::GridT { react::uwp::ResizeMode m_resizeMode{ResizeMode::Contain}; winrt::event> m_onLoadEndEvent; - winrt::Windows::UI::Xaml::FrameworkElement::SizeChanged_revoker m_sizeChangedRevoker; - winrt::Windows::UI::Xaml::Media::LoadedImageSurface::LoadCompleted_revoker m_surfaceLoadedRevoker; - winrt::Windows::UI::Xaml::Media::Imaging::BitmapImage::ImageOpened_revoker m_bitmapImageOpened; - winrt::Windows::UI::Xaml::Media::ImageBrush::ImageOpened_revoker m_imageBrushOpenedRevoker; - winrt::Windows::UI::Xaml::Media::ImageBrush::ImageFailed_revoker m_imageBrushFailedRevoker; - winrt::Windows::UI::Xaml::Media::Imaging::SvgImageSource::Opened_revoker m_svgImageSourceOpenedRevoker; - winrt::Windows::UI::Xaml::Media::Imaging::SvgImageSource::OpenFailed_revoker m_svgImageSourceOpenFailedRevoker; + xaml::FrameworkElement::SizeChanged_revoker m_sizeChangedRevoker; + xaml::Media::LoadedImageSurface::LoadCompleted_revoker m_surfaceLoadedRevoker; + xaml::Media::Imaging::BitmapImage::ImageOpened_revoker m_bitmapImageOpened; + xaml::Media::ImageBrush::ImageOpened_revoker m_imageBrushOpenedRevoker; + xaml::Media::ImageBrush::ImageFailed_revoker m_imageBrushFailedRevoker; + xaml::Media::Imaging::SvgImageSource::Opened_revoker m_svgImageSourceOpenedRevoker; + xaml::Media::Imaging::SvgImageSource::OpenFailed_revoker m_svgImageSourceOpenFailedRevoker; }; // Helper functions diff --git a/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp b/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp index 4a59db48ac1..61f1263ca81 100644 --- a/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp +++ b/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp @@ -7,15 +7,13 @@ #include -#include - #include "BorderEffect.h" namespace winrt { using namespace winrt::Windows::Storage::Streams; -using namespace winrt::Windows::UI::Composition; -using namespace winrt::Windows::UI::Xaml; -using namespace winrt::Windows::UI::Xaml::Media; +using namespace comp; +using namespace xaml; +using namespace xaml::Media; } // namespace winrt namespace react { @@ -56,7 +54,7 @@ void ReactImageBrush::Source(winrt::LoadedImageSurface const &value) { m_loadedImageSurface = value; if (updateSurface) { - winrt::CompositionSurfaceBrush surfaceBrush{GetOrCreateSurfaceBrush()}; + comp::CompositionSurfaceBrush surfaceBrush{GetOrCreateSurfaceBrush()}; surfaceBrush.Surface(m_loadedImageSurface); } @@ -66,10 +64,10 @@ void ReactImageBrush::Source(winrt::LoadedImageSurface const &value) { void ReactImageBrush::UpdateCompositionBrush() { if (m_loadedImageSurface) { - winrt::CompositionSurfaceBrush surfaceBrush{GetOrCreateSurfaceBrush()}; + comp::CompositionSurfaceBrush surfaceBrush{GetOrCreateSurfaceBrush()}; surfaceBrush.Stretch(ResizeModeToStretch()); - auto compositionBrush{surfaceBrush.as()}; + auto compositionBrush{surfaceBrush.as()}; if (ResizeMode() == ResizeMode::Repeat) { // If ResizeMode is set to Repeat, then we need to use a CompositionEffectBrush. // The CompositionSurfaceBrush holding the image is used as its source. @@ -103,66 +101,66 @@ bool ReactImageBrush::IsImageSmallerThanView() { return false; } -winrt::CompositionStretch ReactImageBrush::ResizeModeToStretch() { - auto stretch{winrt::CompositionStretch::None}; +comp::CompositionStretch ReactImageBrush::ResizeModeToStretch() { + auto stretch{comp::CompositionStretch::None}; switch (ResizeMode()) { case ResizeMode::Contain: - stretch = winrt::CompositionStretch::Uniform; + stretch = comp::CompositionStretch::Uniform; break; case ResizeMode::Cover: - stretch = winrt::CompositionStretch::UniformToFill; + stretch = comp::CompositionStretch::UniformToFill; break; case ResizeMode::Stretch: - stretch = winrt::CompositionStretch::Fill; + stretch = comp::CompositionStretch::Fill; break; case ResizeMode::Center: case ResizeMode::Repeat: - stretch = IsImageSmallerThanView() ? winrt::CompositionStretch::None : winrt::CompositionStretch::Uniform; + stretch = IsImageSmallerThanView() ? comp::CompositionStretch::None : comp::CompositionStretch::Uniform; break; } return stretch; } -winrt::CompositionSurfaceBrush ReactImageBrush::GetOrCreateSurfaceBrush() { +comp::CompositionSurfaceBrush ReactImageBrush::GetOrCreateSurfaceBrush() { // If it doesn't exist, create it if (!CompositionBrush()) { - winrt::CompositionSurfaceBrush surfaceBrush{winrt::Window::Current().Compositor().CreateSurfaceBrush()}; + comp::CompositionSurfaceBrush surfaceBrush{xaml::Window::Current().Compositor().CreateSurfaceBrush()}; surfaceBrush.Surface(m_loadedImageSurface); return surfaceBrush; } - auto surfaceBrush{CompositionBrush().try_as()}; + auto surfaceBrush{CompositionBrush().try_as()}; // If ResizeMode is set to Repeat, then we're using a CompositionEffectBrush. // Get the CompositionSurfaceBrush from its source. if (!surfaceBrush) { - auto effectBrush{CompositionBrush().as()}; + auto effectBrush{CompositionBrush().as()}; assert(effectBrush); - surfaceBrush = effectBrush.GetSourceParameter(L"source").as(); + surfaceBrush = effectBrush.GetSourceParameter(L"source").as(); } return surfaceBrush; } -winrt::CompositionEffectBrush ReactImageBrush::GetOrCreateEffectBrush( - winrt::CompositionSurfaceBrush const &surfaceBrush) { +comp::CompositionEffectBrush ReactImageBrush::GetOrCreateEffectBrush( + comp::CompositionSurfaceBrush const &surfaceBrush) { if (!m_effectBrush) { auto borderEffect{winrt::make()}; borderEffect.ExtendX(winrt::CanvasEdgeBehavior::Wrap); borderEffect.ExtendY(winrt::CanvasEdgeBehavior::Wrap); - winrt::CompositionEffectSourceParameter borderEffectSourceParameter{L"source"}; + comp::CompositionEffectSourceParameter borderEffectSourceParameter{L"source"}; borderEffect.Source(borderEffectSourceParameter); - winrt::CompositionEffectFactory effectFactory{ - winrt::Window::Current().Compositor().CreateEffectFactory(borderEffect)}; + comp::CompositionEffectFactory effectFactory{ + xaml::Window::Current().Compositor().CreateEffectFactory(borderEffect)}; m_effectBrush = effectFactory.CreateBrush(); m_effectBrush.SetSourceParameter(L"source", surfaceBrush); diff --git a/vnext/ReactUWP/Views/Image/ReactImageBrush.h b/vnext/ReactUWP/Views/Image/ReactImageBrush.h index 8bc3b98bc51..8f93b1c5620 100644 --- a/vnext/ReactUWP/Views/Image/ReactImageBrush.h +++ b/vnext/ReactUWP/Views/Image/ReactImageBrush.h @@ -4,16 +4,14 @@ #pragma once #include -#include -#include namespace react { namespace uwp { enum class ResizeMode { Cover = 0, Contain = 1, Stretch = 2, Repeat = 3, Center = 4 }; -struct ReactImageBrush : winrt::Windows::UI::Xaml::Media::XamlCompositionBrushBaseT { - using Super = winrt::Windows::UI::Xaml::Media::XamlCompositionBrushBaseT; +struct ReactImageBrush : xaml::Media::XamlCompositionBrushBaseT { + using Super = xaml::Media::XamlCompositionBrushBaseT; ReactImageBrush() = default; @@ -35,20 +33,19 @@ struct ReactImageBrush : winrt::Windows::UI::Xaml::Media::XamlCompositionBrushBa } void AvailableSize(winrt::Windows::Foundation::Size const &value); - void Source(winrt::Windows::UI::Xaml::Media::LoadedImageSurface const &value); + void Source(xaml::Media::LoadedImageSurface const &value); private: void UpdateCompositionBrush(); bool IsImageSmallerThanView(); - winrt::Windows::UI::Composition::CompositionStretch ResizeModeToStretch(); - winrt::Windows::UI::Composition::CompositionSurfaceBrush GetOrCreateSurfaceBrush(); - winrt::Windows::UI::Composition::CompositionEffectBrush GetOrCreateEffectBrush( - winrt::Windows::UI::Composition::CompositionSurfaceBrush const &surfaceBrush); + comp::CompositionStretch ResizeModeToStretch(); + comp::CompositionSurfaceBrush GetOrCreateSurfaceBrush(); + comp::CompositionEffectBrush GetOrCreateEffectBrush(comp::CompositionSurfaceBrush const &surfaceBrush); react::uwp::ResizeMode m_resizeMode{ResizeMode::Contain}; winrt::Windows::Foundation::Size m_availableSize{}; - winrt::Windows::UI::Xaml::Media::LoadedImageSurface m_loadedImageSurface{nullptr}; - winrt::Windows::UI::Composition::CompositionEffectBrush m_effectBrush{nullptr}; + xaml::Media::LoadedImageSurface m_loadedImageSurface{nullptr}; + comp::CompositionEffectBrush m_effectBrush{nullptr}; }; } // namespace uwp } // namespace react diff --git a/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.cpp b/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.cpp index 1e05c2d7e94..40ea7ed5459 100644 --- a/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.cpp +++ b/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.cpp @@ -53,7 +53,7 @@ void ScrollViewUWPImplementation::UpdateScrollableSize() const { const auto zoomFactor = scrollViewer.ZoomFactor(); const auto scaledViewportWidth = static_cast(scrollViewer.ViewportWidth() / zoomFactor); const auto scaledviewportHeight = static_cast(scrollViewer.ViewportHeight() / zoomFactor); - const auto scrollViewContent = scrollViewer.Content().as(); + const auto scrollViewContent = scrollViewer.Content().as(); const auto contentWidth = scrollViewContent.ActualWidth(); const auto contentHeight = scrollViewContent.ActualHeight(); diff --git a/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.h b/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.h index 82cb5203e4c..385101f457d 100644 --- a/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.h +++ b/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.h @@ -9,14 +9,13 @@ #include #include -#include namespace winrt { using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Controls::Primitives; } // namespace winrt namespace react { diff --git a/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.cpp b/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.cpp index fe5beaf6c52..2840ed03695 100644 --- a/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.cpp +++ b/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.cpp @@ -79,7 +79,7 @@ void SnapPointManagingContentControl::VerticalSnapPointsChanged(winrt::event_tok } winrt::IVectorView SnapPointManagingContentControl::GetIrregularSnapPoints( - winrt::Orientation /*orientation*/, + xaml::Controls::Orientation /*orientation*/, winrt::SnapPointsAlignment /*alignment*/) { const auto retVal = winrt::single_threaded_vector(); @@ -99,7 +99,7 @@ winrt::IVectorView SnapPointManagingContentControl::GetIrregularSnapPoint } float SnapPointManagingContentControl::GetRegularSnapPoints( - winrt::Orientation /*orientation*/, + xaml::Controls::Orientation /*orientation*/, winrt::SnapPointsAlignment /*alignment*/, float /*offset*/) { if (m_interval > 0.0f) { diff --git a/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.h b/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.h index 072e6b02658..4bddeb71a48 100644 --- a/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.h +++ b/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.h @@ -2,23 +2,20 @@ #include "winrt/Windows.Foundation.Collections.h" #include "winrt/Windows.Foundation.h" -#include "winrt/Windows.UI.Xaml.Controls.Primitives.h" -#include "winrt/Windows.UI.Xaml.Controls.h" -#include "winrt/Windows.UI.Xaml.h" namespace winrt { using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Controls::Primitives; } // namespace winrt namespace react { namespace uwp { class SnapPointManagingContentControl - : public winrt::ContentControlT { + : public xaml::Controls::ContentControlT { public: SnapPointManagingContentControl(); @@ -43,10 +40,11 @@ class SnapPointManagingContentControl void VerticalSnapPointsChanged(winrt::event_token const &token); winrt::IVectorView GetIrregularSnapPoints( - winrt::Orientation orientation, + xaml::Controls::Orientation orientation, winrt::SnapPointsAlignment alignment); - float GetRegularSnapPoints(winrt::Orientation orientation, winrt::SnapPointsAlignment alignment, float offset); + float + GetRegularSnapPoints(xaml::Controls::Orientation orientation, winrt::SnapPointsAlignment alignment, float offset); // Helpers void SetHorizontal(bool horizontal); diff --git a/vnext/ReactUWP/Views/KeyboardEventHandler.cpp b/vnext/ReactUWP/Views/KeyboardEventHandler.cpp index 56ba0caaf8a..c3a9a70fd91 100644 --- a/vnext/ReactUWP/Views/KeyboardEventHandler.cpp +++ b/vnext/ReactUWP/Views/KeyboardEventHandler.cpp @@ -3,6 +3,7 @@ #include "pch.h" +#include #include #include "Utils/Helpers.h" #include "Utils/PropertyHandlerUtils.h" @@ -67,8 +68,8 @@ PreviewKeyboardEventHandler::PreviewKeyboardEventHandler(KeyboardEventCallback & : KeyboardEventBaseHandler(std::move(keyDown), std::move(keyUp)) {} void PreviewKeyboardEventHandler::hook(XamlView xamlView) { - auto uiElement = xamlView.as(); - if (uiElement.try_as()) { + auto uiElement = xamlView.as(); + if (uiElement.try_as()) { if (m_keyDownCallback) m_previewKeyDownRevoker = uiElement.PreviewKeyDown(winrt::auto_revoke, m_keyDownCallback); @@ -86,7 +87,7 @@ KeyboardEventHandler::KeyboardEventHandler(KeyboardEventCallback &&keyDown, Keyb : KeyboardEventBaseHandler(std::move(keyDown), std::move(keyUp)) {} void KeyboardEventHandler::hook(XamlView xamlView) { - auto uiElement = xamlView.as(); + auto uiElement = xamlView.as(); if (m_keyDownCallback) m_keyDownRevoker = uiElement.KeyDown(winrt::auto_revoke, m_keyDownCallback); @@ -107,13 +108,13 @@ PreviewKeyboardEventHandlerOnRoot::PreviewKeyboardEventHandlerOnRoot(const std:: void PreviewKeyboardEventHandlerOnRoot::OnPreKeyDown( winrt::IInspectable const & /*sender*/, - winrt::KeyRoutedEventArgs const &args) { + xaml::Input::KeyRoutedEventArgs const &args) { DispatchEventToJs("topKeyDown", args); } void PreviewKeyboardEventHandlerOnRoot::OnPreKeyUp( winrt::IInspectable const & /*sender*/, - winrt::KeyRoutedEventArgs const &args) { + xaml::Input::KeyRoutedEventArgs const &args) { DispatchEventToJs("topKeyUp", args); } @@ -166,7 +167,7 @@ void HandledKeyboardEventHandler::EnsureKeyboardEventHandler() { void HandledKeyboardEventHandler::KeyboardEventHandledHandler( KeyboardEventPhase phase, winrt::IInspectable const & /*sender*/, - winrt::KeyRoutedEventArgs const &args) { + xaml::Input::KeyRoutedEventArgs const &args) { HandledEventPhase currentEventPhase = (phase == KeyboardEventPhase::PreviewKeyUp || phase == KeyboardEventPhase::PreviewKeyDown) ? HandledEventPhase::Capturing @@ -199,19 +200,19 @@ bool HandledKeyboardEventHandler::ShouldMarkKeyboardHandled( template void UpdateModifiedKeyStatusTo(T &event) { auto const &coreWindow = winrt::CoreWindow::GetForCurrentThread(); - event.altKey = KeyboardHelper::IsModifiedKeyPressed(coreWindow, winrt::VirtualKey::Menu); - event.shiftKey = KeyboardHelper::IsModifiedKeyPressed(coreWindow, winrt::VirtualKey::Shift); - event.metaKey = KeyboardHelper::IsModifiedKeyPressed(coreWindow, winrt::VirtualKey::LeftWindows) || - KeyboardHelper::IsModifiedKeyPressed(coreWindow, winrt::VirtualKey::RightWindows); - event.ctrlKey = KeyboardHelper::IsModifiedKeyPressed(coreWindow, winrt::VirtualKey::Control); - event.capLocked = KeyboardHelper::IsModifiedKeyLocked(coreWindow, winrt::VirtualKey::CapitalLock); + event.altKey = KeyboardHelper::IsModifiedKeyPressed(coreWindow, winrt::Windows::System::VirtualKey::Menu); + event.shiftKey = KeyboardHelper::IsModifiedKeyPressed(coreWindow, winrt::Windows::System::VirtualKey::Shift); + event.metaKey = KeyboardHelper::IsModifiedKeyPressed(coreWindow, winrt::Windows::System::VirtualKey::LeftWindows) || + KeyboardHelper::IsModifiedKeyPressed(coreWindow, winrt::Windows::System::VirtualKey::RightWindows); + event.ctrlKey = KeyboardHelper::IsModifiedKeyPressed(coreWindow, winrt::Windows::System::VirtualKey::Control); + event.capLocked = KeyboardHelper::IsModifiedKeyLocked(coreWindow, winrt::Windows::System::VirtualKey::CapitalLock); }; void PreviewKeyboardEventHandlerOnRoot::DispatchEventToJs( std::string const &eventName, - winrt::KeyRoutedEventArgs const &args) { + xaml::Input::KeyRoutedEventArgs const &args) { if (auto instance = m_wkReactInstance.lock()) { - if (auto source = args.OriginalSource().try_as()) { + if (auto source = args.OriginalSource().try_as()) { auto reactId = getViewId(instance.operator->(), source); if (reactId.isValid) { ReactKeyboardEvent event; @@ -228,7 +229,7 @@ void PreviewKeyboardEventHandlerOnRoot::DispatchEventToJs( HandledKeyboardEvent KeyboardHelper::CreateKeyboardEvent( HandledEventPhase phase, - winrt::KeyRoutedEventArgs const &args) { + xaml::Input::KeyRoutedEventArgs const &args) { HandledKeyboardEvent event; event.handledEventPhase = phase; UpdateModifiedKeyStatusTo(event); @@ -239,112 +240,112 @@ HandledKeyboardEvent KeyboardHelper::CreateKeyboardEvent( // Should align to // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values -static const std::vector> g_virtualKeyToKey{ +static const std::vector> g_virtualKeyToKey{ // Modifier keys - {winrt::VirtualKey::LeftMenu, "Alt"}, - {winrt::VirtualKey::RightMenu, "Alt"}, - {winrt::VirtualKey::Menu, "Alt"}, - {winrt::VirtualKey::CapitalLock, "CapsLock"}, - {winrt::VirtualKey::LeftControl, "Control"}, - {winrt::VirtualKey::RightControl, "Control"}, - {winrt::VirtualKey::Control, "Control"}, - {winrt::VirtualKey::LeftWindows, "Meta"}, - {winrt::VirtualKey::RightWindows, "Meta"}, - {winrt::VirtualKey::NumberKeyLock, "NumLock"}, - {winrt::VirtualKey::Scroll, "ScrollLock"}, - {winrt::VirtualKey::LeftShift, "Shift"}, - {winrt::VirtualKey::RightShift, "Shift"}, - {winrt::VirtualKey::Shift, "Shift"}, + {winrt::Windows::System::VirtualKey::LeftMenu, "Alt"}, + {winrt::Windows::System::VirtualKey::RightMenu, "Alt"}, + {winrt::Windows::System::VirtualKey::Menu, "Alt"}, + {winrt::Windows::System::VirtualKey::CapitalLock, "CapsLock"}, + {winrt::Windows::System::VirtualKey::LeftControl, "Control"}, + {winrt::Windows::System::VirtualKey::RightControl, "Control"}, + {winrt::Windows::System::VirtualKey::Control, "Control"}, + {winrt::Windows::System::VirtualKey::LeftWindows, "Meta"}, + {winrt::Windows::System::VirtualKey::RightWindows, "Meta"}, + {winrt::Windows::System::VirtualKey::NumberKeyLock, "NumLock"}, + {winrt::Windows::System::VirtualKey::Scroll, "ScrollLock"}, + {winrt::Windows::System::VirtualKey::LeftShift, "Shift"}, + {winrt::Windows::System::VirtualKey::RightShift, "Shift"}, + {winrt::Windows::System::VirtualKey::Shift, "Shift"}, // Whitespace keys - {winrt::VirtualKey::Enter, "Enter"}, - {winrt::VirtualKey::Tab, "Tab"}, - {winrt::VirtualKey::Space, " "}, + {winrt::Windows::System::VirtualKey::Enter, "Enter"}, + {winrt::Windows::System::VirtualKey::Tab, "Tab"}, + {winrt::Windows::System::VirtualKey::Space, " "}, // Navigation keys - {winrt::VirtualKey::Down, "ArrowDown"}, - {winrt::VirtualKey::Left, "ArrowLeft"}, - {winrt::VirtualKey::Right, "ArrowRight"}, - {winrt::VirtualKey::Up, "ArrowUp"}, - {winrt::VirtualKey::End, "End"}, - {winrt::VirtualKey::Home, "Home"}, - {winrt::VirtualKey::PageDown, "PageDown"}, - {winrt::VirtualKey::PageUp, "PageUp"}, + {winrt::Windows::System::VirtualKey::Down, "ArrowDown"}, + {winrt::Windows::System::VirtualKey::Left, "ArrowLeft"}, + {winrt::Windows::System::VirtualKey::Right, "ArrowRight"}, + {winrt::Windows::System::VirtualKey::Up, "ArrowUp"}, + {winrt::Windows::System::VirtualKey::End, "End"}, + {winrt::Windows::System::VirtualKey::Home, "Home"}, + {winrt::Windows::System::VirtualKey::PageDown, "PageDown"}, + {winrt::Windows::System::VirtualKey::PageUp, "PageUp"}, // Editing keys - {winrt::VirtualKey::Back, "Backspace"}, - {winrt::VirtualKey::Clear, "Clear"}, - {winrt::VirtualKey::Delete, "Delete"}, - {winrt::VirtualKey::Insert, "Insert"}, + {winrt::Windows::System::VirtualKey::Back, "Backspace"}, + {winrt::Windows::System::VirtualKey::Clear, "Clear"}, + {winrt::Windows::System::VirtualKey::Delete, "Delete"}, + {winrt::Windows::System::VirtualKey::Insert, "Insert"}, // UI keys - {winrt::VirtualKey::Accept, "Accept"}, - {winrt::VirtualKey::Application, "ContextMenu"}, - {winrt::VirtualKey::Escape, "Escape"}, - {winrt::VirtualKey::Execute, "Execute"}, - {winrt::VirtualKey::Help, "Help"}, - {winrt::VirtualKey::Pause, "Pause"}, - {winrt::VirtualKey::Select, "Select"}, + {winrt::Windows::System::VirtualKey::Accept, "Accept"}, + {winrt::Windows::System::VirtualKey::Application, "ContextMenu"}, + {winrt::Windows::System::VirtualKey::Escape, "Escape"}, + {winrt::Windows::System::VirtualKey::Execute, "Execute"}, + {winrt::Windows::System::VirtualKey::Help, "Help"}, + {winrt::Windows::System::VirtualKey::Pause, "Pause"}, + {winrt::Windows::System::VirtualKey::Select, "Select"}, // Device keys - {winrt::VirtualKey::Snapshot, "PrintScreen"}, - {winrt::VirtualKey::Sleep, "Standby"}, + {winrt::Windows::System::VirtualKey::Snapshot, "PrintScreen"}, + {winrt::Windows::System::VirtualKey::Sleep, "Standby"}, // Common IME keys - {winrt::VirtualKey::Convert, "Convert"}, - {winrt::VirtualKey::Final, "FinalMode"}, - {winrt::VirtualKey::ModeChange, "ModeChange"}, - {winrt::VirtualKey::NonConvert, "NonConvert"}, + {winrt::Windows::System::VirtualKey::Convert, "Convert"}, + {winrt::Windows::System::VirtualKey::Final, "FinalMode"}, + {winrt::Windows::System::VirtualKey::ModeChange, "ModeChange"}, + {winrt::Windows::System::VirtualKey::NonConvert, "NonConvert"}, // Korean keyboards only - {winrt::VirtualKey::Hangul, "HangulMode"}, - {winrt::VirtualKey::Hanja, "HanjaMode"}, - {winrt::VirtualKey::Junja, "JunjaMode"}, + {winrt::Windows::System::VirtualKey::Hangul, "HangulMode"}, + {winrt::Windows::System::VirtualKey::Hanja, "HanjaMode"}, + {winrt::Windows::System::VirtualKey::Junja, "JunjaMode"}, // Japanese keyboards only - {winrt::VirtualKey::Kana, "KanaMode"}, - {winrt::VirtualKey::Kanji, "KanjiMode"}, + {winrt::Windows::System::VirtualKey::Kana, "KanaMode"}, + {winrt::Windows::System::VirtualKey::Kanji, "KanjiMode"}, // Function keys - {winrt::VirtualKey::F1, "F1"}, - {winrt::VirtualKey::F2, "F2"}, - {winrt::VirtualKey::F3, "F3"}, - {winrt::VirtualKey::F4, "F4"}, - {winrt::VirtualKey::F5, "F5"}, - {winrt::VirtualKey::F6, "F6"}, - {winrt::VirtualKey::F7, "F7"}, - {winrt::VirtualKey::F8, "F8"}, - {winrt::VirtualKey::F9, "F9"}, - {winrt::VirtualKey::F10, "F10"}, - {winrt::VirtualKey::F11, "F11"}, - {winrt::VirtualKey::F12, "F12"}, - {winrt::VirtualKey::F13, "F13"}, - {winrt::VirtualKey::F14, "F14"}, - {winrt::VirtualKey::F15, "F15"}, - {winrt::VirtualKey::F16, "F16"}, - {winrt::VirtualKey::F17, "F17"}, - {winrt::VirtualKey::F18, "F18"}, - {winrt::VirtualKey::F19, "F19"}, - {winrt::VirtualKey::F20, "F20"}, + {winrt::Windows::System::VirtualKey::F1, "F1"}, + {winrt::Windows::System::VirtualKey::F2, "F2"}, + {winrt::Windows::System::VirtualKey::F3, "F3"}, + {winrt::Windows::System::VirtualKey::F4, "F4"}, + {winrt::Windows::System::VirtualKey::F5, "F5"}, + {winrt::Windows::System::VirtualKey::F6, "F6"}, + {winrt::Windows::System::VirtualKey::F7, "F7"}, + {winrt::Windows::System::VirtualKey::F8, "F8"}, + {winrt::Windows::System::VirtualKey::F9, "F9"}, + {winrt::Windows::System::VirtualKey::F10, "F10"}, + {winrt::Windows::System::VirtualKey::F11, "F11"}, + {winrt::Windows::System::VirtualKey::F12, "F12"}, + {winrt::Windows::System::VirtualKey::F13, "F13"}, + {winrt::Windows::System::VirtualKey::F14, "F14"}, + {winrt::Windows::System::VirtualKey::F15, "F15"}, + {winrt::Windows::System::VirtualKey::F16, "F16"}, + {winrt::Windows::System::VirtualKey::F17, "F17"}, + {winrt::Windows::System::VirtualKey::F18, "F18"}, + {winrt::Windows::System::VirtualKey::F19, "F19"}, + {winrt::Windows::System::VirtualKey::F20, "F20"}, // Numeric keypad keys - {winrt::VirtualKey::Decimal, "Decimal"}, - {winrt::VirtualKey::Multiply, "Multiply"}, - {winrt::VirtualKey::Add, "Add"}, - {winrt::VirtualKey::Divide, "Divide"}, - {winrt::VirtualKey::Subtract, "Subtract"}, - {winrt::VirtualKey::Separator, "Separator"}, - - {winrt::VirtualKey::NumberPad0, "0"}, - {winrt::VirtualKey::NumberPad1, "1"}, - {winrt::VirtualKey::NumberPad2, "2"}, - {winrt::VirtualKey::NumberPad3, "3"}, - {winrt::VirtualKey::NumberPad4, "4"}, - {winrt::VirtualKey::NumberPad5, "5"}, - {winrt::VirtualKey::NumberPad6, "6"}, - {winrt::VirtualKey::NumberPad7, "7"}, - {winrt::VirtualKey::NumberPad8, "8"}, - {winrt::VirtualKey::NumberPad9, "9"}, + {winrt::Windows::System::VirtualKey::Decimal, "Decimal"}, + {winrt::Windows::System::VirtualKey::Multiply, "Multiply"}, + {winrt::Windows::System::VirtualKey::Add, "Add"}, + {winrt::Windows::System::VirtualKey::Divide, "Divide"}, + {winrt::Windows::System::VirtualKey::Subtract, "Subtract"}, + {winrt::Windows::System::VirtualKey::Separator, "Separator"}, + + {winrt::Windows::System::VirtualKey::NumberPad0, "0"}, + {winrt::Windows::System::VirtualKey::NumberPad1, "1"}, + {winrt::Windows::System::VirtualKey::NumberPad2, "2"}, + {winrt::Windows::System::VirtualKey::NumberPad3, "3"}, + {winrt::Windows::System::VirtualKey::NumberPad4, "4"}, + {winrt::Windows::System::VirtualKey::NumberPad5, "5"}, + {winrt::Windows::System::VirtualKey::NumberPad6, "6"}, + {winrt::Windows::System::VirtualKey::NumberPad7, "7"}, + {winrt::Windows::System::VirtualKey::NumberPad8, "8"}, + {winrt::Windows::System::VirtualKey::NumberPad9, "9"}, // }; @@ -360,22 +361,22 @@ constexpr auto to_underlying(E e) noexcept { // codes are from // https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes All // codes are listed except alpha and numbers. For the unsupported code, they are -// all commented and they key is 'to_underlying(winrt::VirtualKey::None)' For +// all commented and they key is 'to_underlying(winrt::Windows::System::None)' For // example, IntlBackslash is not sent to user: -// //{to_underlying(winrt::VirtualKey::None), "IntlBackslash"}, +// //{to_underlying(winrt::Windows::System::None), "IntlBackslash"}, static const std::vector> g_virtualKeyToCode{ // writing system keys in the Alphanumeric section {192, "Backquote"}, {220, "Backslash"}, - {to_underlying(winrt::VirtualKey::Back), "Backspace"}, + {to_underlying(winrt::Windows::System::VirtualKey::Back), "Backspace"}, {219, "BracketLeft"}, {221, "BracketRight"}, {192, "BracketLeft"}, {188, "Comma"}, {187, "Equal"}, - //{to_underlying(winrt::VirtualKey::None), "IntlBackslash"}, - //{to_underlying(winrt::VirtualKey::None), "IntlRo"}, - //{to_underlying(winrt::VirtualKey::None), "IntlYen"}, + //{to_underlying(winrt::Windows::System::None), "IntlBackslash"}, + //{to_underlying(winrt::Windows::System::None), "IntlRo"}, + //{to_underlying(winrt::Windows::System::None), "IntlYen"}, {189, "Minus"}, {190, "Period"}, {222, "Quote"}, @@ -383,120 +384,120 @@ static const std::vector> g_virtualKeyToCode{ {191, "Slash"}, // Functional Keys - {to_underlying(winrt::VirtualKey::LeftMenu), "AltLeft"}, - {to_underlying(winrt::VirtualKey::RightMenu), "AltRight"}, - {to_underlying(winrt::VirtualKey::CapitalLock), "CapsLock"}, - {to_underlying(winrt::VirtualKey::Menu), "ContextMenu"}, - {to_underlying(winrt::VirtualKey::LeftControl), "ControlLeft"}, - {to_underlying(winrt::VirtualKey::RightControl), "ControlRight"}, - {to_underlying(winrt::VirtualKey::Enter), "Enter"}, - {to_underlying(winrt::VirtualKey::LeftWindows), "MetaLeft"}, - {to_underlying(winrt::VirtualKey::RightWindows), "MetaRight"}, - {to_underlying(winrt::VirtualKey::LeftShift), "ShiftLeft"}, - {to_underlying(winrt::VirtualKey::RightShift), "ShiftRight"}, - {to_underlying(winrt::VirtualKey::Space), "Space"}, - {to_underlying(winrt::VirtualKey::Tab), "Tab"}, + {to_underlying(winrt::Windows::System::VirtualKey::LeftMenu), "AltLeft"}, + {to_underlying(winrt::Windows::System::VirtualKey::RightMenu), "AltRight"}, + {to_underlying(winrt::Windows::System::VirtualKey::CapitalLock), "CapsLock"}, + {to_underlying(winrt::Windows::System::VirtualKey::Menu), "ContextMenu"}, + {to_underlying(winrt::Windows::System::VirtualKey::LeftControl), "ControlLeft"}, + {to_underlying(winrt::Windows::System::VirtualKey::RightControl), "ControlRight"}, + {to_underlying(winrt::Windows::System::VirtualKey::Enter), "Enter"}, + {to_underlying(winrt::Windows::System::VirtualKey::LeftWindows), "MetaLeft"}, + {to_underlying(winrt::Windows::System::VirtualKey::RightWindows), "MetaRight"}, + {to_underlying(winrt::Windows::System::VirtualKey::LeftShift), "ShiftLeft"}, + {to_underlying(winrt::Windows::System::VirtualKey::RightShift), "ShiftRight"}, + {to_underlying(winrt::Windows::System::VirtualKey::Space), "Space"}, + {to_underlying(winrt::Windows::System::VirtualKey::Tab), "Tab"}, // List of code values for functional keys found on Japanese and Korean // keyboards. - {to_underlying(winrt::VirtualKey::Convert), "Convert"}, - {to_underlying(winrt::VirtualKey::Kana), "KanaMode"}, - {to_underlying(winrt::VirtualKey::Hangul), "Lang1"}, - {to_underlying(winrt::VirtualKey::Hanja), "Lang2"}, - //{to_underlying(winrt::VirtualKey::None), "Lang3"}, - //{to_underlying(winrt::VirtualKey::None), "Lang4"}, - //{to_underlying(winrt::VirtualKey::None), "Lang5"}, - {to_underlying(winrt::VirtualKey::NonConvert), "NonConvert"}, + {to_underlying(winrt::Windows::System::VirtualKey::Convert), "Convert"}, + {to_underlying(winrt::Windows::System::VirtualKey::Kana), "KanaMode"}, + {to_underlying(winrt::Windows::System::VirtualKey::Hangul), "Lang1"}, + {to_underlying(winrt::Windows::System::VirtualKey::Hanja), "Lang2"}, + //{to_underlying(winrt::Windows::System::None), "Lang3"}, + //{to_underlying(winrt::Windows::System::None), "Lang4"}, + //{to_underlying(winrt::Windows::System::None), "Lang5"}, + {to_underlying(winrt::Windows::System::VirtualKey::NonConvert), "NonConvert"}, // Control Pad Section - {to_underlying(winrt::VirtualKey::Delete), "Delete"}, - {to_underlying(winrt::VirtualKey::End), "End"}, - {to_underlying(winrt::VirtualKey::Help), "Help"}, - {to_underlying(winrt::VirtualKey::Home), "Home"}, - {to_underlying(winrt::VirtualKey::Insert), "Insert"}, - {to_underlying(winrt::VirtualKey::PageDown), "PageDown"}, - {to_underlying(winrt::VirtualKey::PageUp), "PageUp"}, + {to_underlying(winrt::Windows::System::VirtualKey::Delete), "Delete"}, + {to_underlying(winrt::Windows::System::VirtualKey::End), "End"}, + {to_underlying(winrt::Windows::System::VirtualKey::Help), "Help"}, + {to_underlying(winrt::Windows::System::VirtualKey::Home), "Home"}, + {to_underlying(winrt::Windows::System::VirtualKey::Insert), "Insert"}, + {to_underlying(winrt::Windows::System::VirtualKey::PageDown), "PageDown"}, + {to_underlying(winrt::Windows::System::VirtualKey::PageUp), "PageUp"}, // Arrow Pad Section - {to_underlying(winrt::VirtualKey::Down), "ArrowDown"}, - {to_underlying(winrt::VirtualKey::Left), "ArrowLeft"}, - {to_underlying(winrt::VirtualKey::Right), "ArrowRight"}, - {to_underlying(winrt::VirtualKey::Up), "ArrowUp"}, + {to_underlying(winrt::Windows::System::VirtualKey::Down), "ArrowDown"}, + {to_underlying(winrt::Windows::System::VirtualKey::Left), "ArrowLeft"}, + {to_underlying(winrt::Windows::System::VirtualKey::Right), "ArrowRight"}, + {to_underlying(winrt::Windows::System::VirtualKey::Up), "ArrowUp"}, // Numpad Section - {to_underlying(winrt::VirtualKey::NumberKeyLock), "NumLock"}, - {to_underlying(winrt::VirtualKey::NumberPad0), "Numpad0"}, - {to_underlying(winrt::VirtualKey::NumberPad1), "Numpad1"}, - {to_underlying(winrt::VirtualKey::NumberPad2), "Numpad2"}, - {to_underlying(winrt::VirtualKey::NumberPad3), "Numpad3"}, - {to_underlying(winrt::VirtualKey::NumberPad4), "Numpad4"}, - {to_underlying(winrt::VirtualKey::NumberPad5), "Numpad5"}, - {to_underlying(winrt::VirtualKey::NumberPad6), "Numpad6"}, - {to_underlying(winrt::VirtualKey::NumberPad7), "Numpad7"}, - {to_underlying(winrt::VirtualKey::NumberPad8), "Numpad8"}, - {to_underlying(winrt::VirtualKey::NumberPad9), "Numpad9"}, - {to_underlying(winrt::VirtualKey::Add), "NumpadAdd"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadBackspace"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadClear"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadClearEntry"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadComma"}, - {to_underlying(winrt::VirtualKey::Decimal), "NumpadDecimal"}, - {to_underlying(winrt::VirtualKey::Divide), "NumpadDivide"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadEnter"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadEqual"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadHash"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadMemoryAdd"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadMemoryClear"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadMemoryRecall"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadMemoryStore"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadMemorySubtract"}, - {to_underlying(winrt::VirtualKey::Multiply), "NumpadMultiply"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadParenLeft"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadParenRight"}, - //{to_underlying(winrt::VirtualKey::None), "NumpadStar"}, - {to_underlying(winrt::VirtualKey::Subtract), "NumpadSubtract"}, + {to_underlying(winrt::Windows::System::VirtualKey::NumberKeyLock), "NumLock"}, + {to_underlying(winrt::Windows::System::VirtualKey::NumberPad0), "Numpad0"}, + {to_underlying(winrt::Windows::System::VirtualKey::NumberPad1), "Numpad1"}, + {to_underlying(winrt::Windows::System::VirtualKey::NumberPad2), "Numpad2"}, + {to_underlying(winrt::Windows::System::VirtualKey::NumberPad3), "Numpad3"}, + {to_underlying(winrt::Windows::System::VirtualKey::NumberPad4), "Numpad4"}, + {to_underlying(winrt::Windows::System::VirtualKey::NumberPad5), "Numpad5"}, + {to_underlying(winrt::Windows::System::VirtualKey::NumberPad6), "Numpad6"}, + {to_underlying(winrt::Windows::System::VirtualKey::NumberPad7), "Numpad7"}, + {to_underlying(winrt::Windows::System::VirtualKey::NumberPad8), "Numpad8"}, + {to_underlying(winrt::Windows::System::VirtualKey::NumberPad9), "Numpad9"}, + {to_underlying(winrt::Windows::System::VirtualKey::Add), "NumpadAdd"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadBackspace"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadClear"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadClearEntry"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadComma"}, + {to_underlying(winrt::Windows::System::VirtualKey::Decimal), "NumpadDecimal"}, + {to_underlying(winrt::Windows::System::VirtualKey::Divide), "NumpadDivide"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadEnter"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadEqual"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadHash"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadMemoryAdd"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadMemoryClear"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadMemoryRecall"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadMemoryStore"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadMemorySubtract"}, + {to_underlying(winrt::Windows::System::VirtualKey::Multiply), "NumpadMultiply"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadParenLeft"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadParenRight"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "NumpadStar"}, + {to_underlying(winrt::Windows::System::VirtualKey::Subtract), "NumpadSubtract"}, // Function Section - {to_underlying(winrt::VirtualKey::Escape), "Escape"}, - {to_underlying(winrt::VirtualKey::F1), "F1"}, - {to_underlying(winrt::VirtualKey::F2), "F2"}, - {to_underlying(winrt::VirtualKey::F3), "F3"}, - {to_underlying(winrt::VirtualKey::F4), "F4"}, - {to_underlying(winrt::VirtualKey::F5), "F5"}, - {to_underlying(winrt::VirtualKey::F6), "F6"}, - {to_underlying(winrt::VirtualKey::F7), "F7"}, - {to_underlying(winrt::VirtualKey::F8), "F8"}, - {to_underlying(winrt::VirtualKey::F9), "F9"}, - {to_underlying(winrt::VirtualKey::F10), "F10"}, - {to_underlying(winrt::VirtualKey::F11), "F11"}, - {to_underlying(winrt::VirtualKey::F12), "F12"}, - {to_underlying(winrt::VirtualKey::F13), "F13"}, - {to_underlying(winrt::VirtualKey::F14), "F14"}, - {to_underlying(winrt::VirtualKey::F15), "F15"}, - {to_underlying(winrt::VirtualKey::F16), "F16"}, - {to_underlying(winrt::VirtualKey::F17), "F17"}, - {to_underlying(winrt::VirtualKey::F18), "F18"}, - {to_underlying(winrt::VirtualKey::F19), "F19"}, - {to_underlying(winrt::VirtualKey::F20), "F20"}, - {to_underlying(winrt::VirtualKey::F21), "F21"}, - {to_underlying(winrt::VirtualKey::F22), "F22"}, - {to_underlying(winrt::VirtualKey::F23), "F23"}, - {to_underlying(winrt::VirtualKey::F24), "F24"}, - //{to_underlying(winrt::VirtualKey::None), "Fn"}, - //{to_underlying(winrt::VirtualKey::None), "FnLock"}, - {to_underlying(winrt::VirtualKey::Print), "PrintScreen"}, - {to_underlying(winrt::VirtualKey::Scroll), "ScrollLock"}, - {to_underlying(winrt::VirtualKey::Pause), "Pause"}, + {to_underlying(winrt::Windows::System::VirtualKey::Escape), "Escape"}, + {to_underlying(winrt::Windows::System::VirtualKey::F1), "F1"}, + {to_underlying(winrt::Windows::System::VirtualKey::F2), "F2"}, + {to_underlying(winrt::Windows::System::VirtualKey::F3), "F3"}, + {to_underlying(winrt::Windows::System::VirtualKey::F4), "F4"}, + {to_underlying(winrt::Windows::System::VirtualKey::F5), "F5"}, + {to_underlying(winrt::Windows::System::VirtualKey::F6), "F6"}, + {to_underlying(winrt::Windows::System::VirtualKey::F7), "F7"}, + {to_underlying(winrt::Windows::System::VirtualKey::F8), "F8"}, + {to_underlying(winrt::Windows::System::VirtualKey::F9), "F9"}, + {to_underlying(winrt::Windows::System::VirtualKey::F10), "F10"}, + {to_underlying(winrt::Windows::System::VirtualKey::F11), "F11"}, + {to_underlying(winrt::Windows::System::VirtualKey::F12), "F12"}, + {to_underlying(winrt::Windows::System::VirtualKey::F13), "F13"}, + {to_underlying(winrt::Windows::System::VirtualKey::F14), "F14"}, + {to_underlying(winrt::Windows::System::VirtualKey::F15), "F15"}, + {to_underlying(winrt::Windows::System::VirtualKey::F16), "F16"}, + {to_underlying(winrt::Windows::System::VirtualKey::F17), "F17"}, + {to_underlying(winrt::Windows::System::VirtualKey::F18), "F18"}, + {to_underlying(winrt::Windows::System::VirtualKey::F19), "F19"}, + {to_underlying(winrt::Windows::System::VirtualKey::F20), "F20"}, + {to_underlying(winrt::Windows::System::VirtualKey::F21), "F21"}, + {to_underlying(winrt::Windows::System::VirtualKey::F22), "F22"}, + {to_underlying(winrt::Windows::System::VirtualKey::F23), "F23"}, + {to_underlying(winrt::Windows::System::VirtualKey::F24), "F24"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Fn"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "FnLock"}, + {to_underlying(winrt::Windows::System::VirtualKey::Print), "PrintScreen"}, + {to_underlying(winrt::Windows::System::VirtualKey::Scroll), "ScrollLock"}, + {to_underlying(winrt::Windows::System::VirtualKey::Pause), "Pause"}, //// Media Keys - {to_underlying(winrt::VirtualKey::GoBack), "BrowserBack"}, - {to_underlying(winrt::VirtualKey::Favorites), "BrowserFavorites"}, - {to_underlying(winrt::VirtualKey::GoForward), "BrowserForward"}, - {to_underlying(winrt::VirtualKey::GoHome), "BrowserHome"}, - {to_underlying(winrt::VirtualKey::Refresh), "BrowserRefresh"}, - {to_underlying(winrt::VirtualKey::Search), "BrowserSearch"}, - {to_underlying(winrt::VirtualKey::Stop), "BrowserStop"}, - //{to_underlying(winrt::VirtualKey::None), "Eject"}, + {to_underlying(winrt::Windows::System::VirtualKey::GoBack), "BrowserBack"}, + {to_underlying(winrt::Windows::System::VirtualKey::Favorites), "BrowserFavorites"}, + {to_underlying(winrt::Windows::System::VirtualKey::GoForward), "BrowserForward"}, + {to_underlying(winrt::Windows::System::VirtualKey::GoHome), "BrowserHome"}, + {to_underlying(winrt::Windows::System::VirtualKey::Refresh), "BrowserRefresh"}, + {to_underlying(winrt::Windows::System::VirtualKey::Search), "BrowserSearch"}, + {to_underlying(winrt::Windows::System::VirtualKey::Stop), "BrowserStop"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Eject"}, {182, "LaunchApp1"}, {183, "LaunchApp2"}, {180, "LaunchMail"}, @@ -505,64 +506,64 @@ static const std::vector> g_virtualKeyToCode{ {178, "MediaStop"}, {176, "MediaTrackNext"}, {177, "MediaTrackPrevious"}, - //{to_underlying(winrt::VirtualKey::None), "Power"}, - {to_underlying(winrt::VirtualKey::Sleep), "Sleep"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Power"}, + {to_underlying(winrt::Windows::System::VirtualKey::Sleep), "Sleep"}, {174, "AudioVolumeDown"}, {173, "AudioVolumeMute"}, {175, "AudioVolumeUp"}, - //{to_underlying(winrt::VirtualKey::None), "WakeUp"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "WakeUp"}, ////List of code values for legacy modifier keys. - //{to_underlying(winrt::VirtualKey::None), "Hyper"}, - //{to_underlying(winrt::VirtualKey::None), "Super"}, - //{to_underlying(winrt::VirtualKey::None), "Turbo"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Hyper"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Super"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Turbo"}, ////List of code values for legacy process control keys. - //{to_underlying(winrt::VirtualKey::None), "Abort"}, - //{to_underlying(winrt::VirtualKey::None), "Resume"}, - //{to_underlying(winrt::VirtualKey::None), "Suspend"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Abort"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Resume"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Suspend"}, ////List of code values for legacy editing keys. - //{to_underlying(winrt::VirtualKey::None), "Again"}, - //{to_underlying(winrt::VirtualKey::None), "Copy"}, - //{to_underlying(winrt::VirtualKey::None), "Cut"}, - //{to_underlying(winrt::VirtualKey::None), "Find"}, - //{to_underlying(winrt::VirtualKey::None), "Open"}, - //{to_underlying(winrt::VirtualKey::None), "Paste"}, - //{to_underlying(winrt::VirtualKey::None), "Props"}, - {to_underlying(winrt::VirtualKey::Select), "Select"}, - //{to_underlying(winrt::VirtualKey::None), "Undo"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Again"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Copy"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Cut"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Find"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Open"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Paste"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Props"}, + {to_underlying(winrt::Windows::System::VirtualKey::Select), "Select"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Undo"}, // The following keys may be found on non-standard international keyboards. - //{to_underlying(winrt::VirtualKey::None), "Hiragana"}, - //{to_underlying(winrt::VirtualKey::None), "Katakana"}, - //{to_underlying(winrt::VirtualKey::None), "Undo"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Hiragana"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Katakana"}, + //{to_underlying(winrt::Windows::System::VirtualKey::None), "Undo"}, // Xbox Gamepad - {to_underlying(winrt::VirtualKey::GamepadA), "GamepadA"}, - {to_underlying(winrt::VirtualKey::GamepadB), "GamepadB"}, - {to_underlying(winrt::VirtualKey::GamepadX), "GamepadX"}, - {to_underlying(winrt::VirtualKey::GamepadY), "GamepadY"}, - {to_underlying(winrt::VirtualKey::GamepadRightShoulder), "GamepadRightShoulder"}, - {to_underlying(winrt::VirtualKey::GamepadLeftShoulder), "GamepadLeftShoulder"}, - {to_underlying(winrt::VirtualKey::GamepadLeftTrigger), "GamepadLeftTrigger"}, - {to_underlying(winrt::VirtualKey::GamepadRightTrigger), "GamepadRightTrigger"}, - {to_underlying(winrt::VirtualKey::GamepadDPadUp), "GamepadDPadUp"}, - {to_underlying(winrt::VirtualKey::GamepadDPadDown), "GamepadDPadDown"}, - {to_underlying(winrt::VirtualKey::GamepadDPadLeft), "GamepadDPadLeft"}, - {to_underlying(winrt::VirtualKey::GamepadDPadRight), "GamepadDPadRight"}, - {to_underlying(winrt::VirtualKey::GamepadMenu), "GamepadMenu"}, - {to_underlying(winrt::VirtualKey::GamepadView), "GamepadView"}, - {to_underlying(winrt::VirtualKey::GamepadLeftThumbstickButton), "GamepadLeftThumbstickButton"}, - {to_underlying(winrt::VirtualKey::GamepadRightThumbstickButton), "GamepadRightThumbstickButton"}, - {to_underlying(winrt::VirtualKey::GamepadLeftThumbstickUp), "GamepadLeftThumbstickUp"}, - {to_underlying(winrt::VirtualKey::GamepadLeftThumbstickDown), "GamepadLeftThumbstickDown"}, - {to_underlying(winrt::VirtualKey::GamepadLeftThumbstickRight), "GamepadLeftThumbstickRight"}, - {to_underlying(winrt::VirtualKey::GamepadLeftThumbstickLeft), "GamepadLeftThumbstickLeft"}, - {to_underlying(winrt::VirtualKey::GamepadRightThumbstickUp), "GamepadRightThumbstickUp"}, - {to_underlying(winrt::VirtualKey::GamepadRightThumbstickDown), "GamepadRightThumbstickDown"}, - {to_underlying(winrt::VirtualKey::GamepadRightThumbstickRight), "GamepadRightThumbstickRight"}, - {to_underlying(winrt::VirtualKey::GamepadRightThumbstickLeft), "GamepadRightThumbstickLeft"}}; + {to_underlying(winrt::Windows::System::VirtualKey::GamepadA), "GamepadA"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadB), "GamepadB"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadX), "GamepadX"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadY), "GamepadY"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadRightShoulder), "GamepadRightShoulder"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadLeftShoulder), "GamepadLeftShoulder"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadLeftTrigger), "GamepadLeftTrigger"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadRightTrigger), "GamepadRightTrigger"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadDPadUp), "GamepadDPadUp"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadDPadDown), "GamepadDPadDown"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadDPadLeft), "GamepadDPadLeft"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadDPadRight), "GamepadDPadRight"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadMenu), "GamepadMenu"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadView), "GamepadView"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadLeftThumbstickButton), "GamepadLeftThumbstickButton"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadRightThumbstickButton), "GamepadRightThumbstickButton"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadLeftThumbstickUp), "GamepadLeftThumbstickUp"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadLeftThumbstickDown), "GamepadLeftThumbstickDown"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadLeftThumbstickRight), "GamepadLeftThumbstickRight"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadLeftThumbstickLeft), "GamepadLeftThumbstickLeft"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadRightThumbstickUp), "GamepadRightThumbstickUp"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadRightThumbstickDown), "GamepadRightThumbstickDown"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadRightThumbstickRight), "GamepadRightThumbstickRight"}, + {to_underlying(winrt::Windows::System::VirtualKey::GamepadRightThumbstickLeft), "GamepadRightThumbstickLeft"}}; template static const std::string GetOrUnidentified( @@ -575,7 +576,8 @@ static const std::string GetOrUnidentified( return "Unidentified"; } -std::string KeyboardHelper::FromVirtualKey(winrt::VirtualKey virtualKey, bool /*shiftDown*/, bool /*capLocked*/) { +std::string +KeyboardHelper::FromVirtualKey(winrt::Windows::System::VirtualKey virtualKey, bool /*shiftDown*/, bool /*capLocked*/) { int key = static_cast(virtualKey); if (!isupper(key) && !isdigit(key)) { @@ -589,12 +591,14 @@ std::string KeyboardHelper::FromVirtualKey(winrt::VirtualKey virtualKey, bool /* return std::string(1, static_cast(key)); } -inline winrt::VirtualKey -GetLeftOrRightModifiedKey(winrt::CoreWindow const &coreWindow, winrt::VirtualKey leftKey, winrt::VirtualKey rightKey) { +inline winrt::Windows::System::VirtualKey GetLeftOrRightModifiedKey( + winrt::CoreWindow const &coreWindow, + winrt::Windows::System::VirtualKey leftKey, + winrt::Windows::System::VirtualKey rightKey) { return KeyboardHelper::IsModifiedKeyPressed(coreWindow, leftKey) ? leftKey : rightKey; } -std::string KeyboardHelper::CodeFromVirtualKey(winrt::VirtualKey virtualKey) { +std::string KeyboardHelper::CodeFromVirtualKey(winrt::Windows::System::VirtualKey virtualKey) { int key = static_cast(virtualKey); if (isdigit(key)) { @@ -604,24 +608,32 @@ std::string KeyboardHelper::CodeFromVirtualKey(winrt::VirtualKey virtualKey) { } else { // Override the virtual key if it's modified key of Control, Shift or Menu auto const &coreWindow = winrt::CoreWindow::GetForCurrentThread(); - if (virtualKey == winrt::VirtualKey::Control) { - virtualKey = - GetLeftOrRightModifiedKey(coreWindow, winrt::VirtualKey::LeftControl, winrt::VirtualKey::RightControl); - } else if (virtualKey == winrt::VirtualKey::Shift) { - virtualKey = GetLeftOrRightModifiedKey(coreWindow, winrt::VirtualKey::LeftShift, winrt::VirtualKey::RightShift); - } else if (virtualKey == winrt::VirtualKey::Menu) { - virtualKey = GetLeftOrRightModifiedKey(coreWindow, winrt::VirtualKey::LeftMenu, winrt::VirtualKey::RightMenu); + if (virtualKey == winrt::Windows::System::VirtualKey::Control) { + virtualKey = GetLeftOrRightModifiedKey( + coreWindow, + winrt::Windows::System::VirtualKey::LeftControl, + winrt::Windows::System::VirtualKey::RightControl); + } else if (virtualKey == winrt::Windows::System::VirtualKey::Shift) { + virtualKey = GetLeftOrRightModifiedKey( + coreWindow, winrt::Windows::System::VirtualKey::LeftShift, winrt::Windows::System::VirtualKey::RightShift); + } else if (virtualKey == winrt::Windows::System::VirtualKey::Menu) { + virtualKey = GetLeftOrRightModifiedKey( + coreWindow, winrt::Windows::System::VirtualKey::LeftMenu, winrt::Windows::System::VirtualKey::RightMenu); } } return GetOrUnidentified(virtualKey, g_virtualKeyToCode); } -bool KeyboardHelper::IsModifiedKeyPressed(winrt::CoreWindow const &coreWindow, winrt::VirtualKey virtualKey) { +bool KeyboardHelper::IsModifiedKeyPressed( + winrt::CoreWindow const &coreWindow, + winrt::Windows::System::VirtualKey virtualKey) { return (coreWindow.GetKeyState(virtualKey) & winrt::CoreVirtualKeyStates::Down) == winrt::CoreVirtualKeyStates::Down; } -bool KeyboardHelper::IsModifiedKeyLocked(winrt::CoreWindow const &coreWindow, winrt::VirtualKey virtualKey) { +bool KeyboardHelper::IsModifiedKeyLocked( + winrt::CoreWindow const &coreWindow, + winrt::Windows::System::VirtualKey virtualKey) { return (coreWindow.GetKeyState(virtualKey) & winrt::CoreVirtualKeyStates::Locked) == winrt::CoreVirtualKeyStates::Locked; } diff --git a/vnext/ReactUWP/Views/PickerViewManager.cpp b/vnext/ReactUWP/Views/PickerViewManager.cpp index 5027cf4f1d6..58d3c56a604 100644 --- a/vnext/ReactUWP/Views/PickerViewManager.cpp +++ b/vnext/ReactUWP/Views/PickerViewManager.cpp @@ -12,7 +12,6 @@ #include #include -#include namespace react { namespace uwp { @@ -41,18 +40,18 @@ class PickerShadowNode : public ShadowNodeBase { // FUTURE: remove when we can require RS5+ bool m_isEditableComboboxSupported; - winrt::ComboBox::SelectionChanged_revoker m_comboBoxSelectionChangedRevoker{}; - winrt::ComboBox::DropDownClosed_revoker m_comboBoxDropDownClosedRevoker{}; + xaml::Controls::ComboBox::SelectionChanged_revoker m_comboBoxSelectionChangedRevoker{}; + xaml::Controls::ComboBox::DropDownClosed_revoker m_comboBoxDropDownClosedRevoker{}; }; PickerShadowNode::PickerShadowNode() : Super() { m_isEditableComboboxSupported = winrt::Windows::Foundation::Metadata::ApiInformation::IsPropertyPresent( - L"Windows.UI.Xaml.Controls.ComboBox", L"IsEditableProperty"); + XAML_NAMESPACE_STR L".Controls.ComboBox", L"IsEditableProperty"); } void PickerShadowNode::createView() { Super::createView(); - auto combobox = GetView().as(); + auto combobox = GetView().as(); combobox.TabIndex(0); auto wkinstance = GetViewManager()->GetReactInstance(); @@ -76,7 +75,7 @@ void PickerShadowNode::createView() { // When the drop down closes, attempt to move focus to its anchor // textbox to prevent cases where focus can land on an outer flyout // content and therefore trigger a unexpected flyout dismissal - winrt::FocusManager::TryFocusAsync(combobox, winrt::FocusState::Programmatic); + xaml::Input::FocusManager::TryFocusAsync(combobox, xaml::FocusState::Programmatic); }); } @@ -84,7 +83,7 @@ void PickerShadowNode::updateProperties(const folly::dynamic &&props) { m_updating = true; bool updateSelectedIndex = false; - auto combobox = GetView().as(); + auto combobox = GetView().as(); for (auto &pair : props.items()) { const std::string &propertyName = pair.first.getString(); const folly::dynamic &propertyValue = pair.second; @@ -94,14 +93,14 @@ void PickerShadowNode::updateProperties(const folly::dynamic &&props) { if (propertyValue.isBool()) combobox.IsEditable(propertyValue.asBool()); else if (propertyValue.isNull()) - combobox.ClearValue(winrt::ComboBox::IsEditableProperty()); + combobox.ClearValue(xaml::Controls::ComboBox::IsEditableProperty()); } } else if (propertyName == "text") { if (m_isEditableComboboxSupported) { if (propertyValue.isString()) combobox.Text(asHstring(propertyValue)); else if (propertyValue.isNull()) - combobox.ClearValue(winrt::ComboBox::TextProperty()); + combobox.ClearValue(xaml::Controls::ComboBox::TextProperty()); } } else if (propertyName == "enabled") { if (propertyValue.isBool()) @@ -132,14 +131,14 @@ void PickerShadowNode::updateProperties(const folly::dynamic &&props) { } void PickerShadowNode::RepopulateItems() { - auto combobox = GetView().as(); + auto combobox = GetView().as(); auto comboBoxItems = combobox.Items(); comboBoxItems.Clear(); for (const auto &item : m_items) { if (item.count("label")) { std::string label = item["label"].asString(); - auto comboboxItem = winrt::ComboBoxItem(); + auto comboboxItem = xaml::Controls::ComboBoxItem(); comboboxItem.Content(winrt::box_value(Microsoft::Common::Unicode::Utf8ToUtf16(label))); @@ -188,7 +187,7 @@ facebook::react::ShadowNode *PickerViewManager::createShadow() const { } XamlView PickerViewManager::CreateViewCore(int64_t /*tag*/) { - auto combobox = winrt::ComboBox(); + auto combobox = xaml::Controls::ComboBox(); return combobox; } diff --git a/vnext/ReactUWP/Views/PopupViewManager.cpp b/vnext/ReactUWP/Views/PopupViewManager.cpp index b87fd6a1928..859e378aeff 100644 --- a/vnext/ReactUWP/Views/PopupViewManager.cpp +++ b/vnext/ReactUWP/Views/PopupViewManager.cpp @@ -12,10 +12,8 @@ #include #include -#include - namespace winrt { -using namespace Windows::UI::Xaml::Controls::Primitives; +using namespace xaml::Controls::Primitives; } // namespace winrt namespace react { @@ -36,7 +34,7 @@ class PopupShadowNode : public ShadowNodeBase { static void OnPopupClosed(IReactInstance &instance, int64_t tag); winrt::Windows::Foundation::Size GetAppWindowSize(); - winrt::ContentControl GetControl(); + xaml::Controls::ContentControl GetControl(); void UpdateTabStops(); void UpdateLayout(); @@ -54,8 +52,8 @@ class PopupShadowNode : public ShadowNodeBase { int64_t m_targetTag; winrt::Popup::Closed_revoker m_popupClosedRevoker{}; winrt::Popup::Opened_revoker m_popupOpenedRevoker{}; - winrt::FrameworkElement::SizeChanged_revoker m_popupSizeChangedRevoker{}; - winrt::Window::SizeChanged_revoker m_windowSizeChangedRevoker{}; + xaml::FrameworkElement::SizeChanged_revoker m_popupSizeChangedRevoker{}; + xaml::Window::SizeChanged_revoker m_windowSizeChangedRevoker{}; }; PopupShadowNode::~PopupShadowNode() { @@ -63,9 +61,9 @@ PopupShadowNode::~PopupShadowNode() { m_previewKeyboardEventHandlerOnRoot->unhook(); } -winrt::ContentControl PopupShadowNode::GetControl() { +xaml::Controls::ContentControl PopupShadowNode::GetControl() { auto popup = GetView().as(); - auto control = popup.Child().as(); + auto control = popup.Child().as(); return control; } @@ -93,7 +91,7 @@ void PopupShadowNode::createView() { // translation based on an elevation derived from the count of open // popups/flyouts. We apply this translation on open of the popup. // (Translation is only supported on RS5+, eg. IUIElement9) - if (auto uiElement9 = GetView().try_as()) { + if (auto uiElement9 = GetView().try_as()) { auto numOpenPopups = CountOpenPopups(); if (numOpenPopups > 0) { winrt::Numerics::float3 translation{0, 0, (float)16 * numOpenPopups}; @@ -113,7 +111,7 @@ void PopupShadowNode::createView() { } }); - m_windowSizeChangedRevoker = winrt::Window::Current().SizeChanged(winrt::auto_revoke, [=](auto &&, auto &&) { + m_windowSizeChangedRevoker = xaml::Window::Current().SizeChanged(winrt::auto_revoke, [=](auto &&, auto &&) { auto instance = wkinstance.lock(); if (!m_updating && instance != nullptr) { UpdateLayout(); @@ -248,7 +246,7 @@ void PopupShadowNode::UpdateLayout() { if (pShadowNodeChild != nullptr) { auto targetView = pShadowNodeChild->GetView(); - auto targetElement = targetView.as(); + auto targetElement = targetView.as(); auto popupTransform = targetElement.TransformToVisual(popup); winrt::Point bottomRightPoint( @@ -259,7 +257,7 @@ void PopupShadowNode::UpdateLayout() { } } else // Center relative to app window { - auto appWindow = winrt::Window::Current().Content(); + auto appWindow = xaml::Window::Current().Content(); auto popupToWindow = appWindow.TransformToVisual(popup); auto appWindowSize = GetAppWindowSize(); winrt::Point centerPoint; @@ -275,18 +273,18 @@ void PopupShadowNode::UpdateTabStops() { auto control = GetControl(); if (m_autoFocus) { control.IsTabStop(true); - control.TabFocusNavigation(winrt::Windows::UI::Xaml::Input::KeyboardNavigationMode::Cycle); - winrt::FocusManager::TryFocusAsync(control, winrt::Windows::UI::Xaml::FocusState::Programmatic); + control.TabFocusNavigation(xaml::Input::KeyboardNavigationMode::Cycle); + xaml::Input::FocusManager::TryFocusAsync(control, xaml::FocusState::Programmatic); } else { control.IsTabStop(false); - control.TabFocusNavigation(winrt::Windows::UI::Xaml::Input::KeyboardNavigationMode::Local); + control.TabFocusNavigation(xaml::Input::KeyboardNavigationMode::Local); } } winrt::Size PopupShadowNode::GetAppWindowSize() { winrt::Size windowSize = winrt::SizeHelper::Empty(); - if (auto current = winrt::Window::Current()) { + if (auto current = xaml::Window::Current()) { if (auto coreWindow = current.CoreWindow()) { windowSize.Width = coreWindow.Bounds().Width; windowSize.Height = coreWindow.Bounds().Height; @@ -317,7 +315,7 @@ facebook::react::ShadowNode *PopupViewManager::createShadow() const { XamlView PopupViewManager::CreateViewCore(int64_t /*tag*/) { auto popup = winrt::Popup(); - auto control = winrt::ContentControl(); + auto control = xaml::Controls::ContentControl(); popup.Child(control); @@ -332,7 +330,7 @@ void PopupViewManager::SetLayoutProps( float width, float height) { auto popup = viewToUpdate.as(); - auto control = popup.Child().as(); + auto control = popup.Child().as(); control.Width(width); control.Height(height); diff --git a/vnext/ReactUWP/Views/RawTextViewManager.cpp b/vnext/ReactUWP/Views/RawTextViewManager.cpp index 66dada69cdc..49f82c84c5c 100644 --- a/vnext/ReactUWP/Views/RawTextViewManager.cpp +++ b/vnext/ReactUWP/Views/RawTextViewManager.cpp @@ -12,16 +12,14 @@ #include #include -#include -#include namespace winrt { using namespace Windows::Foundation; using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Documents; -using namespace Windows::UI::Xaml::Media; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Documents; +using namespace xaml::Media; } // namespace winrt namespace react { diff --git a/vnext/ReactUWP/Views/ReactControl.cpp b/vnext/ReactUWP/Views/ReactControl.cpp index b7a8f1a2dfe..029aa61bb55 100644 --- a/vnext/ReactUWP/Views/ReactControl.cpp +++ b/vnext/ReactUWP/Views/ReactControl.cpp @@ -19,12 +19,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include namespace react { namespace uwp { @@ -72,7 +66,7 @@ void ReactControl::HandleInstanceErrorOnUIThread() { if (m_errorTextBlock == nullptr) { m_errorTextBlock = winrt::TextBlock(); m_redBoxGrid = winrt::Grid(); - m_redBoxGrid.Background(winrt::SolidColorBrush(winrt::ColorHelper::FromArgb(0xee, 0xcc, 0, 0))); + m_redBoxGrid.Background(xaml::Media::SolidColorBrush(winrt::ColorHelper::FromArgb(0xee, 0xcc, 0, 0))); m_redBoxGrid.Children().Append(m_errorTextBlock); } @@ -86,9 +80,9 @@ void ReactControl::HandleInstanceErrorOnUIThread() { // Format TextBlock m_errorTextBlock.TextAlignment(winrt::TextAlignment::Center); - m_errorTextBlock.TextWrapping(winrt::TextWrapping::Wrap); + m_errorTextBlock.TextWrapping(xaml::TextWrapping::Wrap); m_errorTextBlock.FontFamily(winrt::FontFamily(L"Consolas")); - m_errorTextBlock.Foreground(winrt::SolidColorBrush(winrt::Colors::White())); + m_errorTextBlock.Foreground(xaml::Media::SolidColorBrush(winrt::Colors::White())); winrt::Thickness margin = {10.0f, 10.0f, 10.0f, 10.0f}; m_errorTextBlock.Margin(margin); } @@ -114,9 +108,9 @@ void ReactControl::HandleInstanceWaitingOnUIThread() { if (m_waitingTextBlock == nullptr) { m_waitingTextBlock = winrt::TextBlock(); m_greenBoxGrid = winrt::Grid(); - m_greenBoxGrid.Background(winrt::SolidColorBrush(winrt::ColorHelper::FromArgb(0xff, 0x03, 0x59, 0))); + m_greenBoxGrid.Background(xaml::Media::SolidColorBrush(winrt::ColorHelper::FromArgb(0xff, 0x03, 0x59, 0))); m_greenBoxGrid.Children().Append(m_waitingTextBlock); - m_greenBoxGrid.VerticalAlignment(winrt::Windows::UI::Xaml::VerticalAlignment::Top); + m_greenBoxGrid.VerticalAlignment(xaml::VerticalAlignment::Top); } // Add box grid to root view @@ -128,9 +122,9 @@ void ReactControl::HandleInstanceWaitingOnUIThread() { // Format TextBlock m_waitingTextBlock.TextAlignment(winrt::TextAlignment::Center); - m_waitingTextBlock.TextWrapping(winrt::TextWrapping::Wrap); + m_waitingTextBlock.TextWrapping(xaml::TextWrapping::Wrap); m_waitingTextBlock.FontFamily(winrt::FontFamily(L"Consolas")); - m_waitingTextBlock.Foreground(winrt::SolidColorBrush(winrt::Colors::White())); + m_waitingTextBlock.Foreground(xaml::Media::SolidColorBrush(winrt::Colors::White())); winrt::Thickness margin = {10.0f, 10.0f, 10.0f, 10.0f}; m_waitingTextBlock.Margin(margin); } @@ -251,9 +245,9 @@ void ReactControl::blur(XamlView const &xamlView) noexcept { EnsureFocusSafeHarbor(); if (m_focusSafeHarbor) { m_focusSafeHarbor.IsTabStop(true); - winrt::FocusManager::TryFocusAsync(m_focusSafeHarbor, winrt::FocusState::Pointer); + xaml::Input::FocusManager::TryFocusAsync(m_focusSafeHarbor, winrt::FocusState::Pointer); } else - winrt::FocusManager::TryFocusAsync(xamlView, winrt::FocusState::Pointer); + xaml::Input::FocusManager::TryFocusAsync(xamlView, winrt::FocusState::Pointer); } void ReactControl::DetachInstance() { @@ -321,14 +315,14 @@ std::string ReactControl::JSComponentName() const noexcept { } int64_t ReactControl::GetActualHeight() const { - auto element = m_xamlRootView.as(); + auto element = m_xamlRootView.as(); assert(element != nullptr); return static_cast(element.ActualHeight()); } int64_t ReactControl::GetActualWidth() const { - auto element = m_xamlRootView.as(); + auto element = m_xamlRootView.as(); assert(element != nullptr); return static_cast(element.ActualWidth()); @@ -349,9 +343,9 @@ void ReactControl::PrepareXamlRootView(XamlView const &rootView) { // Xaml's default projection in 3D is orthographic (all lines are parallel) // However React Native's default projection is a one-point perspective. // Set a default perspective projection on the main control to mimic this. - auto perspectiveTransform3D = winrt::Windows::UI::Xaml::Media::Media3D::PerspectiveTransform3D(); + auto perspectiveTransform3D = xaml::Media::Media3D::PerspectiveTransform3D(); perspectiveTransform3D.Depth(850); - winrt::Windows::UI::Xaml::Media::Media3D::Transform3D t3d(perspectiveTransform3D); + xaml::Media::Media3D::Transform3D t3d(perspectiveTransform3D); newRootView.Transform3D(t3d); children.Append(newRootView); m_xamlRootView = newRootView; @@ -365,7 +359,7 @@ void ReactControl::EnsureFocusSafeHarbor() { auto panel = m_rootView.try_as(); assert(panel.Children().Size() == 1); - m_focusSafeHarbor = winrt::ContentControl(); + m_focusSafeHarbor = xaml::Controls::ContentControl(); m_focusSafeHarbor.Width(0.0); m_focusSafeHarbor.IsTabStop(false); panel.Children().InsertAt(0, m_focusSafeHarbor); @@ -382,9 +376,10 @@ void ReactControl::InitializeDeveloperMenu() { m_coreDispatcherAKARevoker = coreWindow.Dispatcher().AcceleratorKeyActivated( winrt::auto_revoke, [this](const auto &sender, const winrt::AcceleratorKeyEventArgs &args) { if ((args.VirtualKey() == winrt::Windows::System::VirtualKey::D) && - KeyboardHelper::IsModifiedKeyPressed(winrt::CoreWindow::GetForCurrentThread(), winrt::VirtualKey::Shift) && KeyboardHelper::IsModifiedKeyPressed( - winrt::CoreWindow::GetForCurrentThread(), winrt::VirtualKey::Control)) { + winrt::CoreWindow::GetForCurrentThread(), winrt::Windows::System::VirtualKey::Shift) && + KeyboardHelper::IsModifiedKeyPressed( + winrt::CoreWindow::GetForCurrentThread(), winrt::Windows::System::VirtualKey::Control)) { if (!IsDeveloperMenuShowing()) { ShowDeveloperMenu(); } diff --git a/vnext/ReactUWP/Views/ReactControl.h b/vnext/ReactUWP/Views/ReactControl.h index 2da4436a8ac..87e617b60ee 100644 --- a/vnext/ReactUWP/Views/ReactControl.h +++ b/vnext/ReactUWP/Views/ReactControl.h @@ -7,7 +7,6 @@ #include #include -#include #include "IXamlRootView.h" #include "SIPEventHandler.h" #include "TouchEventHandler.h" @@ -15,11 +14,11 @@ namespace winrt { using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Input; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Input; using namespace Windows::Foundation; -using namespace Windows::UI::Xaml::Media; +using namespace xaml::Media; } // namespace winrt namespace react { @@ -100,8 +99,8 @@ class ReactControl final : public std::enable_shared_from_this, pu ErrorCallbackCookie m_errorCallbackCookie{0}; DebuggerAttachCallbackCookie m_debuggerAttachCallbackCookie{0}; - winrt::ContentControl m_focusSafeHarbor{nullptr}; - winrt::ContentControl::LosingFocus_revoker m_focusSafeHarborLosingFocusRevoker{}; + xaml::Controls::ContentControl m_focusSafeHarbor{nullptr}; + xaml::Controls::ContentControl::LosingFocus_revoker m_focusSafeHarborLosingFocusRevoker{}; winrt::Grid m_redBoxGrid{nullptr}; winrt::Grid m_greenBoxGrid{nullptr}; winrt::TextBlock m_errorTextBlock{nullptr}; diff --git a/vnext/ReactUWP/Views/ReactRootView.cpp b/vnext/ReactUWP/Views/ReactRootView.cpp index 92f9c6c008e..bb90b412142 100644 --- a/vnext/ReactUWP/Views/ReactRootView.cpp +++ b/vnext/ReactUWP/Views/ReactRootView.cpp @@ -16,17 +16,13 @@ #include #include #include -#include -#include -#include -#include namespace winrt { -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Input; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Input; using namespace Windows::Foundation; -using namespace Windows::UI::Xaml::Media; +using namespace xaml::Media; } // namespace winrt namespace react { diff --git a/vnext/ReactUWP/Views/RefreshControlManager.cpp b/vnext/ReactUWP/Views/RefreshControlManager.cpp index 89703362f4c..a0230b10362 100644 --- a/vnext/ReactUWP/Views/RefreshControlManager.cpp +++ b/vnext/ReactUWP/Views/RefreshControlManager.cpp @@ -5,14 +5,12 @@ #include "RefreshControlManager.h" -#include - #include #include namespace winrt { -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; +using namespace xaml; +using namespace xaml::Controls; using namespace Windows::Foundation; } // namespace winrt diff --git a/vnext/ReactUWP/Views/RootViewManager.cpp b/vnext/ReactUWP/Views/RootViewManager.cpp index c4aff22af2a..3b74356dd51 100644 --- a/vnext/ReactUWP/Views/RootViewManager.cpp +++ b/vnext/ReactUWP/Views/RootViewManager.cpp @@ -7,12 +7,10 @@ #include -#include - namespace winrt { using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; +using namespace xaml; +using namespace xaml::Controls; } // namespace winrt namespace react { @@ -33,7 +31,7 @@ XamlView RootViewManager::CreateViewCore(int64_t /*tag*/) { void RootViewManager::AddView(const XamlView &parent, const XamlView &child, int64_t index) { auto panel(parent.as()); if (panel != nullptr) - panel.Children().InsertAt(static_cast(index), child.as()); + panel.Children().InsertAt(static_cast(index), child.as()); } void RootViewManager::RemoveAllChildren(const XamlView &parent) { diff --git a/vnext/ReactUWP/Views/SIPEventHandler.cpp b/vnext/ReactUWP/Views/SIPEventHandler.cpp index 35d93f057f8..e8cf8d6b6b3 100644 --- a/vnext/ReactUWP/Views/SIPEventHandler.cpp +++ b/vnext/ReactUWP/Views/SIPEventHandler.cpp @@ -8,16 +8,13 @@ #include #include -#include -#include -#include namespace winrt { using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Windows::UI::ViewManagement::Core; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Media; +using namespace xaml; +using namespace xaml::Media; } // namespace winrt namespace react { namespace uwp { @@ -39,7 +36,7 @@ void SIPEventHandler::AttachView(XamlView xamlView, bool fireKeyboardEvents) { if (winrt::VisualTreeHelper::GetParent(xamlView)) { InitializeCoreInputView(); } else { - m_loadedRevoker = xamlView.as().Loaded( + m_loadedRevoker = xamlView.as().Loaded( winrt::auto_revoke, [this](const auto & /*sender*/, const auto &) { InitializeCoreInputView(); }); } } @@ -52,7 +49,7 @@ void SIPEventHandler::InitializeCoreInputView() { if (Is19H1OrHigher()) { // 19H1 and higher supports island scenarios - auto uiElement(xamlView.as()); + auto uiElement(xamlView.as()); m_coreInputView = winrt::CoreInputView::GetForUIContext(uiElement.UIContext()); } else { m_coreInputView = winrt::CoreInputView::GetForCurrentView(); diff --git a/vnext/ReactUWP/Views/SIPEventHandler.h b/vnext/ReactUWP/Views/SIPEventHandler.h index 67d9652e29f..d40a482f76c 100644 --- a/vnext/ReactUWP/Views/SIPEventHandler.h +++ b/vnext/ReactUWP/Views/SIPEventHandler.h @@ -36,7 +36,7 @@ class SIPEventHandler { winrt::Rect m_finalRect; winrt::CoreInputView m_coreInputView{nullptr}; winrt::weak_ref m_view{}; - winrt::Windows::UI::Xaml::FrameworkElement::Loaded_revoker m_loadedRevoker{}; + xaml::FrameworkElement::Loaded_revoker m_loadedRevoker{}; bool m_isShowing{false}; bool m_fireKeyboradEvents; diff --git a/vnext/ReactUWP/Views/ScrollViewManager.cpp b/vnext/ReactUWP/Views/ScrollViewManager.cpp index 679948f988c..c20009fb937 100644 --- a/vnext/ReactUWP/Views/ScrollViewManager.cpp +++ b/vnext/ReactUWP/Views/ScrollViewManager.cpp @@ -50,13 +50,13 @@ class ScrollViewShadowNode : public ShadowNodeBase { std::shared_ptr m_SIPEventHandler; - winrt::FrameworkElement::SizeChanged_revoker m_scrollViewerSizeChangedRevoker{}; - winrt::FrameworkElement::SizeChanged_revoker m_contentSizeChangedRevoker{}; + xaml::FrameworkElement::SizeChanged_revoker m_scrollViewerSizeChangedRevoker{}; + xaml::FrameworkElement::SizeChanged_revoker m_contentSizeChangedRevoker{}; winrt::ScrollViewer::ViewChanged_revoker m_scrollViewerViewChangedRevoker{}; winrt::ScrollViewer::ViewChanging_revoker m_scrollViewerViewChangingRevoker{}; winrt::ScrollViewer::DirectManipulationCompleted_revoker m_scrollViewerDirectManipulationCompletedRevoker{}; winrt::ScrollViewer::DirectManipulationStarted_revoker m_scrollViewerDirectManipulationStartedRevoker{}; - winrt::Control::Loaded_revoker m_controlLoadedRevoker{}; + xaml::Controls::Control::Loaded_revoker m_controlLoadedRevoker{}; }; ScrollViewShadowNode::ScrollViewShadowNode() {} diff --git a/vnext/ReactUWP/Views/ShadowNodeBase.cpp b/vnext/ReactUWP/Views/ShadowNodeBase.cpp index e02f1b7ce72..7a4e28e9981 100644 --- a/vnext/ReactUWP/Views/ShadowNodeBase.cpp +++ b/vnext/ReactUWP/Views/ShadowNodeBase.cpp @@ -33,9 +33,9 @@ void ShadowNodeBase::createView() { m_view = GetViewManager()->CreateView(this->m_tag); if (g_HasActualSizeProperty == TriBit::Undefined) { - if (auto uielement = m_view.try_as()) { + if (auto uielement = m_view.try_as()) { // ActualSize works on 19H1+ only - g_HasActualSizeProperty = (uielement.try_as()) ? TriBit::Set : TriBit::NotSet; + g_HasActualSizeProperty = (uielement.try_as()) ? TriBit::Set : TriBit::NotSet; } } } @@ -100,9 +100,9 @@ void ShadowNodeBase::ReparentView(XamlView view) { } } -winrt::Windows::UI::Composition::CompositionPropertySet ShadowNodeBase::EnsureTransformPS() { +comp::CompositionPropertySet ShadowNodeBase::EnsureTransformPS() { if (m_transformPS == nullptr) { - m_transformPS = winrt::Window::Current().Compositor().CreatePropertySet(); + m_transformPS = xaml::Window::Current().Compositor().CreatePropertySet(); UpdateTransformPS(); } @@ -117,7 +117,7 @@ void ShadowNodeBase::UpdateTransformPS() { // First build up an ExpressionAnimation to compute the "center" property, // like so: The input to the expression is UIElement.ActualSize/2, output is // a vector3 with [cx, cy, 0]. - auto uielement = m_view.try_as(); + auto uielement = m_view.try_as(); assert(uielement != nullptr); m_transformPS = EnsureTransformPS(); m_transformPS.InsertVector3(L"center", {0, 0, 0}); @@ -135,8 +135,7 @@ void ShadowNodeBase::UpdateTransformPS() { // we will use this value in the scenario where a View changed its backing // XAML element, here we will just transfer existing value to a new backing // XAML element. - if (m_transformPS.TryGetMatrix4x4(L"transform", unused) == - winrt::Windows::UI::Composition::CompositionGetValueStatus::NotFound) { + if (m_transformPS.TryGetMatrix4x4(L"transform", unused) == comp::CompositionGetValueStatus::NotFound) { m_transformPS.InsertMatrix4x4(L"transform", winrt::Windows::Foundation::Numerics::float4x4::identity()); } } diff --git a/vnext/ReactUWP/Views/SliderViewManager.cpp b/vnext/ReactUWP/Views/SliderViewManager.cpp index 4dbb979aaa2..ba7223d67a1 100644 --- a/vnext/ReactUWP/Views/SliderViewManager.cpp +++ b/vnext/ReactUWP/Views/SliderViewManager.cpp @@ -10,10 +10,8 @@ #include -#include - namespace winrt { -using ToggleButton = Windows::UI::Xaml::Controls::Primitives::ToggleButton; +using ToggleButton = xaml::Controls::Primitives::ToggleButton; } namespace react { @@ -57,7 +55,7 @@ facebook::react::ShadowNode *SliderViewManager::createShadow() const { } XamlView SliderViewManager::CreateViewCore(int64_t /*tag*/) { - auto slider = winrt::Slider(); + auto slider = xaml::Controls::Slider(); return slider; } @@ -65,7 +63,7 @@ bool SliderViewManager::UpdateProperty( ShadowNodeBase *nodeToUpdate, const std::string &propertyName, const folly::dynamic &propertyValue) { - auto slider = nodeToUpdate->GetView().as(); + auto slider = nodeToUpdate->GetView().as(); if (slider == nullptr) return true; @@ -73,7 +71,7 @@ bool SliderViewManager::UpdateProperty( if (propertyValue.isBool()) slider.IsEnabled(!propertyValue.asBool()); else if (propertyValue.isNull()) - slider.ClearValue(winrt::Control::IsEnabledProperty()); + slider.ClearValue(xaml::Controls::Control::IsEnabledProperty()); } else if (propertyName == "value") { if (propertyValue.isNumber()) slider.Value(propertyValue.asDouble()); diff --git a/vnext/ReactUWP/Views/SwitchViewManager.cpp b/vnext/ReactUWP/Views/SwitchViewManager.cpp index e4890f0550e..e8401f38a4c 100644 --- a/vnext/ReactUWP/Views/SwitchViewManager.cpp +++ b/vnext/ReactUWP/Views/SwitchViewManager.cpp @@ -7,13 +7,12 @@ #include #include #include -#include #include "SwitchViewManager.h" namespace winrt { -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Shapes; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Shapes; } // namespace winrt namespace react { @@ -148,7 +147,7 @@ bool SwitchViewManager::UpdateProperty( if (propertyValue.isBool()) toggleSwitch.IsEnabled(!propertyValue.asBool()); else if (propertyValue.isNull()) - toggleSwitch.ClearValue(winrt::Control::IsEnabledProperty()); + toggleSwitch.ClearValue(xaml::Controls::Control::IsEnabledProperty()); } else if (propertyName == "value") { if (propertyValue.isBool()) toggleSwitch.IsOn(propertyValue.asBool()); diff --git a/vnext/ReactUWP/Views/TextInputViewManager.cpp b/vnext/ReactUWP/Views/TextInputViewManager.cpp index f8e0a739dd0..51a9c826f02 100644 --- a/vnext/ReactUWP/Views/TextInputViewManager.cpp +++ b/vnext/ReactUWP/Views/TextInputViewManager.cpp @@ -12,12 +12,12 @@ #include #include -#include +#include "CppWinRTIncludes.h" namespace winrt { -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Shapes; +using namespace xaml; +using namespace xaml::Shapes; +using namespace xaml::Media; } // namespace winrt namespace react { @@ -60,21 +60,21 @@ struct json_type_traits { } }; -static const std::unordered_map textBoxKeyboardTypeMap = { - {"default", winrt::InputScopeNameValue::Default}, - {"number-pad", winrt::InputScopeNameValue::TelephoneNumber}, - {"decimal-pad", winrt::InputScopeNameValue::Digits}, - {"email-address", winrt::InputScopeNameValue::EmailNameOrAddress}, - {"phone-pad", winrt::InputScopeNameValue::TelephoneNumber}, - {"numeric", winrt::InputScopeNameValue::Number}, - {"url", winrt::InputScopeNameValue::Url}, - {"web-search", winrt::InputScopeNameValue::Search}}; - -static const std::unordered_map passwordBoxKeyboardTypeMap = { - {"default", winrt::InputScopeNameValue::Password}, - {"numeric", winrt::InputScopeNameValue::NumericPin}}; - -static winrt::InputScopeNameValue parseKeyboardType(const folly::dynamic &val, const bool isTextBox) { +static const std::unordered_map textBoxKeyboardTypeMap = { + {"default", xaml::Input::InputScopeNameValue::Default}, + {"number-pad", xaml::Input::InputScopeNameValue::TelephoneNumber}, + {"decimal-pad", xaml::Input::InputScopeNameValue::Digits}, + {"email-address", xaml::Input::InputScopeNameValue::EmailNameOrAddress}, + {"phone-pad", xaml::Input::InputScopeNameValue::TelephoneNumber}, + {"numeric", xaml::Input::InputScopeNameValue::Number}, + {"url", xaml::Input::InputScopeNameValue::Url}, + {"web-search", xaml::Input::InputScopeNameValue::Search}}; + +static const std::unordered_map passwordBoxKeyboardTypeMap = { + {"default", xaml::Input::InputScopeNameValue::Password}, + {"numeric", xaml::Input::InputScopeNameValue::NumericPin}}; + +static xaml::Input::InputScopeNameValue parseKeyboardType(const folly::dynamic &val, const bool isTextBox) { auto keyboardTypeMap = isTextBox ? textBoxKeyboardTypeMap : passwordBoxKeyboardTypeMap; auto iter = keyboardTypeMap.find(val.asString()); @@ -83,7 +83,7 @@ static winrt::InputScopeNameValue parseKeyboardType(const folly::dynamic &val, c return iter->second; } - return isTextBox ? winrt::InputScopeNameValue::Default : winrt::InputScopeNameValue::Password; + return isTextBox ? xaml::Input::InputScopeNameValue::Default : xaml::Input::InputScopeNameValue::Password; } namespace react { @@ -105,8 +105,8 @@ class TextInputShadowNode : public ShadowNodeBase { void dispatchTextInputChangeEvent(winrt::hstring newText); void registerEvents(); void HideCaretIfNeeded(); - void setPasswordBoxPlaceholderForeground(winrt::PasswordBox passwordBox, folly::dynamic color); - winrt::Shape FindCaret(winrt::DependencyObject element); + void setPasswordBoxPlaceholderForeground(xaml::Controls::PasswordBox passwordBox, folly::dynamic color); + winrt::Shape FindCaret(xaml::DependencyObject element); bool m_shouldClearTextOnFocus = false; bool m_shouldSelectTextOnFocus = false; @@ -123,22 +123,22 @@ class TextInputShadowNode : public ShadowNodeBase { uint32_t m_mostRecentEventCount{0}; // EventCount from javascript private: - winrt::TextBox::TextChanging_revoker m_textBoxTextChangingRevoker{}; - winrt::TextBox::TextChanged_revoker m_textBoxTextChangedRevoker{}; - winrt::TextBox::SelectionChanged_revoker m_textBoxSelectionChangedRevoker{}; - winrt::TextBox::ContextMenuOpening_revoker m_textBoxContextMenuOpeningRevoker{}; - - winrt::PasswordBox::PasswordChanging_revoker m_passwordBoxPasswordChangingRevoker{}; - winrt::PasswordBox::PasswordChanged_revoker m_passwordBoxPasswordChangedRevoker{}; - winrt::PasswordBox::ContextMenuOpening_revoker m_passwordBoxContextMenuOpeningRevoker{}; - - winrt::Control::GotFocus_revoker m_controlGotFocusRevoker{}; - winrt::Control::LostFocus_revoker m_controlLostFocusRevoker{}; - winrt::Control::KeyDown_revoker m_controlKeyDownRevoker{}; - winrt::Control::SizeChanged_revoker m_controlSizeChangedRevoker{}; - winrt::Control::CharacterReceived_revoker m_controlCharacterReceivedRevoker{}; - winrt::ScrollViewer::ViewChanging_revoker m_scrollViewerViewChangingRevoker{}; - winrt::Control::Loaded_revoker m_controlLoadedRevoker{}; + xaml::Controls::TextBox::TextChanging_revoker m_textBoxTextChangingRevoker{}; + xaml::Controls::TextBox::TextChanged_revoker m_textBoxTextChangedRevoker{}; + xaml::Controls::TextBox::SelectionChanged_revoker m_textBoxSelectionChangedRevoker{}; + xaml::Controls::TextBox::ContextMenuOpening_revoker m_textBoxContextMenuOpeningRevoker{}; + + xaml::Controls::PasswordBox::PasswordChanging_revoker m_passwordBoxPasswordChangingRevoker{}; + xaml::Controls::PasswordBox::PasswordChanged_revoker m_passwordBoxPasswordChangedRevoker{}; + xaml::Controls::PasswordBox::ContextMenuOpening_revoker m_passwordBoxContextMenuOpeningRevoker{}; + + xaml::Controls::Control::GotFocus_revoker m_controlGotFocusRevoker{}; + xaml::Controls::Control::LostFocus_revoker m_controlLostFocusRevoker{}; + xaml::Controls::Control::KeyDown_revoker m_controlKeyDownRevoker{}; + xaml::Controls::Control::SizeChanged_revoker m_controlSizeChangedRevoker{}; + xaml::Controls::Control::CharacterReceived_revoker m_controlCharacterReceivedRevoker{}; + xaml::Controls::ScrollViewer::ViewChanging_revoker m_scrollViewerViewChangingRevoker{}; + xaml::Controls::Control::Loaded_revoker m_controlLoadedRevoker{}; }; void TextInputShadowNode::createView() { @@ -158,7 +158,7 @@ void TextInputShadowNode::dispatchTextInputChangeEvent(winrt::hstring newText) { } void TextInputShadowNode::registerEvents() { - auto control = GetView().as(); + auto control = GetView().as(); auto wkinstance = GetViewManager()->GetReactInstance(); auto tag = m_tag; @@ -176,42 +176,42 @@ void TextInputShadowNode::registerEvents() { // another TextChanged event with correct event count. if (m_isTextBox) { m_passwordBoxPasswordChangingRevoker = {}; - m_textBoxTextChangingRevoker = - control.as().TextChanging(winrt::auto_revoke, [=](auto &&, auto &&) { m_nativeEventCount++; }); + m_textBoxTextChangingRevoker = control.as().TextChanging( + winrt::auto_revoke, [=](auto &&, auto &&) { m_nativeEventCount++; }); } else { m_textBoxTextChangingRevoker = {}; - if (control.try_as()) { - m_passwordBoxPasswordChangingRevoker = control.as().PasswordChanging( + if (control.try_as()) { + m_passwordBoxPasswordChangingRevoker = control.as().PasswordChanging( winrt::auto_revoke, [=](auto &&, auto &&) { m_nativeEventCount++; }); } } if (m_isTextBox) { m_passwordBoxPasswordChangedRevoker = {}; - auto textBox = control.as(); + auto textBox = control.as(); m_textBoxTextChangedRevoker = textBox.TextChanged( winrt::auto_revoke, [=](auto &&, auto &&) { dispatchTextInputChangeEvent(textBox.Text()); }); } else { m_textBoxTextChangedRevoker = {}; - auto passwordBox = control.as(); + auto passwordBox = control.as(); m_passwordBoxPasswordChangedRevoker = passwordBox.PasswordChanged( winrt::auto_revoke, [=](auto &&, auto &&) { dispatchTextInputChangeEvent(passwordBox.Password()); }); } if (m_isTextBox) { m_passwordBoxContextMenuOpeningRevoker = {}; - auto textBox = control.as(); + auto textBox = control.as(); m_textBoxContextMenuOpeningRevoker = - textBox.ContextMenuOpening(winrt::auto_revoke, [=](auto &&, winrt::ContextMenuEventArgs const &e) { + textBox.ContextMenuOpening(winrt::auto_revoke, [=](auto &&, xaml::Controls::ContextMenuEventArgs const &e) { if (m_contextMenuHidden) { e.Handled(true); } }); } else { m_textBoxContextMenuOpeningRevoker = {}; - auto passwordBox = control.as(); + auto passwordBox = control.as(); m_passwordBoxContextMenuOpeningRevoker = - passwordBox.ContextMenuOpening(winrt::auto_revoke, [=](auto &&, winrt::ContextMenuEventArgs const &e) { + passwordBox.ContextMenuOpening(winrt::auto_revoke, [=](auto &&, xaml::Controls::ContextMenuEventArgs const &e) { if (m_contextMenuHidden) { e.Handled(true); } @@ -221,17 +221,17 @@ void TextInputShadowNode::registerEvents() { m_controlGotFocusRevoker = control.GotFocus(winrt::auto_revoke, [=](auto &&, auto &&) { if (m_shouldClearTextOnFocus) { if (m_isTextBox) { - control.as().ClearValue(winrt::TextBox::TextProperty()); + control.as().ClearValue(xaml::Controls::TextBox::TextProperty()); } else { - control.as().ClearValue(winrt::PasswordBox::PasswordProperty()); + control.as().ClearValue(xaml::Controls::PasswordBox::PasswordProperty()); } } if (m_shouldSelectTextOnFocus) { if (m_isTextBox) { - control.as().SelectAll(); + control.as().SelectAll(); } else { - control.as().SelectAll(); + control.as().SelectAll(); } } HideCaretIfNeeded(); @@ -248,10 +248,10 @@ void TextInputShadowNode::registerEvents() { folly::dynamic eventDataEndEditing = {}; if (m_isTextBox) { eventDataEndEditing = - folly::dynamic::object("target", tag)("text", HstringToDynamic(control.as().Text())); + folly::dynamic::object("target", tag)("text", HstringToDynamic(control.as().Text())); } else { - eventDataEndEditing = - folly::dynamic::object("target", tag)("text", HstringToDynamic(control.as().Password())); + eventDataEndEditing = folly::dynamic::object("target", tag)( + "text", HstringToDynamic(control.as().Password())); } if (!m_updating && instance != nullptr) { instance->DispatchEvent(tag, "topTextInputBlur", std::move(eventDataBlur)); @@ -259,24 +259,25 @@ void TextInputShadowNode::registerEvents() { } }); - m_controlKeyDownRevoker = control.KeyDown(winrt::auto_revoke, [=](auto &&, winrt::KeyRoutedEventArgs const &args) { - if (args.Key() == winrt::VirtualKey::Enter && !args.Handled()) { - if (auto instance = wkinstance.lock()) { - folly::dynamic eventDataSubmitEditing = {}; - if (m_isTextBox) { - eventDataSubmitEditing = - folly::dynamic::object("target", tag)("text", HstringToDynamic(control.as().Text())); - } else { - eventDataSubmitEditing = folly::dynamic::object("target", tag)( - "text", HstringToDynamic(control.as().Password())); + m_controlKeyDownRevoker = + control.KeyDown(winrt::auto_revoke, [=](auto &&, xaml::Input::KeyRoutedEventArgs const &args) { + if (args.Key() == winrt::Windows::System::VirtualKey::Enter && !args.Handled()) { + if (auto instance = wkinstance.lock()) { + folly::dynamic eventDataSubmitEditing = {}; + if (m_isTextBox) { + eventDataSubmitEditing = folly::dynamic::object("target", tag)( + "text", HstringToDynamic(control.as().Text())); + } else { + eventDataSubmitEditing = folly::dynamic::object("target", tag)( + "text", HstringToDynamic(control.as().Password())); + } + instance->DispatchEvent(tag, "topTextInputSubmitEditing", std::move(eventDataSubmitEditing)); + } } - instance->DispatchEvent(tag, "topTextInputSubmitEditing", std::move(eventDataSubmitEditing)); - } - } - }); + }); if (m_isTextBox) { - auto textBox = control.as(); + auto textBox = control.as(); m_textBoxSelectionChangedRevoker = textBox.SelectionChanged(winrt::auto_revoke, [=](auto &&, auto &&) { auto instance = wkinstance.lock(); folly::dynamic selectionData = folly::dynamic::object("start", textBox.SelectionStart())( @@ -290,7 +291,7 @@ void TextInputShadowNode::registerEvents() { m_controlSizeChangedRevoker = control.SizeChanged(winrt::auto_revoke, [=](auto &&, winrt::SizeChangedEventArgs const &args) { if (m_isTextBox) { - if (control.as().TextWrapping() == winrt::TextWrapping::Wrap) { + if (control.as().TextWrapping() == xaml::TextWrapping::Wrap) { auto instance = wkinstance.lock(); folly::dynamic contentSizeData = folly::dynamic::object("width", args.NewSize().Width)("height", args.NewSize().Height); @@ -302,10 +303,10 @@ void TextInputShadowNode::registerEvents() { }); m_controlLoadedRevoker = control.Loaded(winrt::auto_revoke, [=](auto &&, auto &&) { - auto textBoxView = control.GetTemplateChild(asHstring("ContentElement")).as(); + auto textBoxView = control.GetTemplateChild(asHstring("ContentElement")).as(); if (textBoxView) { m_scrollViewerViewChangingRevoker = textBoxView.ViewChanging( - winrt::auto_revoke, [=](auto &&, winrt::ScrollViewerViewChangingEventArgs const &args) { + winrt::auto_revoke, [=](auto &&, xaml::Controls::ScrollViewerViewChangingEventArgs const &args) { auto instance = wkinstance.lock(); if (!m_updating && instance != nullptr) { folly::dynamic offsetData = folly::dynamic::object("x", args.FinalView().HorizontalOffset())( @@ -318,9 +319,9 @@ void TextInputShadowNode::registerEvents() { HideCaretIfNeeded(); }); - if (control.try_as()) { + if (control.try_as()) { m_controlCharacterReceivedRevoker = control.CharacterReceived( - winrt::auto_revoke, [=](auto &&, winrt::CharacterReceivedRoutedEventArgs const &args) { + winrt::auto_revoke, [=](auto &&, xaml::Input::CharacterReceivedRoutedEventArgs const &args) { auto instance = wkinstance.lock(); std::string key; wchar_t s[2] = L" "; @@ -341,7 +342,7 @@ void TextInputShadowNode::registerEvents() { } } -winrt::Shape TextInputShadowNode::FindCaret(winrt::DependencyObject element) { +xaml::Shapes::Shape TextInputShadowNode::FindCaret(xaml::DependencyObject element) { if (element == nullptr) return nullptr; @@ -361,23 +362,25 @@ winrt::Shape TextInputShadowNode::FindCaret(winrt::DependencyObject element) { // hacking solution to hide the caret void TextInputShadowNode::HideCaretIfNeeded() { if (m_hideCaret) { - auto control = GetView().as(); + auto control = GetView().as(); if (auto caret = FindCaret(control)) { - caret.CompositeMode(winrt::Windows::UI::Xaml::Media::ElementCompositeMode::Inherit); - winrt::SolidColorBrush transparentColor(winrt::Colors::Transparent()); + caret.CompositeMode(xaml::Media::ElementCompositeMode::Inherit); + xaml::Media::SolidColorBrush transparentColor(winrt::Windows::UI::Colors::Transparent()); caret.Fill(transparentColor); } } } -void TextInputShadowNode::setPasswordBoxPlaceholderForeground(winrt::PasswordBox passwordBox, folly::dynamic color) { +void TextInputShadowNode::setPasswordBoxPlaceholderForeground( + xaml::Controls::PasswordBox passwordBox, + folly::dynamic color) { m_placeholderTextColor = color; - auto defaultRD = winrt::Windows::UI::Xaml::ResourceDictionary(); + auto defaultRD = xaml::ResourceDictionary(); auto solidColorBrush = ColorFrom(color); defaultRD.Insert(winrt::box_value(L"TextControlPlaceholderForeground"), winrt::box_value(solidColorBrush)); defaultRD.Insert(winrt::box_value(L"TextControlPlaceholderForegroundFocused"), winrt::box_value(solidColorBrush)); defaultRD.Insert(winrt::box_value(L"TextControlPlaceholderForegroundPointerOver"), winrt::box_value(solidColorBrush)); - auto passwordBoxResource = winrt::Windows::UI::Xaml::ResourceDictionary(); + auto passwordBoxResource = xaml::ResourceDictionary(); auto themeDictionaries = passwordBoxResource.ThemeDictionaries(); themeDictionaries.Insert(winrt::box_value(L"Default"), defaultRD); passwordBoxResource.Insert(winrt::box_value(L"ThemeDictionaries"), themeDictionaries); @@ -386,9 +389,9 @@ void TextInputShadowNode::setPasswordBoxPlaceholderForeground(winrt::PasswordBox void TextInputShadowNode::updateProperties(const folly::dynamic &&props) { m_updating = true; - auto control = GetView().as(); - auto textBox = control.try_as(); - auto passwordBox = control.try_as(); + auto control = GetView().as(); + auto textBox = control.try_as(); + auto passwordBox = control.try_as(); for (auto &pair : props.items()) { const std::string &propertyName = pair.first.getString(); @@ -403,7 +406,7 @@ void TextInputShadowNode::updateProperties(const folly::dynamic &&props) { if (propertyValue.isBool()) control.IsTextScaleFactorEnabled(propertyValue.asBool()); else if (propertyValue.isNull()) - control.ClearValue(winrt::Control::IsTextScaleFactorEnabledProperty()); + control.ClearValue(xaml::Controls::Control::IsTextScaleFactorEnabledProperty()); } else if (propertyName == "clearTextOnFocus") { if (propertyValue.isBool()) m_shouldClearTextOnFocus = propertyValue.asBool(); @@ -426,11 +429,11 @@ void TextInputShadowNode::updateProperties(const folly::dynamic &&props) { if (propertyValue.isBool()) { if (propertyValue.asBool()) { if (m_isTextBox) { - winrt::PasswordBox newPasswordBox; + xaml::Controls::PasswordBox newPasswordBox; ReparentView(newPasswordBox); m_isTextBox = false; registerEvents(); - control = newPasswordBox.as(); + control = newPasswordBox.as(); passwordBox = newPasswordBox; if (!m_placeholderTextColor.isNull()) { setPasswordBoxPlaceholderForeground(newPasswordBox, m_placeholderTextColor); @@ -438,11 +441,11 @@ void TextInputShadowNode::updateProperties(const folly::dynamic &&props) { } } else { if (!m_isTextBox) { - winrt::TextBox newTextBox; + xaml::Controls::TextBox newTextBox; ReparentView(newTextBox); m_isTextBox = true; registerEvents(); - control = newTextBox.as(); + control = newTextBox.as(); textBox = newTextBox; if (!m_placeholderTextColor.isNull()) { textBox.PlaceholderForeground(SolidColorBrushFrom(m_placeholderTextColor)); @@ -453,50 +456,58 @@ void TextInputShadowNode::updateProperties(const folly::dynamic &&props) { } else if (propertyName == "maxLength") { if (propertyValue.isNumber()) { control.SetValue( - m_isTextBox ? winrt::TextBox::MaxLengthProperty() : winrt::PasswordBox::MaxLengthProperty(), + m_isTextBox ? xaml::Controls::TextBox::MaxLengthProperty() + : xaml::Controls::PasswordBox::MaxLengthProperty(), winrt::PropertyValue::CreateInt32(static_cast(propertyValue.asDouble()))); } else if (propertyValue.isNull()) { - control.ClearValue(m_isTextBox ? winrt::TextBox::MaxLengthProperty() : winrt::PasswordBox::MaxLengthProperty()); + control.ClearValue( + m_isTextBox ? xaml::Controls::TextBox::MaxLengthProperty() + : xaml::Controls::PasswordBox::MaxLengthProperty()); } } else if (propertyName == "placeholder") { if (propertyValue.isString()) { control.SetValue( - m_isTextBox ? winrt::TextBox::PlaceholderTextProperty() : winrt::PasswordBox::PlaceholderTextProperty(), + m_isTextBox ? xaml::Controls::TextBox::PlaceholderTextProperty() + : xaml::Controls::PasswordBox::PlaceholderTextProperty(), winrt::PropertyValue::CreateString(asHstring(propertyValue))); } else if (propertyValue.isNull()) { control.ClearValue( - m_isTextBox ? winrt::TextBox::PlaceholderTextProperty() : winrt::PasswordBox::PlaceholderTextProperty()); + m_isTextBox ? xaml::Controls::TextBox::PlaceholderTextProperty() + : xaml::Controls::PasswordBox::PlaceholderTextProperty()); } } else if (propertyName == "selectionColor") { if (IsValidColorValue(propertyValue)) { control.SetValue( - m_isTextBox ? winrt::TextBox::SelectionHighlightColorProperty() - : winrt::PasswordBox::SelectionHighlightColorProperty(), + m_isTextBox ? xaml::Controls::TextBox::SelectionHighlightColorProperty() + : xaml::Controls::PasswordBox::SelectionHighlightColorProperty(), SolidColorBrushFrom(propertyValue)); } else if (propertyValue.isNull()) control.ClearValue( - m_isTextBox ? winrt::TextBox::SelectionHighlightColorProperty() - : winrt::PasswordBox::SelectionHighlightColorProperty()); + m_isTextBox ? xaml::Controls::TextBox::SelectionHighlightColorProperty() + : xaml::Controls::PasswordBox::SelectionHighlightColorProperty()); } else if (propertyName == "keyboardType") { if (propertyValue.isString()) { auto inputScopeNameVaue = parseKeyboardType(propertyValue, m_isTextBox); - auto scope = winrt::InputScope(); - auto scopeName = winrt::InputScopeName(inputScopeNameVaue); + auto scope = xaml::Input::InputScope(); + auto scopeName = xaml::Input::InputScopeName(inputScopeNameVaue); auto names = scope.Names(); names.Append(scopeName); control.SetValue( - m_isTextBox ? winrt::TextBox::InputScopeProperty() : winrt::PasswordBox::InputScopeProperty(), scope); + m_isTextBox ? xaml::Controls::TextBox::InputScopeProperty() + : xaml::Controls::PasswordBox::InputScopeProperty(), + scope); } else if (propertyValue.isNull()) control.ClearValue( - m_isTextBox ? winrt::TextBox::InputScopeProperty() : winrt::PasswordBox::InputScopeProperty()); + m_isTextBox ? xaml::Controls::TextBox::InputScopeProperty() + : xaml::Controls::PasswordBox::InputScopeProperty()); } else if (propertyName == "placeholderTextColor") { m_placeholderTextColor = nullptr; - if (textBox.try_as() && m_isTextBox) { + if (textBox.try_as() && m_isTextBox) { if (IsValidColorValue(propertyValue)) { m_placeholderTextColor = propertyValue; textBox.PlaceholderForeground(SolidColorBrushFrom(propertyValue)); } else if (propertyValue.isNull()) - textBox.ClearValue(winrt::TextBox::PlaceholderForegroundProperty()); + textBox.ClearValue(xaml::Controls::TextBox::PlaceholderForegroundProperty()); } else if (m_isTextBox != true && IsValidColorValue(propertyValue)) { setPasswordBoxPlaceholderForeground(passwordBox, propertyValue); } @@ -507,20 +518,21 @@ void TextInputShadowNode::updateProperties(const folly::dynamic &&props) { } else if (propertyName == "multiline") { if (propertyValue.isBool()) { const bool isMultiline = propertyValue.asBool(); - textBox.TextWrapping(isMultiline ? winrt::TextWrapping::Wrap : winrt::TextWrapping::NoWrap); + textBox.TextWrapping(isMultiline ? xaml::TextWrapping::Wrap : xaml::TextWrapping::NoWrap); textBox.AcceptsReturn(isMultiline); } else if (propertyValue.isNull()) - textBox.ClearValue(winrt::TextBox::TextWrappingProperty()); + textBox.ClearValue(xaml::Controls::TextBox::TextWrappingProperty()); } else if (propertyName == "editable") { if (propertyValue.isBool()) textBox.IsReadOnly(!propertyValue.asBool()); else if (propertyValue.isNull()) - textBox.ClearValue(winrt::TextBox::IsReadOnlyProperty()); + textBox.ClearValue(xaml::Controls::TextBox::IsReadOnlyProperty()); } else if (propertyName == "scrollEnabled") { - if (propertyValue.isBool() && textBox.TextWrapping() == winrt::TextWrapping::Wrap) { - auto scrollMode = propertyValue.asBool() ? winrt::ScrollMode::Auto : winrt::ScrollMode::Disabled; - winrt::ScrollViewer::SetVerticalScrollMode(textBox, scrollMode); - winrt::ScrollViewer::SetHorizontalScrollMode(textBox, scrollMode); + if (propertyValue.isBool() && textBox.TextWrapping() == xaml::TextWrapping::Wrap) { + auto scrollMode = + propertyValue.asBool() ? xaml::Controls::ScrollMode::Auto : xaml::Controls::ScrollMode::Disabled; + xaml::Controls::ScrollViewer::SetVerticalScrollMode(textBox, scrollMode); + xaml::Controls::ScrollViewer::SetHorizontalScrollMode(textBox, scrollMode); } } else if (propertyName == "selection") { if (propertyValue.isObject()) { @@ -533,7 +545,7 @@ void TextInputShadowNode::updateProperties(const folly::dynamic &&props) { if (propertyValue.isBool()) textBox.IsSpellCheckEnabled(propertyValue.asBool()); else if (propertyValue.isNull()) - textBox.ClearValue(winrt::TextBox::IsSpellCheckEnabledProperty()); + textBox.ClearValue(xaml::Controls::TextBox::IsSpellCheckEnabledProperty()); } else if (propertyName == "text") { if (m_mostRecentEventCount == m_nativeEventCount) { if (propertyValue.isString()) { @@ -543,19 +555,19 @@ void TextInputShadowNode::updateProperties(const folly::dynamic &&props) { textBox.Text(newValue); } } else if (propertyValue.isNull()) - textBox.ClearValue(winrt::TextBox::TextProperty()); + textBox.ClearValue(xaml::Controls::TextBox::TextProperty()); } } else if (propertyName == "autoCapitalize") { - if (textBox.try_as()) { + if (textBox.try_as()) { if (propertyValue.isString()) { if (propertyValue.asString() == "characters") { - textBox.CharacterCasing(winrt::CharacterCasing::Upper); + textBox.CharacterCasing(xaml::Controls::CharacterCasing::Upper); } else { // anything else turns off autoCap (should be "None" but // we don't support "words"/"senetences" yet) - textBox.CharacterCasing(winrt::CharacterCasing::Normal); + textBox.CharacterCasing(xaml::Controls::CharacterCasing::Normal); } } else if (propertyValue.isNull()) - textBox.ClearValue(winrt::TextBox::CharacterCasingProperty()); + textBox.ClearValue(xaml::Controls::TextBox::CharacterCasingProperty()); } } } else { // Applicable properties for PasswordBox @@ -568,7 +580,7 @@ void TextInputShadowNode::updateProperties(const folly::dynamic &&props) { passwordBox.Password(newValue); } } else if (propertyValue.isNull()) - passwordBox.ClearValue(winrt::PasswordBox::PasswordProperty()); + passwordBox.ClearValue(xaml::Controls::PasswordBox::PasswordProperty()); } } } @@ -619,7 +631,7 @@ facebook::react::ShadowNode *TextInputViewManager::createShadow() const { } XamlView TextInputViewManager::CreateViewCore(int64_t /*tag*/) { - winrt::TextBox textBox; + xaml::Controls::TextBox textBox; textBox.TabIndex(0); return textBox; } @@ -635,66 +647,83 @@ void TextInputViewManager::TransferInputScope( // transfer input scope, only common keyboardType between secureTextEntry // on/off is numeric, so only need to transfer input scope "Number" <=> // "NumericPin", everything else leave it as default. - winrt::InputScope inputScope; + xaml::Input::InputScope inputScope; if (copyToPasswordBox) { - inputScope = oldView.try_as().InputScope(); + inputScope = oldView.try_as().InputScope(); } else { - inputScope = oldView.try_as().InputScope(); + inputScope = oldView.try_as().InputScope(); } if (inputScope != nullptr) { auto nameValue = inputScope.Names().GetAt(0).NameValue(); - if ((nameValue == winrt::InputScopeNameValue::Number && copyToPasswordBox) || - (nameValue == winrt::InputScopeNameValue::NumericPin && !copyToPasswordBox)) { - auto newScope = winrt::InputScope(); - auto scopeName = winrt::InputScopeName( - copyToPasswordBox ? winrt::InputScopeNameValue::NumericPin : winrt::InputScopeNameValue::Number); + if ((nameValue == xaml::Input::InputScopeNameValue::Number && copyToPasswordBox) || + (nameValue == xaml::Input::InputScopeNameValue::NumericPin && !copyToPasswordBox)) { + auto newScope = xaml::Input::InputScope(); + auto scopeName = xaml::Input::InputScopeName( + copyToPasswordBox ? xaml::Input::InputScopeNameValue::NumericPin : xaml::Input::InputScopeNameValue::Number); auto names = newScope.Names(); names.Append(scopeName); newView.SetValue( - copyToPasswordBox ? winrt::PasswordBox::InputScopeProperty() : winrt::TextBox::InputScopeProperty(), + copyToPasswordBox ? xaml::Controls::PasswordBox::InputScopeProperty() + : xaml::Controls::TextBox::InputScopeProperty(), newScope); } } } void TextInputViewManager::TransferProperties(const XamlView &oldView, const XamlView &newView) { - if ((oldView.try_as() != nullptr && newView.try_as() != nullptr) || - (oldView.try_as() != nullptr && newView.try_as() != nullptr)) { - bool copyToPasswordBox = oldView.try_as() != nullptr; + if ((oldView.try_as() != nullptr && + newView.try_as() != nullptr) || + (oldView.try_as() != nullptr && + newView.try_as() != nullptr)) { + bool copyToPasswordBox = oldView.try_as() != nullptr; // sync common properties between TextBox and PasswordBox if (copyToPasswordBox) { - TransferProperty(oldView, newView, winrt::TextBox::MaxLengthProperty(), winrt::PasswordBox::MaxLengthProperty()); TransferProperty( - oldView, newView, winrt::TextBox::PlaceholderTextProperty(), winrt::PasswordBox::PlaceholderTextProperty()); + oldView, + newView, + xaml::Controls::TextBox::MaxLengthProperty(), + xaml::Controls::PasswordBox::MaxLengthProperty()); TransferProperty( oldView, newView, - winrt::TextBox::SelectionHighlightColorProperty(), - winrt::PasswordBox::SelectionHighlightColorProperty()); - newView.as().Password(oldView.as().Text()); + xaml::Controls::TextBox::PlaceholderTextProperty(), + xaml::Controls::PasswordBox::PlaceholderTextProperty()); + TransferProperty( + oldView, + newView, + xaml::Controls::TextBox::SelectionHighlightColorProperty(), + xaml::Controls::PasswordBox::SelectionHighlightColorProperty()); + newView.as().Password(oldView.as().Text()); } else { - TransferProperty(oldView, newView, winrt::PasswordBox::MaxLengthProperty(), winrt::TextBox::MaxLengthProperty()); TransferProperty( - oldView, newView, winrt::PasswordBox::PlaceholderTextProperty(), winrt::TextBox::PlaceholderTextProperty()); + oldView, + newView, + xaml::Controls::PasswordBox::MaxLengthProperty(), + xaml::Controls::TextBox::MaxLengthProperty()); + TransferProperty( + oldView, + newView, + xaml::Controls::PasswordBox::PlaceholderTextProperty(), + xaml::Controls::TextBox::PlaceholderTextProperty()); TransferProperty( oldView, newView, - winrt::PasswordBox::SelectionHighlightColorProperty(), - winrt::TextBox::SelectionHighlightColorProperty()); - newView.as().Text(oldView.as().Password()); + xaml::Controls::PasswordBox::SelectionHighlightColorProperty(), + xaml::Controls::TextBox::SelectionHighlightColorProperty()); + newView.as().Text(oldView.as().Password()); } TransferInputScope(oldView, newView, copyToPasswordBox); // Set focus if current control has focus - auto focusState = oldView.as().FocusState(); + auto focusState = oldView.as().FocusState(); if (focusState != winrt::FocusState::Unfocused) { - newView.as().Focus(focusState); + newView.as().Focus(focusState); } } Super::TransferProperties(oldView, newView); } } // namespace uwp -} // namespace react \ No newline at end of file +} // namespace react diff --git a/vnext/ReactUWP/Views/TextViewManager.cpp b/vnext/ReactUWP/Views/TextViewManager.cpp index 83e232e23db..7f286249ede 100644 --- a/vnext/ReactUWP/Views/TextViewManager.cpp +++ b/vnext/ReactUWP/Views/TextViewManager.cpp @@ -5,20 +5,15 @@ #include "TextViewManager.h" -#include -#include - #include #include #include -#include - namespace winrt { -using namespace Windows::UI::Xaml::Documents; -using namespace Windows::UI::Xaml::Automation; -using namespace Windows::UI::Xaml::Automation::Peers; +using namespace xaml::Documents; +using namespace xaml::Automation; +using namespace xaml::Automation::Peers; } // namespace winrt namespace react { @@ -43,13 +38,13 @@ class TextShadowNode : public ShadowNodeBase { auto run = static_cast(child).GetView().try_as(); if (run != nullptr) { m_firstChildNode = &child; - auto textBlock = this->GetView().as(); + auto textBlock = this->GetView().as(); textBlock.Text(run.Text()); return; } } else if (index == 1 && m_firstChildNode != nullptr) { - auto textBlock = this->GetView().as(); - textBlock.ClearValue(winrt::TextBlock::TextProperty()); + auto textBlock = this->GetView().as(); + textBlock.ClearValue(xaml::Controls::TextBlock::TextProperty()); Super::AddView(*m_firstChildNode, 0); m_firstChildNode = nullptr; } @@ -80,8 +75,8 @@ const char *TextViewManager::GetName() const { } XamlView TextViewManager::CreateViewCore(int64_t /*tag*/) { - auto textBlock = winrt::TextBlock(); - textBlock.TextWrapping(winrt::TextWrapping::Wrap); // Default behavior in React Native + auto textBlock = xaml::Controls::TextBlock(); + textBlock.TextWrapping(xaml::TextWrapping::Wrap); // Default behavior in React Native return textBlock; } @@ -89,7 +84,7 @@ bool TextViewManager::UpdateProperty( ShadowNodeBase *nodeToUpdate, const std::string &propertyName, const folly::dynamic &propertyValue) { - auto textBlock = nodeToUpdate->GetView().as(); + auto textBlock = nodeToUpdate->GetView().as(); if (textBlock == nullptr) return true; @@ -104,38 +99,38 @@ bool TextViewManager::UpdateProperty( if (propertyValue.isNumber()) { auto numberLines = static_cast(propertyValue.asDouble()); if (numberLines == 1) { - textBlock.TextWrapping(winrt::TextWrapping::NoWrap); // setting no wrap for single line - // text for better trimming - // experience + textBlock.TextWrapping(xaml::TextWrapping::NoWrap); // setting no wrap for single line + // text for better trimming + // experience } else { - textBlock.TextWrapping(winrt::TextWrapping::Wrap); + textBlock.TextWrapping(xaml::TextWrapping::Wrap); } textBlock.MaxLines(numberLines); } else if (propertyValue.isNull()) { - textBlock.TextWrapping(winrt::TextWrapping::Wrap); // set wrapping back to default - textBlock.ClearValue(winrt::TextBlock::MaxLinesProperty()); + textBlock.TextWrapping(xaml::TextWrapping::Wrap); // set wrapping back to default + textBlock.ClearValue(xaml::Controls::TextBlock::MaxLinesProperty()); } } else if (propertyName == "lineHeight") { if (propertyValue.isNumber()) textBlock.LineHeight(static_cast(propertyValue.asDouble())); else if (propertyValue.isNull()) - textBlock.ClearValue(winrt::TextBlock::LineHeightProperty()); + textBlock.ClearValue(xaml::Controls::TextBlock::LineHeightProperty()); } else if (propertyName == "selectable") { if (propertyValue.isBool()) textBlock.IsTextSelectionEnabled(propertyValue.asBool()); else if (propertyValue.isNull()) - textBlock.ClearValue(winrt::TextBlock::IsTextSelectionEnabledProperty()); + textBlock.ClearValue(xaml::Controls::TextBlock::IsTextSelectionEnabledProperty()); } else if (propertyName == "allowFontScaling") { if (propertyValue.isBool()) { textBlock.IsTextScaleFactorEnabled(propertyValue.asBool()); } else { - textBlock.ClearValue(winrt::TextBlock::IsTextScaleFactorEnabledProperty()); + textBlock.ClearValue(xaml::Controls::TextBlock::IsTextScaleFactorEnabledProperty()); } } else if (propertyName == "selectionColor") { if (IsValidColorValue(propertyValue)) { textBlock.SelectionHighlightColor(SolidColorBrushFrom(propertyValue)); } else - textBlock.ClearValue(winrt::TextBlock::SelectionHighlightColorProperty()); + textBlock.ClearValue(xaml::Controls::TextBlock::SelectionHighlightColorProperty()); } else { return Super::UpdateProperty(nodeToUpdate, propertyName, propertyValue); } @@ -143,18 +138,18 @@ bool TextViewManager::UpdateProperty( } void TextViewManager::AddView(const XamlView &parent, const XamlView &child, int64_t index) { - auto textBlock(parent.as()); + auto textBlock(parent.as()); auto childInline(child.as()); textBlock.Inlines().InsertAt(static_cast(index), childInline); } void TextViewManager::RemoveAllChildren(const XamlView &parent) { - auto textBlock(parent.as()); + auto textBlock(parent.as()); textBlock.Inlines().Clear(); } void TextViewManager::RemoveChildAt(const XamlView &parent, int64_t index) { - auto textBlock(parent.as()); + auto textBlock(parent.as()); return textBlock.Inlines().RemoveAt(static_cast(index)); } @@ -163,14 +158,14 @@ YGMeasureFunc TextViewManager::GetYogaCustomMeasureFunc() const { } void TextViewManager::OnDescendantTextPropertyChanged(ShadowNodeBase *node) { - if (auto element = node->GetView().try_as()) { + if (auto element = node->GetView().try_as()) { // If name is set, it's controlled by accessibilityLabel, and it's already // handled in FrameworkElementViewManager. Here it only handles when name is // not set. - if (winrt::AutomationProperties::GetLiveSetting(element) != winrt::AutomationLiveSetting::Off && - winrt::AutomationProperties::GetName(element).empty() && - winrt::AutomationProperties::GetAccessibilityView(element) != winrt::Peers::AccessibilityView::Raw) { - if (auto peer = winrt::FrameworkElementAutomationPeer::FromElement(element)) { + if (xaml::Automation::AutomationProperties::GetLiveSetting(element) != winrt::AutomationLiveSetting::Off && + xaml::Automation::AutomationProperties::GetName(element).empty() && + xaml::Automation::AutomationProperties::GetAccessibilityView(element) != winrt::Peers::AccessibilityView::Raw) { + if (auto peer = xaml::Automation::Peers::FrameworkElementAutomationPeer::FromElement(element)) { peer.RaiseAutomationEvent(winrt::AutomationEvents::LiveRegionChanged); } } diff --git a/vnext/ReactUWP/Views/TouchEventHandler.cpp b/vnext/ReactUWP/Views/TouchEventHandler.cpp index d08300864ca..4a345e8f901 100644 --- a/vnext/ReactUWP/Views/TouchEventHandler.cpp +++ b/vnext/ReactUWP/Views/TouchEventHandler.cpp @@ -14,10 +14,6 @@ #include #include #include -#include -#include -#include -#include namespace react { namespace uwp { @@ -30,7 +26,7 @@ TouchEventHandler::~TouchEventHandler() { } void TouchEventHandler::AddTouchHandlers(XamlView xamlView) { - auto uiElement(xamlView.as()); + auto uiElement(xamlView.as()); if (uiElement == nullptr) { assert(false); return; @@ -74,7 +70,7 @@ void TouchEventHandler::OnPointerPressed( // Only if the view has a Tag can we process this int64_t tag; - winrt::FrameworkElement sourceElement(nullptr); + xaml::FrameworkElement sourceElement(nullptr); if (!TagFromOriginalSource(args, &tag, &sourceElement)) return; @@ -85,7 +81,7 @@ void TouchEventHandler::OnPointerPressed( return; } - if (m_xamlView.as().CapturePointer(args.Pointer())) { + if (m_xamlView.as().CapturePointer(args.Pointer())) { // Pointer pressing updates the enter/leave state UpdatePointersInViews(args, tag, sourceElement); @@ -128,7 +124,7 @@ void TouchEventHandler::OnPointerMoved( // Only if the view has a Tag can we process this int64_t tag; - winrt::FrameworkElement sourceElement(nullptr); + xaml::FrameworkElement sourceElement(nullptr); if (!TagFromOriginalSource(args, &tag, &sourceElement)) return; @@ -158,7 +154,7 @@ void TouchEventHandler::OnPointerConcluded(TouchEventType eventType, const winrt // if the view has a Tag, update the pointer info. // Regardless of that, ensure we Dispatch & cleanup the pointer int64_t tag; - winrt::FrameworkElement sourceElement(nullptr); + xaml::FrameworkElement sourceElement(nullptr); if (TagFromOriginalSource(args, &tag, &sourceElement)) UpdateReactPointer(m_pointers[pointerIndex], args, sourceElement); @@ -168,13 +164,13 @@ void TouchEventHandler::OnPointerConcluded(TouchEventType eventType, const winrt if (m_pointers.size() == 0) m_touchId = 0; - m_xamlView.as().ReleasePointerCapture(args.Pointer()); + m_xamlView.as().ReleasePointerCapture(args.Pointer()); } size_t TouchEventHandler::AddReactPointer( const winrt::PointerRoutedEventArgs &args, int64_t tag, - winrt::FrameworkElement sourceElement) { + xaml::FrameworkElement sourceElement) { ReactPointer pointer = CreateReactPointer(args, tag, sourceElement); m_pointers.emplace_back(std::move(pointer)); return m_pointers.size() - 1; @@ -183,7 +179,7 @@ size_t TouchEventHandler::AddReactPointer( TouchEventHandler::ReactPointer TouchEventHandler::CreateReactPointer( const winrt::PointerRoutedEventArgs &args, int64_t tag, - winrt::FrameworkElement sourceElement) { + xaml::FrameworkElement sourceElement) { auto point = args.GetCurrentPoint(sourceElement); ReactPointer pointer; @@ -204,8 +200,8 @@ TouchEventHandler::ReactPointer TouchEventHandler::CreateReactPointer( void TouchEventHandler::UpdateReactPointer( ReactPointer &pointer, const winrt::PointerRoutedEventArgs &args, - winrt::FrameworkElement sourceElement) { - auto rootPoint = args.GetCurrentPoint(m_xamlView.as()); + xaml::FrameworkElement sourceElement) { + auto rootPoint = args.GetCurrentPoint(m_xamlView.as()); auto point = args.GetCurrentPoint(sourceElement); pointer.positionRoot = rootPoint.Position(); @@ -236,7 +232,7 @@ std::optional TouchEventHandler::IndexOfPointerWithId(uint32_t pointerId void TouchEventHandler::UpdatePointersInViews( const winrt::PointerRoutedEventArgs &args, int64_t tag, - winrt::FrameworkElement sourceElement) { + xaml::FrameworkElement sourceElement) { auto instance = m_wkReactInstance.lock(); if (!instance || instance->IsInError()) return; @@ -289,7 +285,7 @@ void TouchEventHandler::UpdatePointersInViews( void TouchEventHandler::SendPointerMove( const winrt::PointerRoutedEventArgs &args, int64_t tag, - winrt::FrameworkElement sourceElement) { + xaml::FrameworkElement sourceElement) { auto instance = m_wkReactInstance.lock(); auto nativeUiManager = static_cast(instance->NativeUIManager()); facebook::react::INativeUIManagerHost *puiManagerHost = nativeUiManager->getHost(); @@ -302,7 +298,7 @@ void TouchEventHandler::SendPointerMove( } if (node == nullptr || !node->m_onMouseMove) return; - sourceElement = node->GetView().try_as(); + sourceElement = node->GetView().try_as(); if (sourceElement == nullptr) return; @@ -402,20 +398,20 @@ const char *TouchEventHandler::GetTouchEventTypeName(TouchEventType eventType) n bool TouchEventHandler::TagFromOriginalSource( const winrt::PointerRoutedEventArgs &args, int64_t *pTag, - winrt::FrameworkElement *pSourceElement) { + xaml::FrameworkElement *pSourceElement) { assert(pTag != nullptr); if (args.OriginalSource() == nullptr) return false; - auto sourceElement = args.OriginalSource().try_as(); + auto sourceElement = args.OriginalSource().try_as(); if (sourceElement == nullptr) { // TODO: Do we need to handle this for non FrameworkElement views? return false; } else { auto tag = sourceElement.Tag(); while (tag == nullptr && sourceElement && winrt::VisualTreeHelper::GetParent(sourceElement)) { - sourceElement = winrt::VisualTreeHelper::GetParent(sourceElement).try_as(); + sourceElement = winrt::VisualTreeHelper::GetParent(sourceElement).try_as(); tag = sourceElement.Tag(); } @@ -436,7 +432,7 @@ bool TouchEventHandler::TagFromOriginalSource( std::set TouchEventHandler::GetTagsAtPoint(const winrt::PointerRoutedEventArgs &e) { std::set tags; - winrt::UIElement root(m_xamlView.as()); + xaml::UIElement root(m_xamlView.as()); winrt::Point point = e.GetCurrentPoint(root).Position(); auto transform = root.TransformToVisual(nullptr); @@ -444,7 +440,7 @@ std::set TouchEventHandler::GetTagsAtPoint(const winrt::PointerRoutedEv auto elements = winrt::VisualTreeHelper::FindElementsInHostCoordinates(point, root); for (const auto &elem : elements) { - auto element = elem.try_as(); + auto element = elem.try_as(); if (element != nullptr) { auto tag = element.Tag(); if (tag != nullptr) diff --git a/vnext/ReactUWP/Views/TouchEventHandler.h b/vnext/ReactUWP/Views/TouchEventHandler.h index df26eaf2c19..c06b28cb6c8 100644 --- a/vnext/ReactUWP/Views/TouchEventHandler.h +++ b/vnext/ReactUWP/Views/TouchEventHandler.h @@ -3,8 +3,6 @@ #pragma once #include -#include -#include #include #include @@ -13,11 +11,11 @@ namespace winrt { using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Input; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Input; using namespace Windows::Foundation; -using namespace Windows::UI::Xaml::Media; +using namespace xaml::Media; } // namespace winrt namespace react { @@ -64,16 +62,16 @@ class TouchEventHandler { bool ctrlKey = false; bool altKey = false; }; - size_t AddReactPointer(const winrt::PointerRoutedEventArgs &args, int64_t tag, winrt::FrameworkElement sourceElement); + size_t AddReactPointer(const winrt::PointerRoutedEventArgs &args, int64_t tag, xaml::FrameworkElement sourceElement); ReactPointer - CreateReactPointer(const winrt::PointerRoutedEventArgs &args, int64_t tag, winrt::FrameworkElement sourceElement); + CreateReactPointer(const winrt::PointerRoutedEventArgs &args, int64_t tag, xaml::FrameworkElement sourceElement); void UpdateReactPointer( ReactPointer &pointer, const winrt::PointerRoutedEventArgs &args, - winrt::FrameworkElement sourceElement); + xaml::FrameworkElement sourceElement); void - UpdatePointersInViews(const winrt::PointerRoutedEventArgs &args, int64_t tag, winrt::FrameworkElement sourceElement); - void SendPointerMove(const winrt::PointerRoutedEventArgs &args, int64_t tag, winrt::FrameworkElement sourceElement); + UpdatePointersInViews(const winrt::PointerRoutedEventArgs &args, int64_t tag, xaml::FrameworkElement sourceElement); + void SendPointerMove(const winrt::PointerRoutedEventArgs &args, int64_t tag, xaml::FrameworkElement sourceElement); enum class TouchEventType { Start = 0, End, Move, Cancel, PointerEntered, PointerExited, PointerMove }; void OnPointerConcluded(TouchEventType eventType, const winrt::PointerRoutedEventArgs &args); @@ -91,7 +89,7 @@ class TouchEventHandler { bool TagFromOriginalSource( const winrt::PointerRoutedEventArgs &args, int64_t *pTag, - winrt::FrameworkElement *pSourceElement); + xaml::FrameworkElement *pSourceElement); std::set GetTagsAtPoint(const winrt::PointerRoutedEventArgs &e); XamlView m_xamlView; diff --git a/vnext/ReactUWP/Views/ViewControl.cpp b/vnext/ReactUWP/Views/ViewControl.cpp index d35cfba2f9c..5530dc92ce8 100644 --- a/vnext/ReactUWP/Views/ViewControl.cpp +++ b/vnext/ReactUWP/Views/ViewControl.cpp @@ -12,15 +12,15 @@ #endif namespace winrt { -using namespace Windows::UI::Xaml::Automation::Peers; -using namespace Windows::UI::Xaml; +using namespace xaml::Automation::Peers; +using namespace xaml; } // namespace winrt namespace winrt::PROJECT_ROOT_NAMESPACE::implementation { ViewControl::ViewControl() : Super() { - VerticalContentAlignment(winrt::VerticalAlignment::Stretch); - HorizontalContentAlignment(winrt::HorizontalAlignment::Stretch); + VerticalContentAlignment(xaml::VerticalAlignment::Stretch); + HorizontalContentAlignment(xaml::HorizontalAlignment::Stretch); } winrt::AutomationPeer ViewControl::OnCreateAutomationPeer() { @@ -30,7 +30,7 @@ winrt::AutomationPeer ViewControl::OnCreateAutomationPeer() { winrt::PROJECT_ROOT_NAMESPACE::ViewPanel ViewControl::GetPanel() const { auto child = Content(); - if (auto border = child.try_as()) { + if (auto border = child.try_as()) { child = border.Child(); } diff --git a/vnext/ReactUWP/Views/ViewControl.h b/vnext/ReactUWP/Views/ViewControl.h index b9ac5674789..5ef77ea138c 100644 --- a/vnext/ReactUWP/Views/ViewControl.h +++ b/vnext/ReactUWP/Views/ViewControl.h @@ -5,9 +5,6 @@ #include -#include -#include - #include "ViewControl.g.h" namespace winrt::PROJECT_ROOT_NAMESPACE::implementation { @@ -23,7 +20,7 @@ struct ViewControl : ViewControlT { // Constructors ViewControl(); - winrt::Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer(); + xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer(); winrt::PROJECT_ROOT_NAMESPACE::ViewPanel GetPanel() const; }; diff --git a/vnext/ReactUWP/Views/ViewManagerBase.cpp b/vnext/ReactUWP/Views/ViewManagerBase.cpp index 9d40b89ba6b..9723ceca252 100644 --- a/vnext/ReactUWP/Views/ViewManagerBase.cpp +++ b/vnext/ReactUWP/Views/ViewManagerBase.cpp @@ -14,13 +14,11 @@ #include #include #include -#include -#include using namespace folly; namespace winrt { -using namespace Windows::UI::Xaml; +using namespace xaml; } namespace react { @@ -48,7 +46,7 @@ YGSize DefaultYogaSelfMeasureFunc( // TODO: VEC context != nullptr, DefaultYogaSelfMeasureFunc expects a context. XamlView view = context->view; - auto element = view.as(); + auto element = view.as(); float constrainToWidth = widthMode == YGMeasureMode::YGMeasureModeUndefined ? std::numeric_limits::max() : width; @@ -59,8 +57,8 @@ YGSize DefaultYogaSelfMeasureFunc( winrt::Windows::Foundation::Size availableSpace(constrainToWidth, constrainToHeight); // Clear out current size so it doesn't constrain the measurement - auto widthProp = winrt::FrameworkElement::WidthProperty(); - auto heightProp = winrt::FrameworkElement::HeightProperty(); + auto widthProp = xaml::FrameworkElement::WidthProperty(); + auto heightProp = xaml::FrameworkElement::HeightProperty(); auto origWidth = element.GetValue(widthProp); auto origHeight = element.GetValue(heightProp); element.ClearValue(widthProp); @@ -185,7 +183,7 @@ XamlView ViewManagerBase::CreateView(int64_t tag) { // In Debug, set the element name to the tag for convienent // searching within VisualStudio's Live Visual Tree pane #ifdef DEBUG - auto element = view.try_as(); + auto element = view.try_as(); if (element) { element.Name(L": " + std::to_wstring(tag)); } @@ -321,12 +319,12 @@ void ViewManagerBase::SetLayoutProps( float top, float width, float height) { - auto element = viewToUpdate.as(); + auto element = viewToUpdate.as(); if (element == nullptr) { // TODO: Assert return; } - auto fe = element.as(); + auto fe = element.as(); // Set Position & Size Properties ViewPanel::SetLeft(element, left); diff --git a/vnext/ReactUWP/Views/ViewPanel.cpp b/vnext/ReactUWP/Views/ViewPanel.cpp index e4edc07c8cd..ea8db61a316 100644 --- a/vnext/ReactUWP/Views/ViewPanel.cpp +++ b/vnext/ReactUWP/Views/ViewPanel.cpp @@ -7,7 +7,6 @@ #include "ViewPanel.h" #include -#include // Needed for latest versions of C++/WinRT #if __has_include("ViewPanel.g.cpp") @@ -16,11 +15,11 @@ namespace winrt { using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Automation::Peers; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Interop; -using namespace Windows::UI::Xaml::Media; +using namespace xaml; +using namespace xaml::Automation::Peers; +using namespace xaml::Controls; +using namespace xaml::Interop; +using namespace xaml::Media; using namespace Windows::Foundation; } // namespace winrt @@ -36,33 +35,33 @@ winrt::AutomationPeer ViewPanel::OnCreateAutomationPeer() { } /*static*/ void ViewPanel::VisualPropertyChanged( - winrt::DependencyObject sender, - winrt::DependencyPropertyChangedEventArgs e) { + xaml::DependencyObject sender, + xaml::DependencyPropertyChangedEventArgs e) { auto panel{sender.as()}; if (panel.get() != nullptr) panel->m_propertiesChanged = true; } /*static*/ void ViewPanel::PositionPropertyChanged( - winrt::DependencyObject sender, - winrt::DependencyPropertyChangedEventArgs e) { - auto element{sender.as()}; + xaml::DependencyObject sender, + xaml::DependencyPropertyChangedEventArgs e) { + auto element{sender.as()}; if (element != nullptr) element.InvalidateArrange(); } -/*static*/ winrt::DependencyProperty ViewPanel::ViewBackgroundProperty() { - static winrt::DependencyProperty s_viewBackgroundProperty = winrt::DependencyProperty::Register( +/*static*/ xaml::DependencyProperty ViewPanel::ViewBackgroundProperty() { + static xaml::DependencyProperty s_viewBackgroundProperty = xaml::DependencyProperty::Register( L"ViewBackground", winrt::xaml_typename(), viewPanelTypeName, - winrt::PropertyMetadata(winrt::SolidColorBrush(), ViewPanel::VisualPropertyChanged)); + winrt::PropertyMetadata(xaml::Media::SolidColorBrush(), ViewPanel::VisualPropertyChanged)); return s_viewBackgroundProperty; } -/*static*/ winrt::DependencyProperty ViewPanel::BorderThicknessProperty() { - static winrt::DependencyProperty s_borderThicknessProperty = winrt::DependencyProperty::Register( +/*static*/ xaml::DependencyProperty ViewPanel::BorderThicknessProperty() { + static xaml::DependencyProperty s_borderThicknessProperty = xaml::DependencyProperty::Register( L"BorderThickness", winrt::xaml_typename(), viewPanelTypeName, @@ -71,28 +70,28 @@ winrt::AutomationPeer ViewPanel::OnCreateAutomationPeer() { return s_borderThicknessProperty; } -/*static*/ winrt::DependencyProperty ViewPanel::BorderBrushProperty() { - static winrt::DependencyProperty s_borderBrushProperty = winrt::DependencyProperty::Register( +/*static*/ xaml::DependencyProperty ViewPanel::BorderBrushProperty() { + static xaml::DependencyProperty s_borderBrushProperty = xaml::DependencyProperty::Register( L"BorderBrush", winrt::xaml_typename(), viewPanelTypeName, - winrt::PropertyMetadata(winrt::SolidColorBrush(), ViewPanel::VisualPropertyChanged)); + winrt::PropertyMetadata(xaml::Media::SolidColorBrush(), ViewPanel::VisualPropertyChanged)); return s_borderBrushProperty; } -/*static*/ winrt::DependencyProperty ViewPanel::CornerRadiusProperty() { - static winrt::DependencyProperty s_cornerRadiusProperty = winrt::DependencyProperty::Register( +/*static*/ xaml::DependencyProperty ViewPanel::CornerRadiusProperty() { + static xaml::DependencyProperty s_cornerRadiusProperty = xaml::DependencyProperty::Register( L"CornerRadius", - winrt::xaml_typename(), + winrt::xaml_typename(), viewPanelTypeName, - winrt::PropertyMetadata(winrt::box_value(winrt::CornerRadius()), ViewPanel::VisualPropertyChanged)); + winrt::PropertyMetadata(winrt::box_value(xaml::CornerRadius()), ViewPanel::VisualPropertyChanged)); return s_cornerRadiusProperty; } -/*static*/ winrt::DependencyProperty ViewPanel::TopProperty() { - static winrt::DependencyProperty s_topProperty = winrt::DependencyProperty::RegisterAttached( +/*static*/ xaml::DependencyProperty ViewPanel::TopProperty() { + static xaml::DependencyProperty s_topProperty = xaml::DependencyProperty::RegisterAttached( L"Top", winrt::xaml_typename(), viewPanelTypeName, @@ -101,8 +100,8 @@ winrt::AutomationPeer ViewPanel::OnCreateAutomationPeer() { return s_topProperty; } -/*static*/ winrt::DependencyProperty ViewPanel::LeftProperty() { - static winrt::DependencyProperty s_LeftProperty = winrt::DependencyProperty::RegisterAttached( +/*static*/ xaml::DependencyProperty ViewPanel::LeftProperty() { + static xaml::DependencyProperty s_LeftProperty = xaml::DependencyProperty::RegisterAttached( L"Left", winrt::xaml_typename(), viewPanelTypeName, @@ -111,8 +110,8 @@ winrt::AutomationPeer ViewPanel::OnCreateAutomationPeer() { return s_LeftProperty; } -/*static*/ winrt::DependencyProperty ViewPanel::ClipChildrenProperty() { - static winrt::DependencyProperty s_clipChildrenProperty = winrt::DependencyProperty::Register( +/*static*/ xaml::DependencyProperty ViewPanel::ClipChildrenProperty() { + static xaml::DependencyProperty s_clipChildrenProperty = xaml::DependencyProperty::Register( L"ClipChildren", winrt::xaml_typename(), viewPanelTypeName, @@ -121,12 +120,12 @@ winrt::AutomationPeer ViewPanel::OnCreateAutomationPeer() { return s_clipChildrenProperty; } -/*static*/ void ViewPanel::SetTop(winrt::Windows::UI::Xaml::UIElement const &element, double value) { +/*static*/ void ViewPanel::SetTop(xaml::UIElement const &element, double value) { element.SetValue(TopProperty(), winrt::box_value(value)); element.InvalidateArrange(); } -/*static*/ void ViewPanel::SetLeft(winrt::Windows::UI::Xaml::UIElement const &element, double value) { +/*static*/ void ViewPanel::SetLeft(xaml::UIElement const &element, double value) { element.SetValue(LeftProperty(), winrt::box_value(value)); element.InvalidateArrange(); } @@ -135,7 +134,7 @@ winrt::Size ViewPanel::MeasureOverride(winrt::Size /*availableSize*/) { // All children are given as much size as they'd like winrt::Size childConstraint(INFINITY, INFINITY); - for (winrt::UIElement child : Children()) + for (xaml::UIElement child : Children()) child.Measure(childConstraint); // ViewPanels never choose their size, that is completely up to the parent - @@ -154,7 +153,7 @@ winrt::Size ViewPanel::ArrangeOverride(winrt::Size finalSize) { outerBorderLeft = static_cast(borderThickness.Left); outerBorderTop = static_cast(borderThickness.Top); } - for (winrt::UIElement child : Children()) { + for (xaml::UIElement child : Children()) { double childHeight = 0.0; double childWidth = 0.0; @@ -165,7 +164,7 @@ winrt::Size ViewPanel::ArrangeOverride(winrt::Size finalSize) { } else { // We expect elements to have been arranged by yoga which means their // Width & Height are set - winrt::FrameworkElement fe = child.try_as(); + xaml::FrameworkElement fe = child.try_as(); if (fe != nullptr) { childWidth = fe.Width(); childHeight = fe.Height(); @@ -193,7 +192,7 @@ winrt::Size ViewPanel::ArrangeOverride(winrt::Size finalSize) { return finalSize; } -void ViewPanel::InsertAt(uint32_t const index, winrt::UIElement const &value) const { +void ViewPanel::InsertAt(uint32_t const index, xaml::UIElement const &value) const { Children().InsertAt(index, value); } @@ -201,7 +200,7 @@ void ViewPanel::RemoveAt(uint32_t const index) const { Children().RemoveAt(index); } -void ViewPanel::Remove(winrt::UIElement element) const { +void ViewPanel::Remove(xaml::UIElement element) const { uint32_t index; if (Children().IndexOf(element, index)) @@ -224,7 +223,7 @@ void ViewPanel::BorderBrush(winrt::Brush const &value) { SetValue(BorderBrushProperty(), winrt::box_value(value)); } -void ViewPanel::CornerRadius(winrt::CornerRadius const &value) { +void ViewPanel::CornerRadius(xaml::CornerRadius const &value) { SetValue(CornerRadiusProperty(), winrt::box_value(value)); } @@ -253,7 +252,7 @@ void ViewPanel::FinalizeProperties() { // this ViewPanel // >> Border* properties and Background applied to Border - const auto unsetValue = winrt::DependencyProperty::UnsetValue(); + const auto unsetValue = xaml::DependencyProperty::UnsetValue(); const Thickness emptyThickness = ThicknessHelper::FromUniformLength(0.0); bool hasBackground = ReadLocalValue(ViewBackgroundProperty()) != unsetValue; @@ -287,7 +286,7 @@ void ViewPanel::FinalizeProperties() { if (scenario != Scenario::NoBorder) { // Ensure Border is created if (m_border == nullptr) { - m_border = winrt::Border(); + m_border = xaml::Controls::Border(); // Add border as the top child if using as inner border if (scenario == Scenario::InnerBorder) @@ -298,17 +297,17 @@ void ViewPanel::FinalizeProperties() { if (hasBorderBrush) m_border.BorderBrush(BorderBrush()); else - m_border.ClearValue(winrt::Border::BorderBrushProperty()); + m_border.ClearValue(xaml::Controls::Border::BorderBrushProperty()); if (hasBorderThickness) m_border.BorderThickness(BorderThickness()); else - m_border.ClearValue(winrt::Border::BorderThicknessProperty()); + m_border.ClearValue(xaml::Controls::Border::BorderThicknessProperty()); if (hasCornerRadius) m_border.CornerRadius(CornerRadius()); else - m_border.ClearValue(winrt::Border::CornerRadiusProperty()); + m_border.ClearValue(xaml::Controls::Border::CornerRadiusProperty()); } else if (m_border != nullptr) { // Clean up and remove the Border element m_border.Child(nullptr); @@ -320,7 +319,7 @@ void ViewPanel::FinalizeProperties() { if (hasBackground) m_border.Background(ViewBackground()); else - m_border.ClearValue(winrt::Border::BackgroundProperty()); + m_border.ClearValue(xaml::Controls::Border::BackgroundProperty()); ClearValue(winrt::Panel::BackgroundProperty()); @@ -337,11 +336,11 @@ void ViewPanel::FinalizeProperties() { m_propertiesChanged = false; } -winrt::Border ViewPanel::GetOuterBorder() { +xaml::Controls::Border ViewPanel::GetOuterBorder() { if (m_hasOuterBorder && (m_border != nullptr)) return m_border; else - return winrt::Border(nullptr); + return xaml::Controls::Border(nullptr); } void ViewPanel::UpdateClip(winrt::Size &finalSize) { diff --git a/vnext/ReactUWP/Views/ViewPanel.h b/vnext/ReactUWP/Views/ViewPanel.h index dce9f947615..7541a9939c1 100644 --- a/vnext/ReactUWP/Views/ViewPanel.h +++ b/vnext/ReactUWP/Views/ViewPanel.h @@ -3,11 +3,6 @@ #pragma once -#include -#include -#include -#include - #include "ViewPanel.g.h" #ifndef PROJECT_ROOT_NAMESPACE @@ -31,40 +26,40 @@ struct ViewPanel : ViewPanelT { // Constructors ViewPanel(); - winrt::Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer(); + xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer(); // Overrides virtual winrt::Windows::Foundation::Size MeasureOverride(winrt::Windows::Foundation::Size availableSize); virtual winrt::Windows::Foundation::Size ArrangeOverride(winrt::Windows::Foundation::Size finalSize); // Public Methods - void InsertAt(uint32_t const index, winrt::Windows::UI::Xaml::UIElement const &value) const; + void InsertAt(uint32_t const index, xaml::UIElement const &value) const; void RemoveAt(uint32_t const index) const; void Clear() const; void FinalizeProperties(); - winrt::Windows::UI::Xaml::Controls::Border GetOuterBorder(); + xaml::Controls::Border GetOuterBorder(); // Public Properties - winrt::Windows::UI::Xaml::Media::Brush ViewBackground() { - return GetValue(ViewBackgroundProperty()).as(); + xaml::Media::Brush ViewBackground() { + return GetValue(ViewBackgroundProperty()).as(); } - void ViewBackground(winrt::Windows::UI::Xaml::Media::Brush const &value); + void ViewBackground(xaml::Media::Brush const &value); - winrt::Windows::UI::Xaml::Thickness BorderThickness() { - return winrt::unbox_value(GetValue(BorderThicknessProperty())); + xaml::Thickness BorderThickness() { + return winrt::unbox_value(GetValue(BorderThicknessProperty())); } - void BorderThickness(winrt::Windows::UI::Xaml::Thickness const &value); + void BorderThickness(xaml::Thickness const &value); - winrt::Windows::UI::Xaml::Media::Brush BorderBrush() { - return GetValue(BorderBrushProperty()).as(); + xaml::Media::Brush BorderBrush() { + return GetValue(BorderBrushProperty()).as(); } - void BorderBrush(winrt::Windows::UI::Xaml::Media::Brush const &value); + void BorderBrush(xaml::Media::Brush const &value); - winrt::Windows::UI::Xaml::CornerRadius CornerRadius() { - return winrt::unbox_value(GetValue(CornerRadiusProperty())); + xaml::CornerRadius CornerRadius() { + return winrt::unbox_value(GetValue(CornerRadiusProperty())); } - void CornerRadius(winrt::Windows::UI::Xaml::CornerRadius const &value); + void CornerRadius(xaml::CornerRadius const &value); bool ClipChildren() { return winrt::unbox_value(GetValue(ClipChildrenProperty())); @@ -72,27 +67,27 @@ struct ViewPanel : ViewPanelT { void ClipChildren(bool value); // ViewPanel Properties - static winrt::Windows::UI::Xaml::DependencyProperty ViewBackgroundProperty(); - static winrt::Windows::UI::Xaml::DependencyProperty BorderThicknessProperty(); - static winrt::Windows::UI::Xaml::DependencyProperty BorderBrushProperty(); - static winrt::Windows::UI::Xaml::DependencyProperty CornerRadiusProperty(); - static winrt::Windows::UI::Xaml::DependencyProperty ClipChildrenProperty(); + static xaml::DependencyProperty ViewBackgroundProperty(); + static xaml::DependencyProperty BorderThicknessProperty(); + static xaml::DependencyProperty BorderBrushProperty(); + static xaml::DependencyProperty CornerRadiusProperty(); + static xaml::DependencyProperty ClipChildrenProperty(); // Attached Properties - static winrt::Windows::UI::Xaml::DependencyProperty TopProperty(); - static void SetTop(winrt::Windows::UI::Xaml::UIElement const &element, double value); - static double GetTop(winrt::Windows::UI::Xaml::UIElement const &element) { + static xaml::DependencyProperty TopProperty(); + static void SetTop(xaml::UIElement const &element, double value); + static double GetTop(xaml::UIElement const &element) { return winrt::unbox_value(element.GetValue(TopProperty())); } - static winrt::Windows::UI::Xaml::DependencyProperty LeftProperty(); - static void SetLeft(winrt::Windows::UI::Xaml::UIElement const &element, double value); - static double GetLeft(winrt::Windows::UI::Xaml::UIElement const &element) { + static xaml::DependencyProperty LeftProperty(); + static void SetLeft(xaml::UIElement const &element, double value); + static double GetLeft(xaml::UIElement const &element) { return winrt::unbox_value(element.GetValue(LeftProperty())); } private: - void Remove(winrt::Windows::UI::Xaml::UIElement element) const; + void Remove(xaml::UIElement element) const; void UpdateClip(winrt::Windows::Foundation::Size &finalSize); @@ -100,16 +95,12 @@ struct ViewPanel : ViewPanelT { bool m_propertiesChanged{false}; // Child Elements - winrt::Windows::UI::Xaml::Controls::Border m_border{nullptr}; + xaml::Controls::Border m_border{nullptr}; bool m_hasOuterBorder; private: - static void VisualPropertyChanged( - winrt::Windows::UI::Xaml::DependencyObject sender, - winrt::Windows::UI::Xaml::DependencyPropertyChangedEventArgs e); - static void PositionPropertyChanged( - winrt::Windows::UI::Xaml::DependencyObject sender, - winrt::Windows::UI::Xaml::DependencyPropertyChangedEventArgs e); + static void VisualPropertyChanged(xaml::DependencyObject sender, xaml::DependencyPropertyChangedEventArgs e); + static void PositionPropertyChanged(xaml::DependencyObject sender, xaml::DependencyPropertyChangedEventArgs e); }; } // namespace winrt::PROJECT_ROOT_NAMESPACE::implementation diff --git a/vnext/ReactUWP/Views/ViewViewManager.cpp b/vnext/ReactUWP/Views/ViewViewManager.cpp index 273286b791c..efc490184a1 100644 --- a/vnext/ReactUWP/Views/ViewViewManager.cpp +++ b/vnext/ReactUWP/Views/ViewViewManager.cpp @@ -90,7 +90,7 @@ class ViewShadowNode : public ShadowNodeBase { if (IsControl()) { if (tabIndex < 0) { GetControl().IsTabStop(false); - GetControl().ClearValue(winrt::Control::TabIndexProperty()); + GetControl().ClearValue(xaml::Controls::Control::TabIndexProperty()); } else { GetControl().IsTabStop(true); GetControl().TabIndex(tabIndex); @@ -107,7 +107,7 @@ class ViewShadowNode : public ShadowNodeBase { void AddView(ShadowNode &child, int64_t index) override { GetViewPanel().InsertAt( - static_cast(index), static_cast(child).GetView().as()); + static_cast(index), static_cast(child).GetView().as()); } void RemoveChildAt(int64_t indexToRemove) override { @@ -123,13 +123,13 @@ class ViewShadowNode : public ShadowNodeBase { // TODO NOW: Why do we do this? Removal of children doesn't seem to imply we // tear down the infrastr if (IsControl()) { - auto control = m_view.as(); + auto control = m_view.as(); current = control.Content().as(); control.Content(nullptr); } if (HasOuterBorder()) { - if (auto border = current.try_as()) { + if (auto border = current.try_as()) { border.Child(nullptr); } } @@ -139,9 +139,9 @@ class ViewShadowNode : public ShadowNodeBase { auto pPanel = GetViewPanel(); if (pPanel != nullptr) { uint32_t index; - if (pPanel.Children().IndexOf(oldChildView.as(), index)) { + if (pPanel.Children().IndexOf(oldChildView.as(), index)) { pPanel.RemoveAt(index); - pPanel.InsertAt(index, newChildView.as()); + pPanel.InsertAt(index, newChildView.as()); } else { assert(false); } @@ -160,13 +160,13 @@ class ViewShadowNode : public ShadowNodeBase { XamlView current = m_view; if (IsControl()) { - if (auto control = m_view.try_as()) { + if (auto control = m_view.try_as()) { current = control.Content().as(); } } if (HasOuterBorder()) { - if (auto border = current.try_as()) { + if (auto border = current.try_as()) { current = border.Child().try_as(); } } @@ -185,14 +185,14 @@ class ViewShadowNode : public ShadowNodeBase { auto contentControl = winrt::make(); m_contentControlGotFocusRevoker = contentControl.GotFocus(winrt::auto_revoke, [=](auto &&, auto &&args) { - if (args.OriginalSource().try_as() == contentControl.as()) { + if (args.OriginalSource().try_as() == contentControl.as()) { auto tag = m_tag; DispatchEvent("topFocus", std::move(folly::dynamic::object("target", tag))); } }); m_contentControlLostFocusRevoker = contentControl.LostFocus(winrt::auto_revoke, [=](auto &&, auto &&args) { - if (args.OriginalSource().try_as() == contentControl.as()) { + if (args.OriginalSource().try_as() == contentControl.as()) { auto tag = m_tag; DispatchEvent("topBlur", std::move(folly::dynamic::object("target", tag))); } @@ -215,8 +215,8 @@ class ViewShadowNode : public ShadowNodeBase { bool m_onClick = false; int32_t m_tabIndex = -1; - winrt::ContentControl::GotFocus_revoker m_contentControlGotFocusRevoker{}; - winrt::ContentControl::LostFocus_revoker m_contentControlLostFocusRevoker{}; + xaml::Controls::ContentControl::GotFocus_revoker m_contentControlGotFocusRevoker{}; + xaml::Controls::ContentControl::LostFocus_revoker m_contentControlLostFocusRevoker{}; }; // ViewPanel uses a ViewBackground property, not Background, so need to @@ -315,8 +315,8 @@ facebook::react::ShadowNode *ViewViewManager::createShadow() const { XamlView ViewViewManager::CreateViewCore(int64_t /*tag*/) { auto panel = winrt::make(); - panel.VerticalAlignment(winrt::VerticalAlignment::Stretch); - panel.HorizontalAlignment(winrt::HorizontalAlignment::Stretch); + panel.VerticalAlignment(xaml::VerticalAlignment::Stretch); + panel.HorizontalAlignment(xaml::HorizontalAlignment::Stretch); return panel.as(); } @@ -382,7 +382,7 @@ bool ViewViewManager::UpdateProperty( } } - if (auto view = pViewShadowNode->GetView().try_as()) { + if (auto view = pViewShadowNode->GetView().try_as()) { // If we have DynamicAutomationProperties, we need a ViewControl with a // DynamicAutomationPeer shouldBeControl = shouldBeControl || HasDynamicAutomationProperties(view); @@ -497,12 +497,12 @@ void ViewViewManager::TryUpdateView( } // Ensure parenting is setup properly - auto visualRoot = pPanel.try_as(); + auto visualRoot = pPanel.try_as(); if (hasOuterBorder) { - winrt::Border outerBorder = pPanel.GetOuterBorder(); + xaml::Controls::Border outerBorder = pPanel.GetOuterBorder(); if (outerBorder.Child() == nullptr) - outerBorder.Child(pPanel.try_as()); + outerBorder.Child(pPanel.try_as()); visualRoot = outerBorder; } diff --git a/vnext/ReactUWP/Views/ViewViewManager.h b/vnext/ReactUWP/Views/ViewViewManager.h index 261133af62e..c50d1662004 100644 --- a/vnext/ReactUWP/Views/ViewViewManager.h +++ b/vnext/ReactUWP/Views/ViewViewManager.h @@ -6,10 +6,6 @@ #include #include -namespace winrt { -using ContentControl = winrt::Windows::UI::Xaml::Controls::ContentControl; -} - namespace react { namespace uwp { diff --git a/vnext/ReactUWP/Views/VirtualTextViewManager.cpp b/vnext/ReactUWP/Views/VirtualTextViewManager.cpp index eb8af732b87..01bef7a4915 100644 --- a/vnext/ReactUWP/Views/VirtualTextViewManager.cpp +++ b/vnext/ReactUWP/Views/VirtualTextViewManager.cpp @@ -9,14 +9,12 @@ #include #include -#include -#include namespace winrt { using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Documents; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Documents; } // namespace winrt namespace react { diff --git a/vnext/ReactUWP/Views/cppwinrt/DynamicAutomationPeer.idl b/vnext/ReactUWP/Views/cppwinrt/DynamicAutomationPeer.idl index 47c2732bda5..69b5b3c5538 100644 --- a/vnext/ReactUWP/Views/cppwinrt/DynamicAutomationPeer.idl +++ b/vnext/ReactUWP/Views/cppwinrt/DynamicAutomationPeer.idl @@ -9,6 +9,7 @@ #define VERSION 1.0 import "AccessibilityAction.idl"; +#include "../../../include/NamespaceRedirect.h" // The DynamicAutomationProperties must be in the project namespace to be // usable by Xaml dependency properties. @@ -19,116 +20,116 @@ import "AccessibilityAction.idl"; namespace PROJECT_ROOT_NAMESPACE { - enum AccessibilityRoles - { - None = 0, - Button, - Link, - Search, - Image, - KeyboardKey, - Text, - Adjustable, - ImageButton, - Header, - Summary, - Alert, - CheckBox, - ComboBox, - Menu, - MenuBar, - MenuItem, - ProgressBar, - Radio, - RadioGroup, - ScrollBar, - SpinButton, - Switch, - Tab, - TabList, - Timer, - ToolBar, - List, // RNW extension - ListItem, // RNW extension - Unknown, // Catch-all - CountRoles - }; - - enum AccessibilityStates - { - Selected = 0, - Disabled, - Checked, - Unchecked, - Busy, - Expanded, - Collapsed, - CountStates - }; - - delegate void AccessibilityInvokeEventHandler(); - delegate void AccessibilityActionEventHandler(AccessibilityAction action); - - [default_interface] - [webhosthidden] - runtimeclass DynamicAutomationProperties - { - // Attached Properties - static Windows.UI.Xaml.DependencyProperty AccessibilityRoleProperty { get; }; - static void SetAccessibilityRole(Windows.UI.Xaml.UIElement element, AccessibilityRoles value); - static AccessibilityRoles GetAccessibilityRole(Windows.UI.Xaml.UIElement element); - - static Windows.UI.Xaml.DependencyProperty AccessibilityStateSelectedProperty { get; }; - static void SetAccessibilityStateSelected(Windows.UI.Xaml.UIElement element, Boolean value); - static Boolean GetAccessibilityStateSelected(Windows.UI.Xaml.UIElement element); - - static Windows.UI.Xaml.DependencyProperty AccessibilityStateDisabledProperty { get; }; - static void SetAccessibilityStateDisabled(Windows.UI.Xaml.UIElement element, Boolean value); - static Boolean GetAccessibilityStateDisabled(Windows.UI.Xaml.UIElement element); - - static Windows.UI.Xaml.DependencyProperty AccessibilityStateCheckedProperty { get; }; - static void SetAccessibilityStateChecked(Windows.UI.Xaml.UIElement element, Boolean value); - static Boolean GetAccessibilityStateChecked(Windows.UI.Xaml.UIElement element); - - static Windows.UI.Xaml.DependencyProperty AccessibilityStateUncheckedProperty { get; }; - static void SetAccessibilityStateUnchecked(Windows.UI.Xaml.UIElement element, Boolean value); - static Boolean GetAccessibilityStateUnchecked(Windows.UI.Xaml.UIElement element); - - static Windows.UI.Xaml.DependencyProperty AccessibilityStateBusyProperty { get; }; - static void SetAccessibilityStateBusy(Windows.UI.Xaml.UIElement element, Boolean value); - static Boolean GetAccessibilityStateBusy(Windows.UI.Xaml.UIElement element); - - static Windows.UI.Xaml.DependencyProperty AccessibilityStateExpandedProperty { get; }; - static void SetAccessibilityStateExpanded(Windows.UI.Xaml.UIElement element, Boolean value); - static Boolean GetAccessibilityStateExpanded(Windows.UI.Xaml.UIElement element); - - static Windows.UI.Xaml.DependencyProperty AccessibilityStateCollapsedProperty { get; }; - static void SetAccessibilityStateCollapsed(Windows.UI.Xaml.UIElement element, Boolean value); - static Boolean GetAccessibilityStateCollapsed(Windows.UI.Xaml.UIElement element); - - static Windows.UI.Xaml.DependencyProperty AccessibilityInvokeEventHandlerProperty { get; }; - static void SetAccessibilityInvokeEventHandler(Windows.UI.Xaml.UIElement element, AccessibilityInvokeEventHandler value); - static AccessibilityInvokeEventHandler GetAccessibilityInvokeEventHandler(Windows.UI.Xaml.UIElement element); - - static Windows.UI.Xaml.DependencyProperty AccessibilityActionsProperty { get; }; - static void SetAccessibilityActions(Windows.UI.Xaml.UIElement element, Windows.Foundation.Collections.IVector value); - static Windows.Foundation.Collections.IVector GetAccessibilityActions(Windows.UI.Xaml.UIElement element); - - static Windows.UI.Xaml.DependencyProperty AccessibilityActionEventHandlerProperty { get; }; - static void SetAccessibilityActionEventHandler(Windows.UI.Xaml.UIElement element, AccessibilityActionEventHandler value); - static AccessibilityActionEventHandler GetAccessibilityActionEventHandler(Windows.UI.Xaml.UIElement element); - } - - [default_interface] - [webhosthidden] - runtimeclass DynamicAutomationPeer : - Windows.UI.Xaml.Automation.Peers.FrameworkElementAutomationPeer, - Windows.UI.Xaml.Automation.Provider.IInvokeProvider, - Windows.UI.Xaml.Automation.Provider.ISelectionProvider, - Windows.UI.Xaml.Automation.Provider.ISelectionItemProvider, - Windows.UI.Xaml.Automation.Provider.IToggleProvider, - Windows.UI.Xaml.Automation.Provider.IExpandCollapseProvider - { - DynamicAutomationPeer(Windows.UI.Xaml.FrameworkElement owner); - } + enum AccessibilityRoles + { + None = 0, + Button, + Link, + Search, + Image, + KeyboardKey, + Text, + Adjustable, + ImageButton, + Header, + Summary, + Alert, + CheckBox, + ComboBox, + Menu, + MenuBar, + MenuItem, + ProgressBar, + Radio, + RadioGroup, + ScrollBar, + SpinButton, + Switch, + Tab, + TabList, + Timer, + ToolBar, + List, // RNW extension + ListItem, // RNW extension + Unknown, // Catch-all + CountRoles + }; + + enum AccessibilityStates + { + Selected = 0, + Disabled, + Checked, + Unchecked, + Busy, + Expanded, + Collapsed, + CountStates + }; + + delegate void AccessibilityInvokeEventHandler(); + delegate void AccessibilityActionEventHandler(AccessibilityAction action); + + [default_interface] + [webhosthidden] + runtimeclass DynamicAutomationProperties + { + // Attached Properties + static XAML_NAMESPACE.DependencyProperty AccessibilityRoleProperty { get; }; + static void SetAccessibilityRole(XAML_NAMESPACE.UIElement element, AccessibilityRoles value); + static AccessibilityRoles GetAccessibilityRole(XAML_NAMESPACE.UIElement element); + + static XAML_NAMESPACE.DependencyProperty AccessibilityStateSelectedProperty { get; }; + static void SetAccessibilityStateSelected(XAML_NAMESPACE.UIElement element, Boolean value); + static Boolean GetAccessibilityStateSelected(XAML_NAMESPACE.UIElement element); + + static XAML_NAMESPACE.DependencyProperty AccessibilityStateDisabledProperty { get; }; + static void SetAccessibilityStateDisabled(XAML_NAMESPACE.UIElement element, Boolean value); + static Boolean GetAccessibilityStateDisabled(XAML_NAMESPACE.UIElement element); + + static XAML_NAMESPACE.DependencyProperty AccessibilityStateCheckedProperty { get; }; + static void SetAccessibilityStateChecked(XAML_NAMESPACE.UIElement element, Boolean value); + static Boolean GetAccessibilityStateChecked(XAML_NAMESPACE.UIElement element); + + static XAML_NAMESPACE.DependencyProperty AccessibilityStateUncheckedProperty { get; }; + static void SetAccessibilityStateUnchecked(XAML_NAMESPACE.UIElement element, Boolean value); + static Boolean GetAccessibilityStateUnchecked(XAML_NAMESPACE.UIElement element); + + static XAML_NAMESPACE.DependencyProperty AccessibilityStateBusyProperty { get; }; + static void SetAccessibilityStateBusy(XAML_NAMESPACE.UIElement element, Boolean value); + static Boolean GetAccessibilityStateBusy(XAML_NAMESPACE.UIElement element); + + static XAML_NAMESPACE.DependencyProperty AccessibilityStateExpandedProperty { get; }; + static void SetAccessibilityStateExpanded(XAML_NAMESPACE.UIElement element, Boolean value); + static Boolean GetAccessibilityStateExpanded(XAML_NAMESPACE.UIElement element); + + static XAML_NAMESPACE.DependencyProperty AccessibilityStateCollapsedProperty { get; }; + static void SetAccessibilityStateCollapsed(XAML_NAMESPACE.UIElement element, Boolean value); + static Boolean GetAccessibilityStateCollapsed(XAML_NAMESPACE.UIElement element); + + static XAML_NAMESPACE.DependencyProperty AccessibilityInvokeEventHandlerProperty { get; }; + static void SetAccessibilityInvokeEventHandler(XAML_NAMESPACE.UIElement element, AccessibilityInvokeEventHandler value); + static AccessibilityInvokeEventHandler GetAccessibilityInvokeEventHandler(XAML_NAMESPACE.UIElement element); + + static XAML_NAMESPACE.DependencyProperty AccessibilityActionsProperty { get; }; + static void SetAccessibilityActions(XAML_NAMESPACE.UIElement element, Windows.Foundation.Collections.IVector value); + static Windows.Foundation.Collections.IVector GetAccessibilityActions(XAML_NAMESPACE.UIElement element); + + static XAML_NAMESPACE.DependencyProperty AccessibilityActionEventHandlerProperty { get; }; + static void SetAccessibilityActionEventHandler(XAML_NAMESPACE.UIElement element, AccessibilityActionEventHandler value); + static AccessibilityActionEventHandler GetAccessibilityActionEventHandler(XAML_NAMESPACE.UIElement element); + } + + [default_interface] + [webhosthidden] + runtimeclass DynamicAutomationPeer : + XAML_NAMESPACE.Automation.Peers.FrameworkElementAutomationPeer, + XAML_NAMESPACE.Automation.Provider.IInvokeProvider, + XAML_NAMESPACE.Automation.Provider.ISelectionProvider, + XAML_NAMESPACE.Automation.Provider.ISelectionItemProvider, + XAML_NAMESPACE.Automation.Provider.IToggleProvider, + XAML_NAMESPACE.Automation.Provider.IExpandCollapseProvider + { + DynamicAutomationPeer(XAML_NAMESPACE.FrameworkElement owner); + } } diff --git a/vnext/ReactUWP/Views/cppwinrt/ViewPanel.idl b/vnext/ReactUWP/Views/cppwinrt/ViewPanel.idl index 7a809891e9e..1ad670ba1d4 100644 --- a/vnext/ReactUWP/Views/cppwinrt/ViewPanel.idl +++ b/vnext/ReactUWP/Views/cppwinrt/ViewPanel.idl @@ -8,6 +8,8 @@ import "DynamicAutomationPeer.idl"; +#include "../../../include/NamespaceRedirect.h" + // The ViewPanel must be in the project namespace to be // usable by Xaml dependency properties. // We use a macro to be able to change it from the project file. @@ -17,51 +19,51 @@ import "DynamicAutomationPeer.idl"; namespace PROJECT_ROOT_NAMESPACE { - [default_interface] - [webhosthidden] - runtimeclass ViewPanel : Windows.UI.Xaml.Controls.Panel - { - // Constructors - ViewPanel(); + [default_interface] + [webhosthidden] + runtimeclass ViewPanel : XAML_NAMESPACE.Controls.Panel + { + // Constructors + ViewPanel(); - // Public Methods - void InsertAt(UInt32 index, Windows.UI.Xaml.UIElement value); - void RemoveAt(UInt32 index); - void Clear(); + // Public Methods + void InsertAt(UInt32 index, XAML_NAMESPACE.UIElement value); + void RemoveAt(UInt32 index); + void Clear(); - void FinalizeProperties(); - Windows.UI.Xaml.Controls.Border GetOuterBorder(); + void FinalizeProperties(); + XAML_NAMESPACE.Controls.Border GetOuterBorder(); - // Public Properties - Windows.UI.Xaml.Media.Brush ViewBackground { get; set; }; - Windows.UI.Xaml.Thickness BorderThickness { get; set; }; - Windows.UI.Xaml.Media.Brush BorderBrush { get; set; }; - Windows.UI.Xaml.CornerRadius CornerRadius { get; set; }; - Boolean ClipChildren { get; set; }; + // Public Properties + XAML_NAMESPACE.Media.Brush ViewBackground { get; set; }; + XAML_NAMESPACE.Thickness BorderThickness { get; set; }; + XAML_NAMESPACE.Media.Brush BorderBrush { get; set; }; + XAML_NAMESPACE.CornerRadius CornerRadius { get; set; }; + Boolean ClipChildren { get; set; }; - // ViewPanel Properties - static Windows.UI.Xaml.DependencyProperty ViewBackgroundProperty { get; }; - static Windows.UI.Xaml.DependencyProperty BorderThicknessProperty { get; }; - static Windows.UI.Xaml.DependencyProperty BorderBrushProperty { get; }; - static Windows.UI.Xaml.DependencyProperty CornerRadiusProperty { get; }; - static Windows.UI.Xaml.DependencyProperty ClipChildrenProperty { get; }; + // ViewPanel Properties + static XAML_NAMESPACE.DependencyProperty ViewBackgroundProperty { get; }; + static XAML_NAMESPACE.DependencyProperty BorderThicknessProperty { get; }; + static XAML_NAMESPACE.DependencyProperty BorderBrushProperty { get; }; + static XAML_NAMESPACE.DependencyProperty CornerRadiusProperty { get; }; + static XAML_NAMESPACE.DependencyProperty ClipChildrenProperty { get; }; - // Attached Properties - static Windows.UI.Xaml.DependencyProperty TopProperty { get; }; - static void SetTop(Windows.UI.Xaml.UIElement element, Double value); - static Double GetTop(Windows.UI.Xaml.UIElement element); + // Attached Properties + static XAML_NAMESPACE.DependencyProperty TopProperty { get; }; + static void SetTop(XAML_NAMESPACE.UIElement element, Double value); + static Double GetTop(XAML_NAMESPACE.UIElement element); - static Windows.UI.Xaml.DependencyProperty LeftProperty { get; }; - static void SetLeft(Windows.UI.Xaml.UIElement element, Double value); - static Double GetLeft(Windows.UI.Xaml.UIElement element); - } + static XAML_NAMESPACE.DependencyProperty LeftProperty { get; }; + static void SetLeft(XAML_NAMESPACE.UIElement element, Double value); + static Double GetLeft(XAML_NAMESPACE.UIElement element); + } - [default_interface] - [webhosthidden] - runtimeclass ViewControl : Windows.UI.Xaml.Controls.ContentControl - { - ViewControl(); + [default_interface] + [webhosthidden] + runtimeclass ViewControl : XAML_NAMESPACE.Controls.ContentControl + { + ViewControl(); - ViewPanel GetPanel(); - } + ViewPanel GetPanel(); + } } diff --git a/vnext/Universal.IntegrationTests/UniversalTestInstance.cpp b/vnext/Universal.IntegrationTests/UniversalTestInstance.cpp index 069da846d6e..eed2050fd1c 100644 --- a/vnext/Universal.IntegrationTests/UniversalTestInstance.cpp +++ b/vnext/Universal.IntegrationTests/UniversalTestInstance.cpp @@ -4,11 +4,12 @@ #include "UniversalTestInstance.h" -#include -#include +#include // C++/CX #include -namespace xaml = Windows::UI::Xaml; +namespace cx { +namespace xaml = ::Windows::UI::Xaml; +} using namespace react::uwp; @@ -53,17 +54,16 @@ void UniversalTestInstance::AttachMeasuredRootView(std::string &&appName) noexce // Instantiate root view. auto action = Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync( Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([this]() { - auto frame = xaml::Window::Current->Content; - auto presenter = xaml::Media::VisualTreeHelper::GetChild(frame, 0); - auto page = xaml::Media::VisualTreeHelper::GetChild(presenter, 0); - auto mainGrid = static_cast(xaml::Media::VisualTreeHelper::GetChild(page, 0)); + auto frame = cx::xaml::Window::Current->Content; + auto presenter = cx::xaml::Media::VisualTreeHelper::GetChild(frame, 0); + auto page = cx::xaml::Media::VisualTreeHelper::GetChild(presenter, 0); + auto mainGrid = static_cast(cx::xaml::Media::VisualTreeHelper::GetChild(page, 0)); - xaml::IFrameworkElement ^ rootFrameworkElement = mainGrid; + cx::xaml::IFrameworkElement ^ rootFrameworkElement = mainGrid; Microsoft::WRL::ComPtr<::ABI::Windows::UI::Xaml::IFrameworkElement> spFrameworkElementABI = - reinterpret_cast(rootFrameworkElement); + reinterpret_cast<::ABI::Windows::UI::Xaml::IFrameworkElement *>(rootFrameworkElement); // Create C++/WinRT pointer from ABI pointer. - ::react::uwp::XamlView xamlView = - reinterpret_cast(spFrameworkElementABI); + ::react::uwp::XamlView xamlView = reinterpret_cast(spFrameworkElementABI); m_rootView = ::react::uwp::CreateReactRootView(xamlView, L"DummyTest", m_instanceCreator); diff --git a/vnext/Universal.IntegrationTests/UniversalTestRunner.cpp b/vnext/Universal.IntegrationTests/UniversalTestRunner.cpp index edd5501e341..52193fa8a89 100644 --- a/vnext/Universal.IntegrationTests/UniversalTestRunner.cpp +++ b/vnext/Universal.IntegrationTests/UniversalTestRunner.cpp @@ -9,16 +9,16 @@ #include #include "UniversalTestInstance.h" -#include -#include +#include // C++/CX #include #include // Concurrency namespace. #include "MainPage.xaml.h" -namespace xaml = Windows::UI::Xaml; - +namespace cx { +namespace xaml = ::Windows::UI::Xaml; +} using namespace facebook::react; using namespace facebook::xplat::module; diff --git a/vnext/include/CppWinRTIncludes.h b/vnext/include/CppWinRTIncludes.h index bbd92514dfa..4b5780a1772 100644 --- a/vnext/include/CppWinRTIncludes.h +++ b/vnext/include/CppWinRTIncludes.h @@ -3,23 +3,70 @@ // information. #pragma once +#include "NamespaceRedirect.h" +#include +#include #include +#include +#include + +#ifndef WINUI3_SUPPORT + +#include +#include #include #include +#include +#include #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include #include +namespace xaml = winrt::Windows::UI::Xaml; +namespace comp = winrt::Windows::UI::Composition; + +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xaml = winrt::Microsoft::UI::Xaml; +namespace comp = winrt::Microsoft::UI::Composition; +#endif + namespace winrt { -using namespace ::winrt::Windows::UI::Xaml; -using namespace ::winrt::Windows::UI::Core; +using namespace Windows::UI::Core; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Composition; -using namespace Windows::UI::Xaml::Hosting; } // namespace winrt + +#define _QUOTE(x) L#x +#define QUOTE(x) _QUOTE(x) +#define XAML_NAMESPACE_STR QUOTE(XAML_NAMESPACE) diff --git a/vnext/include/Include.vcxitems b/vnext/include/Include.vcxitems index 4c2f792e6c0..9388f6b2969 100644 --- a/vnext/include/Include.vcxitems +++ b/vnext/include/Include.vcxitems @@ -45,4 +45,7 @@ + + + \ No newline at end of file diff --git a/vnext/include/Include.vcxitems.filters b/vnext/include/Include.vcxitems.filters index 3de9e65a5de..3b0e64a54ae 100644 --- a/vnext/include/Include.vcxitems.filters +++ b/vnext/include/Include.vcxitems.filters @@ -102,4 +102,7 @@ {77bf1091-5dda-46a7-ac20-6540d6e396d3} + + + \ No newline at end of file diff --git a/vnext/include/NamespaceRedirect.h b/vnext/include/NamespaceRedirect.h new file mode 100644 index 00000000000..9cee72ab6de --- /dev/null +++ b/vnext/include/NamespaceRedirect.h @@ -0,0 +1,7 @@ +#pragma once + +#ifndef WINUI3_SUPPORT +#define XAML_NAMESPACE Windows.UI.Xaml +#else +#define XAML_NAMESPACE Microsoft.UI.Xaml +#endif diff --git a/vnext/include/ReactUWP/Utils/AccessibilityUtils.h b/vnext/include/ReactUWP/Utils/AccessibilityUtils.h index d551b7dc773..a1f74df19b8 100644 --- a/vnext/include/ReactUWP/Utils/AccessibilityUtils.h +++ b/vnext/include/ReactUWP/Utils/AccessibilityUtils.h @@ -3,19 +3,15 @@ #pragma once -#include -#include -#include - #include - +#include "CppWinRTIncludes.h" namespace react { namespace uwp { REACTWINDOWS_API_(void) -AnnounceLiveRegionChangedIfNeeded(const winrt::Windows::UI::Xaml::FrameworkElement &element); +AnnounceLiveRegionChangedIfNeeded(const xaml::FrameworkElement &element); REACTWINDOWS_API_(bool) -HasDynamicAutomationProperties(const winrt::Windows::UI::Xaml::UIElement &element); +HasDynamicAutomationProperties(const xaml::UIElement &element); } // namespace uwp -} // namespace react \ No newline at end of file +} // namespace react diff --git a/vnext/include/ReactUWP/Utils/Helpers.h b/vnext/include/ReactUWP/Utils/Helpers.h index ad12e1a9ee6..c7750034230 100644 --- a/vnext/include/ReactUWP/Utils/Helpers.h +++ b/vnext/include/ReactUWP/Utils/Helpers.h @@ -6,11 +6,6 @@ #include #include #include -#include - -namespace winrt { -using namespace Windows::UI::Xaml; -} namespace react { namespace uwp { @@ -27,7 +22,7 @@ inline typename T asEnum(folly::dynamic const &obj) { return static_cast(obj.asInt()); } -ReactId getViewId(_In_ IReactInstance *instance, winrt::FrameworkElement const &fe); +ReactId getViewId(_In_ IReactInstance *instance, xaml::FrameworkElement const &fe); std::int32_t CountOpenPopups(); bool IsRS3OrHigher(); diff --git a/vnext/include/ReactUWP/Utils/PropertyUtils.h b/vnext/include/ReactUWP/Utils/PropertyUtils.h index a8e02589475..cd6d629ff2e 100644 --- a/vnext/include/ReactUWP/Utils/PropertyUtils.h +++ b/vnext/include/ReactUWP/Utils/PropertyUtils.h @@ -10,17 +10,9 @@ #include #include #include -#include -#include -#include -#include #include -namespace winrt { -using namespace Windows::UI::Xaml; -} - namespace react { namespace uwp { @@ -40,14 +32,14 @@ static const std::unordered_map edgeTypeMap = { {"borderWidth", ShadowEdges::AllEdges}, }; -inline winrt::Windows::UI::Xaml::Thickness GetThickness(double thicknesses[ShadowEdges::CountEdges]) { +inline xaml::Thickness GetThickness(double thicknesses[ShadowEdges::CountEdges]) { const double defaultWidth = std::max(0, thicknesses[ShadowEdges::AllEdges]); double startWidth = DefaultOrOverride(thicknesses[ShadowEdges::Left], thicknesses[ShadowEdges::Start]); double endWidth = DefaultOrOverride(thicknesses[ShadowEdges::Right], thicknesses[ShadowEdges::End]); // Compute each edge. Most specific setting wins, so fill from broad to // narrow: all, horiz/vert, start/end, left/right - winrt::Windows::UI::Xaml::Thickness thickness = {defaultWidth, defaultWidth, defaultWidth, defaultWidth}; + xaml::Thickness thickness = {defaultWidth, defaultWidth, defaultWidth, defaultWidth}; if (thicknesses[ShadowEdges::Horizontal] != c_UndefinedEdge) thickness.Left = thickness.Right = thicknesses[ShadowEdges::Horizontal]; @@ -66,8 +58,8 @@ inline winrt::Windows::UI::Xaml::Thickness GetThickness(double thicknesses[Shado return thickness; } -inline winrt::Windows::UI::Xaml::CornerRadius GetCornerRadius(double cornerRadii[ShadowCorners::CountCorners]) { - winrt::Windows::UI::Xaml::CornerRadius cornerRadius; +inline xaml::CornerRadius GetCornerRadius(double cornerRadii[ShadowCorners::CountCorners]) { + xaml::CornerRadius cornerRadius; const double defaultRadius = std::max(0, cornerRadii[ShadowCorners::AllCorners]); double topStartRadius = DefaultOrOverride(cornerRadii[ShadowCorners::TopLeft], cornerRadii[ShadowCorners::TopStart]); double topEndRadius = DefaultOrOverride(cornerRadii[ShadowCorners::TopRight], cornerRadii[ShadowCorners::TopEnd]); @@ -87,19 +79,19 @@ inline winrt::Windows::UI::Xaml::CornerRadius GetCornerRadius(double cornerRadii template void UpdatePadding(ShadowNodeBase *node, const T &element, ShadowEdges edge, double margin) { node->m_padding[edge] = margin; - winrt::Thickness thickness = GetThickness(node->m_padding); + xaml::Thickness thickness = GetThickness(node->m_padding); element.Padding(thickness); } template void SetBorderThickness(ShadowNodeBase *node, const T &element, ShadowEdges edge, double margin) { node->m_border[edge] = margin; - winrt::Thickness thickness = GetThickness(node->m_border); + xaml::Thickness thickness = GetThickness(node->m_border); element.BorderThickness(thickness); } template -void SetBorderBrush(const T &element, const winrt::Windows::UI::Xaml::Media::Brush &brush) { +void SetBorderBrush(const T &element, const xaml::Media::Brush &brush) { element.BorderBrush(brush); } @@ -131,7 +123,7 @@ UpdateCornerRadiusValueOnNode(ShadowNodeBase *node, ShadowCorners corner, const template void UpdateCornerRadiusOnElement(ShadowNodeBase *node, const T &element) { - winrt::CornerRadius cornerRadius = GetCornerRadius(node->m_cornerRadius); + xaml::CornerRadius cornerRadius = GetCornerRadius(node->m_cornerRadius); element.CornerRadius(cornerRadius); } @@ -270,7 +262,7 @@ bool TryUpdateFontProperties(const T &element, const std::string &propertyName, element.ClearValue(T::FontSizeProperty()); } else if (propertyName == "fontFamily") { if (propertyValue.isString()) - element.FontFamily(winrt::Windows::UI::Xaml::Media::FontFamily(asWStr(propertyValue))); + element.FontFamily(xaml::Media::FontFamily(asWStr(propertyValue))); else if (propertyValue.isNull()) element.ClearValue(T::FontFamilyProperty()); } else if (propertyName == "fontWeight") { @@ -326,15 +318,15 @@ bool TryUpdateFontProperties(const T &element, const std::string &propertyName, template void SetTextAlignment(const T &element, const std::string &value) { if (value == "left") - element.TextAlignment(winrt::TextAlignment::Left); + element.TextAlignment(xaml::TextAlignment::Left); else if (value == "right") - element.TextAlignment(winrt::TextAlignment::Right); + element.TextAlignment(xaml::TextAlignment::Right); else if (value == "center") - element.TextAlignment(winrt::TextAlignment::Center); + element.TextAlignment(xaml::TextAlignment::Center); else if (value == "justify") - element.TextAlignment(winrt::TextAlignment::Justify); + element.TextAlignment(xaml::TextAlignment::Justify); else - element.TextAlignment(winrt::TextAlignment::DetectFromContent); + element.TextAlignment(xaml::TextAlignment::DetectFromContent); } template @@ -356,13 +348,13 @@ bool TryUpdateTextAlignment(const T &element, const std::string &propertyName, c template void SetTextTrimming(const T &element, const std::string &value) { if (value == "clip") - element.TextTrimming(winrt::TextTrimming::Clip); + element.TextTrimming(xaml::TextTrimming::Clip); else if (value == "head" || value == "middle" || value == "tail") { // "head" and "middle" not supported by UWP, but "tail" // behavior is the most similar - element.TextTrimming(winrt::TextTrimming::CharacterEllipsis); + element.TextTrimming(xaml::TextTrimming::CharacterEllipsis); } else - element.TextTrimming(winrt::TextTrimming::None); + element.TextTrimming(xaml::TextTrimming::None); } template @@ -389,7 +381,7 @@ bool TryUpdateTextDecorationLine( if (propertyName == "textDecorationLine") { // FUTURE: remove when SDK target minVer >= 10.0.15063.0 static bool isTextDecorationsSupported = winrt::Windows::Foundation::Metadata::ApiInformation::IsPropertyPresent( - L"Windows.UI.Xaml.Controls.TextBlock", L"TextDecorations"); + XAML_NAMESPACE_STR L".Controls.TextBlock", L"TextDecorations"); if (!isTextDecorationsSupported) return true; @@ -421,11 +413,11 @@ bool TryUpdateTextDecorationLine( template void SetFlowDirection(const T &element, const std::string &value) { if (value == "rtl") - element.FlowDirection(winrt::FlowDirection::RightToLeft); + element.FlowDirection(xaml::FlowDirection::RightToLeft); else if (value == "ltr") - element.FlowDirection(winrt::FlowDirection::LeftToRight); + element.FlowDirection(xaml::FlowDirection::LeftToRight); else // 'auto', 'inherit' - element.ClearValue(winrt::FrameworkElement::FlowDirectionProperty()); + element.ClearValue(xaml::FrameworkElement::FlowDirectionProperty()); } template @@ -466,9 +458,9 @@ bool TryUpdateOrientation(const T &element, const std::string &propertyName, con } else if (propertyValue.isString()) { const std::string &valueString = propertyValue.getString(); if (valueString == "horizontal") - element.Orientation(winrt::Orientation::Horizontal); + element.Orientation(xaml::Controls::Orientation::Horizontal); else if (valueString == "vertical") - element.Orientation(winrt::Orientation::Vertical); + element.Orientation(xaml::Controls::Orientation::Vertical); } return true; diff --git a/vnext/include/ReactUWP/Utils/ResourceBrushUtils.h b/vnext/include/ReactUWP/Utils/ResourceBrushUtils.h index 778df59df46..ecdb28ec7cc 100644 --- a/vnext/include/ReactUWP/Utils/ResourceBrushUtils.h +++ b/vnext/include/ReactUWP/Utils/ResourceBrushUtils.h @@ -2,15 +2,7 @@ // Licensed under the MIT License. #pragma once - -#include -#include -#include - -namespace winrt { -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Media; -} // namespace winrt +#include "CppWinRTIncludes.h" namespace react { namespace uwp { @@ -24,26 +16,20 @@ namespace uwp { // re-rendering with different props in response to state // change events (onFocus, onBlur, onMouseEnter, onMouseLeave) // or when changing enabled/disabled props. -void UpdateControlBackgroundResourceBrushes( - const winrt::Windows::UI::Xaml::FrameworkElement &element, - const winrt::Media::Brush brush); +void UpdateControlBackgroundResourceBrushes(const xaml::FrameworkElement &element, const xaml::Media::Brush brush); -void UpdateControlForegroundResourceBrushes( - const winrt::Windows::UI::Xaml::DependencyObject object, - const winrt::Media::Brush brush); +void UpdateControlForegroundResourceBrushes(const xaml::DependencyObject object, const xaml::Media::Brush brush); -void UpdateControlBorderResourceBrushes( - const winrt::Windows::UI::Xaml::FrameworkElement &element, - const winrt::Media::Brush brush); +void UpdateControlBorderResourceBrushes(const xaml::FrameworkElement &element, const xaml::Media::Brush brush); void UpdateToggleSwitchThumbResourceBrushes( - const winrt::Windows::UI::Xaml::Controls::ToggleSwitch &toggleSwitch, - const winrt::Windows::UI::Xaml::Media::Brush thumbBrush); + const xaml::Controls::ToggleSwitch &toggleSwitch, + const xaml::Media::Brush thumbBrush); void UpdateToggleSwitchTrackResourceBrushes( - const winrt::Windows::UI::Xaml::Controls::ToggleSwitch &toggleSwitch, - const winrt::Windows::UI::Xaml::Media::Brush onTrackBrush, - const winrt::Windows::UI::Xaml::Media::Brush offTrackBrush); + const xaml::Controls::ToggleSwitch &toggleSwitch, + const xaml::Media::Brush onTrackBrush, + const xaml::Media::Brush offTrackBrush); } // namespace uwp } // namespace react diff --git a/vnext/include/ReactUWP/Utils/ValueUtils.h b/vnext/include/ReactUWP/Utils/ValueUtils.h index cc275d34038..65001f3f111 100644 --- a/vnext/include/ReactUWP/Utils/ValueUtils.h +++ b/vnext/include/ReactUWP/Utils/ValueUtils.h @@ -3,13 +3,10 @@ #pragma once -#include -#include -#include -#include #include #include +#include "CppWinRTIncludes.h" namespace folly { struct dynamic; @@ -18,16 +15,16 @@ struct dynamic; namespace react { namespace uwp { -winrt::Windows::UI::Xaml::Media::Brush BrushFromColorObject(const folly::dynamic &d); +xaml::Media::Brush BrushFromColorObject(const folly::dynamic &d); REACTWINDOWS_API_(winrt::Windows::UI::Color) ColorFrom(const folly::dynamic &d); -REACTWINDOWS_API_(winrt::Windows::UI::Xaml::Media::Brush) +REACTWINDOWS_API_(xaml::Media::Brush) BrushFrom(const folly::dynamic &d); -REACTWINDOWS_API_(winrt::Windows::UI::Xaml::Media::SolidColorBrush) +REACTWINDOWS_API_(xaml::Media::SolidColorBrush) SolidColorBrushFrom(const folly::dynamic &d); -REACTWINDOWS_API_(winrt::Windows::UI::Xaml::VerticalAlignment) +REACTWINDOWS_API_(xaml::VerticalAlignment) VerticalAlignmentFrom(const folly::dynamic &d); -REACTWINDOWS_API_(winrt::Windows::UI::Xaml::HorizontalAlignment) +REACTWINDOWS_API_(xaml::HorizontalAlignment) HorizontalAlignmentFrom(const folly::dynamic &d); REACTWINDOWS_API_(winrt::Windows::Foundation::DateTime) DateTimeFrom(int64_t timeInMilliSeconds, int64_t timeZoneOffsetInSeconds); diff --git a/vnext/include/ReactUWP/Views/FrameworkElementViewManager.h b/vnext/include/ReactUWP/Views/FrameworkElementViewManager.h index e98c4afb6e3..a975dcb2641 100644 --- a/vnext/include/ReactUWP/Views/FrameworkElementViewManager.h +++ b/vnext/include/ReactUWP/Views/FrameworkElementViewManager.h @@ -3,7 +3,6 @@ #pragma once -#include #include "ViewManagerBase.h" namespace react { @@ -19,9 +18,7 @@ class REACTWINDOWS_EXPORT FrameworkElementViewManager : public ViewManagerBase { // Helper functions related to setting/updating TransformMatrix void RefreshTransformMatrix(ShadowNodeBase *shadowNode); - void StartTransformAnimation( - winrt::UIElement uielement, - winrt::Windows::UI::Composition::CompositionPropertySet transformPS); + void StartTransformAnimation(xaml::UIElement uielement, comp::CompositionPropertySet transformPS); virtual void TransferProperties(const XamlView &oldView, const XamlView &newView) override; @@ -31,18 +28,17 @@ class REACTWINDOWS_EXPORT FrameworkElementViewManager : public ViewManagerBase { const std::string &propertyName, const folly::dynamic &propertyValue) override; - void - TransferProperty(const XamlView &oldView, const XamlView &newView, winrt::Windows::UI::Xaml::DependencyProperty dp); + void TransferProperty(const XamlView &oldView, const XamlView &newView, xaml::DependencyProperty dp); void TransferProperty( const XamlView &oldView, const XamlView &newView, - winrt::DependencyProperty oldViewDP, - winrt::DependencyProperty newViewDP); + xaml::DependencyProperty oldViewDP, + xaml::DependencyProperty newViewDP); private: void ApplyTransformMatrix( - winrt::UIElement uielement, + xaml::UIElement uielement, ShadowNodeBase *shadowNode, winrt::Windows::Foundation::Numerics::float4x4 transformMatrix); }; diff --git a/vnext/include/ReactUWP/Views/KeyboardEventHandler.h b/vnext/include/ReactUWP/Views/KeyboardEventHandler.h index 9d6e17787d9..0ec914ea95e 100644 --- a/vnext/include/ReactUWP/Views/KeyboardEventHandler.h +++ b/vnext/include/ReactUWP/Views/KeyboardEventHandler.h @@ -2,23 +2,14 @@ // Licensed under the MIT License. #pragma once +#include #include -#include -#include #include #include - -#include +#include "CppWinRTIncludes.h" #include "XamlView.h" namespace winrt { -using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::Foundation; -using namespace Windows::UI::Xaml::Media; -using namespace Windows::System; using namespace Windows::UI::Core; } // namespace winrt @@ -49,7 +40,7 @@ struct HandledKeyboardEvent : ModifiedKeyState { std::string code{}; }; -typedef std::function KeyboardEventCallback; +typedef std::function KeyboardEventCallback; class KeyboardEventBaseHandler { public: @@ -72,8 +63,8 @@ class PreviewKeyboardEventHandler : public KeyboardEventBaseHandler { void unhook(); private: - winrt::UIElement::PreviewKeyDown_revoker m_previewKeyDownRevoker{}; - winrt::UIElement::PreviewKeyUp_revoker m_previewKeyUpRevoker{}; + xaml::UIElement::PreviewKeyDown_revoker m_previewKeyDownRevoker{}; + xaml::UIElement::PreviewKeyUp_revoker m_previewKeyUpRevoker{}; }; class KeyboardEventHandler : public KeyboardEventBaseHandler { @@ -84,8 +75,8 @@ class KeyboardEventHandler : public KeyboardEventBaseHandler { void unhook(); private: - winrt::UIElement::KeyDown_revoker m_keyDownRevoker{}; - winrt::UIElement::KeyUp_revoker m_keyUpRevoker{}; + xaml::UIElement::KeyDown_revoker m_keyDownRevoker{}; + xaml::UIElement::KeyUp_revoker m_keyUpRevoker{}; }; class PreviewKeyboardEventHandlerOnRoot : public PreviewKeyboardEventHandler { @@ -93,10 +84,10 @@ class PreviewKeyboardEventHandlerOnRoot : public PreviewKeyboardEventHandler { PreviewKeyboardEventHandlerOnRoot(const std::weak_ptr &reactInstance); private: - void OnPreKeyDown(winrt::IInspectable const &sender, winrt::KeyRoutedEventArgs const &args); - void OnPreKeyUp(winrt::IInspectable const &sender, winrt::KeyRoutedEventArgs const &args); + void OnPreKeyDown(winrt::IInspectable const &sender, xaml::Input::KeyRoutedEventArgs const &args); + void OnPreKeyUp(winrt::IInspectable const &sender, xaml::Input::KeyRoutedEventArgs const &args); - void DispatchEventToJs(std::string const &name, winrt::KeyRoutedEventArgs const &args); + void DispatchEventToJs(std::string const &name, xaml::Input::KeyRoutedEventArgs const &args); std::weak_ptr m_wkReactInstance; }; @@ -118,7 +109,7 @@ class HandledKeyboardEventHandler { void KeyboardEventHandledHandler( KeyboardEventPhase phase, winrt::IInspectable const &sender, - winrt::KeyRoutedEventArgs const &args); + xaml::Input::KeyRoutedEventArgs const &args); bool ShouldMarkKeyboardHandled( std::vector const &handledEvents, HandledKeyboardEvent currentEvent); @@ -132,11 +123,11 @@ class HandledKeyboardEventHandler { struct KeyboardHelper { static std::vector FromJS(folly::dynamic const &obj); - static HandledKeyboardEvent CreateKeyboardEvent(HandledEventPhase phase, winrt::KeyRoutedEventArgs const &args); - static std::string FromVirtualKey(winrt::VirtualKey key, bool shiftDown, bool capLocked); - static std::string CodeFromVirtualKey(winrt::VirtualKey key); - static bool IsModifiedKeyPressed(winrt::CoreWindow const &coreWindow, winrt::VirtualKey virtualKey); - static bool IsModifiedKeyLocked(winrt::CoreWindow const &coreWindow, winrt::VirtualKey virtualKey); + static HandledKeyboardEvent CreateKeyboardEvent(HandledEventPhase phase, xaml::Input::KeyRoutedEventArgs const &args); + static std::string FromVirtualKey(winrt::Windows::System::VirtualKey key, bool shiftDown, bool capLocked); + static std::string CodeFromVirtualKey(winrt::Windows::System::VirtualKey key); + static bool IsModifiedKeyPressed(winrt::CoreWindow const &coreWindow, winrt::Windows::System::VirtualKey virtualKey); + static bool IsModifiedKeyLocked(winrt::CoreWindow const &coreWindow, winrt::Windows::System::VirtualKey virtualKey); }; } // namespace uwp } // namespace react diff --git a/vnext/include/ReactUWP/Views/ShadowNodeBase.h b/vnext/include/ReactUWP/Views/ShadowNodeBase.h index dda05559552..a81260c8201 100644 --- a/vnext/include/ReactUWP/Views/ShadowNodeBase.h +++ b/vnext/include/ReactUWP/Views/ShadowNodeBase.h @@ -92,13 +92,13 @@ struct REACTWINDOWS_EXPORT ShadowNodeBase : public facebook::react::ShadowNode { bool HasTransformPS() const { return m_transformPS != nullptr; } - winrt::Windows::UI::Composition::CompositionPropertySet EnsureTransformPS(); + comp::CompositionPropertySet EnsureTransformPS(); void UpdateTransformPS(); protected: XamlView m_view; bool m_updating = false; - winrt::Windows::UI::Composition::CompositionPropertySet m_transformPS{nullptr}; + comp::CompositionPropertySet m_transformPS{nullptr}; public: double m_padding[ShadowEdges::CountEdges] = INIT_UNDEFINED_EDGES; diff --git a/vnext/include/ReactUWP/XamlView.h b/vnext/include/ReactUWP/XamlView.h index 64db4919952..36e76be76a7 100644 --- a/vnext/include/ReactUWP/XamlView.h +++ b/vnext/include/ReactUWP/XamlView.h @@ -3,26 +3,19 @@ #pragma once -#include -#include - -namespace winrt { -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::Foundation; -} // namespace winrt +#include "CppWinRTIncludes.h" namespace react { namespace uwp { -using XamlView = winrt::DependencyObject; +using XamlView = xaml::DependencyObject; inline int64_t GetTag(XamlView view) { - return view.GetValue(winrt::FrameworkElement::TagProperty()).as().GetInt64(); + return view.GetValue(xaml::FrameworkElement::TagProperty()).as().GetInt64(); } inline void SetTag(XamlView view, int64_t tag) { - view.SetValue(winrt::FrameworkElement::TagProperty(), winrt::PropertyValue::CreateInt64(tag)); + view.SetValue(xaml::FrameworkElement::TagProperty(), winrt::PropertyValue::CreateInt64(tag)); } inline void SetTag(XamlView view, winrt::IInspectable tag) { @@ -39,9 +32,9 @@ inline int64_t GetTag(winrt::IPropertyValue value) { return value.GetInt64(); } -inline winrt::IPropertyValue GetTagAsPropertyValue(winrt::FrameworkElement fe) { +inline winrt::IPropertyValue GetTagAsPropertyValue(xaml::FrameworkElement fe) { assert(fe); - return fe.GetValue(winrt::FrameworkElement::TagProperty()).try_as(); + return fe.GetValue(xaml::FrameworkElement::TagProperty()).try_as(); } } // namespace uwp From ccbd12b30c0f0fba11329753b6a54d7a3ae14613 Mon Sep 17 00:00:00 2001 From: Kai Guo Date: Tue, 28 Apr 2020 09:59:57 -0700 Subject: [PATCH 011/209] Update react version (#4734) * Update react version * Change files --- ...e-windows-2020-04-27-20-28-42-fix-peerdependency.json | 8 ++++++++ packages/E2ETest/package.json | 4 ++-- vnext/package.json | 6 +++--- yarn.lock | 9 +++++++++ 4 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 change/react-native-windows-2020-04-27-20-28-42-fix-peerdependency.json diff --git a/change/react-native-windows-2020-04-27-20-28-42-fix-peerdependency.json b/change/react-native-windows-2020-04-27-20-28-42-fix-peerdependency.json new file mode 100644 index 00000000000..5c939f3595a --- /dev/null +++ b/change/react-native-windows-2020-04-27-20-28-42-fix-peerdependency.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Update react version", + "packageName": "react-native-windows", + "email": "kaigu@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-28T03:28:42.499Z" +} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index fa480484cbd..ec5ea8137e7 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -23,7 +23,7 @@ }, "dependencies": { "prompt-sync": "^4.2.0", - "react": "16.9.0", + "react": "16.11.0", "react-native": "0.62.2", "react-native-windows": "0.0.0-master.51" }, @@ -53,4 +53,4 @@ "webdriver": "git+https://github.com/react-native-windows/webdriver.git", "webdriverio": "5.12.1" } -} +} \ No newline at end of file diff --git a/vnext/package.json b/vnext/package.json index 78e485fc0a1..4125857e33f 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -52,14 +52,14 @@ "jscodeshift": "^0.6.2", "just-scripts": "^0.36.1", "prettier": "1.17.0", - "react": "16.9.0", + "react": "16.11.0", "react-native-windows-codegen": "0.0.3", "react-native-windows-override-tools": "^0.0.1", "react-native": "0.62.2", "typescript": "^3.8.3" }, "peerDependencies": { - "react": "16.9.0", + "react": "16.11.0", "react-native": "0.62.2" }, "beachball": { @@ -70,4 +70,4 @@ "patch" ] } -} +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 298a946aa6a..3f38168723e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11640,6 +11640,15 @@ react-test-renderer@16.9.0: react-is "^16.9.0" scheduler "^0.15.0" +react@16.11.0: + version "16.11.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb" + integrity sha512-M5Y8yITaLmU0ynd0r1Yvfq98Rmll6q8AxaEe88c8e7LxO8fZ2cNgmFt0aGAS9wzf1Ao32NKXtCl+/tVVtkxq6g== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + react@16.9.0: version "16.9.0" resolved "https://registry.yarnpkg.com/react/-/react-16.9.0.tgz#40ba2f9af13bc1a38d75dbf2f4359a5185c4f7aa" From 64144a989231a5573b665ac189ac015c6f007dfc Mon Sep 17 00:00:00 2001 From: dannyvv Date: Tue, 28 Apr 2020 13:51:23 -0700 Subject: [PATCH 012/209] Exclude test projects and proposals from being published in the npm package (#4737) * Exclude test projects and proposals from being published in the npm package * Change files --- .../react-native-windows-2020-04-28-10-19-13-master.json | 8 ++++++++ vnext/.npmignore | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 change/react-native-windows-2020-04-28-10-19-13-master.json diff --git a/change/react-native-windows-2020-04-28-10-19-13-master.json b/change/react-native-windows-2020-04-28-10-19-13-master.json new file mode 100644 index 00000000000..6a704cd76eb --- /dev/null +++ b/change/react-native-windows-2020-04-28-10-19-13-master.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Exclude unittests and proposals from being published in the npm package", + "packageName": "react-native-windows", + "email": "dannyvv@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-28T17:19:13.805Z" +} diff --git a/vnext/.npmignore b/vnext/.npmignore index d5ca56801b8..04b1d45695f 100644 --- a/vnext/.npmignore +++ b/vnext/.npmignore @@ -9,12 +9,18 @@ build CMakeLists.txt /Desktop Desktop.Dll +Desktop.ABITests Desktop.IntegrationTests +Desktop.Test.DLL Desktop.UnitTests FollyWin32 IntegrationTests IntegrationTestScripts +JSI.Desktop.UnitTests /NuGet.Config +Microsoft.ReactNative.Cxx.UnitTests +Microsoft.ReactNative.IntegrationTests +Microsoft.ReactNative.Managed.UnitTests package-deps.json packages react-native-windows.build.log @@ -23,6 +29,8 @@ ReactWindows-Universal.sln ReactWindows-Desktop.sln RNTester.* RNTester/ +Mso.UnitTests +proposals src/ target temp From f7be64d8089b847108d4722b219e321aa19a0d25 Mon Sep 17 00:00:00 2001 From: dannyvv Date: Tue, 28 Apr 2020 14:24:29 -0700 Subject: [PATCH 013/209] Update version number of the Azure DevOps PR validation step (#4738) --- .ado/windows-vs-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ado/windows-vs-pr.yml b/.ado/windows-vs-pr.yml index c38b149984a..410ce045095 100644 --- a/.ado/windows-vs-pr.yml +++ b/.ado/windows-vs-pr.yml @@ -1,5 +1,5 @@ # This file defines the Windows Visual Studio PR build steps used during the CI loop -name: $(Date:yyyyMMdd).$(Rev:.r) +name: $(Date:yyyyMMdd).$(Rev:r) trigger: none # will disable CI builds entirely From 808ca324a028a4a283848173954c98cf1418e2b6 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Wed, 29 Apr 2020 00:04:54 +0000 Subject: [PATCH 014/209] applying package updates ***NO_CI*** --- ...ve-windows-2020-04-25-00-45-24-wuxmux.json | 8 ------ ...020-04-27-20-28-42-fix-peerdependency.json | 8 ------ ...ve-windows-2020-04-28-10-19-13-master.json | 8 ------ packages/E2ETest/package.json | 4 +-- .../package.json | 2 +- packages/playground/package.json | 2 +- vnext/CHANGELOG.json | 27 +++++++++++++++++++ vnext/CHANGELOG.md | 12 ++++++++- vnext/package.json | 4 +-- 9 files changed, 44 insertions(+), 31 deletions(-) delete mode 100644 change/react-native-windows-2020-04-25-00-45-24-wuxmux.json delete mode 100644 change/react-native-windows-2020-04-27-20-28-42-fix-peerdependency.json delete mode 100644 change/react-native-windows-2020-04-28-10-19-13-master.json diff --git a/change/react-native-windows-2020-04-25-00-45-24-wuxmux.json b/change/react-native-windows-2020-04-25-00-45-24-wuxmux.json deleted file mode 100644 index 3bcc1973610..00000000000 --- a/change/react-native-windows-2020-04-25-00-45-24-wuxmux.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Start forking namespace and includes for WUX->MUX move", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-25T07:45:23.932Z" -} diff --git a/change/react-native-windows-2020-04-27-20-28-42-fix-peerdependency.json b/change/react-native-windows-2020-04-27-20-28-42-fix-peerdependency.json deleted file mode 100644 index 5c939f3595a..00000000000 --- a/change/react-native-windows-2020-04-27-20-28-42-fix-peerdependency.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Update react version", - "packageName": "react-native-windows", - "email": "kaigu@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-28T03:28:42.499Z" -} diff --git a/change/react-native-windows-2020-04-28-10-19-13-master.json b/change/react-native-windows-2020-04-28-10-19-13-master.json deleted file mode 100644 index 6a704cd76eb..00000000000 --- a/change/react-native-windows-2020-04-28-10-19-13-master.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Exclude unittests and proposals from being published in the npm package", - "packageName": "react-native-windows", - "email": "dannyvv@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-28T17:19:13.805Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index ec5ea8137e7..bc53deb2ace 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.51" + "react-native-windows": "0.0.0-master.52" }, "devDependencies": { "@babel/core": "^7.8.4", @@ -53,4 +53,4 @@ "webdriver": "git+https://github.com/react-native-windows/webdriver.git", "webdriverio": "5.12.1" } -} \ No newline at end of file +} diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 7f23d6ee126..9f4edb68262 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.9.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.51" + "react-native-windows": "0.0.0-master.52" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index e94fc798c83..6cb36921b4c 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.9.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.51" + "react-native-windows": "0.0.0-master.52" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index 33b68acc93c..f31b2ec6e99 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,33 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Wed, 29 Apr 2020 00:04:54 GMT", + "tag": "react-native-windows_v0.0.0-master.52", + "version": "0.0.0-master.52", + "comments": { + "prerelease": [ + { + "comment": "Start forking namespace and includes for WUX->MUX move", + "author": "asklar@microsoft.com", + "commit": "567fc48cf6858ece96ff60fcd52e20cded72cbfc", + "package": "react-native-windows" + }, + { + "comment": "Update react version", + "author": "kaigu@microsoft.com", + "commit": "ccbd12b30c0f0fba11329753b6a54d7a3ae14613", + "package": "react-native-windows" + }, + { + "comment": "Exclude unittests and proposals from being published in the npm package", + "author": "dannyvv@microsoft.com", + "commit": "64144a989231a5573b665ac189ac015c6f007dfc", + "package": "react-native-windows" + } + ] + } + }, { "date": "Tue, 28 Apr 2020 00:04:13 GMT", "tag": "react-native-windows_v0.0.0-master.51", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 5a00ceb2719..75f3b7612d5 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,19 @@ # Change Log - react-native-windows -This log was last generated on Tue, 28 Apr 2020 00:04:13 GMT and should not be manually modified. +This log was last generated on Wed, 29 Apr 2020 00:04:54 GMT and should not be manually modified. +## 0.0.0-master.52 + +Wed, 29 Apr 2020 00:04:54 GMT + +### Changes + +- Start forking namespace and includes for WUX->MUX move (asklar@microsoft.com) +- Update react version (kaigu@microsoft.com) +- Exclude unittests and proposals from being published in the npm package (dannyvv@microsoft.com) + ## 0.0.0-master.51 Tue, 28 Apr 2020 00:04:13 GMT diff --git a/vnext/package.json b/vnext/package.json index 4125857e33f..cf9f523eb2a 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.51", + "version": "0.0.0-master.52", "license": "MIT", "repository": { "type": "git", @@ -70,4 +70,4 @@ "patch" ] } -} \ No newline at end of file +} From ee00cce8da0f3fdc5a3ddb7ac7ced3e2dc01c2d5 Mon Sep 17 00:00:00 2001 From: kmelmon <33470154+kmelmon@users.noreply.github.com> Date: Tue, 28 Apr 2020 17:36:52 -0700 Subject: [PATCH 015/209] Auto-detect RTL locale and apply to root view (#4732) * implement allowRTL, forceRTL, and use RTLness on root * namespace rename * cleanup --- ...-windows-2020-04-27-16-11-30-allowRTL.json | 8 +++ .../ReactHost/ReactInstanceWin.cpp | 3 +- .../ReactHost/ReactInstanceWin.h | 1 - vnext/ReactUWP/Base/CoreNativeModules.cpp | 7 +-- vnext/ReactUWP/Base/CoreNativeModules.h | 1 - vnext/ReactUWP/Base/UwpReactInstance.cpp | 4 +- vnext/ReactUWP/Modules/I18nModule.cpp | 49 +++++++++++++++++-- vnext/ReactUWP/Modules/I18nModule.h | 31 ++++++++++-- vnext/ReactUWP/Modules/NativeUIManager.cpp | 9 +++- vnext/ReactWindowsCore/Modules/I18nModule.cpp | 10 +++- vnext/include/ReactWindowsCore/II18nModule.h | 8 +-- 11 files changed, 104 insertions(+), 27 deletions(-) create mode 100644 change/react-native-windows-2020-04-27-16-11-30-allowRTL.json diff --git a/change/react-native-windows-2020-04-27-16-11-30-allowRTL.json b/change/react-native-windows-2020-04-27-16-11-30-allowRTL.json new file mode 100644 index 00000000000..b45d80d551f --- /dev/null +++ b/change/react-native-windows-2020-04-27-16-11-30-allowRTL.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "auto-detect RTL and push into root view", + "packageName": "react-native-windows", + "email": "kmelmon@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-27T23:11:30.614Z" +} diff --git a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp index d365e4d2c18..d759d30a997 100644 --- a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +++ b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp @@ -155,7 +155,7 @@ void ReactInstanceWin::Initialize() noexcept { strongThis->m_deviceInfo = std::make_shared(legacyInstance); strongThis->m_appTheme = std::make_shared(legacyInstance, strongThis->m_uiMessageThread.LoadWithLock()); - strongThis->m_i18nInfo = react::uwp::I18nModule::GetI18nInfo(); + react::uwp::I18nHelper().Instance().setInfo(react::uwp::I18nModule::GetI18nInfo()); strongThis->m_appearanceListener = Mso::Make(legacyInstance); } }) @@ -200,7 +200,6 @@ void ReactInstanceWin::Initialize() noexcept { m_batchingUIThread, m_uiMessageThread.Load(), std::move(m_deviceInfo), - std::move(m_i18nInfo), std::move(m_appState), std::move(m_appTheme), std::move(m_appearanceListener), diff --git a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h index 0543bf8511d..717e4ded4eb 100644 --- a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +++ b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h @@ -155,7 +155,6 @@ class ReactInstanceWin final : public Mso::ActiveObject m_appState; std::shared_ptr m_redboxHandler; std::shared_ptr m_appTheme; - std::pair m_i18nInfo{}; Mso::CntPtr m_appearanceListener; std::string m_bundleRootPath; }; diff --git a/vnext/ReactUWP/Base/CoreNativeModules.cpp b/vnext/ReactUWP/Base/CoreNativeModules.cpp index 4662a6609e1..6b2ce9e013d 100644 --- a/vnext/ReactUWP/Base/CoreNativeModules.cpp +++ b/vnext/ReactUWP/Base/CoreNativeModules.cpp @@ -53,7 +53,6 @@ std::vector GetCoreModules( const std::shared_ptr &messageQueue, const std::shared_ptr &uiMessageQueue, std::shared_ptr &&deviceInfo, - I18nModule::I18nInfo &&i18nInfo, std::shared_ptr &&appstate, std::shared_ptr &&appTheme, Mso::CntPtr &&appearanceListener, @@ -119,11 +118,7 @@ std::vector GetCoreModules( messageQueue); modules.emplace_back( - "I18nManager", - [i18nInfo = std::move(i18nInfo)]() mutable { - return createI18nModule(std::make_unique(std::move(i18nInfo))); - }, - messageQueue); + "I18nManager", []() mutable { return createI18nModule(std::make_unique()); }, messageQueue); modules.emplace_back( AppearanceModule::Name, diff --git a/vnext/ReactUWP/Base/CoreNativeModules.h b/vnext/ReactUWP/Base/CoreNativeModules.h index f5ef3861f65..d04ad83cbf6 100644 --- a/vnext/ReactUWP/Base/CoreNativeModules.h +++ b/vnext/ReactUWP/Base/CoreNativeModules.h @@ -29,7 +29,6 @@ std::vector GetCoreModules( const std::shared_ptr &messageQueue, const std::shared_ptr &uiMessageQueue, std::shared_ptr &&deviceInfo, - I18nModule::I18nInfo &&i18nInfo, std::shared_ptr &&appstate, std::shared_ptr &&appTheme, Mso::CntPtr &&appearanceListener, diff --git a/vnext/ReactUWP/Base/UwpReactInstance.cpp b/vnext/ReactUWP/Base/UwpReactInstance.cpp index b0361d0ef8a..8fbabcb20ce 100644 --- a/vnext/ReactUWP/Base/UwpReactInstance.cpp +++ b/vnext/ReactUWP/Base/UwpReactInstance.cpp @@ -114,7 +114,7 @@ void UwpReactInstance::Start(const std::shared_ptr &spThis, cons std::shared_ptr appstate = std::make_shared(spThis); std::shared_ptr appTheme = std::make_shared(spThis, m_defaultNativeThread); - std::pair i18nInfo = I18nModule::GetI18nInfo(); + I18nHelper::Instance().setInfo(I18nModule::GetI18nInfo()); auto appearanceListener = Mso::Make(spThis); // TODO: Figure out threading. What thread should this really be on? @@ -124,7 +124,6 @@ void UwpReactInstance::Start(const std::shared_ptr &spThis, cons spThis, deviceInfo, settings, - i18nInfo = std::move(i18nInfo), appstate = std::move(appstate), appTheme = std::move(appTheme), appearanceListener = std::move(appearanceListener)]() mutable { @@ -203,7 +202,6 @@ void UwpReactInstance::Start(const std::shared_ptr &spThis, cons m_batchingNativeThread, m_defaultNativeThread, std::move(deviceInfo), - std::move(i18nInfo), std::move(appstate), std::move(appTheme), std::move(appearanceListener), diff --git a/vnext/ReactUWP/Modules/I18nModule.cpp b/vnext/ReactUWP/Modules/I18nModule.cpp index 4b73f3f9bc2..b7ed1f7e6c7 100644 --- a/vnext/ReactUWP/Modules/I18nModule.cpp +++ b/vnext/ReactUWP/Modules/I18nModule.cpp @@ -30,14 +30,55 @@ namespace uwp { return std::make_pair(std::move(locale), std::move(isRTL)); } -I18nModule::I18nModule(std::pair &&i18nInfo) : m_i18nInfo(std::move(i18nInfo)) {} +I18nModule::I18nModule() : m_helper(I18nHelper::Instance()) {} -std::string I18nModule::getLocaleIdentifier() { +std::string I18nModule::getLocaleIdentifier() const { + return m_helper.getLocaleIdentifier(); +} + +bool I18nModule::getIsRTL() const { + return m_helper.getIsRTL(); +} + +void I18nModule::setAllowRTL(bool allowRTL) { + m_helper.setAllowRTL(allowRTL); +} + +void I18nModule::setForceRTL(bool forceRTL) { + m_helper.setForceRTL(forceRTL); +} + +/*static*/ I18nHelper &I18nHelper::Instance() { + static I18nHelper theInstance; + return theInstance; +} + +I18nHelper::I18nHelper() {} + +void I18nHelper::setInfo(I18nModule::I18nInfo &&i18nInfo) { + m_i18nInfo = i18nInfo; +} + +std::string I18nHelper::getLocaleIdentifier() const { return m_i18nInfo.first; } -bool I18nModule::getIsRTL() { - return m_i18nInfo.second; +bool I18nHelper::getIsRTL() const { + if (m_forceRTL) { + // Used for debugging purposes, forces RTL even in LTR locales + return true; + } + + // If the app allows RTL (default is true), then we are in RTL if the locale is RTL + return m_allowRTL && m_i18nInfo.second; +} + +void I18nHelper::setAllowRTL(bool allowRTL) { + m_allowRTL = allowRTL; +} + +void I18nHelper::setForceRTL(bool forceRTL) { + m_forceRTL = forceRTL; } } // namespace uwp diff --git a/vnext/ReactUWP/Modules/I18nModule.h b/vnext/ReactUWP/Modules/I18nModule.h index 3e69295bab1..7a171d5209d 100644 --- a/vnext/ReactUWP/Modules/I18nModule.h +++ b/vnext/ReactUWP/Modules/I18nModule.h @@ -10,19 +10,42 @@ namespace react { namespace uwp { +class I18nHelper; + class I18nModule final : public react::windows::II18nModule { public: using I18nInfo = std::pair; static I18nInfo GetI18nInfo(); // Must be called from a UI thread // II18nModule - I18nModule(I18nInfo &&i18nInfo); + I18nModule(); - std::string getLocaleIdentifier() override; - bool getIsRTL() override; + std::string getLocaleIdentifier() const override; + bool getIsRTL() const override; + void setAllowRTL(bool allowRTL) override; + void setForceRTL(bool forceRTL) override; private: - I18nInfo m_i18nInfo; + I18nHelper &m_helper; }; + +class I18nHelper { + public: + static I18nHelper &Instance(); + + I18nHelper(); + + void setInfo(I18nModule::I18nInfo &&i18nInfo); + std::string getLocaleIdentifier() const; + bool getIsRTL() const; + void setAllowRTL(bool allowRTL); + void setForceRTL(bool forceRTL); + + private: + I18nModule::I18nInfo m_i18nInfo; + bool m_allowRTL{true}; + bool m_forceRTL{false}; +}; + } // namespace uwp } // namespace react diff --git a/vnext/ReactUWP/Modules/NativeUIManager.cpp b/vnext/ReactUWP/Modules/NativeUIManager.cpp index 39fde0f6657..14550121ac7 100644 --- a/vnext/ReactUWP/Modules/NativeUIManager.cpp +++ b/vnext/ReactUWP/Modules/NativeUIManager.cpp @@ -3,6 +3,7 @@ #include "pch.h" +#include "I18nModule.h" #include "NativeUIManager.h" #include @@ -185,6 +186,10 @@ void NativeUIManager::AddRootView( XamlView view = xamlRootView->GetXamlView(); m_tagsToXamlReactControl.emplace(shadowNode.m_tag, xamlRootView->GetXamlReactControl()); + // Push the appropriate FlowDirection into the root view. + view.as().FlowDirection( + I18nHelper::Instance().getIsRTL() ? xaml::FlowDirection::RightToLeft : xaml::FlowDirection::LeftToRight); + m_tagsToYogaNodes.emplace(shadowNode.m_tag, make_yoga_node()); auto element = view.as(); @@ -851,7 +856,9 @@ void NativeUIManager::DoLayout() { float actualWidth = static_cast(rootElement.ActualWidth()); float actualHeight = static_cast(rootElement.ActualHeight()); - // TODO: Real direction (VSO 1697992: RTL Layout) + // We must always run layout in LTR mode, which might seem unintuitive. + // We will flip the root of the tree into RTL by forcing the root XAML node's FlowDirection to RightToLeft + // which will inherit down the XAML tree, allowing all native controls to pick it up. YGNodeCalculateLayout(rootNode, actualWidth, actualHeight, YGDirectionLTR); for (auto &tagToYogaNode : m_tagsToYogaNodes) { diff --git a/vnext/ReactWindowsCore/Modules/I18nModule.cpp b/vnext/ReactWindowsCore/Modules/I18nModule.cpp index debb8da029f..824e5ff4707 100644 --- a/vnext/ReactWindowsCore/Modules/I18nModule.cpp +++ b/vnext/ReactWindowsCore/Modules/I18nModule.cpp @@ -2,6 +2,9 @@ // Licensed under the MIT License. #include "I18nModule.h" +#include + +using namespace facebook::xplat; namespace react { namespace windows { @@ -18,7 +21,10 @@ std::map I18nModule::getConstants() { } std::vector I18nModule::getMethods() { - return {}; + return { + Method("allowRTL", [this](folly::dynamic args) { this->m_module->setAllowRTL(jsArgAsBool(args, 0)); }), + Method("forceRTL", [this](folly::dynamic args) { this->m_module->setForceRTL(jsArgAsBool(args, 0)); }), + }; } std::unique_ptr createI18nModule(std::unique_ptr module) { @@ -26,4 +32,4 @@ std::unique_ptr createI18nModule(std::unique } } // namespace windows -} // namespace react \ No newline at end of file +} // namespace react diff --git a/vnext/include/ReactWindowsCore/II18nModule.h b/vnext/include/ReactWindowsCore/II18nModule.h index ce84ef1ade9..b2e0b0efee8 100644 --- a/vnext/include/ReactWindowsCore/II18nModule.h +++ b/vnext/include/ReactWindowsCore/II18nModule.h @@ -10,10 +10,12 @@ namespace windows { struct II18nModule { virtual ~II18nModule(){}; - virtual std::string getLocaleIdentifier() = 0; - virtual bool getIsRTL() = 0; + virtual std::string getLocaleIdentifier() const = 0; + virtual bool getIsRTL() const = 0; + virtual void setAllowRTL(bool allowRTL) = 0; + virtual void setForceRTL(bool forceRTL) = 0; }; std::unique_ptr createI18nModule(std::unique_ptr module); } // namespace windows -} // namespace react \ No newline at end of file +} // namespace react From 5edb66b341b6c36e85702eb2a7ea8953495affc9 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Wed, 29 Apr 2020 05:48:32 -0700 Subject: [PATCH 016/209] Expose Debug macro for hresult_error. Start catching these... (#4742) * Expose Debug macro for hresult_error. Start catching these... * Change files --- ...-native-windows-2020-04-29-03-28-07-debug_hresult.json | 8 ++++++++ vnext/ReactUWP/Views/Image/ReactImage.cpp | 5 ++++- vnext/include/ReactWindowsCore/cdebug.h | 5 +++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 change/react-native-windows-2020-04-29-03-28-07-debug_hresult.json diff --git a/change/react-native-windows-2020-04-29-03-28-07-debug_hresult.json b/change/react-native-windows-2020-04-29-03-28-07-debug_hresult.json new file mode 100644 index 00000000000..447fddf6bc8 --- /dev/null +++ b/change/react-native-windows-2020-04-29-03-28-07-debug_hresult.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Expose Debug macro for hresult_error. Start catching these...", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-29T10:28:07.247Z" +} diff --git a/vnext/ReactUWP/Views/Image/ReactImage.cpp b/vnext/ReactUWP/Views/Image/ReactImage.cpp index b8ac25c6780..791a3776ecc 100644 --- a/vnext/ReactUWP/Views/Image/ReactImage.cpp +++ b/vnext/ReactUWP/Views/Image/ReactImage.cpp @@ -10,6 +10,7 @@ #include #include "Unicode.h" +#include "cdebug.h" namespace winrt { using namespace Windows::Foundation; @@ -84,6 +85,7 @@ winrt::Stretch ReactImage::ResizeModeToStretch(react::uwp::ResizeMode value) { default: // ResizeMode::Center // This function should never be called for the 'repeat' resizeMode case. // That is handled by the shouldUseCompositionBrush/switchBrushes code path. + // #4691 assert(value != ResizeMode::Repeat); if (m_imageSource.height < ActualHeight() && m_imageSource.width < ActualWidth()) { @@ -328,7 +330,8 @@ winrt::IAsyncOperation GetImageStreamAsync(Re co_return memoryStream; } - } catch (winrt::hresult_error const &) { + } catch (winrt::hresult_error const &e) { + DEBUG_HRESULT_ERROR(e); } co_return nullptr; diff --git a/vnext/include/ReactWindowsCore/cdebug.h b/vnext/include/ReactWindowsCore/cdebug.h index 942db2420d8..6e5e861d5dc 100644 --- a/vnext/include/ReactWindowsCore/cdebug.h +++ b/vnext/include/ReactWindowsCore/cdebug.h @@ -35,3 +35,8 @@ class basic_dostream : public std::basic_ostream { extern basic_dostream cdebug; extern basic_dostream cwdebug; + +#define DEBUG_HRESULT_ERROR(e) \ + cdebug << __FILE__ << " (" << __LINE__ << ") "; \ + cdebug.flush(); \ + cwdebug << e.message().c_str() << std::endl; From 36ca14d11d0ff8029664d5e77f6b434111c9a6db Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Wed, 29 Apr 2020 07:17:50 -0700 Subject: [PATCH 017/209] Update tscodegen to version based on 0.62 (#4747) * Update tscodegen to version based on 0.62 * Change files --- ...s-codegen-2020-04-29-06-16-44-uptsgen.json | 8 +++ .../react-native-windows-codegen/package.json | 3 +- yarn.lock | 61 ++----------------- 3 files changed, 13 insertions(+), 59 deletions(-) create mode 100644 change/react-native-windows-codegen-2020-04-29-06-16-44-uptsgen.json diff --git a/change/react-native-windows-codegen-2020-04-29-06-16-44-uptsgen.json b/change/react-native-windows-codegen-2020-04-29-06-16-44-uptsgen.json new file mode 100644 index 00000000000..27712a20db0 --- /dev/null +++ b/change/react-native-windows-codegen-2020-04-29-06-16-44-uptsgen.json @@ -0,0 +1,8 @@ +{ + "type": "patch", + "comment": "Update tscodegen to version based on 0.62", + "packageName": "react-native-windows-codegen", + "email": "acoates@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-29T13:16:44.451Z" +} diff --git a/packages/react-native-windows-codegen/package.json b/packages/react-native-windows-codegen/package.json index a9b190bdec3..b0528933186 100644 --- a/packages/react-native-windows-codegen/package.json +++ b/packages/react-native-windows-codegen/package.json @@ -18,8 +18,7 @@ "dependencies": { "chalk": "^3", "globby": "^9.2.0", - "react-native-tscodegen": "0.0.10", - "react-native-codegen": "0.0.2", + "react-native-tscodegen": "0.62.1", "yargs": "^15.1.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 3f38168723e..80435892b73 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4198,11 +4198,6 @@ ast-types@0.11.7: resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.7.tgz#f318bf44e339db6a320be0009ded64ec1471f46c" integrity sha512-2mP3TwtkY/aTv5X3ZsMpNAbOnyoC/aMJwJSoaELPkHId0nSQgFcnU4dRW3isxiz7+zBexk0ym3WNVjMiQBnJSw== -ast-types@0.13.3: - version "0.13.3" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.3.tgz#50da3f28d17bdbc7969a3a2d83a0e4a72ae755a7" - integrity sha512-XTZ7xGML849LkQP86sWdQzfhwbt3YwIO6MqbX9mUNYY98VKaaVZP7YNNm70IpwecbkkxmfC5IYAzOQ/2p29zRA== - astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" @@ -6966,11 +6961,6 @@ flow-parser@0.*: resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.113.0.tgz#5b5913c54833918d0c3136ba69f6cf0cdd85fc20" integrity sha512-+hRyEB1sVLNMTMniDdM1JIS8BJ3HUL7IFIJaxX+t/JUy0GNYdI0Tg1QLx8DJmOF8HeoCrUDcREpnDAc/pPta3w== -flow-parser@^0.121.0: - version "0.121.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.121.0.tgz#9f9898eaec91a9f7c323e9e992d81ab5c58e618f" - integrity sha512-1gIBiWJNR0tKUNv8gZuk7l9rVX06OuLzY9AoGio7y/JT4V1IZErEMEq2TJS+PFcw/y0RshZ1J/27VfK1UQzYVg== - flush-write-stream@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" @@ -8738,30 +8728,6 @@ jscodeshift@0.6.4, jscodeshift@^0.6.2: temp "^0.8.1" write-file-atomic "^2.3.0" -jscodeshift@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.7.0.tgz#4eee7506fd4fdacbd80340287d61575af991fdab" - integrity sha512-Kt6rpTa1HVhAWagD6J0y6qxxqRmDgkFvczerLgOsDNSGoUZSmq2CO1vFRcda9OV1BaZKSHCIh+VREPts5tB/Ig== - dependencies: - "@babel/core" "^7.1.6" - "@babel/parser" "^7.1.6" - "@babel/plugin-proposal-class-properties" "^7.1.0" - "@babel/plugin-proposal-object-rest-spread" "^7.0.0" - "@babel/preset-env" "^7.1.6" - "@babel/preset-flow" "^7.0.0" - "@babel/preset-typescript" "^7.1.0" - "@babel/register" "^7.0.0" - babel-core "^7.0.0-bridge.0" - colors "^1.1.2" - flow-parser "0.*" - graceful-fs "^4.1.11" - micromatch "^3.1.10" - neo-async "^2.5.0" - node-dir "^0.1.17" - recast "^0.18.1" - temp "^0.8.1" - write-file-atomic "^2.3.0" - jsdom@^11.5.1: version "11.12.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" @@ -11570,19 +11536,10 @@ react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-native-codegen@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.0.2.tgz#2a1c15a9deb80b62a5e9c0f215bb29900216f7ee" - integrity sha512-cZ28TUlYanjpca6dcxyGmZi4JKTmeaE4vJhjTABMRD+R7Rw6FtTAUqU2BoAKksEsrf8dJN5pQEUOSb4Cv0502Q== - dependencies: - flow-parser "^0.121.0" - jscodeshift "^0.7.0" - nullthrows "^1.1.1" - -react-native-tscodegen@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/react-native-tscodegen/-/react-native-tscodegen-0.0.10.tgz#2997f039625e55aac91a367ac3d6b496c50f1265" - integrity sha512-MwG76JC/YpelWgcOmPQIiYdIAL+4uwafFROVUMNHI1ko5LkSay1sY1D7FDdAq9fXE0kZoHna7YHD50DR6CLj8w== +react-native-tscodegen@0.62.1: + version "0.62.1" + resolved "https://registry.yarnpkg.com/react-native-tscodegen/-/react-native-tscodegen-0.62.1.tgz#a52b01f1d515a12ebf22487d88cb58452d8e3210" + integrity sha512-fhEzT6pgHuo08mGZwtOZCTAhg+XcNdK0eUwes2x/vCbFzpKm8N3FOq3EMJ9dI9XnNe0DItxWGdRWjeo/DFisJA== dependencies: jscodeshift "0.6.4" nullthrows "1.1.1" @@ -11801,16 +11758,6 @@ recast@^0.16.1: private "~0.1.5" source-map "~0.6.1" -recast@^0.18.1: - version "0.18.10" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.18.10.tgz#605ebbe621511eb89b6356a7e224bff66ed91478" - integrity sha512-XNvYvkfdAN9QewbrxeTOjgINkdY/odTgTS56ZNEWL9Ml0weT4T3sFtvnTuF+Gxyu46ANcRm1ntrF6F5LAJPAaQ== - dependencies: - ast-types "0.13.3" - esprima "~4.0.0" - private "^0.1.8" - source-map "~0.6.1" - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" From d33450d9b0b88411616bf31c7aeb3f6e526405d6 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2020 10:17:03 -0700 Subject: [PATCH 018/209] Bump @types/react-native from 0.62.4 to 0.62.5 (#4748) Bumps [@types/react-native](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-native) from 0.62.4 to 0.62.5. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-native) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 80435892b73..79f7e21a6f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2895,9 +2895,9 @@ integrity sha1-Hs9SYhKZ5luFU3Qzf7Ef0tEGb8E= "@types/react-native@^0.62.2": - version "0.62.4" - resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.62.4.tgz#0aea6619a19de1c6994ce8e4175fc4e44409bcdb" - integrity sha512-AKImyybUzqqPItKNuURkMe7y1X5cxuSJh5td8qbFSEXO58S5qjw01eZweWkKyTVCvrWGXkfm43u1zoYcZSGL6w== + version "0.62.5" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.62.5.tgz#605c2d31485c515ee18b62e8b29ffdbba404a443" + integrity sha512-x6ZBbo752yAw5XUarOyh53oNgMuafL4EhWEbd4ARSMK6Y7nTRm2a1tBHy8Fp7h7ji0XXJrxNRTXGJRRP3+MWzg== dependencies: "@types/react" "*" From 297e217a48d2795b75f88a986ab5d344a384aa42 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Wed, 29 Apr 2020 10:42:00 -0700 Subject: [PATCH 019/209] Remove unnecessary CLI elevation (#4745) * Try uninstalling without elevation in case since it is not needed for layout installs (debug) * Change files --- ...-native-windows-2020-04-29-10-09-33-tryUninstall2.json | 8 ++++++++ vnext/local-cli/runWindows/utils/WindowsStoreAppUtils.ps1 | 7 ++++++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 change/react-native-windows-2020-04-29-10-09-33-tryUninstall2.json diff --git a/change/react-native-windows-2020-04-29-10-09-33-tryUninstall2.json b/change/react-native-windows-2020-04-29-10-09-33-tryUninstall2.json new file mode 100644 index 00000000000..75bcac12ce6 --- /dev/null +++ b/change/react-native-windows-2020-04-29-10-09-33-tryUninstall2.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Try uninstalling without elevation in case since it is not needed for layout installs (debug)", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-29T17:09:33.939Z" +} diff --git a/vnext/local-cli/runWindows/utils/WindowsStoreAppUtils.ps1 b/vnext/local-cli/runWindows/utils/WindowsStoreAppUtils.ps1 index 21b83fe5137..8e2da36859f 100644 --- a/vnext/local-cli/runWindows/utils/WindowsStoreAppUtils.ps1 +++ b/vnext/local-cli/runWindows/utils/WindowsStoreAppUtils.ps1 @@ -63,7 +63,12 @@ function Uninstall-App { if($package) { $pfn = $package.PackageFullName - Invoke-Expression-MayElevate "Remove-AppxPackage $pfn -ErrorAction Stop" -ErrorAction Stop + $command = "Remove-AppxPackage $pfn -ErrorAction Stop" + try { + Invoke-Expression $command + } catch { + Invoke-Expression-MayElevate $command -ErrorAction Stop + } } } From f923f9890441ad5aa6340c95bf412441165c3fcc Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Wed, 29 Apr 2020 13:57:07 -0700 Subject: [PATCH 020/209] Refactor TestHook out of ViewManagerBase and special case layout properties (#4741) * Refactor TestHook out of ViewManagerBase and special case layout properties * Change files * PR and get playground win32 building * format and remove debug in the header --- ...-windows-2020-04-29-03-21-18-testhook.json | 8 ++ .../Microsoft.ReactNative.vcxproj | 2 + .../Microsoft.ReactNative.vcxproj.filters | 10 +- vnext/Microsoft.ReactNative/TestHook.cpp | 103 ++++++++++++++++++ vnext/Microsoft.ReactNative/TestHook.h | 15 +++ .../Microsoft.ReactNative/getLayoutProps.ps1 | 5 + vnext/ReactUWP/ReactUWP.vcxproj | 4 +- vnext/ReactUWP/ReactUWP.vcxproj.filters | 1 + vnext/ReactUWP/TestHookMock.cpp | 7 ++ vnext/ReactUWP/Views/ViewManagerBase.cpp | 38 +------ .../include/ReactUWP/Views/ViewManagerBase.h | 10 +- 11 files changed, 150 insertions(+), 53 deletions(-) create mode 100644 change/react-native-windows-2020-04-29-03-21-18-testhook.json create mode 100644 vnext/Microsoft.ReactNative/TestHook.cpp create mode 100644 vnext/Microsoft.ReactNative/TestHook.h create mode 100644 vnext/Microsoft.ReactNative/getLayoutProps.ps1 create mode 100644 vnext/ReactUWP/TestHookMock.cpp diff --git a/change/react-native-windows-2020-04-29-03-21-18-testhook.json b/change/react-native-windows-2020-04-29-03-21-18-testhook.json new file mode 100644 index 00000000000..3e1c6f1a455 --- /dev/null +++ b/change/react-native-windows-2020-04-29-03-21-18-testhook.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Refactor TestHook out of ViewManagerBase and special case layout properties", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-29T10:21:18.921Z" +} diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj index c5e68931833..57d6d88ea13 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj @@ -331,6 +331,7 @@ + @@ -488,6 +489,7 @@ + diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters index 3b221e531d0..e53f5484d2f 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters @@ -92,9 +92,6 @@ Modules - - Modules - Modules @@ -318,6 +315,8 @@ Views + + @@ -410,9 +409,6 @@ Modules - - Modules - Modules @@ -674,6 +670,8 @@ Views + + diff --git a/vnext/Microsoft.ReactNative/TestHook.cpp b/vnext/Microsoft.ReactNative/TestHook.cpp new file mode 100644 index 00000000000..dc686a34c3f --- /dev/null +++ b/vnext/Microsoft.ReactNative/TestHook.cpp @@ -0,0 +1,103 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#include "pch.h" +#include "TestHook.h" +#include + +#ifdef DEBUG + +// Obtained from https://reactnative.dev/docs/layout-props +// See getLayoutProps.ps1 next to this file. +std::vector TestHook::layoutProperties = { + "alignContent", + "alignItems", + "alignSelf", + "aspectRatio", + "borderBottomWidth", + "borderEndWidth", + "borderLeftWidth", + "borderRightWidth", + "borderStartWidth", + "borderTopWidth", + "borderWidth", + "bottom", + "direction", + "display", + "end", + "flex", + "flexBasis", + "flexDirection", + "flexGrow", + "flexShrink", + "flexWrap", + "height", + "justifyContent", + "left", + "margin", + "marginBottom", + "marginEnd", + "marginHorizontal", + "marginLeft", + "marginRight", + "marginStart", + "marginTop", + "marginVertical", + "maxHeight", + "maxWidth", + "minHeight", + "minWidth", + "overflow", + "padding", + "paddingBottom", + "paddingEnd", + "paddingHorizontal", + "paddingLeft", + "paddingRight", + "paddingStart", + "paddingTop", + "paddingVertical", + "position", + "right", + "start", + "top", + "width", + "zIndex", +}; + +void TestHook::NotifyUnimplementedProperty( + const std::string &viewManager, + const std::string &reactClassName, + const std::string &propertyName, + const folly::dynamic &propertyValue) { + if (std::find(layoutProperties.begin(), layoutProperties.end(), propertyName) != layoutProperties.end()) { + return; + } + std::string value; + size_t size{}; + try { + if (propertyValue.isObject()) { + value = "[Object]"; + } else if (propertyValue.isNull()) { + value = "[Null]"; + } else if (propertyValue.isArray()) { + size = propertyValue.size(); + value = "[Array]"; + } else { + value = propertyValue.asString(); + } + } catch (const folly::TypeError &e) { + value = e.what(); + } + + cdebug << "[UnimplementedProperty] ViewManager = " << viewManager << " elementClass = " << reactClassName + << " propertyName = " << propertyName << " value = " << value; + + if (size != 0) { + cdebug << " (" << size << " elems)"; + } + + cdebug << std::endl; + // DebugBreak(); +} + +#endif // DEBUG diff --git a/vnext/Microsoft.ReactNative/TestHook.h b/vnext/Microsoft.ReactNative/TestHook.h new file mode 100644 index 00000000000..c5dc3983a1c --- /dev/null +++ b/vnext/Microsoft.ReactNative/TestHook.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#pragma once +#include +#include +#include + +struct TestHook { + static void NotifyUnimplementedProperty( + const std::string &viewManager, + const std::string &reactClassName, + const std::string &propertyName, + const folly::dynamic &propertyValue); + static std::vector layoutProperties; +}; diff --git a/vnext/Microsoft.ReactNative/getLayoutProps.ps1 b/vnext/Microsoft.ReactNative/getLayoutProps.ps1 new file mode 100644 index 00000000000..0a222f0219e --- /dev/null +++ b/vnext/Microsoft.ReactNative/getLayoutProps.ps1 @@ -0,0 +1,5 @@ +# This script produces the values for the layoutProperties vector +# in TestHook.cpp +$page = Invoke-WebRequest "https://reactnative.dev/docs/layout-props" +$lines = $page.Content.Split('') | select -skip 1 +$lines -replace ('\n','') -replace ('.*', '') | % { Write-Host "`"$_`", "} \ No newline at end of file diff --git a/vnext/ReactUWP/ReactUWP.vcxproj b/vnext/ReactUWP/ReactUWP.vcxproj index 03c65e65794..b1882e5948e 100644 --- a/vnext/ReactUWP/ReactUWP.vcxproj +++ b/vnext/ReactUWP/ReactUWP.vcxproj @@ -119,7 +119,8 @@ $(ReactNativeWindowsDir)Shared; $(ReactNativeWindowsDir)stubs; $(YogaDir); - %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories); + $(ReactNativeWindowsDir)Microsoft.ReactNative; $(ChakraCoreInclude);$(ChakraCoreDebugInclude);%(AdditionalIncludeDirectories) /await %(AdditionalOptions) @@ -280,6 +281,7 @@ + diff --git a/vnext/ReactUWP/ReactUWP.vcxproj.filters b/vnext/ReactUWP/ReactUWP.vcxproj.filters index 72f9ca1a9bc..30f2d7c7f54 100644 --- a/vnext/ReactUWP/ReactUWP.vcxproj.filters +++ b/vnext/ReactUWP/ReactUWP.vcxproj.filters @@ -323,6 +323,7 @@ Views + diff --git a/vnext/ReactUWP/TestHookMock.cpp b/vnext/ReactUWP/TestHookMock.cpp new file mode 100644 index 00000000000..7a5af1951d7 --- /dev/null +++ b/vnext/ReactUWP/TestHookMock.cpp @@ -0,0 +1,7 @@ +#include "TestHook.h" + +void TestHook::NotifyUnimplementedProperty( + const std::string &, + const std::string &, + const std::string &, + const folly::dynamic &) {} diff --git a/vnext/ReactUWP/Views/ViewManagerBase.cpp b/vnext/ReactUWP/Views/ViewManagerBase.cpp index 9723ceca252..239be0a7da4 100644 --- a/vnext/ReactUWP/Views/ViewManagerBase.cpp +++ b/vnext/ReactUWP/Views/ViewManagerBase.cpp @@ -13,6 +13,7 @@ #include #include +#include #include using namespace folly; @@ -275,43 +276,6 @@ void ViewManagerBase::NotifyUnimplementedProperty( #endif // DEBUG } -#ifdef DEBUG - -void ViewManagerBase::TestHook::NotifyUnimplementedProperty( - const std::string &viewManager, - const std::string &reactClassName, - const std::string &propertyName, - const folly::dynamic &propertyValue) { - std::string value; - size_t size{}; - try { - if (propertyValue.isObject()) { - value = "[Object]"; - } else if (propertyValue.isNull()) { - value = "[Null]"; - } else if (propertyValue.isArray()) { - size = propertyValue.size(); - value = "[Array]"; - } else { - value = propertyValue.asString(); - } - } catch (const TypeError &e) { - value = e.what(); - } - - cdebug << "[UnimplementedProperty] ViewManager = " << viewManager << " elementClass = " << reactClassName - << " propertyName = " << propertyName << " value = " << value; - - if (size != 0) { - cdebug << " (" << size << " elems)"; - } - - cdebug << std::endl; - // DebugBreak(); -} - -#endif // DEBUG - void ViewManagerBase::SetLayoutProps( ShadowNodeBase &nodeToUpdate, const XamlView &viewToUpdate, diff --git a/vnext/include/ReactUWP/Views/ViewManagerBase.h b/vnext/include/ReactUWP/Views/ViewManagerBase.h index ea959424f1c..fab7fad114e 100644 --- a/vnext/include/ReactUWP/Views/ViewManagerBase.h +++ b/vnext/include/ReactUWP/Views/ViewManagerBase.h @@ -92,15 +92,7 @@ class REACTWINDOWS_EXPORT ViewManagerBase : public facebook::react::IViewManager ShadowNodeBase *nodeToUpdate, const std::string &propertyName, const folly::dynamic &value); -#ifdef DEBUG - struct TestHook { - static void NotifyUnimplementedProperty( - const std::string &viewManager, - const std::string &reactClassName, - const std::string &propertyName, - const folly::dynamic &propertyValue); - }; -#endif + protected: std::weak_ptr m_wkReactInstance; }; From 800850c8e945aee6620f3aede38bdb323e2a0116 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Thu, 30 Apr 2020 00:04:27 +0000 Subject: [PATCH 021/209] applying package updates ***NO_CI*** --- ...-windows-2020-04-27-16-11-30-allowRTL.json | 8 ----- ...-windows-2020-04-29-03-21-18-testhook.json | 8 ----- ...ows-2020-04-29-03-28-07-debug_hresult.json | 8 ----- ...ows-2020-04-29-10-09-33-tryUninstall2.json | 8 ----- ...s-codegen-2020-04-29-06-16-44-uptsgen.json | 8 ----- packages/E2ETest/package.json | 2 +- .../package.json | 4 +-- packages/playground/package.json | 2 +- .../CHANGELOG.json | 15 +++++++++ .../react-native-windows-codegen/CHANGELOG.md | 10 +++++- .../react-native-windows-codegen/package.json | 2 +- vnext/CHANGELOG.json | 33 +++++++++++++++++++ vnext/CHANGELOG.md | 13 +++++++- vnext/package.json | 4 +-- 14 files changed, 76 insertions(+), 49 deletions(-) delete mode 100644 change/react-native-windows-2020-04-27-16-11-30-allowRTL.json delete mode 100644 change/react-native-windows-2020-04-29-03-21-18-testhook.json delete mode 100644 change/react-native-windows-2020-04-29-03-28-07-debug_hresult.json delete mode 100644 change/react-native-windows-2020-04-29-10-09-33-tryUninstall2.json delete mode 100644 change/react-native-windows-codegen-2020-04-29-06-16-44-uptsgen.json diff --git a/change/react-native-windows-2020-04-27-16-11-30-allowRTL.json b/change/react-native-windows-2020-04-27-16-11-30-allowRTL.json deleted file mode 100644 index b45d80d551f..00000000000 --- a/change/react-native-windows-2020-04-27-16-11-30-allowRTL.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "auto-detect RTL and push into root view", - "packageName": "react-native-windows", - "email": "kmelmon@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-27T23:11:30.614Z" -} diff --git a/change/react-native-windows-2020-04-29-03-21-18-testhook.json b/change/react-native-windows-2020-04-29-03-21-18-testhook.json deleted file mode 100644 index 3e1c6f1a455..00000000000 --- a/change/react-native-windows-2020-04-29-03-21-18-testhook.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Refactor TestHook out of ViewManagerBase and special case layout properties", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-29T10:21:18.921Z" -} diff --git a/change/react-native-windows-2020-04-29-03-28-07-debug_hresult.json b/change/react-native-windows-2020-04-29-03-28-07-debug_hresult.json deleted file mode 100644 index 447fddf6bc8..00000000000 --- a/change/react-native-windows-2020-04-29-03-28-07-debug_hresult.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Expose Debug macro for hresult_error. Start catching these...", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-29T10:28:07.247Z" -} diff --git a/change/react-native-windows-2020-04-29-10-09-33-tryUninstall2.json b/change/react-native-windows-2020-04-29-10-09-33-tryUninstall2.json deleted file mode 100644 index 75bcac12ce6..00000000000 --- a/change/react-native-windows-2020-04-29-10-09-33-tryUninstall2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Try uninstalling without elevation in case since it is not needed for layout installs (debug)", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-29T17:09:33.939Z" -} diff --git a/change/react-native-windows-codegen-2020-04-29-06-16-44-uptsgen.json b/change/react-native-windows-codegen-2020-04-29-06-16-44-uptsgen.json deleted file mode 100644 index 27712a20db0..00000000000 --- a/change/react-native-windows-codegen-2020-04-29-06-16-44-uptsgen.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "patch", - "comment": "Update tscodegen to version based on 0.62", - "packageName": "react-native-windows-codegen", - "email": "acoates@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-29T13:16:44.451Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index bc53deb2ace..ea71a09ca05 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.52" + "react-native-windows": "0.0.0-master.53" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 9f4edb68262..fb7b45b6ef2 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.9.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.52" + "react-native-windows": "0.0.0-master.53" }, "devDependencies": { "@babel/core": "^7.8.4", @@ -25,7 +25,7 @@ "@types/react-native": "^0.62.2", "just-scripts": "^0.36.1", "metro-react-native-babel-preset": "^0.56.0", - "react-native-windows-codegen": "0.0.3", + "react-native-windows-codegen": "0.0.4", "react-test-renderer": "16.9.0" } } diff --git a/packages/playground/package.json b/packages/playground/package.json index 6cb36921b4c..0994c1e8902 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.9.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.52" + "react-native-windows": "0.0.0-master.53" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/react-native-windows-codegen/CHANGELOG.json b/packages/react-native-windows-codegen/CHANGELOG.json index a40d2b8d583..882b6be68e3 100644 --- a/packages/react-native-windows-codegen/CHANGELOG.json +++ b/packages/react-native-windows-codegen/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "react-native-windows-codegen", "entries": [ + { + "date": "Thu, 30 Apr 2020 00:04:27 GMT", + "tag": "react-native-windows-codegen_v0.0.4", + "version": "0.0.4", + "comments": { + "patch": [ + { + "comment": "Update tscodegen to version based on 0.62", + "author": "acoates@microsoft.com", + "commit": "36ca14d11d0ff8029664d5e77f6b434111c9a6db", + "package": "react-native-windows-codegen" + } + ] + } + }, { "date": "Fri, 24 Apr 2020 00:04:41 GMT", "tag": "react-native-windows-codegen_v0.0.3", diff --git a/packages/react-native-windows-codegen/CHANGELOG.md b/packages/react-native-windows-codegen/CHANGELOG.md index 61f1815a0be..b5414211345 100644 --- a/packages/react-native-windows-codegen/CHANGELOG.md +++ b/packages/react-native-windows-codegen/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - react-native-windows-codegen -This log was last generated on Fri, 24 Apr 2020 00:04:41 GMT and should not be manually modified. +This log was last generated on Thu, 30 Apr 2020 00:04:27 GMT and should not be manually modified. +## 0.0.4 + +Thu, 30 Apr 2020 00:04:27 GMT + +### Patches + +- Update tscodegen to version based on 0.62 (acoates@microsoft.com) + ## 0.0.3 Fri, 24 Apr 2020 00:04:41 GMT diff --git a/packages/react-native-windows-codegen/package.json b/packages/react-native-windows-codegen/package.json index b0528933186..c3c43a368ee 100644 --- a/packages/react-native-windows-codegen/package.json +++ b/packages/react-native-windows-codegen/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows-codegen", - "version": "0.0.3", + "version": "0.0.4", "description": "Generators for react-native-codegen targeting react-native-windows", "main": "index.js", "repository": "https://github.com/microsoft/react-native-windows", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index f31b2ec6e99..acf75ab2578 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,39 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Thu, 30 Apr 2020 00:04:27 GMT", + "tag": "react-native-windows_v0.0.0-master.53", + "version": "0.0.0-master.53", + "comments": { + "prerelease": [ + { + "comment": "auto-detect RTL and push into root view", + "author": "kmelmon@microsoft.com", + "commit": "ee00cce8da0f3fdc5a3ddb7ac7ced3e2dc01c2d5", + "package": "react-native-windows" + }, + { + "comment": "Refactor TestHook out of ViewManagerBase and special case layout properties", + "author": "asklar@microsoft.com", + "commit": "f923f9890441ad5aa6340c95bf412441165c3fcc", + "package": "react-native-windows" + }, + { + "comment": "Expose Debug macro for hresult_error. Start catching these...", + "author": "asklar@microsoft.com", + "commit": "5edb66b341b6c36e85702eb2a7ea8953495affc9", + "package": "react-native-windows" + }, + { + "comment": "Try uninstalling without elevation in case since it is not needed for layout installs (debug)", + "author": "asklar@microsoft.com", + "commit": "297e217a48d2795b75f88a986ab5d344a384aa42", + "package": "react-native-windows" + } + ] + } + }, { "date": "Wed, 29 Apr 2020 00:04:54 GMT", "tag": "react-native-windows_v0.0.0-master.52", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 75f3b7612d5..4418cedb15b 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,20 @@ # Change Log - react-native-windows -This log was last generated on Wed, 29 Apr 2020 00:04:54 GMT and should not be manually modified. +This log was last generated on Thu, 30 Apr 2020 00:04:27 GMT and should not be manually modified. +## 0.0.0-master.53 + +Thu, 30 Apr 2020 00:04:27 GMT + +### Changes + +- auto-detect RTL and push into root view (kmelmon@microsoft.com) +- Refactor TestHook out of ViewManagerBase and special case layout properties (asklar@microsoft.com) +- Expose Debug macro for hresult_error. Start catching these... (asklar@microsoft.com) +- Try uninstalling without elevation in case since it is not needed for layout installs (debug) (asklar@microsoft.com) + ## 0.0.0-master.52 Wed, 29 Apr 2020 00:04:54 GMT diff --git a/vnext/package.json b/vnext/package.json index cf9f523eb2a..8335ad9665b 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.52", + "version": "0.0.0-master.53", "license": "MIT", "repository": { "type": "git", @@ -53,7 +53,7 @@ "just-scripts": "^0.36.1", "prettier": "1.17.0", "react": "16.11.0", - "react-native-windows-codegen": "0.0.3", + "react-native-windows-codegen": "0.0.4", "react-native-windows-override-tools": "^0.0.1", "react-native": "0.62.2", "typescript": "^3.8.3" From 1ec1663d3790ce33fb62db297d324c097d7f163b Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Wed, 29 Apr 2020 21:17:02 -0700 Subject: [PATCH 022/209] .net projects need more work to build a package layout (#4751) * .net projects need more work to build a package layout * Change files * make async --- ...react-native-windows-2020-04-29-18-21-26-4749.json | 8 ++++++++ vnext/local-cli/runWindows/runWindows.js | 5 +++-- vnext/local-cli/runWindows/utils/deploy.js | 11 +++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 change/react-native-windows-2020-04-29-18-21-26-4749.json diff --git a/change/react-native-windows-2020-04-29-18-21-26-4749.json b/change/react-native-windows-2020-04-29-18-21-26-4749.json new file mode 100644 index 00000000000..86abe8e9a6b --- /dev/null +++ b/change/react-native-windows-2020-04-29-18-21-26-4749.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": ".net projects need more work to build a package layout", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-30T01:21:26.428Z" +} diff --git a/vnext/local-cli/runWindows/runWindows.js b/vnext/local-cli/runWindows/runWindows.js index dc2fe0d4bd3..d233c5e87a3 100644 --- a/vnext/local-cli/runWindows/runWindows.js +++ b/vnext/local-cli/runWindows/runWindows.js @@ -25,6 +25,7 @@ function ExitProcessWithError(loggingWasEnabled) { async function runWindows(config, args, options) { const verbose = options.logging; + if (verbose) { newInfo('Verbose: ON'); } @@ -47,12 +48,12 @@ async function runWindows(config, args, options) { // Fix up options options.root = options.root || process.cwd(); + const slnFile = options.sln || build.getSolutionFile(options); if (options.autolink) { autolink.updateAutoLink(verbose); } if (options.build) { - const slnFile = options.sln || build.getSolutionFile(options); if (!slnFile) { newError( 'Visual Studio Solution file not found. Maybe run "react-native windows" first?', @@ -101,7 +102,7 @@ async function runWindows(config, args, options) { if (options.device || options.emulator || options.target) { await deploy.deployToDevice(options, verbose); } else { - await deploy.deployToDesktop(options, verbose); + await deploy.deployToDesktop(options, verbose, slnFile); } } catch (e) { newError(`Failed to deploy${e ? `: ${e.message}` : ''}`); diff --git a/vnext/local-cli/runWindows/utils/deploy.js b/vnext/local-cli/runWindows/utils/deploy.js index 31b88396e97..b302f84a6bb 100644 --- a/vnext/local-cli/runWindows/utils/deploy.js +++ b/vnext/local-cli/runWindows/utils/deploy.js @@ -159,7 +159,13 @@ async function deployToDevice(options, verbose) { } } -async function deployToDesktop(options, verbose) { +async function hasDotNetProjects(slnFile) { + const contents = (await fs.promises.readFile(slnFile)).toString(); + let r = /\"([^"]+\.(csproj|vbproj))\"/; + return r.test(contents); +} + +async function deployToDesktop(options, verbose, slnFile) { const appPackageFolder = getAppPackage(options); const windowsStoreAppUtils = getWindowsStoreAppUtils(options); const appxManifestPath = getAppxManifestPath(options); @@ -202,7 +208,8 @@ async function deployToDesktop(options, verbose) { verbose, ); - if (options.release) { + // #4749 - need to deploy from appx for .net projects. + if (options.release || (await hasDotNetProjects(slnFile))) { await runPowerShellScriptFunction( 'Installing new version of the app', windowsStoreAppUtils, From 15ad43e230f3523beb3efead10d642e1eaab2b13 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Thu, 30 Apr 2020 09:02:12 -0700 Subject: [PATCH 023/209] Expose YellowBox functionality to native code (#4740) * Change files * don't need sstream yet * const noexcept --- ...eact-native-windows-2020-04-29-02-59-44-yellowbox.json | 8 ++++++++ vnext/ReactUWP/Polyester/IconViewManager.cpp | 8 +++++--- vnext/ReactUWP/Views/ShadowNodeBase.cpp | 7 +++++++ vnext/include/ReactUWP/Views/ShadowNodeBase.h | 2 ++ 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 change/react-native-windows-2020-04-29-02-59-44-yellowbox.json diff --git a/change/react-native-windows-2020-04-29-02-59-44-yellowbox.json b/change/react-native-windows-2020-04-29-02-59-44-yellowbox.json new file mode 100644 index 00000000000..4cf803a33b7 --- /dev/null +++ b/change/react-native-windows-2020-04-29-02-59-44-yellowbox.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Expose YellowBox functionality to native code", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-29T09:59:44.174Z" +} diff --git a/vnext/ReactUWP/Polyester/IconViewManager.cpp b/vnext/ReactUWP/Polyester/IconViewManager.cpp index 10a43507480..1be6ee0d005 100644 --- a/vnext/ReactUWP/Polyester/IconViewManager.cpp +++ b/vnext/ReactUWP/Polyester/IconViewManager.cpp @@ -65,9 +65,11 @@ void IconShadowNode::updateProperties(const folly::dynamic &&props) { if (propertyName == "color") { if (IsValidColorValue(propertyValue)) glyphs.Fill(BrushFrom(propertyValue)); -#if FUTURE - else if (propertyValue.isNull()) - ; // Log error, must have a color +#ifdef DEBUG + else if (propertyValue.isNull()) { + // Log error, must have a color + YellowBox("IconShadowNode - color property must be non-null"); + } #endif } else if (propertyName == "fontUri") { if (propertyValue.isString()) { diff --git a/vnext/ReactUWP/Views/ShadowNodeBase.cpp b/vnext/ReactUWP/Views/ShadowNodeBase.cpp index 7a4e28e9981..f4d22f70f03 100644 --- a/vnext/ReactUWP/Views/ShadowNodeBase.cpp +++ b/vnext/ReactUWP/Views/ShadowNodeBase.cpp @@ -154,5 +154,12 @@ void ShadowNodeBase::EnsureHandledKeyboardEventHandler() { } } +void ShadowNodeBase::YellowBox(const std::string &message) const noexcept { + const auto instance = GetViewManager()->GetReactInstance().lock(); + if (instance) { + instance->CallJsFunction("RCTLog", "logToConsole", folly::dynamic::array("warn", message)); + } +} + } // namespace uwp } // namespace react diff --git a/vnext/include/ReactUWP/Views/ShadowNodeBase.h b/vnext/include/ReactUWP/Views/ShadowNodeBase.h index a81260c8201..1c988f9be80 100644 --- a/vnext/include/ReactUWP/Views/ShadowNodeBase.h +++ b/vnext/include/ReactUWP/Views/ShadowNodeBase.h @@ -68,6 +68,8 @@ struct REACTWINDOWS_EXPORT ShadowNodeBase : public facebook::react::ShadowNode { return false; } + void YellowBox(const std::string &message) const noexcept; + ViewManagerBase *GetViewManager() const; XamlView GetView() const { return m_view; From 1ca0c2916ac29d3646a35d0e90c8bee8c6cda8d2 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Thu, 30 Apr 2020 11:27:09 -0700 Subject: [PATCH 024/209] Package Version Fixes (#4752) * Package Fixes 1. Use looser peer dependencies on React Native. 0.61 specified 0.61.5 explicitly, but based on recent discussion we want to allow patch releases of RN to work on any RNW version. Allow prerelease versions as well for any special forks, etc. 2. Fixup React Version everywhere. I missed upgraded React dependencies during the 0.62 upgrade. This was fixed in vnext and e2etest with #4734 but other packages were not updated. Update everything here. * Change files --- ...t-native-win32-2020-04-29-23-49-30-version-fixes.json | 8 ++++++++ ...native-windows-2020-04-29-23-49-30-version-fixes.json | 8 ++++++++ packages/microsoft-reactnative-sampleapps/package.json | 2 +- packages/playground/package.json | 2 +- packages/react-native-win32/package.json | 6 +++--- vnext/package.json | 2 +- yarn.lock | 9 --------- 7 files changed, 22 insertions(+), 15 deletions(-) create mode 100644 change/@office-iss-react-native-win32-2020-04-29-23-49-30-version-fixes.json create mode 100644 change/react-native-windows-2020-04-29-23-49-30-version-fixes.json diff --git a/change/@office-iss-react-native-win32-2020-04-29-23-49-30-version-fixes.json b/change/@office-iss-react-native-win32-2020-04-29-23-49-30-version-fixes.json new file mode 100644 index 00000000000..48952bc34d8 --- /dev/null +++ b/change/@office-iss-react-native-win32-2020-04-29-23-49-30-version-fixes.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Package Fixes", + "packageName": "@office-iss/react-native-win32", + "email": "ngerlem@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-30T06:49:27.467Z" +} diff --git a/change/react-native-windows-2020-04-29-23-49-30-version-fixes.json b/change/react-native-windows-2020-04-29-23-49-30-version-fixes.json new file mode 100644 index 00000000000..d2dbe4c3b8c --- /dev/null +++ b/change/react-native-windows-2020-04-29-23-49-30-version-fixes.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Package Fixes", + "packageName": "react-native-windows", + "email": "ngerlem@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-30T06:49:30.516Z" +} diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index fb7b45b6ef2..daf958c0908 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -14,7 +14,7 @@ "windows": "react-native run-windows" }, "dependencies": { - "react": "16.9.0", + "react": "16.11.0", "react-native": "0.62.2", "react-native-windows": "0.0.0-master.53" }, diff --git a/packages/playground/package.json b/packages/playground/package.json index 0994c1e8902..ea364aee0dc 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -9,7 +9,7 @@ "windows": "react-native run-windows" }, "dependencies": { - "react": "16.9.0", + "react": "16.11.0", "react-native": "0.62.2", "react-native-windows": "0.0.0-master.53" }, diff --git a/packages/react-native-win32/package.json b/packages/react-native-win32/package.json index 275c1c1d759..d77265364ff 100644 --- a/packages/react-native-win32/package.json +++ b/packages/react-native-win32/package.json @@ -53,16 +53,16 @@ "flow-bin": "^0.113.0", "jscodeshift": "^0.6.2", "just-scripts": "^0.36.1", - "react": "16.9.0", + "react": "16.11.0", "react-native-windows-override-tools": "^0.0.1", "react-native": "0.62.2", "rimraf": "^3.0.0", "typescript": "^3.8.3" }, "peerDependencies": { - "react": "16.9.0", + "react": "16.11.0", "react-dom": "16.8.6", - "react-native": "0.62.2" + "react-native": "^0.62.0-0" }, "beachball": { "defaultNpmTag": "master", diff --git a/vnext/package.json b/vnext/package.json index 8335ad9665b..f8bd01054e4 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -60,7 +60,7 @@ }, "peerDependencies": { "react": "16.11.0", - "react-native": "0.62.2" + "react-native": "^0.62.0-0" }, "beachball": { "defaultNpmTag": "master", diff --git a/yarn.lock b/yarn.lock index 79f7e21a6f4..98497fe560a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11606,15 +11606,6 @@ react@16.11.0: object-assign "^4.1.1" prop-types "^15.6.2" -react@16.9.0: - version "16.9.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.9.0.tgz#40ba2f9af13bc1a38d75dbf2f4359a5185c4f7aa" - integrity sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - read-cmd-shim@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.4.tgz#b4a53d43376211b45243f0072b6e603a8e37640d" From 0f2fca4c1a49288840fb640a530d0503e9c36ea3 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Thu, 30 Apr 2020 11:27:32 -0700 Subject: [PATCH 025/209] Stop publishing ReactUwp NuGet Package (#4753) * Stop publishing ReactHwp NuGet Package We no longer support ReactUwp in 0.62. Stop publishing a NuGet package with it. * Change files * Remove stale variable * Remove another stale var --- .ado/publish.yml | 4 +- .ado/templates/prep-and-pack-nuget.yml | 20 -------- ...2020-04-30-00-06-54-no-reactuwp-nuget.json | 8 +++ vnext/Scripts/ReactUwp.nuspec | 49 ------------------- 4 files changed, 9 insertions(+), 72 deletions(-) create mode 100644 change/react-native-windows-2020-04-30-00-06-54-no-reactuwp-nuget.json delete mode 100644 vnext/Scripts/ReactUwp.nuspec diff --git a/.ado/publish.yml b/.ado/publish.yml index 249427d156a..b3240970283 100644 --- a/.ado/publish.yml +++ b/.ado/publish.yml @@ -162,9 +162,7 @@ jobs: parameters: artifactName: ReactWindows layoutHeaders: eq('true', variables['LayoutHeaders']) - contents: | - ReactUWP\** - Microsoft.ReactNative\** + contents: Microsoft.ReactNative\** # Disable for now, not sure this works on github projects anyway. # - task: PublishSymbols@2 diff --git a/.ado/templates/prep-and-pack-nuget.yml b/.ado/templates/prep-and-pack-nuget.yml index f998c54a93c..4ffbdfa76e8 100644 --- a/.ado/templates/prep-and-pack-nuget.yml +++ b/.ado/templates/prep-and-pack-nuget.yml @@ -5,11 +5,9 @@ parameters: nugetroot: $(System.DefaultWorkingDirectory)\ReactWindows desktopId: 'OfficeReact.Win32' microsoftRNId: 'Microsoft.ReactNative' - universalId: 'OfficeReact.UWP' slices: '("x64.Release", "x64.Debug", "x86.Release", "x86.Debug", "ARM.Release", "ARM.Debug", "ARM64.Release", "ARM64.Debug")' packDesktop: true packMicrosoft: true - packUniversal: true steps: - task: DownloadBuildArtifacts@0 @@ -19,14 +17,6 @@ steps: downloadPath: $(System.DefaultWorkingDirectory) # Strip down the binaries from nuget because we may not have built all the flavours. - - task: PowerShell@2 - displayName: Strip slices from ReactUwp.nuspec - inputs: - targetType: filePath - filePath: $(System.DefaultWorkingDirectory)\ReactWindows\StripAdditionalPlatformsFromNuspec.ps1 - arguments: -nuspec $(System.DefaultWorkingDirectory)/ReactWindows/ReactUWP.nuspec -outfile $(System.DefaultWorkingDirectory)/ReactWindows/ReactUWP.nuspec -slices ("x64.Release", "x86.Debug", "ARM.Release") - condition: and(succeeded(), ${{ parameters.packUniversal }}) - - task: PowerShell@2 displayName: Strip slices from Microsoft.ReactNative.nuspec inputs: @@ -45,16 +35,6 @@ steps: buildProperties: CommitId=${{parameters.publishCommitId}};version=${{parameters.npmVersion}};id=${{parameters.desktopId}};nugetroot=${{parameters.nugetroot}} condition: and(succeeded(), ${{ parameters.packDesktop }}) - - task: NuGetCommand@2 - displayName: 'NuGet pack Universal' - inputs: - command: pack - verbosityPack: 'Detailed' - packagesToPack: $(System.DefaultWorkingDirectory)/ReactWindows/ReactUWP.nuspec - packDestination: $(System.DefaultWorkingDirectory)/NugetRootFinal - buildProperties: CommitId=${{parameters.publishCommitId}};version=${{parameters.npmVersion}};id=${{parameters.universalId}};nugetroot=${{parameters.nugetroot}} - condition: and(succeeded(), ${{ parameters.packUniversal }}) - - task: NuGetCommand@2 displayName: 'NuGet pack Microsoft.ReactNative' inputs: diff --git a/change/react-native-windows-2020-04-30-00-06-54-no-reactuwp-nuget.json b/change/react-native-windows-2020-04-30-00-06-54-no-reactuwp-nuget.json new file mode 100644 index 00000000000..e63acbadba4 --- /dev/null +++ b/change/react-native-windows-2020-04-30-00-06-54-no-reactuwp-nuget.json @@ -0,0 +1,8 @@ +{ + "type": "none", + "comment": "Stop publishing ReactHwp NuGet Package", + "packageName": "react-native-windows", + "email": "ngerlem@microsoft.com", + "dependentChangeType": "none", + "date": "2020-04-30T07:06:54.439Z" +} diff --git a/vnext/Scripts/ReactUwp.nuspec b/vnext/Scripts/ReactUwp.nuspec deleted file mode 100644 index 166125d65b6..00000000000 --- a/vnext/Scripts/ReactUwp.nuspec +++ /dev/null @@ -1,49 +0,0 @@ - - - - $id$ - $version$ - Contains Windows Implementation of React-Native - Microsoft - https://github.com/microsoft/react-native-windows - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 3e1e61d677b0688aaa664203034ea037ca43aac5 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Thu, 30 Apr 2020 18:40:40 +0000 Subject: [PATCH 026/209] applying package updates ***NO_CI*** --- ...n32-2020-04-29-23-49-30-version-fixes.json | 8 ----- ...windows-2020-04-29-02-59-44-yellowbox.json | 8 ----- ...tive-windows-2020-04-29-18-21-26-4749.json | 8 ----- ...ows-2020-04-29-23-49-30-version-fixes.json | 8 ----- ...2020-04-30-00-06-54-no-reactuwp-nuget.json | 8 ----- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- packages/react-native-win32/CHANGELOG.json | 15 ++++++++ packages/react-native-win32/CHANGELOG.md | 10 +++++- packages/react-native-win32/package.json | 2 +- vnext/CHANGELOG.json | 35 +++++++++++++++++++ vnext/CHANGELOG.md | 12 ++++++- vnext/package.json | 2 +- 14 files changed, 75 insertions(+), 47 deletions(-) delete mode 100644 change/@office-iss-react-native-win32-2020-04-29-23-49-30-version-fixes.json delete mode 100644 change/react-native-windows-2020-04-29-02-59-44-yellowbox.json delete mode 100644 change/react-native-windows-2020-04-29-18-21-26-4749.json delete mode 100644 change/react-native-windows-2020-04-29-23-49-30-version-fixes.json delete mode 100644 change/react-native-windows-2020-04-30-00-06-54-no-reactuwp-nuget.json diff --git a/change/@office-iss-react-native-win32-2020-04-29-23-49-30-version-fixes.json b/change/@office-iss-react-native-win32-2020-04-29-23-49-30-version-fixes.json deleted file mode 100644 index 48952bc34d8..00000000000 --- a/change/@office-iss-react-native-win32-2020-04-29-23-49-30-version-fixes.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Package Fixes", - "packageName": "@office-iss/react-native-win32", - "email": "ngerlem@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-30T06:49:27.467Z" -} diff --git a/change/react-native-windows-2020-04-29-02-59-44-yellowbox.json b/change/react-native-windows-2020-04-29-02-59-44-yellowbox.json deleted file mode 100644 index 4cf803a33b7..00000000000 --- a/change/react-native-windows-2020-04-29-02-59-44-yellowbox.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Expose YellowBox functionality to native code", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-29T09:59:44.174Z" -} diff --git a/change/react-native-windows-2020-04-29-18-21-26-4749.json b/change/react-native-windows-2020-04-29-18-21-26-4749.json deleted file mode 100644 index 86abe8e9a6b..00000000000 --- a/change/react-native-windows-2020-04-29-18-21-26-4749.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": ".net projects need more work to build a package layout", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-30T01:21:26.428Z" -} diff --git a/change/react-native-windows-2020-04-29-23-49-30-version-fixes.json b/change/react-native-windows-2020-04-29-23-49-30-version-fixes.json deleted file mode 100644 index d2dbe4c3b8c..00000000000 --- a/change/react-native-windows-2020-04-29-23-49-30-version-fixes.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Package Fixes", - "packageName": "react-native-windows", - "email": "ngerlem@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-30T06:49:30.516Z" -} diff --git a/change/react-native-windows-2020-04-30-00-06-54-no-reactuwp-nuget.json b/change/react-native-windows-2020-04-30-00-06-54-no-reactuwp-nuget.json deleted file mode 100644 index e63acbadba4..00000000000 --- a/change/react-native-windows-2020-04-30-00-06-54-no-reactuwp-nuget.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "none", - "comment": "Stop publishing ReactHwp NuGet Package", - "packageName": "react-native-windows", - "email": "ngerlem@microsoft.com", - "dependentChangeType": "none", - "date": "2020-04-30T07:06:54.439Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index ea71a09ca05..fe9b7518092 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.53" + "react-native-windows": "0.0.0-master.54" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index daf958c0908..5281f6aa552 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.53" + "react-native-windows": "0.0.0-master.54" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index ea364aee0dc..bf7cedb1882 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.53" + "react-native-windows": "0.0.0-master.54" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/react-native-win32/CHANGELOG.json b/packages/react-native-win32/CHANGELOG.json index 8ee394f3883..17f4bbc4265 100644 --- a/packages/react-native-win32/CHANGELOG.json +++ b/packages/react-native-win32/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@office-iss/react-native-win32", "entries": [ + { + "date": "Thu, 30 Apr 2020 18:40:40 GMT", + "tag": "@office-iss/react-native-win32_v0.0.0-master.7", + "version": "0.0.0-master.7", + "comments": { + "prerelease": [ + { + "comment": "Package Fixes", + "author": "ngerlem@microsoft.com", + "commit": "1ca0c2916ac29d3646a35d0e90c8bee8c6cda8d2", + "package": "@office-iss/react-native-win32" + } + ] + } + }, { "date": "Tue, 28 Apr 2020 00:04:13 GMT", "tag": "@office-iss/react-native-win32_v0.0.0-master.6", diff --git a/packages/react-native-win32/CHANGELOG.md b/packages/react-native-win32/CHANGELOG.md index 15432ae1647..40992726e67 100644 --- a/packages/react-native-win32/CHANGELOG.md +++ b/packages/react-native-win32/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @office-iss/react-native-win32 -This log was last generated on Sat, 18 Apr 2020 00:04:34 GMT and should not be manually modified. +This log was last generated on Thu, 30 Apr 2020 18:40:40 GMT and should not be manually modified. +## 0.0.0-master.7 + +Thu, 30 Apr 2020 18:40:40 GMT + +### Changes + +- Package Fixes (ngerlem@microsoft.com) + ## 0.0.0-master.6 Sat, 18 Apr 2020 00:04:34 GMT diff --git a/packages/react-native-win32/package.json b/packages/react-native-win32/package.json index d77265364ff..02f68f70fff 100644 --- a/packages/react-native-win32/package.json +++ b/packages/react-native-win32/package.json @@ -1,6 +1,6 @@ { "name": "@office-iss/react-native-win32", - "version": "0.0.0-master.6", + "version": "0.0.0-master.7", "description": "Implementation of react native on top of Office's Win32 platform.", "license": "MIT", "main": "./index.win32.js", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index acf75ab2578..665cde97e71 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,41 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Thu, 30 Apr 2020 18:40:40 GMT", + "tag": "react-native-windows_v0.0.0-master.54", + "version": "0.0.0-master.54", + "comments": { + "prerelease": [ + { + "comment": "Expose YellowBox functionality to native code", + "author": "asklar@microsoft.com", + "commit": "15ad43e230f3523beb3efead10d642e1eaab2b13", + "package": "react-native-windows" + }, + { + "comment": ".net projects need more work to build a package layout", + "author": "asklar@microsoft.com", + "commit": "1ec1663d3790ce33fb62db297d324c097d7f163b", + "package": "react-native-windows" + }, + { + "comment": "Package Fixes", + "author": "ngerlem@microsoft.com", + "commit": "1ca0c2916ac29d3646a35d0e90c8bee8c6cda8d2", + "package": "react-native-windows" + } + ], + "none": [ + { + "comment": "Stop publishing ReactHwp NuGet Package", + "author": "ngerlem@microsoft.com", + "commit": "0f2fca4c1a49288840fb640a530d0503e9c36ea3", + "package": "react-native-windows" + } + ] + } + }, { "date": "Thu, 30 Apr 2020 00:04:27 GMT", "tag": "react-native-windows_v0.0.0-master.53", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 4418cedb15b..bc1c33a8244 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,19 @@ # Change Log - react-native-windows -This log was last generated on Thu, 30 Apr 2020 00:04:27 GMT and should not be manually modified. +This log was last generated on Thu, 30 Apr 2020 18:40:40 GMT and should not be manually modified. +## 0.0.0-master.54 + +Thu, 30 Apr 2020 18:40:40 GMT + +### Changes + +- Expose YellowBox functionality to native code (asklar@microsoft.com) +- .net projects need more work to build a package layout (asklar@microsoft.com) +- Package Fixes (ngerlem@microsoft.com) + ## 0.0.0-master.53 Thu, 30 Apr 2020 00:04:27 GMT diff --git a/vnext/package.json b/vnext/package.json index f8bd01054e4..493163612e8 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.53", + "version": "0.0.0-master.54", "license": "MIT", "repository": { "type": "git", From 2a86937f668952eecb9a3e661da8887ec5c8ce6e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2020 18:44:15 +0000 Subject: [PATCH 027/209] Bump @babel/runtime from 7.9.2 to 7.9.6 (#4758) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 98497fe560a..e852c22084c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -912,9 +912,9 @@ regenerator-runtime "^0.13.4" "@babel/runtime@^7.0.0", "@babel/runtime@^7.4.3", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.4": - version "7.9.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" - integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f" + integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ== dependencies: regenerator-runtime "^0.13.4" From 95a1987c7448efbe271e5dd0b3e9d8cb5251c529 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2020 18:44:42 +0000 Subject: [PATCH 028/209] Bump @babel/preset-env from 7.9.5 to 7.9.6 (#4756) --- yarn.lock | 148 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 77 insertions(+), 71 deletions(-) diff --git a/yarn.lock b/yarn.lock index e852c22084c..2b625105ad4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,12 +9,12 @@ dependencies: "@babel/highlight" "^7.8.3" -"@babel/compat-data@^7.8.6", "@babel/compat-data@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c" - integrity sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g== +"@babel/compat-data@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.6.tgz#3f604c40e420131affe6f2c8052e9a275ae2049b" + integrity sha512-5QPTrNen2bm7RBc7dsOmcA5hbrS4O2Vhmk5XOL4zWW/zD/hV0iinpefDlkm+tBBy8kDtFaaeEvmAqt+nURAV2g== dependencies: - browserslist "^4.9.1" + browserslist "^4.11.1" invariant "^2.2.4" semver "^5.5.0" @@ -83,13 +83,13 @@ "@babel/types" "^7.3.0" esutils "^2.0.0" -"@babel/helper-compilation-targets@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde" - integrity sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw== +"@babel/helper-compilation-targets@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.9.6.tgz#1e05b7ccc9d38d2f8b40b458b380a04dcfadd38a" + integrity sha512-x2Nvu0igO0ejXzx09B/1fGBxY9NXQlBW2kZsSxCJft+KHN8t9XWzIvFxtPHnBOAXpVsdxZKZFbRUC8TsNKajMw== dependencies: - "@babel/compat-data" "^7.8.6" - browserslist "^4.9.1" + "@babel/compat-data" "^7.9.6" + browserslist "^4.11.1" invariant "^2.2.4" levenary "^1.1.1" semver "^5.5.0" @@ -339,10 +339,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz#3fd65911306d8746014ec0d0cf78f0e39a149116" - integrity sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg== +"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz#7a093586fcb18b08266eb1a7177da671ac575b63" + integrity sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" @@ -589,34 +589,34 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-modules-amd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz#19755ee721912cf5bb04c07d50280af3484efef4" - integrity sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q== +"@babel/plugin-transform-modules-amd@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.6.tgz#8539ec42c153d12ea3836e0e3ac30d5aae7b258e" + integrity sha512-zoT0kgC3EixAyIAU+9vfaUVKTv9IxBDSabgHoUCBP6FqEJ+iNiN7ip7NBKcYqbfUDfuC2mFCbM7vbu4qJgOnDw== dependencies: "@babel/helper-module-transforms" "^7.9.0" "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" + babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940" - integrity sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g== +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz#64b7474a4279ee588cacd1906695ca721687c277" + integrity sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ== dependencies: "@babel/helper-module-transforms" "^7.9.0" "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-simple-access" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" + babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz#e9fd46a296fc91e009b64e07ddaa86d6f0edeb90" - integrity sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ== +"@babel/plugin-transform-modules-systemjs@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.6.tgz#207f1461c78a231d5337a92140e52422510d81a4" + integrity sha512-NW5XQuW3N2tTHim8e1b7qGy7s0kZ2OH3m5octc49K1SdAKGxYxeIx7hiIz05kS1R2R+hOWcsr1eYwcGhrdHsrg== dependencies: "@babel/helper-hoist-variables" "^7.8.3" "@babel/helper-module-transforms" "^7.9.0" "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" + babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-modules-umd@^7.9.0": version "7.9.0" @@ -799,12 +799,12 @@ regenerator-runtime "^0.13.2" "@babel/preset-env@^7.1.6", "@babel/preset-env@^7.8.4": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.5.tgz#8ddc76039bc45b774b19e2fc548f6807d8a8919f" - integrity sha512-eWGYeADTlPJH+wq1F0wNfPbVS1w1wtmMJiYk55Td5Yu28AsdR9AsC97sZ0Qq8fHqQuslVSIYSGJMcblr345GfQ== + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.6.tgz#df063b276c6455ec6fcfc6e53aacc38da9b0aea6" + integrity sha512-0gQJ9RTzO0heXOhzftog+a/WyOuqMrAIugVYxMYf83gh1CQaQDjMtsOpqOwXyDL/5JcWsrCm8l4ju8QC97O7EQ== dependencies: - "@babel/compat-data" "^7.9.0" - "@babel/helper-compilation-targets" "^7.8.7" + "@babel/compat-data" "^7.9.6" + "@babel/helper-compilation-targets" "^7.9.6" "@babel/helper-module-imports" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-proposal-async-generator-functions" "^7.8.3" @@ -812,7 +812,7 @@ "@babel/plugin-proposal-json-strings" "^7.8.3" "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-proposal-numeric-separator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.9.5" + "@babel/plugin-proposal-object-rest-spread" "^7.9.6" "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" "@babel/plugin-proposal-optional-chaining" "^7.9.0" "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" @@ -839,9 +839,9 @@ "@babel/plugin-transform-function-name" "^7.8.3" "@babel/plugin-transform-literals" "^7.8.3" "@babel/plugin-transform-member-expression-literals" "^7.8.3" - "@babel/plugin-transform-modules-amd" "^7.9.0" - "@babel/plugin-transform-modules-commonjs" "^7.9.0" - "@babel/plugin-transform-modules-systemjs" "^7.9.0" + "@babel/plugin-transform-modules-amd" "^7.9.6" + "@babel/plugin-transform-modules-commonjs" "^7.9.6" + "@babel/plugin-transform-modules-systemjs" "^7.9.6" "@babel/plugin-transform-modules-umd" "^7.9.0" "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" "@babel/plugin-transform-new-target" "^7.8.3" @@ -857,8 +857,8 @@ "@babel/plugin-transform-typeof-symbol" "^7.8.4" "@babel/plugin-transform-unicode-regex" "^7.8.3" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.9.5" - browserslist "^4.9.1" + "@babel/types" "^7.9.6" + browserslist "^4.11.1" core-js-compat "^3.6.2" invariant "^2.2.2" levenary "^1.1.1" @@ -942,10 +942,10 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.8.7", "@babel/types@^7.9.0", "@babel/types@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" - integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg== +"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.8.7", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" + integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== dependencies: "@babel/helper-validator-identifier" "^7.9.5" lodash "^4.17.13" @@ -4335,10 +4335,10 @@ babel-jest@^24.9.0: chalk "^2.4.2" slash "^2.0.0" -babel-plugin-dynamic-import-node@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: object.assign "^4.1.0" @@ -4647,14 +4647,15 @@ browser-resolve@^1.11.3: dependencies: resolve "1.1.7" -browserslist@^4.8.3, browserslist@^4.9.1: - version "4.9.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.9.1.tgz#01ffb9ca31a1aef7678128fc6a2253316aa7287c" - integrity sha512-Q0DnKq20End3raFulq6Vfp1ecB9fh8yUNV55s8sekaDDeqBaCtWlRHCUdaWyUeSSBJM7IbM6HcsyaeYqgeDhnw== +browserslist@^4.11.1, browserslist@^4.8.3: + version "4.12.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" + integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== dependencies: - caniuse-lite "^1.0.30001030" - electron-to-chromium "^1.3.363" - node-releases "^1.1.50" + caniuse-lite "^1.0.30001043" + electron-to-chromium "^1.3.413" + node-releases "^1.1.53" + pkg-up "^2.0.0" bser@^2.0.0: version "2.1.0" @@ -4894,10 +4895,10 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-lite@^1.0.30001030: - version "1.0.30001032" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001032.tgz#b8d224914e2cd7f507085583d4e38144c652bce4" - integrity sha512-8joOm7BwcpEN4BfVHtfh0hBXSAPVYk+eUIcNntGtMkUWy/6AKRCDZINCLe3kB1vHhT2vBxBF85Hh9VlPXi/qjA== +caniuse-lite@^1.0.30001043: + version "1.0.30001048" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001048.tgz#4bb4f1bc2eb304e5e1154da80b93dee3f1cf447e" + integrity sha512-g1iSHKVxornw0K8LG9LLdf+Fxnv7T1Z+mMsf0/YYLclQX4Cd522Ap0Lrw6NFqHgezit78dtyWxzlV2Xfc7vgRg== capture-exit@^2.0.0: version "2.0.0" @@ -6042,10 +6043,10 @@ ejs@^2.5.7: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.2.tgz#3a32c63d1cd16d11266cd4703b14fec4e74ab4f6" integrity sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q== -electron-to-chromium@^1.3.363: - version "1.3.368" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.368.tgz#d7597e04339f7ca70762031ec473d38eb2df6acb" - integrity sha512-fqzDipW3p+uDkHUHFPrdW3wINRKcJsbnJwBD7hgaQEQwcuLSvNLw6SeUp5gKDpTbmTl7zri7IZfhsdTUTnygJg== +electron-to-chromium@^1.3.413: + version "1.3.425" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.425.tgz#96b7b5aa9115e42baf59be88d2432c9f406128c4" + integrity sha512-JTEOWiqCY4snuKuQAaFy0z6LK2Gdb8Lojkd/csQwpNHgMUF8I6QRjGVKk44IH46dHQhUFKzr4o6zxZrtDBjc2Q== emits@1.0.x: version "1.0.2" @@ -6900,7 +6901,7 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.0.0: +find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= @@ -10342,12 +10343,10 @@ node-pre-gyp@^0.12.0: semver "^5.3.0" tar "^4" -node-releases@^1.1.50: - version "1.1.50" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.50.tgz#803c40d2c45db172d0410e4efec83aa8c6ad0592" - integrity sha512-lgAmPv9eYZ0bGwUYAKlr8MG6K4CvWliWqnkcT2P8mMAgVrH3lqfBPorFlxiG1pHQnqmavJZ9vbMXUTNyMLbrgQ== - dependencies: - semver "^6.3.0" +node-releases@^1.1.53: + version "1.1.53" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" + integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ== node-simctl@^5.0.0, node-simctl@^5.0.1, node-simctl@^5.0.2: version "5.1.0" @@ -11177,6 +11176,13 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= + dependencies: + find-up "^2.1.0" + please-upgrade-node@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" From 9d9a541aa40c4af2950cf784b5ba0ada935686c4 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Thu, 30 Apr 2020 13:05:31 -0700 Subject: [PATCH 029/209] Removed the ref count work around from classes derived from ReactApplication (#4755) * Removed the ref count work around from classes derived from ReactApplications * Change files --- ...8-22-39-MS_RemoveReactAppRefCountHack.json | 8 +++ .../windows/SampleAppCPP/App.cpp | 5 -- .../ReactApplication.cpp | 14 ++++- .../Microsoft.ReactNative/ReactApplication.h | 55 +++++++++++++++++-- .../templates/cpp/src/App.cpp | 5 -- 5 files changed, 71 insertions(+), 16 deletions(-) create mode 100644 change/react-native-windows-2020-04-30-08-22-39-MS_RemoveReactAppRefCountHack.json diff --git a/change/react-native-windows-2020-04-30-08-22-39-MS_RemoveReactAppRefCountHack.json b/change/react-native-windows-2020-04-30-08-22-39-MS_RemoveReactAppRefCountHack.json new file mode 100644 index 00000000000..0faac8416ae --- /dev/null +++ b/change/react-native-windows-2020-04-30-08-22-39-MS_RemoveReactAppRefCountHack.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Removed the ref count work around from classes derived from ReactApplications", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-30T15:22:39.524Z" +} diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp index d5c23ef61ce..6cbc618bc3b 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp @@ -39,11 +39,6 @@ App::App() noexcept { PackageProviders().Append(winrt::SampleLibraryCS::ReactPackageProvider()); InitializeComponent(); - - // This works around a cpp/winrt bug with composable/aggregable types tracked - // by 22116519 - AddRef(); - m_inner.as<::IUnknown>()->Release(); } } // namespace winrt::SampleAppCpp::implementation diff --git a/vnext/Microsoft.ReactNative/ReactApplication.cpp b/vnext/Microsoft.ReactNative/ReactApplication.cpp index 38c271ddb6c..a4f2d1d4e93 100644 --- a/vnext/Microsoft.ReactNative/ReactApplication.cpp +++ b/vnext/Microsoft.ReactNative/ReactApplication.cpp @@ -4,6 +4,7 @@ #include "pch.h" #include "ReactApplication.h" #include "ReactApplication.g.cpp" + #include "Modules/LinkingManagerModule.h" #include "ReactNativeHost.h" @@ -22,7 +23,16 @@ using namespace xaml::Navigation; namespace winrt::Microsoft::ReactNative::implementation { -ReactApplication::ReactApplication() noexcept { +ReactApplication::ReactApplication() = default; + +ReactApplication::ReactApplication(IInspectable const &outer) noexcept : ReactApplication{} { + // The factory is usually called in the base generated class. We call it here to pass correct + // 'outer' interface to enable inheritance from the ReactApplication class in user code. + impl::call_factory([&](xaml::IApplicationFactory const &f) { + [[maybe_unused]] auto winrt_impl_discarded = + f.CreateInstance(outer ? outer : static_cast(*this), this->m_inner); + }); + Suspending({this, &ReactApplication::OnSuspending}); #if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION @@ -111,7 +121,7 @@ void ReactApplication::OnActivated(IActivatedEventArgs const &e) { } void ReactApplication::OnLaunched(LaunchActivatedEventArgs const &e) { - Super::OnLaunched(e); + base_type::OnLaunched(e); // auto args = std::wstring(e.Arguments().c_str()); this->OnCreate(e); } diff --git a/vnext/Microsoft.ReactNative/ReactApplication.h b/vnext/Microsoft.ReactNative/ReactApplication.h index 1bb0e357aa8..b17d031257b 100644 --- a/vnext/Microsoft.ReactNative/ReactApplication.h +++ b/vnext/Microsoft.ReactNative/ReactApplication.h @@ -4,15 +4,55 @@ #pragma once #include "ReactApplication.g.h" +#include #include "ReactNativeHost.h" namespace winrt::Microsoft::ReactNative::implementation { -struct ReactApplication : ReactApplicationT { - using Super = ReactApplicationT; +// NoDefaultCtorReactApplication_base is a copy of the generated ReactApplication_base +// without the default constructor where it calls a factory for the base type. +// This is done to fix the aggregation issue in types inheriting from the ReactApplication. +// We call the factory in the ReactApplication constructor where we can pass correct +// 'outer' interface. +// +// This class must match the generated ReactApplication_base. +// It must be updated if the shape of generated ReactApplication_base is changed in future. +// The only difference is that this class has no default constructor. +template +struct __declspec(empty_bases) NoDefaultCtorReactApplication_base + : implements< + D, + Microsoft::ReactNative::ReactApplication, + composable, + composing, + xaml::IApplicationOverrides, + xaml::IApplicationOverrides2, + I...>, + impl::require, + impl::base, + xaml::IApplicationOverridesT, + xaml::IApplicationOverrides2T { + using base_type = NoDefaultCtorReactApplication_base; + using class_type = Microsoft::ReactNative::ReactApplication; + using implements_type = typename NoDefaultCtorReactApplication_base::implements_type; + using implements_type::implements_type; + using composable_base = xaml::Application; + + hstring GetRuntimeClassName() const { + return L"Microsoft.ReactNative.ReactApplication"; + } + protected: + using dispatch = impl::dispatch_to_overridable; + auto overridable() noexcept { + return dispatch::overridable(static_cast(*this)); + } +}; + +struct ReactApplication : NoDefaultCtorReactApplication_base { public: // ReactApplication ABI API - ReactApplication() noexcept; + ReactApplication(); + ReactApplication(IInspectable const &outer) noexcept; ReactNative::ReactInstanceSettings InstanceSettings() noexcept; void InstanceSettings(ReactNative::ReactInstanceSettings const &value) noexcept; @@ -57,6 +97,13 @@ struct ReactApplication : ReactApplicationT { namespace winrt::Microsoft::ReactNative::factory_implementation { -struct ReactApplication : ReactApplicationT {}; +// Override the CreateInstance method to pass baseInterface to the ReactApplication constructor +// to support correct COM aggregation that is need to inherit from the ReactApplication. +struct ReactApplication : ReactApplicationT { + auto CreateInstance(IInspectable const &baseInterface, IInspectable &innerInterface) { + return impl::composable_factory::template CreateInstance< + Microsoft::ReactNative::ReactApplication>(baseInterface, innerInterface, baseInterface); + } +}; } // namespace winrt::Microsoft::ReactNative::factory_implementation diff --git a/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp b/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp index e79bb0b7dd8..15b8fe539bf 100644 --- a/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp +++ b/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp @@ -36,11 +36,6 @@ App::App() noexcept REACT_REGISTER_NATIVE_MODULE_PACKAGES(); //code-gen macro from autolink InitializeComponent(); - - // This works around a cpp/winrt bug with composable/aggregable types tracked - // by 22116519 - AddRef(); - m_inner.as<::IUnknown>()->Release(); } From fb48078eefa5948e49d71e77c1010d115eda316f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2020 14:51:02 -0700 Subject: [PATCH 030/209] Bump @babel/core from 7.9.0 to 7.9.6 (#4757) Bumps [@babel/core](https://github.com/babel/babel) from 7.9.0 to 7.9.6. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel/compare/v7.9.0...v7.9.6) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 72 ++++++++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 41 deletions(-) diff --git a/yarn.lock b/yarn.lock index 2b625105ad4..546086dfedf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,18 +19,18 @@ semver "^5.5.0" "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.1.6", "@babel/core@^7.8.4": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" - integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.6.tgz#d9aa1f580abf3b2286ef40b6904d390904c63376" + integrity sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg== dependencies: "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.0" + "@babel/generator" "^7.9.6" "@babel/helper-module-transforms" "^7.9.0" - "@babel/helpers" "^7.9.0" - "@babel/parser" "^7.9.0" + "@babel/helpers" "^7.9.6" + "@babel/parser" "^7.9.6" "@babel/template" "^7.8.6" - "@babel/traverse" "^7.9.0" - "@babel/types" "^7.9.0" + "@babel/traverse" "^7.9.6" + "@babel/types" "^7.9.6" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -40,22 +40,12 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.4.0", "@babel/generator@^7.9.0", "@babel/generator@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9" - integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ== - dependencies: - "@babel/types" "^7.9.5" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - -"@babel/generator@^7.5.0": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.7.tgz#870b3cf7984f5297998152af625c4f3e341400f7" - integrity sha512-DQwjiKJqH4C3qGiyQCAExJHoZssn49JTMJgZ8SANGgVFdkupcUhLOdkAeoC6kmHZCPfoDG5M0b6cFlSN5wW7Ew== +"@babel/generator@^7.4.0", "@babel/generator@^7.5.0", "@babel/generator@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.6.tgz#5408c82ac5de98cda0d77d8124e99fa1f2170a43" + integrity sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ== dependencies: - "@babel/types" "^7.8.7" + "@babel/types" "^7.9.6" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" @@ -252,14 +242,14 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helpers@^7.9.0": - version "7.9.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f" - integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA== +"@babel/helpers@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.6.tgz#092c774743471d0bb6c7de3ad465ab3d3486d580" + integrity sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw== dependencies: "@babel/template" "^7.8.3" - "@babel/traverse" "^7.9.0" - "@babel/types" "^7.9.0" + "@babel/traverse" "^7.9.6" + "@babel/types" "^7.9.6" "@babel/highlight@^7.8.3": version "7.9.0" @@ -270,10 +260,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0": - version "7.9.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" - integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7" + integrity sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q== "@babel/plugin-external-helpers@^7.0.0": version "7.2.0" @@ -927,22 +917,22 @@ "@babel/parser" "^7.8.6" "@babel/types" "^7.8.6" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2" - integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442" + integrity sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg== dependencies: "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.5" + "@babel/generator" "^7.9.6" "@babel/helper-function-name" "^7.9.5" "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.0" - "@babel/types" "^7.9.5" + "@babel/parser" "^7.9.6" + "@babel/types" "^7.9.6" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.8.7", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6": +"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6": version "7.9.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== From d2583c94eda49aa95704a917d94d6f8333a88d89 Mon Sep 17 00:00:00 2001 From: dannyvv Date: Thu, 30 Apr 2020 14:51:50 -0700 Subject: [PATCH 031/209] Add a step in CI to upload verdaccio logs to diagnose package restore failures (#4761) --- .ado/templates/react-native-init.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.ado/templates/react-native-init.yml b/.ado/templates/react-native-init.yml index d6a92173390..be4bd9d0f8e 100644 --- a/.ado/templates/react-native-init.yml +++ b/.ado/templates/react-native-init.yml @@ -143,3 +143,12 @@ steps: inputs: script: npx --no-install react-native bundle --entry-file index.js --platform windows --bundle-output test.bundle workingDirectory: $(Agent.BuildDirectory)\testcli + + # We are experiencing random package restore failures. Uploading the vedaccio logs to aid in diagnosing if it is verdaccio or npmjs.org + - task: PublishPipelineArtifact@1 + displayName: Upload Verdaccio.log (on failure) + inputs: + targetPath: 'verdaccio.log' + artifact: 'Verdaccio.log' + publishLocation: 'pipeline' + condition: failed() From 518284b8bd22271f4a7813eb6b4e53cf864fc6a8 Mon Sep 17 00:00:00 2001 From: dannyvv Date: Thu, 30 Apr 2020 16:45:03 -0700 Subject: [PATCH 032/209] Minor cleanup: Remove unused namespace from C# files (#4763) * Minor cleanup: Remove unused namespace from C# files * Change files --- .../react-native-windows-2020-04-30-16-10-37-master.json | 8 ++++++++ .../SampleLibraryCS/CustomUserControlViewManagerCS.cs | 1 - .../windows/SampleLibraryCS/SampleModuleCS.cs | 2 -- .../ReactContextGenerator.cs | 1 - .../ReactSyncMethodInfo.cs | 1 - 5 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 change/react-native-windows-2020-04-30-16-10-37-master.json diff --git a/change/react-native-windows-2020-04-30-16-10-37-master.json b/change/react-native-windows-2020-04-30-16-10-37-master.json new file mode 100644 index 00000000000..5440f995200 --- /dev/null +++ b/change/react-native-windows-2020-04-30-16-10-37-master.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Minor cleanup: Remove unused namespace from C# files", + "packageName": "react-native-windows", + "email": "dannyvv@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-30T23:10:37.840Z" +} diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/CustomUserControlViewManagerCS.cs b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/CustomUserControlViewManagerCS.cs index b50510b5c78..33fed3be6fe 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/CustomUserControlViewManagerCS.cs +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/CustomUserControlViewManagerCS.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; using System.Diagnostics; using Windows.UI.Xaml; diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs index cd40e29bd09..f69b8ca7a9d 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs @@ -1,11 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using Microsoft.ReactNative; using Microsoft.ReactNative.Managed; using System; using System.Diagnostics; -using System.Reflection; using System.Threading.Tasks; using Windows.System.Threading; diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs index f2a7f3a094b..4b02ba12b41 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs @@ -4,7 +4,6 @@ using System; using System.Linq; using System.Reflection; -using System.Runtime.CompilerServices; using Windows.UI.Xaml; namespace Microsoft.ReactNative.Managed diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactSyncMethodInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactSyncMethodInfo.cs index 31f192b4ebb..b423cfb8866 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactSyncMethodInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactSyncMethodInfo.cs @@ -7,7 +7,6 @@ using static Microsoft.ReactNative.Managed.JSValueGenerator; using static Microsoft.ReactNative.Managed.JSValueReaderGenerator; using static Microsoft.ReactNative.Managed.JSValueWriterGenerator; -using static System.Linq.Expressions.Expression; namespace Microsoft.ReactNative.Managed { From 06370db95789843ec9b1893d988a5a7b5da92fea Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Fri, 1 May 2020 00:04:15 +0000 Subject: [PATCH 033/209] applying package updates ***NO_CI*** --- ...8-22-39-MS_RemoveReactAppRefCountHack.json | 8 ------- ...ve-windows-2020-04-30-16-10-37-master.json | 8 ------- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- vnext/CHANGELOG.json | 21 +++++++++++++++++++ vnext/CHANGELOG.md | 11 +++++++++- vnext/package.json | 2 +- 8 files changed, 35 insertions(+), 21 deletions(-) delete mode 100644 change/react-native-windows-2020-04-30-08-22-39-MS_RemoveReactAppRefCountHack.json delete mode 100644 change/react-native-windows-2020-04-30-16-10-37-master.json diff --git a/change/react-native-windows-2020-04-30-08-22-39-MS_RemoveReactAppRefCountHack.json b/change/react-native-windows-2020-04-30-08-22-39-MS_RemoveReactAppRefCountHack.json deleted file mode 100644 index 0faac8416ae..00000000000 --- a/change/react-native-windows-2020-04-30-08-22-39-MS_RemoveReactAppRefCountHack.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Removed the ref count work around from classes derived from ReactApplications", - "packageName": "react-native-windows", - "email": "vmorozov@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-30T15:22:39.524Z" -} diff --git a/change/react-native-windows-2020-04-30-16-10-37-master.json b/change/react-native-windows-2020-04-30-16-10-37-master.json deleted file mode 100644 index 5440f995200..00000000000 --- a/change/react-native-windows-2020-04-30-16-10-37-master.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Minor cleanup: Remove unused namespace from C# files", - "packageName": "react-native-windows", - "email": "dannyvv@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-30T23:10:37.840Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index fe9b7518092..85ec5bf1891 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.54" + "react-native-windows": "0.0.0-master.55" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 5281f6aa552..3764fb0997f 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.54" + "react-native-windows": "0.0.0-master.55" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index bf7cedb1882..3f59af4db2e 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.54" + "react-native-windows": "0.0.0-master.55" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index 665cde97e71..649a3b5ac44 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,27 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Fri, 01 May 2020 00:04:15 GMT", + "tag": "react-native-windows_v0.0.0-master.55", + "version": "0.0.0-master.55", + "comments": { + "prerelease": [ + { + "comment": "Removed the ref count work around from classes derived from ReactApplications", + "author": "vmorozov@microsoft.com", + "commit": "9d9a541aa40c4af2950cf784b5ba0ada935686c4", + "package": "react-native-windows" + }, + { + "comment": "Minor cleanup: Remove unused namespace from C# files", + "author": "dannyvv@microsoft.com", + "commit": "518284b8bd22271f4a7813eb6b4e53cf864fc6a8", + "package": "react-native-windows" + } + ] + } + }, { "date": "Thu, 30 Apr 2020 18:40:40 GMT", "tag": "react-native-windows_v0.0.0-master.54", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index bc1c33a8244..6c50abc8a73 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,18 @@ # Change Log - react-native-windows -This log was last generated on Thu, 30 Apr 2020 18:40:40 GMT and should not be manually modified. +This log was last generated on Fri, 01 May 2020 00:04:15 GMT and should not be manually modified. +## 0.0.0-master.55 + +Fri, 01 May 2020 00:04:15 GMT + +### Changes + +- Removed the ref count work around from classes derived from ReactApplications (vmorozov@microsoft.com) +- Minor cleanup: Remove unused namespace from C# files (dannyvv@microsoft.com) + ## 0.0.0-master.54 Thu, 30 Apr 2020 18:40:40 GMT diff --git a/vnext/package.json b/vnext/package.json index 493163612e8..33ea4d95940 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.54", + "version": "0.0.0-master.55", "license": "MIT", "repository": { "type": "git", From 8c693448a1f95ec028d8e6beda97cc5c0d0e4303 Mon Sep 17 00:00:00 2001 From: Aaron Schultz Date: Thu, 30 Apr 2020 19:57:13 -0700 Subject: [PATCH 034/209] Update mouseEnter/mouseLeave algorithm (#4574) * - Change MouseEnter/MouseLeave behavior to match web behavior - Improve performance of frequently-called mouse move handler * Change files * Update mouse sample * Fix * formatting --- ...0-04-10-22-47-43-users-aschultz-hover.json | 8 + packages/playground/Samples/mouse.tsx | 230 +++++++++++----- vnext/ReactUWP/Views/TouchEventHandler.cpp | 252 +++++++++--------- vnext/ReactUWP/Views/TouchEventHandler.h | 30 ++- 4 files changed, 301 insertions(+), 219 deletions(-) create mode 100644 change/react-native-windows-2020-04-10-22-47-43-users-aschultz-hover.json diff --git a/change/react-native-windows-2020-04-10-22-47-43-users-aschultz-hover.json b/change/react-native-windows-2020-04-10-22-47-43-users-aschultz-hover.json new file mode 100644 index 00000000000..d6c57b73c84 --- /dev/null +++ b/change/react-native-windows-2020-04-10-22-47-43-users-aschultz-hover.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "- Change MouseEnter/MouseLeave behavior to match web behavior - Improve performance of frequently-called mouse move handler", + "packageName": "react-native-windows", + "email": "aschultz@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-11T05:47:43.048Z" +} \ No newline at end of file diff --git a/packages/playground/Samples/mouse.tsx b/packages/playground/Samples/mouse.tsx index 455947f7ada..b2a4f0f6902 100644 --- a/packages/playground/Samples/mouse.tsx +++ b/packages/playground/Samples/mouse.tsx @@ -14,22 +14,80 @@ import { BackHandler, } from 'react-native'; +const styles = StyleSheet.create({ + page: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#FFFFFF', + }, + mainContainer: { + width: 400, + height: 400, + backgroundColor: '#CCCCCC', + }, + contentContainer: { + flex: 1, + backgroundColor: '#F2E2C4', + }, + contentContainerHovered: { + backgroundColor: '#B3A791', + }, + contentChild: { + position: 'absolute', + top: 0, + right: 0, + width: 200, + height: 200, + backgroundColor: '#C2D2F2', + }, + contentChildHovered: { + backgroundColor: '#8F9BB3', + }, + overlayContainer: { + position: 'absolute', + right: -100, + top: 100, + width: 200, + height: 200, + backgroundColor: '#FF9C65', + }, + overlayContainerHovered: { + backgroundColor: '#BF754D', + }, + overlayChild: { + position: 'absolute', + top: 0, + right: 0, + width: 100, + height: 100, + backgroundColor: '#99A4BF', + }, + overlayChildHovered: { + backgroundColor: '#666D80', + }, +}); + export default class Bootstrap extends React.Component< {}, { clicked: number; - mouseEntered0: boolean; - mouseEntered1: boolean; - mouseEntered2: boolean; + pageHover: boolean; + contentHover: boolean; + contentChildHover: boolean; + overlayHover: boolean; + overlayChildHover: boolean; } > { constructor(props: {}) { super(props); this.state = { clicked: 0, - mouseEntered0: false, - mouseEntered1: false, - mouseEntered2: false, + pageHover: false, + contentHover: false, + contentChildHover: false, + overlayHover: false, + overlayChildHover: false, }; } @@ -38,75 +96,117 @@ export default class Bootstrap extends React.Component< } render() { + const pageProps: any = { + style: styles.page, + onMouseEnter: this.mouseEnterPage, + onMouseLeave: this.mouseLeavePage, + }; return ( - - - - World - - Hello + + + {this.renderContent()} + {this.renderOverlay()} - - Mousey + + {this.state.pageHover ? 'Mouse over page' : ''} ); } - click = () => { - this.setState({clicked: this.state.clicked + 1}); + renderContent(): JSX.Element { + const containerProps: any = { + style: [ + styles.contentContainer, + this.state.contentHover ? styles.contentContainerHovered : undefined, + ], + onMouseEnter: this.mouseEnterContentContainer, + onMouseLeave: this.mouseLeaveContentContainer, + }; + const childProps: any = { + style: [ + styles.contentChild, + this.state.contentChildHover ? styles.contentChildHovered : undefined, + ], + onMouseEnter: this.mouseEnterContentChild, + onMouseLeave: this.mouseLeaveContentChild, + onPress: this.press, + onPressIn: this.pressIn, + onPressOut: this.pressOut, + }; + + return ( + + + This is a TouchableHighlight + + + ); + } + + renderOverlay(): JSX.Element { + const containerProps: any = { + style: [ + styles.overlayContainer, + this.state.overlayHover ? styles.overlayContainerHovered : undefined, + ], + onMouseEnter: this.mouseEnterOverlay, + onMouseLeave: this.mouseLeaveOverlay, + }; + const childProps: any = { + style: [ + styles.overlayChild, + this.state.overlayChildHover ? styles.overlayChildHovered : undefined, + ], + onMouseEnter: this.mouseEnterOverlayChild, + onMouseLeave: this.mouseLeaveOverlayChild, + }; + + return ( + + + This is an overlay view + + + ); + } + + mouseEnterPage = () => { + this.setState({pageHover: true}); }; - mouseEnter0 = () => { - this.setState({mouseEntered0: true}); + mouseLeavePage = () => { + this.setState({pageHover: false}); }; - mouseLeave0 = () => { - this.setState({mouseEntered0: false}); + mouseEnterContentContainer = () => { + this.setState({contentHover: true}); + }; + mouseLeaveContentContainer = () => { + this.setState({contentHover: false}); }; - mouseEnter1 = () => { - this.setState({mouseEntered1: true}); + mouseEnterContentChild = () => { + this.setState({contentChildHover: true}); + }; + mouseLeaveContentChild = () => { + this.setState({contentChildHover: false}); }; - mouseLeave1 = () => { - this.setState({mouseEntered1: false}); + mouseEnterOverlay = () => { + this.setState({overlayHover: true}); }; - mouseEnter2 = () => { - this.setState({mouseEntered2: true}); + mouseLeaveOverlay = () => { + this.setState({overlayHover: false}); + }; + mouseEnterOverlayChild = () => { + this.setState({overlayChildHover: true}); + }; + mouseLeaveOverlayChild = () => { + this.setState({overlayChildHover: false}); }; - mouseLeave2 = () => { - this.setState({mouseEntered2: false}); + click = () => { + this.setState({clicked: this.state.clicked + 1}); }; press = (event: GestureResponderEvent) => { console.log('press'); @@ -126,18 +226,4 @@ export default class Bootstrap extends React.Component< }; } -const styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: '#C5CCFF', - }, - welcome: { - fontSize: 20, - textAlign: 'center', - margin: 10, - }, -}); - AppRegistry.registerComponent('Bootstrap', () => Bootstrap); diff --git a/vnext/ReactUWP/Views/TouchEventHandler.cpp b/vnext/ReactUWP/Views/TouchEventHandler.cpp index 4a345e8f901..53f9e87c60d 100644 --- a/vnext/ReactUWP/Views/TouchEventHandler.cpp +++ b/vnext/ReactUWP/Views/TouchEventHandler.cpp @@ -18,6 +18,8 @@ namespace react { namespace uwp { +std::vector GetTagsForBranch(facebook::react::INativeUIManagerHost *host, int64_t tag); + TouchEventHandler::TouchEventHandler(const std::weak_ptr &reactInstance) : m_xamlView(nullptr), m_wkReactInstance(reactInstance) {} @@ -34,24 +36,24 @@ void TouchEventHandler::AddTouchHandlers(XamlView xamlView) { m_xamlView = xamlView; - m_pressedRevoker.revoke(); + RemoveTouchHandlers(); + m_pressedRevoker = uiElement.PointerPressed(winrt::auto_revoke, {this, &TouchEventHandler::OnPointerPressed}); - m_releasedRevoker.revoke(); m_releasedRevoker = uiElement.PointerReleased(winrt::auto_revoke, {this, &TouchEventHandler::OnPointerReleased}); - m_canceledRevoker.revoke(); m_canceledRevoker = uiElement.PointerCanceled(winrt::auto_revoke, {this, &TouchEventHandler::OnPointerCanceled}); - m_captureLostRevoker.revoke(); m_captureLostRevoker = uiElement.PointerCaptureLost(winrt::auto_revoke, {this, &TouchEventHandler::OnPointerCaptureLost}); - m_exitedRevoker.revoke(); m_exitedRevoker = uiElement.PointerExited(winrt::auto_revoke, {this, &TouchEventHandler::OnPointerExited}); - m_movedRevoker.revoke(); m_movedRevoker = uiElement.PointerMoved(winrt::auto_revoke, {this, &TouchEventHandler::OnPointerMoved}); } void TouchEventHandler::RemoveTouchHandlers() { m_pressedRevoker.revoke(); m_releasedRevoker.revoke(); + m_canceledRevoker.revoke(); + m_captureLostRevoker.revoke(); + m_exitedRevoker.revoke(); + m_movedRevoker.revoke(); } void TouchEventHandler::OnPointerPressed( @@ -70,7 +72,7 @@ void TouchEventHandler::OnPointerPressed( // Only if the view has a Tag can we process this int64_t tag; - xaml::FrameworkElement sourceElement(nullptr); + xaml::UIElement sourceElement(nullptr); if (!TagFromOriginalSource(args, &tag, &sourceElement)) return; @@ -83,7 +85,7 @@ void TouchEventHandler::OnPointerPressed( if (m_xamlView.as().CapturePointer(args.Pointer())) { // Pointer pressing updates the enter/leave state - UpdatePointersInViews(args, tag, sourceElement); + UpdatePointersInViews(instance, args, tag, sourceElement); size_t pointerIndex = AddReactPointer(args, tag, sourceElement); DispatchTouchEvent(TouchEventType::Start, pointerIndex); @@ -111,7 +113,12 @@ void TouchEventHandler::OnPointerCaptureLost( void TouchEventHandler::OnPointerExited( const winrt::IInspectable & /*sender*/, const winrt::PointerRoutedEventArgs &args) { - UpdatePointersInViews(args, -1, nullptr); + // Short circuit all of this if we are in an error state + auto instance = m_wkReactInstance.lock(); + if (!instance || instance->IsInError()) + return; + + UpdatePointersInViews(instance, args, -1, nullptr); } void TouchEventHandler::OnPointerMoved( @@ -124,7 +131,7 @@ void TouchEventHandler::OnPointerMoved( // Only if the view has a Tag can we process this int64_t tag; - xaml::FrameworkElement sourceElement(nullptr); + xaml::UIElement sourceElement(nullptr); if (!TagFromOriginalSource(args, &tag, &sourceElement)) return; @@ -134,7 +141,7 @@ void TouchEventHandler::OnPointerMoved( DispatchTouchEvent(TouchEventType::Move, *optPointerIndex); } else { // Move with no buttons pressed - UpdatePointersInViews(args, tag, sourceElement); + UpdatePointersInViews(instance, args, tag, sourceElement); // MouseMove support: (Not yet enabled, requires adding to ViewPropTypes.js) // SendPointerMove(args, tag, sourceElement); } @@ -150,17 +157,16 @@ void TouchEventHandler::OnPointerConcluded(TouchEventType eventType, const winrt if (!optPointerIndex) return; - const auto pointerIndex = *optPointerIndex; // if the view has a Tag, update the pointer info. // Regardless of that, ensure we Dispatch & cleanup the pointer int64_t tag; - xaml::FrameworkElement sourceElement(nullptr); + xaml::UIElement sourceElement(nullptr); if (TagFromOriginalSource(args, &tag, &sourceElement)) - UpdateReactPointer(m_pointers[pointerIndex], args, sourceElement); + UpdateReactPointer(m_pointers[*optPointerIndex], args, sourceElement); - DispatchTouchEvent(eventType, pointerIndex); + DispatchTouchEvent(eventType, *optPointerIndex); - m_pointers.erase(cbegin(m_pointers) + pointerIndex); + m_pointers.erase(cbegin(m_pointers) + *optPointerIndex); if (m_pointers.size() == 0) m_touchId = 0; @@ -170,7 +176,7 @@ void TouchEventHandler::OnPointerConcluded(TouchEventType eventType, const winrt size_t TouchEventHandler::AddReactPointer( const winrt::PointerRoutedEventArgs &args, int64_t tag, - xaml::FrameworkElement sourceElement) { + xaml::UIElement sourceElement) { ReactPointer pointer = CreateReactPointer(args, tag, sourceElement); m_pointers.emplace_back(std::move(pointer)); return m_pointers.size() - 1; @@ -179,19 +185,21 @@ size_t TouchEventHandler::AddReactPointer( TouchEventHandler::ReactPointer TouchEventHandler::CreateReactPointer( const winrt::PointerRoutedEventArgs &args, int64_t tag, - xaml::FrameworkElement sourceElement) { + xaml::UIElement sourceElement) { auto point = args.GetCurrentPoint(sourceElement); + auto props = point.Properties(); ReactPointer pointer; pointer.target = tag; pointer.identifier = m_touchId++; pointer.pointerId = point.PointerId(); pointer.deviceType = point.PointerDevice().PointerDeviceType(); - pointer.isLeftButton = point.Properties().IsLeftButtonPressed(); - pointer.isRightButton = point.Properties().IsRightButtonPressed(); - pointer.isMiddleButton = point.Properties().IsMiddleButtonPressed(); - pointer.isHorizontalScrollWheel = point.Properties().IsHorizontalMouseWheel(); - pointer.isEraser = point.Properties().IsEraser(); + pointer.isLeftButton = props.IsLeftButtonPressed(); + pointer.isRightButton = props.IsRightButtonPressed(); + pointer.isMiddleButton = props.IsMiddleButtonPressed(); + pointer.isHorizontalScrollWheel = props.IsHorizontalMouseWheel(); + pointer.isEraser = props.IsEraser(); + UpdateReactPointer(pointer, args, sourceElement); return pointer; @@ -200,24 +208,20 @@ TouchEventHandler::ReactPointer TouchEventHandler::CreateReactPointer( void TouchEventHandler::UpdateReactPointer( ReactPointer &pointer, const winrt::PointerRoutedEventArgs &args, - xaml::FrameworkElement sourceElement) { + xaml::UIElement sourceElement) { auto rootPoint = args.GetCurrentPoint(m_xamlView.as()); auto point = args.GetCurrentPoint(sourceElement); + auto props = point.Properties(); + auto keyModifiers = static_cast(args.KeyModifiers()); pointer.positionRoot = rootPoint.Position(); pointer.positionView = point.Position(); pointer.timestamp = point.Timestamp() / 1000; // us -> ms - pointer.pressure = point.Properties().Pressure(); - pointer.isBarrelButton = point.Properties().IsBarrelButtonPressed(); - pointer.shiftKey = !!static_cast( - static_cast(args.KeyModifiers()) & - static_cast(winrt::Windows::System::VirtualKeyModifiers::Shift)); - pointer.ctrlKey = !!static_cast( - static_cast(args.KeyModifiers()) & - static_cast(winrt::Windows::System::VirtualKeyModifiers::Control)); - pointer.altKey = !!static_cast( - static_cast(args.KeyModifiers()) & - static_cast(winrt::Windows::System::VirtualKeyModifiers::Menu)); + pointer.pressure = props.Pressure(); + pointer.isBarrelButton = props.IsBarrelButtonPressed(); + pointer.shiftKey = 0 != (keyModifiers & static_cast(winrt::Windows::System::VirtualKeyModifiers::Shift)); + pointer.ctrlKey = 0 != (keyModifiers & static_cast(winrt::Windows::System::VirtualKeyModifiers::Control)); + pointer.altKey = 0 != (keyModifiers & static_cast(winrt::Windows::System::VirtualKeyModifiers::Menu)); } std::optional TouchEventHandler::IndexOfPointerWithId(uint32_t pointerId) { @@ -230,86 +234,76 @@ std::optional TouchEventHandler::IndexOfPointerWithId(uint32_t pointerId } void TouchEventHandler::UpdatePointersInViews( + std::shared_ptr instance, const winrt::PointerRoutedEventArgs &args, int64_t tag, - xaml::FrameworkElement sourceElement) { - auto instance = m_wkReactInstance.lock(); - if (!instance || instance->IsInError()) - return; - + xaml::UIElement sourceElement) { + auto nativeUiManager = static_cast(instance->NativeUIManager()); + auto puiManagerHost = nativeUiManager->getHost(); int32_t pointerId = args.Pointer().PointerId(); - auto optPointerIndex = IndexOfPointerWithId(pointerId); - ReactPointer pointer = - (optPointerIndex) ? m_pointers[*optPointerIndex] : CreateReactPointer(args, tag, sourceElement); + // m_pointers is tracking the pointers that are 'down', for moves we usually // don't have any pointers down and should reset the touchId back to zero if (m_pointers.size() == 0) m_touchId = 0; - std::set newViews; + // Get the branch of views under the pointer in leaf to root order + std::vector newViews; if (tag != -1) - newViews = GetTagsAtPoint(args); - std::set existingViews; + newViews = GetTagsForBranch(puiManagerHost, tag); + + // Get the results of the last time we calculated the path auto it = m_pointersInViews.find(pointerId); - if (it != m_pointersInViews.end()) - existingViews = it->second; - if (newViews == existingViews) + TagSet *existingViews; + if (it != m_pointersInViews.end()) { + existingViews = &it->second; + } else { + existingViews = nullptr; + } + + // Short-circuit if the hierarchy hasn't changed + if ((existingViews == nullptr && newViews.size() == 0) || + (existingViews != nullptr && existingViews->orderedTags == newViews)) return; - auto nativeUiManager = static_cast(instance->NativeUIManager()); - facebook::react::INativeUIManagerHost *puiManagerHost = nativeUiManager->getHost(); + // Prep to fire pointer events + std::unordered_set newViewsSet(newViews.begin(), newViews.end()); + ReactPointer pointer; - // Notify tags that are no longer in the list - for (int64_t existingTag : existingViews) { - if (newViews.count(existingTag)) - continue; + auto optPointerIndex = IndexOfPointerWithId(pointerId); + if (optPointerIndex) { + pointer = m_pointers[*optPointerIndex]; + UpdateReactPointer(pointer, args, sourceElement); + } else { + pointer = CreateReactPointer(args, tag, sourceElement); + } - ShadowNodeBase *node = static_cast(puiManagerHost->FindShadowNodeForTag(existingTag)); - if (node != nullptr && node->m_onMouseLeave) - instance->DispatchEvent(existingTag, "topMouseLeave", GetPointerJson(pointer, existingTag)); + // Walk through existingViews from innermost to outer, firing mouseLeave events if they are not in newViews + if (existingViews) { + for (int64_t existingTag : existingViews->orderedTags) { + if (newViewsSet.count(existingTag)) { + continue; + } + + ShadowNodeBase *node = static_cast(puiManagerHost->FindShadowNodeForTag(existingTag)); + if (node != nullptr && node->m_onMouseLeave) + instance->DispatchEvent(existingTag, "topMouseLeave", GetPointerJson(pointer, existingTag)); + } } - // Notify tags new in the list - for (int64_t newTag : newViews) { - if (existingViews.count(newTag)) + // Walk through newViews from outermost to inner, firing mouseEnter events if they are not in existingViews + for (auto iter = newViews.rbegin(); iter != newViews.rend(); ++iter) { + int64_t newTag = *iter; + if (existingViews && existingViews->tags.count(newTag)) { continue; + } ShadowNodeBase *node = static_cast(puiManagerHost->FindShadowNodeForTag(newTag)); if (node != nullptr && node->m_onMouseEnter) instance->DispatchEvent(newTag, "topMouseEnter", GetPointerJson(pointer, newTag)); } - m_pointersInViews[pointerId] = std::move(newViews); -} - -void TouchEventHandler::SendPointerMove( - const winrt::PointerRoutedEventArgs &args, - int64_t tag, - xaml::FrameworkElement sourceElement) { - auto instance = m_wkReactInstance.lock(); - auto nativeUiManager = static_cast(instance->NativeUIManager()); - facebook::react::INativeUIManagerHost *puiManagerHost = nativeUiManager->getHost(); - - // Look for an element subscribed to onMouseMove - ShadowNodeBase *node = static_cast(puiManagerHost->FindShadowNodeForTag(tag)); - while (node != nullptr && !node->m_onMouseMove) { - tag = node->m_parent; - node = tag == -1 ? nullptr : node = static_cast(puiManagerHost->FindShadowNodeForTag(tag)); - } - if (node == nullptr || !node->m_onMouseMove) - return; - sourceElement = node->GetView().try_as(); - if (sourceElement == nullptr) - return; - - auto optPointerIndex = IndexOfPointerWithId(args.Pointer().PointerId()); - ReactPointer pointer = - (optPointerIndex) ? m_pointers[*optPointerIndex] : CreateReactPointer(args, tag, sourceElement); - if (m_pointers.size() == 0) // If we created a reactPointer, reset the touchId back to zero - m_touchId = 0; - - folly::dynamic touch = GetPointerJson(pointer, pointer.target); - instance->DispatchEvent(tag, "topMouseEnter", GetPointerJson(pointer, tag)); + m_pointersInViews[pointerId] = {std::move(newViewsSet), std::move(newViews)}; } folly::dynamic TouchEventHandler::GetPointerJson(const ReactPointer &pointer, int64_t target) { @@ -398,54 +392,46 @@ const char *TouchEventHandler::GetTouchEventTypeName(TouchEventType eventType) n bool TouchEventHandler::TagFromOriginalSource( const winrt::PointerRoutedEventArgs &args, int64_t *pTag, - xaml::FrameworkElement *pSourceElement) { + xaml::UIElement *pSourceElement) { assert(pTag != nullptr); + assert(pSourceElement != nullptr); + + // Find the React element that triggered the input event + xaml::UIElement sourceElement = args.OriginalSource().try_as(); + winrt::IPropertyValue tag(nullptr); + while (sourceElement) { + tag = sourceElement.GetValue(xaml::FrameworkElement::TagProperty()).try_as(); + if (tag) { + break; + } + sourceElement = winrt::VisualTreeHelper::GetParent(sourceElement).try_as(); + } - if (args.OriginalSource() == nullptr) - return false; - - auto sourceElement = args.OriginalSource().try_as(); - if (sourceElement == nullptr) { - // TODO: Do we need to handle this for non FrameworkElement views? + if (tag == nullptr) { + // If the root view fails to be fully created, then the Tag property will + // never be set. This can happen, + // for example, when the red box error box is shown. return false; - } else { - auto tag = sourceElement.Tag(); - while (tag == nullptr && sourceElement && winrt::VisualTreeHelper::GetParent(sourceElement)) { - sourceElement = winrt::VisualTreeHelper::GetParent(sourceElement).try_as(); - tag = sourceElement.Tag(); - } + } - if (tag == nullptr) { - // If the root view fails to be fully created, then the Tag property will - // never be set. This can happen, - // for example, when the red box error box is shown. - return false; - } + *pTag = tag.GetInt64(); + *pSourceElement = sourceElement; + return true; +} - assert(tag.as() != nullptr); +// +// Retreives the path of nodes from an element to the root. +// The order of the returned list is from child to parent. +// +std::vector GetTagsForBranch(facebook::react::INativeUIManagerHost *host, int64_t tag) { + std::vector tags; - *pTag = tag.as().GetInt64(); - *pSourceElement = sourceElement; - return true; - } -} + auto *shadowNode = host->FindShadowNodeForTag(tag); + while (shadowNode != nullptr && tag != -1) { + tags.push_back(tag); -std::set TouchEventHandler::GetTagsAtPoint(const winrt::PointerRoutedEventArgs &e) { - std::set tags; - xaml::UIElement root(m_xamlView.as()); - - winrt::Point point = e.GetCurrentPoint(root).Position(); - auto transform = root.TransformToVisual(nullptr); - point = transform.TransformPoint(point); - - auto elements = winrt::VisualTreeHelper::FindElementsInHostCoordinates(point, root); - for (const auto &elem : elements) { - auto element = elem.try_as(); - if (element != nullptr) { - auto tag = element.Tag(); - if (tag != nullptr) - tags.insert(tag.as().GetInt64()); - } + tag = shadowNode->m_parent; + shadowNode = host->FindShadowNodeForTag(tag); } return tags; diff --git a/vnext/ReactUWP/Views/TouchEventHandler.h b/vnext/ReactUWP/Views/TouchEventHandler.h index c06b28cb6c8..31cba6e24ab 100644 --- a/vnext/ReactUWP/Views/TouchEventHandler.h +++ b/vnext/ReactUWP/Views/TouchEventHandler.h @@ -62,16 +62,16 @@ class TouchEventHandler { bool ctrlKey = false; bool altKey = false; }; - size_t AddReactPointer(const winrt::PointerRoutedEventArgs &args, int64_t tag, xaml::FrameworkElement sourceElement); + size_t AddReactPointer(const winrt::PointerRoutedEventArgs &args, int64_t tag, xaml::UIElement sourceElement); ReactPointer - CreateReactPointer(const winrt::PointerRoutedEventArgs &args, int64_t tag, xaml::FrameworkElement sourceElement); - void UpdateReactPointer( - ReactPointer &pointer, - const winrt::PointerRoutedEventArgs &args, - xaml::FrameworkElement sourceElement); + CreateReactPointer(const winrt::PointerRoutedEventArgs &args, int64_t tag, xaml::UIElement sourceElement); void - UpdatePointersInViews(const winrt::PointerRoutedEventArgs &args, int64_t tag, xaml::FrameworkElement sourceElement); - void SendPointerMove(const winrt::PointerRoutedEventArgs &args, int64_t tag, xaml::FrameworkElement sourceElement); + UpdateReactPointer(ReactPointer &pointer, const winrt::PointerRoutedEventArgs &args, xaml::UIElement sourceElement); + void UpdatePointersInViews( + std::shared_ptr instance, + const winrt::PointerRoutedEventArgs &args, + int64_t tag, + xaml::UIElement sourceElement); enum class TouchEventType { Start = 0, End, Move, Cancel, PointerEntered, PointerExited, PointerMove }; void OnPointerConcluded(TouchEventType eventType, const winrt::PointerRoutedEventArgs &args); @@ -82,15 +82,17 @@ class TouchEventHandler { std::optional IndexOfPointerWithId(uint32_t pointerId); folly::dynamic GetPointerJson(const ReactPointer &pointer, int64_t target); + + struct TagSet { + std::unordered_set tags; + std::vector orderedTags; + }; + std::vector m_pointers; - std::unordered_map /*tags*/> m_pointersInViews; + std::unordered_map m_pointersInViews; int64_t m_touchId = 0; - bool TagFromOriginalSource( - const winrt::PointerRoutedEventArgs &args, - int64_t *pTag, - xaml::FrameworkElement *pSourceElement); - std::set GetTagsAtPoint(const winrt::PointerRoutedEventArgs &e); + bool TagFromOriginalSource(const winrt::PointerRoutedEventArgs &args, int64_t *pTag, xaml::UIElement *pSourceElement); XamlView m_xamlView; std::weak_ptr m_wkReactInstance; From 800e41679415c0011ca354a0caf3a9eeaea39d8d Mon Sep 17 00:00:00 2001 From: tudorms <48035227+tudorms@users.noreply.github.com> Date: Fri, 1 May 2020 16:37:31 -0700 Subject: [PATCH 035/209] Delay load ChakraCore.dll (#4773) * Delay load ChakraCore.dll * Change files Co-authored-by: tudorm --- .../react-native-windows-2020-05-01-15-34-56-master.json | 8 ++++++++ vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 change/react-native-windows-2020-05-01-15-34-56-master.json diff --git a/change/react-native-windows-2020-05-01-15-34-56-master.json b/change/react-native-windows-2020-05-01-15-34-56-master.json new file mode 100644 index 00000000000..8ce2b59e221 --- /dev/null +++ b/change/react-native-windows-2020-05-01-15-34-56-master.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Delay load ChakraCore.dll", + "packageName": "react-native-windows", + "email": "tudorm@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-01T22:34:56.237Z" +} diff --git a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj index f92c4c0636f..09ecc50f835 100644 --- a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj +++ b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj @@ -94,7 +94,7 @@ we have a better solution for handling the absence of WinRT string and error DLLs on Win7. --> WindowsApp_downlevel.lib;%(AdditionalDependencies) - api-ms-win-core-winrt-error-l1-1-0.dll;api-ms-win-core-winrt-error-l1-1-1.dll;api-ms-win-core-winrt-string-l1-1-0.dll;ChakraCore.Debugger.DLL;%(DelayLoadDLLs) + api-ms-win-core-winrt-error-l1-1-0.dll;api-ms-win-core-winrt-error-l1-1-1.dll;api-ms-win-core-winrt-string-l1-1-0.dll;ChakraCore.Debugger.DLL;ChakraCore.dll;%(DelayLoadDLLs) From 3bcd8a1e3c51301b178c68d7469b8e5140b58c8a Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Sat, 2 May 2020 00:05:12 +0000 Subject: [PATCH 036/209] applying package updates ***NO_CI*** --- ...0-04-10-22-47-43-users-aschultz-hover.json | 8 ------- ...ve-windows-2020-05-01-15-34-56-master.json | 8 ------- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- vnext/CHANGELOG.json | 21 +++++++++++++++++++ vnext/CHANGELOG.md | 11 +++++++++- vnext/package.json | 2 +- 8 files changed, 35 insertions(+), 21 deletions(-) delete mode 100644 change/react-native-windows-2020-04-10-22-47-43-users-aschultz-hover.json delete mode 100644 change/react-native-windows-2020-05-01-15-34-56-master.json diff --git a/change/react-native-windows-2020-04-10-22-47-43-users-aschultz-hover.json b/change/react-native-windows-2020-04-10-22-47-43-users-aschultz-hover.json deleted file mode 100644 index d6c57b73c84..00000000000 --- a/change/react-native-windows-2020-04-10-22-47-43-users-aschultz-hover.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "- Change MouseEnter/MouseLeave behavior to match web behavior - Improve performance of frequently-called mouse move handler", - "packageName": "react-native-windows", - "email": "aschultz@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-11T05:47:43.048Z" -} \ No newline at end of file diff --git a/change/react-native-windows-2020-05-01-15-34-56-master.json b/change/react-native-windows-2020-05-01-15-34-56-master.json deleted file mode 100644 index 8ce2b59e221..00000000000 --- a/change/react-native-windows-2020-05-01-15-34-56-master.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Delay load ChakraCore.dll", - "packageName": "react-native-windows", - "email": "tudorm@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-01T22:34:56.237Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index 85ec5bf1891..f56b9a9ef29 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.55" + "react-native-windows": "0.0.0-master.56" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 3764fb0997f..a64f5e0ecce 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.55" + "react-native-windows": "0.0.0-master.56" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index 3f59af4db2e..b71532e0b77 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.55" + "react-native-windows": "0.0.0-master.56" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index 649a3b5ac44..e57c502bcd5 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,27 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Sat, 02 May 2020 00:05:12 GMT", + "tag": "react-native-windows_v0.0.0-master.56", + "version": "0.0.0-master.56", + "comments": { + "prerelease": [ + { + "comment": "- Change MouseEnter/MouseLeave behavior to match web behavior - Improve performance of frequently-called mouse move handler", + "author": "aschultz@microsoft.com", + "commit": "8c693448a1f95ec028d8e6beda97cc5c0d0e4303", + "package": "react-native-windows" + }, + { + "comment": "Delay load ChakraCore.dll", + "author": "tudorm@microsoft.com", + "commit": "800e41679415c0011ca354a0caf3a9eeaea39d8d", + "package": "react-native-windows" + } + ] + } + }, { "date": "Fri, 01 May 2020 00:04:15 GMT", "tag": "react-native-windows_v0.0.0-master.55", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 6c50abc8a73..0291c0d08fb 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,18 @@ # Change Log - react-native-windows -This log was last generated on Fri, 01 May 2020 00:04:15 GMT and should not be manually modified. +This log was last generated on Sat, 02 May 2020 00:05:12 GMT and should not be manually modified. +## 0.0.0-master.56 + +Sat, 02 May 2020 00:05:12 GMT + +### Changes + +- - Change MouseEnter/MouseLeave behavior to match web behavior - Improve performance of frequently-called mouse move handler (aschultz@microsoft.com) +- Delay load ChakraCore.dll (tudorm@microsoft.com) + ## 0.0.0-master.55 Fri, 01 May 2020 00:04:15 GMT diff --git a/vnext/package.json b/vnext/package.json index 33ea4d95940..8b439b77059 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.55", + "version": "0.0.0-master.56", "license": "MIT", "repository": { "type": "git", From 56e08530db3e751a8813785bb51aeb728aad98b0 Mon Sep 17 00:00:00 2001 From: Andreas Eulitz <44379427+aeulitz@users.noreply.github.com> Date: Fri, 1 May 2020 17:17:24 -0700 Subject: [PATCH 037/209] Build logic to create test bundles, test to call JS function (#4765) * create MS.ReactNative.IntegrationTests project * RNHost activation succeeds * update * update * Change files * add JS function call test * Change files * fix formatting --- ...indows-2020-04-30-18-28-03-abi-safety.json | 8 ++ .../AddValues.js | 9 +++ ...osoft.ReactNative.IntegrationTests.vcxproj | 3 + .../ReactNativeHostTests.cpp | 81 +++++++++++++++++-- .../TestBundle.targets | 10 +++ .../main.cpp | 2 + .../pch.h | 6 +- vnext/ReactWindows-Universal.sln | 1 + 8 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 change/react-native-windows-2020-04-30-18-28-03-abi-safety.json create mode 100644 vnext/Microsoft.ReactNative.IntegrationTests/AddValues.js create mode 100644 vnext/Microsoft.ReactNative.IntegrationTests/TestBundle.targets diff --git a/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json b/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json new file mode 100644 index 00000000000..7cf31717cd8 --- /dev/null +++ b/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json @@ -0,0 +1,8 @@ +{ + "type": "none", + "comment": "test bundle build logic, JS function call test", + "packageName": "react-native-windows", + "email": "aeulitz@microsoft.com", + "dependentChangeType": "none", + "date": "2020-05-01T01:28:03.315Z" +} diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/AddValues.js b/vnext/Microsoft.ReactNative.IntegrationTests/AddValues.js new file mode 100644 index 00000000000..5079081362b --- /dev/null +++ b/vnext/Microsoft.ReactNative.IntegrationTests/AddValues.js @@ -0,0 +1,9 @@ +import { NativeModules } from 'react-native'; + +class SampleModuleCpp { + addValues(a, b) { + NativeModules.TestHostModule.returnInt(a + b); + } +} + +global.__fbBatchedBridge.registerLazyCallableModule('SampleModuleCpp', () => new SampleModuleCpp()); diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj b/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj index 24559702450..5b1aacd65ec 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj +++ b/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj @@ -47,6 +47,7 @@ + @@ -119,6 +120,7 @@ + @@ -130,6 +132,7 @@ + diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp b/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp index 4117db9e01d..11d16009c32 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp +++ b/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp @@ -1,17 +1,84 @@ #include "pch.h" -#include +using namespace React; namespace ReactNativeIntegrationTests { +REACT_MODULE(TestHostModule) +struct TestHostModule { + REACT_INIT(Initialize) + void Initialize(ReactContext const & /*reactContext*/) noexcept { + TestHostModule::Instance.set_value(*this); + } + + REACT_FUNCTION(addValues) + std::function addValues; + + REACT_METHOD(returnInt) + void returnInt(int value) noexcept { + TestHostModule::IntReturnValue.set_value(value); + } + + static std::promise Instance; + static std::promise IntReturnValue; +}; + +std::promise TestHostModule::Instance; +std::promise TestHostModule::IntReturnValue; + +struct TestPackageProvider : winrt::implements { + void CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept { + TryAddAttributedModule(packageBuilder, L"TestHostModule"); + } +}; + TEST_CLASS (ReactNativeHostTests) { TEST_METHOD(Activation_Succeeds) { - try { - winrt::Microsoft::ReactNative::ReactNativeHost host{}; - TestCheck(true); - } catch (...) { - TestCheckFail(); - } + TestCheckNoThrow(winrt::Microsoft::ReactNative::ReactNativeHost{}); + } + + // The test method below is being skipped as the instance creation currently crashes with the following dependency on + // the Xaml application framework: + // 0b VCRUNTIME140D!_CxxThrowException + // 0c Microsoft_ReactNative!winrt::throw_hresult + // 0d Microsoft_ReactNative!winrt::check_hresult + // 0e + // Microsoft_ReactNative!winrt::impl::consume_Windows_ApplicationModel_Core_ICoreImmersiveApplication::MainView + // 0f Microsoft_ReactNative!::operator() + // 10 Microsoft_ReactNative!:: + // 11 + // Microsoft_ReactNative!winrt::impl::factory_cache_entry::call 12 + // Microsoft_ReactNative!winrt::impl::call_factory_cast + // > 13 Microsoft_ReactNative!winrt::Windows::ApplicationModel::Core::CoreApplication::MainView 14 + // Microsoft_ReactNative!Mso::DispatchQueueStatic::MakeMainUIScheduler 15 + // Microsoft_ReactNative!Mso::DispatchQueueStatic::MainUIQueue 16 + // Microsoft_ReactNative!Mso::DispatchQueue::MainUIQueue 17 + // Microsoft_ReactNative!Mso::React::ReactInstanceWin::InitUIMessageThread 18 + // Microsoft_ReactNative!Mso::React::ReactInstanceWin::Initialize + // In the short term, there are several ways in which this could get mitigated (e.g. transforming the integration test + // app into a UWP app). In the long term, the issue should get addressed by splitting the Microsoft.ReactNative.dll + // into a "core" and a "UI" DLL, and by having the tests in this project target the "core" DLL. + SKIPTESTMETHOD(JsFunctionCall_Succeeds) { + std::future testHostModule = TestHostModule::Instance.get_future(); + std::future returnValue = TestHostModule::IntReturnValue.get_future(); + + winrt::Microsoft::ReactNative::ReactNativeHost host{}; + host.PackageProviders().Append(winrt::make()); + + // bundle is assumed to be co-located with the test binary + wchar_t testBinaryPath[MAX_PATH]; + TestCheck(GetModuleFileNameW(NULL, testBinaryPath, MAX_PATH) < MAX_PATH); + testBinaryPath[std::wstring_view{testBinaryPath}.rfind(L"\\")] = 0; + host.InstanceSettings().BundleRootPath(testBinaryPath); + + host.InstanceSettings().JavaScriptBundleFile(L"AddValues.bundle"); + host.ReloadInstance(); + + testHostModule.get().addValues(12, 23); + TestCheckEqual(35, returnValue.get()); } }; diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/TestBundle.targets b/vnext/Microsoft.ReactNative.IntegrationTests/TestBundle.targets new file mode 100644 index 00000000000..284e1cd3af6 --- /dev/null +++ b/vnext/Microsoft.ReactNative.IntegrationTests/TestBundle.targets @@ -0,0 +1,10 @@ + + + + + + diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/main.cpp b/vnext/Microsoft.ReactNative.IntegrationTests/main.cpp index 3e0e14c0536..4d4152fe7f4 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/main.cpp +++ b/vnext/Microsoft.ReactNative.IntegrationTests/main.cpp @@ -1,4 +1,6 @@ #include "pch.h" + +#include "gtest/gtest.h" #include "motifCpp/gTestAdapter.h" int main(int argc, char **argv) { diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/pch.h b/vnext/Microsoft.ReactNative.IntegrationTests/pch.h index cdbaa25a673..df633651c1b 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/pch.h +++ b/vnext/Microsoft.ReactNative.IntegrationTests/pch.h @@ -2,6 +2,8 @@ #define NOMINMAX -#include "gtest/gtest.h" -#include "motifCpp/gTestAdapter.h" +#include +#include +#include "NativeModules.h" +#include "functional/functor.h" #include "motifCpp/testCheck.h" diff --git a/vnext/ReactWindows-Universal.sln b/vnext/ReactWindows-Universal.sln index 89f5f1eb5c3..5b0b2509e19 100644 --- a/vnext/ReactWindows-Universal.sln +++ b/vnext/ReactWindows-Universal.sln @@ -108,6 +108,7 @@ EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 + Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{14fa0516-e6d7-4e4d-b097-1470198c5072}*SharedItemsImports = 4 Mso\Mso.vcxitems*{14fa0516-e6d7-4e4d-b097-1470198c5072}*SharedItemsImports = 4 Mso\Mso.vcxitems*{1958ceaa-fbe0-44e3-8a99-90ad85531ffe}*SharedItemsImports = 4 Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 From cc400a0a09760ca1017fa59bf2c5d86628e788d2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 2 May 2020 05:36:42 +0000 Subject: [PATCH 038/209] Bump beachball from 1.30.2 to 1.31.0 (#4769) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 546086dfedf..7c892c30627 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4495,9 +4495,9 @@ bcrypt-pbkdf@^1.0.0: tweetnacl "^0.14.3" beachball@^1.13.4: - version "1.30.2" - resolved "https://registry.yarnpkg.com/beachball/-/beachball-1.30.2.tgz#c0e645b783d74de23fea404ed220dac59aab651d" - integrity sha512-d/2+T5+vQD/32wAQAMY7hRVyVunjD0mRCVYLPYqfxBeYHMJeQ/Irwm8u1rhhjCf94oIdoVGn2dXtWLm99RcttA== + version "1.31.0" + resolved "https://registry.yarnpkg.com/beachball/-/beachball-1.31.0.tgz#8909754fa62e4e3bda14a5f799aaacef53627e23" + integrity sha512-IQTpnItQPt9O5nZ3nVE4Gqxt4ipJ+zJTkKaAst0aDVAQSSVB90AOIUB/TAXx2CZaYCebt4DfnzPSNu09PTXU6g== dependencies: cosmiconfig "^6.0.0" fs-extra "^8.0.1" From a6d5ff43421d4fb450db47aaa753c767c5966ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20C=C3=A9sar=20Rocha?= Date: Sat, 2 May 2020 02:24:58 -0700 Subject: [PATCH 039/209] Implement WinRTWebSocket unit tests (#4767) * Allow constructing resource with generalized types * Use IMessageWebSocketMessageReceivedEventArgs * Implement MockMessageWebSocket * Implement MockMessageWebSocket * Declare MockMessageWebSocket mocks * clang format * Implement mocked methods * Define MockDataWriter * Complete MockWebSocketResource. TODO: Fix handler memory access when invoked explicitly. * Implement ConnectSucceeds * Upgrade to Microsoft.Windows.CppWinRT.2.0.200316.3 * Comment-out connect test. * Move mocks into struct. * Make MockMessageWebSocket extend implements * Uncommented test partially * Uncommented test partially * Temporarily comment IMessageWebSocket mock usage * Temporarily comment IMessageWebSocket mock usage * Make MockMessageWebSocket extends implements * Implement Mocks.Control * MockMessageWS implement same types as MessageWS. * Also implement winrt::...IWebSocket * Drop impls of IMessageWebSocket2,3 * Add /await compiler switch * Implement no-op IAsyncAction * Implement ThrowAsync * Updated MockWebSocketResource Mocks * Change files * Make MockMessageWebSocket primarily IMessageWebSocket * clang format --- ...e-windows-2020-05-01-15-49-42-wsrc_ut.json | 8 + .../React.Windows.Desktop.DLL.vcxproj | 12 +- ...t.Windows.Desktop.IntegrationTests.vcxproj | 2 - vnext/Desktop.UnitTests/InstanceMocks.h | 3 + .../React.Windows.Desktop.UnitTests.vcxproj | 28 +- ....Windows.Desktop.UnitTests.vcxproj.filters | 66 ++-- vnext/Desktop.UnitTests/WebSocketMocks.cpp | 126 ++++++- vnext/Desktop.UnitTests/WebSocketMocks.h | 37 +- .../Desktop.UnitTests/WebSocketModuleTest.cpp | 9 +- .../WinRTNetworkingMocks.cpp | 357 ++++++++++++++++++ .../Desktop.UnitTests/WinRTNetworkingMocks.h | 217 +++++++++++ .../WinRTWebSocketResourceUnitTest.cpp | 98 +++++ vnext/Desktop/WebSocketResourceFactory.cpp | 2 +- .../ReactWindowsCore/ReactWindowsCore.vcxproj | 1 - .../WinRTWebSocketResource.cpp | 26 +- .../ReactWindowsCore/WinRTWebSocketResource.h | 19 +- 16 files changed, 934 insertions(+), 77 deletions(-) create mode 100644 change/react-native-windows-2020-05-01-15-49-42-wsrc_ut.json create mode 100644 vnext/Desktop.UnitTests/WinRTNetworkingMocks.cpp create mode 100644 vnext/Desktop.UnitTests/WinRTNetworkingMocks.h create mode 100644 vnext/Desktop.UnitTests/WinRTWebSocketResourceUnitTest.cpp diff --git a/change/react-native-windows-2020-05-01-15-49-42-wsrc_ut.json b/change/react-native-windows-2020-05-01-15-49-42-wsrc_ut.json new file mode 100644 index 00000000000..852ba6218ea --- /dev/null +++ b/change/react-native-windows-2020-05-01-15-49-42-wsrc_ut.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Implement WinRTWebSocketResource unit tests", + "packageName": "react-native-windows", + "email": "julio.rocha@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-01T22:49:42.857Z" +} diff --git a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj index 09ecc50f835..651a667e8ac 100644 --- a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj +++ b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj @@ -79,20 +79,18 @@ Windows -minpdbpathlen:256 comsuppw.lib; Shlwapi.lib; Version.lib; - Winhttp.lib; + WindowsApp_downlevel.lib; %(AdditionalDependencies) - WindowsApp_downlevel.lib;%(AdditionalDependencies) api-ms-win-core-winrt-error-l1-1-0.dll;api-ms-win-core-winrt-error-l1-1-1.dll;api-ms-win-core-winrt-string-l1-1-0.dll;ChakraCore.Debugger.DLL;ChakraCore.dll;%(DelayLoadDLLs) diff --git a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj index 8276fcba366..f0b2cb8e758 100644 --- a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj +++ b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj @@ -74,14 +74,12 @@ comsuppw.lib; delayimp.lib; Shlwapi.lib; Version.lib; - Winhttp.lib; %(AdditionalDependencies) true diff --git a/vnext/Desktop.UnitTests/InstanceMocks.h b/vnext/Desktop.UnitTests/InstanceMocks.h index bb535c79ece..5b562b42ef6 100644 --- a/vnext/Desktop.UnitTests/InstanceMocks.h +++ b/vnext/Desktop.UnitTests/InstanceMocks.h @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + #pragma once #include diff --git a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj index 548a182d84d..1048078ca0f 100644 --- a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj +++ b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj @@ -1,6 +1,6 @@ - + Debug @@ -40,7 +40,7 @@ - $(ReactNativeWindowsDir)Common;$(ReactNativeWindowsDir)Desktop;$(FollyDir);$(ReactNativeWindowsDir)stubs;$(ReactNativeWindowsDir)Shared;$(ReactNativeWindowsDir)ReactWindowsCore;$(ReactNativeWindowsDir)include\ReactWindowsCore;$(ReactNativeDir)\ReactCommon;$(JSI_Source);$(MSBuildThisFileDirectory);$(IncludePath) + $(ReactNativeWindowsDir)\Mso;$(ReactNativeWindowsDir)Common;$(ReactNativeWindowsDir)Desktop;$(FollyDir);$(ReactNativeWindowsDir)stubs;$(ReactNativeWindowsDir)Shared;$(ReactNativeWindowsDir)ReactWindowsCore;$(ReactNativeWindowsDir)include\ReactWindowsCore;$(ReactNativeDir)\ReactCommon;$(JSI_Source);$(MSBuildThisFileDirectory);$(IncludePath) true @@ -63,17 +63,26 @@ JSI_EXPORT=; %(PreprocessorDefinitions) - $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + + + WINRT_LEAN_AND_MEAN; + %(UndefinePreprocessorDefinitions) + + + $(VCInstallDir)UnitTest\include; + %(AdditionalIncludeDirectories) + + %(AdditionalOptions) /await comsuppw.lib; Shlwapi.lib; - Winhttp.lib; %(AdditionalDependencies) @@ -97,6 +106,8 @@ + + @@ -109,6 +120,7 @@ + @@ -120,7 +132,7 @@ - + @@ -129,8 +141,8 @@ - - + + diff --git a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj.filters b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj.filters index b473de81f8b..ef2b1ef1d39 100644 --- a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj.filters +++ b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj.filters @@ -1,55 +1,61 @@  - + Source Files - + Source Files - - Source Files + + Unit Tests - - Source Files + + Unit Tests - - Source Files + + Unit Tests - - Source Files + + Unit Tests - - Source Files + + Unit Tests - - Source Files + + Unit Tests - Source Files + Unit Tests - - Source Files + + Unit Tests - Source Files + Unit Tests - - Source Files + + Unit Tests - - Source Files + + Unit Tests - - Source Files + + Unit Tests - - Source Files + + Unit Tests + + + Unit Tests + + + Unit Tests Source Files - + Source Files @@ -63,6 +69,9 @@ {047f5ee2-0f34-4c7c-aee6-cef679234701} + + {73161bf3-3cf2-47a9-b674-c436649b71a7} + @@ -80,5 +89,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/vnext/Desktop.UnitTests/WebSocketMocks.cpp b/vnext/Desktop.UnitTests/WebSocketMocks.cpp index a57365cff9d..bdba2b4e67a 100644 --- a/vnext/Desktop.UnitTests/WebSocketMocks.cpp +++ b/vnext/Desktop.UnitTests/WebSocketMocks.cpp @@ -1,43 +1,141 @@ #include "WebSocketMocks.h" +using std::exception; using std::function; using std::string; namespace Microsoft::React::Test { + +MockWebSocketResource::~MockWebSocketResource() {} + #pragma region IWebSocketResource overrides -void MockWebSocketResource::Connect(const Protocols &, const Options &) /*override*/ +void MockWebSocketResource::Connect(const Protocols &protocols, const Options &options) /*override*/ +{ + if (Mocks.Connect) + return Mocks.Connect(protocols, options); + + throw exception("Not implemented"); +} + +void MockWebSocketResource::Ping() /*override*/ { - m_onConnect(); + if (Mocks.Connect) + return Mocks.Ping(); + + throw exception("Not implemented"); } -void MockWebSocketResource::Ping() /*override*/ {} +void MockWebSocketResource::Send(const string &message) /*override*/ +{ + if (Mocks.Send) + return Mocks.Send(message); -void MockWebSocketResource::Send(const string &) /*override*/ {} + throw exception("Not implemented"); +} -void MockWebSocketResource::SendBinary(const string &) /*override*/ {} +void MockWebSocketResource::SendBinary(const string &message) /*override*/ +{ + if (Mocks.SendBinary) + return Mocks.SendBinary(message); -void MockWebSocketResource::Close(CloseCode, const string &) /*override*/ {} + throw exception("Not implemented"); +} + +void MockWebSocketResource::Close(CloseCode code, const string &reason) /*override*/ +{ + if (Mocks.Close) + return Mocks.Close(code, reason); + + throw exception("Not implemented"); +} IWebSocketResource::ReadyState MockWebSocketResource::GetReadyState() const /*override*/ { - return ReadyState::Open; + if (Mocks.GetReadyState) + return Mocks.GetReadyState(); + + throw exception("Not implemented"); } -void MockWebSocketResource::SetOnConnect(function &&onConnect) /*override*/ +void MockWebSocketResource::SetOnConnect(function &&handler) /*override*/ { - m_onConnect = std::move(onConnect); + if (Mocks.SetOnConnect) + return SetOnConnect(std::move(handler)); + + m_connectHandler = std::move(handler); } -void MockWebSocketResource::SetOnPing(function &&) /*override*/ {} +void MockWebSocketResource::SetOnPing(function &&handler) /*override*/ +{ + if (Mocks.SetOnPing) + return Mocks.SetOnPing(std::move(handler)); -void MockWebSocketResource::SetOnSend(function &&) /*override*/ {} + m_pingHandler = std::move(handler); +} -void MockWebSocketResource::SetOnMessage(function &&) /*override*/ {} +void MockWebSocketResource::SetOnSend(function &&handler) /*override*/ +{ + if (Mocks.SetOnSend) + return Mocks.SetOnSend(std::move(handler)); -void MockWebSocketResource::SetOnClose(function &&) /*override*/ {} + m_writeHandler = std::move(handler); +} -void MockWebSocketResource::SetOnError(function &&) /*override*/ {} +void MockWebSocketResource::SetOnMessage(function &&handler) /*override*/ +{ + if (Mocks.SetOnMessage) + return Mocks.SetOnMessage(std::move(handler)); + + m_readHandler = std::move(handler); +} + +void MockWebSocketResource::SetOnClose(function &&handler) /*override*/ +{ + if (Mocks.SetOnClose) + return Mocks.SetOnClose(std::move(handler)); + + m_closeHandler = std::move(handler); +} + +void MockWebSocketResource::SetOnError(function &&handler) /*override*/ +{ + if (Mocks.SetOnError) + return Mocks.SetOnError(std::move(handler)); + + m_errorHandler = std::move(handler); +} #pragma endregion IWebSocketResource overrides + +void MockWebSocketResource::OnConnect() { + if (m_connectHandler) + m_connectHandler(); +} + +void MockWebSocketResource::OnPing() { + if (m_pingHandler) + m_pingHandler(); +} + +void MockWebSocketResource::OnSend(size_t size) { + if (m_writeHandler) + m_writeHandler(size); +} + +void MockWebSocketResource::OnMessage(size_t size, const string &message) { + if (m_readHandler) + m_readHandler(size, message); +} + +void MockWebSocketResource::OnClose(CloseCode code, const string &reason) { + if (m_closeHandler) + m_closeHandler(code, reason); +} + +void MockWebSocketResource::OnError(Error &&error) { + if (m_errorHandler) + m_errorHandler(std::move(error)); +} + } // namespace Microsoft::React::Test diff --git a/vnext/Desktop.UnitTests/WebSocketMocks.h b/vnext/Desktop.UnitTests/WebSocketMocks.h index beeceac830b..d0e388bbf95 100644 --- a/vnext/Desktop.UnitTests/WebSocketMocks.h +++ b/vnext/Desktop.UnitTests/WebSocketMocks.h @@ -4,6 +4,25 @@ namespace Microsoft::React::Test { struct MockWebSocketResource : public IWebSocketResource { + ~MockWebSocketResource(); + + struct Mocks { + std::function Connect; + std::function Ping; + std::function Send; + std::function SendBinary; + std::function Close; + std::function GetReadyState; + std::function &&)> SetOnConnect; + std::function &&)> SetOnPing; + std::function &&)> SetOnSend; + std::function &&)> SetOnMessage; + std::function &&)> SetOnClose; + std::function &&)> SetOnError; + }; + + Mocks Mocks; + #pragma region IWebSocketResource overrides void Connect(const Protocols &, const Options &) override; @@ -22,9 +41,9 @@ struct MockWebSocketResource : public IWebSocketResource { void SetOnPing(std::function &&) override; - void SetOnSend(std::function &&) override; + void SetOnSend(std::function &&) override; - void SetOnMessage(std::function &&) override; + void SetOnMessage(std::function &&) override; void SetOnClose(std::function &&) override; @@ -32,8 +51,20 @@ struct MockWebSocketResource : public IWebSocketResource { #pragma endregion IWebSocketResource overrides + void OnConnect(); + void OnPing(); + void OnSend(std::size_t size); + void OnMessage(std::size_t, const std::string &message); + void OnClose(CloseCode code, const std::string &reason); + void OnError(Error &&error); + private: - std::function m_onConnect; + std::function m_connectHandler; + std::function m_pingHandler; + std::function m_writeHandler; + std::function m_readHandler; + std::function m_closeHandler; + std::function m_errorHandler; }; } // namespace Microsoft::React::Test diff --git a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp index 0aa7d57dba3..c07c33a50d5 100644 --- a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp +++ b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp @@ -60,7 +60,14 @@ TEST_CLASS (WebSocketModuleTest) { auto instance = CreateMockInstance(jsef); auto module = make_unique(); module->setInstance(instance); - module->SetResourceFactory([](const string &, bool, bool) { return make_shared(); }); + module->SetResourceFactory([](const string &, bool, bool) { + auto rc = make_shared(); + rc->Mocks.Connect = [rc](const IWebSocketResource::Protocols &, const IWebSocketResource::Options &) { + rc->OnConnect(); + }; + + return rc; + }); // Execute module method auto connect = module->getMethods().at(WebSocketModule::MethodId::Connect); diff --git a/vnext/Desktop.UnitTests/WinRTNetworkingMocks.cpp b/vnext/Desktop.UnitTests/WinRTNetworkingMocks.cpp new file mode 100644 index 00000000000..dc6f857c792 --- /dev/null +++ b/vnext/Desktop.UnitTests/WinRTNetworkingMocks.cpp @@ -0,0 +1,357 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "WinRTNetworkingMocks.h" + +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Networking::Sockets; +using namespace winrt::Windows::Storage::Streams; + +using std::exception; +using winrt::auto_revoke_t; +using winrt::event_token; +using winrt::param::hstring; + +namespace Microsoft::React::Test { + +#pragma region MockMessageWebSocket + +// IWebSocket +IOutputStream MockMessageWebSocket::OutputStream() const { + if (Mocks.OutputStream) + return Mocks.OutputStream(); + + throw exception("Not implemented"); +} + +IAsyncAction MockMessageWebSocket::ConnectAsync(Uri const &uri) const { + if (Mocks.ConnectAsync) + return Mocks.ConnectAsync(uri); + + throw exception("Not implemented"); +} + +void MockMessageWebSocket::SetRequestHeader(hstring const &headerName, hstring const &headerValue) const { + if (Mocks.SetRequestHeader) + return Mocks.SetRequestHeader(headerName, headerValue); + + throw exception("Not implemented"); +} + +event_token MockMessageWebSocket::Closed( + TypedEventHandler const &eventHandler) const { + if (Mocks.ClosedToken) + return Mocks.ClosedToken(eventHandler); + + throw exception("Not implemented"); +} + +IWebSocket::Closed_revoker MockMessageWebSocket::Closed( + auto_revoke_t autoRevoke, + TypedEventHandler const &eventHandler) const { + if (Mocks.ClosedRevoker) + return Mocks.ClosedRevoker(autoRevoke, eventHandler); + + throw exception("Not implemented"); +} + +void MockMessageWebSocket::Closed(event_token const &eventCookie) const noexcept { + if (Mocks.ClosedVoid) + Mocks.ClosedVoid(eventCookie); +} + +void MockMessageWebSocket::Close(uint16_t code, hstring const &reason) const { + if (Mocks.Close) + return Mocks.Close(code, reason); + + throw exception("Not implemented"); +} + +// IMessageWebSocket +MessageWebSocketControl MockMessageWebSocket::Control() const { + if (Mocks.Control) + return Mocks.Control(); + + return m_messageWebSocket.Control(); +}; + +MessageWebSocketInformation MockMessageWebSocket::Information() const { + if (Mocks.Information) + return Mocks.Information(); + + throw exception("Not implemented"); +} + +event_token MockMessageWebSocket::MessageReceived( + TypedEventHandler const &eventHandler) const { + if (Mocks.MessageReceivedToken) + return Mocks.MessageReceivedToken(eventHandler); + + throw exception("Not implemented"); +} + +IMessageWebSocket::MessageReceived_revoker MockMessageWebSocket::MessageReceived( + winrt::auto_revoke_t autoRevoker, + TypedEventHandler const &eventHandler) const { + if (Mocks.MessageReceivedRevoker) + return Mocks.MessageReceivedRevoker(autoRevoker, eventHandler); + + throw exception("Not implemented"); +} + +void MockMessageWebSocket::MessageReceived(event_token const &eventCookie) const noexcept { + if (Mocks.MessageReceivedVoid) + Mocks.MessageReceivedVoid(eventCookie); +} + +#pragma endregion MockMessageWebSocket + +#pragma region MockDataWriter + +uint32_t MockDataWriter::UnstoredBufferLength() const { + if (Mocks.UnstoredBufferLength) + return Mocks.UnstoredBufferLength(); + + throw exception("Not implemented"); +} + +UnicodeEncoding MockDataWriter::UnicodeEncoding() const { + if (Mocks.GetUnicodeEncoding) + return Mocks.GetUnicodeEncoding(); + + throw exception("Not implemented"); +} + +void MockDataWriter::UnicodeEncoding(winrt::Windows::Storage::Streams::UnicodeEncoding const &value) const { + if (Mocks.SetUnicodeEncoding) + return Mocks.SetUnicodeEncoding(value); + + throw exception("Not implemented"); +} + +ByteOrder MockDataWriter::ByteOrder() const { + if (Mocks.GetByteOrder) + return Mocks.GetByteOrder(); + + throw exception("Not implemented"); +} + +void MockDataWriter::ByteOrder(winrt::Windows::Storage::Streams::ByteOrder const &value) const { + if (Mocks.SetByteOrder) + return Mocks.SetByteOrder(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteByte(uint8_t value) const { + if (Mocks.WriteByte) + return Mocks.WriteByte(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteBytes(winrt::array_view value) const { + if (Mocks.WriteBytes) + return Mocks.WriteBytes(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteBuffer(IBuffer const &buffer) const { + if (Mocks.WriteBuffer) + return Mocks.WriteBuffer(buffer); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteBuffer(IBuffer const &buffer, uint32_t start, uint32_t count) const { + if (Mocks.WriteBufferRange) + return Mocks.WriteBufferRange(buffer, start, count); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteBoolean(bool value) const { + if (Mocks.WriteBoolean) + return Mocks.WriteBoolean(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteGuid(winrt::guid const &value) const { + if (Mocks.WriteGuid) + return Mocks.WriteGuid(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteInt16(int16_t value) const { + if (Mocks.WriteInt16) + return Mocks.WriteInt16(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteInt32(int32_t value) const { + if (Mocks.WriteInt32) + return Mocks.WriteInt32(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteInt64(int64_t value) const { + if (Mocks.WriteInt64) + return Mocks.WriteInt64(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteUInt16(uint16_t value) const { + if (Mocks.WriteUInt16) + return Mocks.WriteUInt16(value); +} + +void MockDataWriter::WriteUInt32(uint32_t value) const { + if (Mocks.WriteUInt32) + return Mocks.WriteUInt32(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteUInt64(uint64_t value) const { + if (Mocks.WriteUInt64) + return Mocks.WriteUInt64(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteSingle(float value) const { + if (Mocks.WriteSingle) + return Mocks.WriteSingle(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteDouble(double value) const { + if (Mocks.WriteDouble) + return Mocks.WriteDouble(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteDateTime(DateTime const &value) const { + if (Mocks.WriteDateTime) + return Mocks.WriteDateTime(value); + + throw exception("Not implemented"); +} + +void MockDataWriter::WriteTimeSpan(TimeSpan const &value) const { + if (Mocks.WriteTimeSpan) + return Mocks.WriteTimeSpan(value); + + throw exception("Not implemented"); +} + +uint32_t MockDataWriter::WriteString(hstring const &value) const { + if (Mocks.WriteString) + return Mocks.WriteString(value); + + throw exception("Not implemented"); +} + +uint32_t MockDataWriter::MeasureString(hstring const &value) const { + if (Mocks.MeasureString) + return Mocks.MeasureString(value); + + throw exception("Not implemented"); +} + +DataWriterStoreOperation MockDataWriter::StoreAsync() const { + if (Mocks.StoreAsync) + return Mocks.StoreAsync(); + + throw exception("Not implemented"); +} + +IAsyncOperation MockDataWriter::FlushAsync() const { + if (Mocks.FlushAsync) + return Mocks.FlushAsync(); + + throw exception("Not implemented"); +} + +IBuffer MockDataWriter::DetachBuffer() const { + if (Mocks.DetachBuffer) + return Mocks.DetachBuffer(); + + throw exception("Not implemented"); +} + +IOutputStream MockDataWriter::DetachStream() const { + if (Mocks.DetachStream) + return Mocks.DetachStream(); + + throw exception("Not implemented"); +} + +#pragma endregion MockDataWriter + +// TODO: Work around linker error: +// error LNK2019: unresolved external symbol +// "public: __cdecl winrt::Windows::Security::Credentials::PasswordCredential::PasswordCredential(void)" +// (??0PasswordCredential@Credentials@Security@Windows@winrt@@QEAA@XZ) +// referenced in function +// "public: struct winrt::Windows::Security::Credentials::PasswordCredential +// __cdecl Microsoft::React::Test::MockMessageWebSocketControl::ProxyCredential(void)const " +// (?ProxyCredential@MockMessageWebSocketControl@Test@React@Microsoft@@ +// QEBA?AUPasswordCredential@Credentials@Security@Windows@winrt@@XZ) +#if 0 +#pragma region MockMessageWebSocketControl + +// IWebSocketControl + +uint32_t MockMessageWebSocketControl::OutboundBufferSizeInBytes() const { + return 0; +} + +void MockMessageWebSocketControl::OutboundBufferSizeInBytes(uint32_t value) const {} + +winrt::Windows::Security::Credentials::PasswordCredential MockMessageWebSocketControl::ServerCredential() const { + return {}; +} + +void MockMessageWebSocketControl::ServerCredential( + winrt::Windows::Security::Credentials::PasswordCredential const &value) const {} + +winrt::Windows::Security::Credentials::PasswordCredential MockMessageWebSocketControl::ProxyCredential() const { + return winrt::Windows::Security::Credentials::PasswordCredential(); +} + +void MockMessageWebSocketControl::ProxyCredential( + winrt::Windows::Security::Credentials::PasswordCredential const &value) const {} + +winrt::Windows::Foundation::Collections::IVector MockMessageWebSocketControl::SupportedProtocols() + const { + return winrt::single_threaded_vector(); +} + +// IMessageWebSocketControl + +uint32_t MockMessageWebSocketControl::MaxMessageSize() const { + return 0; +} + +void MockMessageWebSocketControl::MaxMessageSize(std::uint32_t value) const {} + +SocketMessageType MockMessageWebSocketControl::MessageType() const { + return SocketMessageType::Utf8; +} + +void MockMessageWebSocketControl::MessageType(SocketMessageType const &value) const {} + +#pragma endregion MockMessageWebsocketControl + +#endif // 0 + +} // namespace Microsoft::React::Test diff --git a/vnext/Desktop.UnitTests/WinRTNetworkingMocks.h b/vnext/Desktop.UnitTests/WinRTNetworkingMocks.h new file mode 100644 index 00000000000..bd670ac02dd --- /dev/null +++ b/vnext/Desktop.UnitTests/WinRTNetworkingMocks.h @@ -0,0 +1,217 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include + +namespace Microsoft::React::Test { + +/// +// Mocks winrt::Windows::Networking::Sockets::MessageWebSocket +/// +struct MockMessageWebSocket : public winrt::implements< + MockMessageWebSocket, + winrt::Windows::Networking::Sockets::IMessageWebSocket, + winrt::Windows::Networking::Sockets::IWebSocket> { + struct Mocks { + // IWebSocket + std::function + ConnectAsync; + + std::function SetRequestHeader; + + std::function OutputStream; + + std::function Close; + + std::function const &) /*const*/> + ClosedToken; + + std::function const &) /*const*/> + ClosedRevoker; + + std::function ClosedVoid; + + // IMessageWebSocket + std::function Control; + + std::function Information; + + std::function const &) /*const*/> + MessageReceivedToken; + + std::function const &) /*const*/> + MessageReceivedRevoker; + + std::function MessageReceivedVoid; + }; + + Mocks Mocks; + +#pragma region IWebSocket overrides + + // Methods + + winrt::Windows::Foundation::IAsyncAction ConnectAsync(winrt::Windows::Foundation::Uri const &uri) const; + + void SetRequestHeader(winrt::param::hstring const &headerName, winrt::param::hstring const &headerValue) const; + + winrt::Windows::Storage::Streams::IOutputStream OutputStream() const; + + void Close(std::uint16_t code, winrt::param::hstring const &reason) const; + + // Events + + // TODO: WebSocketClosedEventArgs instead? + winrt::event_token Closed(winrt::Windows::Foundation::TypedEventHandler< + winrt::Windows::Networking::Sockets::IWebSocket, + winrt::Windows::Networking::Sockets::WebSocketClosedEventArgs> const &eventHandler) const; + + winrt::Windows::Networking::Sockets::IMessageWebSocket::Closed_revoker Closed( + winrt::auto_revoke_t, + winrt::Windows::Foundation::TypedEventHandler< + winrt::Windows::Networking::Sockets::IWebSocket, + winrt::Windows::Networking::Sockets::WebSocketClosedEventArgs> const &eventHandler) const; + + void Closed(winrt::event_token const &eventCookie) const noexcept; + +#pragma endregion IWebSocket overrides + +#pragma region IMessageWebSocket overrides + + winrt::Windows::Networking::Sockets::MessageWebSocketControl Control() const; + winrt::Windows::Networking::Sockets::MessageWebSocketInformation Information() const; + winrt::event_token MessageReceived( + winrt::Windows::Foundation::TypedEventHandler< + winrt::Windows::Networking::Sockets::MessageWebSocket, + winrt::Windows::Networking::Sockets::MessageWebSocketMessageReceivedEventArgs> const &eventHandler) const; + winrt::Windows::Networking::Sockets::IMessageWebSocket::MessageReceived_revoker MessageReceived( + winrt::auto_revoke_t, + winrt::Windows::Foundation::TypedEventHandler< + winrt::Windows::Networking::Sockets::MessageWebSocket, + winrt::Windows::Networking::Sockets::MessageWebSocketMessageReceivedEventArgs> const &eventHandler) const; + void MessageReceived(winrt::event_token const &eventCookie) const noexcept; + +#pragma endregion IMessageWebSocket overrides + + private: + // Used only for MessageWebSocketControl. + // Remove once MockMessageWebSocketControl is fully implemented. + winrt::Windows::Networking::Sockets::MessageWebSocket m_messageWebSocket; + +}; // MockMessageWebSocket + +struct MockDataWriter : public winrt::Windows::Storage::Streams::IDataWriter { + struct Mocks { + std::function UnstoredBufferLength; + std::function GetUnicodeEncoding; + std::function SetUnicodeEncoding; + std::function GetByteOrder; + std::function SetByteOrder; + std::function WriteByte; + std::function value) /*const*/> WriteBytes; + std::function WriteBuffer; + std::function + WriteBufferRange; + std::function WriteBoolean; + std::function WriteGuid; + std::function WriteInt16; + std::function WriteInt32; + std::function WriteInt64; + std::function WriteUInt16; + std::function WriteUInt32; + std::function WriteUInt64; + std::function WriteSingle; + std::function WriteDouble; + std::function WriteDateTime; + std::function WriteTimeSpan; + std::function WriteString; + std::function MeasureString; + std::function StoreAsync; + std::function() /*const*/> FlushAsync; + std::function DetachBuffer; + std::function DetachStream; + }; + + Mocks Mocks; + +#pragma region IDataWriter overrides + + std::uint32_t UnstoredBufferLength() const; + winrt::Windows::Storage::Streams::UnicodeEncoding UnicodeEncoding() const; + void UnicodeEncoding(winrt::Windows::Storage::Streams::UnicodeEncoding const &value) const; + winrt::Windows::Storage::Streams::ByteOrder ByteOrder() const; + void ByteOrder(winrt::Windows::Storage::Streams::ByteOrder const &value) const; + void WriteByte(std::uint8_t value) const; + void WriteBytes(winrt::array_view value) const; + void WriteBuffer(winrt::Windows::Storage::Streams::IBuffer const &buffer) const; + void WriteBuffer(winrt::Windows::Storage::Streams::IBuffer const &buffer, std::uint32_t start, std::uint32_t count) + const; + void WriteBoolean(bool value) const; + void WriteGuid(winrt::guid const &value) const; + void WriteInt16(std::int16_t value) const; + void WriteInt32(std::int32_t value) const; + void WriteInt64(std::int64_t value) const; + void WriteUInt16(std::uint16_t value) const; + void WriteUInt32(std::uint32_t value) const; + void WriteUInt64(std::uint64_t value) const; + void WriteSingle(float value) const; + void WriteDouble(double value) const; + void WriteDateTime(winrt::Windows::Foundation::DateTime const &value) const; + void WriteTimeSpan(winrt::Windows::Foundation::TimeSpan const &value) const; + std::uint32_t WriteString(winrt::param::hstring const &value) const; + std::uint32_t MeasureString(winrt::param::hstring const &value) const; + winrt::Windows::Storage::Streams::DataWriterStoreOperation StoreAsync() const; + winrt::Windows::Foundation::IAsyncOperation FlushAsync() const; + winrt::Windows::Storage::Streams::IBuffer DetachBuffer() const; + winrt::Windows::Storage::Streams::IOutputStream DetachStream() const; + +#pragma endregion IDataWriter overrides + +}; // MockDataWriter + +struct MockMessageWebSocketControl : winrt::implements< + MockMessageWebSocketControl, + winrt::Windows::Networking::Sockets::IMessageWebSocketControl, + winrt::Windows::Networking::Sockets::IWebSocketControl> { +#pragma region IWebSocketControl + + std::uint32_t OutboundBufferSizeInBytes() const; + void OutboundBufferSizeInBytes(std::uint32_t value) const; + winrt::Windows::Security::Credentials::PasswordCredential ServerCredential() const; + void ServerCredential(winrt::Windows::Security::Credentials::PasswordCredential const &value) const; + winrt::Windows::Security::Credentials::PasswordCredential ProxyCredential() const; + void ProxyCredential(winrt::Windows::Security::Credentials::PasswordCredential const &value) const; + winrt::Windows::Foundation::Collections::IVector SupportedProtocols() const; + +#pragma endregion + +#pragma region IMessageWebSocketControl + + uint32_t MaxMessageSize() const; + void MaxMessageSize(std::uint32_t value) const; + winrt::Windows::Networking::Sockets::SocketMessageType MessageType() const; + void MessageType(winrt::Windows::Networking::Sockets::SocketMessageType const &value) const; + +#pragma endregion +}; + +} // namespace Microsoft::React::Test diff --git a/vnext/Desktop.UnitTests/WinRTWebSocketResourceUnitTest.cpp b/vnext/Desktop.UnitTests/WinRTWebSocketResourceUnitTest.cpp new file mode 100644 index 00000000000..996a9caaa5d --- /dev/null +++ b/vnext/Desktop.UnitTests/WinRTWebSocketResourceUnitTest.cpp @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include +#include // WinRT fundamentals, i.e. coroutines impl. +#include "WinRTNetworkingMocks.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Networking::Sockets; + +using std::make_shared; +using std::string; +using winrt::event_token; +using winrt::param::hstring; + +using CertExceptions = std::vector; +using CloseCode = Microsoft::React::IWebSocketResource::CloseCode; +using Error = Microsoft::React::IWebSocketResource::Error; + +namespace { + +IAsyncAction DoNothingAsync() { + co_return; +} + +IAsyncAction ThrowAsync() { + throw winrt::hresult_error(winrt::hresult(E_FAIL), L"Expected Failure"); +} + +} // namespace + +namespace Microsoft::React::Test { + +TEST_CLASS (WinRTWebSocketResourceUnitTest) { + TEST_METHOD(ConnectSucceeds) { + bool connected = true; + string errorMessage; + auto imws{winrt::make()}; + + // Set up mocks + auto mws{imws.as()}; + // TODO: Mock Control() + mws->Mocks.ConnectAsync = [](const Uri &) -> IAsyncAction { return DoNothingAsync(); }; + mws->Mocks.MessageReceivedToken = + [](TypedEventHandler const &) -> event_token { + return event_token{}; + }; + mws->Mocks.Close = [](uint16_t, const hstring &) {}; + + // Test APIs + auto rc = + make_shared(std::move(imws), MockDataWriter{}, Uri{L"ws://host:0"}, CertExceptions{}); + rc->SetOnConnect([&connected]() { connected = true; }); + rc->SetOnError([&errorMessage](Error &&error) { errorMessage = error.Message; }); + + rc->Connect({}, {}); + rc->Close(CloseCode::Normal, {}); + + Assert::AreEqual({}, errorMessage); + Assert::IsTrue(connected); + } + + // TODO: Re-enable. Fails in x86|Release. + // Hangs due to exception not being caught within WinRTWebSocketResource::PerformConnect. + BEGIN_TEST_METHOD_ATTRIBUTE(ConnectFails) + TEST_IGNORE() + END_TEST_METHOD_ATTRIBUTE() + TEST_METHOD(ConnectFails) { + bool connected = false; + string errorMessage; + auto imws{winrt::make()}; + + // Set up mocks + auto mws{imws.as()}; + mws->Mocks.ConnectAsync = [](const Uri &) -> IAsyncAction { return ThrowAsync(); }; + mws->Mocks.MessageReceivedToken = + [](TypedEventHandler const &) -> event_token { + return event_token{}; + }; + mws->Mocks.Close = [](uint16_t, const hstring &) {}; + + // Test APIs + auto rc = + make_shared(std::move(imws), MockDataWriter{}, Uri{L"ws://host:0"}, CertExceptions{}); + rc->SetOnConnect([&connected]() { connected = true; }); + rc->SetOnError([&errorMessage](Error &&error) { errorMessage = error.Message; }); + + rc->Connect({}, {}); + rc->Close(CloseCode::Normal, {}); + + Assert::AreNotEqual({}, errorMessage); + Assert::IsFalse(connected); + } +}; + +} // namespace Microsoft::React::Test diff --git a/vnext/Desktop/WebSocketResourceFactory.cpp b/vnext/Desktop/WebSocketResourceFactory.cpp index 49da9e47e5b..8b71d37db24 100644 --- a/vnext/Desktop/WebSocketResourceFactory.cpp +++ b/vnext/Desktop/WebSocketResourceFactory.cpp @@ -24,7 +24,7 @@ IWebSocketResource::Make(const string &urlString, bool legacyImplementation, boo certExceptions.emplace_back( winrt::Windows::Security::Cryptography::Certificates::ChainValidationResult::InvalidName); } - return make_shared(urlString, certExceptions); + return make_shared(urlString, std::move(certExceptions)); } else { Url url(urlString); diff --git a/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj b/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj index 5ff0d84dbb7..c428d90da22 100644 --- a/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj +++ b/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj @@ -106,7 +106,6 @@ $(HERMES_Package)\installed\$(VcpkgTriplet)\include\;%(AdditionalIncludeDirectories) /await %(AdditionalOptions) false - /await %(AdditionalOptions) false diff --git a/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp b/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp index 8f31431cd42..8ee1ea218b4 100644 --- a/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp +++ b/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp @@ -30,15 +30,17 @@ using winrt::resume_background; using winrt::resume_on_signal; using winrt::Windows::Foundation::IAsyncAction; using winrt::Windows::Foundation::Uri; +using winrt::Windows::Networking::Sockets::IMessageWebSocket; +using winrt::Windows::Networking::Sockets::IMessageWebSocketMessageReceivedEventArgs; using winrt::Windows::Networking::Sockets::IWebSocket; using winrt::Windows::Networking::Sockets::MessageWebSocket; -using winrt::Windows::Networking::Sockets::MessageWebSocketMessageReceivedEventArgs; using winrt::Windows::Networking::Sockets::SocketMessageType; using winrt::Windows::Networking::Sockets::WebSocketClosedEventArgs; -using winrt::Windows::Security::Cryptography::Certificates::ChainValidationResult; using winrt::Windows::Security::Cryptography::CryptographicBuffer; -using winrt::Windows::Storage::Streams::DataReader; +using winrt::Windows::Security::Cryptography::Certificates::ChainValidationResult; using winrt::Windows::Storage::Streams::DataWriter; +using winrt::Windows::Storage::Streams::IDataReader; +using winrt::Windows::Storage::Streams::IDataWriter; using winrt::Windows::Storage::Streams::UnicodeEncoding; namespace @@ -80,8 +82,11 @@ namespace namespace Microsoft::React { -WinRTWebSocketResource::WinRTWebSocketResource(Uri&& uri, vector certExeptions) + +WinRTWebSocketResource::WinRTWebSocketResource(IMessageWebSocket&& socket, IDataWriter&& writer, Uri&& uri, vector &&certExeptions) : m_uri{ std::move(uri) } + , m_socket{ std::move(socket) } + , m_writer{ std::move(writer) } { m_socket.MessageReceived({ this, &WinRTWebSocketResource::OnMessageReceived }); @@ -91,8 +96,13 @@ WinRTWebSocketResource::WinRTWebSocketResource(Uri&& uri, vector certExeptions) - : WinRTWebSocketResource(Uri{ Utf8ToUtf16(urlString) }, certExeptions) +WinRTWebSocketResource::WinRTWebSocketResource(IMessageWebSocket&& socket, Uri&& uri, vector certExeptions) + : WinRTWebSocketResource(std::move(socket), DataWriter{ socket.OutputStream() }, std::move(uri), std::move(certExeptions)) +{ +} + +WinRTWebSocketResource::WinRTWebSocketResource(const string& urlString, vector &&certExeptions) + : WinRTWebSocketResource(MessageWebSocket{}, Uri{ Utf8ToUtf16(urlString) }, std::move(certExeptions)) { } @@ -295,12 +305,12 @@ fire_and_forget WinRTWebSocketResource::PerformClose() m_closePerformed.Set(); } -void WinRTWebSocketResource::OnMessageReceived(IWebSocket const& sender, MessageWebSocketMessageReceivedEventArgs const& args) +void WinRTWebSocketResource::OnMessageReceived(IWebSocket const& sender, IMessageWebSocketMessageReceivedEventArgs const& args) { try { string response; - DataReader reader = args.GetDataReader(); + IDataReader reader = args.GetDataReader(); auto len = reader.UnconsumedBufferLength(); if (args.MessageType() == SocketMessageType::Utf8) { diff --git a/vnext/ReactWindowsCore/WinRTWebSocketResource.h b/vnext/ReactWindowsCore/WinRTWebSocketResource.h index b274d7c0e2f..d4b2867a7bb 100644 --- a/vnext/ReactWindowsCore/WinRTWebSocketResource.h +++ b/vnext/ReactWindowsCore/WinRTWebSocketResource.h @@ -20,9 +20,10 @@ namespace Microsoft::React { class WinRTWebSocketResource : public IWebSocketResource, public std::enable_shared_from_this { winrt::Windows::Foundation::Uri m_uri; - winrt::Windows::Networking::Sockets::MessageWebSocket m_socket; - winrt::Windows::Networking::Sockets::MessageWebSocket::MessageReceived_revoker m_revoker; - winrt::Windows::Storage::Streams::DataWriter m_writer{m_socket.OutputStream()}; + winrt::Windows::Networking::Sockets::IMessageWebSocket m_socket; + // TODO: Use or remove. + winrt::Windows::Networking::Sockets::IMessageWebSocket::MessageReceived_revoker m_revoker; + winrt::Windows::Storage::Streams::IDataWriter m_writer; Mso::DispatchQueue m_dispatchQueue; Mso::ManualResetEvent m_closePerformed; @@ -44,6 +45,7 @@ class WinRTWebSocketResource : public IWebSocketResource, public std::enable_sha std::function m_errorHandler; WinRTWebSocketResource( + winrt::Windows::Networking::Sockets::IMessageWebSocket &&socket, winrt::Windows::Foundation::Uri &&uri, std::vector certExeptions); @@ -54,13 +56,20 @@ class WinRTWebSocketResource : public IWebSocketResource, public std::enable_sha void OnMessageReceived( winrt::Windows::Networking::Sockets::IWebSocket const &sender, - winrt::Windows::Networking::Sockets::MessageWebSocketMessageReceivedEventArgs const &args); + winrt::Windows::Networking::Sockets::IMessageWebSocketMessageReceivedEventArgs const &args); void Synchronize(); public: + WinRTWebSocketResource( + winrt::Windows::Networking::Sockets::IMessageWebSocket &&socket, + winrt::Windows::Storage::Streams::IDataWriter &&writer, + winrt::Windows::Foundation::Uri &&uri, + std::vector &&certExeptions); + WinRTWebSocketResource( const std::string &urlString, - std::vector certExeptions); + std::vector &&certExeptions); + ~WinRTWebSocketResource() override; #pragma region IWebSocketResource From fe265840fe8b42a2b73e7626bf8543342fcc2a2b Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Sun, 3 May 2020 00:04:42 +0000 Subject: [PATCH 040/209] applying package updates ***NO_CI*** --- ...indows-2020-04-30-18-28-03-abi-safety.json | 8 ------- ...e-windows-2020-05-01-15-49-42-wsrc_ut.json | 8 ------- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- vnext/CHANGELOG.json | 23 +++++++++++++++++++ vnext/CHANGELOG.md | 10 +++++++- vnext/package.json | 2 +- 8 files changed, 36 insertions(+), 21 deletions(-) delete mode 100644 change/react-native-windows-2020-04-30-18-28-03-abi-safety.json delete mode 100644 change/react-native-windows-2020-05-01-15-49-42-wsrc_ut.json diff --git a/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json b/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json deleted file mode 100644 index 7cf31717cd8..00000000000 --- a/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "none", - "comment": "test bundle build logic, JS function call test", - "packageName": "react-native-windows", - "email": "aeulitz@microsoft.com", - "dependentChangeType": "none", - "date": "2020-05-01T01:28:03.315Z" -} diff --git a/change/react-native-windows-2020-05-01-15-49-42-wsrc_ut.json b/change/react-native-windows-2020-05-01-15-49-42-wsrc_ut.json deleted file mode 100644 index 852ba6218ea..00000000000 --- a/change/react-native-windows-2020-05-01-15-49-42-wsrc_ut.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Implement WinRTWebSocketResource unit tests", - "packageName": "react-native-windows", - "email": "julio.rocha@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-01T22:49:42.857Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index f56b9a9ef29..2c98c1ba6db 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.56" + "react-native-windows": "0.0.0-master.57" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index a64f5e0ecce..17c9ca43a94 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.56" + "react-native-windows": "0.0.0-master.57" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index b71532e0b77..cb123bfd6b9 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.56" + "react-native-windows": "0.0.0-master.57" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index e57c502bcd5..348d1c85c66 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,29 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Sun, 03 May 2020 00:04:42 GMT", + "tag": "react-native-windows_v0.0.0-master.57", + "version": "0.0.0-master.57", + "comments": { + "none": [ + { + "comment": "test bundle build logic, JS function call test", + "author": "aeulitz@microsoft.com", + "commit": "56e08530db3e751a8813785bb51aeb728aad98b0", + "package": "react-native-windows" + } + ], + "prerelease": [ + { + "comment": "Implement WinRTWebSocketResource unit tests", + "author": "julio.rocha@microsoft.com", + "commit": "a6d5ff43421d4fb450db47aaa753c767c5966ede", + "package": "react-native-windows" + } + ] + } + }, { "date": "Sat, 02 May 2020 00:05:12 GMT", "tag": "react-native-windows_v0.0.0-master.56", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 0291c0d08fb..adf89fe64b5 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - react-native-windows -This log was last generated on Sat, 02 May 2020 00:05:12 GMT and should not be manually modified. +This log was last generated on Sun, 03 May 2020 00:04:42 GMT and should not be manually modified. +## 0.0.0-master.57 + +Sun, 03 May 2020 00:04:42 GMT + +### Changes + +- Implement WinRTWebSocketResource unit tests (julio.rocha@microsoft.com) + ## 0.0.0-master.56 Sat, 02 May 2020 00:05:12 GMT diff --git a/vnext/package.json b/vnext/package.json index 8b439b77059..189fb279fb3 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.56", + "version": "0.0.0-master.57", "license": "MIT", "repository": { "type": "git", From ccf291bb1de85a7fe68a385e587750f83da62978 Mon Sep 17 00:00:00 2001 From: dannyvv Date: Mon, 4 May 2020 09:50:18 -0700 Subject: [PATCH 041/209] Add parallel MsBuild support (/m) when building the generated solution. (#4739) * Make generated msbuild project compile in parralel (/m) * Change files --- .../react-native-windows-2020-04-29-09-45-05-master.json | 8 ++++++++ vnext/local-cli/runWindows/utils/msbuildtools.js | 1 + 2 files changed, 9 insertions(+) create mode 100644 change/react-native-windows-2020-04-29-09-45-05-master.json diff --git a/change/react-native-windows-2020-04-29-09-45-05-master.json b/change/react-native-windows-2020-04-29-09-45-05-master.json new file mode 100644 index 00000000000..afaee012d34 --- /dev/null +++ b/change/react-native-windows-2020-04-29-09-45-05-master.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Make generated msbuild project compile in parralel (/m)", + "packageName": "react-native-windows", + "email": "dannyvv@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-29T16:45:05.116Z" +} diff --git a/vnext/local-cli/runWindows/utils/msbuildtools.js b/vnext/local-cli/runWindows/utils/msbuildtools.js index a6ad327a507..eec72655537 100644 --- a/vnext/local-cli/runWindows/utils/msbuildtools.js +++ b/vnext/local-cli/runWindows/utils/msbuildtools.js @@ -56,6 +56,7 @@ class MSBuildTools { const args = [ `/clp:NoSummary;NoItemAndPropertyList;Verbosity=${verbosityOption}`, '/nologo', + '/maxCpuCount', `/p:Configuration=${buildType}`, `/p:Platform=${buildArch}`, '/p:AppxBundle=Never', From 409537e4d8555cb636fced49877d1cba56cc19cb Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 4 May 2020 19:20:51 +0000 Subject: [PATCH 042/209] Bump io-ts from 2.2.1 to 2.2.2 (#4784) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7c892c30627..b320ac58089 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7858,9 +7858,9 @@ invert-kv@^2.0.0: integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== io-ts@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.1.tgz#d8cb21a23cf8fbe697d78445a65bab42c0eb467f" - integrity sha512-RufppkTV58MfDKF2gXlHVBvi+WIyL7nUcAQMkJ1O3SiQcqwlxf6dBOJP/LV19UxHRkGKJZ6ImSj7LqYcELIejQ== + version "2.2.2" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.2.tgz#82b9ef96d95a3fb27a1abf5f29f59b07cc9b8cca" + integrity sha512-cXXIL4CR5/sWfKw/Ssc/cbZJGG13J4pJv9/RN6SlWJyh+foAPEUE0I9sWTX1kG24dvhiCM9fpO4F+2AsP+WzaQ== io.appium.settings@^2.10.0: version "2.14.1" From 023ca8ef2a109933a6a7734638f9dae6e3e094ad Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 4 May 2020 19:21:10 +0000 Subject: [PATCH 043/209] Bump @types/react-native from 0.62.5 to 0.62.7 (#4783) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index b320ac58089..b3fee2d7537 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2885,9 +2885,9 @@ integrity sha1-Hs9SYhKZ5luFU3Qzf7Ef0tEGb8E= "@types/react-native@^0.62.2": - version "0.62.5" - resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.62.5.tgz#605c2d31485c515ee18b62e8b29ffdbba404a443" - integrity sha512-x6ZBbo752yAw5XUarOyh53oNgMuafL4EhWEbd4ARSMK6Y7nTRm2a1tBHy8Fp7h7ji0XXJrxNRTXGJRRP3+MWzg== + version "0.62.7" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.62.7.tgz#bfc5ed03ba576f288603daa3f67f0f67d9a8bf57" + integrity sha512-FGFEt9GcFVl//XxWmxkeBxAx0YnzyEhJpR8hOJrjfaFKZm0KjHzzyCmCksBAP2qHSTrcJCiBkIvYCX/kGiOgww== dependencies: "@types/react" "*" From 7379a569a3f4f371f6c633b59de2162a3bd9b057 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 4 May 2020 19:22:30 +0000 Subject: [PATCH 044/209] Bump @microsoft/api-documenter from 7.7.19 to 7.7.20 (#4782) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index b3fee2d7537..87f19fc8fda 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2408,9 +2408,9 @@ write-file-atomic "^2.3.0" "@microsoft/api-documenter@^7.3.8": - version "7.7.19" - resolved "https://registry.yarnpkg.com/@microsoft/api-documenter/-/api-documenter-7.7.19.tgz#c19bbf6659ecbf2f170f32b9cab53d432232532b" - integrity sha512-MjNSttuCj5Q2eAdUXKCZc3IUltHhU5HqyizIWayjduUgLrfNYYq0kX4S17NKKUYdfwNps/mDdmAzYIR3Uc94ow== + version "7.7.20" + resolved "https://registry.yarnpkg.com/@microsoft/api-documenter/-/api-documenter-7.7.20.tgz#034fe4df720d62ebcc6af311168fdb0faf89da9c" + integrity sha512-B2gOOoYJDOqAn9iPg4Z9ay03MYtjmY2ldF3u1povTkzl5eJWERMDuuK5BLOdGdDTMr6TUd/FrhERFEeJNeQ3rg== dependencies: "@microsoft/api-extractor-model" "7.7.11" "@microsoft/tsdoc" "0.12.19" From 6bfc38a0bb7ca670d224cf484d8a0aa20189d9c0 Mon Sep 17 00:00:00 2001 From: dannyvv Date: Mon, 4 May 2020 13:01:51 -0700 Subject: [PATCH 045/209] Kill verdacio server before uploading logs and name artifacts by job (#4772) --- .ado/templates/react-native-init.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.ado/templates/react-native-init.yml b/.ado/templates/react-native-init.yml index be4bd9d0f8e..032e894506a 100644 --- a/.ado/templates/react-native-init.yml +++ b/.ado/templates/react-native-init.yml @@ -21,7 +21,7 @@ steps: - task: CmdLine@2 displayName: yarn install (local react-native-windows) inputs: - script: yarn install --frozen-lockfile + script: yarn install --frozen-lockfile - task: CmdLine@2 displayName: yarn build @@ -144,11 +144,22 @@ steps: script: npx --no-install react-native bundle --entry-file index.js --platform windows --bundle-output test.bundle workingDirectory: $(Agent.BuildDirectory)\testcli - # We are experiencing random package restore failures. Uploading the vedaccio logs to aid in diagnosing if it is verdaccio or npmjs.org + # We are experiencing random package restore failures. + # We want to uploading the vedaccio logs to aid in diagnosing if it is verdaccio or npmjs.org + # To do so we have to kill the existing server because it keeps a file-lock on the log file + - task: PowerShell@2 + displayName: Stop test npm server (verdaccio) to upload it's logs (on failure) + inputs: + targetType: inline + script: | + stop-process -name node + condition: failed() + + - task: PublishPipelineArtifact@1 displayName: Upload Verdaccio.log (on failure) inputs: targetPath: 'verdaccio.log' - artifact: 'Verdaccio.log' + artifact: '$(Agent.JobName).Verdaccio.log' publishLocation: 'pipeline' condition: failed() From 96c1c93fbf9ac314f6aaf5da151bc9365a1e75e6 Mon Sep 17 00:00:00 2001 From: Kai Guo Date: Mon, 4 May 2020 15:22:57 -0700 Subject: [PATCH 046/209] Fix appPackage path in deploy.js (#4762) * fix appPackage path * Change files * More fix * lint fix * Concat paths directly --- ...ws-2020-04-30-12-57-06-fix-apppackage-path.json | 8 ++++++++ vnext/local-cli/runWindows/utils/deploy.js | 14 ++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 change/react-native-windows-2020-04-30-12-57-06-fix-apppackage-path.json diff --git a/change/react-native-windows-2020-04-30-12-57-06-fix-apppackage-path.json b/change/react-native-windows-2020-04-30-12-57-06-fix-apppackage-path.json new file mode 100644 index 00000000000..d5f06326741 --- /dev/null +++ b/change/react-native-windows-2020-04-30-12-57-06-fix-apppackage-path.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "fix appPackage path", + "packageName": "react-native-windows", + "email": "kaigu@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-30T19:57:06.111Z" +} diff --git a/vnext/local-cli/runWindows/utils/deploy.js b/vnext/local-cli/runWindows/utils/deploy.js index b302f84a6bb..d32b6530f05 100644 --- a/vnext/local-cli/runWindows/utils/deploy.js +++ b/vnext/local-cli/runWindows/utils/deploy.js @@ -45,7 +45,10 @@ function getAppPackage(options) { options.arch === 'x86' ? `{*_x86_${configuration}_*,*_Win32_${configuration}_*}` : `*_${options.arch}_${configuration}_*`; - const appPackageGlob = `windows/{*/AppPackages,AppPackages/*}/${packageFolder}`; + + const appPackageGlob = `${ + options.root + }/windows/{*/AppPackages,AppPackages/*}/${packageFolder}`; let appPackage = glob.sync(appPackageGlob)[0]; if (!appPackage && options.release) { @@ -53,8 +56,11 @@ function getAppPackage(options) { newWarn( 'No package found in *_Release_* folder, remove _Release_ and check again', ); + appPackage = glob.sync( - `windows/{*/AppPackages,AppPackages/*}/*_${options.arch}_*`, + `${options.root}/windows/{*/AppPackages,AppPackages/*}/*_${ + options.arch + }_*`, )[0]; } @@ -192,8 +198,6 @@ async function deployToDesktop(options, verbose, slnFile) { } } - const popd = pushd(options.root); - await runPowerShellScriptFunction( 'Removing old version of the app', windowsStoreAppUtils, @@ -259,8 +263,6 @@ async function deployToDesktop(options, verbose, slnFile) { } else { newInfo('Skip the step to start the app'); } - - popd(); } function startServerInNewWindow(options, verbose) { From 523209123a0753e3151028a22507ee5e83828919 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Tue, 5 May 2020 00:04:31 +0000 Subject: [PATCH 047/209] applying package updates ***NO_CI*** --- ...ve-windows-2020-04-29-09-45-05-master.json | 8 ------- ...20-04-30-12-57-06-fix-apppackage-path.json | 8 ------- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- vnext/CHANGELOG.json | 21 +++++++++++++++++++ vnext/CHANGELOG.md | 11 +++++++++- vnext/package.json | 2 +- 8 files changed, 35 insertions(+), 21 deletions(-) delete mode 100644 change/react-native-windows-2020-04-29-09-45-05-master.json delete mode 100644 change/react-native-windows-2020-04-30-12-57-06-fix-apppackage-path.json diff --git a/change/react-native-windows-2020-04-29-09-45-05-master.json b/change/react-native-windows-2020-04-29-09-45-05-master.json deleted file mode 100644 index afaee012d34..00000000000 --- a/change/react-native-windows-2020-04-29-09-45-05-master.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Make generated msbuild project compile in parralel (/m)", - "packageName": "react-native-windows", - "email": "dannyvv@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-29T16:45:05.116Z" -} diff --git a/change/react-native-windows-2020-04-30-12-57-06-fix-apppackage-path.json b/change/react-native-windows-2020-04-30-12-57-06-fix-apppackage-path.json deleted file mode 100644 index d5f06326741..00000000000 --- a/change/react-native-windows-2020-04-30-12-57-06-fix-apppackage-path.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "fix appPackage path", - "packageName": "react-native-windows", - "email": "kaigu@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-04-30T19:57:06.111Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index 2c98c1ba6db..52a5cacfd3d 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.57" + "react-native-windows": "0.0.0-master.58" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 17c9ca43a94..dca8a586354 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.57" + "react-native-windows": "0.0.0-master.58" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index cb123bfd6b9..d8e2f7a8fae 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.57" + "react-native-windows": "0.0.0-master.58" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index 348d1c85c66..57530e1476d 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,27 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Tue, 05 May 2020 00:04:31 GMT", + "tag": "react-native-windows_v0.0.0-master.58", + "version": "0.0.0-master.58", + "comments": { + "prerelease": [ + { + "comment": "Make generated msbuild project compile in parralel (/m)", + "author": "dannyvv@microsoft.com", + "commit": "ccf291bb1de85a7fe68a385e587750f83da62978", + "package": "react-native-windows" + }, + { + "comment": "fix appPackage path", + "author": "kaigu@microsoft.com", + "commit": "96c1c93fbf9ac314f6aaf5da151bc9365a1e75e6", + "package": "react-native-windows" + } + ] + } + }, { "date": "Sun, 03 May 2020 00:04:42 GMT", "tag": "react-native-windows_v0.0.0-master.57", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index adf89fe64b5..2ed4bbe1418 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,18 @@ # Change Log - react-native-windows -This log was last generated on Sun, 03 May 2020 00:04:42 GMT and should not be manually modified. +This log was last generated on Tue, 05 May 2020 00:04:31 GMT and should not be manually modified. +## 0.0.0-master.58 + +Tue, 05 May 2020 00:04:31 GMT + +### Changes + +- Make generated msbuild project compile in parralel (/m) (dannyvv@microsoft.com) +- fix appPackage path (kaigu@microsoft.com) + ## 0.0.0-master.57 Sun, 03 May 2020 00:04:42 GMT diff --git a/vnext/package.json b/vnext/package.json index 189fb279fb3..5fab018ee78 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.57", + "version": "0.0.0-master.58", "license": "MIT", "repository": { "type": "git", From f467d8b06d481b6e36a7cd239608594017f4ebbf Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Mon, 4 May 2020 21:53:12 -0700 Subject: [PATCH 048/209] RNW on WinUI3! (#4766) Accrues towards #2492 Migrates RN code to straddle OS XAML and WinUI 3 (MUX/MUC)+WebView2 Creates a WinUI3 build config which is "build with WinUI3 in Debug". This is handled by: specifying both WinUI 2.x and 3.0 Alpha in packages.config, conditionally including one or the other props/targets based on a flag that is set (UseWinUI3) In code the UseWinUI3 flag is translated into the USE_WINUI3 macro which dictates a number of things: XAML and Comp namespaces, as well as whether to use WebView or WebView2. This build configuration is added to the PR CI. Once we validate all our partners are ok with WinUI3 we can flip the switch and make this the default. In the meantime this allows us to validate the approach as well as make sure our code doesn't rot out of being WinUI-friendly. --- .ado/ReactUWPTestApp.reg | Bin 0 -> 2826 bytes .ado/SetupLocalDumps.cmd | 2 + .ado/windows-vs-pr.yml | 48 ++++++++- ...tive-windows-2020-05-01-22-10-52-dual.json | 8 ++ .../windows/SampleAppCPP/SampleAppCpp.vcxproj | 1 - packages/playground/windows/.gitignore | 1 + .../playground/windows/playground-win32.sln | 4 + .../playground-win32/Playground-win32.vcxproj | 4 + packages/playground/windows/playground.sln | 64 +++++++++++ .../playground/windows/playground/App.cpp | 8 +- packages/playground/windows/playground/App.h | 2 +- .../windows/playground/MainPage.cpp | 10 +- .../playground/windows/playground/MainPage.h | 6 +- .../windows/playground/MainPage.idl | 3 +- .../windows/playground/Playground.vcxproj | 40 ++++++- .../playground/Playground.vcxproj.filters | 8 +- .../windows/playground/packages.config | 5 +- packages/playground/windows/playground/pch.h | 9 +- vnext/Common/Common.vcxproj | 26 ++++- vnext/Folly/Folly.vcxproj | 18 +++- vnext/JSI/Universal/JSI.Universal.vcxproj | 23 +++- .../ReactModuleBuilderMock.h | 2 +- .../CppWinRTIncludes.h | 60 ++++++++++- vnext/Microsoft.ReactNative.Cxx/JSValueXaml.h | 2 +- .../Microsoft.ReactNative.Cxx.vcxitems | 7 +- .../NamespaceRedirect.h | 2 +- .../Microsoft.ReactNative.Cxx/ReactContext.h | 12 +-- vnext/Microsoft.ReactNative/IReactContext.idl | 2 +- vnext/Microsoft.ReactNative/IViewManager.idl | 2 +- .../Microsoft.ReactNative.vcxproj | 43 ++++++-- .../Microsoft.ReactNative/PropertySheet.props | 10 ++ .../ReactApplication.idl | 2 +- .../ReactApplicationDelegate.idl | 2 +- .../ReactNative.V8JSI.Windows.WinUI3.targets | 21 ++++ vnext/Microsoft.ReactNative/ReactRootView.idl | 2 +- vnext/Microsoft.ReactNative/RedBox.cpp | 100 ++++++++++-------- vnext/Microsoft.ReactNative/XamlHelper.idl | 2 +- vnext/Microsoft.ReactNative/packages.config | 2 + vnext/PropertySheets/Application/WinUI3.props | 4 + vnext/PropertySheets/WinUI3.props | 11 ++ vnext/ReactCommon/ReactCommon.vcxproj | 18 +++- vnext/ReactUWP/Polyester/IconViewManager.cpp | 5 +- vnext/ReactUWP/ReactUWP.vcxproj | 11 +- vnext/ReactUWP/Views/ControlViewManager.cpp | 6 +- .../Views/DynamicAutomationProperties.cpp | 1 + vnext/ReactUWP/Views/FlyoutViewManager.cpp | 1 + .../Views/FrameworkElementViewManager.cpp | 3 + vnext/ReactUWP/Views/Image/BorderEffect.h | 19 +++- .../ReactUWP/Views/Image/ReactImageBrush.cpp | 6 +- vnext/ReactUWP/Views/Image/ReactImageBrush.h | 1 + vnext/ReactUWP/Views/PickerViewManager.cpp | 27 +++-- vnext/ReactUWP/Views/TextInputViewManager.cpp | 2 +- vnext/ReactUWP/Views/ViewPanel.cpp | 1 + .../ReactUWP/Views/cppwinrt/BorderEffect.idl | 11 ++ .../Views/cppwinrt/DynamicAutomationPeer.idl | 2 +- vnext/ReactUWP/Views/cppwinrt/ViewPanel.idl | 2 +- vnext/ReactUWP/packages.config | 1 + vnext/ReactWindows-Universal.sln | 3 + .../ReactWindowsCore/ReactWindowsCore.vcxproj | 16 +++ ...Windows.Universal.IntegrationTests.vcxproj | 6 +- .../React.Windows.Universal.UnitTests.vcxproj | 4 + vnext/include/ReactUWP/Utils/PropertyUtils.h | 9 +- 62 files changed, 594 insertions(+), 139 deletions(-) create mode 100644 .ado/ReactUWPTestApp.reg create mode 100644 change/react-native-windows-2020-05-01-22-10-52-dual.json rename vnext/{include => Microsoft.ReactNative.Cxx}/CppWinRTIncludes.h (56%) rename vnext/{include => Microsoft.ReactNative.Cxx}/NamespaceRedirect.h (82%) create mode 100644 vnext/Microsoft.ReactNative/ReactNative.V8JSI.Windows.WinUI3.targets create mode 100644 vnext/PropertySheets/Application/WinUI3.props create mode 100644 vnext/PropertySheets/WinUI3.props diff --git a/.ado/ReactUWPTestApp.reg b/.ado/ReactUWPTestApp.reg new file mode 100644 index 0000000000000000000000000000000000000000..a869023202322f4c5dfb26fa8aae5548d3917320 GIT binary patch literal 2826 zcmd^>NpBND5QX0viT@D!Ze+(h5{K~yh-?ak2w@Z@_SjfVJeF+|Ld0JOzSs6RF^42) ztX5BNRn^t6URTeb-=`XDqJdIfYpxv~E7pj)xfYt~hM5klV@4_C9ered#_E{ygmFbL zRG>W9vrs?ljozX2NoU&Ap<0S)&$Lh5V(qOCSncUOYh8WNDf7o+W*?hYOvgc-KWg3B8Vf(Du<>tbIS!bUm75*JnRRW}y?% zn6g(KaERznIcFSfd&;b{}j>{7bSne%m+Y=+15hV;DNrsRWc4Q_V>*K6dX2>HgE;bz|d z|BCe18FPtZ8EgvRQ00DhKr7GKcfS-+yrA!l(FCnBefKK#N=R9!4Sr3&ovlN0FWl5` zAaV;XMG)wKU>z)+YYU93%$kV}>MlLMW6rkDwa&0D=ADJBAnCWUy~Z$ywmF}WCkE`Z z`8sDW=%&mG_Kx{;csQGFSLV2%VV7}=!fV$A^$7GG9lws%&?|ztS#QQWnt9p=wF|O- dCp#fZj@8|p=ot9#?v&i^f7Mvof5}th@E6^{$gBVW literal 0 HcmV?d00001 diff --git a/.ado/SetupLocalDumps.cmd b/.ado/SetupLocalDumps.cmd index 6afd36134dd..bcc55a704a0 100644 --- a/.ado/SetupLocalDumps.cmd +++ b/.ado/SetupLocalDumps.cmd @@ -8,4 +8,6 @@ if not exist %CRASHDUMPS_FOLDER% ( ) else ( del %CRASHDUMPS_FOLDER%\* /s /q ) + +regedit /S %~dp0%\ReactUWPTestApp.reg endlocal \ No newline at end of file diff --git a/.ado/windows-vs-pr.yml b/.ado/windows-vs-pr.yml index 410ce045095..25ae525a021 100644 --- a/.ado/windows-vs-pr.yml +++ b/.ado/windows-vs-pr.yml @@ -135,6 +135,52 @@ jobs: pathtoPublish: $(Build.StagingDirectory)/TestMSRNNuget condition: eq('true', variables['TestMSRNNuget']) + - job: RNW_WinUI3 + displayName: WinUI3 Playground + dependsOn: Setup + condition: ne( dependencies.Setup.outputs['checkPayload.shouldSkipPRBuild'], 'True' ) + strategy: + matrix: # Why we only build some flavors: https://github.com/microsoft/react-native-windows/issues/4308 + X86: + BuildConfiguration: WinUI3 + BuildPlatform: x86 + pool: + vmImage: $(VmImage) + timeoutInMinutes: 60 + cancelTimeoutInMinutes: 5 + + steps: + - checkout: self + clean: false + submodules: false + + - template: templates/prepare-env.yml + + - task: NuGetCommand@2 + displayName: NuGet restore - Playground + inputs: + command: restore + restoreSolution: packages/playground/windows/Playground.sln + verbosityRestore: Detailed # Options: quiet, normal, detailed + + - task: VSBuild@1 + displayName: VSBuild - Playground + inputs: + solution: packages/playground/windows/Playground.sln + vsVersion: $(MSBuildVersion) # Optional. Options: latest, 16.0, 15.0, 14.0, 12.0, 4.0 + msbuildArchitecture: $(MSBuildArchitecture) # Optional. Options: x86, x64 + platform: $(BuildPlatform) # Optional + configuration: $(BuildConfiguration) # Optional + clean: true # Optional + maximumCpuCount: false # Optional + restoreNugetPackages: false # Optional + msbuildArgs: + /p:PreferredToolArchitecture=$(MSBuildPreferredToolArchitecture) + /p:PlatformToolset=$(MSBuildPlatformToolset) + /p:BaseIntDir=$(BaseIntDir) + /p:AppxPackageSigningEnabled=false + + - job: RNWUniversalOtherProjectsPR displayName: Universal Other Projects PR dependsOn: Setup @@ -601,4 +647,4 @@ jobs: - template: templates/prep-and-pack-nuget.yml parameters: slices: '("x64.Release", "x86.Debug", "ARM.Debug")' - packUniversal: false \ No newline at end of file + packUniversal: false diff --git a/change/react-native-windows-2020-05-01-22-10-52-dual.json b/change/react-native-windows-2020-05-01-22-10-52-dual.json new file mode 100644 index 00000000000..86e0ba60fd5 --- /dev/null +++ b/change/react-native-windows-2020-05-01-22-10-52-dual.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "WinUI 3 Alpha support in RNW", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-02T05:10:51.951Z" +} diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/SampleAppCpp.vcxproj b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/SampleAppCpp.vcxproj index 61c4965de7d..addc3cc801d 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/SampleAppCpp.vcxproj +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/SampleAppCpp.vcxproj @@ -111,7 +111,6 @@ /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) %(DisableSpecificWarnings) - %(AdditionalIncludeDirectories) NOMINMAX;_HAS_AUTO_PTR_ETC;RN_EXPORT=;%(PreprocessorDefinitions) diff --git a/packages/playground/windows/.gitignore b/packages/playground/windows/.gitignore index cdb229b3b3a..0925a804895 100644 --- a/packages/playground/windows/.gitignore +++ b/packages/playground/windows/.gitignore @@ -33,6 +33,7 @@ ipch/ [Bb]in [Dd]ebug*/ [Rr]elease*/ +[Ww]inUI3*/ Ankh.NoLoad # Visual C++ cache files diff --git a/packages/playground/windows/playground-win32.sln b/packages/playground/windows/playground-win32.sln index 8b30f151e52..96253acb397 100644 --- a/packages/playground/windows/playground-win32.sln +++ b/packages/playground/windows/playground-win32.sln @@ -38,11 +38,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Universal", "..\..\..\v EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "..\..\..\vnext\Common\Common.vcxproj", "{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", "..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems", "{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ..\..\..\vnext\Chakra\Chakra.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 + ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 ..\..\..\vnext\Mso\Mso.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 ..\..\..\vnext\Shared\Shared.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 + ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{8b88ffae-4dbc-49a2-afa5-d2477d4ad189}*SharedItemsImports = 4 ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/packages/playground/windows/playground-win32/Playground-win32.vcxproj b/packages/playground/windows/playground-win32/Playground-win32.vcxproj index 3d8ffa2eef5..9e4ec292c29 100644 --- a/packages/playground/windows/playground-win32/Playground-win32.vcxproj +++ b/packages/playground/windows/playground-win32/Playground-win32.vcxproj @@ -7,6 +7,7 @@ UAP 10.0.18362.0 10.0.18362.0 + false @@ -57,6 +58,9 @@ + + + False 867D41FE5091AED426000143497EA4DFC29A8097 diff --git a/packages/playground/windows/playground.sln b/packages/playground/windows/playground.sln index ba7822ac2d1..6c610df8452 100644 --- a/packages/playground/windows/playground.sln +++ b/packages/playground/windows/playground.sln @@ -65,6 +65,10 @@ Global Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 + WinUI3|ARM = WinUI3|ARM + WinUI3|ARM64 = WinUI3|ARM64 + WinUI3|x64 = WinUI3|x64 + WinUI3|x86 = WinUI3|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.Debug|ARM.ActiveCfg = Debug|ARM @@ -91,6 +95,18 @@ Global {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.Release|x86.ActiveCfg = Release|Win32 {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.Release|x86.Build.0 = Release|Win32 {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.Release|x86.Deploy.0 = Release|Win32 + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|ARM.ActiveCfg = WinUI3|ARM + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|ARM.Build.0 = WinUI3|ARM + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|ARM.Deploy.0 = WinUI3|ARM + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|ARM64.ActiveCfg = WinUI3|ARM64 + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|ARM64.Build.0 = WinUI3|ARM64 + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|ARM64.Deploy.0 = WinUI3|ARM64 + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|x64.ActiveCfg = WinUI3|x64 + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|x64.Build.0 = WinUI3|x64 + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|x64.Deploy.0 = WinUI3|x64 + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|x86.ActiveCfg = WinUI3|Win32 + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|x86.Build.0 = WinUI3|Win32 + {6B6AA847-B32F-41AC-9D3B-48A8CDFA8ADE}.WinUI3|x86.Deploy.0 = WinUI3|Win32 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM.ActiveCfg = Debug|ARM {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM.Build.0 = Debug|ARM {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -107,6 +123,14 @@ Global {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.Build.0 = Release|x64 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.ActiveCfg = Release|Win32 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.Build.0 = Release|Win32 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.WinUI3|ARM.ActiveCfg = WinUI3|ARM + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.WinUI3|ARM.Build.0 = WinUI3|ARM + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.WinUI3|ARM64.ActiveCfg = WinUI3|ARM64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.WinUI3|ARM64.Build.0 = WinUI3|ARM64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.WinUI3|x64.ActiveCfg = WinUI3|x64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.WinUI3|x64.Build.0 = WinUI3|x64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.WinUI3|x86.ActiveCfg = WinUI3|Win32 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.WinUI3|x86.Build.0 = WinUI3|Win32 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.ActiveCfg = Debug|ARM {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.Build.0 = Debug|ARM {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -123,6 +147,14 @@ Global {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.Build.0 = Release|x64 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.ActiveCfg = Release|Win32 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.Build.0 = Release|Win32 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.WinUI3|ARM.ActiveCfg = WinUI3|ARM + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.WinUI3|ARM.Build.0 = WinUI3|ARM + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.WinUI3|ARM64.ActiveCfg = WinUI3|ARM64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.WinUI3|ARM64.Build.0 = WinUI3|ARM64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.WinUI3|x64.ActiveCfg = WinUI3|x64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.WinUI3|x64.Build.0 = WinUI3|x64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.WinUI3|x86.ActiveCfg = WinUI3|Win32 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.WinUI3|x86.Build.0 = WinUI3|Win32 {11C084A3-A57C-4296-A679-CAC17B603144}.Debug|ARM.ActiveCfg = Debug|ARM {11C084A3-A57C-4296-A679-CAC17B603144}.Debug|ARM.Build.0 = Debug|ARM {11C084A3-A57C-4296-A679-CAC17B603144}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -139,6 +171,14 @@ Global {11C084A3-A57C-4296-A679-CAC17B603144}.Release|x64.Build.0 = Release|x64 {11C084A3-A57C-4296-A679-CAC17B603144}.Release|x86.ActiveCfg = Release|Win32 {11C084A3-A57C-4296-A679-CAC17B603144}.Release|x86.Build.0 = Release|Win32 + {11C084A3-A57C-4296-A679-CAC17B603144}.WinUI3|ARM.ActiveCfg = WinUI3|ARM + {11C084A3-A57C-4296-A679-CAC17B603144}.WinUI3|ARM.Build.0 = WinUI3|ARM + {11C084A3-A57C-4296-A679-CAC17B603144}.WinUI3|ARM64.ActiveCfg = WinUI3|ARM64 + {11C084A3-A57C-4296-A679-CAC17B603144}.WinUI3|ARM64.Build.0 = WinUI3|ARM64 + {11C084A3-A57C-4296-A679-CAC17B603144}.WinUI3|x64.ActiveCfg = WinUI3|x64 + {11C084A3-A57C-4296-A679-CAC17B603144}.WinUI3|x64.Build.0 = WinUI3|x64 + {11C084A3-A57C-4296-A679-CAC17B603144}.WinUI3|x86.ActiveCfg = WinUI3|Win32 + {11C084A3-A57C-4296-A679-CAC17B603144}.WinUI3|x86.Build.0 = WinUI3|Win32 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.ActiveCfg = Debug|ARM {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.Build.0 = Debug|ARM {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -155,6 +195,14 @@ Global {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.Build.0 = Release|x64 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.ActiveCfg = Release|Win32 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.Build.0 = Release|Win32 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.WinUI3|ARM.ActiveCfg = WinUI3|ARM + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.WinUI3|ARM.Build.0 = WinUI3|ARM + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.WinUI3|ARM64.ActiveCfg = WinUI3|ARM64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.WinUI3|ARM64.Build.0 = WinUI3|ARM64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.WinUI3|x64.ActiveCfg = WinUI3|x64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.WinUI3|x64.Build.0 = WinUI3|x64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.WinUI3|x86.ActiveCfg = WinUI3|Win32 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.WinUI3|x86.Build.0 = WinUI3|Win32 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.ActiveCfg = Debug|ARM {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.Build.0 = Debug|ARM {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -171,6 +219,14 @@ Global {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x64.Build.0 = Release|x64 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x86.ActiveCfg = Release|Win32 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x86.Build.0 = Release|Win32 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.WinUI3|ARM.ActiveCfg = WinUI3|ARM + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.WinUI3|ARM.Build.0 = WinUI3|ARM + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.WinUI3|ARM64.ActiveCfg = WinUI3|ARM64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.WinUI3|ARM64.Build.0 = WinUI3|ARM64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.WinUI3|x64.ActiveCfg = WinUI3|x64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.WinUI3|x64.Build.0 = WinUI3|x64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.WinUI3|x86.ActiveCfg = WinUI3|Win32 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.WinUI3|x86.Build.0 = WinUI3|Win32 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM.ActiveCfg = Debug|ARM {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM.Build.0 = Debug|ARM {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -187,6 +243,14 @@ Global {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.Build.0 = Release|x64 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.ActiveCfg = Release|Win32 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.Build.0 = Release|Win32 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.WinUI3|ARM.ActiveCfg = WinUI3|ARM + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.WinUI3|ARM.Build.0 = WinUI3|ARM + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.WinUI3|ARM64.ActiveCfg = WinUI3|ARM64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.WinUI3|ARM64.Build.0 = WinUI3|ARM64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.WinUI3|x64.ActiveCfg = WinUI3|x64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.WinUI3|x64.Build.0 = WinUI3|x64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.WinUI3|x86.ActiveCfg = WinUI3|Win32 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.WinUI3|x86.Build.0 = WinUI3|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/packages/playground/windows/playground/App.cpp b/packages/playground/windows/playground/App.cpp index 04ad962f094..b06cf5068f7 100644 --- a/packages/playground/windows/playground/App.cpp +++ b/packages/playground/windows/playground/App.cpp @@ -7,9 +7,9 @@ using namespace winrt; using namespace Windows::ApplicationModel; using namespace Windows::ApplicationModel::Activation; using namespace Windows::Foundation; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Navigation; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Navigation; using namespace playground; using namespace playground::implementation; @@ -101,4 +101,4 @@ void App::OnSuspending([[maybe_unused]] IInspectable const &sender, [[maybe_unus /// Details about the navigation failure void App::OnNavigationFailed(IInspectable const &, NavigationFailedEventArgs const &e) { throw hresult_error(E_FAIL, hstring(L"Failed to load Page ") + e.SourcePageType().Name); -} \ No newline at end of file +} diff --git a/packages/playground/windows/playground/App.h b/packages/playground/windows/playground/App.h index 303240357f1..159487a4d81 100644 --- a/packages/playground/windows/playground/App.h +++ b/packages/playground/windows/playground/App.h @@ -7,6 +7,6 @@ struct App : AppT { void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const &); void OnSuspending(IInspectable const &, Windows::ApplicationModel::SuspendingEventArgs const &); - void OnNavigationFailed(IInspectable const &, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs const &); + void OnNavigationFailed(IInspectable const &, xaml::Navigation::NavigationFailedEventArgs const &); }; } // namespace winrt::playground::implementation diff --git a/packages/playground/windows/playground/MainPage.cpp b/packages/playground/windows/playground/MainPage.cpp index b1e7b1dd4ca..57ad5438409 100644 --- a/packages/playground/windows/playground/MainPage.cpp +++ b/packages/playground/windows/playground/MainPage.cpp @@ -6,9 +6,9 @@ using namespace winrt; using namespace Windows::ApplicationModel::Activation; using namespace Windows::Foundation; using namespace Windows::UI; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Media; +using namespace xaml; +using namespace xaml::Controls; +using namespace xaml::Media; using namespace Windows::Storage; using namespace Windows::Storage::Streams; using namespace Windows::Graphics::Imaging; @@ -31,7 +31,7 @@ MainPage::MainPage() { void MainPage::OnLoadClick( Windows::Foundation::IInspectable const & /*sender*/, - Windows::UI::Xaml::RoutedEventArgs const & /*args*/) { + xaml::RoutedEventArgs const & /*args*/) { auto host = Host(); auto bundleFile = unbox_value(x_entryPointCombo().SelectedItem().as().Content()); host.InstanceSettings().JavaScriptBundleFile(bundleFile); @@ -56,7 +56,7 @@ void MainPage::OnLoadClick( void winrt::playground::implementation::MainPage::x_entryPointCombo_SelectionChanged( winrt::Windows::Foundation::IInspectable const & /*sender*/, - winrt::Windows::UI::Xaml::Controls::SelectionChangedEventArgs const & /*e*/) { + xaml::Controls::SelectionChangedEventArgs const & /*e*/) { if (x_rootComponentNameCombo()) { auto bundleFile = unbox_value(x_entryPointCombo().SelectedItem().as().Content()); if (std::wstring(bundleFile).compare(L"Samples\\rntester") == 0) { diff --git a/packages/playground/windows/playground/MainPage.h b/packages/playground/windows/playground/MainPage.h index 6f5666185fc..cc2d8777abc 100644 --- a/packages/playground/windows/playground/MainPage.h +++ b/packages/playground/windows/playground/MainPage.h @@ -6,9 +6,7 @@ namespace winrt::playground::implementation { struct MainPage : MainPageT { MainPage(); - void OnLoadClick( - Windows::Foundation::IInspectable const & /*sender*/, - Windows::UI::Xaml::RoutedEventArgs const & /*args*/); + void OnLoadClick(Windows::Foundation::IInspectable const & /*sender*/, xaml::RoutedEventArgs const & /*args*/); private: Microsoft::ReactNative::ReactNativeHost Host() noexcept; @@ -25,7 +23,7 @@ struct MainPage : MainPageT { public: void x_entryPointCombo_SelectionChanged( winrt::Windows::Foundation::IInspectable const &sender, - winrt::Windows::UI::Xaml::Controls::SelectionChangedEventArgs const &e); + xaml::Controls::SelectionChangedEventArgs const &e); }; } // namespace winrt::playground::implementation diff --git a/packages/playground/windows/playground/MainPage.idl b/packages/playground/windows/playground/MainPage.idl index 7fa1ef443d8..da576534c32 100644 --- a/packages/playground/windows/playground/MainPage.idl +++ b/packages/playground/windows/playground/MainPage.idl @@ -1,10 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#include "NamespaceRedirect.h" namespace playground { [default_interface] - runtimeclass MainPage : Windows.UI.Xaml.Controls.Page { + runtimeclass MainPage : XAML_NAMESPACE.Controls.Page { MainPage(); } diff --git a/packages/playground/windows/playground/Playground.vcxproj b/packages/playground/windows/playground/Playground.vcxproj index b4f37c4a9e6..1c31c93f41c 100644 --- a/packages/playground/windows/playground/Playground.vcxproj +++ b/packages/playground/windows/playground/Playground.vcxproj @@ -53,6 +53,22 @@ Release x64 + + WinUI3 + ARM + + + WinUI3 + ARM64 + + + WinUI3 + Win32 + + + WinUI3 + x64 + Application @@ -62,11 +78,18 @@ true true + + true + true + true + false true false + @@ -95,6 +118,14 @@ _DEBUG;%(PreprocessorDefinitions) + + + _DEBUG;USE_WINUI3;%(PreprocessorDefinitions) + + + USE_WINUI3;%(PreprocessorDefinitions) + + NDEBUG;%(PreprocessorDefinitions) @@ -169,7 +200,6 @@ - @@ -178,7 +208,8 @@ - + + @@ -186,6 +217,7 @@ - + + - \ No newline at end of file + diff --git a/packages/playground/windows/playground/Playground.vcxproj.filters b/packages/playground/windows/playground/Playground.vcxproj.filters index 4a2e229c0c9..e0fa9658ed5 100644 --- a/packages/playground/windows/playground/Playground.vcxproj.filters +++ b/packages/playground/windows/playground/Playground.vcxproj.filters @@ -50,10 +50,16 @@ - + + + + + + + \ No newline at end of file diff --git a/packages/playground/windows/playground/packages.config b/packages/playground/windows/playground/packages.config index 944c02938da..ae337d5b3f2 100644 --- a/packages/playground/windows/playground/packages.config +++ b/packages/playground/windows/playground/packages.config @@ -1,5 +1,6 @@ - + - \ No newline at end of file + + diff --git a/packages/playground/windows/playground/pch.h b/packages/playground/windows/playground/pch.h index 4d593052bfd..28f6bb4ffec 100644 --- a/packages/playground/windows/playground/pch.h +++ b/packages/playground/windows/playground/pch.h @@ -17,13 +17,8 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include + +#include "CppWinRTIncludes.h" #include diff --git a/vnext/Common/Common.vcxproj b/vnext/Common/Common.vcxproj index 412cd2a01fb..e58ce1dd665 100644 --- a/vnext/Common/Common.vcxproj +++ b/vnext/Common/Common.vcxproj @@ -10,7 +10,7 @@ - + Debug x64 @@ -43,8 +43,24 @@ Release ARM64 + + WinUI3 + ARM + + + WinUI3 + ARM64 + + + WinUI3 + Win32 + + + WinUI3 + x64 + - + StaticLibrary @@ -86,11 +102,11 @@ - + - - + + diff --git a/vnext/Folly/Folly.vcxproj b/vnext/Folly/Folly.vcxproj index 5f8c698dd40..25762721c5d 100644 --- a/vnext/Folly/Folly.vcxproj +++ b/vnext/Folly/Folly.vcxproj @@ -45,6 +45,22 @@ Release Win32 + + WinUI3 + ARM + + + WinUI3 + ARM64 + + + WinUI3 + Win32 + + + WinUI3 + x64 + StaticLibrary @@ -277,7 +293,7 @@ - + @@ -15,7 +15,7 @@ Windows Store 10.0 10.0.18362.0 - 10.0.16299.0 + 10.0.17134.0 true @@ -55,6 +55,22 @@ Release x64 + + WinUI3 + ARM + + + WinUI3 + ARM64 + + + WinUI3 + Win32 + + + WinUI3 + x64 + DynamicLibrary @@ -65,11 +81,18 @@ true true + + true + true + true + false true false + @@ -158,7 +181,11 @@ _DEBUG;%(PreprocessorDefinitions) - false + + + + + _DEBUG;%(PreprocessorDefinitions) @@ -169,7 +196,7 @@ - PROJECT_ROOT_NAMESPACE=$(RootNamespace) + PROJECT_ROOT_NAMESPACE=$(RootNamespace);%(PreprocessorDefinitions) @@ -583,8 +610,11 @@ - + + + + @@ -593,7 +623,8 @@ - + + diff --git a/vnext/Microsoft.ReactNative/PropertySheet.props b/vnext/Microsoft.ReactNative/PropertySheet.props index 064dec08100..8b025412380 100644 --- a/vnext/Microsoft.ReactNative/PropertySheet.props +++ b/vnext/Microsoft.ReactNative/PropertySheet.props @@ -14,4 +14,14 @@ $(CppWinRTVerbosity) + + + + USE_WINUI3;%(PreprocessorDefinitions) + + + USE_WINUI3;%(PreprocessorDefinitions) + + + \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative/ReactApplication.idl b/vnext/Microsoft.ReactNative/ReactApplication.idl index b554783f0bb..1b62f75856a 100644 --- a/vnext/Microsoft.ReactNative/ReactApplication.idl +++ b/vnext/Microsoft.ReactNative/ReactApplication.idl @@ -2,7 +2,7 @@ // Licensed under the MIT License. import "ReactNativeHost.idl"; -#include "../include/NamespaceRedirect.h" +#include "NamespaceRedirect.h" namespace Microsoft.ReactNative { diff --git a/vnext/Microsoft.ReactNative/ReactApplicationDelegate.idl b/vnext/Microsoft.ReactNative/ReactApplicationDelegate.idl index a7bf51ddbff..ca596c9f4d6 100644 --- a/vnext/Microsoft.ReactNative/ReactApplicationDelegate.idl +++ b/vnext/Microsoft.ReactNative/ReactApplicationDelegate.idl @@ -2,7 +2,7 @@ // Licensed under the MIT License. import "ReactApplication.idl"; -#include "../include/NamespaceRedirect.h" +#include "NamespaceRedirect.h" namespace Microsoft.ReactNative { diff --git a/vnext/Microsoft.ReactNative/ReactNative.V8JSI.Windows.WinUI3.targets b/vnext/Microsoft.ReactNative/ReactNative.V8JSI.Windows.WinUI3.targets new file mode 100644 index 00000000000..cde3e36edc3 --- /dev/null +++ b/vnext/Microsoft.ReactNative/ReactNative.V8JSI.Windows.WinUI3.targets @@ -0,0 +1,21 @@ + + + + $(V8_Package)\build\native\..\..\lib\Debug\x64;%(AdditionalLibraryDirectories) + $(V8_Package)\build\native\..\..\lib\Debug\x86;%(AdditionalLibraryDirectories) + v8jsi.dll.lib;%(AdditionalDependencies) + v8jsi.dll;%(DelayLoadDLLs) + + + $(V8_Package)\build\native\include;%(AdditionalIncludeDirectories) + + + + + + + + + + + \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative/ReactRootView.idl b/vnext/Microsoft.ReactNative/ReactRootView.idl index 8e572f8464a..38764d590b8 100644 --- a/vnext/Microsoft.ReactNative/ReactRootView.idl +++ b/vnext/Microsoft.ReactNative/ReactRootView.idl @@ -3,7 +3,7 @@ import "IJSValueWriter.idl"; import "ReactNativeHost.idl"; -#include "../include/NamespaceRedirect.h" +#include "NamespaceRedirect.h" namespace Microsoft.ReactNative { diff --git a/vnext/Microsoft.ReactNative/RedBox.cpp b/vnext/Microsoft.ReactNative/RedBox.cpp index 90279a135e7..0c1c327cb24 100644 --- a/vnext/Microsoft.ReactNative/RedBox.cpp +++ b/vnext/Microsoft.ReactNative/RedBox.cpp @@ -151,6 +151,59 @@ struct RedBox : public std::enable_shared_from_this { #define _MAKE_WIDE_STR(x) L##x #define MAKE_WIDE_STR(x) _MAKE_WIDE_STR(x) + void CreateWebView(xaml::Controls::Panel parent, const winrt::hstring &content) { +#ifndef USE_WINUI3 + xaml::Controls::WebView webView; +#else + xaml::Controls::WebView2 webView; +#endif + + webView.HorizontalAlignment(xaml::HorizontalAlignment::Stretch); + webView.VerticalAlignment(xaml::VerticalAlignment::Stretch); + webView.MinWidth(400); + auto dispatcher = winrt::system::DispatcherQueue::GetForCurrentThread(); + // XAML doesn't currently provide a way to measure a WebView control, + // So we're going to tell the WebView to measure itself by running some javascript, + // and then we'll post a task back to XAML to set the XAML WebView minimum height. + // The HTML we get from Metro doesn't have any styling, so we'll take advantage of + // the fact that we're running javascript in the WebView, to set the + // foreground/background to match the rest of the RedBox. + // setProperty returns undefined so we continue the first expression with a comma + // whereas the height expression gets executed because of the || + // (since the setProperty calls resulted in undefined). + // Finally, it's important to note that JS expressions of that are not of string type + // need to be manually converted to string for them to get marshaled properly back here. + webView.NavigationCompleted([=](IInspectable const &, auto const &) { + // #eecc0000 ARGB is #be0000 RGB (background doesn't seem to allow alpha channel in WebView) + std::wstring jsExpression = + L"(document.body.style.setProperty('color', 'white'), " + L"document.body.style.setProperty('background', '#be0000')) " + L"|| document.documentElement.scrollHeight.toString()"; + +#ifndef USE_WINUI3 + auto async = webView.InvokeScriptAsync(L"eval", std::vector{winrt::hstring { jsExpression }}); +#else + auto async = webView.ExecuteScriptAsync(std::wstring(L"eval(") + jsExpression + L")"); +#endif + + async.Completed([=](IAsyncOperation const &op, auto &&) { + auto result = op.GetResults(); + int documentHeight = _wtoi(result.c_str()); + dispatcher.TryEnqueue([=]() { + // Ensure the webview has a min height of the content it wants to show, + // and that the horizontal scrollbar that might exist, doesn't occlude the webview. + constexpr int horizontalScrollbarHeight = 12; + webView.MinHeight(documentHeight + horizontalScrollbarHeight); + }); + }); + }); + + m_stackPanel.Children().Clear(); + m_stackPanel.Children().Append(webView); + + webView.NavigateToString(content); + } + void UpdateErrorMessageUI() noexcept { const std::regex colorsRegex( "\\x1b\\[[0-9;]*m"); // strip out console colors which is often added to JS error messages @@ -168,8 +221,7 @@ struct RedBox : public std::enable_shared_from_this { xaml::Documents::Run linkRun; linkRun.Text(Microsoft::Common::Unicode::Utf8ToUtf16(METRO_TROUBLESHOOTING_URL)); - link.Foreground( - xaml::Media::SolidColorBrush(winrt::Windows::UI::ColorHelper::FromArgb(0xff, 0xff, 0xff, 0xff))); + link.Foreground(xaml::Media::SolidColorBrush(winrt::ColorHelper::FromArgb(0xff, 0xff, 0xff, 0xff))); link.Inlines().Append(linkRun); xaml::Documents::Run normalRun; normalRun.Text(Microsoft::Common::Unicode::Utf8ToUtf16(json["type"].asString() + (" ─ See "))); @@ -204,51 +256,9 @@ struct RedBox : public std::enable_shared_from_this { } catch (...) { std::string doctype = ""; if (boost::istarts_with(plain, doctype)) { - auto webView = xaml::Controls::WebView(xaml::Controls::WebViewExecutionMode::SameThread); - winrt::hstring content(Microsoft::Common::Unicode::Utf8ToUtf16(plain.substr(doctype.length()).c_str())); - webView.HorizontalAlignment(xaml::HorizontalAlignment::Stretch); - webView.VerticalAlignment(xaml::VerticalAlignment::Stretch); - webView.MinWidth(400); - - m_stackPanel.Children().Clear(); - m_stackPanel.Children().Append(webView); - - auto dispatcher = winrt::Windows::System::DispatcherQueue::GetForCurrentThread(); - // XAML doesn't currently provide a way to measure a WebView control, - // So we're going to tell the WebView to measure itself by running some javascript, - // and then we'll post a task back to XAML to set the XAML WebView minimum height. - // The HTML we get from Metro doesn't have any styling, so we'll take advantage of - // the fact that we're running javascript in the WebView, to set the - // foreground/background to match the rest of the RedBox. - // setProperty returns undefined so we continue the first expression with a comma - // whereas the height expression gets executed because of the || - // (since the setProperty calls resulted in undefined). - // Finally, it's important to note that JS expressions of that are not of string type - // need to be manually converted to string for them to get marshaled properly back here. - webView.NavigationCompleted( - [=](IInspectable const &, xaml::Controls::WebViewNavigationCompletedEventArgs const &) { - // #eecc0000 ARGB is #be0000 RGB (background doesn't seem to allow alpha channel in WebView) - std::vector args{ - L"(document.body.style.setProperty('color', 'white'), " - L"document.body.style.setProperty('background', '#be0000')) " - L"|| document.documentElement.scrollHeight.toString()"}; - auto async = webView.InvokeScriptAsync(L"eval", std::move(args)); - - async.Completed([=](IAsyncOperation const &op, auto &&state) { - auto result = op.GetResults(); - int documentHeight = _wtoi(result.c_str()); - dispatcher.TryEnqueue([=]() { - // Ensure the webview has a min height of the content it wants to show, - // and that the horizontal scrollbar that might exist, doesn't occlude the webview. - constexpr int horizontalScrollbarHeight = 12; - webView.MinHeight(documentHeight + horizontalScrollbarHeight); - }); - }); - }); - - webView.NavigateToString(content); + CreateWebView(m_stackPanel, content); m_stackPanel.Margin(xaml::ThicknessHelper::FromUniformLength(0)); m_stackPanelUpper.Visibility(xaml::Visibility::Collapsed); diff --git a/vnext/Microsoft.ReactNative/XamlHelper.idl b/vnext/Microsoft.ReactNative/XamlHelper.idl index 3f24e28ad94..474c23f9eae 100644 --- a/vnext/Microsoft.ReactNative/XamlHelper.idl +++ b/vnext/Microsoft.ReactNative/XamlHelper.idl @@ -2,7 +2,7 @@ // Licensed under the MIT License. import "IJSValueWriter.idl"; -#include "../include/NamespaceRedirect.h" +#include "NamespaceRedirect.h" namespace Microsoft.ReactNative { diff --git a/vnext/Microsoft.ReactNative/packages.config b/vnext/Microsoft.ReactNative/packages.config index ee35bcc7405..0ce52b5a221 100644 --- a/vnext/Microsoft.ReactNative/packages.config +++ b/vnext/Microsoft.ReactNative/packages.config @@ -2,5 +2,7 @@ + + \ No newline at end of file diff --git a/vnext/PropertySheets/Application/WinUI3.props b/vnext/PropertySheets/Application/WinUI3.props new file mode 100644 index 00000000000..a5e67783eee --- /dev/null +++ b/vnext/PropertySheets/Application/WinUI3.props @@ -0,0 +1,4 @@ + + + + diff --git a/vnext/PropertySheets/WinUI3.props b/vnext/PropertySheets/WinUI3.props new file mode 100644 index 00000000000..500b6ba12f6 --- /dev/null +++ b/vnext/PropertySheets/WinUI3.props @@ -0,0 +1,11 @@ + + + + + + + USE_WINUI3;%(PreprocessorDefinitions) + + + + diff --git a/vnext/ReactCommon/ReactCommon.vcxproj b/vnext/ReactCommon/ReactCommon.vcxproj index a4e72c30509..ed24e5bdbc5 100644 --- a/vnext/ReactCommon/ReactCommon.vcxproj +++ b/vnext/ReactCommon/ReactCommon.vcxproj @@ -11,7 +11,7 @@ - + Debug ARM @@ -44,6 +44,22 @@ Release Win32 + + WinUI3 + ARM + + + WinUI3 + ARM64 + + + WinUI3 + Win32 + + + WinUI3 + x64 + StaticLibrary diff --git a/vnext/ReactUWP/Polyester/IconViewManager.cpp b/vnext/ReactUWP/Polyester/IconViewManager.cpp index 1be6ee0d005..42b31ffb6c9 100644 --- a/vnext/ReactUWP/Polyester/IconViewManager.cpp +++ b/vnext/ReactUWP/Polyester/IconViewManager.cpp @@ -16,7 +16,6 @@ namespace winrt { using namespace Windows::Foundation; -using namespace Windows::UI; using namespace xaml; using namespace xaml::Documents; using namespace xaml::Media; @@ -119,14 +118,14 @@ void IconShadowNode::updateProperties(const folly::dynamic &&props) { glyphs.IsColorFontEnabled(false); auto application = winrt::Application::Current(); - if (!winrt::ViewManagement::AccessibilitySettings().HighContrast()) { + if (!winrt::Windows::UI::ViewManagement::AccessibilitySettings().HighContrast()) { // 0 - Light, 1 - Light Disabled, 2 - Dark, 3 - Dark Disabled glyphs.ColorFontPaletteIndex(application.RequestedTheme() == winrt::ApplicationTheme::Light ? 0 : 2); } // Set default Fill color auto appDictionary = application.Resources(); - auto color = winrt::Windows::UI::Colors::Black(); + auto color = winrt::Colors::Black(); if (appDictionary.HasKey(winrt::box_value(L"SystemAccentColor"))) color = winrt::unbox_value(appDictionary.Lookup(winrt::box_value(L"SystemAccentColor"))); diff --git a/vnext/ReactUWP/ReactUWP.vcxproj b/vnext/ReactUWP/ReactUWP.vcxproj index b1882e5948e..ffddc8d89cb 100644 --- a/vnext/ReactUWP/ReactUWP.vcxproj +++ b/vnext/ReactUWP/ReactUWP.vcxproj @@ -1,6 +1,7 @@ + Debug @@ -56,6 +57,7 @@ $(OutDir.TrimEnd("/\")) $(MSBuildThisFileDirectory)GeneratedWinmdHeader false + false @@ -67,6 +69,7 @@ + @@ -136,7 +139,7 @@ winsqlite3.dll;%(DelayLoadDLLs) - $(ProjectDir)ABI\idl;$(ProjectDir)Views\cppwinrt + $(ProjectDir)ABI\idl;$(ProjectDir)Views\cppwinrt;%(AdditionalIncludeDirectories) @@ -442,7 +445,8 @@ - + + @@ -452,7 +456,8 @@ - + + diff --git a/vnext/ReactUWP/Views/ControlViewManager.cpp b/vnext/ReactUWP/Views/ControlViewManager.cpp index a2679f44c04..0b26c602d03 100644 --- a/vnext/ReactUWP/Views/ControlViewManager.cpp +++ b/vnext/ReactUWP/Views/ControlViewManager.cpp @@ -32,7 +32,7 @@ void ControlViewManager::TransferProperties(const XamlView &oldView, const XamlV TransferProperty(oldView, newView, xaml::Controls::Control::ForegroundProperty()); TransferProperty(oldView, newView, xaml::Controls::Control::TabIndexProperty()); // Control.CornerRadius is only supported on >= RS5 - if (oldView.try_as() && newView.try_as()) { + if (oldView.try_as() && newView.try_as()) { TransferProperty(oldView, newView, xaml::Controls::Control::CornerRadiusProperty()); } Super::TransferProperties(oldView, newView); @@ -75,7 +75,7 @@ bool ControlViewManager::UpdateProperty( } } - if (finalizeBorderRadius && control.try_as()) { + if (finalizeBorderRadius && control.try_as()) { // Control.CornerRadius is only supported on >= RS5, setting borderRadius on Controls have no effect < RS5 UpdateCornerRadiusOnElement(nodeToUpdate, control); } @@ -85,7 +85,7 @@ bool ControlViewManager::UpdateProperty( void ControlViewManager::OnViewCreated(XamlView view) { // Set the default cornerRadius to 0 for Control: WinUI usually default cornerRadius to 2 // Only works on >= RS5 becuase Control.CornerRadius is only supported >= RS5 - if (auto control = view.try_as()) { + if (auto control = view.try_as()) { control.CornerRadius({0}); } } diff --git a/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp b/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp index 495759e25d2..b5170f9228e 100644 --- a/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp +++ b/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp @@ -15,6 +15,7 @@ using namespace Windows::Foundation; using namespace Windows::UI; using namespace xaml; using namespace xaml::Interop; +using namespace winrt::Windows::UI::Xaml::Interop; } // namespace winrt namespace winrt::PROJECT_ROOT_NAMESPACE::implementation { diff --git a/vnext/ReactUWP/Views/FlyoutViewManager.cpp b/vnext/ReactUWP/Views/FlyoutViewManager.cpp index 0f1f1c7560a..b2d0b6d697a 100644 --- a/vnext/ReactUWP/Views/FlyoutViewManager.cpp +++ b/vnext/ReactUWP/Views/FlyoutViewManager.cpp @@ -16,6 +16,7 @@ namespace winrt { using namespace xaml::Controls; using namespace xaml::Controls::Primitives; using namespace xaml::Interop; +using namespace winrt::Windows::UI::Xaml::Interop; } // namespace winrt static const std::unordered_map placementModeMinVersion = { diff --git a/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp b/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp index 0e9802f7c43..9792ac582fa 100644 --- a/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp +++ b/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp @@ -21,6 +21,7 @@ #include "DynamicAutomationProperties.h" #include +#include "cdebug.h" namespace winrt { using namespace xaml; @@ -199,6 +200,8 @@ bool FrameworkElementViewManager::UpdateProperty( } else if (propertyValue.isNull()) { element.TransformMatrix(winrt::Windows::Foundation::Numerics::float4x4::identity()); } + } else { + cdebug << "[Dim down] " << propertyName << std::endl; } } else if (propertyName == "width") { if (propertyValue.isNumber()) { diff --git a/vnext/ReactUWP/Views/Image/BorderEffect.h b/vnext/ReactUWP/Views/Image/BorderEffect.h index 9a56525f07a..9a2598611db 100644 --- a/vnext/ReactUWP/Views/Image/BorderEffect.h +++ b/vnext/ReactUWP/Views/Image/BorderEffect.h @@ -1,10 +1,21 @@ #pragma once +#ifndef USE_WINUI3 #include +#define BORDEREFFECT_NAMESPACE winrt::Microsoft::UI::Composition::Effects +#else +#define BORDEREFFECT_NAMESPACE winrt::Microsoft::ReactNative +#include +#endif + +#pragma warning(push) +#pragma warning(disable : 28285 28196 6387 6319 26812) + #include "Microsoft.UI.Composition.Effects_Impl.h" -namespace winrt::Microsoft::UI::Composition::Effects::implementation { -class BorderEffect : public BorderEffectT { +namespace BORDEREFFECT_NAMESPACE::implementation { +class BorderEffect + : public BorderEffectT { public: DECLARE_D2D_GUID(CLSID_D2D1Border); DECLARE_SINGLE_SOURCE(Source); @@ -33,4 +44,6 @@ class BorderEffect : public BorderEffectT { }); } }; -} // namespace winrt::Microsoft::UI::Composition::Effects::implementation +} // namespace BORDEREFFECT_NAMESPACE::implementation + +#pragma warning(pop) diff --git a/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp b/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp index 61f1263ca81..2876e8749cb 100644 --- a/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp +++ b/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp @@ -7,6 +7,8 @@ #include +#include +#include #include "BorderEffect.h" namespace winrt { @@ -14,6 +16,7 @@ using namespace winrt::Windows::Storage::Streams; using namespace comp; using namespace xaml; using namespace xaml::Media; +using namespace comp::Effects; } // namespace winrt namespace react { @@ -152,7 +155,8 @@ comp::CompositionSurfaceBrush ReactImageBrush::GetOrCreateSurfaceBrush() { comp::CompositionEffectBrush ReactImageBrush::GetOrCreateEffectBrush( comp::CompositionSurfaceBrush const &surfaceBrush) { if (!m_effectBrush) { - auto borderEffect{winrt::make()}; + auto borderEffect{winrt::make()}; + borderEffect.ExtendX(winrt::CanvasEdgeBehavior::Wrap); borderEffect.ExtendY(winrt::CanvasEdgeBehavior::Wrap); diff --git a/vnext/ReactUWP/Views/Image/ReactImageBrush.h b/vnext/ReactUWP/Views/Image/ReactImageBrush.h index 8f93b1c5620..86cd626d564 100644 --- a/vnext/ReactUWP/Views/Image/ReactImageBrush.h +++ b/vnext/ReactUWP/Views/Image/ReactImageBrush.h @@ -4,6 +4,7 @@ #pragma once #include +#include "CppWinRTIncludes.h" namespace react { namespace uwp { diff --git a/vnext/ReactUWP/Views/PickerViewManager.cpp b/vnext/ReactUWP/Views/PickerViewManager.cpp index 58d3c56a604..ffa863aebfc 100644 --- a/vnext/ReactUWP/Views/PickerViewManager.cpp +++ b/vnext/ReactUWP/Views/PickerViewManager.cpp @@ -3,11 +3,11 @@ #include "pch.h" +#include #include #include "PickerViewManager.h" - -#include #include "Unicode.h" +#include "XamlFeatures.h" #include @@ -38,15 +38,26 @@ class PickerShadowNode : public ShadowNodeBase { int32_t m_selectedIndex = -1; // FUTURE: remove when we can require RS5+ - bool m_isEditableComboboxSupported; + static react::uwp::TriBit s_isEditableComboboxSupported; xaml::Controls::ComboBox::SelectionChanged_revoker m_comboBoxSelectionChangedRevoker{}; xaml::Controls::ComboBox::DropDownClosed_revoker m_comboBoxDropDownClosedRevoker{}; }; +react::uwp::TriBit PickerShadowNode::s_isEditableComboboxSupported = react::uwp::TriBit::Undefined; + PickerShadowNode::PickerShadowNode() : Super() { - m_isEditableComboboxSupported = winrt::Windows::Foundation::Metadata::ApiInformation::IsPropertyPresent( - XAML_NAMESPACE_STR L".Controls.ComboBox", L"IsEditableProperty"); + if (s_isEditableComboboxSupported == react::uwp::TriBit::Undefined) { + s_isEditableComboboxSupported = +#ifndef USE_WINUI3 + winrt::Windows::Foundation::Metadata::ApiInformation::IsPropertyPresent( + XAML_NAMESPACE_STR L".Controls.ComboBox", L"IsEditableProperty") + ? react::uwp::TriBit::Set + : react::uwp::TriBit::NotSet; +#else + react::uwp::TriBit::Set; +#endif + } } void PickerShadowNode::createView() { @@ -65,7 +76,7 @@ void PickerShadowNode::createView() { if (index >= 0 && index < static_cast(m_items.size())) value = m_items.at(index)["value"]; folly::dynamic text; - if (m_isEditableComboboxSupported && index == -1) + if (s_isEditableComboboxSupported == react::uwp::TriBit::Set && index == -1) text = HstringToDynamic(combobox.Text()); OnSelectionChanged(*instance, m_tag, std::move(value), index, std::move(text)); } @@ -89,14 +100,14 @@ void PickerShadowNode::updateProperties(const folly::dynamic &&props) { const folly::dynamic &propertyValue = pair.second; if (propertyName == "editable") { - if (m_isEditableComboboxSupported) { + if (s_isEditableComboboxSupported == react::uwp::TriBit::Set) { if (propertyValue.isBool()) combobox.IsEditable(propertyValue.asBool()); else if (propertyValue.isNull()) combobox.ClearValue(xaml::Controls::ComboBox::IsEditableProperty()); } } else if (propertyName == "text") { - if (m_isEditableComboboxSupported) { + if (s_isEditableComboboxSupported == react::uwp::TriBit::Set) { if (propertyValue.isString()) combobox.Text(asHstring(propertyValue)); else if (propertyValue.isNull()) diff --git a/vnext/ReactUWP/Views/TextInputViewManager.cpp b/vnext/ReactUWP/Views/TextInputViewManager.cpp index 51a9c826f02..d3b6cc22697 100644 --- a/vnext/ReactUWP/Views/TextInputViewManager.cpp +++ b/vnext/ReactUWP/Views/TextInputViewManager.cpp @@ -365,7 +365,7 @@ void TextInputShadowNode::HideCaretIfNeeded() { auto control = GetView().as(); if (auto caret = FindCaret(control)) { caret.CompositeMode(xaml::Media::ElementCompositeMode::Inherit); - xaml::Media::SolidColorBrush transparentColor(winrt::Windows::UI::Colors::Transparent()); + xaml::Media::SolidColorBrush transparentColor(winrt::Colors::Transparent()); caret.Fill(transparentColor); } } diff --git a/vnext/ReactUWP/Views/ViewPanel.cpp b/vnext/ReactUWP/Views/ViewPanel.cpp index ea8db61a316..c24a5e396c2 100644 --- a/vnext/ReactUWP/Views/ViewPanel.cpp +++ b/vnext/ReactUWP/Views/ViewPanel.cpp @@ -19,6 +19,7 @@ using namespace xaml; using namespace xaml::Automation::Peers; using namespace xaml::Controls; using namespace xaml::Interop; +using namespace winrt::Windows::UI::Xaml::Interop; using namespace xaml::Media; using namespace Windows::Foundation; } // namespace winrt diff --git a/vnext/ReactUWP/Views/cppwinrt/BorderEffect.idl b/vnext/ReactUWP/Views/cppwinrt/BorderEffect.idl index 62859deeae4..eb293f85c17 100644 --- a/vnext/ReactUWP/Views/cppwinrt/BorderEffect.idl +++ b/vnext/ReactUWP/Views/cppwinrt/BorderEffect.idl @@ -5,9 +5,15 @@ // // If you modify this file, be sure to run buildcppwinrt.cmd in this folder // to generate new headers +#include "NamespaceRedirect.h" +#ifndef USE_WINUI3 namespace Microsoft.UI.Composition.Effects +#else +namespace Microsoft.ReactNative +#endif { +#ifndef USE_WINUI3 [version(1)] typedef enum CanvasEdgeBehavior { @@ -15,11 +21,16 @@ namespace Microsoft.UI.Composition.Effects Wrap = (int)1, Mirror = (int)2 } CanvasEdgeBehavior; +#endif runtimeclass BorderEffect; [version(1)] +#ifndef USE_WINUI3 [uuid(31602441-15db-5b4a-98dd-ba4247548b40), exclusiveto(BorderEffect)] +#else + [uuid(d21ed48b-9d10-40d1-a6f6-e6bfca14a050), exclusiveto(BorderEffect)] +#endif interface IBorderEffect : IInspectable { [propget] HRESULT ExtendX([out, retval] Microsoft.UI.Composition.Effects.CanvasEdgeBehavior* value); diff --git a/vnext/ReactUWP/Views/cppwinrt/DynamicAutomationPeer.idl b/vnext/ReactUWP/Views/cppwinrt/DynamicAutomationPeer.idl index 69b5b3c5538..b12f9e06d77 100644 --- a/vnext/ReactUWP/Views/cppwinrt/DynamicAutomationPeer.idl +++ b/vnext/ReactUWP/Views/cppwinrt/DynamicAutomationPeer.idl @@ -9,7 +9,7 @@ #define VERSION 1.0 import "AccessibilityAction.idl"; -#include "../../../include/NamespaceRedirect.h" +#include "NamespaceRedirect.h" // The DynamicAutomationProperties must be in the project namespace to be // usable by Xaml dependency properties. diff --git a/vnext/ReactUWP/Views/cppwinrt/ViewPanel.idl b/vnext/ReactUWP/Views/cppwinrt/ViewPanel.idl index 1ad670ba1d4..d097fc22d00 100644 --- a/vnext/ReactUWP/Views/cppwinrt/ViewPanel.idl +++ b/vnext/ReactUWP/Views/cppwinrt/ViewPanel.idl @@ -8,7 +8,7 @@ import "DynamicAutomationPeer.idl"; -#include "../../../include/NamespaceRedirect.h" +#include "NamespaceRedirect.h" // The ViewPanel must be in the project namespace to be // usable by Xaml dependency properties. diff --git a/vnext/ReactUWP/packages.config b/vnext/ReactUWP/packages.config index ee35bcc7405..931bf233e88 100644 --- a/vnext/ReactUWP/packages.config +++ b/vnext/ReactUWP/packages.config @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/vnext/ReactWindows-Universal.sln b/vnext/ReactWindows-Universal.sln index 5b0b2509e19..f7e3cc07f31 100644 --- a/vnext/ReactWindows-Universal.sln +++ b/vnext/ReactWindows-Universal.sln @@ -107,18 +107,21 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Integ EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution + Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{069986c5-80f3-4a56-af79-f24ebb05941f}*SharedItemsImports = 4 JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{14fa0516-e6d7-4e4d-b097-1470198c5072}*SharedItemsImports = 4 Mso\Mso.vcxitems*{14fa0516-e6d7-4e4d-b097-1470198c5072}*SharedItemsImports = 4 Mso\Mso.vcxitems*{1958ceaa-fbe0-44e3-8a99-90ad85531ffe}*SharedItemsImports = 4 Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 Chakra\Chakra.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 + Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 Mso\Mso.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 Shared\Shared.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{46d76f7a-8fd9-4a7d-8102-2857e5da6b84}*SharedItemsImports = 4 Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{67a1076f-7790-4203-86ea-4402ccb5e782}*SharedItemsImports = 13 Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{6c60e295-c8ca-4dc5-b8be-09888f58b249}*SharedItemsImports = 4 Mso\Mso.vcxitems*{6c60e295-c8ca-4dc5-b8be-09888f58b249}*SharedItemsImports = 4 + Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{6f713ca6-6bfe-4df8-932d-4e49745c967e}*SharedItemsImports = 4 Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9 JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4 Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9 diff --git a/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj b/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj index c428d90da22..d861e40d112 100644 --- a/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj +++ b/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj @@ -41,6 +41,22 @@ Release Win32 + + WinUI3 + ARM + + + WinUI3 + ARM64 + + + WinUI3 + Win32 + + + WinUI3 + x64 + diff --git a/vnext/Universal.IntegrationTests/React.Windows.Universal.IntegrationTests.vcxproj b/vnext/Universal.IntegrationTests/React.Windows.Universal.IntegrationTests.vcxproj index 47ab85a5f78..bb1b046560c 100644 --- a/vnext/Universal.IntegrationTests/React.Windows.Universal.IntegrationTests.vcxproj +++ b/vnext/Universal.IntegrationTests/React.Windows.Universal.IntegrationTests.vcxproj @@ -9,6 +9,7 @@ NativeUnitTestProject 10.0 true + false @@ -36,6 +37,9 @@ + + + @@ -57,7 +61,7 @@ $(ReactNativeWindowsDir)target\$(PlatformTarget)\$(Configuration)\ReactUWP\React.uwp.lib;%(AdditionalDependencies) - + MainPage.xaml diff --git a/vnext/Universal.UnitTests/React.Windows.Universal.UnitTests.vcxproj b/vnext/Universal.UnitTests/React.Windows.Universal.UnitTests.vcxproj index d8ec53c802a..51e9f3f11bd 100644 --- a/vnext/Universal.UnitTests/React.Windows.Universal.UnitTests.vcxproj +++ b/vnext/Universal.UnitTests/React.Windows.Universal.UnitTests.vcxproj @@ -8,6 +8,7 @@ 15.0 NativeUnitTestProject 10.0 + false @@ -35,6 +36,9 @@ + + + diff --git a/vnext/include/ReactUWP/Utils/PropertyUtils.h b/vnext/include/ReactUWP/Utils/PropertyUtils.h index cd6d629ff2e..3a8024c6092 100644 --- a/vnext/include/ReactUWP/Utils/PropertyUtils.h +++ b/vnext/include/ReactUWP/Utils/PropertyUtils.h @@ -380,8 +380,13 @@ bool TryUpdateTextDecorationLine( const folly::dynamic &propertyValue) { if (propertyName == "textDecorationLine") { // FUTURE: remove when SDK target minVer >= 10.0.15063.0 - static bool isTextDecorationsSupported = winrt::Windows::Foundation::Metadata::ApiInformation::IsPropertyPresent( - XAML_NAMESPACE_STR L".Controls.TextBlock", L"TextDecorations"); + static bool isTextDecorationsSupported = +#ifndef USE_WINUI3 + winrt::Windows::Foundation::Metadata::ApiInformation::IsPropertyPresent( + XAML_NAMESPACE_STR L".Controls.TextBlock", L"TextDecorations"); +#else + true; +#endif if (!isTextDecorationsSupported) return true; From a20e950879c75f3dcd87be2624bbdb79664061cc Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Tue, 5 May 2020 11:26:39 -0700 Subject: [PATCH 049/209] Treat yes the same as y in template overwrite prompt (#4788) * Treat yes the same as y in template overwrite prompt * Change files --- ...-native-windows-2020-05-05-08-23-01-promptyes.json | 8 ++++++++ vnext/local-cli/generator-common/index.js | 11 +++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 change/react-native-windows-2020-05-05-08-23-01-promptyes.json diff --git a/change/react-native-windows-2020-05-05-08-23-01-promptyes.json b/change/react-native-windows-2020-05-05-08-23-01-promptyes.json new file mode 100644 index 00000000000..2ddd54e3763 --- /dev/null +++ b/change/react-native-windows-2020-05-05-08-23-01-promptyes.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Treat yes the same as y in template overwrite prompt", + "packageName": "react-native-windows", + "email": "acoates@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-05T15:23:01.596Z" +} diff --git a/vnext/local-cli/generator-common/index.js b/vnext/local-cli/generator-common/index.js index 1349e42e2d2..87242892ce0 100644 --- a/vnext/local-cli/generator-common/index.js +++ b/vnext/local-cli/generator-common/index.js @@ -76,14 +76,17 @@ function upgradeFileContentChangedCallback( console.log( `${chalk.bold(relativeDestPath)} ` + `has changed in the new version.\nDo you want to keep your ${relativeDestPath} or replace it with the ` + - 'latest version?\nIf you ever made any changes ' + - 'to this file, you\'ll probably want to keep it.\n' + + 'latest version?\nMake sure you have any changes you made to this file saved somewhere.\n' + `You can see the new version here: ${absoluteSrcFilePath}\n` + `Do you want to replace ${relativeDestPath}? ` + 'Answer y to replace, n to keep your version: ' ); - const answer = prompt(); - if (answer === 'y') { + let answer; + while (!answer) { + answer = prompt(); + } + + if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') { console.log(`Replacing ${relativeDestPath}`); return 'overwrite'; } From 9bce53ea8849bc462817cc09910266c0183b2cc8 Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Tue, 5 May 2020 13:55:41 -0700 Subject: [PATCH 050/209] Support --version file: for running init against local changes (#4794) * Support --version file: for running init against local changes * Change files --- ...react-native-windows-init-2020-05-05-12-50-32-cli.json | 8 ++++++++ packages/react-native-windows-init/src/Cli.ts | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 change/react-native-windows-init-2020-05-05-12-50-32-cli.json diff --git a/change/react-native-windows-init-2020-05-05-12-50-32-cli.json b/change/react-native-windows-init-2020-05-05-12-50-32-cli.json new file mode 100644 index 00000000000..e6056813e61 --- /dev/null +++ b/change/react-native-windows-init-2020-05-05-12-50-32-cli.json @@ -0,0 +1,8 @@ +{ + "type": "patch", + "comment": "Support --version file: for running init against local changes", + "packageName": "react-native-windows-init", + "email": "acoates@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-05T19:50:32.625Z" +} diff --git a/packages/react-native-windows-init/src/Cli.ts b/packages/react-native-windows-init/src/Cli.ts index 512a797113a..c6bb52dc523 100644 --- a/packages/react-native-windows-init/src/Cli.ts +++ b/packages/react-native-windows-init/src/Cli.ts @@ -49,7 +49,6 @@ const argv = yargs.version(false).options({ }, }).argv; -const EXITCODE_NO_MATCHING_RNW = 2; const EXITCODE_UNSUPPORTED_VERION_RN = 3; const EXITCODE_USER_CANCEL = 4; const EXITCODE_NO_REACTNATIVE_FOUND = 5; @@ -254,10 +253,11 @@ function isProjectUsingYarn(cwd: string) { if (!rnwResolvedVersion) { if (argv.version) { - console.error( - `Error: No version of react-native-windows@${argv.version} found`, + console.warn( + `Warning: Querying npm to find react-native-windows@${ + argv.version + } failed. Attempting to continue anyway...`, ); - process.exit(EXITCODE_NO_MATCHING_RNW); } else { const rnwLatestVersion = await getLatestRNWVersion(); console.error( From 9c825674683bed63dfb5502c43df8f5554365ff1 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Wed, 6 May 2020 00:05:03 +0000 Subject: [PATCH 051/209] applying package updates ***NO_CI*** --- ...tive-windows-2020-05-01-22-10-52-dual.json | 8 ------- ...windows-2020-05-05-08-23-01-promptyes.json | 8 ------- ...-windows-init-2020-05-05-12-50-32-cli.json | 8 ------- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- .../react-native-windows-init/CHANGELOG.json | 15 +++++++++++++ .../react-native-windows-init/CHANGELOG.md | 10 ++++++++- .../react-native-windows-init/package.json | 2 +- vnext/CHANGELOG.json | 21 +++++++++++++++++++ vnext/CHANGELOG.md | 11 +++++++++- vnext/package.json | 2 +- 12 files changed, 60 insertions(+), 31 deletions(-) delete mode 100644 change/react-native-windows-2020-05-01-22-10-52-dual.json delete mode 100644 change/react-native-windows-2020-05-05-08-23-01-promptyes.json delete mode 100644 change/react-native-windows-init-2020-05-05-12-50-32-cli.json diff --git a/change/react-native-windows-2020-05-01-22-10-52-dual.json b/change/react-native-windows-2020-05-01-22-10-52-dual.json deleted file mode 100644 index 86e0ba60fd5..00000000000 --- a/change/react-native-windows-2020-05-01-22-10-52-dual.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "WinUI 3 Alpha support in RNW", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-02T05:10:51.951Z" -} diff --git a/change/react-native-windows-2020-05-05-08-23-01-promptyes.json b/change/react-native-windows-2020-05-05-08-23-01-promptyes.json deleted file mode 100644 index 2ddd54e3763..00000000000 --- a/change/react-native-windows-2020-05-05-08-23-01-promptyes.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Treat yes the same as y in template overwrite prompt", - "packageName": "react-native-windows", - "email": "acoates@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-05T15:23:01.596Z" -} diff --git a/change/react-native-windows-init-2020-05-05-12-50-32-cli.json b/change/react-native-windows-init-2020-05-05-12-50-32-cli.json deleted file mode 100644 index e6056813e61..00000000000 --- a/change/react-native-windows-init-2020-05-05-12-50-32-cli.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "patch", - "comment": "Support --version file: for running init against local changes", - "packageName": "react-native-windows-init", - "email": "acoates@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-05T19:50:32.625Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index 52a5cacfd3d..5c70b885191 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.58" + "react-native-windows": "0.0.0-master.59" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index dca8a586354..a8cb2c0d13f 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.58" + "react-native-windows": "0.0.0-master.59" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index d8e2f7a8fae..1481d224c32 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.58" + "react-native-windows": "0.0.0-master.59" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/react-native-windows-init/CHANGELOG.json b/packages/react-native-windows-init/CHANGELOG.json index 779d63823f0..348ade66582 100644 --- a/packages/react-native-windows-init/CHANGELOG.json +++ b/packages/react-native-windows-init/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "react-native-windows-init", "entries": [ + { + "date": "Wed, 06 May 2020 00:05:03 GMT", + "tag": "react-native-windows-init_v0.1.6", + "version": "0.1.6", + "comments": { + "patch": [ + { + "comment": "Support --version file: for running init against local changes", + "author": "acoates@microsoft.com", + "commit": "9bce53ea8849bc462817cc09910266c0183b2cc8", + "package": "react-native-windows-init" + } + ] + } + }, { "date": "Wed, 22 Apr 2020 00:04:29 GMT", "tag": "react-native-windows-init_v0.1.5", diff --git a/packages/react-native-windows-init/CHANGELOG.md b/packages/react-native-windows-init/CHANGELOG.md index 4858be37ae3..88e41cbbd3c 100644 --- a/packages/react-native-windows-init/CHANGELOG.md +++ b/packages/react-native-windows-init/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - react-native-windows-init -This log was last generated on Wed, 22 Apr 2020 00:04:29 GMT and should not be manually modified. +This log was last generated on Wed, 06 May 2020 00:05:03 GMT and should not be manually modified. +## 0.1.6 + +Wed, 06 May 2020 00:05:03 GMT + +### Patches + +- Support --version file: for running init against local changes (acoates@microsoft.com) + ## 0.1.5 Wed, 22 Apr 2020 00:04:29 GMT diff --git a/packages/react-native-windows-init/package.json b/packages/react-native-windows-init/package.json index 362c27f21be..4d79b0c4252 100644 --- a/packages/react-native-windows-init/package.json +++ b/packages/react-native-windows-init/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows-init", - "version": "0.1.5", + "version": "0.1.6", "description": "CLI to add react-native-windows to an existing react-native project", "main": "index.js", "repository": "https://github.com/microsoft/react-native-windows", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index 57530e1476d..007414b864b 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,27 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Wed, 06 May 2020 00:05:03 GMT", + "tag": "react-native-windows_v0.0.0-master.59", + "version": "0.0.0-master.59", + "comments": { + "prerelease": [ + { + "comment": "WinUI 3 Alpha support in RNW", + "author": "asklar@microsoft.com", + "commit": "f467d8b06d481b6e36a7cd239608594017f4ebbf", + "package": "react-native-windows" + }, + { + "comment": "Treat yes the same as y in template overwrite prompt", + "author": "acoates@microsoft.com", + "commit": "a20e950879c75f3dcd87be2624bbdb79664061cc", + "package": "react-native-windows" + } + ] + } + }, { "date": "Tue, 05 May 2020 00:04:31 GMT", "tag": "react-native-windows_v0.0.0-master.58", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 2ed4bbe1418..2e07c4f7b9a 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,18 @@ # Change Log - react-native-windows -This log was last generated on Tue, 05 May 2020 00:04:31 GMT and should not be manually modified. +This log was last generated on Wed, 06 May 2020 00:05:03 GMT and should not be manually modified. +## 0.0.0-master.59 + +Wed, 06 May 2020 00:05:03 GMT + +### Changes + +- WinUI 3 Alpha support in RNW (asklar@microsoft.com) +- Treat yes the same as y in template overwrite prompt (acoates@microsoft.com) + ## 0.0.0-master.58 Tue, 05 May 2020 00:04:31 GMT diff --git a/vnext/package.json b/vnext/package.json index 5fab018ee78..3c7bbbc95ad 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.58", + "version": "0.0.0-master.59", "license": "MIT", "repository": { "type": "git", From 67781f6f00498216349c33716d451525e59229ca Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Tue, 5 May 2020 18:37:36 -0700 Subject: [PATCH 052/209] Don't delete nuget.exe if using locally-installed (e.g. chocolatey) (#4798) * Don't delete nuget.exe if using locally-installed (e.g. chocolatey) * Change files --- ...dows-2020-05-05-17-17-21-dontDeleteInstalledNuget.json | 8 ++++++++ vnext/local-cli/runWindows/utils/build.js | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 change/react-native-windows-2020-05-05-17-17-21-dontDeleteInstalledNuget.json diff --git a/change/react-native-windows-2020-05-05-17-17-21-dontDeleteInstalledNuget.json b/change/react-native-windows-2020-05-05-17-17-21-dontDeleteInstalledNuget.json new file mode 100644 index 00000000000..3951ee2aea7 --- /dev/null +++ b/change/react-native-windows-2020-05-05-17-17-21-dontDeleteInstalledNuget.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Don't delete nuget.exe if using locally-installed (e.g. chocolatey)", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-06T00:17:21.228Z" +} diff --git a/vnext/local-cli/runWindows/utils/build.js b/vnext/local-cli/runWindows/utils/build.js index 991fe8ab046..9dfe59c1703 100644 --- a/vnext/local-cli/runWindows/utils/build.js +++ b/vnext/local-cli/runWindows/utils/build.js @@ -68,6 +68,7 @@ async function restoreNuGetPackages(options, slnFile, verbose) { let nugetPath = options.nugetPath || path.join(os.tmpdir(), 'nuget.4.9.2.exe'); + let downloadedNuget = false; const ensureNugetSpinner = newSpinner('Locating NuGet executable'); if (!(await existsAsync(nugetPath))) { try { @@ -87,6 +88,7 @@ async function restoreNuGetPackages(options, slnFile, verbose) { ), verbose, ); + downloadedNuget = true; } ensureNugetSpinner.succeed('Found NuGet Binary'); @@ -105,7 +107,9 @@ async function restoreNuGetPackages(options, slnFile, verbose) { } catch (e) { if (!options.isRetryingNuget) { const retryOptions = Object.assign({isRetryingNuget: true}, options); - fs.unlinkSync(nugetPath); + if (downloadedNuget) { + fs.unlinkSync(nugetPath); + } return restoreNuGetPackages(retryOptions, slnFile, verbose); } throw e; From 6398c2dc10d8c7093b3c6b108b5c541f067389b8 Mon Sep 17 00:00:00 2001 From: Brian Zhao Date: Tue, 5 May 2020 19:48:33 -0700 Subject: [PATCH 053/209] Fix @office-iss/react-native-win32 sourcemap (#4797) Use inlineSourceMap and inlineSources to encode original TS into sourcemap --- ...-native-win32-2020-05-05-16-57-21-win32-sourcemap.json | 8 ++++++++ packages/react-native-win32/tsconfig.json | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 change/@office-iss-react-native-win32-2020-05-05-16-57-21-win32-sourcemap.json diff --git a/change/@office-iss-react-native-win32-2020-05-05-16-57-21-win32-sourcemap.json b/change/@office-iss-react-native-win32-2020-05-05-16-57-21-win32-sourcemap.json new file mode 100644 index 00000000000..27c5e387a44 --- /dev/null +++ b/change/@office-iss-react-native-win32-2020-05-05-16-57-21-win32-sourcemap.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Use inlineSourceMap and inlineSources to encode original TS into sourcemap", + "packageName": "@office-iss/react-native-win32", + "email": "rezha@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-05T23:57:21.665Z" +} diff --git a/packages/react-native-win32/tsconfig.json b/packages/react-native-win32/tsconfig.json index 20350dfccbe..99bd2741818 100644 --- a/packages/react-native-win32/tsconfig.json +++ b/packages/react-native-win32/tsconfig.json @@ -6,7 +6,8 @@ "jsx": "react", "outDir": ".", "declaration": true, - "sourceMap": true, + "inlineSourceMap": true, + "inlineSources": true, "experimentalDecorators": true, "noEmitOnError": true, "skipLibCheck": true, From 76b3478cb83004b5b6718af0381e8a3856ef893d Mon Sep 17 00:00:00 2001 From: Brian Zhao Date: Wed, 6 May 2020 00:34:47 -0700 Subject: [PATCH 054/209] [Trivial] Fix typo in msbuildtools.js (#4803) * Fix typo * Change files --- .../react-native-windows-2020-05-05-22-41-31-msbuilt.json | 8 ++++++++ vnext/local-cli/runWindows/utils/msbuildtools.js | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 change/react-native-windows-2020-05-05-22-41-31-msbuilt.json diff --git a/change/react-native-windows-2020-05-05-22-41-31-msbuilt.json b/change/react-native-windows-2020-05-05-22-41-31-msbuilt.json new file mode 100644 index 00000000000..4e4ea0df790 --- /dev/null +++ b/change/react-native-windows-2020-05-05-22-41-31-msbuilt.json @@ -0,0 +1,8 @@ +{ + "type": "none", + "comment": "Fix typo", + "packageName": "react-native-windows", + "email": "rezha@microsoft.com", + "dependentChangeType": "none", + "date": "2020-05-06T05:41:31.008Z" +} diff --git a/vnext/local-cli/runWindows/utils/msbuildtools.js b/vnext/local-cli/runWindows/utils/msbuildtools.js index eec72655537..885db3d7a5e 100644 --- a/vnext/local-cli/runWindows/utils/msbuildtools.js +++ b/vnext/local-cli/runWindows/utils/msbuildtools.js @@ -216,7 +216,7 @@ function checkMSBuildVersion(version, buildArch, verbose) { ); if (verbose) { - console.log('Looking for MSBuilt at: ' + msBuildPath); + console.log('Looking for MSBuild at: ' + msBuildPath); } toolsPath = fs.existsSync(msBuildPath) ? path.dirname(msBuildPath) : null; From 80cef10818276ec17ad9683df1a9523b2b486fd0 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 6 May 2020 06:32:47 -0700 Subject: [PATCH 055/209] Disable CxxFrameHandler4 (#4805) * Disable CxxFrameHandler4 V142 Build tools turn on FH4 (CxxFrameHandler4) by default. This reduces the size of EH maps, but leads to incompatibility with code compiled using older toolsets. Disable FH4 until consumers (i.e. Office) are on an ABI-safe API or are updated. Microsoft.ReactNative.dll x64 Release Size: Before: 2,139 KB After: 2,294 KB * Change files --- ...t-native-windows-2020-05-06-05-03-56-no-fh4.json | 8 ++++++++ vnext/PropertySheets/React.Cpp.props | 13 +++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 change/react-native-windows-2020-05-06-05-03-56-no-fh4.json diff --git a/change/react-native-windows-2020-05-06-05-03-56-no-fh4.json b/change/react-native-windows-2020-05-06-05-03-56-no-fh4.json new file mode 100644 index 00000000000..fd0e19ceca1 --- /dev/null +++ b/change/react-native-windows-2020-05-06-05-03-56-no-fh4.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Disable CxxFrameHandler4", + "packageName": "react-native-windows", + "email": "ngerlem@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-06T12:03:56.512Z" +} diff --git a/vnext/PropertySheets/React.Cpp.props b/vnext/PropertySheets/React.Cpp.props index ee1740d4e35..264a9a37c7c 100644 --- a/vnext/PropertySheets/React.Cpp.props +++ b/vnext/PropertySheets/React.Cpp.props @@ -103,6 +103,19 @@ + + + + /d2FH4- %(AdditionalOptions) + + + /d2:-FH4- %(AdditionalOptions) + + + Console From c18e0c17fa6c2a2f778aa6607fb7e1601f6089da Mon Sep 17 00:00:00 2001 From: dannyvv Date: Wed, 6 May 2020 11:46:02 -0700 Subject: [PATCH 056/209] Switch package layout to use `files` in `package.json` rather than `.npmignore` (#4796) * Switch package layout to use `files` in `pacakge.json` rather than `.npmignore` The `files` field in `package.json` is an inclusive model. Which means you have to be explicit to opt in to shipping certain files. Rather than the `.npmignore` uses an exclusive model, where everything ships by default unless it is this risks shipping too much by accident. Testing will cover the case if you missed something as your new change won't work. * Change files * Remove some files and folders from the shipped package per PR-comments --- ...ve-windows-2020-05-05-14-51-37-master.json | 8 ++++ vnext/.npmignore | 43 +---------------- vnext/package.json | 48 ++++++++++++++++++- 3 files changed, 56 insertions(+), 43 deletions(-) create mode 100644 change/react-native-windows-2020-05-05-14-51-37-master.json diff --git a/change/react-native-windows-2020-05-05-14-51-37-master.json b/change/react-native-windows-2020-05-05-14-51-37-master.json new file mode 100644 index 00000000000..34742b9debd --- /dev/null +++ b/change/react-native-windows-2020-05-05-14-51-37-master.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Switch package layout to use `files` in `pacakge.json` rather than `.npmignore`", + "packageName": "react-native-windows", + "email": "dannyvv@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-05T21:51:37.660Z" +} diff --git a/vnext/.npmignore b/vnext/.npmignore index 04b1d45695f..4398938564a 100644 --- a/vnext/.npmignore +++ b/vnext/.npmignore @@ -1,42 +1 @@ -.eslintignore -.eslintrc.js -.vs -.vscode -**/*.inc -**/*.windesktop.* -api-extractor.json -build -CMakeLists.txt -/Desktop -Desktop.Dll -Desktop.ABITests -Desktop.IntegrationTests -Desktop.Test.DLL -Desktop.UnitTests -FollyWin32 -IntegrationTests -IntegrationTestScripts -JSI.Desktop.UnitTests -/NuGet.Config -Microsoft.ReactNative.Cxx.UnitTests -Microsoft.ReactNative.IntegrationTests -Microsoft.ReactNative.Managed.UnitTests -package-deps.json -packages -react-native-windows.build.log -ReactCopies/ -ReactWindows-Universal.sln -ReactWindows-Desktop.sln -RNTester.* -RNTester/ -Mso.UnitTests -proposals -src/ -target -temp -tsconfig.json -Universal.IntegrationTests -Universal.UnitTests -win32 -WindowsSampleCSharpApp -yarn.lock +# This project follows an explicit 'include' pattern as defined in the `files` section of pacakge.json diff --git a/vnext/package.json b/vnext/package.json index 3c7bbbc95ad..03896b6eb42 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -69,5 +69,51 @@ "minor", "patch" ] - } + }, + "files": [ + "/codegen", + "/Chakra", + "/Common", + "/DeforkingPatches", + "/etc", + "/flow", + "/Folly", + "/include", + "/JSI", + "/Libraries", + "!/Libraries/**/*.windesktop.*", + "/local-cli", + "/Microsoft.ReactNative", + "/Microsoft.ReactNative.Cxx", + "/Microsoft.ReactNative.Managed", + "/Microsoft.ReactNative.SharedManaged", + "/Mso", + "/PropertySheets", + "/ReactCommon", + "/ReactUWP", + "/ReactWindowsCore", + "/Scripts", + "/Shared", + "/stubs", + + "/.flowconfig", + "/Directory.Build.props", + "/Directory.Build.targets", + "/index.js", + "/index.windows.d.ts", + "/index.windows.d.ts.map", + "/index.windows.js", + "/index.windows.js.map", + "/interface.js", + "/just-task.js", + "/layoutFilesForNuget.bat", + "/metro-react-native-platform.js", + "/metro.config.js", + "/react-native.config.js", + "/typings-index.d.ts", + "/typings-index.d.ts.map", + "/typings-index.js", + "/typings-index.js.map", + "/rn-get-polyfills.js" + ] } From 8940e5ee6ecce0fa1fc573d1cfa54be757bce431 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Wed, 6 May 2020 14:58:18 -0700 Subject: [PATCH 057/209] Don't bundle during intellisense (#4800) * Only bundle when not running Intellisense builds * Change files --- ...-2020-05-05-19-47-51-dontBundleDuringIntellisense.json | 8 ++++++++ vnext/PropertySheets/Bundle.Common.targets | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 change/react-native-windows-2020-05-05-19-47-51-dontBundleDuringIntellisense.json diff --git a/change/react-native-windows-2020-05-05-19-47-51-dontBundleDuringIntellisense.json b/change/react-native-windows-2020-05-05-19-47-51-dontBundleDuringIntellisense.json new file mode 100644 index 00000000000..6608ecfd99b --- /dev/null +++ b/change/react-native-windows-2020-05-05-19-47-51-dontBundleDuringIntellisense.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Only bundle when not running Intellisense builds", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-06T02:47:51.102Z" +} diff --git a/vnext/PropertySheets/Bundle.Common.targets b/vnext/PropertySheets/Bundle.Common.targets index c3f08007f8b..ae634bd4993 100644 --- a/vnext/PropertySheets/Bundle.Common.targets +++ b/vnext/PropertySheets/Bundle.Common.targets @@ -5,7 +5,7 @@ --> + Condition="'$(UseBundle)' == 'true' And ('$(BuildingInsideVisualStudio)'!='true' Or '$(BuildingProject)'=='true')"> From 2cb78b5a7c1e7528df4555c60d89a6481afa7832 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 6 May 2020 22:01:41 +0000 Subject: [PATCH 058/209] Bump @microsoft/api-documenter from 7.7.20 to 7.8.0 (#4808) --- yarn.lock | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 87f19fc8fda..e2a966a53b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2408,11 +2408,11 @@ write-file-atomic "^2.3.0" "@microsoft/api-documenter@^7.3.8": - version "7.7.20" - resolved "https://registry.yarnpkg.com/@microsoft/api-documenter/-/api-documenter-7.7.20.tgz#034fe4df720d62ebcc6af311168fdb0faf89da9c" - integrity sha512-B2gOOoYJDOqAn9iPg4Z9ay03MYtjmY2ldF3u1povTkzl5eJWERMDuuK5BLOdGdDTMr6TUd/FrhERFEeJNeQ3rg== + version "7.8.0" + resolved "https://registry.yarnpkg.com/@microsoft/api-documenter/-/api-documenter-7.8.0.tgz#92816329eb4286bf284b92e31bcbed05b8bd5195" + integrity sha512-PZuOlS+b5LfCUOQ2iI32dl9xFcXine4Yu9xrb1w3LCwqYUxWU3K/tbwTatleOVPVDD6ZrH5XaddnGPyng2SrmA== dependencies: - "@microsoft/api-extractor-model" "7.7.11" + "@microsoft/api-extractor-model" "7.8.0" "@microsoft/tsdoc" "0.12.19" "@rushstack/node-core-library" "3.19.7" "@rushstack/ts-command-line" "4.3.14" @@ -2428,6 +2428,14 @@ "@microsoft/tsdoc" "0.12.19" "@rushstack/node-core-library" "3.19.7" +"@microsoft/api-extractor-model@7.8.0": + version "7.8.0" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.8.0.tgz#5f532998f01109f23d57b422803bbdf5ad655d80" + integrity sha512-rk3n2GJ2DyKsmKmSK0VYN92ZAWPgc5+zBLbGASpty3pBZBuByJ0ioZdkxbtm5gaeurJzsG9DFTPCmpg/+Mt/nw== + dependencies: + "@microsoft/tsdoc" "0.12.19" + "@rushstack/node-core-library" "3.19.7" + "@microsoft/api-extractor@^7.3.8": version "7.7.13" resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.7.13.tgz#7ee70978825a36d294d26e50b5d888ca3789d1b0" From 608b98b46627d9c6a79bbe6a7f3f3ceb7aa8ff2a Mon Sep 17 00:00:00 2001 From: Andreas Eulitz <44379427+aeulitz@users.noreply.github.com> Date: Wed, 6 May 2020 15:45:56 -0700 Subject: [PATCH 059/209] Fix publish pipeline (#4815) * fix issue 4792 * Change files --- ...eact-native-windows-2020-05-06-14-46-56-Issue4792.json | 8 ++++++++ .../TestBundle.targets | 1 + 2 files changed, 9 insertions(+) create mode 100644 change/react-native-windows-2020-05-06-14-46-56-Issue4792.json diff --git a/change/react-native-windows-2020-05-06-14-46-56-Issue4792.json b/change/react-native-windows-2020-05-06-14-46-56-Issue4792.json new file mode 100644 index 00000000000..d87f94119c0 --- /dev/null +++ b/change/react-native-windows-2020-05-06-14-46-56-Issue4792.json @@ -0,0 +1,8 @@ +{ + "type": "none", + "comment": "fix issue 4792", + "packageName": "react-native-windows", + "email": "aeulitz@microsoft.com", + "dependentChangeType": "none", + "date": "2020-05-06T21:46:56.216Z" +} diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/TestBundle.targets b/vnext/Microsoft.ReactNative.IntegrationTests/TestBundle.targets index 284e1cd3af6..20507149e42 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/TestBundle.targets +++ b/vnext/Microsoft.ReactNative.IntegrationTests/TestBundle.targets @@ -5,6 +5,7 @@ BeforeTargets="PrepareForBuild" Inputs="@(JsBundleEntry)" Outputs="@(JsBundleEntry->'$(OutputPath)%(Filename).bundle')"> + From 02d40fb70f45b08e639bfbfd18a9c81732042d12 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 6 May 2020 15:55:47 -0700 Subject: [PATCH 060/209] Bump @microsoft/api-extractor from 7.7.13 to 7.8.0 (#4807) Bumps [@microsoft/api-extractor](https://github.com/microsoft/rushstack) from 7.7.13 to 7.8.0. - [Release notes](https://github.com/microsoft/rushstack/releases) - [Commits](https://github.com/microsoft/rushstack/compare/@microsoft/api-extractor_v7.7.13...@microsoft/api-extractor_v7.8.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/yarn.lock b/yarn.lock index e2a966a53b5..2c25ad6a8df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2420,14 +2420,6 @@ js-yaml "~3.13.1" resolve "1.8.1" -"@microsoft/api-extractor-model@7.7.11": - version "7.7.11" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.7.11.tgz#9dfc5425f4a6a2b6b1ebc39332ae8101ab8da36a" - integrity sha512-Kf3RytYDq7sP4ASaaA9IcvaOPbVj1Xj34E2Wxd9DznI7sG4HzcpoOGmxaZHCzyYVh7wfAaAlvcXf3SV+djhNZw== - dependencies: - "@microsoft/tsdoc" "0.12.19" - "@rushstack/node-core-library" "3.19.7" - "@microsoft/api-extractor-model@7.8.0": version "7.8.0" resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.8.0.tgz#5f532998f01109f23d57b422803bbdf5ad655d80" @@ -2437,11 +2429,11 @@ "@rushstack/node-core-library" "3.19.7" "@microsoft/api-extractor@^7.3.8": - version "7.7.13" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.7.13.tgz#7ee70978825a36d294d26e50b5d888ca3789d1b0" - integrity sha512-7+EGunGd7OSfDxZl4aDI4qMWG98+I84vTryNadti+IfgpB9IyhJtgA4r3dCG7hewTwKACBhi5aPqpH2C7l/30A== + version "7.8.0" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.8.0.tgz#fea68e4f21c1bf18020560fd5728b15fe44f0976" + integrity sha512-H9dI7dCw005XuGa1dPAdZLQWEUu+B4yiF2v7NZ3p70mKo2iAZcd9LwmDTZ5OFALsNiHnJk1I5JZjcsj8dtB73g== dependencies: - "@microsoft/api-extractor-model" "7.7.11" + "@microsoft/api-extractor-model" "7.8.0" "@microsoft/tsdoc" "0.12.19" "@rushstack/node-core-library" "3.19.7" "@rushstack/ts-command-line" "4.3.14" From b26c409d7314f074477a8acc5ed2acf6773fc6ba Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Thu, 7 May 2020 00:05:07 +0000 Subject: [PATCH 061/209] applying package updates ***NO_CI*** --- ...2-2020-05-05-16-57-21-win32-sourcemap.json | 8 ---- ...ve-windows-2020-05-05-14-51-37-master.json | 8 ---- ...-05-17-17-21-dontDeleteInstalledNuget.json | 8 ---- ...19-47-51-dontBundleDuringIntellisense.json | 8 ---- ...e-windows-2020-05-05-22-41-31-msbuilt.json | 8 ---- ...ve-windows-2020-05-06-05-03-56-no-fh4.json | 8 ---- ...windows-2020-05-06-14-46-56-Issue4792.json | 8 ---- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- packages/react-native-win32/CHANGELOG.json | 15 ++++++ packages/react-native-win32/CHANGELOG.md | 10 +++- packages/react-native-win32/package.json | 2 +- vnext/CHANGELOG.json | 47 +++++++++++++++++++ vnext/CHANGELOG.md | 13 ++++- vnext/package.json | 3 +- 16 files changed, 88 insertions(+), 64 deletions(-) delete mode 100644 change/@office-iss-react-native-win32-2020-05-05-16-57-21-win32-sourcemap.json delete mode 100644 change/react-native-windows-2020-05-05-14-51-37-master.json delete mode 100644 change/react-native-windows-2020-05-05-17-17-21-dontDeleteInstalledNuget.json delete mode 100644 change/react-native-windows-2020-05-05-19-47-51-dontBundleDuringIntellisense.json delete mode 100644 change/react-native-windows-2020-05-05-22-41-31-msbuilt.json delete mode 100644 change/react-native-windows-2020-05-06-05-03-56-no-fh4.json delete mode 100644 change/react-native-windows-2020-05-06-14-46-56-Issue4792.json diff --git a/change/@office-iss-react-native-win32-2020-05-05-16-57-21-win32-sourcemap.json b/change/@office-iss-react-native-win32-2020-05-05-16-57-21-win32-sourcemap.json deleted file mode 100644 index 27c5e387a44..00000000000 --- a/change/@office-iss-react-native-win32-2020-05-05-16-57-21-win32-sourcemap.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Use inlineSourceMap and inlineSources to encode original TS into sourcemap", - "packageName": "@office-iss/react-native-win32", - "email": "rezha@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-05T23:57:21.665Z" -} diff --git a/change/react-native-windows-2020-05-05-14-51-37-master.json b/change/react-native-windows-2020-05-05-14-51-37-master.json deleted file mode 100644 index 34742b9debd..00000000000 --- a/change/react-native-windows-2020-05-05-14-51-37-master.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Switch package layout to use `files` in `pacakge.json` rather than `.npmignore`", - "packageName": "react-native-windows", - "email": "dannyvv@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-05T21:51:37.660Z" -} diff --git a/change/react-native-windows-2020-05-05-17-17-21-dontDeleteInstalledNuget.json b/change/react-native-windows-2020-05-05-17-17-21-dontDeleteInstalledNuget.json deleted file mode 100644 index 3951ee2aea7..00000000000 --- a/change/react-native-windows-2020-05-05-17-17-21-dontDeleteInstalledNuget.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Don't delete nuget.exe if using locally-installed (e.g. chocolatey)", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-06T00:17:21.228Z" -} diff --git a/change/react-native-windows-2020-05-05-19-47-51-dontBundleDuringIntellisense.json b/change/react-native-windows-2020-05-05-19-47-51-dontBundleDuringIntellisense.json deleted file mode 100644 index 6608ecfd99b..00000000000 --- a/change/react-native-windows-2020-05-05-19-47-51-dontBundleDuringIntellisense.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Only bundle when not running Intellisense builds", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-06T02:47:51.102Z" -} diff --git a/change/react-native-windows-2020-05-05-22-41-31-msbuilt.json b/change/react-native-windows-2020-05-05-22-41-31-msbuilt.json deleted file mode 100644 index 4e4ea0df790..00000000000 --- a/change/react-native-windows-2020-05-05-22-41-31-msbuilt.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "none", - "comment": "Fix typo", - "packageName": "react-native-windows", - "email": "rezha@microsoft.com", - "dependentChangeType": "none", - "date": "2020-05-06T05:41:31.008Z" -} diff --git a/change/react-native-windows-2020-05-06-05-03-56-no-fh4.json b/change/react-native-windows-2020-05-06-05-03-56-no-fh4.json deleted file mode 100644 index fd0e19ceca1..00000000000 --- a/change/react-native-windows-2020-05-06-05-03-56-no-fh4.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Disable CxxFrameHandler4", - "packageName": "react-native-windows", - "email": "ngerlem@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-06T12:03:56.512Z" -} diff --git a/change/react-native-windows-2020-05-06-14-46-56-Issue4792.json b/change/react-native-windows-2020-05-06-14-46-56-Issue4792.json deleted file mode 100644 index d87f94119c0..00000000000 --- a/change/react-native-windows-2020-05-06-14-46-56-Issue4792.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "none", - "comment": "fix issue 4792", - "packageName": "react-native-windows", - "email": "aeulitz@microsoft.com", - "dependentChangeType": "none", - "date": "2020-05-06T21:46:56.216Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index 5c70b885191..f34f6988299 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.59" + "react-native-windows": "0.0.0-master.60" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index a8cb2c0d13f..04c85f7d310 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.59" + "react-native-windows": "0.0.0-master.60" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index 1481d224c32..6324967e105 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.59" + "react-native-windows": "0.0.0-master.60" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/react-native-win32/CHANGELOG.json b/packages/react-native-win32/CHANGELOG.json index 17f4bbc4265..899eac98310 100644 --- a/packages/react-native-win32/CHANGELOG.json +++ b/packages/react-native-win32/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@office-iss/react-native-win32", "entries": [ + { + "date": "Thu, 07 May 2020 00:05:07 GMT", + "tag": "@office-iss/react-native-win32_v0.0.0-master.8", + "version": "0.0.0-master.8", + "comments": { + "prerelease": [ + { + "comment": "Use inlineSourceMap and inlineSources to encode original TS into sourcemap", + "author": "rezha@microsoft.com", + "commit": "6398c2dc10d8c7093b3c6b108b5c541f067389b8", + "package": "@office-iss/react-native-win32" + } + ] + } + }, { "date": "Thu, 30 Apr 2020 18:40:40 GMT", "tag": "@office-iss/react-native-win32_v0.0.0-master.7", diff --git a/packages/react-native-win32/CHANGELOG.md b/packages/react-native-win32/CHANGELOG.md index 40992726e67..0a9d7ed5851 100644 --- a/packages/react-native-win32/CHANGELOG.md +++ b/packages/react-native-win32/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @office-iss/react-native-win32 -This log was last generated on Thu, 30 Apr 2020 18:40:40 GMT and should not be manually modified. +This log was last generated on Thu, 07 May 2020 00:05:07 GMT and should not be manually modified. +## 0.0.0-master.8 + +Thu, 07 May 2020 00:05:07 GMT + +### Changes + +- Use inlineSourceMap and inlineSources to encode original TS into sourcemap (rezha@microsoft.com) + ## 0.0.0-master.7 Thu, 30 Apr 2020 18:40:40 GMT diff --git a/packages/react-native-win32/package.json b/packages/react-native-win32/package.json index 02f68f70fff..fca31b52b77 100644 --- a/packages/react-native-win32/package.json +++ b/packages/react-native-win32/package.json @@ -1,6 +1,6 @@ { "name": "@office-iss/react-native-win32", - "version": "0.0.0-master.7", + "version": "0.0.0-master.8", "description": "Implementation of react native on top of Office's Win32 platform.", "license": "MIT", "main": "./index.win32.js", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index 007414b864b..fdaadb1c5f3 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,53 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Thu, 07 May 2020 00:05:07 GMT", + "tag": "react-native-windows_v0.0.0-master.60", + "version": "0.0.0-master.60", + "comments": { + "prerelease": [ + { + "comment": "Don't delete nuget.exe if using locally-installed (e.g. chocolatey)", + "author": "asklar@microsoft.com", + "commit": "67781f6f00498216349c33716d451525e59229ca", + "package": "react-native-windows" + }, + { + "comment": "Only bundle when not running Intellisense builds", + "author": "asklar@microsoft.com", + "commit": "8940e5ee6ecce0fa1fc573d1cfa54be757bce431", + "package": "react-native-windows" + }, + { + "comment": "Disable CxxFrameHandler4", + "author": "ngerlem@microsoft.com", + "commit": "80cef10818276ec17ad9683df1a9523b2b486fd0", + "package": "react-native-windows" + }, + { + "comment": "Switch package layout to use `files` in `pacakge.json` rather than `.npmignore`", + "author": "dannyvv@microsoft.com", + "commit": "c18e0c17fa6c2a2f778aa6607fb7e1601f6089da", + "package": "react-native-windows" + } + ], + "none": [ + { + "comment": "Fix typo", + "author": "rezha@microsoft.com", + "commit": "76b3478cb83004b5b6718af0381e8a3856ef893d", + "package": "react-native-windows" + }, + { + "comment": "fix issue 4792", + "author": "aeulitz@microsoft.com", + "commit": "608b98b46627d9c6a79bbe6a7f3f3ceb7aa8ff2a", + "package": "react-native-windows" + } + ] + } + }, { "date": "Wed, 06 May 2020 00:05:03 GMT", "tag": "react-native-windows_v0.0.0-master.59", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 2e07c4f7b9a..e5d1931c2c7 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,20 @@ # Change Log - react-native-windows -This log was last generated on Wed, 06 May 2020 00:05:03 GMT and should not be manually modified. +This log was last generated on Thu, 07 May 2020 00:05:07 GMT and should not be manually modified. +## 0.0.0-master.60 + +Thu, 07 May 2020 00:05:07 GMT + +### Changes + +- Don't delete nuget.exe if using locally-installed (e.g. chocolatey) (asklar@microsoft.com) +- Only bundle when not running Intellisense builds (asklar@microsoft.com) +- Disable CxxFrameHandler4 (ngerlem@microsoft.com) +- Switch package layout to use `files` in `pacakge.json` rather than `.npmignore` (dannyvv@microsoft.com) + ## 0.0.0-master.59 Wed, 06 May 2020 00:05:03 GMT diff --git a/vnext/package.json b/vnext/package.json index 03896b6eb42..9f3d78d6d33 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.59", + "version": "0.0.0-master.60", "license": "MIT", "repository": { "type": "git", @@ -95,7 +95,6 @@ "/Scripts", "/Shared", "/stubs", - "/.flowconfig", "/Directory.Build.props", "/Directory.Build.targets", From 04583378bd66c2d473a804c5e7cb663596e1a4be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20C=C3=A9sar=20Rocha?= Date: Wed, 6 May 2020 21:25:01 -0700 Subject: [PATCH 062/209] Ensure WebSocket write lifetime (#4790) * Promote awaitable DispatchQueue callback to member field --- ...tive-windows-2020-05-04-19-05-45-OC-4133953-pwrav.json | 8 ++++++++ vnext/ReactWindowsCore/WinRTWebSocketResource.cpp | 6 ++++-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 change/react-native-windows-2020-05-04-19-05-45-OC-4133953-pwrav.json diff --git a/change/react-native-windows-2020-05-04-19-05-45-OC-4133953-pwrav.json b/change/react-native-windows-2020-05-04-19-05-45-OC-4133953-pwrav.json new file mode 100644 index 00000000000..515ff1a6d51 --- /dev/null +++ b/change/react-native-windows-2020-05-04-19-05-45-OC-4133953-pwrav.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Promote awaitable DispatchQueue callback to member field", + "packageName": "react-native-windows", + "email": "julio.rocha@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-05T02:05:45.427Z" +} diff --git a/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp b/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp index 8ee1ea218b4..e88efbdf448 100644 --- a/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp +++ b/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp @@ -66,14 +66,16 @@ namespace void await_suspend(std::experimental::coroutine_handle<> resume) { - m_queue.Post([context = resume.address()]() noexcept + m_callback = [context = resume.address()]() noexcept { std::experimental::coroutine_handle<>::from_address(context)(); - }); + }; + m_queue.Post(std::move(m_callback)); } private: Mso::DispatchQueue m_queue; + Mso::VoidFunctor m_callback; }; return awaitable{ queue }; From 6088cb0d6b9291e7877d5b0aefd6f18cb1bace3c Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Thu, 7 May 2020 00:43:01 -0700 Subject: [PATCH 063/209] Ensure InitializeCore is run before app code (#4814) * Ensure InitializeCore is run before app code * Change files --- ...ive-win32-2020-05-06-14-34-01-fixfast.json | 8 ++++ ...e-windows-2020-05-06-14-34-01-fixfast.json | 8 ++++ packages/E2ETest/metro.config.js | 13 +++-- .../metro.config.js | 13 +++-- packages/playground/metro.config.js | 13 +++-- .../metro-react-native-platform.js | 47 ++++++++++++++++++- packages/react-native-win32/metro.config.js | 13 +++-- .../templates/metro.config.js | 14 ++++-- vnext/metro-react-native-platform.js | 38 ++++++++++++++- vnext/metro.config.js | 21 ++++++--- 10 files changed, 164 insertions(+), 24 deletions(-) create mode 100644 change/@office-iss-react-native-win32-2020-05-06-14-34-01-fixfast.json create mode 100644 change/react-native-windows-2020-05-06-14-34-01-fixfast.json diff --git a/change/@office-iss-react-native-win32-2020-05-06-14-34-01-fixfast.json b/change/@office-iss-react-native-win32-2020-05-06-14-34-01-fixfast.json new file mode 100644 index 00000000000..5e0b830af9f --- /dev/null +++ b/change/@office-iss-react-native-win32-2020-05-06-14-34-01-fixfast.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Ensure InitializeCore is run before app code", + "packageName": "@office-iss/react-native-win32", + "email": "acoates@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-06T21:33:58.938Z" +} diff --git a/change/react-native-windows-2020-05-06-14-34-01-fixfast.json b/change/react-native-windows-2020-05-06-14-34-01-fixfast.json new file mode 100644 index 00000000000..566bb7c5451 --- /dev/null +++ b/change/react-native-windows-2020-05-06-14-34-01-fixfast.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Ensure InitializeCore is run before app code", + "packageName": "react-native-windows", + "email": "acoates@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-06T21:34:00.993Z" +} diff --git a/packages/E2ETest/metro.config.js b/packages/E2ETest/metro.config.js index a5b5455186f..dd5772a7d4b 100644 --- a/packages/E2ETest/metro.config.js +++ b/packages/E2ETest/metro.config.js @@ -6,6 +6,10 @@ */ const path = require('path'); const blacklist = require('metro-config/src/defaults/blacklist'); +const { + getModulesRunBeforeMainModule, + reactNativePlatformResolver, +} = require('react-native-windows/metro-react-native-platform'); const rnwPath = path.resolve(__dirname, '../../vnext'); @@ -19,9 +23,9 @@ module.exports = { ], resolver: { - resolveRequest: require('react-native-windows/metro-react-native-platform').reactNativePlatformResolver( - { windows: 'react-native-windows' } - ), + resolveRequest: reactNativePlatformResolver({ + windows: 'react-native-windows', + }), extraNodeModules: { // Redirect metro to rnwPath instead of node_modules/react-native-windows, since metro doesn't like symlinks 'react-native-windows': rnwPath, @@ -34,6 +38,9 @@ module.exports = { ), ]), }, + serializer: { + getModulesRunBeforeMainModule, + }, transformer: { // The cli defaults this to a full path to react-native, which bypasses the reactNativePlatformResolver above // Hopefully we can fix the default in the future diff --git a/packages/microsoft-reactnative-sampleapps/metro.config.js b/packages/microsoft-reactnative-sampleapps/metro.config.js index d850032e67a..051c80f4a7f 100644 --- a/packages/microsoft-reactnative-sampleapps/metro.config.js +++ b/packages/microsoft-reactnative-sampleapps/metro.config.js @@ -6,6 +6,10 @@ */ const path = require('path'); const blacklist = require('metro-config/src/defaults/blacklist'); +const { + getModulesRunBeforeMainModule, + reactNativePlatformResolver, +} = require('react-native-windows/metro-react-native-platform'); const rnwPath = path.resolve(__dirname, '../../vnext'); @@ -19,9 +23,9 @@ module.exports = { ], resolver: { - resolveRequest: require('react-native-windows/metro-react-native-platform').reactNativePlatformResolver( - {windows: 'react-native-windows'}, - ), + resolveRequest: reactNativePlatformResolver({ + windows: 'react-native-windows', + }), extraNodeModules: { // Redirect metro to rnwPath instead of node_modules/react-native-windows, since metro doesn't like symlinks 'react-native-windows': rnwPath, @@ -36,6 +40,9 @@ module.exports = { ), ]), }, + serializer: { + getModulesRunBeforeMainModule, + }, transformer: { // The cli defaults this to a full path to react-native, which bypasses the reactNativePlatformResolver above // Hopefully we can fix the default in the future diff --git a/packages/playground/metro.config.js b/packages/playground/metro.config.js index 6a543d2b85b..9d3e6b90a00 100644 --- a/packages/playground/metro.config.js +++ b/packages/playground/metro.config.js @@ -7,6 +7,10 @@ const fs = require('fs'); const path = require('path'); const blacklist = require('metro-config/src/defaults/blacklist'); +const { + getModulesRunBeforeMainModule, + reactNativePlatformResolver, +} = require('react-native-windows/metro-react-native-platform'); const rnwPath = fs.realpathSync( path.resolve(require.resolve('react-native-windows/package.json'), '..'), @@ -22,9 +26,9 @@ module.exports = { ], resolver: { - resolveRequest: require('react-native-windows/metro-react-native-platform').reactNativePlatformResolver( - {windows: 'react-native-windows'}, - ), + resolveRequest: reactNativePlatformResolver({ + windows: 'react-native-windows', + }), extraNodeModules: { // Redirect react-native-windows to avoid symlink (metro doesn't like symlinks) 'react-native-windows': rnwPath, @@ -36,6 +40,9 @@ module.exports = { ), ]), }, + serializer: { + getModulesRunBeforeMainModule, + }, transformer: { // The cli defaults this to a full path to react-native, which bypasses the reactNativePlatformResolver above // Hopefully we can fix the default in the future diff --git a/packages/react-native-win32/metro-react-native-platform.js b/packages/react-native-win32/metro-react-native-platform.js index c908a32c52c..daf9a550e04 100644 --- a/packages/react-native-win32/metro-react-native-platform.js +++ b/packages/react-native-win32/metro-react-native-platform.js @@ -38,4 +38,49 @@ function reactNativePlatformResolver(platformImplementations) { }; } -module.exports = {reactNativePlatformResolver}; +/** + * The CLI will get a more complete implementation of this in https://github.com/react-native-community/cli/pull/1115 + * but until then, use a solution that supports having react-native-win32 and/or react-native-windows and/or react-native-macos + */ +const getModulesRunBeforeMainModule = () => { + const options = { + paths: [process.cwd()], + }; + const modules = [ + require.resolve('react-native/Libraries/Core/InitializeCore', options), + ]; + + try { + modules.push( + require.resolve( + '@office-iss/react-native-win32/Libraries/Core/InitializeCore', + options, + ), + ); + } catch {} + + try { + modules.push( + require.resolve( + 'react-native-windows/Libraries/Core/InitializeCore', + options, + ), + ); + } catch {} + + try { + modules.push( + require.resolve( + 'react-native-macos/Libraries/Core/InitializeCore', + options, + ), + ); + } catch {} + + return modules; +}; + +module.exports = { + getModulesRunBeforeMainModule, + reactNativePlatformResolver, +}; diff --git a/packages/react-native-win32/metro.config.js b/packages/react-native-win32/metro.config.js index c15ae2c5ca5..084652f0ad0 100644 --- a/packages/react-native-win32/metro.config.js +++ b/packages/react-native-win32/metro.config.js @@ -3,6 +3,10 @@ */ const fs = require('fs'); const path = require('path'); +const { + getModulesRunBeforeMainModule, + reactNativePlatformResolver, +} = require('./metro-react-native-platform'); module.exports = { // WatchFolders is only needed due to the yarn workspace layout of node_modules, we need to watch the symlinked locations separately @@ -12,9 +16,12 @@ module.exports = { ], resolver: { - resolveRequest: require('./metro-react-native-platform').reactNativePlatformResolver( - {win32: '@office-iss/react-native-win32'}, - ), + resolveRequest: reactNativePlatformResolver({ + win32: '@office-iss/react-native-win32', + }), + }, + serializer: { + getModulesRunBeforeMainModule, }, transformer: { // The cli defaults this to a full path to react-native, which bypasses the reactNativePlatformResolver above diff --git a/vnext/local-cli/generator-windows/templates/metro.config.js b/vnext/local-cli/generator-windows/templates/metro.config.js index d3d86824f7b..a1e6b552e99 100644 --- a/vnext/local-cli/generator-windows/templates/metro.config.js +++ b/vnext/local-cli/generator-windows/templates/metro.config.js @@ -7,11 +7,16 @@ const path = require('path'); const blacklist = require('metro-config/src/defaults/blacklist'); +const { + getModulesRunBeforeMainModule, + reactNativePlatformResolver, +} = require('react-native-windows/metro-react-native-platform'); + module.exports = { resolver: { - resolveRequest: require('react-native-windows/metro-react-native-platform').reactNativePlatformResolver( - {windows: 'react-native-windows'}, - ), + resolveRequest: reactNativePlatformResolver({ + windows: 'react-native-windows', + }), blacklistRE: blacklist([ // This stops "react-native run-windows" from causing the metro server to crash if its already running new RegExp( @@ -25,6 +30,9 @@ module.exports = { ), ]), }, + serializer: { + getModulesRunBeforeMainModule, + }, transformer: { // The cli defaults this to a full path to react-native, which bypasses the reactNativePlatformResolver above // Hopefully we can fix the default in the future diff --git a/vnext/metro-react-native-platform.js b/vnext/metro-react-native-platform.js index c908a32c52c..e9acdf525a7 100644 --- a/vnext/metro-react-native-platform.js +++ b/vnext/metro-react-native-platform.js @@ -38,4 +38,40 @@ function reactNativePlatformResolver(platformImplementations) { }; } -module.exports = {reactNativePlatformResolver}; +/** + * The CLI will get a more complete implementation of this in https://github.com/react-native-community/cli/pull/1115 + * but until then, use a solution that supports having react-native-windows and/or react-native-macos + */ +const getModulesRunBeforeMainModule = () => { + const options = { + paths: [process.cwd()], + }; + const modules = [ + require.resolve('react-native/Libraries/Core/InitializeCore', options), + ]; + + try { + modules.push( + require.resolve( + 'react-native-windows/Libraries/Core/InitializeCore', + options, + ), + ); + } catch {} + + try { + modules.push( + require.resolve( + 'react-native-macos/Libraries/Core/InitializeCore', + options, + ), + ); + } catch {} + + return modules; +}; + +module.exports = { + getModulesRunBeforeMainModule, + reactNativePlatformResolver, +}; diff --git a/vnext/metro.config.js b/vnext/metro.config.js index b332c81a94e..3082ecc5edc 100644 --- a/vnext/metro.config.js +++ b/vnext/metro.config.js @@ -3,7 +3,11 @@ */ const fs = require('fs'); const path = require('path'); -const blacklist = require('metro-config/src/defaults/blacklist'); + +const { + getModulesRunBeforeMainModule, + reactNativePlatformResolver, +} = require('react-native-windows/metro-react-native-platform'); const rnwPath = __dirname; @@ -15,17 +19,20 @@ module.exports = { ], resolver: { - resolveRequest: require('./metro-react-native-platform').reactNativePlatformResolver( - { - windesktop: 'react-native-windows', - windows: 'react-native-windows', - }, - ), + resolveRequest: reactNativePlatformResolver({ + windesktop: 'react-native-windows', + windows: 'react-native-windows', + }), extraNodeModules: { // Redirect react-native-windows to this folder 'react-native-windows': rnwPath, }, }, + + serializer: { + getModulesRunBeforeMainModule, + }, + transformer: { // The cli defaults this to a full path to react-native, which bypasses the reactNativePlatformResolver above // Hopefully we can fix the default in the future From 1cff8969f12ab8e680cf9e221ec8478a56512d98 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 7 May 2020 16:50:31 +0000 Subject: [PATCH 064/209] Bump stacktrace-parser from 0.1.9 to 0.1.10 (#4821) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 2c25ad6a8df..8dccb129849 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12694,9 +12694,9 @@ stack-utils@^1.0.1: integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== stacktrace-parser@^0.1.3: - version "0.1.9" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.9.tgz#11e6d61d42e8cfc87293143d0766408b7a87b00f" - integrity sha512-DRy03ljj0367Ud3OAJHD6eVS/+CvMK2u/djVYuU37fHYcYHoZ8tkFyhbRf7PNG1h3bWLsw+SNTSXrPFe07A7aQ== + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== dependencies: type-fest "^0.7.1" From 605e3f8dc651706cfafbb4f21931bcbc03a9f140 Mon Sep 17 00:00:00 2001 From: dannyvv Date: Thu, 7 May 2020 10:22:40 -0700 Subject: [PATCH 065/209] Upgrade the shared managed project to a proper csharp library. (#4793) * Upgrade the shared managed project to a proper csharp library. This change intentionally does not yet update the C# template yet, I'll do so in a separate pr. The old shared project is not remvoed in the PR as it needs to remain because existing customers that used the templates might refer to this. * Change files --- ...ve-windows-2020-05-05-12-31-18-master.json | 8 ++ docs/project-structure.md | 8 +- packages/E2ETest/windows/ReactUWPTestApp.sln | 25 +++- .../windows/ReactUWPTestApp/App.xaml.cs | 4 +- .../ReactUWPTestApp/ReactUWPTestApp.csproj | 8 +- .../TreeDumpLibrary/ReactPackageProvider.cs | 2 +- .../TreeDumpLibrary/TreeDumpLibrary.csproj | 8 +- .../windows/SampleAppCS/App.xaml.cs | 2 + .../windows/SampleAppCS/SampleAppCS.csproj | 13 +- .../windows/SampleApps.sln | 25 +++- .../CustomUserControlViewManagerCS.cs | 2 +- .../SampleLibraryCS/ReactPackageProvider.cs | 3 +- .../SampleLibraryCS/SampleLibraryCS.csproj | 12 +- vnext/JSI/Shared/JSI.Shared.vcxitems | 2 +- .../JSValueReaderTest.cs | 8 ++ ...osoft.ReactNative.Managed.UnitTests.csproj | 5 +- .../NativeModuleTest.cs | 7 + .../Microsoft.ReactNative.Managed.csproj | 125 ++++++++++++++++++ .../Properties/AssemblyInfo.cs | 18 +++ .../Microsoft.ReactNative.Managed.rd.xml | 32 +++++ .../AttributedViewManager.cs | 4 +- .../IJSValueTreeReader.cs | 2 +- .../IReactPromise.cs | 4 +- .../JSValue.cs | 6 +- .../JSValueReader.cs | 4 +- .../JSValueReaderGenerator.cs | 73 ++++++---- .../JSValueTreeReader.cs | 2 +- .../JSValueTreeWriter.cs | 4 +- .../JSValueWriter.cs | 4 +- .../JSValueWriterGenerator.cs | 32 ++++- ...rosoft.ReactNative.SharedManaged.projitems | 1 + ...Microsoft.ReactNative.SharedManaged.shproj | 3 +- .../OneOf.cs | 14 +- .../ReactAttributes.cs | 16 +-- .../ReactConstantInfo.cs | 2 +- .../ReactConstantProvider.cs | 2 +- .../ReactConstantProviderInfo.cs | 2 +- .../ReactContext.cs | 2 +- .../ReactContextGenerator.cs | 2 +- .../ReactEventInfo.cs | 2 +- .../ReactException.cs | 2 +- .../ReactFunctionInfo.cs | 2 +- .../ReactInitializerInfo.cs | 2 +- .../ReactMethodInfo.cs | 2 +- .../ReactModuleInfo.cs | 2 +- .../ReactPackageBuilderExtensions.cs | 71 ++++++++-- .../ReactPackageProvider.cs | 14 +- .../ReactPromise.cs | 2 +- .../ReactSyncMethodInfo.cs | 2 +- .../ReflectionReactPackageProvider.cs | 54 ++++++++ .../ViewManagerAttributes.cs | 10 +- .../ViewManagerEvent.cs | 2 +- vnext/Microsoft.ReactNative.sln | 19 ++- vnext/ReactWindows-Universal.sln | 19 ++- vnext/Shared/Shared.vcxitems | 2 +- 55 files changed, 569 insertions(+), 134 deletions(-) create mode 100644 change/react-native-windows-2020-05-05-12-31-18-master.json create mode 100644 vnext/Microsoft.ReactNative.Managed/Microsoft.ReactNative.Managed.csproj create mode 100644 vnext/Microsoft.ReactNative.Managed/Properties/AssemblyInfo.cs create mode 100644 vnext/Microsoft.ReactNative.Managed/Properties/Microsoft.ReactNative.Managed.rd.xml create mode 100644 vnext/Microsoft.ReactNative.SharedManaged/ReflectionReactPackageProvider.cs diff --git a/change/react-native-windows-2020-05-05-12-31-18-master.json b/change/react-native-windows-2020-05-05-12-31-18-master.json new file mode 100644 index 00000000000..4a323b24011 --- /dev/null +++ b/change/react-native-windows-2020-05-05-12-31-18-master.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Upgrade the shared managed project to a proper csharp library.", + "packageName": "react-native-windows", + "email": "dannyvv@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-05T19:31:18.766Z" +} diff --git a/docs/project-structure.md b/docs/project-structure.md index e9e2693074b..fc20a99bf97 100644 --- a/docs/project-structure.md +++ b/docs/project-structure.md @@ -20,6 +20,7 @@ Sample applications are not covered. - [JSI.Desktop.UnitTests\JSI.Desktop.UnitTests](#JSI.Desktop.UnitTests) - **[Microsoft.ReactNative\Microsoft.ReactNative.vcxproj](#Microsoft.ReactNative)** - [Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems](#Microsoft.ReactNative.Cxx) +- [Microsoft.ReactNative.Managed\Microsoft.ReactNative.Managed.csproj](#Microsoft.ReactNative.Managed) - [Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems](#Microsoft.ReactNative.SharedManaged) - [ReactCommon\ReactCommon.vcxproj](#ReactCommon) - [ReactUWP\ReactUWP.vcxproj](#ReactUWP) @@ -66,10 +67,15 @@ Code shared between [JSI\Desktop\JSI.Desktop.vcxproj](#JSI.Desktop) and [JSI\Uni *Shared Items (no build artifact)*
Contains helpers to simplify authoring C++/WinRT native modules on top of [Microsoft.ReactNative](#Microsoft.ReactNative). -### Microsoft.ReactNative.SharedManaged +### Microsoft.ReactNative.Managed *Shared Items (no build artifact)*
Contains helpers to simplify authoring C# native modules on top of [Microsoft.ReactNative](#Microsoft.ReactNative). +### Microsoft.ReactNative.SharedManaged +*Shared Items (no build artifact)*
+This shared project is to be deprecated in some time in favor of the library [Microsoft.ReactNative.Managed](#Microsoft.ReactNative.Managed). +For now it contaisn the same code as the library. + ### React.Windows.IntegrationTests *Static Library*
Common framework for running out of process and/or full React instance testing. diff --git a/packages/E2ETest/windows/ReactUWPTestApp.sln b/packages/E2ETest/windows/ReactUWPTestApp.sln index fc8d5c38e59..fd7c8a089aa 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp.sln +++ b/packages/E2ETest/windows/ReactUWPTestApp.sln @@ -37,16 +37,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReactNative", "ReactNative" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative", "..\..\..\vnext\Microsoft.ReactNative\Microsoft.ReactNative.vcxproj", "{F7D32BD0-2749-483E-9A0D-1635EF7E3136}" EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Microsoft.ReactNative.SharedManaged", "..\..\..\vnext\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.shproj", "{67A1076F-7790-4203-86EA-4402CCB5E782}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TreeDumpLibrary", "TreeDumpLibrary\TreeDumpLibrary.csproj", "{C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ReactNative.Managed", "..\..\..\vnext\Microsoft.ReactNative.Managed\Microsoft.ReactNative.Managed.csproj", "{F2824844-CE15-4242-9420-308923CD76C3}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - ..\..\..\vnext\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{67a1076f-7790-4203-86ea-4402ccb5e782}*SharedItemsImports = 13 ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4 - ..\..\..\vnext\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{abbb0407-0e82-486f-94ce-710900fcaadc}*SharedItemsImports = 4 - ..\..\..\vnext\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{c0a6bd9c-3ee5-4b12-8ce4-cee95178539c}*SharedItemsImports = 4 ..\..\..\vnext\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 @@ -200,6 +197,22 @@ Global {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Release|x64.Build.0 = Release|x64 {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Release|x86.ActiveCfg = Release|x86 {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Release|x86.Build.0 = Release|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.ActiveCfg = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.Build.0 = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.Build.0 = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.ActiveCfg = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.Build.0 = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.ActiveCfg = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.Build.0 = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.ActiveCfg = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.Build.0 = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.ActiveCfg = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.Build.0 = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.ActiveCfg = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.Build.0 = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.ActiveCfg = Release|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -211,7 +224,7 @@ Global {A62D504A-16B8-41D2-9F19-E2E86019E5E4} = {AB7DB37D-898C-4BBC-9F2A-E043EC90C8F3} {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D} = {AB7DB37D-898C-4BBC-9F2A-E043EC90C8F3} {F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {AB7DB37D-898C-4BBC-9F2A-E043EC90C8F3} - {67A1076F-7790-4203-86EA-4402CCB5E782} = {AB7DB37D-898C-4BBC-9F2A-E043EC90C8F3} + {F2824844-CE15-4242-9420-308923CD76C3} = {AB7DB37D-898C-4BBC-9F2A-E043EC90C8F3} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F5EAF3BA-6B6F-4E81-B5C6-49B30EC0A32E} diff --git a/packages/E2ETest/windows/ReactUWPTestApp/App.xaml.cs b/packages/E2ETest/windows/ReactUWPTestApp/App.xaml.cs index d813eb85f37..9befe037a84 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp/App.xaml.cs +++ b/packages/E2ETest/windows/ReactUWPTestApp/App.xaml.cs @@ -8,6 +8,7 @@ using Windows.Graphics.Display; using Windows.UI.Core; using Windows.UI.ViewManagement; +using Microsoft.ReactNative.Managed; namespace ReactUWPTestApp { @@ -40,7 +41,8 @@ public App() InstanceSettings.EnableDeveloperMenu = false; #endif - PackageProviders.Add(new Microsoft.ReactNative.Managed.ReactPackageProvider()); // Includes any modules in this project + PackageProviders.Add(new Microsoft.ReactNative.Managed.ReactPackageProvider()); + PackageProviders.Add(new ReflectionReactPackageProvider()); PackageProviders.Add(new TreeDumpLibrary.ReactPackageProvider()); this.InitializeComponent(); diff --git a/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj b/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj index 863452d52a0..5ffa2dda86c 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj +++ b/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj @@ -1,5 +1,6 @@  - + Debug @@ -164,12 +165,15 @@ {f7d32bd0-2749-483e-9a0d-1635ef7e3136} Microsoft.ReactNative + + {F2824844-CE15-4242-9420-308923CD76C3} + Microsoft.ReactNative.Managed + {c0a6bd9c-3ee5-4b12-8ce4-cee95178539c} TreeDumpLibrary - 16.0 diff --git a/packages/E2ETest/windows/TreeDumpLibrary/ReactPackageProvider.cs b/packages/E2ETest/windows/TreeDumpLibrary/ReactPackageProvider.cs index 30d9991f556..e3c30644e70 100644 --- a/packages/E2ETest/windows/TreeDumpLibrary/ReactPackageProvider.cs +++ b/packages/E2ETest/windows/TreeDumpLibrary/ReactPackageProvider.cs @@ -10,7 +10,7 @@ public sealed class ReactPackageProvider : IReactPackageProvider { public void CreatePackage(IReactPackageBuilder packageBuilder) { - packageBuilder.AddViewManagers(); + packageBuilder.AddReflectionReactPackageProvider(); } } } diff --git a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj index 6e960869419..e8ca1d3675b 100644 --- a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj +++ b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj @@ -1,5 +1,6 @@  - + Debug @@ -125,11 +126,14 @@ Microsoft.ReactNative False + + {F2824844-CE15-4242-9420-308923CD76C3} + Microsoft.ReactNative.Managed + - 16.0 diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/App.xaml.cs b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/App.xaml.cs index a2552c4c772..a42b17de53f 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/App.xaml.cs +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/App.xaml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using Microsoft.ReactNative; +using Microsoft.ReactNative.Managed; namespace SampleAppCS { @@ -37,6 +38,7 @@ public App() #endif PackageProviders.Add(new Microsoft.ReactNative.Managed.ReactPackageProvider()); // Includes any modules in this project + PackageProviders.Add(new ReflectionReactPackageProvider()); PackageProviders.Add(new SampleLibraryCS.ReactPackageProvider()); PackageProviders.Add(new SampleLibraryCpp.ReactPackageProvider()); diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/SampleAppCS.csproj b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/SampleAppCS.csproj index 39da02a581d..51a0edd703a 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/SampleAppCS.csproj +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/SampleAppCS.csproj @@ -1,5 +1,6 @@  - + Debug @@ -19,7 +20,7 @@ true false false - 7.0 + 8.0 true @@ -154,6 +155,10 @@ + + {F2824844-CE15-4242-9420-308923CD76C3} + Microsoft.ReactNative.Managed + {f7d32bd0-2749-483e-9a0d-1635ef7e3136} Microsoft.ReactNative @@ -166,11 +171,7 @@ {c0a6bd9c-3ee5-4b12-8ce4-cee95178539c} SampleLibraryCS - - 2.3.191129002 - - 16.0 diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleApps.sln b/packages/microsoft-reactnative-sampleapps/windows/SampleApps.sln index d2e1223a74b..2f4bae66813 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleApps.sln +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleApps.sln @@ -35,8 +35,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Universal", "..\..\..\v EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", "..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems", "{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B}" EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Microsoft.ReactNative.SharedManaged", "..\..\..\vnext\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.shproj", "{67A1076F-7790-4203-86EA-4402CCB5E782}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "..\..\..\vnext\Common\Common.vcxproj", "{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReactNative", "ReactNative", "{5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}" @@ -47,17 +45,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso", "..\..\..\vnext\Mso\M EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Include", "..\..\..\vnext\include\Include.vcxitems", "{EF074BA1-2D54-4D49-A28E-5E040B47CD2E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ReactNative.Managed", "..\..\..\vnext\Microsoft.ReactNative.Managed\Microsoft.ReactNative.Managed.csproj", "{F2824844-CE15-4242-9420-308923CD76C3}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - ..\..\..\vnext\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{09f4e6c1-2d12-4059-aa96-0b190861fd6a}*SharedItemsImports = 4 ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 ..\..\..\vnext\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{47eec7f3-40d3-49ba-82c1-eaf103b54215}*SharedItemsImports = 4 - ..\..\..\vnext\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{67a1076f-7790-4203-86ea-4402ccb5e782}*SharedItemsImports = 13 ..\..\..\vnext\Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{93f7572c-64b9-4096-9ef9-6ba0ede2b50d}*SharedItemsImports = 4 ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4 - ..\..\..\vnext\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{c0a6bd9c-3ee5-4b12-8ce4-cee95178539c}*SharedItemsImports = 4 ..\..\..\vnext\Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9 ..\..\..\vnext\include\Include.vcxitems*{ef074ba1-2d54-4d49-a28e-5e040b47cd2e}*SharedItemsImports = 9 @@ -254,6 +251,22 @@ Global {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.Build.0 = Release|x64 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.ActiveCfg = Release|Win32 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.Build.0 = Release|Win32 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.ActiveCfg = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.Build.0 = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.Build.0 = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.ActiveCfg = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.Build.0 = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.ActiveCfg = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.Build.0 = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.ActiveCfg = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.Build.0 = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.ActiveCfg = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.Build.0 = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.ActiveCfg = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.Build.0 = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.ActiveCfg = Release|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -267,11 +280,11 @@ Global {0CC28589-39E4-4288-B162-97B959F8B843} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {A62D504A-16B8-41D2-9F19-E2E86019E5E4} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} - {67A1076F-7790-4203-86EA-4402CCB5E782} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {2049DBE9-8D13-42C9-AE4B-413AE38FFFD0} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {EF074BA1-2D54-4D49-A28E-5E040B47CD2E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {F2824844-CE15-4242-9420-308923CD76C3} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AE882847-CAE9-450F-8962-E76672DC23CE} diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/CustomUserControlViewManagerCS.cs b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/CustomUserControlViewManagerCS.cs index 33fed3be6fe..ba2b3adf7c8 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/CustomUserControlViewManagerCS.cs +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/CustomUserControlViewManagerCS.cs @@ -20,7 +20,7 @@ public override FrameworkElement CreateView() { if (obj is CustomUserControlCS c) { - LabelChanged(c, c.Label); + LabelChanged?.Invoke(c, c.Label); } }); diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/ReactPackageProvider.cs b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/ReactPackageProvider.cs index 6fd469a3ebb..ca42f3e52c2 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/ReactPackageProvider.cs +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/ReactPackageProvider.cs @@ -10,8 +10,7 @@ public sealed class ReactPackageProvider : IReactPackageProvider { public void CreatePackage(IReactPackageBuilder packageBuilder) { - packageBuilder.AddAttributedModules(); - packageBuilder.AddViewManagers(); + packageBuilder.AddReflectionReactPackageProvider(); } } } diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleLibraryCS.csproj b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleLibraryCS.csproj index 36cc8bb8b1c..03bc1a7e219 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleLibraryCS.csproj +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleLibraryCS.csproj @@ -1,5 +1,6 @@  - + Debug @@ -18,7 +19,7 @@ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} false false - 7.0 + 8.0 x86 @@ -119,6 +120,10 @@ + + {F2824844-CE15-4242-9420-308923CD76C3} + Microsoft.ReactNative.Managed + {f7d32bd0-2749-483e-9a0d-1635ef7e3136} Microsoft.ReactNative @@ -131,7 +136,6 @@ Designer - 16.0 @@ -143,4 +147,4 @@ --> - + \ No newline at end of file diff --git a/vnext/JSI/Shared/JSI.Shared.vcxitems b/vnext/JSI/Shared/JSI.Shared.vcxitems index e835ad07a35..bab06720838 100644 --- a/vnext/JSI/Shared/JSI.Shared.vcxitems +++ b/vnext/JSI/Shared/JSI.Shared.vcxitems @@ -26,4 +26,4 @@ - + \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative.Managed.UnitTests/JSValueReaderTest.cs b/vnext/Microsoft.ReactNative.Managed.UnitTests/JSValueReaderTest.cs index 5531704e962..bd9efc3e68c 100644 --- a/vnext/Microsoft.ReactNative.Managed.UnitTests/JSValueReaderTest.cs +++ b/vnext/Microsoft.ReactNative.Managed.UnitTests/JSValueReaderTest.cs @@ -168,6 +168,13 @@ public static void WriteValue(this IJSValueWriter writer, OneOf2{f7d32bd0-2749-483e-9a0d-1635ef7e3136} Microsoft.ReactNative + + {F2824844-CE15-4242-9420-308923CD76C3} + Microsoft.ReactNative.Managed + - + + + + + + + diff --git a/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs b/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs index ab835d574ae..c4d33d12c1b 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs @@ -12,7 +12,7 @@ namespace Microsoft.ReactNative.Managed { - internal abstract class AttributedViewManager : + public abstract class AttributedViewManager : IViewManager, IViewManagerWithReactContext, IViewManagerWithExportedViewConstants, @@ -139,7 +139,7 @@ internal Dictionary> ViewManagerP } private Dictionary> _properties; - internal struct ViewManagerProperty where U : TFrameworkElement + public struct ViewManagerProperty where U : TFrameworkElement { public string Name; public ViewManagerPropertyType Type; diff --git a/vnext/Microsoft.ReactNative.SharedManaged/IJSValueTreeReader.cs b/vnext/Microsoft.ReactNative.SharedManaged/IJSValueTreeReader.cs index 9757e83b155..670c7df4329 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/IJSValueTreeReader.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/IJSValueTreeReader.cs @@ -3,7 +3,7 @@ namespace Microsoft.ReactNative.Managed { - interface IJSValueTreeReader + public interface IJSValueTreeReader { JSValue Current { get; } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/IReactPromise.cs b/vnext/Microsoft.ReactNative.SharedManaged/IReactPromise.cs index b6ee4972e92..7f647b6d060 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/IReactPromise.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/IReactPromise.cs @@ -22,7 +22,7 @@ namespace Microsoft.ReactNative.Managed // // Methods annotated with ReactMethodAttribute that use a IReactPromise as the last parameter // will be marked as "promise" and will return a promise when invoked from JavaScript. - interface IReactPromise + public interface IReactPromise { // Successfully resolve the IReactPromise with an optional value. void Resolve(T value = default(T)); @@ -31,7 +31,7 @@ interface IReactPromise void Reject(ReactError error); } - class ReactError + public class ReactError { public string Code = null; public string Message = null; diff --git a/vnext/Microsoft.ReactNative.SharedManaged/JSValue.cs b/vnext/Microsoft.ReactNative.SharedManaged/JSValue.cs index 10068e26fa4..955cfa156f1 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/JSValue.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/JSValue.cs @@ -12,7 +12,7 @@ namespace Microsoft.ReactNative.Managed { // JSValueObject is based on Dictionary and can be used to initialize Object value in JSValue. // It is possible to write: JSValueObject{{"X", 4}, {"Y", 5}} or JSValueObject{["X"] = 4, ["Y"] = 5} and assign it to JSValue. - class JSValueObject : Dictionary, IEquatable + public class JSValueObject : Dictionary, IEquatable { // Default constructor public JSValueObject() { } @@ -129,7 +129,7 @@ public override int GetHashCode() // JSValueObject is based on List and can be used to initialize Array value in JSValue. // It is possible to write: JSValueArray{"X", 42, JSValue.Null, true} and assign it to JSValue. - class JSValueArray : List, IEquatable + public class JSValueArray : List, IEquatable { // Default constructor public JSValueArray() { } @@ -252,7 +252,7 @@ public override int GetHashCode() // - It avoids boxing simple values by using a union type to store them. // The JSValue is an immutable and is safe to be used from multiple threads. // It does not implement GetHashCode() and must not be used as a key in a dictionary. - struct JSValue : IEquatable + public struct JSValue : IEquatable { public static readonly JSValue Null = new JSValue(); public static readonly JSValue EmptyObject = new JSValueObject(); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/JSValueReader.cs b/vnext/Microsoft.ReactNative.SharedManaged/JSValueReader.cs index d4b85aa3c34..2496ca5433b 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/JSValueReader.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/JSValueReader.cs @@ -9,12 +9,12 @@ namespace Microsoft.ReactNative.Managed { - delegate void ReadValueDelegate(IJSValueReader reader, out T value); + public delegate void ReadValueDelegate(IJSValueReader reader, out T value); // A value can be read from IJSValueReader in one of two ways: // 1. There is a ReadValue extension for IJSValueReader interface that matches the type. // 2. We can auto-generate the read method for the type. - static class JSValueReader + public static class JSValueReader { private static IReadOnlyDictionary s_readerDelegates = new Dictionary(); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/JSValueReaderGenerator.cs b/vnext/Microsoft.ReactNative.SharedManaged/JSValueReaderGenerator.cs index c246f58aec6..2de9fdd6c6f 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/JSValueReaderGenerator.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/JSValueReaderGenerator.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; @@ -12,14 +13,37 @@ namespace Microsoft.ReactNative.Managed { - static class JSValueReaderGenerator + public static class JSValueReaderGenerator { + // The current assembly to ensure we always register the basic type readers + private static readonly Assembly s_currentAssembly = typeof(JSValueReaderGenerator).Assembly; + + private static readonly ConcurrentDictionary m_registerdAssemblies = new ConcurrentDictionary(); private static readonly Lazy[]> s_allMethods; private static readonly Lazy> s_nonGenericMethods; private static readonly Lazy>> s_genericMethods; + public static void RegisterAssembly(Assembly assembly) + { + // UnitTests re-register over and over, safe to skip if already added. + if (m_registerdAssemblies.ContainsKey(assembly)) + { + return; + } + + m_registerdAssemblies.GetOrAdd(assembly, true); + + // Fail programs that register after we started serializing values. + if (s_allMethods.IsValueCreated) + { + throw new InvalidOperationException("Cannot register assemblies dynamically after the first value is serialized."); + } + } + static JSValueReaderGenerator() { + m_registerdAssemblies.GetOrAdd(s_currentAssembly, true); + // Get all extension ReadValue methods for IJSValueReader and JSValue. // The first parameter must be IJSValueReader or JSValue. // The second parameter must be an 'out' parameter and must not be a generic parameter T. @@ -28,20 +52,21 @@ static JSValueReaderGenerator() s_allMethods = new Lazy[]>(() => { var extensionMethods = - from type in typeof(JSValueReader).GetTypeInfo().Assembly.GetTypes() - let typeInfo = type.GetTypeInfo() - where typeInfo.IsSealed && !typeInfo.IsGenericType && !typeInfo.IsNested - from member in type.GetMember(nameof(JSValueReader.ReadValue), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) - let method = member as MethodInfo - where (method != null) && method.IsDefined(typeof(ExtensionAttribute), inherit: false) - let parameters = method.GetParameters() - where parameters.Length == 2 - && (parameters[0].ParameterType == typeof(IJSValueReader) - || parameters[0].ParameterType == typeof(JSValue)) - && parameters[1].IsOut - let dataType = parameters[1].ParameterType.GetElementType() - where !dataType.IsGenericParameter - select new KeyValuePair(dataType, method); + from assembly in m_registerdAssemblies.Keys + from type in assembly.GetTypes() + let typeInfo = type.GetTypeInfo() + where typeInfo.IsSealed && !typeInfo.IsGenericType && !typeInfo.IsNested + from member in type.GetMember(nameof(JSValueReader.ReadValue), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) + let method = member as MethodInfo + where (method != null) && method.IsDefined(typeof(ExtensionAttribute), inherit: false) + let parameters = method.GetParameters() + where parameters.Length == 2 + && (parameters[0].ParameterType == typeof(IJSValueReader) + || parameters[0].ParameterType == typeof(JSValue)) + && parameters[1].IsOut + let dataType = parameters[1].ParameterType.GetElementType() + where !dataType.IsGenericParameter + select new KeyValuePair(dataType, method); return extensionMethods.ToArray(); }); @@ -59,15 +84,15 @@ from member in type.GetMember(nameof(JSValueReader.ReadValue), BindingFlags.Stat { var genericMethods = from pair in s_allMethods.Value - where pair.Value.IsGenericMethod - let type = pair.Key - let keyType = type.GetTypeInfo().IsGenericType ? type.GetGenericTypeDefinition() - : type.IsArray ? typeof(Array) - : throw new InvalidOperationException($"Unsupported argument type {type}") - group pair by keyType into g - select new KeyValuePair>( - g.Key, new SortedList( - g.ToDictionary(p => p.Key, p => p.Value), GenericTypeComparer.Default)); + where pair.Value.IsGenericMethod + let type = pair.Key + let keyType = type.GetTypeInfo().IsGenericType ? type.GetGenericTypeDefinition() + : type.IsArray ? typeof(Array) + : throw new InvalidOperationException($"Unsupported argument type {type}") + group pair by keyType into g + select new KeyValuePair>( + g.Key, new SortedList( + g.ToDictionary(p => p.Key, p => p.Value), GenericTypeComparer.Default)); return genericMethods.ToDictionary(p => p.Key, p => p.Value); }); } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/JSValueTreeReader.cs b/vnext/Microsoft.ReactNative.SharedManaged/JSValueTreeReader.cs index 7dfde232905..b1688594d40 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/JSValueTreeReader.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/JSValueTreeReader.cs @@ -5,7 +5,7 @@ namespace Microsoft.ReactNative.Managed { - class JSValueTreeReader : IJSValueReader, IJSValueTreeReader + public class JSValueTreeReader : IJSValueReader, IJSValueTreeReader { private bool m_isIterating = false; private readonly Stack m_stack = new Stack(); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/JSValueTreeWriter.cs b/vnext/Microsoft.ReactNative.SharedManaged/JSValueTreeWriter.cs index a18f0142636..01f3959d7c0 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/JSValueTreeWriter.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/JSValueTreeWriter.cs @@ -7,7 +7,7 @@ namespace Microsoft.ReactNative.Managed { - class JSValueTreeWriter : IJSValueWriter + public class JSValueTreeWriter : IJSValueWriter { private State m_state = State.Start; private readonly Stack m_stack = new Stack(); @@ -166,7 +166,7 @@ public void WriteArrayEnd() private enum State { Start, PropertyName, PropertyValue, Array, Finish }; - class StackEntry + private class StackEntry { public State State; public object Dynamic; diff --git a/vnext/Microsoft.ReactNative.SharedManaged/JSValueWriter.cs b/vnext/Microsoft.ReactNative.SharedManaged/JSValueWriter.cs index 5ae0aac6667..1abe1efc13a 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/JSValueWriter.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/JSValueWriter.cs @@ -8,9 +8,9 @@ namespace Microsoft.ReactNative.Managed { - delegate void WriteValueDelegate(IJSValueWriter writer, T value); + public delegate void WriteValueDelegate(IJSValueWriter writer, T value); - static class JSValueWriter + public static class JSValueWriter { private static IReadOnlyDictionary s_writerDelegates = new Dictionary(); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/JSValueWriterGenerator.cs b/vnext/Microsoft.ReactNative.SharedManaged/JSValueWriterGenerator.cs index 4447b32bf8c..3c9553a1876 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/JSValueWriterGenerator.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/JSValueWriterGenerator.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; @@ -12,14 +13,38 @@ namespace Microsoft.ReactNative.Managed { - static class JSValueWriterGenerator + public static class JSValueWriterGenerator { + // The current assembly to ensure we always register the basic type readers + private static readonly Assembly s_currentAssembly = typeof(JSValueReaderGenerator).Assembly; + + private static readonly ConcurrentDictionary m_registerdAssemblies = new ConcurrentDictionary(); + private static readonly Lazy[]> s_allMethods; private static readonly Lazy> s_nonGenericMethods; private static readonly Lazy>> s_genericMethods; + public static void RegisterAssembly(Assembly assembly) + { + // UnitTests re-register over and over, safe to skip if already added. + if (m_registerdAssemblies.ContainsKey(assembly)) + { + return; + } + + m_registerdAssemblies.GetOrAdd(assembly, true); + + // Fail programs that register after we started serializing values. + if (s_allMethods.IsValueCreated) + { + throw new InvalidOperationException("Cannot register assemblies dynamically after the first value is serialized."); + } + } + static JSValueWriterGenerator() { + m_registerdAssemblies.GetOrAdd(s_currentAssembly, true); + // Get all extension WriteValue methods for IJSValueWriter. // The first parameter must be IJSValueWriter. // The second parameter must be not a generic parameter T. @@ -28,7 +53,8 @@ static JSValueWriterGenerator() s_allMethods = new Lazy[]>(() => { var extensionMethods = - from type in typeof(JSValueWriter).GetTypeInfo().Assembly.GetTypes() + from assembly in m_registerdAssemblies.Keys + from type in assembly.GetTypes() let typeInfo = type.GetTypeInfo() where typeInfo.IsSealed && !typeInfo.IsGenericType && !typeInfo.IsNested from member in type.GetMember(nameof(JSValueWriter.WriteValue), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) @@ -223,7 +249,7 @@ from field in valueType.GetFields(BindingFlags.Public | BindingFlags.Instance) var properties = from property in valueType.GetProperties(BindingFlags.Public | BindingFlags.Instance) let propertySetter = property.SetMethod - where propertySetter.IsPublic + where propertySetter != null && propertySetter.IsPublic select new { property.Name, Type = property.PropertyType }; var members = fields.Concat(properties).ToArray(); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems b/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems index 49a4f0ca31b..96d2da47780 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems +++ b/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems @@ -39,6 +39,7 @@ + diff --git a/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.shproj b/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.shproj index 4c511a40948..6790c46e71c 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.shproj +++ b/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.shproj @@ -1,5 +1,6 @@ - + 67a1076f-7790-4203-86ea-4402ccb5e782 16.0 diff --git a/vnext/Microsoft.ReactNative.SharedManaged/OneOf.cs b/vnext/Microsoft.ReactNative.SharedManaged/OneOf.cs index b1e793f3c58..63a84e612ad 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/OneOf.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/OneOf.cs @@ -7,7 +7,7 @@ namespace Microsoft.ReactNative.Managed { - struct OneOf1 + public struct OneOf1 { public OneOf1(T1 value) { @@ -26,7 +26,7 @@ public bool TryGet(out T value) } } - struct OneOf2 + public struct OneOf2 { public OneOf2(T1 value) { @@ -51,7 +51,7 @@ public bool TryGet(out T value) } } - struct OneOf3 + public struct OneOf3 { public OneOf3(T1 value) { @@ -82,7 +82,7 @@ public bool TryGet(out T value) } } - struct OneOf4 + public struct OneOf4 { public OneOf4(T1 value) { @@ -119,7 +119,7 @@ public bool TryGet(out T value) } } - struct OneOf5 + public struct OneOf5 { public OneOf5(T1 value) { @@ -162,7 +162,7 @@ public bool TryGet(out T value) } } - struct OneOf6 + public struct OneOf6 { public OneOf6(T1 value) { @@ -211,7 +211,7 @@ public bool TryGet(out T value) } } - struct OneOf7 + public struct OneOf7 { public OneOf7(T1 value) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactAttributes.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactAttributes.cs index d42b209985c..d2399e4d999 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactAttributes.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactAttributes.cs @@ -6,7 +6,7 @@ namespace Microsoft.ReactNative.Managed { [AttributeUsage(AttributeTargets.Class)] - class ReactModuleAttribute : Attribute + public class ReactModuleAttribute : Attribute { public ReactModuleAttribute(string moduleName = null) { @@ -19,12 +19,12 @@ public ReactModuleAttribute(string moduleName = null) } [AttributeUsage(AttributeTargets.Method)] - class ReactInitializerAttribute : Attribute + public class ReactInitializerAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] - class ReactConstantAttribute : Attribute + public class ReactConstantAttribute : Attribute { public ReactConstantAttribute(string constantName = null) { @@ -36,12 +36,12 @@ public ReactConstantAttribute(string constantName = null) [AttributeUsage(AttributeTargets.Method)] - class ReactConstantProviderAttribute : Attribute + public class ReactConstantProviderAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method)] - class ReactMethodAttribute : Attribute + public class ReactMethodAttribute : Attribute { public ReactMethodAttribute(string methodName = null) { @@ -52,7 +52,7 @@ public ReactMethodAttribute(string methodName = null) } [AttributeUsage(AttributeTargets.Method)] - class ReactSyncMethodAttribute : Attribute + public class ReactSyncMethodAttribute : Attribute { public ReactSyncMethodAttribute(string methodName = null) { @@ -63,7 +63,7 @@ public ReactSyncMethodAttribute(string methodName = null) } [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] - class ReactEventAttribute : Attribute + public class ReactEventAttribute : Attribute { public ReactEventAttribute(string eventName = null) { @@ -76,7 +76,7 @@ public ReactEventAttribute(string eventName = null) } [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] - class ReactFunctionAttribute : Attribute + public class ReactFunctionAttribute : Attribute { public ReactFunctionAttribute(string functionName = null) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantInfo.cs index d052abbc8cc..bd313f74b9c 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantInfo.cs @@ -10,7 +10,7 @@ namespace Microsoft.ReactNative.Managed { - class ReactConstantInfo + internal class ReactConstantInfo { public ReactConstantInfo(PropertyInfo propertyInfo, ReactConstantAttribute constantAttribute) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs index 2d6a048cb79..ab4a1ebc946 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs @@ -3,7 +3,7 @@ namespace Microsoft.ReactNative.Managed { - struct ReactConstantProvider + public struct ReactConstantProvider { public ReactConstantProvider(IJSValueWriter writer) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProviderInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProviderInfo.cs index 799f85296c8..6d3ac3e67b7 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProviderInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProviderInfo.cs @@ -9,7 +9,7 @@ namespace Microsoft.ReactNative.Managed { - class ReactConstantProviderInfo + internal class ReactConstantProviderInfo { public ReactConstantProviderInfo(MethodInfo methodInfo) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs index bfd8098550f..35bc1bffc59 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs @@ -5,7 +5,7 @@ namespace Microsoft.ReactNative.Managed { - struct ReactContext + public struct ReactContext { public ReactContext(IReactContext context) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs index 4b02ba12b41..3adfe9d007e 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs @@ -8,7 +8,7 @@ namespace Microsoft.ReactNative.Managed { - static class ReactContextGenerator + public static class ReactContextGenerator { private static MethodInfo GetMethod(string methodName, Type[] typeArgs, params Type[] requiredArgTypes) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs index 858fc886069..8ec994db2dc 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs @@ -11,7 +11,7 @@ namespace Microsoft.ReactNative.Managed { - class ReactEventInfo + internal class ReactEventInfo { public ReactEventInfo(PropertyInfo propertyInfo, ReactEventAttribute eventAttribute, string eventEmitterName) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactException.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactException.cs index eeb61f34a66..100d729d2fe 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactException.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactException.cs @@ -5,7 +5,7 @@ namespace Microsoft.ReactNative.Managed { - class ReactException : Exception + public class ReactException : Exception { public ReactException() { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs index 777ef64f0bf..f472ff35260 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs @@ -11,7 +11,7 @@ namespace Microsoft.ReactNative.Managed { - class ReactFunctionInfo + internal class ReactFunctionInfo { public ReactFunctionInfo(PropertyInfo propertyInfo, ReactFunctionAttribute functionAttribute, string moduleName) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs index 9e8c23cd2c7..5005e9e5136 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs @@ -10,7 +10,7 @@ namespace Microsoft.ReactNative.Managed { - class ReactInitializerInfo + internal class ReactInitializerInfo { public ReactInitializerInfo(MethodInfo methodInfo) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactMethodInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactMethodInfo.cs index ec7d19d77f8..7070a3f3845 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactMethodInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactMethodInfo.cs @@ -11,7 +11,7 @@ namespace Microsoft.ReactNative.Managed { - class ReactMethodInfo + internal class ReactMethodInfo { public ReactMethodInfo(MethodInfo methodInfo, ReactMethodAttribute methodAttribute) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactModuleInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactModuleInfo.cs index 2e5dd2bf8aa..76a8701ab58 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactModuleInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactModuleInfo.cs @@ -9,7 +9,7 @@ namespace Microsoft.ReactNative.Managed { - class ReactModuleInfo + public class ReactModuleInfo { private static readonly object s_moduleInfoMutex = new object(); private static Dictionary s_moduleInfos; diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactPackageBuilderExtensions.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactPackageBuilderExtensions.cs index 5c2d5c80449..b891b3a76bf 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactPackageBuilderExtensions.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactPackageBuilderExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -9,8 +10,19 @@ namespace Microsoft.ReactNative.Managed { - static class ReactPackageBuilderExtensions + public static class ReactPackageBuilderExtensions { + private static readonly Assembly s_currentAssembly = typeof(ReactPackageBuilderExtensions).Assembly; + + /// + /// This caches for each assembly (keyed on location + /// + /// + /// We use concurrentDictionary instead of ConcurrentBag due to it's performance charateristics. + /// + private static readonly ConcurrentDictionary>> s_registeredAssemblies = + new ConcurrentDictionary>>(); + struct AttributedModule { public Type ModuleType; @@ -23,41 +35,60 @@ public void AddToPackageBuilder(IReactPackageBuilder packageBuilder) } } - private static readonly Lazy> m_attributedModules = - new Lazy>(InitAttributedModules, LazyThreadSafetyMode.PublicationOnly); - - private static Dictionary InitAttributedModules() + private static Dictionary InitAttributedModules(Assembly assembly) { var initializers = - from typeInfo in typeof(ReactPackageBuilderExtensions).GetTypeInfo().Assembly.DefinedTypes + from typeInfo in assembly.DefinedTypes let moduleAttribute = typeInfo.GetCustomAttribute() where moduleAttribute != null select new AttributedModule { ModuleType = typeInfo.AsType(), ModuleAttribute = moduleAttribute }; return initializers.ToDictionary(m => ReactModuleInfo.GetModuleName(m.ModuleType, m.ModuleAttribute)); } - public static void AddAttributedModules(this IReactPackageBuilder packageBuilder) + /// + /// This method registered the attributed models for the given assembly via reflection to the package builder. + /// + public static void AddAttributedModules(this IReactPackageBuilder packageBuilder, Assembly assembly) { - foreach (var attributedModule in m_attributedModules.Value) + var attributedModules = s_registeredAssemblies.GetOrAdd(assembly, asm => new Lazy>(() => InitAttributedModules(asm))); + foreach (var attributedModule in attributedModules.Value.Values) { - attributedModule.Value.AddToPackageBuilder(packageBuilder); + attributedModule.AddToPackageBuilder(packageBuilder); } } + /// + /// Adds the attributed models for the current assembly via reflection to the package builder. + /// + /// + /// This method will be obsolete soon. It should only be called by existing generated project that still use the `Microsoft.ReactNative.SharedManaged` project + /// where s_currentAssembly will reflect the users assembly that compiles this code as well. + /// + public static void AddAttributedModules(this IReactPackageBuilder packageBuilder) + { + AddAttributedModules(packageBuilder, s_currentAssembly); + } + public static bool TryAddAttributedModule(this IReactPackageBuilder packageBuilder, string moduleName) { - if (m_attributedModules.Value.TryGetValue(moduleName, out var attributedModule)) + if (s_registeredAssemblies.TryGetValue(s_currentAssembly, out var attributedModules)) { - attributedModule.AddToPackageBuilder(packageBuilder); - return true; + if (attributedModules.Value.TryGetValue(moduleName, out var attributedModule)) + { + attributedModule.AddToPackageBuilder(packageBuilder); + return true; + } } return false; } - internal static void AddViewManagers(this IReactPackageBuilder packageBuilder) + /// + /// Adds the view managers defined in the given assembly via reflection to the package builder. + /// + public static void AddViewManagers(this IReactPackageBuilder packageBuilder, Assembly assembly) { - foreach (var typeInfo in typeof(ReactPackageBuilderExtensions).GetTypeInfo().Assembly.DefinedTypes) + foreach (var typeInfo in assembly.DefinedTypes) { if (!typeInfo.IsAbstract && typeInfo.ImplementedInterfaces.Contains(typeof(IViewManager))) { @@ -65,5 +96,17 @@ internal static void AddViewManagers(this IReactPackageBuilder packageBuilder) } } } + + /// + /// Adds the view manages in the given assembly via reflection to the package builder. + /// + /// + /// This method will be obsolete soon. It should only be called by existing generated project that still use the `Microsoft.ReactNative.SharedManaged` project + /// where s_currentAssembly will reflect the users assembly that compiles this code as well. + /// + public static void AddViewManagers(this IReactPackageBuilder packageBuilder) + { + AddViewManagers(packageBuilder, s_currentAssembly); + } } } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactPackageProvider.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactPackageProvider.cs index 8c8fce10764..a97bbf310b9 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactPackageProvider.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactPackageProvider.cs @@ -3,12 +3,14 @@ namespace Microsoft.ReactNative.Managed { - class ReactPackageProvider : IReactPackageProvider - { - public void CreatePackage(IReactPackageBuilder packageBuilder) + /// + /// This provider needs to remain for projects that still reference this code via a source package instead of a library. + /// + public class ReactPackageProvider : IReactPackageProvider { - packageBuilder.AddAttributedModules(); - packageBuilder.AddViewManagers(); + public void CreatePackage(IReactPackageBuilder packageBuilder) + { + packageBuilder.AddReflectionReactPackageProvider(); + } } - } } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactPromise.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactPromise.cs index 5ce8924e8bd..be7d70990a6 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactPromise.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactPromise.cs @@ -21,7 +21,7 @@ namespace Microsoft.ReactNative.Managed // // Methods with ReactMethodAttribute that use an IReactPromise as the last parameter // will be marked as "promise" and will return a promise when invoked from JavaScript. - class ReactPromise : IReactPromise + public class ReactPromise : IReactPromise { private static readonly string ErrorDefaultCode = "EUNSPECIFIED"; private static readonly string ErrorDefaultMessage = "Error not specified."; diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactSyncMethodInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactSyncMethodInfo.cs index b423cfb8866..a4e048ae5cd 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactSyncMethodInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactSyncMethodInfo.cs @@ -10,7 +10,7 @@ namespace Microsoft.ReactNative.Managed { - class ReactSyncMethodInfo + internal class ReactSyncMethodInfo { public ReactSyncMethodInfo(MethodInfo methodInfo, ReactSyncMethodAttribute methodAttribute) { diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReflectionReactPackageProvider.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReflectionReactPackageProvider.cs new file mode 100644 index 00000000000..6df083337d3 --- /dev/null +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReflectionReactPackageProvider.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.ReactNative; + +namespace Microsoft.ReactNative.Managed +{ + /// + /// A default implementation that uses reflection to extract the Modules and ViewManagers + /// to be registered on the package builder. + /// + /// This must be thea type defined in the assembly where the items for the react package should be extracted. + /// + /// The common use case of this type is adding this to the PackageProviders from the constructor of your application (say: in App() of App.g.cs) like PackageProviders.Add(new ReflectionReactPackageProvider());. + /// + public class ReflectionReactPackageProvider : IReactPackageProvider + { + public virtual void CreatePackage(IReactPackageBuilder packageBuilder) + { + ReflectionReactPackageProviderExtensions.AddReflectionReactPackageProvider(packageBuilder); + } + } + + /// + /// Extensions for registring a reflection based package provider + /// + public static class ReflectionReactPackageProviderExtensions + { + /// + /// Helper extension method to register a reflection + /// + /// This must be thea type defined in the assembly where the items for the react package should be extracted. + /// + /// The common use case of this type is when you have a react library. Then you would call this from the function in ReactPackageProvider class that implements like: + /// public sealed class ReactPackageProvider : IReactPackageProvider + /// { + /// public void CreatePackage(IReactPackageBuilder packageBuilder) + /// { + /// packageBuilder.AddReflectionReactPackageProvider(); + /// } + /// } + /// . + /// + public static void AddReflectionReactPackageProvider(this IReactPackageBuilder packageBuilder) + { + var assembly = typeof(T).Assembly; + + packageBuilder.AddAttributedModules(assembly); + packageBuilder.AddViewManagers(assembly); + JSValueReaderGenerator.RegisterAssembly(assembly); + JSValueWriterGenerator.RegisterAssembly(assembly); + } + } +} diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ViewManagerAttributes.cs b/vnext/Microsoft.ReactNative.SharedManaged/ViewManagerAttributes.cs index 489ee54cd3c..0a92f710551 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ViewManagerAttributes.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ViewManagerAttributes.cs @@ -6,7 +6,7 @@ namespace Microsoft.ReactNative.Managed { [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] - internal class ViewManagerExportedViewConstantAttribute : Attribute + public class ViewManagerExportedViewConstantAttribute : Attribute { public string ConstantName { get; set; } @@ -19,7 +19,7 @@ public ViewManagerExportedViewConstantAttribute(string constantName) } [AttributeUsage(AttributeTargets.Method)] - internal class ViewManagerPropertyAttribute : Attribute + public class ViewManagerPropertyAttribute : Attribute { public string PropertyName { get; set; } @@ -39,7 +39,7 @@ public ViewManagerPropertyAttribute(string propertyName, ViewManagerPropertyType } [AttributeUsage(AttributeTargets.Method)] - internal class ViewManagerCommandAttribute : Attribute + public class ViewManagerCommandAttribute : Attribute { public string CommandName { get; set; } @@ -51,7 +51,7 @@ public ViewManagerCommandAttribute(string commandName) } } - internal class ViewManagerExportedDirectEventTypeConstantAttribute : Attribute + public class ViewManagerExportedDirectEventTypeConstantAttribute : Attribute { public string EventName { get; private set; } @@ -67,7 +67,7 @@ public ViewManagerExportedDirectEventTypeConstantAttribute(string eventName, str } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] - internal class ViewManagerExportedBubblingEventTypeConstantAttribute : Attribute + public class ViewManagerExportedBubblingEventTypeConstantAttribute : Attribute { public string EventName { get; private set; } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ViewManagerEvent.cs b/vnext/Microsoft.ReactNative.SharedManaged/ViewManagerEvent.cs index b77e4635351..a1ff4c46bda 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ViewManagerEvent.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ViewManagerEvent.cs @@ -5,5 +5,5 @@ namespace Microsoft.ReactNative.Managed { - internal delegate void ViewManagerEvent(TFrameworkElement view, TEventData eventData) where TFrameworkElement : FrameworkElement; + public delegate void ViewManagerEvent(TFrameworkElement view, TEventData eventData) where TFrameworkElement : FrameworkElement; } diff --git a/vnext/Microsoft.ReactNative.sln b/vnext/Microsoft.ReactNative.sln index ee46a960a52..51e87ddc0dd 100644 --- a/vnext/Microsoft.ReactNative.sln +++ b/vnext/Microsoft.ReactNative.sln @@ -21,6 +21,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx.U EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", "Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems", "{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ReactNative.Managed", "Microsoft.ReactNative.Managed\Microsoft.ReactNative.Managed.csproj", "{F2824844-CE15-4242-9420-308923CD76C3}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ReactNative.Managed.UnitTests", "Microsoft.ReactNative.Managed.UnitTests\Microsoft.ReactNative.Managed.UnitTests.csproj", "{46D76F7A-8FD9-4A7D-8102-2857E5DA6B84}" EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Microsoft.ReactNative.SharedManaged", "Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.shproj", "{67A1076F-7790-4203-86EA-4402CCB5E782}" @@ -118,7 +120,6 @@ Global JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 Mso\Mso.vcxitems*{1958ceaa-fbe0-44e3-8a99-90ad85531ffe}*SharedItemsImports = 4 Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 - Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{46d76f7a-8fd9-4a7d-8102-2857e5da6b84}*SharedItemsImports = 4 Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{67a1076f-7790-4203-86ea-4402ccb5e782}*SharedItemsImports = 13 Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{6c60e295-c8ca-4dc5-b8be-09888f58b249}*SharedItemsImports = 4 Mso\Mso.vcxitems*{6c60e295-c8ca-4dc5-b8be-09888f58b249}*SharedItemsImports = 4 @@ -280,6 +281,22 @@ Global {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.Build.0 = Release|x64 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.ActiveCfg = Release|Win32 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.Build.0 = Release|Win32 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.ActiveCfg = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.Build.0 = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.Build.0 = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.ActiveCfg = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.Build.0 = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.ActiveCfg = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.Build.0 = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.ActiveCfg = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.Build.0 = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.ActiveCfg = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.Build.0 = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.ActiveCfg = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.Build.0 = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.ActiveCfg = Release|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vnext/ReactWindows-Universal.sln b/vnext/ReactWindows-Universal.sln index f7e3cc07f31..c82887ef128 100644 --- a/vnext/ReactWindows-Universal.sln +++ b/vnext/ReactWindows-Universal.sln @@ -101,6 +101,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Shared", "Shared\Shared.vcx EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso.UnitTests", "Mso.UnitTests\Mso.UnitTests.vcxproj", "{1958CEAA-FBE0-44E3-8A99-90AD85531FFE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ReactNative.Managed", "Microsoft.ReactNative.Managed\Microsoft.ReactNative.Managed.csproj", "{F2824844-CE15-4242-9420-308923CD76C3}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ReactNative.Managed.UnitTests", "Microsoft.ReactNative.Managed.UnitTests\Microsoft.ReactNative.Managed.UnitTests.csproj", "{46D76F7A-8FD9-4A7D-8102-2857E5DA6B84}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.IntegrationTests", "Microsoft.ReactNative.IntegrationTests\Microsoft.ReactNative.IntegrationTests.vcxproj", "{14FA0516-E6D7-4E4D-B097-1470198C5072}" @@ -117,7 +119,6 @@ Global Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 Mso\Mso.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 Shared\Shared.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 - Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{46d76f7a-8fd9-4a7d-8102-2857e5da6b84}*SharedItemsImports = 4 Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{67a1076f-7790-4203-86ea-4402ccb5e782}*SharedItemsImports = 13 Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{6c60e295-c8ca-4dc5-b8be-09888f58b249}*SharedItemsImports = 4 Mso\Mso.vcxitems*{6c60e295-c8ca-4dc5-b8be-09888f58b249}*SharedItemsImports = 4 @@ -351,6 +352,22 @@ Global {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|x64.Build.0 = Release|x64 {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|x86.ActiveCfg = Release|Win32 {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|x86.Build.0 = Release|Win32 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.ActiveCfg = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.Build.0 = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.Build.0 = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.ActiveCfg = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.Build.0 = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.ActiveCfg = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.Build.0 = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.ActiveCfg = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.Build.0 = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.ActiveCfg = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.Build.0 = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.ActiveCfg = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.Build.0 = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.ActiveCfg = Release|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vnext/Shared/Shared.vcxitems b/vnext/Shared/Shared.vcxitems index ddf60590b25..c426153725d 100644 --- a/vnext/Shared/Shared.vcxitems +++ b/vnext/Shared/Shared.vcxitems @@ -25,4 +25,4 @@ - + \ No newline at end of file From 206b92504b6cc6ed9265f927440a5fe1d2504b09 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Fri, 8 May 2020 00:05:16 +0000 Subject: [PATCH 066/209] applying package updates ***NO_CI*** --- ...ive-win32-2020-05-06-14-34-01-fixfast.json | 8 ------ ...-2020-05-04-19-05-45-OC-4133953-pwrav.json | 8 ------ ...ve-windows-2020-05-05-12-31-18-master.json | 8 ------ ...e-windows-2020-05-06-14-34-01-fixfast.json | 8 ------ packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- packages/react-native-win32/CHANGELOG.json | 15 +++++++++++ packages/react-native-win32/CHANGELOG.md | 10 ++++++- packages/react-native-win32/package.json | 2 +- vnext/CHANGELOG.json | 27 +++++++++++++++++++ vnext/CHANGELOG.md | 12 ++++++++- vnext/package.json | 2 +- 13 files changed, 67 insertions(+), 39 deletions(-) delete mode 100644 change/@office-iss-react-native-win32-2020-05-06-14-34-01-fixfast.json delete mode 100644 change/react-native-windows-2020-05-04-19-05-45-OC-4133953-pwrav.json delete mode 100644 change/react-native-windows-2020-05-05-12-31-18-master.json delete mode 100644 change/react-native-windows-2020-05-06-14-34-01-fixfast.json diff --git a/change/@office-iss-react-native-win32-2020-05-06-14-34-01-fixfast.json b/change/@office-iss-react-native-win32-2020-05-06-14-34-01-fixfast.json deleted file mode 100644 index 5e0b830af9f..00000000000 --- a/change/@office-iss-react-native-win32-2020-05-06-14-34-01-fixfast.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Ensure InitializeCore is run before app code", - "packageName": "@office-iss/react-native-win32", - "email": "acoates@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-06T21:33:58.938Z" -} diff --git a/change/react-native-windows-2020-05-04-19-05-45-OC-4133953-pwrav.json b/change/react-native-windows-2020-05-04-19-05-45-OC-4133953-pwrav.json deleted file mode 100644 index 515ff1a6d51..00000000000 --- a/change/react-native-windows-2020-05-04-19-05-45-OC-4133953-pwrav.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Promote awaitable DispatchQueue callback to member field", - "packageName": "react-native-windows", - "email": "julio.rocha@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-05T02:05:45.427Z" -} diff --git a/change/react-native-windows-2020-05-05-12-31-18-master.json b/change/react-native-windows-2020-05-05-12-31-18-master.json deleted file mode 100644 index 4a323b24011..00000000000 --- a/change/react-native-windows-2020-05-05-12-31-18-master.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Upgrade the shared managed project to a proper csharp library.", - "packageName": "react-native-windows", - "email": "dannyvv@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-05T19:31:18.766Z" -} diff --git a/change/react-native-windows-2020-05-06-14-34-01-fixfast.json b/change/react-native-windows-2020-05-06-14-34-01-fixfast.json deleted file mode 100644 index 566bb7c5451..00000000000 --- a/change/react-native-windows-2020-05-06-14-34-01-fixfast.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Ensure InitializeCore is run before app code", - "packageName": "react-native-windows", - "email": "acoates@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-06T21:34:00.993Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index f34f6988299..2ed34937d60 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.60" + "react-native-windows": "0.0.0-master.61" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 04c85f7d310..1259e9c60c5 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.60" + "react-native-windows": "0.0.0-master.61" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index 6324967e105..b4ad114bc06 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.60" + "react-native-windows": "0.0.0-master.61" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/react-native-win32/CHANGELOG.json b/packages/react-native-win32/CHANGELOG.json index 899eac98310..055afae980e 100644 --- a/packages/react-native-win32/CHANGELOG.json +++ b/packages/react-native-win32/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@office-iss/react-native-win32", "entries": [ + { + "date": "Fri, 08 May 2020 00:05:16 GMT", + "tag": "@office-iss/react-native-win32_v0.0.0-master.9", + "version": "0.0.0-master.9", + "comments": { + "prerelease": [ + { + "comment": "Ensure InitializeCore is run before app code", + "author": "acoates@microsoft.com", + "commit": "6088cb0d6b9291e7877d5b0aefd6f18cb1bace3c", + "package": "@office-iss/react-native-win32" + } + ] + } + }, { "date": "Thu, 07 May 2020 00:05:07 GMT", "tag": "@office-iss/react-native-win32_v0.0.0-master.8", diff --git a/packages/react-native-win32/CHANGELOG.md b/packages/react-native-win32/CHANGELOG.md index 0a9d7ed5851..78a25298698 100644 --- a/packages/react-native-win32/CHANGELOG.md +++ b/packages/react-native-win32/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @office-iss/react-native-win32 -This log was last generated on Thu, 07 May 2020 00:05:07 GMT and should not be manually modified. +This log was last generated on Fri, 08 May 2020 00:05:16 GMT and should not be manually modified. +## 0.0.0-master.9 + +Fri, 08 May 2020 00:05:16 GMT + +### Changes + +- Ensure InitializeCore is run before app code (acoates@microsoft.com) + ## 0.0.0-master.8 Thu, 07 May 2020 00:05:07 GMT diff --git a/packages/react-native-win32/package.json b/packages/react-native-win32/package.json index fca31b52b77..41be5de4059 100644 --- a/packages/react-native-win32/package.json +++ b/packages/react-native-win32/package.json @@ -1,6 +1,6 @@ { "name": "@office-iss/react-native-win32", - "version": "0.0.0-master.8", + "version": "0.0.0-master.9", "description": "Implementation of react native on top of Office's Win32 platform.", "license": "MIT", "main": "./index.win32.js", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index fdaadb1c5f3..7927c055f3a 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,33 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Fri, 08 May 2020 00:05:16 GMT", + "tag": "react-native-windows_v0.0.0-master.61", + "version": "0.0.0-master.61", + "comments": { + "prerelease": [ + { + "comment": "Promote awaitable DispatchQueue callback to member field", + "author": "julio.rocha@microsoft.com", + "commit": "04583378bd66c2d473a804c5e7cb663596e1a4be", + "package": "react-native-windows" + }, + { + "comment": "Upgrade the shared managed project to a proper csharp library.", + "author": "dannyvv@microsoft.com", + "commit": "605e3f8dc651706cfafbb4f21931bcbc03a9f140", + "package": "react-native-windows" + }, + { + "comment": "Ensure InitializeCore is run before app code", + "author": "acoates@microsoft.com", + "commit": "6088cb0d6b9291e7877d5b0aefd6f18cb1bace3c", + "package": "react-native-windows" + } + ] + } + }, { "date": "Thu, 07 May 2020 00:05:07 GMT", "tag": "react-native-windows_v0.0.0-master.60", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index e5d1931c2c7..167bacae0a2 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,19 @@ # Change Log - react-native-windows -This log was last generated on Thu, 07 May 2020 00:05:07 GMT and should not be manually modified. +This log was last generated on Fri, 08 May 2020 00:05:16 GMT and should not be manually modified. +## 0.0.0-master.61 + +Fri, 08 May 2020 00:05:16 GMT + +### Changes + +- Promote awaitable DispatchQueue callback to member field (julio.rocha@microsoft.com) +- Upgrade the shared managed project to a proper csharp library. (dannyvv@microsoft.com) +- Ensure InitializeCore is run before app code (acoates@microsoft.com) + ## 0.0.0-master.60 Thu, 07 May 2020 00:05:07 GMT diff --git a/vnext/package.json b/vnext/package.json index 9f3d78d6d33..747dc6f7adc 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.60", + "version": "0.0.0-master.61", "license": "MIT", "repository": { "type": "git", From 082b57fe338378d03d00134d0628caa4d944fe4d Mon Sep 17 00:00:00 2001 From: dannyvv Date: Thu, 7 May 2020 19:42:54 -0700 Subject: [PATCH 067/209] Set C# langversion of templates back to 7.3 from 8.0 (#4828) * Set C# langversion of templates back to 7.3 from 8.0 * Change files --- .../react-native-windows-2020-05-07-17-34-52-master.json | 8 ++++++++ .../windows/SampleAppCS/SampleAppCS.csproj | 2 +- .../windows/SampleLibraryCS/SampleLibraryCS.csproj | 2 +- .../generator-windows/templates/cs/proj/MyApp.csproj | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 change/react-native-windows-2020-05-07-17-34-52-master.json diff --git a/change/react-native-windows-2020-05-07-17-34-52-master.json b/change/react-native-windows-2020-05-07-17-34-52-master.json new file mode 100644 index 00000000000..3a3b1e84193 --- /dev/null +++ b/change/react-native-windows-2020-05-07-17-34-52-master.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Set C# langversion of templates back to 7.3 from 8.0", + "packageName": "react-native-windows", + "email": "dannyvv@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-08T00:34:52.261Z" +} diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/SampleAppCS.csproj b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/SampleAppCS.csproj index 51a0edd703a..47686e19670 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/SampleAppCS.csproj +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/SampleAppCS.csproj @@ -20,7 +20,7 @@ true false false - 8.0 + 7.3 true diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleLibraryCS.csproj b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleLibraryCS.csproj index 03bc1a7e219..e77c4c5f3da 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleLibraryCS.csproj +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleLibraryCS.csproj @@ -19,7 +19,7 @@ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} false false - 8.0 + 7.3 x86 diff --git a/vnext/local-cli/generator-windows/templates/cs/proj/MyApp.csproj b/vnext/local-cli/generator-windows/templates/cs/proj/MyApp.csproj index e7010aff763..40c12f5b5a1 100644 --- a/vnext/local-cli/generator-windows/templates/cs/proj/MyApp.csproj +++ b/vnext/local-cli/generator-windows/templates/cs/proj/MyApp.csproj @@ -21,6 +21,7 @@ <%=certificateThumbprint%> password false + 7.3 $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ From c51c3ad85dd7bce29c47ecffc861106b97f0d6f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20C=C3=A9sar=20Rocha?= Date: Thu, 7 May 2020 21:07:02 -0700 Subject: [PATCH 068/209] Correct WebSocket binary message tagging (#4829) * Correct binary message tagging * Change files --- ...ative-windows-2020-05-07-18-29-02-enable-binaryws.json | 8 ++++++++ vnext/ReactWindowsCore/WinRTWebSocketResource.cpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 change/react-native-windows-2020-05-07-18-29-02-enable-binaryws.json diff --git a/change/react-native-windows-2020-05-07-18-29-02-enable-binaryws.json b/change/react-native-windows-2020-05-07-18-29-02-enable-binaryws.json new file mode 100644 index 00000000000..0281eb0cf82 --- /dev/null +++ b/change/react-native-windows-2020-05-07-18-29-02-enable-binaryws.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Correct binary message tagging", + "packageName": "react-native-windows", + "email": "julio.rocha@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-08T01:29:02.376Z" +} diff --git a/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp b/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp index e88efbdf448..b54dfd69eaa 100644 --- a/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp +++ b/vnext/ReactWindowsCore/WinRTWebSocketResource.cpp @@ -391,7 +391,7 @@ void WinRTWebSocketResource::Send(const string& message) void WinRTWebSocketResource::SendBinary(const string& base64String) { - m_writeQueue.push({ base64String, false }); + m_writeQueue.push({ base64String, true }); PerformWrite(); } From e3aa341e368efbc7465665711685ec167c9790e6 Mon Sep 17 00:00:00 2001 From: Harini Kannan Date: Thu, 7 May 2020 22:58:42 -0700 Subject: [PATCH 069/209] Update README.md (#4826) Updating main landing page readme: - Cleaning up some obsolete references (reactiflux channel etc.,) - Added Contents and reorganized sections - Simplified text and matched to the latest updates done to the macos repo so they look a bit more unified. --- README.md | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 5145a32ee2f..1bf45cb1191 100644 --- a/README.md +++ b/README.md @@ -24,52 +24,51 @@ This repository adds support for the [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads), which allows you to build apps for [all devices supported by Windows 10](https://developer.microsoft.com/en-us/windows/get-started-windows-10) including PCs, tablets, 2-in-1s, Xbox, Mixed reality devices etc. -## Status and roadmap -[Check out our blog](https://microsoft.github.io/react-native-windows/blog/) If you'd like to stay up to date on the status of React Native for Windows and check out current and past roadmaps, We will post all new releases, updates and general news about the project there. +Visit the official [React Native for Windows & Mac website](https://microsoft.github.io/react-native-windows) to learn more. -## System Requirements +## Contents -You can run React Native Windows UWP apps only on Windows 10 devices. +- [Requirements](#requirements) +- [Getting Started](#getting-started) +- [Contributing](#contributing) +- [Documentation](#documentation) +- [License](#license) +- [Code of Conduct](#code-of-conduct) -For a full and detailed list of the system requirements and how to set up your development platform, see our [System Requirements](https://microsoft.github.io/react-native-windows/docs/rnw-dependencies) documentation on our website. +### Status and roadmap +[Check out our blog](https://microsoft.github.io/react-native-windows/blog/) if you'd like to stay up to date on the status of React Native for Windows and check out current and past roadmaps. We will post all new releases, updates and general news about the project there. -## Documentation -[React Native already has great documentation](https://reactnative.dev/docs/getting-started.html) and we're working to ensure the React Native Windows is part of that documentation story. - -[React Native for Windows](https://microsoft.github.io/react-native-windows/) has it's own separate documentation site where Windows and Mac specific information, like API docs and blog updates live. +## Requirements +You can run React Native Windows apps only on devices supported by the [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads). -## Get Started -See the [Getting Started Guide](https://microsoft.github.io/react-native-windows/docs/getting-started) on our React Native for Windows website. - -## Need Help? - -Come join us and chat on the [Reactiflux](https://discord.gg/0ZcbPKXt5bWJVmUY) Discord server under in **#react-native** +For a full and detailed list of the system requirements and how to set up your development platform, see our [System Requirements](https://microsoft.github.io/react-native-windows/docs/rnw-dependencies) documentation on our website. -If it turns out that you may have found a bug, we would like to hear about it! +## Getting Started +See the [Getting Started Guide](https://microsoft.github.io/react-native-windows/docs/getting-started) on our React Native for Windows & Mac website to build your first React Native for Windows app. ### Logging Issues Search the [existing issues](https://github.com/microsoft/react-native-windows/issues) and try to make sure your problem doesn’t already exist before opening a new issue. If your issue doesn't exist yet, try to make sure you provide as much information as possible to us so we can help you sooner. It’s helpful if you include information like: -- The version of Windows, React Native, React Native Windows plugin, and device family (i.e., mobile, desktop, Xbox, etc.) where you ran into the issue. +- The version of Windows, React Native, React Native Windows extension, and device family (i.e., mobile, desktop, Xbox, etc.) where you ran into the issue. - A stack trace and reduced repro case when possible. - Ensure the [appropriate template](https://github.com/microsoft/react-native-windows/issues/new/choose) is used when filing your issue(s). -The GitHub issues are intended for bug reports and feature requests. For help and questions with using the React Native Windows plugin please make use of the resources listed our main README's the [Getting Help](https://github.com/microsoft/react-native-windows#getting-help) section. - ## Contributing See [Contributing guidelines](https://github.com/microsoft/react-native-windows/blob/master/docs/contributing.md) for how to setup your fork of the repo and start a PR to contribute to React Native for Windows. [Good First Task](https://github.com/microsoft/react-native-windows/labels/Good%20First%20Task) and [help wanted](https://github.com/microsoft/react-native-windows/labels/help%20wanted) are great starting points for PRs. -### Examples +## Documentation +[React Native already has great documentation](https://reactnative.dev/docs/getting-started.html) and we're working to ensure the React Native Windows is part of that documentation story. + +[React Native for Windows](https://microsoft.github.io/react-native-windows/) has it's own separate documentation site where Windows and Mac specific information, like API docs and blog updates live. +### Examples - Using the CLI in the [Getting Started](https://microsoft.github.io/react-native-windows/docs/getting-started) guide will set you up with a sample React Native for Windows app that you can begin editing right away. - If you're looking for sample code, just browse the RNTester folder in the GitHub web UI ## License - -The React Native Windows plugin, including modifications to the original Facebook source code, and all newly contributed code is provided under the [MIT License](LICENSE). Portions of the React Native Windows plugin derived from React Native are copyright Facebook. +The React Native Windows extension, including modifications to the original Facebook source code, and all newly contributed code is provided under the [MIT License](LICENSE). Portions of the React Native Windows extension derived from React Native are copyright Facebook. ## Code of Conduct - This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. From 951333f6e1bb811daafffc624b740ac7f1d3566f Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Thu, 7 May 2020 23:00:54 -0700 Subject: [PATCH 070/209] Remove V8 and Hermes by default (#4820) * separate desktop from uwp ReactWindowsCore since desktop uses V8 * . * Change files * opt desktop projects into v8 * playground win32 doesnt use desktop dll --- ...-windows-2020-05-07-16-53-49-splitRWC.json | 8 + .../playground/windows/playground-win32.sln | 2 + .../React.Windows.Desktop.DLL.vcxproj | 3 +- ...t.Windows.Desktop.IntegrationTests.vcxproj | 3 +- vnext/Desktop/React.Windows.Desktop.vcxproj | 3 +- .../JSI.Desktop.UnitTests.vcxproj | 3 +- vnext/JSI/Desktop/JSI.Desktop.vcxproj | 5 +- vnext/Microsoft.ReactNative.sln | 2 + vnext/PropertySheets/React.Cpp.props | 2 +- vnext/ReactWindows-Desktop.sln | 5 +- vnext/ReactWindows-Universal.sln | 36 ++- .../ReactWindowsCore-Desktop.vcxproj | 11 + .../ReactWindowsCore-Desktop.vcxproj.filters | 294 ++++++++++++++++++ .../ReactWindowsCore.vcxitems | 259 +++++++++++++++ .../ReactWindowsCore/ReactWindowsCore.vcxproj | 255 +-------------- .../ReactWindowsCore.vcxproj.filters | 6 - .../packages.ReactWindowsCore-Desktop.config | 6 + vnext/ReactWindowsCore/packages.config | 2 - 18 files changed, 620 insertions(+), 285 deletions(-) create mode 100644 change/react-native-windows-2020-05-07-16-53-49-splitRWC.json create mode 100644 vnext/ReactWindowsCore/ReactWindowsCore-Desktop.vcxproj create mode 100644 vnext/ReactWindowsCore/ReactWindowsCore-Desktop.vcxproj.filters create mode 100644 vnext/ReactWindowsCore/ReactWindowsCore.vcxitems create mode 100644 vnext/ReactWindowsCore/packages.ReactWindowsCore-Desktop.config diff --git a/change/react-native-windows-2020-05-07-16-53-49-splitRWC.json b/change/react-native-windows-2020-05-07-16-53-49-splitRWC.json new file mode 100644 index 00000000000..be340025bd0 --- /dev/null +++ b/change/react-native-windows-2020-05-07-16-53-49-splitRWC.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "separate desktop from uwp ReactWindowsCore since desktop uses V8", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-07T23:53:49.455Z" +} diff --git a/packages/playground/windows/playground-win32.sln b/packages/playground/windows/playground-win32.sln index 96253acb397..3339e428ab1 100644 --- a/packages/playground/windows/playground-win32.sln +++ b/packages/playground/windows/playground-win32.sln @@ -42,12 +42,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\..\..\vnext\ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4 ..\..\..\vnext\Chakra\Chakra.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 ..\..\..\vnext\Mso\Mso.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 ..\..\..\vnext\Shared\Shared.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{8b88ffae-4dbc-49a2-afa5-d2477d4ad189}*SharedItemsImports = 4 ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4 + ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM diff --git a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj index 651a667e8ac..c598ae4e5e7 100644 --- a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj +++ b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj @@ -23,6 +23,7 @@ {88BAB0FA-E1AC-4DA7-A30C-F91702A8EADB} React.Windows.Desktop.DLL react-native-win32 + true @@ -133,7 +134,7 @@ {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} - + {11C084A3-A57C-4296-A679-CAC17B603144} diff --git a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj index f0b2cb8e758..44603739225 100644 --- a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj +++ b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj @@ -23,6 +23,7 @@ {E0D269B4-D7F0-4C4E-92CD-B2C06109A2BB} React.Windows.Desktop.IntegrationTests true + true @@ -113,7 +114,7 @@ {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} - + {11C084A3-A57C-4296-A679-CAC17B603144} diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj b/vnext/Desktop/React.Windows.Desktop.vcxproj index a95ef3c358f..41a7846d4fd 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj @@ -33,6 +33,7 @@ C++/WinRT 2 true + true true @@ -178,7 +179,7 @@ {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} - + {11C084A3-A57C-4296-A679-CAC17B603144} diff --git a/vnext/JSI.Desktop.UnitTests/JSI.Desktop.UnitTests.vcxproj b/vnext/JSI.Desktop.UnitTests/JSI.Desktop.UnitTests.vcxproj index 690ef7b7fa4..6dbf207ef0d 100644 --- a/vnext/JSI.Desktop.UnitTests/JSI.Desktop.UnitTests.vcxproj +++ b/vnext/JSI.Desktop.UnitTests/JSI.Desktop.UnitTests.vcxproj @@ -16,6 +16,7 @@ {6f354505-fe3a-4bd2-a9a6-d12bbf37a85c} JSI.Desktop.UnitTests + true @@ -130,7 +131,7 @@ {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} - + {11C084A3-A57C-4296-A679-CAC17B603144} diff --git a/vnext/JSI/Desktop/JSI.Desktop.vcxproj b/vnext/JSI/Desktop/JSI.Desktop.vcxproj index 361386ab7ab..0737e735265 100644 --- a/vnext/JSI/Desktop/JSI.Desktop.vcxproj +++ b/vnext/JSI/Desktop/JSI.Desktop.vcxproj @@ -21,6 +21,7 @@ {17DD1B17-3094-40DD-9373-AC2497932ECA} JSI.Desktop + true @@ -48,14 +49,14 @@ NotUsing - CHAKRACORE_UWP;%(PreprocessorDefinitions) + CHAKRACORE_UWP;%(PreprocessorDefinitions) CHAKRACORE;%(PreprocessorDefinitions) %(AdditionalOptions) /Zc:strictStrings - $(ChakraCoreInclude);$(ChakraCoreDebugInclude);%(AdditionalIncludeDirectories) + $(ChakraCoreInclude);$(ChakraCoreDebugInclude);%(AdditionalIncludeDirectories) ChakraCore.Debugger.Protocol.lib;ChakraCore.Debugger.ProtocolHandler.lib;ChakraCore.Debugger.Service.lib;ChakraCore.lib;%(AdditionalDependencies) diff --git a/vnext/Microsoft.ReactNative.sln b/vnext/Microsoft.ReactNative.sln index 51e87ddc0dd..840c7acbf18 100644 --- a/vnext/Microsoft.ReactNative.sln +++ b/vnext/Microsoft.ReactNative.sln @@ -31,6 +31,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso", "Mso\Mso.vcxitems", " EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso.UnitTests", "Mso.UnitTests\Mso.UnitTests.vcxproj", "{1958CEAA-FBE0-44E3-8A99-90AD85531FFE}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxitems", "{11c084a3-a57c-4296-a679-cac17b603145}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxproj", "{11C084A3-A57C-4296-A679-CAC17B603144}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Shared", "Shared\Shared.vcxitems", "{2049DBE9-8D13-42C9-AE4B-413AE38FFFD0}" diff --git a/vnext/PropertySheets/React.Cpp.props b/vnext/PropertySheets/React.Cpp.props index 264a9a37c7c..2bb87442726 100644 --- a/vnext/PropertySheets/React.Cpp.props +++ b/vnext/PropertySheets/React.Cpp.props @@ -27,7 +27,7 @@ 0.1.6 $(SolutionDir)packages\ReactNative.Hermes.Windows.$(HERMES_Version) - true + false 0.2.7 $(SolutionDir)packages\ReactNative.V8Jsi.Windows.$(V8_Version) diff --git a/vnext/ReactWindows-Desktop.sln b/vnext/ReactWindows-Desktop.sln index 0fdbd8d9cb5..85f6e997614 100644 --- a/vnext/ReactWindows-Desktop.sln +++ b/vnext/ReactWindows-Desktop.sln @@ -9,7 +9,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactCommon", "ReactCommon\ {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxproj", "{11C084A3-A57C-4296-A679-CAC17B603144}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxitems", "{11c084a3-a57c-4296-a679-cac17b603145}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore-Desktop", "ReactWindowsCore\ReactWindowsCore-Desktop.vcxproj", "{11C084A3-A57C-4296-A679-CAC17B603144}" ProjectSection(ProjectDependencies) = postProject {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} EndProjectSection @@ -120,6 +122,7 @@ EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 + ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4 JSI\Shared\JSI.Shared.vcxitems*{17dd1b17-3094-40dd-9373-ac2497932eca}*SharedItemsImports = 4 Mso\Mso.vcxitems*{1958ceaa-fbe0-44e3-8a99-90ad85531ffe}*SharedItemsImports = 4 Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 diff --git a/vnext/ReactWindows-Universal.sln b/vnext/ReactWindows-Universal.sln index c82887ef128..65288035f89 100644 --- a/vnext/ReactWindows-Universal.sln +++ b/vnext/ReactWindows-Universal.sln @@ -14,6 +14,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactCommon", "ReactCommon\ {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxitems", "{11C084A3-A57C-4296-A679-CAC17B603145}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxproj", "{11C084A3-A57C-4296-A679-CAC17B603144}" ProjectSection(ProjectDependencies) = postProject {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} @@ -111,6 +113,8 @@ Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{069986c5-80f3-4a56-af79-f24ebb05941f}*SharedItemsImports = 4 JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 + ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4 + ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603145}*SharedItemsImports = 9 Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{14fa0516-e6d7-4e4d-b097-1470198c5072}*SharedItemsImports = 4 Mso\Mso.vcxitems*{14fa0516-e6d7-4e4d-b097-1470198c5072}*SharedItemsImports = 4 Mso\Mso.vcxitems*{1958ceaa-fbe0-44e3-8a99-90ad85531ffe}*SharedItemsImports = 4 @@ -324,6 +328,22 @@ Global {1958CEAA-FBE0-44E3-8A99-90AD85531FFE}.Release|x64.Build.0 = Release|x64 {1958CEAA-FBE0-44E3-8A99-90AD85531FFE}.Release|x86.ActiveCfg = Release|Win32 {1958CEAA-FBE0-44E3-8A99-90AD85531FFE}.Release|x86.Build.0 = Release|Win32 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.ActiveCfg = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.Build.0 = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.Build.0 = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.ActiveCfg = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.Build.0 = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.ActiveCfg = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.Build.0 = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.ActiveCfg = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.Build.0 = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.ActiveCfg = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.Build.0 = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.ActiveCfg = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.Build.0 = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.ActiveCfg = Release|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.Build.0 = Release|x86 {46D76F7A-8FD9-4A7D-8102-2857E5DA6B84}.Debug|ARM.ActiveCfg = Debug|ARM {46D76F7A-8FD9-4A7D-8102-2857E5DA6B84}.Debug|ARM64.ActiveCfg = Debug|ARM64 {46D76F7A-8FD9-4A7D-8102-2857E5DA6B84}.Debug|x64.ActiveCfg = Debug|x64 @@ -352,22 +372,6 @@ Global {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|x64.Build.0 = Release|x64 {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|x86.ActiveCfg = Release|Win32 {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|x86.Build.0 = Release|Win32 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.ActiveCfg = Debug|ARM - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.Build.0 = Debug|ARM - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.Build.0 = Debug|ARM64 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.ActiveCfg = Debug|x64 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.Build.0 = Debug|x64 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.ActiveCfg = Debug|x86 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.Build.0 = Debug|x86 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.ActiveCfg = Release|ARM - {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.Build.0 = Release|ARM - {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.ActiveCfg = Release|ARM64 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.Build.0 = Release|ARM64 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.ActiveCfg = Release|x64 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.Build.0 = Release|x64 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.ActiveCfg = Release|x86 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vnext/ReactWindowsCore/ReactWindowsCore-Desktop.vcxproj b/vnext/ReactWindowsCore/ReactWindowsCore-Desktop.vcxproj new file mode 100644 index 00000000000..5ff28843410 --- /dev/null +++ b/vnext/ReactWindowsCore/ReactWindowsCore-Desktop.vcxproj @@ -0,0 +1,11 @@ + + + + {11C084A3-A57C-4296-A679-CAC17B603144} + + + true + false + + + \ No newline at end of file diff --git a/vnext/ReactWindowsCore/ReactWindowsCore-Desktop.vcxproj.filters b/vnext/ReactWindowsCore/ReactWindowsCore-Desktop.vcxproj.filters new file mode 100644 index 00000000000..4e5ea03369e --- /dev/null +++ b/vnext/ReactWindowsCore/ReactWindowsCore-Desktop.vcxproj.filters @@ -0,0 +1,294 @@ + + + + + {06a27269-2c1f-418a-9e70-82d17deb7de2} + + + {32892a40-82db-4c1b-9390-5893f9ddbb0b} + + + {afc5d1fe-6d70-4040-a72b-036ffa74a2eb} + + + {81319f88-192e-40cf-bc1c-76a84bf37ccd} + + + {6e20d3aa-721b-4f62-a1aa-ec6af1a114fb} + + + {b8d1b3de-1573-4d49-a26f-99892413a797} + + + {efe7ad3d-598a-4633-a2b7-2de458833b88} + + + {2b4f6cca-9c7e-4bf1-9711-829006f0be1e} + + + {43770517-0df1-4cff-bd30-563b9d0f56e7} + + + {eae44522-b665-4bd2-85f2-8ca26f4ce15f} + + + {8b1364fc-cc9f-4ca9-834b-894849d8b487} + + + + + Source Files\AsyncStorage + + + Source Files\AsyncStorage + + + Source Files\AsyncStorage + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\Modules + + + Source Files\Modules + + + Source Files\Modules + + + Source Files\Modules + + + Source Files\Modules + + + Source Files\Modules + + + Source Files\Modules + + + Source Files\Modules + + + Source Files\Pch + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\Tracing + + + Source Files\Modules + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files\AsyncStorage + + + Header Files\AsyncStorage + + + Header Files\AsyncStorage + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + etw + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files\Modules + + + Header Files\Modules + + + Header Files\Modules + + + Header Files\Modules + + + Header Files\Modules + + + Header Files\Modules + + + Header Files\Modules + + + Header Files + + + Header Files + + + Header Files\Pch + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files\Tracing + + + Header Files\Modules + + + Header Files\Modules + + + Header Files + + + + + etw + + + + \ No newline at end of file diff --git a/vnext/ReactWindowsCore/ReactWindowsCore.vcxitems b/vnext/ReactWindowsCore/ReactWindowsCore.vcxitems new file mode 100644 index 00000000000..13e56fc783b --- /dev/null +++ b/vnext/ReactWindowsCore/ReactWindowsCore.vcxitems @@ -0,0 +1,259 @@ + + + + {11c084a3-a57c-4296-a679-cac17b603145} + StaticLibrary + ReactWindowsCore + true + Windows Store + 10.0 + + + + Debug + ARM + + + Release + ARM + + + Debug + ARM64 + + + Release + ARM64 + + + Debug + x64 + + + Release + x64 + + + Debug + Win32 + + + Release + Win32 + + + WinUI3 + ARM + + + WinUI3 + ARM64 + + + WinUI3 + Win32 + + + WinUI3 + x64 + + + + + + StaticLibrary + + + + + + + + + + + + + + x86-windows + x64-windows + arm-windows + arm64-windows + + + false + {11C084A3-A57C-4296-A679-CAC17B603145} + + + + Use + pch.h + false + true + + + REACTWINDOWS_BUILD; + NOMINMAX; + FOLLY_NO_CONFIG; + WIN32=0; + RN_EXPORT=; + CHAKRACORE; + %(PreprocessorDefinitions) + + USE_HERMES;%(PreprocessorDefinitions) + + $(ReactNativeWindowsDir); + $(ReactNativeWindowsDir)Common; + $(ReactNativeWindowsDir)Shared; + $(ReactNativeWindowsDir)include; + $(ReactNativeWindowsDir)include\ReactWindowsCore; + $(ReactNativeDir)\ReactCommon; + $(ReactNativeDir)\ReactCommon\callinvoker; + $(JSI_Source); + $(ReactNativeWindowsDir)JSI\Shared; + $(ReactNativeWindowsDir)stubs; + $(FollyDir); + $(ReactNativeWindowsDir)\ReactWindowsCore\pch; + $(ReactNativeWindowsDir)\ReactWindowsCore\tracing; + $(ReactNativeWindowsDir)\Mso; + %(AdditionalIncludeDirectories) + + $(HERMES_Package)\installed\$(VcpkgTriplet)\include\;%(AdditionalIncludeDirectories) + /await %(AdditionalOptions) + false + + + false + false + + + $(HERMES_Package)\installed\$(VcpkgTriplet)\lib;%(AdditionalLibraryDirectories) + hermes.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + {fca38f3c-7c73-4c47-be4e-32f77fa8538d} + + + {a990658c-ce31-4bcc-976f-0fc6b1af693d} + + + {a9d95a91-4db7-4f72-beb6-fe8a5c89bfbd} + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + \ No newline at end of file diff --git a/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj b/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj index d861e40d112..ded2311ae69 100644 --- a/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj +++ b/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj @@ -1,258 +1,7 @@ - {11c084a3-a57c-4296-a679-cac17b603144} - StaticLibrary - ReactWindowsCore - true - Windows Store - 10.0 + {11C084A3-A57C-4296-A679-CAC17B603144} - - - Debug - ARM - - - Release - ARM - - - Debug - ARM64 - - - Release - ARM64 - - - Debug - x64 - - - Release - x64 - - - Debug - Win32 - - - Release - Win32 - - - WinUI3 - ARM - - - WinUI3 - ARM64 - - - WinUI3 - Win32 - - - WinUI3 - x64 - - - - - - StaticLibrary - - - - - - - - - - - - - - x86-windows - x64-windows - arm-windows - arm64-windows - - - false - - - - Use - pch.h - false - true - - - REACTWINDOWS_BUILD; - NOMINMAX; - FOLLY_NO_CONFIG; - WIN32=0; - RN_EXPORT=; - CHAKRACORE; - %(PreprocessorDefinitions) - - USE_HERMES;%(PreprocessorDefinitions) - - $(ReactNativeWindowsDir); - $(ReactNativeWindowsDir)Common; - $(ReactNativeWindowsDir)Shared; - $(ReactNativeWindowsDir)include; - $(ReactNativeWindowsDir)include\ReactWindowsCore; - $(ReactNativeDir)\ReactCommon; - $(ReactNativeDir)\ReactCommon\callinvoker; - $(JSI_Source); - $(ReactNativeWindowsDir)JSI\Shared; - $(ReactNativeWindowsDir)stubs; - $(FollyDir); - $(ReactNativeWindowsDir)\ReactWindowsCore\pch; - $(ReactNativeWindowsDir)\ReactWindowsCore\tracing; - $(ReactNativeWindowsDir)\Mso; - %(AdditionalIncludeDirectories) - - $(HERMES_Package)\installed\$(VcpkgTriplet)\include\;%(AdditionalIncludeDirectories) - /await %(AdditionalOptions) - false - - - false - false - - - $(HERMES_Package)\installed\$(VcpkgTriplet)\lib;%(AdditionalLibraryDirectories) - hermes.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - - - - - - - - - - - - - - - - - - - - - {fca38f3c-7c73-4c47-be4e-32f77fa8538d} - - - {a990658c-ce31-4bcc-976f-0fc6b1af693d} - - - {a9d95a91-4db7-4f72-beb6-fe8a5c89bfbd} - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - + \ No newline at end of file diff --git a/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj.filters b/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj.filters index ad6ca83f025..7db04cf3419 100644 --- a/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj.filters +++ b/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj.filters @@ -117,9 +117,6 @@ Source Files\Modules - - Source Files - Source Files @@ -281,9 +278,6 @@ Header Files\Modules - - Header Files - diff --git a/vnext/ReactWindowsCore/packages.ReactWindowsCore-Desktop.config b/vnext/ReactWindowsCore/packages.ReactWindowsCore-Desktop.config new file mode 100644 index 00000000000..9d410408cf0 --- /dev/null +++ b/vnext/ReactWindowsCore/packages.ReactWindowsCore-Desktop.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/vnext/ReactWindowsCore/packages.config b/vnext/ReactWindowsCore/packages.config index 9d410408cf0..cdb7bb377d4 100644 --- a/vnext/ReactWindowsCore/packages.config +++ b/vnext/ReactWindowsCore/packages.config @@ -1,6 +1,4 @@  - - \ No newline at end of file From e4a5f453b6d1d85e19b6e7ae7350d92db81f3aaf Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Fri, 8 May 2020 00:21:01 -0700 Subject: [PATCH 071/209] Align local metro config with future CLI changes (#4827) * Align local metro config with future CLI changes * Change files --- ...eact-native-win32-2020-05-07-14-18-13-clifeedback.json | 8 ++++++++ ...ct-native-windows-2020-05-07-14-18-13-clifeedback.json | 8 ++++++++ .../react-native-win32/metro-react-native-platform.js | 4 ++-- vnext/metro-react-native-platform.js | 4 ++-- 4 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 change/@office-iss-react-native-win32-2020-05-07-14-18-13-clifeedback.json create mode 100644 change/react-native-windows-2020-05-07-14-18-13-clifeedback.json diff --git a/change/@office-iss-react-native-win32-2020-05-07-14-18-13-clifeedback.json b/change/@office-iss-react-native-win32-2020-05-07-14-18-13-clifeedback.json new file mode 100644 index 00000000000..fd332b25345 --- /dev/null +++ b/change/@office-iss-react-native-win32-2020-05-07-14-18-13-clifeedback.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Align local metro config with future CLI changes", + "packageName": "@office-iss/react-native-win32", + "email": "acoates@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-07T21:18:12.974Z" +} diff --git a/change/react-native-windows-2020-05-07-14-18-13-clifeedback.json b/change/react-native-windows-2020-05-07-14-18-13-clifeedback.json new file mode 100644 index 00000000000..0a15e1dc31e --- /dev/null +++ b/change/react-native-windows-2020-05-07-14-18-13-clifeedback.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Align local metro config with future CLI changes", + "packageName": "react-native-windows", + "email": "acoates@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-07T21:18:13.813Z" +} diff --git a/packages/react-native-win32/metro-react-native-platform.js b/packages/react-native-win32/metro-react-native-platform.js index daf9a550e04..bce9b4f4a36 100644 --- a/packages/react-native-win32/metro-react-native-platform.js +++ b/packages/react-native-win32/metro-react-native-platform.js @@ -29,11 +29,11 @@ function reactNativePlatformResolver(platformImplementations) { } } let result = resolve(context, modifiedModuleName, platform); - context.resolveRequest = backupResolveRequest; return result; } catch (e) { - context.resolveRequest = backupResolveRequest; throw e; + } finally { + context.resolveRequest = backupResolveRequest; } }; } diff --git a/vnext/metro-react-native-platform.js b/vnext/metro-react-native-platform.js index e9acdf525a7..5ee8ff3d65a 100644 --- a/vnext/metro-react-native-platform.js +++ b/vnext/metro-react-native-platform.js @@ -29,11 +29,11 @@ function reactNativePlatformResolver(platformImplementations) { } } let result = resolve(context, modifiedModuleName, platform); - context.resolveRequest = backupResolveRequest; return result; } catch (e) { - context.resolveRequest = backupResolveRequest; throw e; + } finally { + context.resolveRequest = backupResolveRequest; } }; } From ccce48832687e4f09f8343508e21d4272a1a0afc Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Fri, 8 May 2020 08:18:15 -0700 Subject: [PATCH 072/209] Added Microsoft.ReactNative.IntegrationTests project to Microsoft.ReactNative.sln (#4832) * Added Microsoft.ReactNative.IntegrationTests project to Microsoft.ReactNative.sln * Change files --- ...05-07-19-10-10-MS.RN.IntegrationTests.json | 8 +++ vnext/Microsoft.ReactNative.sln | 49 +++++++++++++------ 2 files changed, 41 insertions(+), 16 deletions(-) create mode 100644 change/react-native-windows-2020-05-07-19-10-10-MS.RN.IntegrationTests.json diff --git a/change/react-native-windows-2020-05-07-19-10-10-MS.RN.IntegrationTests.json b/change/react-native-windows-2020-05-07-19-10-10-MS.RN.IntegrationTests.json new file mode 100644 index 00000000000..f58b1afa289 --- /dev/null +++ b/change/react-native-windows-2020-05-07-19-10-10-MS.RN.IntegrationTests.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Added Microsoft.ReactNative.IntegrationTests project to Microsoft.ReactNative.sln", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-08T02:10:09.919Z" +} diff --git a/vnext/Microsoft.ReactNative.sln b/vnext/Microsoft.ReactNative.sln index 840c7acbf18..e800a3153c5 100644 --- a/vnext/Microsoft.ReactNative.sln +++ b/vnext/Microsoft.ReactNative.sln @@ -117,9 +117,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MIDL", "MIDL", "{A7A199BB-2 PropertySheets\MIDL\MidlRT.xml = PropertySheets\MIDL\MidlRT.xml EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.IntegrationTests", "Microsoft.ReactNative.IntegrationTests\Microsoft.ReactNative.IntegrationTests.vcxproj", "{14FA0516-E6D7-4E4D-B097-1470198C5072}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 + Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{14fa0516-e6d7-4e4d-b097-1470198c5072}*SharedItemsImports = 4 + Mso\Mso.vcxitems*{14fa0516-e6d7-4e4d-b097-1470198c5072}*SharedItemsImports = 4 Mso\Mso.vcxitems*{1958ceaa-fbe0-44e3-8a99-90ad85531ffe}*SharedItemsImports = 4 Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{67a1076f-7790-4203-86ea-4402ccb5e782}*SharedItemsImports = 13 @@ -223,6 +227,22 @@ Global {6C60E295-C8CA-4DC5-B8BE-09888F58B249}.Release|x64.Build.0 = Release|x64 {6C60E295-C8CA-4DC5-B8BE-09888F58B249}.Release|x86.ActiveCfg = Release|Win32 {6C60E295-C8CA-4DC5-B8BE-09888F58B249}.Release|x86.Build.0 = Release|Win32 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.ActiveCfg = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.Build.0 = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.Build.0 = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.ActiveCfg = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.Build.0 = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.ActiveCfg = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.Build.0 = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.ActiveCfg = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.Build.0 = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.ActiveCfg = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.Build.0 = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.ActiveCfg = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.Build.0 = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.ActiveCfg = Release|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.Build.0 = Release|x86 {46D76F7A-8FD9-4A7D-8102-2857E5DA6B84}.Debug|ARM.ActiveCfg = Debug|ARM {46D76F7A-8FD9-4A7D-8102-2857E5DA6B84}.Debug|ARM64.ActiveCfg = Debug|ARM64 {46D76F7A-8FD9-4A7D-8102-2857E5DA6B84}.Debug|x64.ActiveCfg = Debug|x64 @@ -283,22 +303,18 @@ Global {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.Build.0 = Release|x64 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.ActiveCfg = Release|Win32 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.Build.0 = Release|Win32 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.ActiveCfg = Debug|ARM - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.Build.0 = Debug|ARM - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.Build.0 = Debug|ARM64 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.ActiveCfg = Debug|x64 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.Build.0 = Debug|x64 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.ActiveCfg = Debug|x86 - {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.Build.0 = Debug|x86 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.ActiveCfg = Release|ARM - {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.Build.0 = Release|ARM - {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.ActiveCfg = Release|ARM64 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.Build.0 = Release|ARM64 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.ActiveCfg = Release|x64 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.Build.0 = Release|x64 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.ActiveCfg = Release|x86 - {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.Build.0 = Release|x86 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Debug|ARM.ActiveCfg = Debug|Win32 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Debug|ARM64.ActiveCfg = Debug|Win32 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Debug|x64.ActiveCfg = Debug|x64 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Debug|x64.Build.0 = Debug|x64 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Debug|x86.ActiveCfg = Debug|Win32 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Debug|x86.Build.0 = Debug|Win32 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|ARM.ActiveCfg = Release|Win32 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|ARM64.ActiveCfg = Release|Win32 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|x64.ActiveCfg = Release|x64 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|x64.Build.0 = Release|x64 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|x86.ActiveCfg = Release|Win32 + {14FA0516-E6D7-4E4D-B097-1470198C5072}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -322,6 +338,7 @@ Global {19F9503C-4A05-4F96-8A41-0BD93228F220} = {D1CDE6A6-E011-4852-8500-E259AD60846F} {529E25F3-F1D4-41CC-9BAC-DEE9A5B0FF97} = {D1CDE6A6-E011-4852-8500-E259AD60846F} {A7A199BB-2B8D-4142-92D0-5EA0B299F287} = {D1CDE6A6-E011-4852-8500-E259AD60846F} + {14FA0516-E6D7-4E4D-B097-1470198C5072} = {25C4DA8C-A4D2-4D5F-950A-E5371A8AB659} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {988F03E6-640A-4C7E-8B55-C1291B70669E} From 4cfd393e489017ae619663782e37cfdafa004e53 Mon Sep 17 00:00:00 2001 From: Jon Thysell Date: Fri, 8 May 2020 09:20:42 -0700 Subject: [PATCH 073/209] Single Targets for CLI app templates (#4816) This PR updates the CLI app templates to point to a single (per language) target file, and adds stubs for files that will be generated by autolinking. * Added Microsoft.ReactNative.CSharpApp.props|targets and updated cs app template * Added Microsoft.ReactNative.CppApp.props|targets and updated cpp app templates * Added AutolinkedNativeModules.g.targets and AutolinkedNativeModules.g.h to cpp templates * Added AutolinkedNativeModules.g.targets and AutolinkedNativeModules.g.cs to cs template * Added VSProjectUtils.ps1 for nuget package management --- ...ndows-2020-05-06-15-51-59-autolinking.json | 8 + .../Microsoft.ReactNative.Uwp.CSharpApp.props | 11 ++ ...icrosoft.ReactNative.Uwp.CSharpApp.targets | 19 +++ .../Microsoft.ReactNative.Uwp.CppApp.props | 12 ++ .../Microsoft.ReactNative.Uwp.CppApp.targets | 17 ++ vnext/local-cli/generator-windows/index.js | 1 - .../cpp/proj-experimental/MyApp.vcxproj | 25 +-- .../templates/cpp/proj/MyApp.vcxproj | 29 ++-- .../templates/cpp/src/App.cpp | 7 +- .../cpp/src/AutolinkedNativeModules.g.h | 17 ++ .../cpp/src/ReactPackageProvider.cpp | 1 + .../templates/cpp/src/ReactPackageProvider.h | 1 + .../templates/cpp/src/nativeModules.g.h | 2 - .../generator-windows/templates/cpp/src/pch.h | 2 +- .../templates/cs/proj/MyApp.csproj | 30 ++-- .../templates/cs/src/App.xaml.cs | 30 ++-- .../cs/src/AutolinkedNativeModules.g.cs | 14 ++ .../templates/index.windows.bundle | 2 +- .../runWindows/utils/VSProjectUtils.ps1 | 153 ++++++++++++++++++ vnext/local-cli/runWindows/utils/autolink.js | 10 +- 20 files changed, 324 insertions(+), 67 deletions(-) create mode 100644 change/react-native-windows-2020-05-06-15-51-59-autolinking.json create mode 100644 vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CSharpApp.props create mode 100644 vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CSharpApp.targets create mode 100644 vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CppApp.props create mode 100644 vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CppApp.targets create mode 100644 vnext/local-cli/generator-windows/templates/cpp/src/AutolinkedNativeModules.g.h delete mode 100644 vnext/local-cli/generator-windows/templates/cpp/src/nativeModules.g.h create mode 100644 vnext/local-cli/generator-windows/templates/cs/src/AutolinkedNativeModules.g.cs create mode 100644 vnext/local-cli/runWindows/utils/VSProjectUtils.ps1 diff --git a/change/react-native-windows-2020-05-06-15-51-59-autolinking.json b/change/react-native-windows-2020-05-06-15-51-59-autolinking.json new file mode 100644 index 00000000000..9b5ae58bc74 --- /dev/null +++ b/change/react-native-windows-2020-05-06-15-51-59-autolinking.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Autolinking", + "packageName": "react-native-windows", + "email": "jthysell@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-06T22:51:59.672Z" +} diff --git a/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CSharpApp.props b/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CSharpApp.props new file mode 100644 index 00000000000..e4caf2e7ca0 --- /dev/null +++ b/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CSharpApp.props @@ -0,0 +1,11 @@ + + + + + $([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)\..\..'))\ + + + diff --git a/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CSharpApp.targets b/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CSharpApp.targets new file mode 100644 index 00000000000..0eb69a50d81 --- /dev/null +++ b/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CSharpApp.targets @@ -0,0 +1,19 @@ + + + + + + + {f7d32bd0-2749-483e-9a0d-1635ef7e3136} + Microsoft.ReactNative + + + 2.3.191129002 + + + + + diff --git a/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CppApp.props b/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CppApp.props new file mode 100644 index 00000000000..77f591c83e0 --- /dev/null +++ b/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CppApp.props @@ -0,0 +1,12 @@ + + + + + $([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)\..\..'))\ + false + + + diff --git a/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CppApp.targets b/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CppApp.targets new file mode 100644 index 00000000000..c68fa4447d0 --- /dev/null +++ b/vnext/PropertySheets/External/Microsoft.ReactNative.Uwp.CppApp.targets @@ -0,0 +1,17 @@ + + + + + + + + + {f7d32bd0-2749-483e-9a0d-1635ef7e3136} + + + + + diff --git a/vnext/local-cli/generator-windows/index.js b/vnext/local-cli/generator-windows/index.js index 7387048d3dd..bd91a929efa 100644 --- a/vnext/local-cli/generator-windows/index.js +++ b/vnext/local-cli/generator-windows/index.js @@ -112,7 +112,6 @@ function copyProjectTemplateAndReplace( { from: path.join(srcPath, projDir, 'MyApp.vcxproj'), to: path.join(windowsDir, newProjectName, newProjectName + '.vcxproj') }, { from: path.join(srcPath, projDir, 'MyApp.vcxproj.filters'), to: path.join(windowsDir, newProjectName, newProjectName + '.vcxproj.filters') }, { from: path.join(srcPath, projDir, 'packages.config'), to: path.join(windowsDir, newProjectName, 'packages.config') }, - { from: path.join(srcPath, projDir, 'packages.config'), to: 'packages.config' }, ].forEach((mapping) => copyAndReplaceWithChangedCallback(mapping.from, destPath, mapping.to, templateVars, options.overwrite)); // Once we are publishing to nuget.org, this shouldn't be needed anymore diff --git a/vnext/local-cli/generator-windows/templates/cpp/proj-experimental/MyApp.vcxproj b/vnext/local-cli/generator-windows/templates/cpp/proj-experimental/MyApp.vcxproj index f6a21a959da..215038b6e54 100644 --- a/vnext/local-cli/generator-windows/templates/cpp/proj-experimental/MyApp.vcxproj +++ b/vnext/local-cli/generator-windows/templates/cpp/proj-experimental/MyApp.vcxproj @@ -19,9 +19,6 @@ <%=certificateThumbprint%> password - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ - @@ -73,9 +70,6 @@ - - - @@ -151,11 +145,22 @@ false - - - - + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ + true + + + + + + + + This project references targets in your node_modules\react-native-windows folder. The missing file is {0}. + + + + diff --git a/vnext/local-cli/generator-windows/templates/cpp/proj/MyApp.vcxproj b/vnext/local-cli/generator-windows/templates/cpp/proj/MyApp.vcxproj index d6970f786da..ad4204b1b23 100644 --- a/vnext/local-cli/generator-windows/templates/cpp/proj/MyApp.vcxproj +++ b/vnext/local-cli/generator-windows/templates/cpp/proj/MyApp.vcxproj @@ -19,9 +19,6 @@ <%=certificateThumbprint%> password - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ - @@ -73,9 +70,6 @@ - - - @@ -151,16 +145,21 @@ false - - - {f7d32bd0-2749-483e-9a0d-1635ef7e3136} - - - - - - + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ + + + + + + + + This project references targets in your node_modules\react-native-windows folder. The missing file is {0}. + + + + diff --git a/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp b/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp index 15b8fe539bf..f7afd63819d 100644 --- a/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp +++ b/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp @@ -2,6 +2,7 @@ #include "App.h" #include "ReactPackageProvider.h" + // clang-format off using namespace winrt::<%=ns%>; using namespace winrt::<%=ns%>::implementation; @@ -31,11 +32,9 @@ App::App() noexcept InstanceSettings().EnableDeveloperMenu(false); #endif - PackageProviders().Append(make()); // Includes all modules in this project + RegisterAutolinkedNativeModulePackages(PackageProviders()); // Includes any autolinked modules - REACT_REGISTER_NATIVE_MODULE_PACKAGES(); //code-gen macro from autolink + PackageProviders().Append(make()); // Includes all modules in this project InitializeComponent(); } - - diff --git a/vnext/local-cli/generator-windows/templates/cpp/src/AutolinkedNativeModules.g.h b/vnext/local-cli/generator-windows/templates/cpp/src/AutolinkedNativeModules.g.h new file mode 100644 index 00000000000..6608d9c46d0 --- /dev/null +++ b/vnext/local-cli/generator-windows/templates/cpp/src/AutolinkedNativeModules.g.h @@ -0,0 +1,17 @@ +// AutolinkedNativeModules.g.h -- contents generated by "react-native run-windows" + +#include "pch.h" + +#pragma once + +// clang-format off + +namespace winrt::Microsoft::ReactNative +{ + +static void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders) +{ + +} + +} diff --git a/vnext/local-cli/generator-windows/templates/cpp/src/ReactPackageProvider.cpp b/vnext/local-cli/generator-windows/templates/cpp/src/ReactPackageProvider.cpp index 6fdeb9cf1e0..37448a1ee58 100644 --- a/vnext/local-cli/generator-windows/templates/cpp/src/ReactPackageProvider.cpp +++ b/vnext/local-cli/generator-windows/templates/cpp/src/ReactPackageProvider.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "ReactPackageProvider.h" #include "NativeModules.h" + // clang-format off using namespace winrt::Microsoft::ReactNative; diff --git a/vnext/local-cli/generator-windows/templates/cpp/src/ReactPackageProvider.h b/vnext/local-cli/generator-windows/templates/cpp/src/ReactPackageProvider.h index 8ef31e28534..3c8c0a5ebfe 100644 --- a/vnext/local-cli/generator-windows/templates/cpp/src/ReactPackageProvider.h +++ b/vnext/local-cli/generator-windows/templates/cpp/src/ReactPackageProvider.h @@ -1,6 +1,7 @@ #pragma once #include "winrt/Microsoft.ReactNative.h" + // clang-format off namespace winrt::<%=ns%>::implementation { diff --git a/vnext/local-cli/generator-windows/templates/cpp/src/nativeModules.g.h b/vnext/local-cli/generator-windows/templates/cpp/src/nativeModules.g.h deleted file mode 100644 index 049a8c9e57c..00000000000 --- a/vnext/local-cli/generator-windows/templates/cpp/src/nativeModules.g.h +++ /dev/null @@ -1,2 +0,0 @@ -// NativeModules.g.h -- contents generated by "react-native run-windows" -#define REACT_REGISTER_NATIVE_MODULE_PACKAGES() \ No newline at end of file diff --git a/vnext/local-cli/generator-windows/templates/cpp/src/pch.h b/vnext/local-cli/generator-windows/templates/cpp/src/pch.h index 379e0b4c80e..4226997d4d4 100644 --- a/vnext/local-cli/generator-windows/templates/cpp/src/pch.h +++ b/vnext/local-cli/generator-windows/templates/cpp/src/pch.h @@ -25,4 +25,4 @@ #include #include -#include "nativeModules.g.h" +#include "AutolinkedNativeModules.g.h" diff --git a/vnext/local-cli/generator-windows/templates/cs/proj/MyApp.csproj b/vnext/local-cli/generator-windows/templates/cs/proj/MyApp.csproj index 40c12f5b5a1..cda8ee820f5 100644 --- a/vnext/local-cli/generator-windows/templates/cs/proj/MyApp.csproj +++ b/vnext/local-cli/generator-windows/templates/cs/proj/MyApp.csproj @@ -23,9 +23,6 @@ false 7.3 - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ - true bin\x86\Debug\ @@ -126,6 +123,7 @@ App.xaml + @@ -154,22 +152,24 @@ 6.2.8 - - - {f7d32bd0-2749-483e-9a0d-1635ef7e3136} - Microsoft.ReactNative - - - 2.3.191129002 - - - 16.0 - - + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ + + + + + + + + This project references targets in your node_modules\react-native-windows folder. The missing file is {0}. + + + + diff --git a/vnext/local-cli/generator-windows/templates/cs/src/App.xaml.cs b/vnext/local-cli/generator-windows/templates/cs/src/App.xaml.cs index 77b1a40b190..24cc95d62ea 100644 --- a/vnext/local-cli/generator-windows/templates/cs/src/App.xaml.cs +++ b/vnext/local-cli/generator-windows/templates/cs/src/App.xaml.cs @@ -3,30 +3,32 @@ namespace <%=ns%> { sealed partial class App : ReactApplication -{ - public App() { - MainComponentName = "<%=name%>"; + public App() + { + MainComponentName = "<%=name%>"; #if BUNDLE - JavaScriptBundleFile = "index.windows"; - InstanceSettings.UseWebDebugger = false; - InstanceSettings.UseFastRefresh = false; + JavaScriptBundleFile = "index.windows"; + InstanceSettings.UseWebDebugger = false; + InstanceSettings.UseFastRefresh = false; #else - JavaScriptMainModuleName = "index"; - InstanceSettings.UseWebDebugger = true; - InstanceSettings.UseFastRefresh = true; + JavaScriptMainModuleName = "index"; + InstanceSettings.UseWebDebugger = true; + InstanceSettings.UseFastRefresh = true; #endif #if DEBUG - InstanceSettings.EnableDeveloperMenu = true; + InstanceSettings.EnableDeveloperMenu = true; #else - InstanceSettings.EnableDeveloperMenu = false; + InstanceSettings.EnableDeveloperMenu = false; #endif - PackageProviders.Add(new Microsoft.ReactNative.Managed.ReactPackageProvider()); // Includes any modules in this project + Microsoft.ReactNative.Managed.AutolinkedNativeModules.RegisterAutolinkedNativeModulePackages(PackageProviders); // Includes any autolinked modules + + PackageProviders.Add(new Microsoft.ReactNative.Managed.ReactPackageProvider()); // Includes any modules in this project - InitializeComponent(); + InitializeComponent(); + } } } -} diff --git a/vnext/local-cli/generator-windows/templates/cs/src/AutolinkedNativeModules.g.cs b/vnext/local-cli/generator-windows/templates/cs/src/AutolinkedNativeModules.g.cs new file mode 100644 index 00000000000..4f311206b86 --- /dev/null +++ b/vnext/local-cli/generator-windows/templates/cs/src/AutolinkedNativeModules.g.cs @@ -0,0 +1,14 @@ +// AutolinkedNativeModules.g.cs -- contents generated by "react-native run-windows" + +using System.Collections.Generic; + +namespace Microsoft.ReactNative.Managed +{ + internal static class AutolinkedNativeModules + { + internal static void RegisterAutolinkedNativeModulePackages(IList packageProviders) + { + + } + } +} diff --git a/vnext/local-cli/generator-windows/templates/index.windows.bundle b/vnext/local-cli/generator-windows/templates/index.windows.bundle index 1dfbebec13f..d87c04f64f8 100644 --- a/vnext/local-cli/generator-windows/templates/index.windows.bundle +++ b/vnext/local-cli/generator-windows/templates/index.windows.bundle @@ -2,7 +2,7 @@ * * Be sure to generate this file using the CLI: * - * react-native bundle --platform windows --entry-file index.js + * npx react-native bundle --platform windows --entry-file index.js * --bundle-output windows\<%=name%>\Bundle\index.windows.bundle * --assets-dest windows\<%=name%>\Bundle * diff --git a/vnext/local-cli/runWindows/utils/VSProjectUtils.ps1 b/vnext/local-cli/runWindows/utils/VSProjectUtils.ps1 new file mode 100644 index 00000000000..c80a798a0a9 --- /dev/null +++ b/vnext/local-cli/runWindows/utils/VSProjectUtils.ps1 @@ -0,0 +1,153 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +# Checks that $PackagesConfigPath is to a packages.config file +# If $ExistingFile, check that the file exists, else that it doesn't exist +function Check-PackagesConfigXml { + param( + [string] $PackagesConfigPath, + [bool] $ExistingFile = $True + ) + + Write-Host + Write-Host "Checking " -NoNewLine + Write-Host -ForegroundColor White $PackagesConfigPath -NoNewLine + Write-Host "..." -NoNewLine + + if ((Split-Path -Path $PackagesConfigPath -Leaf) -ne 'packages.config') { + Write-Host " error." + throw "$PackagesConfigPath is not a packages.config file." + } + + if ($ExistingFile -and -not(Test-Path -Path $PackagesConfigPath)) { + Write-Host " error." + throw "$PackagesConfigPath does not exist." + } elseif (-not($ExistingFile) -and (Test-Path -Path $PackagesConfigPath)) { + Write-Host " error." + throw "$PackagesConfigPath already exists." + } + + Write-Host " done." +} + +# Creates a new packages.config file at $PackagesConfigPath +# If $CheckConfig, check the file doesn't already exist first +function Create-PackagesConfigXml { + param( + [string] $PackagesConfigPath, + [bool] $CheckConfig = $True + ) + + if ($CheckConfig) { + Check-PackagesConfigXml -PackagesConfigPath $PackagesConfigPath -ExistingFile $False + } + + Write-Host + Write-Host "Creating " -NoNewLine + Write-Host -ForegroundColor White $PackagesConfigPath -NoNewLine + Write-Host "..." -NoNewLine + + [xml]$packageXml = ' + + ' + + $packageXml.Save($PackagesConfigPath) + + Write-Host " done." +} + +# Loads the packages.config file at $PackagesConfigPath +# If $CheckConfig, check the file exists first +function Load-PackagesConfigXml { + param( + [string] $PackagesConfigPath, + [bool] $CheckConfig = $True + ) + + if ($CheckConfig) { + Check-PackagesConfigXml -PackagesConfigPath $PackagesConfigPath + } + + Write-Host + Write-Host "Loading " -NoNewLine + Write-Host -ForegroundColor White $PackagesConfigPath -NoNewLine + Write-Host "..." -NoNewLine + + [xml]$content = Get-Content -Path $PackagesConfigPath + + Write-Host " done." + + $content.packages.package | foreach { + Write-Host "Found package " -NoNewLine + Write-Host -ForegroundColor White $_.id -NoNewLine + Write-Host " version " -NoNewLine + Write-Host -ForegroundColor White $_.version -NoNewLine + Write-Host "." + } + + return $content; +} + +# Update package $PackageName to version $PackageVersion in the packages.config +# file at $PackagesConfigPath +# If $CheckConfig, check the file exists first +function Update-PackagesConfigXml { + param( + [string] $PackagesConfigPath, + [string] $PackageName, + [string] $PackageVersion, + [bool] $CheckConfig = $True + ) + + if ($CheckConfig) { + Check-PackagesConfigXml -PackagesConfigPath $PackagesConfigPath + } + + Write-Host + Write-Host "Updating package " -NoNewLine + Write-Host -ForegroundColor White $PackageName -NoNewLine + Write-Host " to version " -NoNewLine + Write-Host -ForegroundColor White $PackageVersion -NoNewLine + Write-Host "..." + + & nuget.exe update "$PackagesConfigPath" -Id "$PackageName" -Version "$PackageVersion" +} + +# Add package $PackageName version $PackageVersion to the packages.config +# file at $PackagesConfigPath +# If $CheckConfig, check the file exists first +function Add-PackagesConfigXml { + param( + [string] $PackagesConfigPath, + [string] $PackageName, + [string] $PackageVersion, + [bool] $CheckConfig = $True + ) + + $packageXml = Load-PackagesConfigXml -PackagesConfigPath $PackagesConfigPath + + $existingPackageNode = $packageXml.selectSingleNode("packages/package[@id=""$PackageName""]") + + if ($existingPackageNode) { + Write-Host + Write-Host "Nothing to add, package " -NoNewLine + Write-Host -ForegroundColor White $PackageName -NoNewLine + Write-Host " is already present." + } else { + Write-Host + Write-Host "Adding package " -NoNewLine + Write-Host -ForegroundColor White $PackageName -NoNewLine + Write-Host "..." -NoNewLine + + $packagesNode = $packageXml.selectSingleNode('packages') + $newPackageNode = $packagesNode.appendChild($packageXml.CreateElement('package')) + $newPackageNode.SetAttribute('id', $PackageName) + $newPackageNode.SetAttribute('version', '0') + + $packageXml.Save($PackagesConfigPath) + + Write-Host " done." + } + + Update-PackagesConfigXml -PackagesConfigPath $PackagesConfigPath -PackageName $PackageName -PackageVersion $PackageVersion -CheckConfig $False +} diff --git a/vnext/local-cli/runWindows/utils/autolink.js b/vnext/local-cli/runWindows/utils/autolink.js index 5dc6d73afb9..d69ba539849 100644 --- a/vnext/local-cli/runWindows/utils/autolink.js +++ b/vnext/local-cli/runWindows/utils/autolink.js @@ -42,7 +42,7 @@ function updateAutoLink(verbose) { const generatedHeader = path.join( sourceDir, projectName, - 'nativeModules.g.h', + 'AutolinkedNativeModules.g.h', ); if (!fs.existsSync(generatedHeader)) { console.log( @@ -51,11 +51,13 @@ function updateAutoLink(verbose) { return; } + //TODO: Update to the new RegisterAutolinkedNativeModulePackages method + let generatedIncludes = - '// NativeModules.g.h -- contents generated by "react-native run-windows"'; + '// AutolinkedNativeModules.g.h -- contents generated by "react-native run-windows"\\\r\n\\\r\n#pragma once\\\r\n\\\r\n'; const dependencies = config.dependencies; let packageRegistrations = - '#define REACT_REGISTER_NATIVE_MODULE_PACKAGES()'; + '#define REGISTER_AUTOLINKED_NATIVE_MODULE_PACKAGES()'; for (const dependency in dependencies) { const windowDependency = dependencies[dependency].platforms.windows; const cppProjFile = windowDependency @@ -75,7 +77,7 @@ function updateAutoLink(verbose) { packageRegistrations += packageRegistration; } - console.log('Updating nativeModules.g.h...'); + console.log('Updating AutolinkedNativeModules.g.h...'); const contents = generatedIncludes + '\r\n' + packageRegistrations; fs.writeFileSync(generatedHeader, contents, {encoding: 'utf8', flag: 'w'}); From 4255e8196403730eafe0888fa7848ece82176559 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Fri, 8 May 2020 11:04:34 -0700 Subject: [PATCH 074/209] Ensure Beachball Uses The Right Branch for Experimental NuGet PR Tests (#4837) During the 0.61 timeframe, CI changes were added to use PR target branch in beachball scripts to avoid needing to manually change CI scripts when branching. Experimental Nuget work added a new usage without injecting PR target branch. This currently leads to CI failures when adding new changes to the 0.62 branch. Make sure to use the right branch here. --- .ado/windows-vs-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ado/windows-vs-pr.yml b/.ado/windows-vs-pr.yml index 25ae525a021..3a9f922b1bd 100644 --- a/.ado/windows-vs-pr.yml +++ b/.ado/windows-vs-pr.yml @@ -112,7 +112,7 @@ jobs: Microsoft.ReactNative\** - script: | - npx --no-install beachball bump + npx --no-install beachball bump --branch origin/$(System.PullRequest.TargetBranch) displayName: Bump package versions to align nuget version with npm version condition: eq('true', variables['TestMSRNNuget']) From b590fffb4df3433111f917a2a71e9cad31fb1042 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Fri, 8 May 2020 12:09:48 -0700 Subject: [PATCH 075/209] Implemented PropertyBag for ReactContext and ReactInstanceSettings (#4817) * Implemented PropertyBag for ReactContext and ReactInstanceSettings * Change files * yarn format * Delete the old PropertyBag files. * Make PropertyBag's ToObject and FromObject methods private. * Renamed some classes and methods. * Fixed sample project compilation * VS updates the sln file * VS automatically updated solutions --- ...ws-2020-05-06-20-33-40-MS_PropertyBag.json | 8 + .../windows/SampleAppCPP/App.cpp | 4 + .../windows/SampleAppCS/App.xaml.cs | 3 + .../windows/SampleApps.sln | 1 + .../SampleLibraryCPP/SampleModuleCPP.h | 7 +- .../windows/SampleLibraryCS/SampleModuleCS.cs | 6 +- ...icrosoft.ReactNative.Cxx.UnitTests.vcxproj | 1 + .../NativeModuleTest.cpp | 2 +- .../NoAttributeNativeModuleTest.cpp | 2 +- .../ReactModuleBuilderMock.h | 4 + .../TurboModuleTest.cpp | 2 +- .../Microsoft.ReactNative.Cxx.UnitTests/pch.h | 2 + .../Microsoft.ReactNative.Cxx.vcxitems | 1 + .../Microsoft.ReactNative.Cxx/NativeModules.h | 16 +- .../Microsoft.ReactNative.Cxx/ReactContext.h | 97 +-- .../ReactPropertyBag.h | 280 +++++++++ ...osoft.ReactNative.IntegrationTests.vcxproj | 1 + .../ReactPropertyBagTests.cpp | 509 +++++++++++++++ .../pch.h | 4 +- .../ReactModuleBuilderMock.cs | 2 + .../ReactContext.cs | 46 +- vnext/Microsoft.ReactNative.sln | 4 +- vnext/Microsoft.ReactNative/IReactContext.cpp | 4 + vnext/Microsoft.ReactNative/IReactContext.h | 1 + vnext/Microsoft.ReactNative/IReactContext.idl | 2 + .../IReactPropertyBag.cpp | 216 +++++++ .../Microsoft.ReactNative/IReactPropertyBag.h | 37 ++ .../IReactPropertyBag.idl | 71 +++ .../Microsoft.ReactNative.vcxproj | 15 +- .../Microsoft.ReactNative.vcxproj.filters | 104 ++-- .../NoExceptionAttribute.idl | 2 +- .../ReactHost/PropertyBag.cpp | 172 ------ .../ReactHost/PropertyBag.h | 583 ------------------ .../ReactHost/PropertyBag_internal.h | 80 --- vnext/Microsoft.ReactNative/ReactHost/React.h | 15 +- .../ReactHost/ReactInstanceWin.cpp | 26 +- .../ReactHost/ReactInstanceWin.h | 8 +- .../ReactInstanceSettings.h | 7 + .../ReactInstanceSettings.idl | 3 +- .../Microsoft.ReactNative/ReactNativeHost.cpp | 1 + vnext/Mso/crash/verifyElseCrash.h | 4 + vnext/ReactWindows-Desktop.sln | 3 +- 42 files changed, 1326 insertions(+), 1030 deletions(-) create mode 100644 change/react-native-windows-2020-05-06-20-33-40-MS_PropertyBag.json create mode 100644 vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h create mode 100644 vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp create mode 100644 vnext/Microsoft.ReactNative/IReactPropertyBag.cpp create mode 100644 vnext/Microsoft.ReactNative/IReactPropertyBag.h create mode 100644 vnext/Microsoft.ReactNative/IReactPropertyBag.idl delete mode 100644 vnext/Microsoft.ReactNative/ReactHost/PropertyBag.cpp delete mode 100644 vnext/Microsoft.ReactNative/ReactHost/PropertyBag.h delete mode 100644 vnext/Microsoft.ReactNative/ReactHost/PropertyBag_internal.h diff --git a/change/react-native-windows-2020-05-06-20-33-40-MS_PropertyBag.json b/change/react-native-windows-2020-05-06-20-33-40-MS_PropertyBag.json new file mode 100644 index 00000000000..93332582c6b --- /dev/null +++ b/change/react-native-windows-2020-05-06-20-33-40-MS_PropertyBag.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Implemented PropertyBag for ReactContext and ReactInstanceSettings", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-07T03:33:40.086Z" +} diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp index 6cbc618bc3b..24ef3d664fb 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp @@ -5,6 +5,7 @@ #include "App.h" #include "ReactPackageProvider.h" +#include "ReactPropertyBag.h" #include "winrt/SampleLibraryCS.h" #include "winrt/SampleLibraryCpp.h" @@ -34,6 +35,9 @@ App::App() noexcept { InstanceSettings().EnableDeveloperMenu(false); #endif + ReactPropertyBag::Set(InstanceSettings().Properties(), ReactPropertyId{L"Prop1"}, 42); + ReactPropertyBag::Set(InstanceSettings().Properties(), ReactPropertyId{L"Prop2"}, L"Hello World!"); + PackageProviders().Append(make()); // Includes all modules in this project PackageProviders().Append(winrt::SampleLibraryCpp::ReactPackageProvider()); PackageProviders().Append(winrt::SampleLibraryCS::ReactPackageProvider()); diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/App.xaml.cs b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/App.xaml.cs index a42b17de53f..7c5bbd5dc94 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/App.xaml.cs +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCS/App.xaml.cs @@ -37,6 +37,9 @@ public App() InstanceSettings.EnableDeveloperMenu = false; #endif + InstanceSettings.Properties.Set(ReactPropertyBagHelper.GetName(null, "Prop1"), 43); + InstanceSettings.Properties.Set(ReactPropertyBagHelper.GetName(null, "Prop2"), "Hello RNW!"); + PackageProviders.Add(new Microsoft.ReactNative.Managed.ReactPackageProvider()); // Includes any modules in this project PackageProviders.Add(new ReflectionReactPackageProvider()); PackageProviders.Add(new SampleLibraryCS.ReactPackageProvider()); diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleApps.sln b/packages/microsoft-reactnative-sampleapps/windows/SampleApps.sln index 2f4bae66813..fa268b1004d 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleApps.sln +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleApps.sln @@ -50,6 +50,7 @@ EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 + ..\..\..\vnext\ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4 ..\..\..\vnext\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{47eec7f3-40d3-49ba-82c1-eaf103b54215}*SharedItemsImports = 4 ..\..\..\vnext\Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9 diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleModuleCPP.h b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleModuleCPP.h index 0541d247d87..87f071637f2 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleModuleCPP.h +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleModuleCPP.h @@ -33,7 +33,12 @@ struct SampleModuleCppImpl { #pragma region Initialization REACT_INIT(Initialize) - void Initialize(ReactContext const & /*reactContext*/) noexcept { + void Initialize(ReactContext const &reactContext) noexcept { + const ReactPropertyId myProp1{L"Prop1"}; + const ReactPropertyId myProp2{L"Prop2"}; + DEBUG_OUTPUT("globalProps.Prop1:", *reactContext.Properties().Get(myProp1)); + DEBUG_OUTPUT("instanceProps.Prop2:", winrt::to_string(*reactContext.Properties().Get(myProp2))); + m_timer = winrt::Windows::System::Threading::ThreadPoolTimer::CreatePeriodicTimer( [this](const winrt::Windows::System::Threading::ThreadPoolTimer) noexcept { TimedEvent(++m_timerCount); diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs index f69b8ca7a9d..655e8391d7b 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using Microsoft.ReactNative; using Microsoft.ReactNative.Managed; using System; using System.Diagnostics; @@ -23,8 +24,11 @@ internal sealed class SampleModuleCS #region Initializer [ReactInitializer] - public void Initialize(ReactContext _) + public void Initialize(ReactContext reactContext) { + Debug.WriteLine($"C# globalProps.Prop1: {reactContext.Handle.Properties.Get(ReactPropertyBagHelper.GetName(null, "Prop1"))}"); + Debug.WriteLine($"C# instanceProps.Prop2: {reactContext.Handle.Properties.Get(ReactPropertyBagHelper.GetName(null, "Prop2"))}"); + _timer = ThreadPoolTimer.CreatePeriodicTimer(new TimerElapsedHandler((timer) => { TimedEvent?.Invoke(++_timerCount); diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj b/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj index 352c770761e..1849911ed19 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj @@ -144,6 +144,7 @@ + diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp index 9a87ab2374a..62abfec9cba 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp @@ -599,7 +599,7 @@ TEST_CLASS (NativeModuleTest) { auto provider = React::MakeModuleProvider(); m_moduleObject = m_builderMock.CreateModule(provider, m_moduleBuilder); auto reactModule = m_moduleObject.as(); - m_module = &React::BoxedValue::GetImpl(reactModule); + m_module = &React::BoxedValue::GetValueUnsafe(reactModule); } TEST_METHOD(TestMethodCall_Add) { diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp index 5c801dda4e7..bb1fc56272e 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp @@ -604,7 +604,7 @@ TEST_CLASS (NoAttributeNativeModuleTest) { auto provider = React::MakeModuleProvider(); m_moduleObject = m_builderMock.CreateModule(provider, m_moduleBuilder); auto reactModule = m_moduleObject.as(); - m_module = &React::BoxedValue::GetImpl(reactModule); + m_module = &React::BoxedValue::GetValueUnsafe(reactModule); } TEST_METHOD(TestMethodCall_Add) { diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h index ae661ba718e..28da1d8c0fd 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h @@ -120,6 +120,10 @@ struct ReactModuleBuilderMock { struct ReactContextMock : implements { ReactContextMock(ReactModuleBuilderMock *builderMock) noexcept; + IReactPropertyBag Properties() noexcept { + VerifyElseCrashSz(false, "Not implemented"); + } + void DispatchEvent( xaml::FrameworkElement const & /*view*/, hstring const & /*eventName*/, diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp index 201834777f1..0933de064d8 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp @@ -1118,7 +1118,7 @@ TEST_CLASS (TurboModuleTest) { auto provider = winrt::Microsoft::ReactNative::MakeTurboModuleProvider(); m_moduleObject = m_builderMock.CreateModule(provider, m_moduleBuilder); auto reactModule = m_moduleObject.as(); - m_module = &winrt::Microsoft::ReactNative::BoxedValue::GetImpl(reactModule); + m_module = &winrt::Microsoft::ReactNative::BoxedValue::GetValueUnsafe(reactModule); } TEST_METHOD(TestMethodCall_Add) { diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/pch.h b/vnext/Microsoft.ReactNative.Cxx.UnitTests/pch.h index bd279fd0d84..06661b920e8 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/pch.h +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/pch.h @@ -8,6 +8,8 @@ #include +#undef GetCurrentTime + #include #include #include "winrt/Microsoft.ReactNative.h" diff --git a/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems b/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems index 8e87dbfe24d..9a476a959fb 100644 --- a/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +++ b/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems @@ -28,6 +28,7 @@ + diff --git a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h index d7ab009b8c5..19ab45c0080 100644 --- a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h +++ b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h @@ -1107,28 +1107,26 @@ struct TurboModuleSpec { template struct BoxedValue : implements, IBoxedValue> { - BoxedValue() noexcept {} + template + BoxedValue(TArgs &&... args) noexcept : m_value(std::forward(args)...) {} int64_t GetPtr() noexcept { return reinterpret_cast(&m_value); } - static T &GetImpl(IBoxedValue &module) noexcept; + static T &GetValueUnsafe(IBoxedValue const &boxedValue) noexcept { + return *reinterpret_cast(boxedValue.GetPtr()); + } private: T m_value{}; }; -template -inline T &BoxedValue::GetImpl(IBoxedValue &module) noexcept { - return *reinterpret_cast(module.GetPtr()); -} - template inline ReactModuleProvider MakeModuleProvider() noexcept { return [](IReactModuleBuilder const &moduleBuilder) noexcept { auto moduleObject = make>(); - auto module = &BoxedValue::GetImpl(moduleObject); + auto module = &BoxedValue::GetValueUnsafe(moduleObject); ReactModuleBuilder builder{module, moduleBuilder}; GetReactModuleInfo(module, builder); builder.CompleteRegistration(); @@ -1141,7 +1139,7 @@ inline ReactModuleProvider MakeTurboModuleProvider() noexcept { TModuleSpec::template ValidateModule(); return [](IReactModuleBuilder const &moduleBuilder) noexcept { auto moduleObject = make>(); - auto module = &BoxedValue::GetImpl(moduleObject); + auto module = &BoxedValue::GetValueUnsafe(moduleObject); ReactModuleBuilder builder{module, moduleBuilder}; GetReactModuleInfo(module, builder); builder.CompleteRegistration(); diff --git a/vnext/Microsoft.ReactNative.Cxx/ReactContext.h b/vnext/Microsoft.ReactNative.Cxx/ReactContext.h index d0cdd442745..a40c869f3c6 100644 --- a/vnext/Microsoft.ReactNative.Cxx/ReactContext.h +++ b/vnext/Microsoft.ReactNative.Cxx/ReactContext.h @@ -8,7 +8,7 @@ #include #include #include "JSValueWriter.h" -#include "winrt/Microsoft.ReactNative.h" +#include "ReactPropertyBag.h" namespace winrt::Microsoft::ReactNative { @@ -16,95 +16,60 @@ namespace winrt::Microsoft::ReactNative { // It wraps up the IReactContext and adds convenience methods for // working with C++ types. struct ReactContext { - ReactContext(IReactContext const &context) noexcept; + ReactContext(IReactContext const &handle) noexcept : m_handle{handle} {} - IReactContext const &ContextAbi() const noexcept; + IReactContext const &Handle() const noexcept { + return m_handle; + } - explicit operator bool() noexcept; + explicit operator bool() const noexcept { + return static_cast(m_handle); + } + + ReactPropertyBag Properties() const noexcept { + return ReactPropertyBag{m_handle.Properties()}; + } template - void CallJSFunction(std::wstring_view moduleName, std::wstring_view methodName, TArgs &&... args) noexcept; + void CallJSFunction(std::wstring_view moduleName, std::wstring_view methodName, TArgs &&... args) const noexcept { + m_handle.CallJSFunction(moduleName, methodName, MakeJSValueArgWriter(std::forward(args)...)); + } void CallJSFunction( std::wstring_view moduleName, std::wstring_view methodName, - JSValueArgWriter const ¶msArgWriter) noexcept; + JSValueArgWriter const ¶msArgWriter) const noexcept { + m_handle.CallJSFunction(moduleName, methodName, paramsArgWriter); + } template - void EmitJSEvent(std::wstring_view eventEmitterName, std::wstring_view eventName, TArgs &&... args) noexcept; + void EmitJSEvent(std::wstring_view eventEmitterName, std::wstring_view eventName, TArgs &&... args) const noexcept { + m_handle.EmitJSEvent(eventEmitterName, eventName, MakeJSValueArgWriter(std::forward(args)...)); + } void EmitJSEvent( std::wstring_view eventEmitterName, std::wstring_view eventName, - JSValueArgWriter const ¶msArgWriter) noexcept; + JSValueArgWriter const ¶msArgWriter) const noexcept { + m_handle.EmitJSEvent(eventEmitterName, eventName, paramsArgWriter); + } template - void DispatchEvent(xaml::FrameworkElement const &view, std::wstring_view eventName, TArgs &&... args) noexcept; + void DispatchEvent(xaml::FrameworkElement const &view, std::wstring_view eventName, TArgs &&... args) const noexcept { + m_handle.DispatchEvent(view, eventName, MakeJSValueArgWriter(std::forward(args)...)); + } void DispatchEvent( xaml::FrameworkElement const &view, std::wstring_view eventName, - JSValueArgWriter const ¶msArgWriter) noexcept; + JSValueArgWriter const ¶msArgWriter) const noexcept { + m_handle.DispatchEvent(view, eventName, paramsArgWriter); + } private: - const IReactContext m_context; + const IReactContext m_handle; }; -//============================================================================== -// ReactContext inline implementation -//============================================================================== - -inline ReactContext::ReactContext(IReactContext const &context) noexcept : m_context{context} {} - -inline IReactContext const &ReactContext::ContextAbi() const noexcept { - return m_context; -} - -inline ReactContext::operator bool() noexcept { - return m_context != nullptr; -} - -template -inline void -ReactContext::CallJSFunction(std::wstring_view moduleName, std::wstring_view methodName, TArgs &&... args) noexcept { - m_context.CallJSFunction(moduleName, methodName, MakeJSValueArgWriter(std::forward(args)...)); -} - -inline void ReactContext::CallJSFunction( - std::wstring_view moduleName, - std::wstring_view methodName, - JSValueArgWriter const ¶msArgWriter) noexcept { - m_context.CallJSFunction(moduleName, methodName, paramsArgWriter); -} - -template -inline void -ReactContext::EmitJSEvent(std::wstring_view eventEmitterName, std::wstring_view eventName, TArgs &&... args) noexcept { - m_context.EmitJSEvent(eventEmitterName, eventName, MakeJSValueArgWriter(std::forward(args)...)); -} - -inline void ReactContext::EmitJSEvent( - std::wstring_view eventEmitterName, - std::wstring_view eventName, - JSValueArgWriter const ¶msArgWriter) noexcept { - m_context.EmitJSEvent(eventEmitterName, eventName, paramsArgWriter); -} - -template -inline void ReactContext::DispatchEvent( - xaml::FrameworkElement const &view, - std::wstring_view eventName, - TArgs &&... args) noexcept { - m_context.DispatchEvent(view, eventName, MakeJSValueArgWriter(std::forward(args)...)); -} - -inline void ReactContext::DispatchEvent( - xaml::FrameworkElement const &view, - std::wstring_view eventName, - JSValueArgWriter const ¶msArgWriter) noexcept { - m_context.DispatchEvent(view, eventName, paramsArgWriter); -} - } // namespace winrt::Microsoft::ReactNative #endif // MICROSOFT_REACTNATIVE_REACTCONTEXT diff --git a/vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h b/vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h new file mode 100644 index 00000000000..1dc6d09bcdf --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h @@ -0,0 +1,280 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#ifndef MICROSOFT_REACTNATIVE_PROPERTYBAG +#define MICROSOFT_REACTNATIVE_PROPERTYBAG + +// +// ReactPropertyBag is a thread-safe storage of property values. +// Internally the value is IInspectable and the key is a name object that represents an +// atomized string name. Each name object is defined in the context of a namespace object. +// The null or empty namespace object is a global namespace object. +// The property name is unique for the same namespace object. +// Different namespaces may have properties with the same local names. +// +// The ReactPropertyBag struct is a wrapper around the ABI-safe IReactPropertyBag interface. +// The IReactPropertyBag represents all values as IInspectable object which can wrap any type. +// On top of the untyped IReactPropertyBag values, the ReactPropertyBag offers a set of typed +// property accessors: Get, GetOrCreate, Remove, and Set. +// +// To simplify access to properties we offer ReactPropertyId type that helps to +// wrap up property name and type into one variable. +// +// For example, we can define a property to access an integer value: +// +// const React::ReactPropertyId MyIntProperty{"MyInt"}; +// +// then we can use it to set property in settings properties during initialization: +// +// settings.Properties().Set(MyIntProperty, 42); +// +// The property can be accessed later in a native modules: +// +// std::optional myInt = context.Properties().Get(MyIntProperty); +// +// Note that types inherited from IInspectable are returned +// directly because their null value may indicated absent property value. +// For other types we return std::optional. It has std::nullopt value in case if +// no property value is found or if it has a wrong type. +// To avoid compilation errors the non-IInspectable types must be WinRT types which are described here: +// https://docs.microsoft.com/en-us/uwp/api/windows.foundation.propertytype?view=winrt-18362 +// + +#include +#include + +namespace winrt::Microsoft::ReactNative { + +// Encapsulates the IReactPropertyNamespace +struct ReactPropertyNamespace { + ReactPropertyNamespace(std::nullptr_t = nullptr) noexcept {} + + explicit ReactPropertyNamespace(IReactPropertyNamespace const &handle) noexcept : m_handle{handle} {} + + explicit ReactPropertyNamespace(param::hstring const &ns) noexcept + : m_handle{ReactPropertyBagHelper::GetNamespace(ns)} {} + + static ReactPropertyNamespace Global() noexcept { + return ReactPropertyNamespace{ReactPropertyBagHelper::GlobalNamespace()}; + } + + hstring NamespaceName() const noexcept { + return m_handle ? m_handle.NamespaceName() : hstring{}; + } + + IReactPropertyNamespace const &Handle() const noexcept { + return m_handle; + } + + explicit operator bool() const noexcept { + return static_cast(m_handle); + } + + private: + IReactPropertyNamespace m_handle; +}; + +// Encapsulates the IReactPropertyName and the property type +template +struct ReactPropertyId { + using PropertyType = T; + + ReactPropertyId(std::nullptr_t = nullptr) noexcept {} + + explicit ReactPropertyId(IReactPropertyName const &handle) noexcept : m_handle{handle} {} + + explicit ReactPropertyId(hstring const &localName) noexcept + : m_handle{ReactPropertyBagHelper::GetName(nullptr, localName)} {} + + ReactPropertyId(ReactPropertyNamespace const &ns, hstring const &localName) noexcept + : m_handle{ReactPropertyBagHelper::GetName(ns.Handle(), localName)} {} + + ReactPropertyId(hstring const &ns, hstring const &localName) noexcept + : m_handle{ReactPropertyBagHelper::GetName(ReactPropertyBagHelper::GetNamespace(ns), localName)} {} + + hstring NamespaceName() const noexcept { + return m_handle ? m_handle.Namespace().NamespaceName() : hstring{}; + } + + hstring LocalName() const noexcept { + return m_handle ? m_handle.LocalName() : hstring{}; + } + + IReactPropertyName const &Handle() const noexcept { + return m_handle; + } + + explicit operator bool() const noexcept { + return static_cast(m_handle); + } + + private: + IReactPropertyName m_handle; +}; + +// ReactPropertyBag is a wrapper for IReactPropertyBag to stores strongly-typed properties in a thread-safe way. +// Types inherited from IInspectable are stored directly. +// Values of other types are boxed with help of winrt::box_value. +// Only WinRT types can be stored. +struct ReactPropertyBag { + // Property result type is either T or std::optional. + // T is returned for types inherited from IInspectable. + // The std::optional is returned for all other types. + template + using ResultType = std::conditional_t, T, std::optional>; + + // Create a new empty instance of ReactPropertyBag. + ReactPropertyBag(std::nullptr_t = nullptr) noexcept {} + + // Creates a new instance of ReactPropertyBag with the provided handle. + explicit ReactPropertyBag(IReactPropertyBag const &handle) noexcept : m_handle{handle} {} + + // True if handle is not null. + explicit operator bool() const noexcept { + return static_cast(m_handle); + } + + // Get ReactPropertyBag handle. + IReactPropertyBag const &Handle() const noexcept { + return m_handle; + } + + // Get property value by property name. + template + static ResultType Get(IReactPropertyBag const &handle, ReactPropertyId const &propertyId) noexcept { + Windows::Foundation::IInspectable propertyValue = handle ? handle.Get(propertyId.Handle()) : nullptr; + return FromObject(propertyValue); + } + + // Ensure that property is created by calling valueCreator if needed, and return value by property name. + // The TCreateValue must return either T or std::optional. It must have no parameters. + template + static ResultType GetOrCreate( + IReactPropertyBag const &handle, + ReactPropertyId const &propertyId, + TCreateValue const &createValue) noexcept { + Windows::Foundation::IInspectable propertyValue = handle + ? handle.GetOrCreate(propertyId.Handle(), [&createValue]() noexcept { return ToObject(createValue()); }) + : nullptr; + return FromObject(propertyValue); + } + + // Set property value by property name. + template + static void Set(IReactPropertyBag const &handle, ReactPropertyId const &propertyId, TValue const &value) noexcept { + if (handle) { + auto propertyValue = ToObject(value); + handle.Set(propertyId.Handle(), propertyValue); + } + } + + // Removes property value by property name. + template + static void Remove(IReactPropertyBag const &handle, ReactPropertyId const &propertyId) noexcept { + if (handle) { + handle.Set(propertyId.Handle(), nullptr); + } + } + + // Get property value by property name. + template + ResultType Get(ReactPropertyId const &propertyId) const noexcept { + return Get(m_handle, propertyId); + } + + // Ensure that property is created by calling valueCreator if needed, and return value by property name. + // The TCreateValue must return either T or std::optional. It must have no parameters. + template + ResultType GetOrCreate(ReactPropertyId const &propertyId, TCreateValue const &createValue) const noexcept { + return GetOrCreate(m_handle, propertyId, createValue); + } + + // Set property value by property name. + template + void Set(ReactPropertyId const &propertyId, TValue const &value) const noexcept { + Set(m_handle, propertyId, value); + } + + // Removes property value by property name. + template + void Remove(ReactPropertyId const &propertyId) const noexcept { + Remove(m_handle, propertyId); + } + + // True if two ReactPropertyBags have the same handle. + friend bool operator==(const ReactPropertyBag &left, const ReactPropertyBag &right) noexcept { + return left.m_handle == right.m_handle; + } + + // True if two ReactPropertyBags have different handles. + friend bool operator!=(const ReactPropertyBag &left, const ReactPropertyBag &right) noexcept { + return left.m_handle != right.m_handle; + } + + // True if left ReactPropertyBag handle is null. + friend bool operator==(const ReactPropertyBag &left, std::nullptr_t) noexcept { + return !static_cast(left.m_handle); + } + + // True if left ReactPropertyBag handle is not null. + friend bool operator!=(const ReactPropertyBag &left, std::nullptr_t) noexcept { + return static_cast(left.m_handle); + } + + // True if right ReactPropertyBag handle is null. + friend bool operator==(std::nullptr_t, const ReactPropertyBag &right) noexcept { + return !static_cast(right.m_handle); + } + + // True if right ReactPropertyBag handle is not null. + friend bool operator!=(std::nullptr_t, const ReactPropertyBag &right) noexcept { + return static_cast(right.m_handle); + } + + private: + template + static Windows::Foundation::IInspectable ToObject(T const &value) noexcept { + return winrt::box_value(value); + } + + template + static Windows::Foundation::IInspectable ToObject(std::optional const &value) noexcept { + return value ? ToObject(*value) : nullptr; + } + + template + static auto FromObject(Windows::Foundation::IInspectable const &obj) noexcept { + if constexpr (std::is_base_of_v) { + return obj.try_as(); + } else { + if (obj) { +#ifdef WINRT_IMPL_IUNKNOWN_DEFINED + if constexpr (std::is_same_v) { + if (auto temp = obj.try_as>()) { + return std::optional{temp.Value()}; + } + } +#endif + if (auto temp = obj.try_as>()) { + return std::optional{temp.Value()}; + } + + if constexpr (std::is_enum_v) { + if (auto temp = obj.try_as>>()) { + return std::optional{static_cast(temp.Value())}; + } + } + } + + return std::optional{}; + } + } + + private: + IReactPropertyBag m_handle; +}; + +} // namespace winrt::Microsoft::ReactNative + +#endif // MICROSOFT_REACTNATIVE_PROPERTYBAG diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj b/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj index 5b1aacd65ec..6747f99b5dc 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj +++ b/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj @@ -108,6 +108,7 @@
+ diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp b/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp new file mode 100644 index 00000000000..7553d4be66a --- /dev/null +++ b/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp @@ -0,0 +1,509 @@ +#include "pch.h" + +#include +#include +#include + +using namespace winrt; +using namespace Microsoft::ReactNative; + +namespace ReactNativeIntegrationTests { + +TEST_CLASS (ReactPropertyBagTests) { + TEST_METHOD(StoreNamespace) { + // Return the same namespace object for the same string. + auto ns1 = ReactPropertyBagHelper::GetNamespace(L"Foo"); + auto ns2 = ReactPropertyBagHelper::GetNamespace(L"Foo"); + TestCheck(ns1); + TestCheck(ns2); + TestCheck(ns1 == ns2); + } + + TEST_METHOD(WeakNamespace) { + // Property bag keeps a weak reference to namespaces. + weak_ref nsWeak; + { + auto ns = ReactPropertyBagHelper::GetNamespace(L"Foo"); + TestCheck(ns); + nsWeak = ns; + TestCheck(nsWeak.get()); + } + TestCheck(!nsWeak.get()); + } + + TEST_METHOD(GlobalNamespace) { + // Global namespace is the same as the empty string + auto ns1 = ReactPropertyBagHelper::GlobalNamespace(); + auto ns2 = ReactPropertyBagHelper::GetNamespace(L""); + TestCheck(ns1); + TestCheck(ns2); + TestCheck(ns1 == ns2); + } + + TEST_METHOD(GlobalNamespaceNull) { + // Global namespace is the same as null string + auto ns1 = ReactPropertyBagHelper::GlobalNamespace(); + hstring nullStr{nullptr, take_ownership_from_abi}; + auto ns2 = ReactPropertyBagHelper::GetNamespace(nullStr); + TestCheck(ns1); + TestCheck(ns2); + TestCheck(ns1 == ns2); + } + + TEST_METHOD(WeakGlobalNamespace) { + // Property bag keeps a weak reference to the Global namespace. + weak_ref globalWeak; + { + auto global = ReactPropertyBagHelper::GlobalNamespace(); + TestCheck(global); + globalWeak = global; + TestCheck(globalWeak.get()); + } + TestCheck(!globalWeak.get()); + } + + TEST_METHOD(StoreName) { + // Return the same namespace object for the same string. + auto ns1 = ReactPropertyBagHelper::GetNamespace(L"Foo"); + auto n11 = ReactPropertyBagHelper::GetName(ns1, L"FooName"); + auto n12 = ReactPropertyBagHelper::GetName(ns1, L"FooName"); + TestCheck(n11); + TestCheck(n12); + TestCheck(n11 == n12); + } + + TEST_METHOD(StoreNameDifferentNamespace) { + // Return different name objects for the same string in different namespaces. + auto ns1 = ReactPropertyBagHelper::GetNamespace(L"Foo1"); + auto ns2 = ReactPropertyBagHelper::GetNamespace(L"Foo2"); + auto n11 = ReactPropertyBagHelper::GetName(ns1, L"FooName"); + auto n21 = ReactPropertyBagHelper::GetName(ns2, L"FooName"); + TestCheck(n11); + TestCheck(n21); + TestCheck(n11 != n21); + } + + TEST_METHOD(WeakName) { + // Property bag keeps a weak reference to namespaces. + weak_ref nWeak; + { + auto ns = ReactPropertyBagHelper::GetNamespace(L"Foo"); + auto n = ReactPropertyBagHelper::GetName(ns, L"Foo"); + TestCheck(ns); + TestCheck(n); + nWeak = n; + TestCheck(nWeak.get()); + } + TestCheck(!nWeak.get()); + } + + TEST_METHOD(GlobalNamespaceName) { + // null namespace is the same as global. + auto n1 = ReactPropertyBagHelper::GetName(nullptr, L"Foo"); + auto n2 = ReactPropertyBagHelper::GetName(ReactPropertyBagHelper::GlobalNamespace(), L"Foo"); + auto n3 = ReactPropertyBagHelper::GetName(ReactPropertyBagHelper::GetNamespace(L""), L"Foo"); + TestCheck(n1 == n2); + TestCheck(n1 == n3); + } + + TEST_METHOD(GetProperty_DoesNotExist) { + auto fooName = ReactPropertyBagHelper::GetName(nullptr, L"Foo"); + IReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + auto value = pb.Get(fooName); + TestCheck(!value); + } + + TEST_METHOD(GetProperty_Int) { + auto fooName = ReactPropertyBagHelper::GetName(nullptr, L"Foo"); + IReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + pb.Set(fooName, box_value(5)); + auto value = pb.Get(fooName); + TestCheck(value); + TestCheckEqual(5, unbox_value(value)); + } + + TEST_METHOD(GetOrCreateProperty_Int) { + auto fooName = ReactPropertyBagHelper::GetName(nullptr, L"Foo"); + IReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + auto value = pb.GetOrCreate(fooName, []() { return box_value(5); }); + TestCheck(value); + TestCheckEqual(5, unbox_value(value)); + } + + TEST_METHOD(SetProperty_Int) { + auto fooName = ReactPropertyBagHelper::GetName(nullptr, L"Foo"); + IReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + + auto value1 = pb.Get(fooName); + TestCheck(!value1); + + pb.Set(fooName, box_value(5)); + auto value2 = pb.Get(fooName); + TestCheck(value2); + TestCheckEqual(5, unbox_value(value2)); + + pb.Set(fooName, box_value(10)); + auto value3 = pb.Get(fooName); + TestCheck(value3); + TestCheckEqual(10, unbox_value(value3)); + + pb.Set(fooName, nullptr); + auto value4 = pb.Get(fooName); + TestCheck(!value4); + } + + TEST_METHOD(TwoProperties) { + auto fooName = ReactPropertyBagHelper::GetName(nullptr, L"Foo"); + auto barName = ReactPropertyBagHelper::GetName(nullptr, L"Bar"); + IReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + + pb.Set(fooName, box_value(5)); + pb.Set(barName, box_value(L"Hello")); + + auto value1 = pb.Get(fooName); + TestCheck(value1); + TestCheckEqual(5, unbox_value(value1)); + + auto value2 = pb.Get(barName); + TestCheck(value2); + TestCheckEqual(L"Hello", unbox_value(value2)); + } + + TEST_METHOD(RemoveProperty_Int) { + auto fooName = ReactPropertyBagHelper::GetName(nullptr, L"Foo"); + IReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + + pb.Set(fooName, box_value(5)); + auto value1 = pb.Get(fooName); + TestCheck(value1); + TestCheckEqual(5, unbox_value(value1)); + + pb.Set(fooName, nullptr); + auto value2 = pb.Get(fooName); + TestCheck(!value2); + } + + TEST_METHOD(PropertyNamespace_ctor_default) { + ReactPropertyNamespace ns1; + TestCheck(!ns1); + TestCheckEqual(L"", ns1.NamespaceName()); + TestCheckEqual(nullptr, ns1.Handle()); + } + + TEST_METHOD(PropertyNamespace_ctor_nullptr) { + ReactPropertyNamespace ns1{nullptr}; + TestCheck(!ns1); + TestCheckEqual(L"", ns1.NamespaceName()); + TestCheckEqual(nullptr, ns1.Handle()); + } + + TEST_METHOD(PropertyNamespace_ctor_IReactPropertyNamespace) { + ReactPropertyNamespace ns1{ReactPropertyBagHelper::GetNamespace(L"Foo")}; + TestCheck(ns1); + TestCheckEqual(ReactPropertyBagHelper::GetNamespace(L"Foo"), ns1.Handle()); + TestCheckEqual(L"Foo", ns1.Handle().NamespaceName()); + TestCheckEqual(L"Foo", ns1.NamespaceName()); + TestCheck(ReactPropertyBagHelper::GetNamespace(L"Bar") != ns1.Handle()); + } + + TEST_METHOD(PropertyNamespace_ctor_hstring) { + ReactPropertyNamespace ns1{L"Foo"}; + TestCheck(ns1); + TestCheckEqual(ReactPropertyBagHelper::GetNamespace(L"Foo"), ns1.Handle()); + TestCheckEqual(L"Foo", ns1.Handle().NamespaceName()); + TestCheckEqual(L"Foo", ns1.NamespaceName()); + TestCheck(ReactPropertyBagHelper::GetNamespace(L"Bar") != ns1.Handle()); + } + + TEST_METHOD(PropertyNamespace_ctor_copy) { + ReactPropertyNamespace ns1{L"Foo"}; + ReactPropertyNamespace ns2{ns1}; + TestCheck(ns1); + TestCheck(ns2); + TestCheckEqual(ReactPropertyBagHelper::GetNamespace(L"Foo"), ns1.Handle()); + TestCheckEqual(ReactPropertyBagHelper::GetNamespace(L"Foo"), ns2.Handle()); + } + + TEST_METHOD(PropertyNamespace_ctor_move) { + ReactPropertyNamespace ns1{L"Foo"}; + ReactPropertyNamespace ns2{std::move(ns1)}; + TestCheck(!ns1); + TestCheck(ns2); + TestCheckEqual(nullptr, ns1.Handle()); + TestCheckEqual(ReactPropertyBagHelper::GetNamespace(L"Foo"), ns2.Handle()); + } + + TEST_METHOD(PropertyNamespace_assign_copy) { + ReactPropertyNamespace ns1{L"Foo"}; + ReactPropertyNamespace ns2; + ns2 = ns1; + TestCheck(ns1); + TestCheck(ns2); + TestCheckEqual(ReactPropertyBagHelper::GetNamespace(L"Foo"), ns1.Handle()); + TestCheckEqual(ReactPropertyBagHelper::GetNamespace(L"Foo"), ns2.Handle()); + } + + TEST_METHOD(PropertyNamespace_assign_move) { + ReactPropertyNamespace ns1{L"Foo"}; + ReactPropertyNamespace ns2; + ns2 = std::move(ns1); + TestCheck(!ns1); + TestCheck(ns2); + TestCheckEqual(nullptr, ns1.Handle()); + TestCheckEqual(ReactPropertyBagHelper::GetNamespace(L"Foo"), ns2.Handle()); + } + + TEST_METHOD(PropertyNamespace_Global) { + ReactPropertyNamespace ns1{L""}; + TestCheckEqual(ReactPropertyBagHelper::GlobalNamespace(), ns1.Handle()); + TestCheckEqual(ReactPropertyBagHelper::GlobalNamespace(), ReactPropertyNamespace::Global().Handle()); + } + + TEST_METHOD(PropertyId_ctor_default) { + ReactPropertyId name1; + TestCheck(!name1); + TestCheckEqual(L"", name1.NamespaceName()); + TestCheckEqual(L"", name1.LocalName()); + TestCheckEqual(nullptr, name1.Handle()); + } + + TEST_METHOD(PropertyId_ctor_nullptr) { + ReactPropertyId name1{nullptr}; + TestCheck(!name1); + TestCheckEqual(L"", name1.NamespaceName()); + TestCheckEqual(L"", name1.LocalName()); + TestCheckEqual(nullptr, name1.Handle()); + } + + TEST_METHOD(PropertyId_ctor_IReactPropertyName) { + ReactPropertyId name1{ReactPropertyBagHelper::GetName(nullptr, L"Foo")}; + TestCheck(name1); + TestCheckEqual(ReactPropertyBagHelper::GetName(nullptr, L"Foo"), name1.Handle()); + TestCheckEqual(L"", name1.NamespaceName()); + TestCheckEqual(L"Foo", name1.LocalName()); + TestCheckEqual(L"Foo", name1.Handle().LocalName()); + TestCheck(ReactPropertyBagHelper::GetName(nullptr, L"Bar") != name1.Handle()); + } + + TEST_METHOD(PropertyId_ctor_hstring) { + ReactPropertyId name1{L"Foo"}; + TestCheck(name1); + TestCheckEqual(ReactPropertyBagHelper::GetName(nullptr, L"Foo"), name1.Handle()); + TestCheckEqual(L"", name1.NamespaceName()); + TestCheckEqual(L"Foo", name1.LocalName()); + TestCheckEqual(L"Foo", name1.Handle().LocalName()); + } + + TEST_METHOD(PropertyId_ctor_ns_hstring) { + ReactPropertyNamespace ns1{L"Foo"}; + ReactPropertyId name1{ns1, L"Bar"}; + TestCheck(name1); + TestCheckEqual( + ReactPropertyBagHelper::GetName(ReactPropertyBagHelper::GetNamespace(L"Foo"), L"Bar"), name1.Handle()); + TestCheckEqual(L"Foo", name1.NamespaceName()); + TestCheckEqual(L"Bar", name1.LocalName()); + TestCheckEqual(L"Bar", name1.Handle().LocalName()); + } + + TEST_METHOD(PropertyId_ctor_hstring_hstring) { + ReactPropertyId name1{L"Foo", L"Bar"}; + TestCheck(name1); + TestCheckEqual( + ReactPropertyBagHelper::GetName(ReactPropertyBagHelper::GetNamespace(L"Foo"), L"Bar"), name1.Handle()); + TestCheckEqual(L"Foo", name1.NamespaceName()); + TestCheckEqual(L"Bar", name1.LocalName()); + TestCheckEqual(L"Bar", name1.Handle().LocalName()); + } + + TEST_METHOD(PropertyId_ctor_copy) { + ReactPropertyId name1{L"Foo"}; + ReactPropertyId name2{name1}; + TestCheck(name1); + TestCheck(name2); + TestCheckEqual(ReactPropertyBagHelper::GetName(nullptr, L"Foo"), name1.Handle()); + TestCheckEqual(ReactPropertyBagHelper::GetName(nullptr, L"Foo"), name2.Handle()); + } + + TEST_METHOD(PropertyId_ctor_move) { + ReactPropertyId name1{L"Foo"}; + ReactPropertyId name2{std::move(name1)}; + TestCheck(!name1); + TestCheck(name2); + TestCheckEqual(nullptr, name1.Handle()); + TestCheckEqual(ReactPropertyBagHelper::GetName(nullptr, L"Foo"), name2.Handle()); + } + + TEST_METHOD(PropertyId_assign_copy) { + ReactPropertyId name1{L"Foo"}; + ReactPropertyId name2; + name2 = name1; + TestCheck(name1); + TestCheck(name2); + TestCheckEqual(ReactPropertyBagHelper::GetName(nullptr, L"Foo"), name1.Handle()); + TestCheckEqual(ReactPropertyBagHelper::GetName(nullptr, L"Foo"), name2.Handle()); + } + + TEST_METHOD(PropertyId_assign_move) { + ReactPropertyId name1{L"Foo"}; + ReactPropertyId name2; + name2 = std::move(name1); + TestCheck(!name1); + TestCheck(name2); + TestCheckEqual(nullptr, name1.Handle()); + TestCheckEqual(ReactPropertyBagHelper::GetName(nullptr, L"Foo"), name2.Handle()); + } + + TEST_METHOD(PropertyBag_ctor_default) { + ReactPropertyBag pb1; + TestCheck(!pb1); + TestCheckEqual(nullptr, pb1.Handle()); + TestCheck(nullptr == pb1); + TestCheck(pb1 == nullptr); + } + + TEST_METHOD(PropertyBag_ctor_nullptr) { + ReactPropertyBag pb1{nullptr}; + TestCheck(!pb1); + TestCheckEqual(nullptr, pb1.Handle()); + TestCheck(nullptr == pb1); + TestCheck(pb1 == nullptr); + } + + TEST_METHOD(PropertyId_ctor_IReactPropertyBag) { + IReactPropertyBag ipb1{ReactPropertyBagHelper::CreatePropertyBag()}; + ReactPropertyBag pb1{ipb1}; + TestCheck(pb1); + TestCheckEqual(ipb1, pb1.Handle()); + TestCheck(pb1.Handle()); + TestCheck(nullptr != pb1); + TestCheck(pb1 != nullptr); + } + + TEST_METHOD(PropertyBag_ctor_copy) { + IReactPropertyBag ipb1{ReactPropertyBagHelper::CreatePropertyBag()}; + ReactPropertyBag pb1{ipb1}; + ReactPropertyBag pb2{pb1}; + TestCheck(pb1); + TestCheck(pb2); + TestCheckEqual(ipb1, pb1.Handle()); + TestCheckEqual(ipb1, pb2.Handle()); + } + + TEST_METHOD(PropertyBag_ctor_move) { + IReactPropertyBag ipb1{ReactPropertyBagHelper::CreatePropertyBag()}; + ReactPropertyBag pb1{ipb1}; + ReactPropertyBag pb2{std::move(pb1)}; + TestCheck(!pb1); + TestCheck(pb2); + TestCheckEqual(nullptr, pb1.Handle()); + TestCheckEqual(ipb1, pb2.Handle()); + } + + TEST_METHOD(PropertyBag_assign_copy) { + IReactPropertyBag ipb1{ReactPropertyBagHelper::CreatePropertyBag()}; + ReactPropertyBag pb1{ipb1}; + ReactPropertyBag pb2; + pb2 = pb1; + TestCheck(pb1); + TestCheck(pb2); + TestCheckEqual(ipb1, pb1.Handle()); + TestCheckEqual(ipb1, pb2.Handle()); + } + + TEST_METHOD(PropertyBag_assign_move) { + IReactPropertyBag ipb1{ReactPropertyBagHelper::CreatePropertyBag()}; + ReactPropertyBag pb1{ipb1}; + ReactPropertyBag pb2; + pb2 = std::move(pb1); + TestCheck(!pb1); + TestCheck(pb2); + TestCheckEqual(nullptr, pb1.Handle()); + TestCheckEqual(ipb1, pb2.Handle()); + } + + TEST_METHOD(PropertyBag_equal) { + IReactPropertyBag ipb1{ReactPropertyBagHelper::CreatePropertyBag()}; + IReactPropertyBag ipb2{ReactPropertyBagHelper::CreatePropertyBag()}; + ReactPropertyBag pb11{ipb1}; + ReactPropertyBag pb12{ipb1}; + ReactPropertyBag pb21{ipb2}; + + TestCheck(pb11 == pb12); + TestCheck(pb12 == pb11); + TestCheck(pb11 != pb21); + TestCheck(pb21 != pb11); + } + + TEST_METHOD(PropertyBag_Property_int) { + ReactPropertyId fooName{L"Foo"}; + ReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + + TestCheck(!pb.Get(fooName)); + TestCheckEqual(5, *pb.GetOrCreate(fooName, []() { return 5; })); + TestCheckEqual(5, *pb.Get(fooName)); + pb.Set(fooName, 10); + TestCheckEqual(10, *pb.Get(fooName)); + pb.Remove(fooName); + TestCheck(!pb.Get(fooName)); + } + + TEST_METHOD(PropertyBag_Property_optional_int) { + ReactPropertyId fooName{L"Foo"}; + ReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + + TestCheck(!pb.Get(fooName)); + TestCheckEqual(5, *pb.GetOrCreate(fooName, []() { return std::optional{5}; })); + TestCheckEqual(5, *pb.Get(fooName)); + pb.Set(fooName, std::optional{10}); + TestCheckEqual(10, *pb.Get(fooName)); + pb.Remove(fooName); + TestCheck(!pb.Get(fooName)); + } + + TEST_METHOD(PropertyBag_Property_enum) { + // We only support enums defined in IDL. Use underlying type for C++ enums. + ReactPropertyId fooName{L"Foo"}; + ReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + + TestCheck(!pb.Get(fooName)); + TestCheckEqual(JSValueType::String, *pb.GetOrCreate(fooName, []() { return JSValueType::String; })); + TestCheckEqual(JSValueType::String, *pb.Get(fooName)); + pb.Set(fooName, JSValueType::Boolean); + TestCheckEqual(JSValueType::Boolean, *pb.Get(fooName)); + pb.Remove(fooName); + TestCheck(!pb.Get(fooName)); + } + + TEST_METHOD(PropertyBag_Property_ReactPropertyBag) { + // Store IInsectable-inherited type + ReactPropertyId fooName{L"Foo"}; + ReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + + IReactPropertyBag value1{ReactPropertyBagHelper::CreatePropertyBag()}; + IReactPropertyBag value2{ReactPropertyBagHelper::CreatePropertyBag()}; + TestCheck(!pb.Get(fooName)); + TestCheckEqual(value1, pb.GetOrCreate(fooName, [&value1]() { return value1; })); + TestCheckEqual(value1, pb.Get(fooName)); + pb.Set(fooName, value2); + TestCheckEqual(value2, pb.Get(fooName)); + pb.Remove(fooName); + TestCheck(!pb.Get(fooName)); + } + + TEST_METHOD(PropertyBag_Property_string) { + // We only support enums defined in IDL. + ReactPropertyId fooName{L"Foo"}; + ReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + + TestCheck(!pb.Get(fooName)); + TestCheckEqual(L"Hello", *pb.GetOrCreate(fooName, []() { return L"Hello"; })); + TestCheckEqual(L"Hello", *pb.Get(fooName)); + pb.Set(fooName, L"World"); + TestCheckEqual(L"World", *pb.Get(fooName)); + TestCheck(L"Hello" != *pb.Get(fooName)); + pb.Remove(fooName); + TestCheck(!pb.Get(fooName)); + } +}; + +} // namespace ReactNativeIntegrationTests diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/pch.h b/vnext/Microsoft.ReactNative.IntegrationTests/pch.h index df633651c1b..cde08a53662 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/pch.h +++ b/vnext/Microsoft.ReactNative.IntegrationTests/pch.h @@ -2,8 +2,10 @@ #define NOMINMAX -#include #include #include "NativeModules.h" #include "functional/functor.h" #include "motifCpp/testCheck.h" + +#undef GetCurrentTime +#include diff --git a/vnext/Microsoft.ReactNative.Managed.UnitTests/ReactModuleBuilderMock.cs b/vnext/Microsoft.ReactNative.Managed.UnitTests/ReactModuleBuilderMock.cs index 66fc037e2ad..c61cc11abfb 100644 --- a/vnext/Microsoft.ReactNative.Managed.UnitTests/ReactModuleBuilderMock.cs +++ b/vnext/Microsoft.ReactNative.Managed.UnitTests/ReactModuleBuilderMock.cs @@ -283,6 +283,8 @@ public ReactContextMock(ReactModuleBuilderMock builder) m_builder = builder; } + public IReactPropertyBag Properties { get; } = ReactPropertyBagHelper.CreatePropertyBag(); + public void DispatchEvent(FrameworkElement view, string eventName, JSValueArgWriter eventDataArgWriter) { throw new NotImplementedException(); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs index 35bc1bffc59..e61ea3dd654 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs @@ -7,29 +7,29 @@ namespace Microsoft.ReactNative.Managed { public struct ReactContext { - public ReactContext(IReactContext context) + public ReactContext(IReactContext handle) { - ContextAbi = context; + Handle = handle; } - public IReactContext ContextAbi { get; } + public IReactContext Handle { get; } public void DispatchEvent(FrameworkElement view, string eventName, T arg) { var argWriter = arg as JSValueArgWriter; if (argWriter != null) { - ContextAbi.DispatchEvent(view, eventName, argWriter); + Handle.DispatchEvent(view, eventName, argWriter); } else { - ContextAbi.DispatchEvent(view, eventName, (IJSValueWriter writer) => writer.WriteValue(arg)); + Handle.DispatchEvent(view, eventName, (IJSValueWriter writer) => writer.WriteValue(arg)); } } public void CallJSFunction(string moduleName, string methodName) { - ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs()); + Handle.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs()); } public void CallJSFunction(string moduleName, string methodName, T1 arg1) @@ -37,51 +37,51 @@ public void CallJSFunction(string moduleName, string methodName, T1 arg1) var argWriter = arg1 as JSValueArgWriter; if (argWriter != null) { - ContextAbi.CallJSFunction(moduleName, methodName, argWriter); + Handle.CallJSFunction(moduleName, methodName, argWriter); } else { - ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1)); + Handle.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1)); } } public void CallJSFunction(string moduleName, string methodName, T1 arg1, T2 arg2) { - ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2)); + Handle.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2)); } public void CallJSFunction(string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3) { - ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3)); + Handle.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3)); } public void CallJSFunction( string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { - ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4)); + Handle.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4)); } public void CallJSFunction( string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) { - ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5)); + Handle.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5)); } public void CallJSFunction( string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) { - ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6)); + Handle.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6)); } public void CallJSFunction( string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) { - ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6, arg7)); + Handle.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6, arg7)); } public void EmitJSEvent(string eventEmitterName, string eventName) { - ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter _) => { }); + Handle.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter _) => { }); } public void EmitJSEvent(string eventEmitterName, string eventName, T1 arg1) @@ -89,11 +89,11 @@ public void EmitJSEvent(string eventEmitterName, string eventName, T1 arg1) var argWriter = arg1 as JSValueArgWriter; if (argWriter != null) { - ContextAbi.EmitJSEvent(eventEmitterName, eventName, argWriter); + Handle.EmitJSEvent(eventEmitterName, eventName, argWriter); } else { - ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + Handle.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => { writer.WriteValue(arg1); }); @@ -102,7 +102,7 @@ public void EmitJSEvent(string eventEmitterName, string eventName, T1 arg1) public void EmitJSEvent(string eventEmitterName, string eventName, T1 arg1, T2 arg2) { - ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + Handle.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => { writer.WriteValue(arg1); writer.WriteValue(arg2); @@ -111,7 +111,7 @@ public void EmitJSEvent(string eventEmitterName, string eventName, T1 ar public void EmitJSEvent(string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3) { - ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + Handle.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => { writer.WriteValue(arg1); writer.WriteValue(arg2); @@ -122,7 +122,7 @@ public void EmitJSEvent(string eventEmitterName, string eventName, T public void EmitJSEvent( string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { - ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + Handle.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => { writer.WriteValue(arg1); writer.WriteValue(arg2); @@ -134,7 +134,7 @@ public void EmitJSEvent( public void EmitJSEvent( string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) { - ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + Handle.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => { writer.WriteValue(arg1); writer.WriteValue(arg2); @@ -147,7 +147,7 @@ public void EmitJSEvent( public void EmitJSEvent( string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) { - ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + Handle.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => { writer.WriteValue(arg1); writer.WriteValue(arg2); @@ -161,7 +161,7 @@ public void EmitJSEvent( public void EmitJSEvent( string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) { - ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + Handle.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => { writer.WriteValue(arg1); writer.WriteValue(arg2); diff --git a/vnext/Microsoft.ReactNative.sln b/vnext/Microsoft.ReactNative.sln index e800a3153c5..06dfd25b48b 100644 --- a/vnext/Microsoft.ReactNative.sln +++ b/vnext/Microsoft.ReactNative.sln @@ -31,7 +31,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso", "Mso\Mso.vcxitems", " EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso.UnitTests", "Mso.UnitTests\Mso.UnitTests.vcxproj", "{1958CEAA-FBE0-44E3-8A99-90AD85531FFE}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxitems", "{11c084a3-a57c-4296-a679-cac17b603145}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxitems", "{11C084A3-A57C-4296-A679-CAC17B603145}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxproj", "{11C084A3-A57C-4296-A679-CAC17B603144}" EndProject @@ -122,6 +122,8 @@ EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 + ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4 + ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603145}*SharedItemsImports = 9 Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{14fa0516-e6d7-4e4d-b097-1470198c5072}*SharedItemsImports = 4 Mso\Mso.vcxitems*{14fa0516-e6d7-4e4d-b097-1470198c5072}*SharedItemsImports = 4 Mso\Mso.vcxitems*{1958ceaa-fbe0-44e3-8a99-90ad85531ffe}*SharedItemsImports = 4 diff --git a/vnext/Microsoft.ReactNative/IReactContext.cpp b/vnext/Microsoft.ReactNative/IReactContext.cpp index 1215bea4d59..1032555d5d2 100644 --- a/vnext/Microsoft.ReactNative/IReactContext.cpp +++ b/vnext/Microsoft.ReactNative/IReactContext.cpp @@ -9,6 +9,10 @@ namespace winrt::Microsoft::ReactNative { ReactContext::ReactContext(Mso::CntPtr &&context) noexcept : m_context{std::move(context)} {} +IReactPropertyBag ReactContext::Properties() noexcept { + return m_context->Properties(); +} + void ReactContext::DispatchEvent( xaml::FrameworkElement const &view, hstring const &eventName, diff --git a/vnext/Microsoft.ReactNative/IReactContext.h b/vnext/Microsoft.ReactNative/IReactContext.h index 018619414c8..0ea7a200db2 100644 --- a/vnext/Microsoft.ReactNative/IReactContext.h +++ b/vnext/Microsoft.ReactNative/IReactContext.h @@ -12,6 +12,7 @@ struct ReactContext : winrt::implements { ReactContext(Mso::CntPtr &&context) noexcept; public: // IReactContext + IReactPropertyBag Properties() noexcept; void DispatchEvent( xaml::FrameworkElement const &view, hstring const &eventName, diff --git a/vnext/Microsoft.ReactNative/IReactContext.idl b/vnext/Microsoft.ReactNative/IReactContext.idl index 4770e20255a..1b4bdd826e5 100644 --- a/vnext/Microsoft.ReactNative/IReactContext.idl +++ b/vnext/Microsoft.ReactNative/IReactContext.idl @@ -2,6 +2,7 @@ // Licensed under the MIT License. import "IJSValueWriter.idl"; +import "IReactPropertyBag.idl"; #include "NamespaceRedirect.h" @@ -9,6 +10,7 @@ namespace Microsoft.ReactNative { [webhosthidden] interface IReactContext { + IReactPropertyBag Properties { get; }; void DispatchEvent(XAML_NAMESPACE.FrameworkElement view, String eventName, JSValueArgWriter eventDataArgWriter); void CallJSFunction(String moduleName, String methodName, JSValueArgWriter paramsArgWriter); void EmitJSEvent(String eventEmitterName, String eventName, JSValueArgWriter paramsArgWriter); diff --git a/vnext/Microsoft.ReactNative/IReactPropertyBag.cpp b/vnext/Microsoft.ReactNative/IReactPropertyBag.cpp new file mode 100644 index 00000000000..f1c519ba8df --- /dev/null +++ b/vnext/Microsoft.ReactNative/IReactPropertyBag.cpp @@ -0,0 +1,216 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" +#include "IReactPropertyBag.h" +#include "ReactPropertyBagHelper.g.cpp" +#include +#include +#include + +using namespace winrt; +using namespace Windows::Foundation; + +namespace winrt::Microsoft::ReactNative { + +template +struct ReactNametable : Mso::RefCountedObjectNoVTable> { + com_ptr GetOrCreate(hstring const &key, Mso::FunctorRef()> const &createValue) noexcept { + com_ptr result; + + { + // Try to retrieve value. + std::scoped_lock lock{m_mutex}; + result = m_entries[key].get(); + } + + if (!result) { + // If value cannot be retrieved, then create it outside of lock. + auto newValue = createValue(); + std::scoped_lock lock{m_mutex}; + // Make sure that the value was not inserted while we were unlocked + auto &entry = m_entries[key]; + result = entry.get(); + if (!result) { + result = std::move(newValue); + entry = result; + } + } + + return result; + } + + private: + std::mutex m_mutex; + std::unordered_map, std::hash, std::equal_to<>> m_entries; +}; + +struct ReactPropertyName; + +struct ReactPropertyNamespace : winrt::implements { + using NamespaceNametable = ReactNametable; + using LocalNameNametable = ReactNametable; + + ReactPropertyNamespace(hstring const &namespaceName) noexcept + : m_namespaceName{namespaceName}, m_localNames{Mso::Make()} {} + + static com_ptr GetNamespace(hstring const &namespaceName) noexcept { + if (namespaceName.size() == 0) { + return GlobalNamespace(); + } + + // Create the s_namespaces on demand. + auto namespaces = s_namespaces.load(std::memory_order_relaxed); + while (!namespaces) { + Mso::CntPtr newNamespaces = Mso::Make(); + if (s_namespaces.compare_exchange_weak(namespaces, newNamespaces.Get())) { + // We won the race: make sure that we store a pointer with ref count == 1. + namespaces = newNamespaces.Detach(); + } + } + + return namespaces->GetOrCreate( + namespaceName, [&namespaceName]() noexcept { return make_self(namespaceName); }); + } + + static com_ptr GlobalNamespace() noexcept { + com_ptr result; + + { + std::scoped_lock lock{s_mutex}; + result = s_globalNamespace.get(); + } + + if (!result) { + auto newGlobalNamespace = make_self(L""); + std::scoped_lock lock{s_mutex}; + // Make sure that the value was not inserted while we were unlocked + result = s_globalNamespace.get(); + if (!result) { + result = std::move(newGlobalNamespace); + s_globalNamespace = result; + } + } + + return result; + } + + com_ptr GetLocalName(hstring const &localName) noexcept; + + public: // IReactPropertyNamespace + hstring NamespaceName() noexcept { + return m_namespaceName; + } + + private: + static std::atomic s_namespaces; + static std::mutex s_mutex; + static weak_ref s_globalNamespace; + + hstring m_namespaceName; + Mso::CntPtr m_localNames; +}; + +/*static*/ std::atomic ReactPropertyNamespace::s_namespaces{nullptr}; +/*static*/ std::mutex ReactPropertyNamespace::s_mutex; +/*static*/ weak_ref ReactPropertyNamespace::s_globalNamespace; + +struct ReactPropertyName : winrt::implements { + ReactPropertyName(IReactPropertyNamespace const &ns, hstring const &localName) noexcept + : m_namespace{ns}, m_localName{localName} {} + + public: // IReactPropertyName + hstring LocalName() const noexcept { + return m_localName; + } + + IReactPropertyNamespace Namespace() const noexcept { + return m_namespace; + } + + private: + IReactPropertyNamespace m_namespace; + hstring m_localName; +}; + +com_ptr ReactPropertyNamespace::GetLocalName(hstring const &localName) noexcept { + // Implement outside of class because we need the ReactPropertyName definition. + return m_localNames->GetOrCreate(localName, [ this, &localName ]() noexcept { + IReactPropertyNamespace x = *this; + return make_self(x, localName); + }); +} + +} // namespace winrt::Microsoft::ReactNative + +namespace winrt::Microsoft::ReactNative::implementation { + +IInspectable ReactPropertyBag::Get(IReactPropertyName const &propertyName) noexcept { + std::scoped_lock lock{m_mutex}; + auto it = m_entries.find(propertyName); + if (it != m_entries.end()) { + return it->second; + } + + return {nullptr}; +} + +IInspectable ReactPropertyBag::GetOrCreate( + IReactPropertyName const &propertyName, + ReactCreatePropertyValue const &createValue) noexcept { + IInspectable result{Get(propertyName)}; + if (!result) { + IInspectable newValue = createValue(); + std::scoped_lock lock{m_mutex}; + auto &entry = m_entries[propertyName]; + if (!entry) { + entry = std::move(newValue); + } + + result = entry; + } + + return result; +} + +IInspectable ReactPropertyBag::Set(IReactPropertyName const &propertyName, IInspectable const &value) noexcept { + IInspectable result{nullptr}; + std::scoped_lock lock{m_mutex}; + if (value) { + auto &entry = m_entries[propertyName]; + result = std::move(entry); + entry = value; + } else { + auto it = m_entries.find(propertyName); + if (it != m_entries.end()) { + result = std::move(it->second); + m_entries.erase(it); + } + } + + return result; +} + +/*static*/ IReactPropertyNamespace ReactPropertyBagHelper::GlobalNamespace() noexcept { + return ReactPropertyNamespace::GlobalNamespace().as(); +} + +/*static*/ IReactPropertyNamespace ReactPropertyBagHelper::GetNamespace(hstring const &namespaceName) noexcept { + return ReactPropertyNamespace::GetNamespace(namespaceName).as(); +} + +/*static*/ IReactPropertyName ReactPropertyBagHelper::GetName( + IReactPropertyNamespace const &ns, + hstring const &localName) noexcept { + if (!ns) { + return ReactPropertyNamespace::GlobalNamespace()->GetLocalName(localName).as(); + } + + return get_self(ns)->GetLocalName(localName).as(); +} + +/*static*/ IReactPropertyBag ReactPropertyBagHelper::CreatePropertyBag() noexcept { + return make(); +} + +} // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Microsoft.ReactNative/IReactPropertyBag.h b/vnext/Microsoft.ReactNative/IReactPropertyBag.h new file mode 100644 index 00000000000..99fef4e766f --- /dev/null +++ b/vnext/Microsoft.ReactNative/IReactPropertyBag.h @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#include "ReactPropertyBagHelper.g.h" + +namespace winrt::Microsoft::ReactNative::implementation { + +struct ReactPropertyBag : implements { + ReactPropertyBag() = default; + + IInspectable Get(IReactPropertyName const &name) noexcept; + IInspectable GetOrCreate(IReactPropertyName const &name, ReactCreatePropertyValue const &createValue) noexcept; + IInspectable Set(IReactPropertyName const &name, IInspectable const &value) noexcept; + + private: + std::mutex m_mutex; + std::map m_entries; +}; + +struct ReactPropertyBagHelper { + ReactPropertyBagHelper() = default; + + static IReactPropertyNamespace GlobalNamespace() noexcept; + static IReactPropertyNamespace GetNamespace(hstring const &namespaceName) noexcept; + static IReactPropertyName GetName(IReactPropertyNamespace const &ns, hstring const &localName) noexcept; + static IReactPropertyBag CreatePropertyBag() noexcept; +}; + +} // namespace winrt::Microsoft::ReactNative::implementation + +namespace winrt::Microsoft::ReactNative::factory_implementation { + +struct ReactPropertyBagHelper + : ReactPropertyBagHelperT {}; + +} // namespace winrt::Microsoft::ReactNative::factory_implementation diff --git a/vnext/Microsoft.ReactNative/IReactPropertyBag.idl b/vnext/Microsoft.ReactNative/IReactPropertyBag.idl new file mode 100644 index 00000000000..b9ae64f6aed --- /dev/null +++ b/vnext/Microsoft.ReactNative/IReactPropertyBag.idl @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.ReactNative { + + // The delegate is used to create property value on-demand. + [webhosthidden] + delegate Object ReactCreatePropertyValue(); + + // Namespace for the property name. + // Use ReactPropertyBagHelper.GetNamespace to get atomic property namespace for a string. + [webhosthidden] + interface IReactPropertyNamespace { + // Get String name representation of the property namespace. + String NamespaceName { get; }; + } + + // Name of a property. + // Use ReactPropertyBagHelper.GetName to get atomic property name for a string. + [webhosthidden] + interface IReactPropertyName { + // The local property name String in context of the property namespace. + String LocalName { get; }; + + // The namespace the property name is defined in. + IReactPropertyNamespace Namespace { get; }; + } + + // The IReactPropertyBag provides a thread-safe property storage. + // Properties are identified by IReactPropertyName instance. + // It is expected that there will be no direct use of this interface. + // Ideally, all usage should happen through a strongly typed accessors. + [webhosthidden] + interface IReactPropertyBag + { + // Get property value by its name. It returns null if the property does not exist. + Object Get(IReactPropertyName name); + + // Get property value for the property name. + // If the property does not exist, then create it by calling createValue delegate. + // The function may return null if the createValue returns null when called. + // The createValue is called outside of lock. It is possible that its + // result is not used in case if other thread sets the property value before + // the created value is applied. + Object GetOrCreate(IReactPropertyName name, ReactCreatePropertyValue createValue); + + // Set property value for the property name. + // It returns previously stored property value. + // It returns null if property did not exist. + // If the new value is null, then the property is removed. + Object Set(IReactPropertyName name, Object value); + } + + // Helper methods for the property bag implementation. + [webhosthidden] + static runtimeclass ReactPropertyBagHelper { + // Return a global namespace that corresponds to an empty string. + static IReactPropertyNamespace GlobalNamespace { get; }; + + // Get an atomic IReactPropertyNamespace for a provided namespaceName. + // Consider to use module name as a namespace for module-specific properties. + static IReactPropertyNamespace GetNamespace(String namespaceName); + + // Get atomic IReactPropertyName for the namespace and local name. + // If ns is null, then it uses IReactPropertyNamespace.GlobalNamespace. + static IReactPropertyName GetName(IReactPropertyNamespace ns, String localName); + + // Create new instance of IReactPropertyBag + static IReactPropertyBag CreatePropertyBag(); + } +} // namespace Microsoft.ReactNative diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj index d5a8dcfeee3..4558c0c563e 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj @@ -91,8 +91,7 @@ true false - + @@ -328,8 +327,6 @@ - - @@ -352,6 +349,10 @@ IReactPackageBuilder.idl + + IReactPropertyBag.idl + Code + ReactRootView.idl Code @@ -490,7 +491,6 @@ - @@ -510,6 +510,10 @@ IReactPackageBuilder.idl + + IReactPropertyBag.idl + Code + ReactRootView.idl Code @@ -537,6 +541,7 @@ + diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters index e53f5484d2f..f5cee04be05 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters @@ -268,6 +268,7 @@ Modules + Modules @@ -285,9 +286,6 @@ ReactHost - - ReactHost - ReactHost @@ -300,8 +298,10 @@ ReactHost + + Threading @@ -315,10 +315,50 @@ Views - - + + Utils + + + Utils + + + Utils + + + Utils + + + Utils + + + Utils + + + Utils + + + Utils + + + Utils + + + Views + + + Views + + + Views + + + Views + + + Views + Base @@ -454,48 +494,6 @@ Polyester - - Utils - - - Utils - - - Utils - - - Utils - - - Utils - - - Utils - - - Utils - - - Utils - - - Utils - - - Views - - - Views - - - Views - - - Views - - - Views - Views @@ -605,6 +603,7 @@ Modules + Modules @@ -628,12 +627,6 @@ ReactHost - - ReactHost - - - ReactHost - ReactHost @@ -655,8 +648,10 @@ ReactHost + + Threading @@ -670,8 +665,6 @@ Views - - @@ -695,6 +688,7 @@ + diff --git a/vnext/Microsoft.ReactNative/NoExceptionAttribute.idl b/vnext/Microsoft.ReactNative/NoExceptionAttribute.idl index 0f4cb8e6a24..feb086ed997 100644 --- a/vnext/Microsoft.ReactNative/NoExceptionAttribute.idl +++ b/vnext/Microsoft.ReactNative/NoExceptionAttribute.idl @@ -3,7 +3,7 @@ namespace Windows.Foundation.Metadata { - // A temporary substitution for the [noexcept] attrbute that is + // A temporary substitution for the [noexcept] attribute that is // going to be implemented in future versions of Windows SDK // This attribute allows generation of noexcept methods. [attributeusage(target_method, target_property)] diff --git a/vnext/Microsoft.ReactNative/ReactHost/PropertyBag.cpp b/vnext/Microsoft.ReactNative/ReactHost/PropertyBag.cpp deleted file mode 100644 index 1424ab22ef0..00000000000 --- a/vnext/Microsoft.ReactNative/ReactHost/PropertyBag.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "PropertyBag.h" -#include "PropertyBag_internal.h" - -namespace Mso { -namespace JSHost { - -//============================================================================================= -// PropertyBag implementation -//============================================================================================= - -LIBLET_PUBLICAPI PropertyBag::PropertyBag() noexcept : m_content{Mso::Make()} {} - -LIBLET_PUBLICAPI PropertyBag::PropertyBag(std::nullptr_t) noexcept {} - -LIBLET_PUBLICAPI PropertyBag::PropertyBag(Mso::CntPtr &&content) noexcept - : m_content{std::move(content)} {} - -LIBLET_PUBLICAPI PropertyBag::PropertyBag(const PropertyBag &other) noexcept : m_content{other.m_content} {} - -LIBLET_PUBLICAPI PropertyBag::PropertyBag(PropertyBag &&other) noexcept : m_content{std::move(other.m_content)} {} - -LIBLET_PUBLICAPI PropertyBag::~PropertyBag() noexcept {} - -LIBLET_PUBLICAPI PropertyBag &PropertyBag::operator=(const PropertyBag &other) noexcept { - m_content = other.m_content; - return *this; -} - -LIBLET_PUBLICAPI PropertyBag &PropertyBag::operator=(PropertyBag &&other) noexcept { - m_content = std::move(other.m_content); - return *this; -} - -LIBLET_PUBLICAPI void PropertyBag::Remove(const char *propertyName) const noexcept { - m_content->Replace(nullptr, propertyName, nullptr); -} - -LIBLET_PUBLICAPI void PropertyBag::Remove(const void *isolationKey, const char *propertyName) const noexcept { - m_content->Replace(isolationKey, propertyName, nullptr); -} - -//============================================================================================= -// IsolatedIdComparer implementation -//============================================================================================= - -bool IsolatedIdComparer::operator()(const IsolatedId &left, const IsolatedId &right) const noexcept { - if (left.IsolationKey < right.IsolationKey) { - return true; - } else if (left.IsolationKey > right.IsolationKey) { - return false; - } else { - return left.PropertyName < right.PropertyName; - } -} - -//============================================================================================= -// ThreadSafePropertyBag implementation -//============================================================================================= - -Mso::CntPtr ThreadSafePropertyBag::GetOrCreate( - const void *isolationKey, - const char *propertyName, - const Mso::FunctorRef()> &valueMaker) noexcept { - IsolatedId isolatedId{reinterpret_cast(isolationKey), std::string{propertyName}}; - - Mso::CntPtr result = GetInternal(isolatedId); - - if (!result) { - result = valueMaker(); - if (result) { - std::lock_guard locker(m_lock); - // std::map operator[] creates a new entry if it is not found - auto &entry = m_isolatedObjects[isolatedId]; - if (!entry) { - entry = result; - } else { - // Entry is not empty - return existing value - result = entry; - } - } - } - - return result; -} - -Mso::CntPtr ThreadSafePropertyBag::Get(const void *isolationKey, const char *propertyName) const noexcept { - return GetInternal({reinterpret_cast(isolationKey), std::string{propertyName}}); -} - -Mso::CntPtr ThreadSafePropertyBag::GetInternal(const IsolatedId &isolatedId) const noexcept { - std::lock_guard locker(m_lock); - auto it = m_isolatedObjects.find(isolatedId); - return (it != m_isolatedObjects.end()) ? it->second : nullptr; -} - -Mso::CntPtr ThreadSafePropertyBag::Replace( - const void *isolationKey, - const char *propertyName, - Mso::CntPtr &&value) noexcept { - IsolatedId isolatedId{reinterpret_cast(isolationKey), std::string{propertyName}}; - - std::lock_guard locker(m_lock); - // std::map operator[] creates a new entry if it is not found - Mso::CntPtr &entry = m_isolatedObjects[isolatedId]; - Mso::CntPtr oldValue = std::move(entry); - entry = std::move(value); - return oldValue; -} - -//============================================================================================= -// WeakPropertyBagProxy implementation -//============================================================================================= - -WeakPropertyBagProxy::WeakPropertyBagProxy(const PropertyBag &propertyBag) noexcept - : m_weakPropertyBag{GetIPropertyBag(propertyBag)} {} - -Mso::CntPtr WeakPropertyBagProxy::GetOrCreate( - const void *isolationKey, - const char *propertyName, - const Mso::FunctorRef()> &valueMaker) noexcept { - if (auto propertyBag = m_weakPropertyBag.GetStrongPtr()) { - return propertyBag->GetOrCreate(isolationKey, propertyName, valueMaker); - } - return nullptr; -} - -Mso::CntPtr WeakPropertyBagProxy::Get(const void *isolationKey, const char *propertyName) const noexcept { - if (auto propertyBag = m_weakPropertyBag.GetStrongPtr()) { - return propertyBag->Get(isolationKey, propertyName); - } - return nullptr; -} - -Mso::CntPtr WeakPropertyBagProxy::Replace( - const void *isolationKey, - const char *propertyName, - Mso::CntPtr &&value) noexcept { - if (auto propertyBag = m_weakPropertyBag.GetStrongPtr()) { - return propertyBag->Replace(isolationKey, propertyName, std::move(value)); - } - return nullptr; -} - -//============================================================================================= -// PropertyBagLocalProxy implementation -//============================================================================================= - -PropertyBagLocalProxy::PropertyBagLocalProxy(IPropertyBag &propertyBag) noexcept : m_propertyBag{propertyBag} {} - -Mso::CntPtr PropertyBagLocalProxy::Replace( - const void *isolationKey, - const char *propertyName, - Mso::CntPtr &&value) noexcept { - return m_propertyBag.Replace(isolationKey, propertyName, std::move(value)); -} - -Mso::CntPtr PropertyBagLocalProxy::Get(const void *isolationKey, const char *propertyName) const noexcept { - return m_propertyBag.Get(isolationKey, propertyName); -} - -Mso::CntPtr PropertyBagLocalProxy::GetOrCreate( - const void *isolationKey, - const char *propertyName, - const Mso::FunctorRef()> &valueMaker) noexcept { - return m_propertyBag.GetOrCreate(isolationKey, propertyName, valueMaker); -} - -} // namespace JSHost -} // namespace Mso diff --git a/vnext/Microsoft.ReactNative/ReactHost/PropertyBag.h b/vnext/Microsoft.ReactNative/ReactHost/PropertyBag.h deleted file mode 100644 index be6b48aafed..00000000000 --- a/vnext/Microsoft.ReactNative/ReactHost/PropertyBag.h +++ /dev/null @@ -1,583 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once -#ifndef JSHOST_REKA_PROPERTYBAG_H -#define JSHOST_REKA_PROPERTYBAG_H - -//! -//! PropertyBag is a thread-safe storage of property values. -//! Each property has a name and optional isolation key. -//! Properties with null isolation key are considered global inside of the PropertyBag instance. -//! Isolation key allows to group properties or even hide/isolate them between different components. -//! Property name should be unique for the same isolation key. -//! Different isolation keys may have properties with the same name. -//! -//! The PropertyBag class is a smart pointer to the IPropertyBag ref-counted interface. -//! The IPropertyBag defines three methods: Get, GetOrCreate, and Replace: -//! - Get - returns a property value it exists or null otherwise. -//! - GetOrCreate - tries to find a property and creates if it is not found. -//! Since property value creation is called outside of lock, the valueMaker -//! could be called multiple times, but only first result is used. -//! GetOrCreate may return null if valueMaker returns null. -//! - Replace - replaces current property value with a new one and returns the old value. -//! Replacing property value with null, removes the property. -//! -//! On top of the untyped IPropertyBag interface, the PropertyBag offers a set of typed property accessors: -//! Get, GetOrCreate, Remove, and Set. -//! There can be two kinds of property value types: -//! - IUnknown inheriting interfaces. Each such type must have an associated GUID and be QI-able from the IUnknown. -//! Returning values are wrapped up into Mso::CntPtr. -//! - Other types. For other types we use an internal wrapper and we require to associate GUID with each such type. -//! Macro MSO_PROPERTY_TYPE_GUID can be used to associate property types with GUID. There are some predefined -//! association in this header file. Values of other types are wrapped up into std::optional. -//! -//! To simplify access to properties we offer NamedProperty and IsolatedNamedProperty types that help to -//! wrap up property type, name, and isolation key into one constant. -//! -//! For example, we can define a property to access UI dispatch queue: -//! -//! const Mso::JSHost::NamedProperty UIQueueProperty{"UIQueue"}; -//! -//! then we can use it to set property in Reka context during initialization: -//! -//! context.Properties().Set(UIQueueProperty, uiQueue); -//! -//! The property can be accessed later in a Reka service: -//! -//! auto uiQueue = context.Properties().Get(UIQueueProperty); -//! -//! The property can also be given to the RekaServiceWithQueueRegistration class -//! to always call service constructor, destructor, and its methods in UI queue: -//! -//! Mso::JSHost::RekaServiceWithQueueRegistration vTestServce{UIQueueProperty}; -//! - -#include -#include -#include "comUtil/qiCastCore.h" -#include "compilerAdapters/cppMacros.h" -#include "functional/functorRef.h" -#include "guid/msoGuid.h" -#include "object/unknownObject.h" - -//! To provide strongly typed access to non-IUnknown derived types we are associating -//! each type a with GUID. It is done by declaring a GetPropertyTypeGuid function -//! without implementation that receives a pointer of target type and returns -//! type with a GUID. -//! The MSO_PROPERTY_TYPE_GUID can be used do the associating with simple types. -//! For template specializations with a list of type parameters, you should -//! write the same two lines as in the MSO_PROPERTY_TYPE_GUID macro directly. -#define MSO_PROPERTY_TYPE_GUID(Type, GuidString) \ - MSO_STRUCT_GUID(Type##_PropertyTypeGuid, GuidString); \ - Type##_PropertyTypeGuid GetPropertyTypeGuid(Type *) noexcept; - -namespace Mso::JSHost { -namespace Details { - -//! Used for a default case when there is no associated GUID. -struct DefaultPropertyTypeGuid; - -//! The default case when type T has no associated GUID. -template -DefaultPropertyTypeGuid GetPropertyTypeGuid(T *) noexcept; - -// Associating GUID with the most common property types. -MSO_PROPERTY_TYPE_GUID(int8_t, "a7997e63-e468-4f4a-ac5e-71389563be98"); -MSO_PROPERTY_TYPE_GUID(int16_t, "86d5de2b-b9d9-4908-8f39-ade17a3e3809"); -MSO_PROPERTY_TYPE_GUID(int32_t, "40d0fbc8-32fb-4208-bae4-3ab5eef07233"); -MSO_PROPERTY_TYPE_GUID(int64_t, "00baf690-91c0-47a8-a6c0-cb448633ff28"); -MSO_PROPERTY_TYPE_GUID(uint8_t, "30461cc2-5849-47b6-9c00-bc38608cf823"); -MSO_PROPERTY_TYPE_GUID(uint16_t, "e07be325-6fb9-44c5-885d-0cdf3f4dcc58"); -MSO_PROPERTY_TYPE_GUID(uint32_t, "b6c3bdd2-ea46-4185-9f04-cad3f57c0edd"); -MSO_PROPERTY_TYPE_GUID(uint64_t, "3ed1dbad-d9c3-4989-b6be-6f59470b0034"); -MSO_PROPERTY_TYPE_GUID(double, "356c1104-fcd4-4595-a7ca-3aad6f2d51b8"); -MSO_PROPERTY_TYPE_GUID(float, "a82a427c-a454-4fd2-a866-c5c0ce3daf26"); -MSO_PROPERTY_TYPE_GUID(bool, "e8aa81bd-bbe4-4c55-a18f-edd97d25def4"); - -//! Associates property type with a GUID. -//! While it is possible to write PropertyTypeGuid::Value specialization -//! for the target type, the recommended way is to associate GUID with a property type -//! using MSO_PROPERTY_TYPE_GUID or declaring GetPropertyTypeGuid function. -template -struct PropertyTypeGuid { - static const GUID Value; -}; - -template -const GUID PropertyTypeGuid::Value = - __uuidof(decltype(GetPropertyTypeGuid(static_cast(nullptr)))); - -//! Wraps up property values non-inherited from IUnknown into an IUnknown based interface. -MSO_STRUCT_GUID(IPropertyValueWrapper, "8eedb560-d51d-4689-8601-3b02a74ed7a5") -struct IPropertyValueWrapper : IUnknown { - //! Gets the wrapped value and verifies that it has correct GUID and size. - virtual void *GetValue(const GUID &propertyTypeId, size_t valueSize) noexcept = 0; -}; - -//! IPropertyValueWrapper implementation. -template -struct PropertyValueWrapper : Mso::UnknownObject { - PropertyValueWrapper(const TProperty &value) noexcept : m_value{value} {} - - PropertyValueWrapper(TProperty &&value) noexcept : m_value{std::move(value)} {} - - //! Returns the wrapped value if GUID and size are matching. - //! Otherwise, it crashes the app. - void *GetValue(const GUID &propertyTypeId, size_t valueSize) noexcept override { - VerifyElseCrashSzTag( - propertyTypeId == PropertyTypeGuid::Value, "Incorrect value type", 0x0281d359 /* tag_c63nz */); - VerifyElseCrashSzTag(valueSize == sizeof(TProperty), "Incorrect value size", 0x0281d35a /* tag_c63n0 */); - return &m_value; - } - - private: - TProperty m_value; -}; - -//! Property traits for property types not inherited from IUnknown. -template -struct PropertyTraits { - // Use std::optional for return type to indicate missing values. - using ReturnType = std::optional; - - static Mso::CntPtr ToIUnknown(const TProperty &value) noexcept { - return Mso::Make, IUnknown>(value); - } - - static Mso::CntPtr ToIUnknown(TProperty &&value) noexcept { - return Mso::Make, IUnknown>(std::move(value)); - } - - static Mso::CntPtr ToIUnknown(const std::optional &value) noexcept { - return value ? Mso::Make, IUnknown>(*value) : nullptr; - } - - static Mso::CntPtr ToIUnknown(std::optional &&value) noexcept { - return value ? Mso::Make, IUnknown>(std::move(*value)) : nullptr; - } - - static std::optional FromIUnknown(Mso::CntPtr &&obj) noexcept { - if (obj) { - auto &wrapper = query_cast(*obj); - void *valuePtr = wrapper.GetValue(PropertyTypeGuid::Value, sizeof(TProperty)); - return std::optional{*static_cast(valuePtr)}; - } - return {}; - } -}; - -//! Property traits for property types inherited from IUnknown. -//! The type must be used as a pointer. -template -struct PropertyTraits::value>> { - using ReturnType = Mso::CntPtr; - - template - static Mso::CntPtr ToIUnknown(TValue &&value) noexcept { - return Mso::CntPtr(std::forward(value)); - } - - static Mso::CntPtr FromIUnknown(Mso::CntPtr &&obj) noexcept { - Mso::CntPtr result; - if (obj) { - IUnknown *unknownValue = obj.Get(); - TProperty *typedValue = query_cast(unknownValue); - if (typedValue) { - result.Attach(typedValue); - obj.Detach(); - } else { - result = qi_cast_or_crash(unknownValue); - } - } - - return result; - } -}; - -//! Property traits for property types inherited from IUnknown. -//! The type must be used as an Mso::CntPtr pointer. -template -struct PropertyTraits, std::enable_if_t::value>> { - using ReturnType = Mso::CntPtr; - - template - static Mso::CntPtr ToIUnknown(TValue &&value) noexcept { - return Mso::CntPtr(std::forward(value)); - } - - static Mso::CntPtr FromIUnknown(Mso::CntPtr &&obj) noexcept { - Mso::CntPtr result; - if (obj) { - IUnknown *unknownValue = obj.Get(); - TProperty *typedValue = query_cast(unknownValue); - if (typedValue) { - result.Attach(typedValue); - obj.Detach(); - } else { - result = qi_cast_or_crash(unknownValue); - } - } - - return result; - } -}; - -} // namespace Details - -//! Thread-safe untyped property bag interface definition. -//! PropertyBag uses instance of IPropertyBag to keep its content. -//! PropertyBag provides access to strongly typed properties. -//! -//! Properties are uniquely identified by an isolationKey and propertyName. -//! The isolationKey allows to have properties with the same name in the different scopes. -//! It also allows to define properties local to some component that does not share its isolationKey. -//! The isolationKey with a null value enables access to unscoped properties. -MSO_STRUCT_GUID(IPropertyBag, "ffd7e115-472a-45dc-bdaf-0765ab6b2361") -struct DECLSPEC_NOVTABLE IPropertyBag : IUnknown { - //! Gets value for the provided isolationKey and propertyName. - //! It returns nullptr if property does not exist. - virtual Mso::CntPtr Get(const void *isolationKey, const char *propertyName) const noexcept = 0; - - //! Ensures that property with the provided isolationKey and propertyName exists - //! by calling valueMaker if needed, and then returns the property value. - //! The function may return null if valueMaker returns null when called. - virtual Mso::CntPtr GetOrCreate( - const void *isolationKey, - const char *propertyName, - const Mso::FunctorRef()> &valueMaker) noexcept = 0; - - //! Replaces property value for the provided isolationKey and propertyName. - //! Returns previously stored value. - //! If provided value is null, then the property is removed. - virtual Mso::CntPtr - Replace(const void *isolationKey, const char *propertyName, Mso::CntPtr &&value) noexcept = 0; -}; - -//! Encapsulates property name and type in the same variable. -//! The typical use is to define properties as constants, and then use them in PropertyBag API. -template -struct NamedProperty { - using Type = T; - const char *Name{""}; -}; - -//! Encapsulates isolation key, property name, and property type in the same variable. -//! The typical use is to define properties as constants, and then use them in PropertyBag API. -template -struct IsolatedNamedProperty { - using Type = T; - const void *IsolationKey{nullptr}; - const char *Name{""}; -}; - -//! PropertyBag implementation that can store strongly-typed properties in a thread-safe way. -//! Types inherited from IUnknown are store directly as Mso::CntPtr. -//! Values of other types are wrapped up into PropertyValueWrapper object. -struct PropertyBag { - //! Property return type is either Mso::CntPtr or std::optional. - //! Mso::CntPtr is returned for types inherited from IUnknown. - //! The std::optional is returned for all other types. - template - using ReturnType = typename Details::PropertyTraits::ReturnType; - - //! Creates a new instance of PropertyBag. - LIBLET_PUBLICAPI PropertyBag() noexcept; - - //! Creates a new instance of PropertyBag with a null content. - LIBLET_PUBLICAPI PropertyBag(std::nullptr_t) noexcept; - - //! Creates a new instance of PropertyBag with the provided content. - LIBLET_PUBLICAPI PropertyBag(Mso::CntPtr &&content) noexcept; - - //! Creates a new instance of PropertyBag with the other PropertyBag content to share. - LIBLET_PUBLICAPI PropertyBag(const PropertyBag &other) noexcept; - - //! Creates a new instance of PropertyBag with content taken from the other PropertyBag. - //! The other PropertyBag content becomes null. - LIBLET_PUBLICAPI PropertyBag(PropertyBag &&other) noexcept; - - //! Destroys instance of PropertyBag. - LIBLET_PUBLICAPI ~PropertyBag() noexcept; - - //! Assigns the content from the other PropertyBag to share. - LIBLET_PUBLICAPI PropertyBag &operator=(const PropertyBag &other) noexcept; - - //! Assigns the content taken from the other PropertyBag. The other PropertyBag content becomes null. - LIBLET_PUBLICAPI PropertyBag &operator=(PropertyBag &&other) noexcept; - - //! True if content is not null. - explicit operator bool() const noexcept; - - //! Swaps content between two PropertyBags. - friend void swap(PropertyBag &left, PropertyBag &right) noexcept; - - //! Gets content from the PropertyBag. - friend IPropertyBag *GetIPropertyBag(const PropertyBag &propertyBag) noexcept; - - //! Gets property value by property name. - template - ReturnType Get(const char *propertyName) const noexcept; - - //! Gets property value by named property. - template - ReturnType Get(const NamedProperty &property) const noexcept; - - //! Gets property value by isolated named property. - template - ReturnType Get(const IsolatedNamedProperty &property) const noexcept; - - //! Gets property value by isolationKey and property name. - template - ReturnType Get(const void *isolationKey, const char *propertyName) const noexcept; - - //! Gets property value by isolationKey and named property. - template - ReturnType Get(const void *isolationKey, const NamedProperty &property) const noexcept; - - //! Ensures that property is created by calling valueMaker if needed, and returns value by property name. - template - ReturnType GetOrCreate( - const char *propertyName, - const Mso::FunctorRef()> &valueMaker) const noexcept; - - //! Ensures that property is created by calling valueMaker if needed, and returns value by named property. - template - ReturnType GetOrCreate( - const NamedProperty &property, - const Mso::FunctorRef()> &valueMaker) const noexcept; - - //! Ensures that property is created by calling valueMaker if needed, and returns value by isolated named property. - template - ReturnType GetOrCreate( - const IsolatedNamedProperty &property, - const Mso::FunctorRef()> &valueMaker) const noexcept; - - //! Ensures that property is created by calling valueMaker if needed, and returns value by isolationKey and property - //! name. - template - ReturnType GetOrCreate( - const void *isolationKey, - const char *propertyName, - const Mso::FunctorRef()> &valueMaker) const noexcept; - - //! Ensures that property is created by calling valueMaker if needed, and returns value by isolationKey and named - //! property. - template - ReturnType GetOrCreate( - const void *isolationKey, - const NamedProperty &property, - const Mso::FunctorRef()> &valueMaker) const noexcept; - - //! Removes property value by property name. - LIBLET_PUBLICAPI void Remove(const char *propertyName) const noexcept; - - //! Removes property value by named property. - template - void Remove(const NamedProperty &property) const noexcept; - - //! Removes property value by isolated named property. - template - void Remove(const IsolatedNamedProperty &property) const noexcept; - - //! Removes property value by isolationKey and property name. - LIBLET_PUBLICAPI void Remove(const void *isolationKey, const char *propertyName) const noexcept; - - //! Removes property value by isolationKey and named property. - template - void Remove(const void *isolationKey, const NamedProperty &property) const noexcept; - - //! Sets property value by property type and name. - template - void Set(const char *propertyName, TValue &&value) const noexcept; - - //! Sets property value by named property. - template - void Set(const NamedProperty &property, TValue &&value) const noexcept; - - //! Sets property value by isolated named property. - template - void Set(const IsolatedNamedProperty &property, TValue &&value) const noexcept; - - //! Sets property value by isolationKey, property type and name. - template - void Set(const void *isolationKey, const char *propertyName, TValue &&value) const noexcept; - - //! Sets property value by isolationKey and named property. - template - void Set(const void *isolationKey, const NamedProperty &property, TValue &&value) const noexcept; - - private: - Mso::CntPtr m_content; -}; - -//! Swaps content between two PropertyBags. -inline void swap(PropertyBag &left, PropertyBag &right) noexcept; - -//! Gets content from the PropertyBag. -inline IPropertyBag *GetIPropertyBag(const PropertyBag &propertyBag) noexcept; - -//! True if two PropertyBags have the same content object instance. -inline bool operator==(const PropertyBag &left, const PropertyBag &right) noexcept; - -//! True if two PropertyBags have different content object instances. -inline bool operator!=(const PropertyBag &left, const PropertyBag &right) noexcept; - -//! True if left PropertyBag content is null. -inline bool operator==(const PropertyBag &left, std::nullptr_t) noexcept; - -//! True if left PropertyBag content is not null. -inline bool operator!=(const PropertyBag &left, std::nullptr_t) noexcept; - -//! True if right PropertyBag content is null. -inline bool operator==(std::nullptr_t, const PropertyBag &left) noexcept; - -//! True if right PropertyBag content is not null. -inline bool operator!=(std::nullptr_t, const PropertyBag &left) noexcept; - -//======================================================================== -// PropertyBag inline implementation -//======================================================================== - -inline PropertyBag::operator bool() const noexcept { - return m_content != nullptr; -} - -template -PropertyBag::ReturnType PropertyBag::Get(const char *propertyName) const noexcept { - return Details::PropertyTraits::FromIUnknown(m_content->Get(nullptr, propertyName)); -} - -template -PropertyBag::ReturnType PropertyBag::Get(const NamedProperty &property) const noexcept { - return Details::PropertyTraits::FromIUnknown(m_content->Get(nullptr, property.Name)); -} - -template -PropertyBag::ReturnType PropertyBag::Get(const IsolatedNamedProperty &property) const noexcept { - return Details::PropertyTraits::FromIUnknown(m_content->Get(property.IsolationKey, property.Name)); -} - -template -PropertyBag::ReturnType PropertyBag::Get(const void *isolationKey, const char *propertyName) const noexcept { - return Details::PropertyTraits::FromIUnknown(m_content->Get(isolationKey, propertyName)); -} - -template -PropertyBag::ReturnType PropertyBag::Get(const void *isolationKey, const NamedProperty &property) - const noexcept { - return Details::PropertyTraits::FromIUnknown(m_content->Get(isolationKey, property.Name)); -} - -template -PropertyBag::ReturnType PropertyBag::GetOrCreate( - const char *propertyName, - const Mso::FunctorRef()> &valueMaker) const noexcept { - return Details::PropertyTraits::FromIUnknown( - m_content->GetOrCreate(nullptr, propertyName, [&valueMaker]() noexcept { - return Details::PropertyTraits::ToIUnknown(valueMaker()); - })); -} - -template -PropertyBag::ReturnType PropertyBag::GetOrCreate( - const NamedProperty &property, - const Mso::FunctorRef()> &valueMaker) const noexcept { - return Details::PropertyTraits::FromIUnknown( - m_content->GetOrCreate(nullptr, property.Name, [&valueMaker]() noexcept { - return Details::PropertyTraits::ToIUnknown(valueMaker()); - })); -} - -template -PropertyBag::ReturnType PropertyBag::GetOrCreate( - const IsolatedNamedProperty &property, - const Mso::FunctorRef()> &valueMaker) const noexcept { - return Details::PropertyTraits::FromIUnknown( - m_content->GetOrCreate(property.IsolationKey, property.Name, [&valueMaker]() noexcept { - return Details::PropertyTraits::ToIUnknown(valueMaker()); - })); -} - -template -PropertyBag::ReturnType PropertyBag::GetOrCreate( - const void *isolationKey, - const char *propertyName, - const Mso::FunctorRef()> &valueMaker) const noexcept { - return Details::PropertyTraits::FromIUnknown( - m_content->GetOrCreate(isolationKey, propertyName, [&valueMaker]() noexcept { - return Details::PropertyTraits::ToIUnknown(valueMaker()); - })); -} - -template -PropertyBag::ReturnType PropertyBag::GetOrCreate( - const void *isolationKey, - const NamedProperty &property, - const Mso::FunctorRef()> &valueMaker) const noexcept { - return Details::PropertyTraits::FromIUnknown( - m_content->GetOrCreate(isolationKey, property.Name, [&valueMaker]() noexcept { - return Details::PropertyTraits::ToIUnknown(valueMaker()); - })); -} - -template -void PropertyBag::Remove(const NamedProperty &property) const noexcept { - m_content->Replace(nullptr, property.Name, nullptr); -} - -template -void PropertyBag::Remove(const IsolatedNamedProperty &property) const noexcept { - m_content->Replace(property.IsolationKey, property.Name, nullptr); -} - -template -void PropertyBag::Remove(const void *isolationKey, const NamedProperty &property) const noexcept { - m_content->Replace(isolationKey, property.Name, nullptr); -} - -template -void PropertyBag::Set(const char *propertyName, TValue &&value) const noexcept { - m_content->Replace( - nullptr, propertyName, Details::PropertyTraits::ToIUnknown(std::forward(value))); -} - -template -void PropertyBag::Set(const NamedProperty &property, TValue &&value) const noexcept { - m_content->Replace( - nullptr, property.Name, Details::PropertyTraits::ToIUnknown(std::forward(value))); -} - -template -void PropertyBag::Set(const IsolatedNamedProperty &property, TValue &&value) const noexcept { - m_content->Replace( - property.IsolationKey, - property.Name, - Details::PropertyTraits::ToIUnknown(std::forward(value))); -} - -template -void PropertyBag::Set(const void *isolationKey, const char *propertyName, TValue &&value) const noexcept { - m_content->Replace( - isolationKey, propertyName, Details::PropertyTraits::ToIUnknown(std::forward(value))); -} - -template -void PropertyBag::Set(const void *isolationKey, const NamedProperty &property, TValue &&value) const - noexcept { - m_content->Replace( - isolationKey, property.Name, Details::PropertyTraits::ToIUnknown(std::forward(value))); -} - -inline void swap(PropertyBag &left, PropertyBag &right) noexcept { - using std::swap; - swap(left.m_content, right.m_content); -} - -inline IPropertyBag *GetIPropertyBag(const PropertyBag &propertyBag) noexcept { - return propertyBag.m_content.Get(); -} - -} // namespace Mso::JSHost - -#endif // JSHOST_REKA_PROPERTYBAG_H diff --git a/vnext/Microsoft.ReactNative/ReactHost/PropertyBag_internal.h b/vnext/Microsoft.ReactNative/ReactHost/PropertyBag_internal.h deleted file mode 100644 index 673c3d6c6c7..00000000000 --- a/vnext/Microsoft.ReactNative/ReactHost/PropertyBag_internal.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include -#include -#include -#include "PropertyBag.h" -#include "object/unknownObject.h" - -namespace Mso::JSHost { - -struct IsolatedId { - intptr_t IsolationKey; - std::string PropertyName; -}; - -struct IsolatedIdComparer { - bool operator()(const IsolatedId &left, const IsolatedId &right) const noexcept; -}; - -// IPropertyBag implementation that uses thread safe storage -struct ThreadSafePropertyBag final : Mso::UnknownObject { - Mso::CntPtr GetOrCreate( - const void *isolationKey, - const char *propertyName, - const Mso::FunctorRef()> &valueMaker) noexcept override; - - Mso::CntPtr Get(const void *isolationKey, const char *propertyName) const noexcept override; - - Mso::CntPtr - Replace(const void *isolationKey, const char *propertyName, Mso::CntPtr &&value) noexcept override; - - private: - Mso::CntPtr GetInternal(const IsolatedId &isolatedId) const noexcept; - - private: - mutable std::mutex m_lock; - std::map, IsolatedIdComparer> m_isolatedObjects; -}; - -struct WeakPropertyBagProxy final : Mso::UnknownObject { - WeakPropertyBagProxy(const PropertyBag &propertyBag) noexcept; - - Mso::CntPtr GetOrCreate( - const void *isolationKey, - const char *propertyName, - const Mso::FunctorRef()> &valueMaker) noexcept override; - - Mso::CntPtr Get(const void *isolationKey, const char *propertyName) const noexcept override; - - Mso::CntPtr - Replace(const void *isolationKey, const char *propertyName, Mso::CntPtr &&value) noexcept override; - - private: - Mso::WeakPtr m_weakPropertyBag; -}; - -// IPropertyBag non ref-counting proxy to another IPropertyBag. -// This is intended to be allocate on a call stack or by std::make_unique. -// It does not implement ref counting for itself and does not change ref count for provided IPropertyBag. -struct PropertyBagLocalProxy final : Mso::UnknownObject { - PropertyBagLocalProxy(IPropertyBag &propertyBag) noexcept; - - Mso::CntPtr GetOrCreate( - const void *isolationKey, - const char *propertyName, - const Mso::FunctorRef()> &valueMaker) noexcept override; - - Mso::CntPtr Get(const void *isolationKey, const char *propertyName) const noexcept override; - - Mso::CntPtr - Replace(const void *isolationKey, const char *propertyName, Mso::CntPtr &&value) noexcept override; - - private: - IPropertyBag &m_propertyBag; -}; - -} // namespace Mso::JSHost diff --git a/vnext/Microsoft.ReactNative/ReactHost/React.h b/vnext/Microsoft.ReactNative/ReactHost/React.h index 567fa021cf4..11a44973a68 100644 --- a/vnext/Microsoft.ReactNative/ReactHost/React.h +++ b/vnext/Microsoft.ReactNative/ReactHost/React.h @@ -9,7 +9,6 @@ #include #include "JSBundle.h" -#include "PropertyBag.h" #include "RedBoxHandler.h" #include "dispatchQueue/dispatchQueue.h" #include "errorCode/errorCode.h" @@ -18,6 +17,7 @@ #include #include #include +#include namespace Mso::React { @@ -43,13 +43,6 @@ using OnReactInstanceDestroyedCallback = Mso::Functor; //! Returns default OnError handler. LIBLET_PUBLICAPI OnErrorCallback GetDefaultOnErrorHandler() noexcept; -//! PropertyBag named property for JavaScript dispatch queue. -constexpr const Mso::JSHost::NamedProperty JSDispatchQueueProperty{"JSDispatchQueue"}; - -//! PropertyBag named property for Native dispatch queue. -constexpr const Mso::JSHost::NamedProperty NativeDispatchQueueProperty{ - "NativeDispatchQueue"}; - enum class ReactInstanceState { Loading, WaitingForDebugger, @@ -71,6 +64,7 @@ struct IReactInstance : IUnknown { MSO_GUID(IReactContext, "a4309a29-8fc5-478e-abea-0ddb9ecc5e40") struct IReactContext : IUnknown { + virtual winrt::Microsoft::ReactNative::IReactPropertyBag Properties() noexcept = 0; virtual void CallJSFunction(std::string &&module, std::string &&method, folly::dynamic &¶ms) noexcept = 0; virtual void DispatchEvent(int64_t viewTag, std::string &&eventName, folly::dynamic &&eventData) noexcept = 0; }; @@ -153,6 +147,8 @@ struct ViewManagerProvider2 { struct ReactOptions { react::uwp::ReactInstanceSettings LegacySettings; + winrt::Microsoft::ReactNative::IReactPropertyBag Properties; + std::shared_ptr ModuleProvider; std::shared_ptr ViewManagerProvider; @@ -219,9 +215,6 @@ struct ReactOptions { ReactDevOptions DeveloperSettings = {}; - //! Additional properties associated with the ReactOptions. - Mso::JSHost::PropertyBag Properties; - //! Adds registered JS bundle to JSBundles. LIBLET_PUBLICAPI ReactOptions &AddRegisteredJSBundle(std::string_view jsBundleId) noexcept; diff --git a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp index d759d30a997..957aca066f2 100644 --- a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +++ b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp @@ -63,8 +63,14 @@ namespace Mso::React { // ReactContext implementation //============================================================================================= -ReactContext::ReactContext(Mso::WeakPtr &&reactInstance) noexcept - : m_reactInstance{std::move(reactInstance)} {} +ReactContext::ReactContext( + Mso::WeakPtr &&reactInstance, + winrt::Microsoft::ReactNative::IReactPropertyBag const &properties) noexcept + : m_reactInstance{std::move(reactInstance)}, m_properties{properties} {} + +winrt::Microsoft::ReactNative::IReactPropertyBag ReactContext::Properties() noexcept { + return m_properties; +} void ReactContext::CallJSFunction(std::string &&module, std::string &&method, folly::dynamic &¶ms) noexcept { if (auto instance = m_reactInstance.GetStrongPtr()) { @@ -115,17 +121,17 @@ struct LoadedCallbackGuard { ReactInstanceWin::ReactInstanceWin( IReactHost &reactHost, - ReactOptions &&options, + ReactOptions const &options, Mso::Promise &&whenCreated, Mso::Promise &&whenLoaded, Mso::VoidFunctor &&updateUI) noexcept : Super{reactHost.NativeQueue()}, m_weakReactHost{&reactHost}, - m_options{std::move(options)}, + m_options{options}, m_whenCreated{std::move(whenCreated)}, m_whenLoaded{std::move(whenLoaded)}, m_updateUI{std::move(updateUI)}, - m_reactContext{Mso::Make(this)}, + m_reactContext{Mso::Make(this, options.Properties)}, m_legacyInstance{std::make_shared( Mso::WeakPtr{this}, Mso::Copy(options.LegacySettings))} { @@ -431,15 +437,7 @@ ReactInstanceState ReactInstanceWin::State() const noexcept { } void ReactInstanceWin::InitJSMessageThread() noexcept { - // Use the explicit JSQueue if it is provided. - const auto &properties = m_options.Properties; - auto jsDispatchQueue = Mso::DispatchQueue{properties.Get(JSDispatchQueueProperty)}; - if (jsDispatchQueue) { - VerifyElseCrashSz(jsDispatchQueue.IsSerial(), "JS Queue must be sequential"); - } else { - // Currently we have to use Looper DispatchQueue because our JS Engine based on Chakra uses thread local storage. - jsDispatchQueue = Mso::DispatchQueue::MakeLooperQueue(); - } + auto jsDispatchQueue = Mso::DispatchQueue::MakeLooperQueue(); // Create MessageQueueThread for the DispatchQueue VerifyElseCrashSz(jsDispatchQueue, "m_jsDispatchQueue must not be null"); diff --git a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h index 717e4ded4eb..7a90f7da41b 100644 --- a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +++ b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h @@ -39,14 +39,18 @@ class ReactInstanceWin; class ReactContext final : public Mso::UnknownObject { public: - ReactContext(Mso::WeakPtr &&reactInstance) noexcept; + ReactContext( + Mso::WeakPtr &&reactInstance, + winrt::Microsoft::ReactNative::IReactPropertyBag const &properties) noexcept; public: // IReactContext + winrt::Microsoft::ReactNative::IReactPropertyBag Properties() noexcept override; void CallJSFunction(std::string &&module, std::string &&method, folly::dynamic &¶ms) noexcept override; void DispatchEvent(int64_t viewTag, std::string &&eventName, folly::dynamic &&eventData) noexcept override; private: Mso::WeakPtr m_reactInstance; + winrt::Microsoft::ReactNative::IReactPropertyBag m_properties; }; //! ReactInstance implementation for Windows that is managed by ReactHost. @@ -79,7 +83,7 @@ class ReactInstanceWin final : public Mso::ActiveObject &viewManagerProvider = nullptr); ReactInstanceWin( IReactHost &reactHost, - ReactOptions &&options, + ReactOptions const &options, Mso::Promise &&whenCreated, Mso::Promise &&whenLoaded, Mso::VoidFunctor &&updateUI) noexcept; diff --git a/vnext/Microsoft.ReactNative/ReactInstanceSettings.h b/vnext/Microsoft.ReactNative/ReactInstanceSettings.h index 081ef1d2cfb..daeb91102b9 100644 --- a/vnext/Microsoft.ReactNative/ReactInstanceSettings.h +++ b/vnext/Microsoft.ReactNative/ReactInstanceSettings.h @@ -24,6 +24,8 @@ namespace winrt::Microsoft::ReactNative::implementation { struct ReactInstanceSettings : ReactInstanceSettingsT { ReactInstanceSettings() = default; + IReactPropertyBag Properties() noexcept; + hstring MainComponentName() noexcept; void MainComponentName(hstring const &value) noexcept; @@ -79,6 +81,7 @@ struct ReactInstanceSettings : ReactInstanceSettingsT { void DebuggerPort(uint16_t value) noexcept; private: + IReactPropertyBag m_properties{ReactPropertyBagHelper::CreatePropertyBag()}; hstring m_mainComponentName{}; bool m_useDeveloperSupport{REACT_DEFAULT_USE_DEVELOPER_SUPPORT}; hstring m_javaScriptMainModuleName{}; @@ -113,6 +116,10 @@ namespace winrt::Microsoft::ReactNative::implementation { // ReactInstanceSettings inline implementation //============================================================================================= +inline IReactPropertyBag ReactInstanceSettings::Properties() noexcept { + return m_properties; +} + inline hstring ReactInstanceSettings::MainComponentName() noexcept { return m_mainComponentName; } diff --git a/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl b/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl index d78b4149020..22887666ca3 100644 --- a/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl +++ b/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import "NoExceptionAttribute.idl"; +import "IReactPropertyBag.idl"; namespace Microsoft.ReactNative { @@ -10,6 +10,7 @@ namespace Microsoft.ReactNative { { ReactInstanceSettings(); + IReactPropertyBag Properties { get; }; String MainComponentName { get; set; }; Boolean UseDeveloperSupport { get; set; }; String JavaScriptMainModuleName { get; set; }; diff --git a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp index 61ed3d4e4a4..6812a46bef3 100644 --- a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp +++ b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp @@ -79,6 +79,7 @@ void ReactNativeHost::ReloadInstance() noexcept { legacySettings.DebuggerPort = m_instanceSettings.DebuggerPort(); Mso::React::ReactOptions reactOptions{}; + reactOptions.Properties = m_instanceSettings.Properties(); reactOptions.DeveloperSettings.IsDevModeEnabled = legacySettings.EnableDeveloperMenu; reactOptions.DeveloperSettings.SourceBundleName = legacySettings.DebugBundlePath; reactOptions.DeveloperSettings.UseWebDebugger = legacySettings.UseWebDebugger; diff --git a/vnext/Mso/crash/verifyElseCrash.h b/vnext/Mso/crash/verifyElseCrash.h index c7d5ddd7c87..69b0557ec10 100644 --- a/vnext/Mso/crash/verifyElseCrash.h +++ b/vnext/Mso/crash/verifyElseCrash.h @@ -11,10 +11,14 @@ DECLSPEC_NORETURN void CrashWithRecovery(uint32_t tag) noexcept; #define DisableVecAssert() false +#ifndef VerifyElseCrash #define VerifyElseCrash(f) VerifyElseCrashTag(f, UNTAGGED) +#endif #define VerifySucceededElseCrash(hr) VerifySucceededElseCrashTag(hr, UNTAGGED) #define VerifyElseCrashTag(f, tag) VerifyElseCrashSzTag(f, "False: " #f, tag) +#ifndef VerifyElseCrashSz #define VerifyElseCrashSz(f, sz) VerifyElseCrashSzTag(f, sz, UNTAGGED) +#endif // Asserts first so the dev can easily attach. If already attached, it does not assert // because bringing up the assert dialog can cause more code to run (OM:278842). diff --git a/vnext/ReactWindows-Desktop.sln b/vnext/ReactWindows-Desktop.sln index 85f6e997614..8e60ffd4d45 100644 --- a/vnext/ReactWindows-Desktop.sln +++ b/vnext/ReactWindows-Desktop.sln @@ -9,7 +9,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactCommon", "ReactCommon\ {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxitems", "{11c084a3-a57c-4296-a679-cac17b603145}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxitems", "{11C084A3-A57C-4296-A679-CAC17B603145}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore-Desktop", "ReactWindowsCore\ReactWindowsCore-Desktop.vcxproj", "{11C084A3-A57C-4296-A679-CAC17B603144}" ProjectSection(ProjectDependencies) = postProject @@ -123,6 +123,7 @@ Global GlobalSection(SharedMSBuildProjectFiles) = preSolution JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4 + ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603145}*SharedItemsImports = 9 JSI\Shared\JSI.Shared.vcxitems*{17dd1b17-3094-40dd-9373-ac2497932eca}*SharedItemsImports = 4 Mso\Mso.vcxitems*{1958ceaa-fbe0-44e3-8a99-90ad85531ffe}*SharedItemsImports = 4 Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 From 2db09bc3029c76cc4d207fd999333f708d81d0e4 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Sat, 9 May 2020 00:04:42 +0000 Subject: [PATCH 076/209] applying package updates ***NO_CI*** --- ...win32-2020-05-07-14-18-13-clifeedback.json | 8 --- ...ndows-2020-05-06-15-51-59-autolinking.json | 8 --- ...ws-2020-05-06-20-33-40-MS_PropertyBag.json | 8 --- ...ndows-2020-05-07-14-18-13-clifeedback.json | 8 --- ...-windows-2020-05-07-16-53-49-splitRWC.json | 8 --- ...ve-windows-2020-05-07-17-34-52-master.json | 8 --- ...s-2020-05-07-18-29-02-enable-binaryws.json | 8 --- ...05-07-19-10-10-MS.RN.IntegrationTests.json | 8 --- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- packages/react-native-win32/CHANGELOG.json | 15 ++++++ packages/react-native-win32/CHANGELOG.md | 10 +++- packages/react-native-win32/package.json | 2 +- vnext/CHANGELOG.json | 51 +++++++++++++++++++ vnext/CHANGELOG.md | 16 +++++- vnext/package.json | 2 +- 17 files changed, 95 insertions(+), 71 deletions(-) delete mode 100644 change/@office-iss-react-native-win32-2020-05-07-14-18-13-clifeedback.json delete mode 100644 change/react-native-windows-2020-05-06-15-51-59-autolinking.json delete mode 100644 change/react-native-windows-2020-05-06-20-33-40-MS_PropertyBag.json delete mode 100644 change/react-native-windows-2020-05-07-14-18-13-clifeedback.json delete mode 100644 change/react-native-windows-2020-05-07-16-53-49-splitRWC.json delete mode 100644 change/react-native-windows-2020-05-07-17-34-52-master.json delete mode 100644 change/react-native-windows-2020-05-07-18-29-02-enable-binaryws.json delete mode 100644 change/react-native-windows-2020-05-07-19-10-10-MS.RN.IntegrationTests.json diff --git a/change/@office-iss-react-native-win32-2020-05-07-14-18-13-clifeedback.json b/change/@office-iss-react-native-win32-2020-05-07-14-18-13-clifeedback.json deleted file mode 100644 index fd332b25345..00000000000 --- a/change/@office-iss-react-native-win32-2020-05-07-14-18-13-clifeedback.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Align local metro config with future CLI changes", - "packageName": "@office-iss/react-native-win32", - "email": "acoates@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-07T21:18:12.974Z" -} diff --git a/change/react-native-windows-2020-05-06-15-51-59-autolinking.json b/change/react-native-windows-2020-05-06-15-51-59-autolinking.json deleted file mode 100644 index 9b5ae58bc74..00000000000 --- a/change/react-native-windows-2020-05-06-15-51-59-autolinking.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Autolinking", - "packageName": "react-native-windows", - "email": "jthysell@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-06T22:51:59.672Z" -} diff --git a/change/react-native-windows-2020-05-06-20-33-40-MS_PropertyBag.json b/change/react-native-windows-2020-05-06-20-33-40-MS_PropertyBag.json deleted file mode 100644 index 93332582c6b..00000000000 --- a/change/react-native-windows-2020-05-06-20-33-40-MS_PropertyBag.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Implemented PropertyBag for ReactContext and ReactInstanceSettings", - "packageName": "react-native-windows", - "email": "vmorozov@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-07T03:33:40.086Z" -} diff --git a/change/react-native-windows-2020-05-07-14-18-13-clifeedback.json b/change/react-native-windows-2020-05-07-14-18-13-clifeedback.json deleted file mode 100644 index 0a15e1dc31e..00000000000 --- a/change/react-native-windows-2020-05-07-14-18-13-clifeedback.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Align local metro config with future CLI changes", - "packageName": "react-native-windows", - "email": "acoates@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-07T21:18:13.813Z" -} diff --git a/change/react-native-windows-2020-05-07-16-53-49-splitRWC.json b/change/react-native-windows-2020-05-07-16-53-49-splitRWC.json deleted file mode 100644 index be340025bd0..00000000000 --- a/change/react-native-windows-2020-05-07-16-53-49-splitRWC.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "separate desktop from uwp ReactWindowsCore since desktop uses V8", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-07T23:53:49.455Z" -} diff --git a/change/react-native-windows-2020-05-07-17-34-52-master.json b/change/react-native-windows-2020-05-07-17-34-52-master.json deleted file mode 100644 index 3a3b1e84193..00000000000 --- a/change/react-native-windows-2020-05-07-17-34-52-master.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Set C# langversion of templates back to 7.3 from 8.0", - "packageName": "react-native-windows", - "email": "dannyvv@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-08T00:34:52.261Z" -} diff --git a/change/react-native-windows-2020-05-07-18-29-02-enable-binaryws.json b/change/react-native-windows-2020-05-07-18-29-02-enable-binaryws.json deleted file mode 100644 index 0281eb0cf82..00000000000 --- a/change/react-native-windows-2020-05-07-18-29-02-enable-binaryws.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Correct binary message tagging", - "packageName": "react-native-windows", - "email": "julio.rocha@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-08T01:29:02.376Z" -} diff --git a/change/react-native-windows-2020-05-07-19-10-10-MS.RN.IntegrationTests.json b/change/react-native-windows-2020-05-07-19-10-10-MS.RN.IntegrationTests.json deleted file mode 100644 index f58b1afa289..00000000000 --- a/change/react-native-windows-2020-05-07-19-10-10-MS.RN.IntegrationTests.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Added Microsoft.ReactNative.IntegrationTests project to Microsoft.ReactNative.sln", - "packageName": "react-native-windows", - "email": "vmorozov@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-08T02:10:09.919Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index 2ed34937d60..43cc94f53a4 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.61" + "react-native-windows": "0.0.0-master.62" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 1259e9c60c5..512f96ab9ca 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.61" + "react-native-windows": "0.0.0-master.62" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index b4ad114bc06..429fc214d7b 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.61" + "react-native-windows": "0.0.0-master.62" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/react-native-win32/CHANGELOG.json b/packages/react-native-win32/CHANGELOG.json index 055afae980e..c1328fdab67 100644 --- a/packages/react-native-win32/CHANGELOG.json +++ b/packages/react-native-win32/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@office-iss/react-native-win32", "entries": [ + { + "date": "Sat, 09 May 2020 00:04:42 GMT", + "tag": "@office-iss/react-native-win32_v0.0.0-master.10", + "version": "0.0.0-master.10", + "comments": { + "prerelease": [ + { + "comment": "Align local metro config with future CLI changes", + "author": "acoates@microsoft.com", + "commit": "e4a5f453b6d1d85e19b6e7ae7350d92db81f3aaf", + "package": "@office-iss/react-native-win32" + } + ] + } + }, { "date": "Fri, 08 May 2020 00:05:16 GMT", "tag": "@office-iss/react-native-win32_v0.0.0-master.9", diff --git a/packages/react-native-win32/CHANGELOG.md b/packages/react-native-win32/CHANGELOG.md index 78a25298698..890deefd57e 100644 --- a/packages/react-native-win32/CHANGELOG.md +++ b/packages/react-native-win32/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @office-iss/react-native-win32 -This log was last generated on Fri, 08 May 2020 00:05:16 GMT and should not be manually modified. +This log was last generated on Sat, 09 May 2020 00:04:42 GMT and should not be manually modified. +## 0.0.0-master.10 + +Sat, 09 May 2020 00:04:42 GMT + +### Changes + +- Align local metro config with future CLI changes (acoates@microsoft.com) + ## 0.0.0-master.9 Fri, 08 May 2020 00:05:16 GMT diff --git a/packages/react-native-win32/package.json b/packages/react-native-win32/package.json index 41be5de4059..2344d647958 100644 --- a/packages/react-native-win32/package.json +++ b/packages/react-native-win32/package.json @@ -1,6 +1,6 @@ { "name": "@office-iss/react-native-win32", - "version": "0.0.0-master.9", + "version": "0.0.0-master.10", "description": "Implementation of react native on top of Office's Win32 platform.", "license": "MIT", "main": "./index.win32.js", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index 7927c055f3a..e5de6cf161b 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,57 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Sat, 09 May 2020 00:04:42 GMT", + "tag": "react-native-windows_v0.0.0-master.62", + "version": "0.0.0-master.62", + "comments": { + "prerelease": [ + { + "comment": "Autolinking", + "author": "jthysell@microsoft.com", + "commit": "4cfd393e489017ae619663782e37cfdafa004e53", + "package": "react-native-windows" + }, + { + "comment": "Implemented PropertyBag for ReactContext and ReactInstanceSettings", + "author": "vmorozov@microsoft.com", + "commit": "b590fffb4df3433111f917a2a71e9cad31fb1042", + "package": "react-native-windows" + }, + { + "comment": "Align local metro config with future CLI changes", + "author": "acoates@microsoft.com", + "commit": "e4a5f453b6d1d85e19b6e7ae7350d92db81f3aaf", + "package": "react-native-windows" + }, + { + "comment": "separate desktop from uwp ReactWindowsCore since desktop uses V8", + "author": "asklar@microsoft.com", + "commit": "951333f6e1bb811daafffc624b740ac7f1d3566f", + "package": "react-native-windows" + }, + { + "comment": "Set C# langversion of templates back to 7.3 from 8.0", + "author": "dannyvv@microsoft.com", + "commit": "082b57fe338378d03d00134d0628caa4d944fe4d", + "package": "react-native-windows" + }, + { + "comment": "Correct binary message tagging", + "author": "julio.rocha@microsoft.com", + "commit": "c51c3ad85dd7bce29c47ecffc861106b97f0d6f8", + "package": "react-native-windows" + }, + { + "comment": "Added Microsoft.ReactNative.IntegrationTests project to Microsoft.ReactNative.sln", + "author": "vmorozov@microsoft.com", + "commit": "ccce48832687e4f09f8343508e21d4272a1a0afc", + "package": "react-native-windows" + } + ] + } + }, { "date": "Fri, 08 May 2020 00:05:16 GMT", "tag": "react-native-windows_v0.0.0-master.61", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 167bacae0a2..740bdc37cfe 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,23 @@ # Change Log - react-native-windows -This log was last generated on Fri, 08 May 2020 00:05:16 GMT and should not be manually modified. +This log was last generated on Sat, 09 May 2020 00:04:42 GMT and should not be manually modified. +## 0.0.0-master.62 + +Sat, 09 May 2020 00:04:42 GMT + +### Changes + +- Autolinking (jthysell@microsoft.com) +- Implemented PropertyBag for ReactContext and ReactInstanceSettings (vmorozov@microsoft.com) +- Align local metro config with future CLI changes (acoates@microsoft.com) +- separate desktop from uwp ReactWindowsCore since desktop uses V8 (asklar@microsoft.com) +- Set C# langversion of templates back to 7.3 from 8.0 (dannyvv@microsoft.com) +- Correct binary message tagging (julio.rocha@microsoft.com) +- Added Microsoft.ReactNative.IntegrationTests project to Microsoft.ReactNative.sln (vmorozov@microsoft.com) + ## 0.0.0-master.61 Fri, 08 May 2020 00:05:16 GMT diff --git a/vnext/package.json b/vnext/package.json index 747dc6f7adc..b55fcc9940c 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.61", + "version": "0.0.0-master.62", "license": "MIT", "repository": { "type": "git", From 858fdce423bb4a0eac46dd4eca97adb3b6b042e9 Mon Sep 17 00:00:00 2001 From: tudorms <48035227+tudorms@users.noreply.github.com> Date: Sat, 9 May 2020 00:21:56 -0700 Subject: [PATCH 077/209] Reenable V8 for desktop projects (#4840) * Delay load ChakraCore.dll * Change files * clean up unneeded project references * Overwrite property after React.Cpp.props gets included * Change files * change file * Fix WinUI3 * Reverse the conditional logic * Revert some unnecessary changes. Consolidate the preprocessor defines in the props Co-authored-by: tudorm --- ...ve-windows-2020-05-08-14-17-35-master.json | 8 ++ packages/E2ETest/windows/ReactUWPTestApp.sln | 1 + .../playground-win32/Playground-win32.vcxproj | 2 - packages/playground/windows/playground.sln | 1 + .../React.Windows.Desktop.DLL.vcxproj | 18 +-- vnext/Desktop.DLL/packages.config | 1 + ...t.Windows.Desktop.IntegrationTests.vcxproj | 14 -- .../React.Windows.Desktop.UnitTests.vcxproj | 2 - vnext/Desktop/React.Windows.Desktop.vcxproj | 3 +- .../React.Windows.IntegrationTests.vcxproj | 3 - .../JSI.Desktop.UnitTests.vcxproj | 30 +---- vnext/JSI.Desktop.UnitTests/packages.config | 1 + vnext/JSI/Desktop/JSI.Desktop.vcxproj | 6 +- vnext/JSI/Universal/JSI.Universal.vcxproj | 5 - .../Microsoft.ReactNative.vcxproj | 2 - vnext/PropertySheets/React.Cpp.props | 4 +- vnext/ReactUWP/ReactUWP.vcxproj | 2 - vnext/ReactWindows-Desktop.sln | 1 - .../ReactWindowsCore.vcxitems | 12 -- vnext/Shared/Shared.vcxitems | 2 - .../React.Windows.Universal.UnitTests.vcxproj | 3 - vnext/V8Inspector/V8Inspector.vcxproj | 122 ------------------ vnext/V8Inspector/V8Inspector.vcxproj.filters | 63 --------- 23 files changed, 19 insertions(+), 287 deletions(-) create mode 100644 change/react-native-windows-2020-05-08-14-17-35-master.json delete mode 100644 vnext/V8Inspector/V8Inspector.vcxproj delete mode 100644 vnext/V8Inspector/V8Inspector.vcxproj.filters diff --git a/change/react-native-windows-2020-05-08-14-17-35-master.json b/change/react-native-windows-2020-05-08-14-17-35-master.json new file mode 100644 index 00000000000..c55a7882828 --- /dev/null +++ b/change/react-native-windows-2020-05-08-14-17-35-master.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Reenable V8 for desktop projects", + "packageName": "react-native-windows", + "email": "tudorm@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-08T21:17:35.875Z" +} diff --git a/packages/E2ETest/windows/ReactUWPTestApp.sln b/packages/E2ETest/windows/ReactUWPTestApp.sln index fd7c8a089aa..d632b950855 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp.sln +++ b/packages/E2ETest/windows/ReactUWPTestApp.sln @@ -43,6 +43,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ReactNative.Manag EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\..\..\vnext\ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4 ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4 ..\..\..\vnext\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 diff --git a/packages/playground/windows/playground-win32/Playground-win32.vcxproj b/packages/playground/windows/playground-win32/Playground-win32.vcxproj index 9e4ec292c29..19af51184fe 100644 --- a/packages/playground/windows/playground-win32/Playground-win32.vcxproj +++ b/packages/playground/windows/playground-win32/Playground-win32.vcxproj @@ -74,8 +74,6 @@ pch.h true Level3 - USE_V8;%(PreprocessorDefinitions) - USE_HERMES;%(PreprocessorDefinitions) shell32.lib;user32.lib;windowsapp.lib;$(ReactNativeWindowsDir)target\$(PlatformTarget)\$(Configuration)\ReactUWP\React.uwp.lib;%(AdditionalDependenices) diff --git a/packages/playground/windows/playground.sln b/packages/playground/windows/playground.sln index 6c610df8452..62a9c082eae 100644 --- a/packages/playground/windows/playground.sln +++ b/packages/playground/windows/playground.sln @@ -43,6 +43,7 @@ EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 + ..\..\..\vnext\ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4 ..\..\..\vnext\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 ..\..\..\vnext\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{67a1076f-7790-4203-86ea-4402ccb5e782}*SharedItemsImports = 13 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{6b6aa847-b32f-41ac-9d3b-48a8cdfa8ade}*SharedItemsImports = 4 diff --git a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj index c598ae4e5e7..5376bcd160f 100644 --- a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj +++ b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj @@ -63,10 +63,8 @@ WIN32; _WINDOWS; _USRDLL; - REACTNATIVEWIN32_EXPORTS; FOLLY_NO_CONFIG; NOMINMAX; - GLOG_NO_ABBREVIATED_SEVERITIES; _HAS_AUTO_PTR_ETC; CHAKRACORE; RN_EXPORT=; @@ -122,21 +120,6 @@ - - {fca38f3c-7c73-4c47-be4e-32f77fa8538d} - - - {A990658C-CE31-4BCC-976F-0FC6B1AF693D} - - - {74085F13-2DDE-45E5-A0CA-927AC9D0B953} - - - {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} - - - {11C084A3-A57C-4296-A679-CAC17B603144} - {95048601-C3DC-475F-ADF8-7C0C764C10D5} @@ -169,6 +152,7 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + diff --git a/vnext/Desktop.DLL/packages.config b/vnext/Desktop.DLL/packages.config index 50494a3bc9d..aa1174628fc 100644 --- a/vnext/Desktop.DLL/packages.config +++ b/vnext/Desktop.DLL/packages.config @@ -4,4 +4,5 @@ + \ No newline at end of file diff --git a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj index 44603739225..a44671c4fd1 100644 --- a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj +++ b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj @@ -55,10 +55,8 @@ _WIN32_WINNT=$(WinVer); WIN32; _WINDOWS; - REACTNATIVEWIN32_EXPORTS; FOLLY_NO_CONFIG; NOMINMAX; - GLOG_NO_ABBREVIATED_SEVERITIES; _HAS_AUTO_PTR_ETC; CHAKRACORE; RN_PLATFORM=windesktop; @@ -102,21 +100,9 @@ - - {fca38f3c-7c73-4c47-be4e-32f77fa8538d} - {A990658C-CE31-4BCC-976F-0FC6B1AF693D} - - {74085F13-2DDE-45E5-A0CA-927AC9D0B953} - - - {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} - - - {11C084A3-A57C-4296-A679-CAC17B603144} - {700A84FD-F92A-43F1-8D06-B0E0745DF9B5} diff --git a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj index 1048078ca0f..84f5784e4f1 100644 --- a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj +++ b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj @@ -53,10 +53,8 @@ _WIN32_WINNT=$(WinVer); WIN32; _WINDOWS; - REACTNATIVEWIN32_EXPORTS; FOLLY_NO_CONFIG; NOMINMAX; - GLOG_NO_ABBREVIATED_SEVERITIES; _HAS_AUTO_PTR_ETC; CHAKRACORE; RN_EXPORT=; diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj b/vnext/Desktop/React.Windows.Desktop.vcxproj index 41a7846d4fd..556cb33f4db 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj @@ -72,10 +72,8 @@ _WIN32_WINNT=$(WinVer); WIN32; _WINDOWS; - REACTNATIVEWIN32_EXPORTS; FOLLY_NO_CONFIG; NOMINMAX; - GLOG_NO_ABBREVIATED_SEVERITIES; _HAS_AUTO_PTR_ETC; CHAKRACORE; RN_PLATFORM=win32; @@ -196,6 +194,7 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + diff --git a/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj b/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj index 470ab3aadbd..1023d7466b2 100644 --- a/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj +++ b/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj @@ -64,9 +64,6 @@ {fca38f3c-7c73-4c47-be4e-32f77fa8538d} - - {11C084A3-A57C-4296-A679-CAC17B603144} - diff --git a/vnext/JSI.Desktop.UnitTests/JSI.Desktop.UnitTests.vcxproj b/vnext/JSI.Desktop.UnitTests/JSI.Desktop.UnitTests.vcxproj index 6dbf207ef0d..c51a6f46a48 100644 --- a/vnext/JSI.Desktop.UnitTests/JSI.Desktop.UnitTests.vcxproj +++ b/vnext/JSI.Desktop.UnitTests/JSI.Desktop.UnitTests.vcxproj @@ -26,16 +26,9 @@ - - - - - - - $(ReactNativeWindowsDir);$(ReactNativeWindowsDir)Common;$(ReactNativeWindowsDir)stubs;$(FollyDir);$(ReactNativeDir)\ReactCommon;$(JSI_Source);$(ReactNativeWindowsDir)ReactWindowsCore;$(ReactNativeWindowsDir)\ReactWindowsCore\tracing;$(ReactNativeWindowsDir)include\ReactWindowsCore;$(ReactNativeWindowsDir)Desktop;$(ReactNativeWindowsDir)IntegrationTests;$(ReactNativeWindowsDir)JSI\Shared;$(MSBuildProjectDirectory);$(ReactNativeDir)\ReactCommon\callinvoker;$(IncludePath) true @@ -53,10 +46,8 @@ _WIN32_WINNT=$(WinVer); WIN32; _WINDOWS; - REACTNATIVEWIN32_EXPORTS; FOLLY_NO_CONFIG; NOMINMAX; - GLOG_NO_ABBREVIATED_SEVERITIES; _HAS_AUTO_PTR_ETC; CHAKRACORE; RN_EXPORT=; @@ -73,16 +64,8 @@ -minpdbpathlen:256 - - comsuppw.lib; delayimp.lib; - Shlwapi.lib; - Winhttp.lib; %(AdditionalDependencies) DebugFull @@ -119,21 +102,9 @@ - - {fca38f3c-7c73-4c47-be4e-32f77fa8538d} - - - {A990658C-CE31-4BCC-976F-0FC6B1AF693D} - - - {74085F13-2DDE-45E5-A0CA-927AC9D0B953} - {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} - - {11C084A3-A57C-4296-A679-CAC17B603144} - {95048601-C3DC-475F-ADF8-7C0C764C10D5} @@ -158,6 +129,7 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + diff --git a/vnext/JSI.Desktop.UnitTests/packages.config b/vnext/JSI.Desktop.UnitTests/packages.config index d9a6b100a5f..87f1304896e 100644 --- a/vnext/JSI.Desktop.UnitTests/packages.config +++ b/vnext/JSI.Desktop.UnitTests/packages.config @@ -6,4 +6,5 @@ + \ No newline at end of file diff --git a/vnext/JSI/Desktop/JSI.Desktop.vcxproj b/vnext/JSI/Desktop/JSI.Desktop.vcxproj index 0737e735265..58788a35444 100644 --- a/vnext/JSI/Desktop/JSI.Desktop.vcxproj +++ b/vnext/JSI/Desktop/JSI.Desktop.vcxproj @@ -74,11 +74,6 @@ - - - {fca38f3c-7c73-4c47-be4e-32f77fa8538d} - - @@ -89,6 +84,7 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + diff --git a/vnext/JSI/Universal/JSI.Universal.vcxproj b/vnext/JSI/Universal/JSI.Universal.vcxproj index 2dbbf006cb2..8ed94f58f44 100644 --- a/vnext/JSI/Universal/JSI.Universal.vcxproj +++ b/vnext/JSI/Universal/JSI.Universal.vcxproj @@ -115,11 +115,6 @@ - - - {fca38f3c-7c73-4c47-be4e-32f77fa8538d} - - diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj index 4558c0c563e..06198259254 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj @@ -147,8 +147,6 @@ --> CHAKRACORE;CHAKRACORE_UWP;%(PreprocessorDefinitions) USE_EDGEMODE_JSRT;%(PreprocessorDefinitions) - USE_HERMES;%(PreprocessorDefinitions) - USE_V8;%(PreprocessorDefinitions) REACTWINDOWS_BUILD; RN_PLATFORM=windows; diff --git a/vnext/PropertySheets/React.Cpp.props b/vnext/PropertySheets/React.Cpp.props index 2bb87442726..f191493c0f9 100644 --- a/vnext/PropertySheets/React.Cpp.props +++ b/vnext/PropertySheets/React.Cpp.props @@ -27,7 +27,7 @@ 0.1.6 $(SolutionDir)packages\ReactNative.Hermes.Windows.$(HERMES_Version) - false + false 0.2.7 $(SolutionDir)packages\ReactNative.V8Jsi.Windows.$(V8_Version) @@ -46,6 +46,8 @@ ENABLE_ETW_TRACING;%(PreprocessorDefinitions) ENABLE_JS_SYSTRACE_TO_ETW;WITH_FBSYSTRACE;%(PreprocessorDefinitions) + USE_HERMES;%(PreprocessorDefinitions) + USE_V8;%(PreprocessorDefinitions) diff --git a/vnext/ReactUWP/ReactUWP.vcxproj b/vnext/ReactUWP/ReactUWP.vcxproj index ffddc8d89cb..7045c842381 100644 --- a/vnext/ReactUWP/ReactUWP.vcxproj +++ b/vnext/ReactUWP/ReactUWP.vcxproj @@ -90,8 +90,6 @@ --> CHAKRACORE;CHAKRACORE_UWP;%(PreprocessorDefinitions) USE_EDGEMODE_JSRT;%(PreprocessorDefinitions) - USE_HERMES;%(PreprocessorDefinitions) - USE_V8;%(PreprocessorDefinitions) REACTWINDOWS_BUILD; RN_PLATFORM=windows; diff --git a/vnext/ReactWindows-Desktop.sln b/vnext/ReactWindows-Desktop.sln index 8e60ffd4d45..6e3ddae5d0a 100644 --- a/vnext/ReactWindows-Desktop.sln +++ b/vnext/ReactWindows-Desktop.sln @@ -128,7 +128,6 @@ Global Mso\Mso.vcxitems*{1958ceaa-fbe0-44e3-8a99-90ad85531ffe}*SharedItemsImports = 4 Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 Chakra\Chakra.vcxitems*{6f354505-fe3a-4bd2-a9a6-d12bbf37a85c}*SharedItemsImports = 4 - Shared\Shared.vcxitems*{6f354505-fe3a-4bd2-a9a6-d12bbf37a85c}*SharedItemsImports = 4 Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9 Chakra\Chakra.vcxitems*{95048601-c3dc-475f-adf8-7c0c764c10d5}*SharedItemsImports = 4 Mso\Mso.vcxitems*{95048601-c3dc-475f-adf8-7c0c764c10d5}*SharedItemsImports = 4 diff --git a/vnext/ReactWindowsCore/ReactWindowsCore.vcxitems b/vnext/ReactWindowsCore/ReactWindowsCore.vcxitems index 13e56fc783b..45f57133a2e 100644 --- a/vnext/ReactWindowsCore/ReactWindowsCore.vcxitems +++ b/vnext/ReactWindowsCore/ReactWindowsCore.vcxitems @@ -66,10 +66,6 @@ - - - - @@ -102,12 +98,10 @@ CHAKRACORE; %(PreprocessorDefinitions) - USE_HERMES;%(PreprocessorDefinitions) $(ReactNativeWindowsDir); $(ReactNativeWindowsDir)Common; $(ReactNativeWindowsDir)Shared; - $(ReactNativeWindowsDir)include; $(ReactNativeWindowsDir)include\ReactWindowsCore; $(ReactNativeDir)\ReactCommon; $(ReactNativeDir)\ReactCommon\callinvoker; @@ -232,12 +226,6 @@ {fca38f3c-7c73-4c47-be4e-32f77fa8538d} - - {a990658c-ce31-4bcc-976f-0fc6b1af693d} - - - {a9d95a91-4db7-4f72-beb6-fe8a5c89bfbd} - diff --git a/vnext/Shared/Shared.vcxitems b/vnext/Shared/Shared.vcxitems index c426153725d..4d31e11fc82 100644 --- a/vnext/Shared/Shared.vcxitems +++ b/vnext/Shared/Shared.vcxitems @@ -8,8 +8,6 @@ %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) - USE_HERMES;%(PreprocessorDefinitions) - USE_V8;%(PreprocessorDefinitions) diff --git a/vnext/Universal.UnitTests/React.Windows.Universal.UnitTests.vcxproj b/vnext/Universal.UnitTests/React.Windows.Universal.UnitTests.vcxproj index 51e9f3f11bd..c138c10390e 100644 --- a/vnext/Universal.UnitTests/React.Windows.Universal.UnitTests.vcxproj +++ b/vnext/Universal.UnitTests/React.Windows.Universal.UnitTests.vcxproj @@ -121,9 +121,6 @@ {a990658c-ce31-4bcc-976f-0fc6b1af693d} - - {a9d95a91-4db7-4f72-beb6-fe8a5c89bfbd} - {2d5d43d9-cffc-4c40-b4cd-02efb4e2742b} diff --git a/vnext/V8Inspector/V8Inspector.vcxproj b/vnext/V8Inspector/V8Inspector.vcxproj deleted file mode 100644 index 3522fe72dde..00000000000 --- a/vnext/V8Inspector/V8Inspector.vcxproj +++ /dev/null @@ -1,122 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - {F1B91D19-79E4-461B-AC8E-E3E6E747F65F} - Win32Proj - V8Inspector - 10.0.18362.0 - - - - StaticLibrary - true - Unicode - - - StaticLibrary - false - true - Unicode - - - StaticLibrary - true - Unicode - - - StaticLibrary - false - true - Unicode - - - - - - - - - - - - - - - - - - - - - - NotUsing - false - true - $(ReactNativeDir)\ReactCommon;$(JSI_Source);%(AdditionalIncludeDirectories) - - BOOST_ASIO_DISABLE_BOOST_REGEX; - BOOST_ERROR_CODE_HEADER_ONLY; - BOOST_ASIO_HAS_IOCP; - _WIN32_WINNT=$(WinVer); - WIN32; - _WINDOWS; - _WIN32; - JSI_EXPORT=; - %(PreprocessorDefinitions) - - - false - - - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file diff --git a/vnext/V8Inspector/V8Inspector.vcxproj.filters b/vnext/V8Inspector/V8Inspector.vcxproj.filters deleted file mode 100644 index 1097daff606..00000000000 --- a/vnext/V8Inspector/V8Inspector.vcxproj.filters +++ /dev/null @@ -1,63 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file From d374932510f3cd3377920aa0234f5237f69bfc66 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Sun, 10 May 2020 00:05:02 +0000 Subject: [PATCH 078/209] applying package updates ***NO_CI*** --- ...native-windows-2020-05-08-14-17-35-master.json | 8 -------- packages/E2ETest/package.json | 2 +- .../microsoft-reactnative-sampleapps/package.json | 2 +- packages/playground/package.json | 2 +- vnext/CHANGELOG.json | 15 +++++++++++++++ vnext/CHANGELOG.md | 10 +++++++++- vnext/package.json | 2 +- 7 files changed, 28 insertions(+), 13 deletions(-) delete mode 100644 change/react-native-windows-2020-05-08-14-17-35-master.json diff --git a/change/react-native-windows-2020-05-08-14-17-35-master.json b/change/react-native-windows-2020-05-08-14-17-35-master.json deleted file mode 100644 index c55a7882828..00000000000 --- a/change/react-native-windows-2020-05-08-14-17-35-master.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Reenable V8 for desktop projects", - "packageName": "react-native-windows", - "email": "tudorm@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-08T21:17:35.875Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index 43cc94f53a4..39106f4510a 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.62" + "react-native-windows": "0.0.0-master.63" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 512f96ab9ca..faf33dc0167 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.62" + "react-native-windows": "0.0.0-master.63" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index 429fc214d7b..449e7089930 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.62" + "react-native-windows": "0.0.0-master.63" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index e5de6cf161b..f1ddb330210 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Sun, 10 May 2020 00:05:02 GMT", + "tag": "react-native-windows_v0.0.0-master.63", + "version": "0.0.0-master.63", + "comments": { + "prerelease": [ + { + "comment": "Reenable V8 for desktop projects", + "author": "tudorm@microsoft.com", + "commit": "858fdce423bb4a0eac46dd4eca97adb3b6b042e9", + "package": "react-native-windows" + } + ] + } + }, { "date": "Sat, 09 May 2020 00:04:42 GMT", "tag": "react-native-windows_v0.0.0-master.62", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 740bdc37cfe..c340b96fa98 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - react-native-windows -This log was last generated on Sat, 09 May 2020 00:04:42 GMT and should not be manually modified. +This log was last generated on Sun, 10 May 2020 00:05:02 GMT and should not be manually modified. +## 0.0.0-master.63 + +Sun, 10 May 2020 00:05:02 GMT + +### Changes + +- Reenable V8 for desktop projects (tudorm@microsoft.com) + ## 0.0.0-master.62 Sat, 09 May 2020 00:04:42 GMT diff --git a/vnext/package.json b/vnext/package.json index b55fcc9940c..c3e32b9805b 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.62", + "version": "0.0.0-master.63", "license": "MIT", "repository": { "type": "git", From cf658bab8ef4045251876a1408c71aefc7539cd7 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Mon, 11 May 2020 10:10:29 -0700 Subject: [PATCH 079/209] Improve run_wdio to print out failed tests (#4843) * Improve run_wdio to print out failed tests --- packages/E2ETest/run_wdio.js | 95 +++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 29 deletions(-) diff --git a/packages/E2ETest/run_wdio.js b/packages/E2ETest/run_wdio.js index 56a33f269f5..aec747f94f2 100644 --- a/packages/E2ETest/run_wdio.js +++ b/packages/E2ETest/run_wdio.js @@ -4,10 +4,11 @@ const xml2js = require('xml2js'); const parser = new xml2js.Parser({ attrkey: 'ATTR' }); const child_process = require('child_process'); const prompt = require('prompt-sync')(); +const chalk = require('chalk'); const specFolder = 'wdio/test'; -function GetMetadata(specPath) { +function getMetadata(specPath) { const contents = fs.readFileSync(specPath); const metadataTag = '// @metadata '; const metadataStart = contents.indexOf(metadataTag); @@ -29,31 +30,31 @@ const filters = { // Returns true if the spec is to run. // Specs marked SkipCI are excluded from CI (identified by environment variables in the ADO lab) -function FilterSpec(specPath) { - const metadata = GetMetadata(specPath); - for (let i = 0; i < metadata.length; i++) { - if (filters[metadata[i]](specPath)) { +function filterSpec(specPath) { + const metadata = getMetadata(specPath); + for (const metadataElement of metadata) { + if (filters[metadataElement](specPath)) { return false; } } return true; } -function SelectSpecs(folder) { +function selectSpecs(folder) { let specs = []; if (process.argv.length > 2) { specs = process.argv.splice(2).map(spec => spec + '.spec.ts'); } else { specs = fs.readdirSync(folder).filter(x => x.endsWith('.spec.ts')); } - specs = specs.map(spec => path.join(folder, spec)).filter(FilterSpec); + specs = specs.map(spec => path.join(folder, spec)).filter(filterSpec); return specs; } -let opts = SelectSpecs(specFolder); +let opts = selectSpecs(specFolder); console.log(`Selected tests: ${opts}`); -function OverrideHyperV() { +function ensureRunningInHyperV() { const baseboardMfr = child_process .execSync('powershell.exe (gwmi Win32_BaseBoard).Manufacturer') .toString() @@ -69,26 +70,41 @@ function OverrideHyperV() { } } -OverrideHyperV(); - const Launcher = require('@wdio/cli').default; const wdio = new Launcher('wdio.conf.js', { specs: opts }); function parseLog(logfile) { const xmlString = fs.readFileSync(logfile); - let name; + let failures = {}; parser.parseString(xmlString, (err, res) => { if (!res.testsuites) { - name = 'something went wrong'; + console.error(`Something went wrong processing file ${logfile}`); } else { - const attr = res.testsuites.testsuite[0].ATTR; - if (attr.errors > 0 || attr.failures > 0) { - name = attr.name; + for (const testsuite of res.testsuites.testsuite) { + const attr = testsuite.ATTR; + + if (attr.errors > 0 || attr.failures > 0) { + const name = attr.name; + failures[name] = {}; + + for (const testcase of testsuite.testcases) { + if (testcase.error && testcase.error[0].ATTR) { + failures[name].testcase = testcase.ATTR.name; + failures[name].error = testcase.error[0].ATTR.message; + const systemErr = testcase['system-err'][0]; + const stack = systemErr.substr( + systemErr.indexOf('\n at ') + 1 + ); + failures[name].stack = stack; + } + } + } } } }); - return name; + + return failures; } function parseLogs() { @@ -100,20 +116,41 @@ function parseLogs() { return names; } -function Process(code) { +function printFailedTests(ft) { + for (const key in ft) { + console.log(chalk.redBright(key)); + console.log( + ' ', + chalk.underline('testcase'), + chalk.bold(ft[key].testcase) + ); + console.log(' ', chalk.underline('error'), chalk.bold(ft[key].error)); + console.log(' ', chalk.underline('stack')); + console.log(ft[key].stack); + } +} + +function doProcess(code) { const failedTests = parseLogs(); - for (let i = 0; i < failedTests.length; i++) { - console.log(`Failed test: ${failedTests[i]}`); + for (const failedTest of failedTests) { + console.log('Failed tests: '); + printFailedTests(failedTest); } process.exit(code); } -wdio.run().then( - code => { - Process(code); - }, - error => { - console.error('Launcher failed to start the test', error.stacktrace); - process.exit(1); - } -); +function runWdio() { + ensureRunningInHyperV(); + + wdio.run().then( + code => { + doProcess(code); + }, + error => { + console.error('Launcher failed to start the test', error.stacktrace); + process.exit(1); + } + ); +} + +runWdio(); From c40cc0ea1de8b4acb830939ba79146739f438111 Mon Sep 17 00:00:00 2001 From: lamxdoan Date: Mon, 11 May 2020 10:12:05 -0700 Subject: [PATCH 080/209] Fire onLoad event when a bitmap image is opened (#4750) * Fire onLoad event when a bitmap image is opeed * Change files * add imageFailed * remove firing of onload events in the createImageBrush block so that load events don't fire twice. --- ...ndows-2020-04-29-15-37-41-imageonload.json | 9 +++++ vnext/ReactUWP/Views/Image/ReactImage.cpp | 37 ++++++++++--------- vnext/ReactUWP/Views/Image/ReactImage.h | 2 +- 3 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 change/react-native-windows-2020-04-29-15-37-41-imageonload.json diff --git a/change/react-native-windows-2020-04-29-15-37-41-imageonload.json b/change/react-native-windows-2020-04-29-15-37-41-imageonload.json new file mode 100644 index 00000000000..714ebefda8d --- /dev/null +++ b/change/react-native-windows-2020-04-29-15-37-41-imageonload.json @@ -0,0 +1,9 @@ +{ + "type": "prerelease", + "comment": "Fire onLoad event when a bitmap image is opeed", + "packageName": "react-native-windows", + "email": "lamdoan@microsoft.com", + "commit": "22edad7ea69232ae7636424c237df4eee7577f54", + "dependentChangeType": "patch", + "date": "2020-04-29T22:37:41.642Z" +} \ No newline at end of file diff --git a/vnext/ReactUWP/Views/Image/ReactImage.cpp b/vnext/ReactUWP/Views/Image/ReactImage.cpp index 791a3776ecc..7ec70a89aca 100644 --- a/vnext/ReactUWP/Views/Image/ReactImage.cpp +++ b/vnext/ReactUWP/Views/Image/ReactImage.cpp @@ -213,10 +213,8 @@ winrt::fire_and_forget ReactImage::SetBackground(bool fireLoadEndEvent) { if (createImageBrush) { imageBrush = winrt::ImageBrush{}; - // ImageOpened and ImageFailed are mutually exclusive. One event of the other will - // always fire whenever an ImageBrush has the ImageSource value set or reset. - strong_this->m_imageBrushOpenedRevoker = imageBrush.ImageOpened( - winrt::auto_revoke, [weak_this, imageBrush, fireLoadEndEvent](const auto &, const auto &) { + strong_this->m_imageBrushOpenedRevoker = + imageBrush.ImageOpened(winrt::auto_revoke, [weak_this, imageBrush](const auto &, const auto &) { if (auto strong_this{weak_this.get()}) { if (auto bitmap{imageBrush.ImageSource().try_as()}) { strong_this->m_imageSource.height = bitmap.PixelHeight(); @@ -224,18 +222,6 @@ winrt::fire_and_forget ReactImage::SetBackground(bool fireLoadEndEvent) { } imageBrush.Stretch(strong_this->ResizeModeToStretch(strong_this->m_resizeMode)); - - if (fireLoadEndEvent) { - strong_this->m_onLoadEndEvent(*strong_this, true); - } - } - }); - - strong_this->m_imageBrushFailedRevoker = - imageBrush.ImageFailed(winrt::auto_revoke, [weak_this, fireLoadEndEvent](const auto &, const auto &) { - const auto strong_this{weak_this.get()}; - if (strong_this && fireLoadEndEvent) { - strong_this->m_onLoadEndEvent(*strong_this, false); } }); } @@ -274,7 +260,24 @@ winrt::fire_and_forget ReactImage::SetBackground(bool fireLoadEndEvent) { bitmapImage = winrt::BitmapImage{}; strong_this->m_bitmapImageOpened = bitmapImage.ImageOpened( - winrt::auto_revoke, [imageBrush](const auto &, const auto &) { imageBrush.Opacity(1); }); + winrt::auto_revoke, [imageBrush, weak_this, fireLoadEndEvent](const auto &, const auto &) { + imageBrush.Opacity(1); + + auto strong_this{weak_this.get()}; + if (strong_this && fireLoadEndEvent) { + strong_this->m_onLoadEndEvent(*strong_this, true); + } + }); + + strong_this->m_bitmapImageFailed = bitmapImage.ImageFailed( + winrt::auto_revoke, [imageBrush, weak_this, fireLoadEndEvent](const auto &, const auto &) { + imageBrush.Opacity(1); + + auto strong_this{weak_this.get()}; + if (strong_this && fireLoadEndEvent) { + strong_this->m_onLoadEndEvent(*strong_this, false); + } + }); imageBrush.ImageSource(bitmapImage); } diff --git a/vnext/ReactUWP/Views/Image/ReactImage.h b/vnext/ReactUWP/Views/Image/ReactImage.h index 4a8ac619460..e73ca246581 100644 --- a/vnext/ReactUWP/Views/Image/ReactImage.h +++ b/vnext/ReactUWP/Views/Image/ReactImage.h @@ -67,8 +67,8 @@ struct ReactImage : xaml::Controls::GridT { xaml::FrameworkElement::SizeChanged_revoker m_sizeChangedRevoker; xaml::Media::LoadedImageSurface::LoadCompleted_revoker m_surfaceLoadedRevoker; xaml::Media::Imaging::BitmapImage::ImageOpened_revoker m_bitmapImageOpened; + xaml::Media::Imaging::BitmapImage::ImageFailed_revoker m_bitmapImageFailed; xaml::Media::ImageBrush::ImageOpened_revoker m_imageBrushOpenedRevoker; - xaml::Media::ImageBrush::ImageFailed_revoker m_imageBrushFailedRevoker; xaml::Media::Imaging::SvgImageSource::Opened_revoker m_svgImageSourceOpenedRevoker; xaml::Media::Imaging::SvgImageSource::OpenFailed_revoker m_svgImageSourceOpenFailedRevoker; }; From 55091b9447d741fc0e9c23acb8dfdee53ad11598 Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Mon, 11 May 2020 12:55:05 -0700 Subject: [PATCH 081/209] Expose ability for apps to provide their own RedBox implementation (#4786) * Expose ability for apps to provide their own RedBox implementation * Change files * minor changes * Code review feedback * minor fix * format fixes * minor change * minor fix * minor fix * minor fix --- ...020-05-04-12-54-41-publiccustomredbox.json | 8 + packages/scripts/formatFiles.js | 1 + .../Microsoft.ReactNative.vcxproj | 11 ++ .../Microsoft.ReactNative.vcxproj.filters | 1 + .../ReactHost/ReactInstanceWin.cpp | 2 +- .../ReactInstanceSettings.h | 12 ++ .../ReactInstanceSettings.idl | 2 + .../Microsoft.ReactNative/ReactNativeHost.cpp | 6 + vnext/Microsoft.ReactNative/RedBox.cpp | 162 +++++++++++++----- vnext/Microsoft.ReactNative/RedBox.h | 7 +- vnext/Microsoft.ReactNative/RedBoxHandler.cpp | 63 +++++++ vnext/Microsoft.ReactNative/RedBoxHandler.h | 26 +++ vnext/Microsoft.ReactNative/RedBoxHandler.idl | 43 +++++ vnext/ReactUWP/Base/UwpReactInstance.cpp | 4 +- vnext/ReactWindowsCore/DevSettings.h | 2 +- .../{RedBoxHandler.h => IRedBoxHandler.h} | 2 +- .../Modules/ExceptionsManagerModule.h | 2 +- .../ReactWindowsCore.vcxitems | 2 +- .../ReactWindowsCore.vcxproj.filters | 2 +- vnext/Scripts/ReactWin32.nuspec | 2 +- 20 files changed, 309 insertions(+), 51 deletions(-) create mode 100644 change/react-native-windows-2020-05-04-12-54-41-publiccustomredbox.json create mode 100644 vnext/Microsoft.ReactNative/RedBoxHandler.cpp create mode 100644 vnext/Microsoft.ReactNative/RedBoxHandler.h create mode 100644 vnext/Microsoft.ReactNative/RedBoxHandler.idl rename vnext/ReactWindowsCore/{RedBoxHandler.h => IRedBoxHandler.h} (94%) diff --git a/change/react-native-windows-2020-05-04-12-54-41-publiccustomredbox.json b/change/react-native-windows-2020-05-04-12-54-41-publiccustomredbox.json new file mode 100644 index 00000000000..dc9e8030a2f --- /dev/null +++ b/change/react-native-windows-2020-05-04-12-54-41-publiccustomredbox.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Expose ability for apps to provide their own RedBox implementation", + "packageName": "react-native-windows", + "email": "acoates@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-04T19:54:41.414Z" +} diff --git a/packages/scripts/formatFiles.js b/packages/scripts/formatFiles.js index 86c16d088e0..7bce4725db7 100644 --- a/packages/scripts/formatFiles.js +++ b/packages/scripts/formatFiles.js @@ -35,6 +35,7 @@ function queryNoOpenFiles() { if (opened) { console.error('The following files have incorrect formatting:'); console.error(opened); + console.error('Running `yarn format` from the repo root should fix this.'); process.exit(2); } } diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj index 06198259254..68d21f19ac0 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj @@ -340,6 +340,10 @@ ReactInstanceSettings.idl Code + + RedBoxHandler.idl + Code + ReactNativeHost.idl Code @@ -501,6 +505,10 @@ ReactInstanceSettings.idl Code + + RedBoxHandler.idl + Code + ReactNativeHost.idl Code @@ -558,6 +566,9 @@ Designer + + Designer + Designer diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters index f5cee04be05..de2019f2870 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters @@ -688,6 +688,7 @@ + diff --git a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp index 957aca066f2..0218b9b075c 100644 --- a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +++ b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp @@ -517,7 +517,7 @@ std::shared_ptr ReactInstanceWin::GetRedBoxHandler() noexcept { return m_options.RedBoxHandler; } else if (m_options.DeveloperSettings.IsDevModeEnabled) { auto localWkReactHost = m_weakReactHost; - return CreateRedBoxHandler(std::move(localWkReactHost), m_uiMessageThread.LoadWithLock()); + return CreateDefaultRedBoxHandler(std::move(localWkReactHost)); } else { return {}; } diff --git a/vnext/Microsoft.ReactNative/ReactInstanceSettings.h b/vnext/Microsoft.ReactNative/ReactInstanceSettings.h index daeb91102b9..1e828273511 100644 --- a/vnext/Microsoft.ReactNative/ReactInstanceSettings.h +++ b/vnext/Microsoft.ReactNative/ReactInstanceSettings.h @@ -80,6 +80,9 @@ struct ReactInstanceSettings : ReactInstanceSettingsT { uint16_t DebuggerPort() noexcept; void DebuggerPort(uint16_t value) noexcept; + IRedBoxHandler RedBoxHandler() noexcept; + void RedBoxHandler(IRedBoxHandler const &value) noexcept; + private: IReactPropertyBag m_properties{ReactPropertyBagHelper::CreatePropertyBag()}; hstring m_mainComponentName{}; @@ -100,6 +103,7 @@ struct ReactInstanceSettings : ReactInstanceSettingsT { hstring m_debugBundlePath{}; hstring m_bundleRootPath{}; uint16_t m_debuggerPort{9229}; + IRedBoxHandler m_redBoxHandler{nullptr}; }; } // namespace winrt::Microsoft::ReactNative::implementation @@ -264,4 +268,12 @@ inline void ReactInstanceSettings::DebuggerPort(uint16_t value) noexcept { m_debuggerPort = value; } +inline IRedBoxHandler ReactInstanceSettings::RedBoxHandler() noexcept { + return m_redBoxHandler; +} + +inline void ReactInstanceSettings::RedBoxHandler(IRedBoxHandler const &value) noexcept { + m_redBoxHandler = value; +} + } // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl b/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl index 22887666ca3..f388e735f29 100644 --- a/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl +++ b/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +import "RedBoxHandler.idl"; import "IReactPropertyBag.idl"; namespace Microsoft.ReactNative { @@ -29,5 +30,6 @@ namespace Microsoft.ReactNative { String DebugBundlePath { get; set; }; String BundleRootPath { get; set; }; UInt16 DebuggerPort { get; set; }; + Microsoft.ReactNative.IRedBoxHandler RedBoxHandler { get; set; }; } } diff --git a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp index 6812a46bef3..a7a1c9f3c99 100644 --- a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp +++ b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp @@ -6,6 +6,7 @@ #include "ReactNativeHost.g.cpp" #include "ReactPackageBuilder.h" +#include "RedBox.h" using namespace winrt; using namespace Windows::Foundation::Collections; @@ -78,6 +79,10 @@ void ReactNativeHost::ReloadInstance() noexcept { legacySettings.UseWebDebugger = m_instanceSettings.UseWebDebugger(); legacySettings.DebuggerPort = m_instanceSettings.DebuggerPort(); + if (m_instanceSettings.RedBoxHandler()) { + legacySettings.RedBoxHandler = std::move(Mso::React::CreateRedBoxHandler(m_instanceSettings.RedBoxHandler())); + } + Mso::React::ReactOptions reactOptions{}; reactOptions.Properties = m_instanceSettings.Properties(); reactOptions.DeveloperSettings.IsDevModeEnabled = legacySettings.EnableDeveloperMenu; @@ -91,6 +96,7 @@ void ReactNativeHost::ReloadInstance() noexcept { reactOptions.DeveloperSettings.DebugHost = legacySettings.DebugHost; reactOptions.BundleRootPath = legacySettings.BundleRootPath; reactOptions.DeveloperSettings.DebuggerPort = legacySettings.DebuggerPort; + reactOptions.RedBoxHandler = legacySettings.RedBoxHandler; reactOptions.LegacySettings = std::move(legacySettings); diff --git a/vnext/Microsoft.ReactNative/RedBox.cpp b/vnext/Microsoft.ReactNative/RedBox.cpp index 0c1c327cb24..699454c743e 100644 --- a/vnext/Microsoft.ReactNative/RedBox.cpp +++ b/vnext/Microsoft.ReactNative/RedBox.cpp @@ -4,6 +4,7 @@ #include "RedBox.h" #include #include +#include #include #include #include @@ -18,10 +19,10 @@ namespace Mso::React { struct RedBox : public std::enable_shared_from_this { RedBox( - Mso::WeakPtr weakReactHost, + const Mso::WeakPtr &weakReactHost, Mso::Functor &&onClosedCallback, ErrorInfo &&errorInfo) noexcept - : m_weakReactHost(std::move(weakReactHost)), + : m_weakReactHost(weakReactHost), m_onClosedCallback(std::move(onClosedCallback)), m_errorInfo(std::move(errorInfo)) {} @@ -356,26 +357,22 @@ struct RedBox : public std::enable_shared_from_this { /* * This class is implemented such that the methods on IRedBoxHandler are thread safe. */ -struct RedBoxHandler : public std::enable_shared_from_this, IRedBoxHandler { - RedBoxHandler( - Mso::WeakPtr weakReactHost, - std::shared_ptr uiMessageQueue) noexcept - : m_weakReactHost(std::move(weakReactHost)), m_wkUIMessageQueue(std::move(uiMessageQueue)) {} +struct DefaultRedBoxHandler : public std::enable_shared_from_this, IRedBoxHandler { + DefaultRedBoxHandler(Mso::WeakPtr &&weakReactHost) noexcept + : m_weakReactHost(std::move(weakReactHost)) {} - ~RedBoxHandler() { + ~DefaultRedBoxHandler() { // Hide any currently showing redboxes std::vector> redboxes; { std::scoped_lock lock{m_lockRedBox}; std::swap(m_redboxes, redboxes); } - if (auto uiQueue = m_wkUIMessageQueue.lock()) { - uiQueue->runOnQueue([redboxes = std::move(redboxes)]() { - for (const auto redbox : redboxes) { - redbox->Dismiss(); - } - }); - } + Mso::DispatchQueue::MainUIQueue().Post([redboxes = std::move(redboxes)]() { + for (const auto redbox : redboxes) { + redbox->Dismiss(); + } + }); } virtual void showNewError(ErrorInfo &&info, ErrorType /*exceptionType*/) override { @@ -394,7 +391,7 @@ struct RedBoxHandler : public std::enable_shared_from_this, IRedB showTopJSError(); } - virtual bool isDevSupportEnabled() override { + virtual bool isDevSupportEnabled() const override { if (auto reactHost = m_weakReactHost.GetStrongPtr()) { return reactHost->Options().DeveloperSettings.IsDevModeEnabled; } @@ -414,28 +411,26 @@ struct RedBoxHandler : public std::enable_shared_from_this, IRedB } } if (redbox) { - if (auto uiQueue = m_wkUIMessageQueue.lock()) { - uiQueue->runOnQueue([redboxCaptured = std::move(redbox), errorInfo = std::move(info)]() { - redboxCaptured->UpdateError(std::move(errorInfo)); - }); - } + Mso::DispatchQueue::MainUIQueue().Post([redboxCaptured = std::move(redbox), errorInfo = std::move(info)]() { + redboxCaptured->UpdateError(std::move(errorInfo)); + }); } } virtual void dismissRedbox() override { - if (auto uiQueue = m_wkUIMessageQueue.lock()) { - uiQueue->runOnQueue([&]() { - std::scoped_lock lock{m_lockRedBox}; - if (!m_redboxes.empty()) - m_redboxes[0]->Dismiss(); - }); - } + Mso::DispatchQueue::MainUIQueue().Post([wkthis = std::weak_ptr(shared_from_this())]() { + if (auto pthis = wkthis.lock()) { + std::scoped_lock lock{pthis->m_lockRedBox}; + if (!pthis->m_redboxes.empty()) + pthis->m_redboxes[0]->Dismiss(); + } + }); } private: // When notified by a redbox that its been dismisssed void onDismissedCallback(uint32_t id) noexcept { - // Save a local ref, so if we are removing the last redbox which could hold the last ref to the RedBoxHandler + // Save a local ref, so if we are removing the last redbox which could hold the last ref to the DefaultRedBoxHandler // We ensure that we exit the mutex before the handler is destroyed. std::shared_ptr redbox; { @@ -463,25 +458,114 @@ struct RedBoxHandler : public std::enable_shared_from_this, IRedB } } - if (auto uiQueue = m_wkUIMessageQueue.lock()) { - if (m_showingRedBox || !redbox) // Only show one redbox at a time - return; - m_showingRedBox = true; - uiQueue->runOnQueue([redboxCaptured = std::move(redbox)]() { redboxCaptured->ShowNewJSError(); }); - } + if (m_showingRedBox || !redbox) // Only show one redbox at a time + return; + m_showingRedBox = true; + + Mso::DispatchQueue::MainUIQueue().Post( + [redboxCaptured = std::move(redbox)]() { redboxCaptured->ShowNewJSError(); }); } bool m_showingRedBox = false; // Access from UI Thread only std::mutex m_lockRedBox; std::vector> m_redboxes; // Protected by m_lockRedBox const Mso::WeakPtr m_weakReactHost; - const std::weak_ptr m_wkUIMessageQueue; +}; + +struct RedBoxErrorFrameInfo + : public winrt::implements { + RedBoxErrorFrameInfo(Mso::React::ErrorFrameInfo &&errorFrameInfo) : m_frame(std::move(errorFrameInfo)) {} + + winrt::hstring File() const noexcept { + return ::Microsoft::Common::Unicode::Utf8ToUtf16(m_frame.File).c_str(); + } + + winrt::hstring Method() const noexcept { + return ::Microsoft::Common::Unicode::Utf8ToUtf16(m_frame.Method).c_str(); + } + + uint32_t Line() const noexcept { + return m_frame.Line; + } + + uint32_t Column() const noexcept { + return m_frame.Column; + } + + private: + Mso::React::ErrorFrameInfo m_frame; +}; + +struct RedBoxErrorInfo : public winrt::implements { + RedBoxErrorInfo(Mso::React::ErrorInfo &&errorInfo) : m_errorInfo(std::move(errorInfo)) {} + + winrt::hstring Message() const noexcept { + return ::Microsoft::Common::Unicode::Utf8ToUtf16(m_errorInfo.Message).c_str(); + } + + uint32_t Id() const noexcept { + return m_errorInfo.Id; + } + + winrt::Windows::Foundation::Collections::IVectorView + Callstack() noexcept { + if (!m_callstack) { + m_callstack = winrt::single_threaded_vector(); + for (auto frame : m_errorInfo.Callstack) { + m_callstack.Append(winrt::make(std::move(frame))); + } + } + + return m_callstack.GetView(); + } + + private: + winrt::Windows::Foundation::Collections::IVector m_callstack{ + nullptr}; + + Mso::React::ErrorInfo m_errorInfo; +}; + +struct RedBoxHandler : public Mso::React::IRedBoxHandler { + RedBoxHandler(winrt::Microsoft::ReactNative::IRedBoxHandler const &redBoxHandler) : m_redBoxHandler(redBoxHandler) {} + + static_assert( + static_cast(Mso::React::ErrorType::JSFatal) == + static_cast(winrt::Microsoft::ReactNative::RedBoxErrorType::JavaScriptFatal)); + static_assert( + static_cast(Mso::React::ErrorType::JSSoft) == + static_cast(winrt::Microsoft::ReactNative::RedBoxErrorType::JavaScriptSoft)); + static_assert( + static_cast(Mso::React::ErrorType::Native) == + static_cast(winrt::Microsoft::ReactNative::RedBoxErrorType::Native)); + + virtual void showNewError(Mso::React::ErrorInfo &&info, Mso::React::ErrorType errorType) override { + m_redBoxHandler.ShowNewError( + winrt::make(std::move(info)), + static_cast(static_cast(errorType))); + } + virtual bool isDevSupportEnabled() const override { + return m_redBoxHandler.IsDevSupportEnabled(); + } + virtual void updateError(Mso::React::ErrorInfo &&info) override { + m_redBoxHandler.UpdateError(winrt::make(std::move(info))); + } + + virtual void dismissRedbox() override { + m_redBoxHandler.DismissRedBox(); + } + + private: + winrt::Microsoft::ReactNative::IRedBoxHandler m_redBoxHandler; }; std::shared_ptr CreateRedBoxHandler( - Mso::WeakPtr &&weakReactHost, - std::shared_ptr &&uiMessageQueue) noexcept { - return std::make_shared(std::move(weakReactHost), std::move(uiMessageQueue)); + winrt::Microsoft::ReactNative::IRedBoxHandler const &redBoxHandler) noexcept { + return std::make_shared(redBoxHandler); +} + +std::shared_ptr CreateDefaultRedBoxHandler(Mso::WeakPtr &&weakReactHost) noexcept { + return std::make_shared(std::move(weakReactHost)); } } // namespace Mso::React diff --git a/vnext/Microsoft.ReactNative/RedBox.h b/vnext/Microsoft.ReactNative/RedBox.h index 8be0393b921..0a14590aaea 100644 --- a/vnext/Microsoft.ReactNative/RedBox.h +++ b/vnext/Microsoft.ReactNative/RedBox.h @@ -2,13 +2,14 @@ // Licensed under the MIT License. #pragma once #include +#include "IRedBoxHandler.h" #include "ReactHost/React.h" -#include "RedBoxHandler.h" namespace Mso::React { std::shared_ptr CreateRedBoxHandler( - Mso::WeakPtr &&weakReactHost, - std::shared_ptr &&uiMessageQueue) noexcept; + winrt::Microsoft::ReactNative::IRedBoxHandler const &redBoxHandler) noexcept; + +std::shared_ptr CreateDefaultRedBoxHandler(Mso::WeakPtr &&weakReactHost) noexcept; } // namespace Mso::React diff --git a/vnext/Microsoft.ReactNative/RedBoxHandler.cpp b/vnext/Microsoft.ReactNative/RedBoxHandler.cpp new file mode 100644 index 00000000000..945bece5241 --- /dev/null +++ b/vnext/Microsoft.ReactNative/RedBoxHandler.cpp @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" +#include "RedBoxHandler.h" +#if __has_include("RedBoxHelper.g.cpp") +#include "RedBoxHelper.g.cpp" +#endif + +#include +#include +#include + +namespace winrt::Microsoft::ReactNative::implementation { + +Mso::React::ErrorInfo CreateErrorInfo(const IRedBoxErrorInfo &info) { + Mso::React::ErrorInfo ei; + ei.Id = info.Id(); + ei.Message = ::Microsoft::Common::Unicode::Utf16ToUtf8(info.Message()); + for (const auto &frame : info.Callstack()) { + Mso::React::ErrorFrameInfo efi; + efi.Method = ::Microsoft::Common::Unicode::Utf16ToUtf8(frame.Method()); + efi.File = ::Microsoft::Common::Unicode::Utf16ToUtf8(frame.File()); + efi.Line = frame.Line(); + efi.Column = frame.Column(); + ei.Callstack.push_back(std::move(efi)); + } + return ei; +} + +struct DefaultRedBoxHandler : winrt::implements { + DefaultRedBoxHandler(winrt::Microsoft::ReactNative::ReactNativeHost const &host) noexcept { + auto hostImpl = winrt::get_self(host); + Mso::WeakPtr wkHost(hostImpl->ReactHost()); + m_redBoxHandler = Mso::React::CreateDefaultRedBoxHandler(std::move(wkHost)); + } + + void ShowNewError(IRedBoxErrorInfo const &info, RedBoxErrorType type) noexcept { + m_redBoxHandler->showNewError( + CreateErrorInfo(info), static_cast(static_cast(type))); + } + + bool IsDevSupportEnabled() noexcept { + return m_redBoxHandler->isDevSupportEnabled(); + } + + void UpdateError(IRedBoxErrorInfo const &info) noexcept { + m_redBoxHandler->updateError(std::move(CreateErrorInfo(info))); + } + + void DismissRedBox() noexcept { + m_redBoxHandler->dismissRedbox(); + } + + private: + std::shared_ptr m_redBoxHandler; +}; + +IRedBoxHandler RedBoxHelper::CreateDefaultHandler(winrt::Microsoft::ReactNative::ReactNativeHost const &host) noexcept { + return winrt::make(host); +} + +} // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Microsoft.ReactNative/RedBoxHandler.h b/vnext/Microsoft.ReactNative/RedBoxHandler.h new file mode 100644 index 00000000000..e8aa4b1f6ac --- /dev/null +++ b/vnext/Microsoft.ReactNative/RedBoxHandler.h @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "RedBoxHelper.g.h" + +namespace Mso::React { +struct IRedBoxHandler; +} + +namespace winrt::Microsoft::ReactNative::implementation { + +struct RedBoxHelper : RedBoxHelperT { + RedBoxHelper() = default; + + static IRedBoxHandler CreateDefaultHandler(winrt::Microsoft::ReactNative::ReactNativeHost const &host) noexcept; +}; + +} // namespace winrt::Microsoft::ReactNative::implementation + +namespace winrt::Microsoft::ReactNative::factory_implementation { + +struct RedBoxHelper : RedBoxHelperT {}; + +} // namespace winrt::Microsoft::ReactNative::factory_implementation diff --git a/vnext/Microsoft.ReactNative/RedBoxHandler.idl b/vnext/Microsoft.ReactNative/RedBoxHandler.idl new file mode 100644 index 00000000000..0092086437e --- /dev/null +++ b/vnext/Microsoft.ReactNative/RedBoxHandler.idl @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import "ReactNativeHost.idl"; + +namespace Microsoft.ReactNative { + + enum RedBoxErrorType { + JavaScriptFatal, // A JS Exception was thrown or otherwise fatal error + JavaScriptSoft, // An error coming from JS that isn't fatal, such as console.error + Native, + }; + + [webhosthidden] interface IRedBoxErrorFrameInfo { + String File { get; }; + String Method { get; }; + UInt32 Line { get; }; + UInt32 Column { get; }; + } + + [webhosthidden] interface IRedBoxErrorInfo { + String Message { get; }; + UInt32 Id { get; }; + IVectorView Callstack { get; }; + } + + [webhosthidden] + interface IRedBoxHandler + { + void ShowNewError(IRedBoxErrorInfo info, RedBoxErrorType type); + Boolean IsDevSupportEnabled { get; }; + void UpdateError(IRedBoxErrorInfo info); + void DismissRedBox(); + } + + [webhosthidden] + [default_interface] + runtimeclass RedBoxHelper { + RedBoxHelper(); + static IRedBoxHandler CreateDefaultHandler(Microsoft.ReactNative.ReactNativeHost host); + } + +} diff --git a/vnext/ReactUWP/Base/UwpReactInstance.cpp b/vnext/ReactUWP/Base/UwpReactInstance.cpp index 8fbabcb20ce..ce74a02918b 100644 --- a/vnext/ReactUWP/Base/UwpReactInstance.cpp +++ b/vnext/ReactUWP/Base/UwpReactInstance.cpp @@ -51,7 +51,7 @@ #include "V8JSIRuntimeHolder.h" #endif // USE_V8 -#include +#include #include #include "ChakraRuntimeHolder.h" @@ -87,7 +87,7 @@ struct UwpReactRedBoxHandler : Mso::React::IRedBoxHandler { Microsoft::Common::Unicode::Utf8ToUtf16(ss.str().c_str()), L"RedBox Error"); dlg.ShowAsync(); } - virtual bool isDevSupportEnabled() override { + virtual bool isDevSupportEnabled() const override { return true; } virtual void updateError(Mso::React::ErrorInfo &&) override {} diff --git a/vnext/ReactWindowsCore/DevSettings.h b/vnext/ReactWindowsCore/DevSettings.h index 44808a5e4d9..061ea4259c4 100644 --- a/vnext/ReactWindowsCore/DevSettings.h +++ b/vnext/ReactWindowsCore/DevSettings.h @@ -5,7 +5,7 @@ #include "Logging.h" #include "MemoryTracker.h" -#include +#include #include #include #include diff --git a/vnext/ReactWindowsCore/RedBoxHandler.h b/vnext/ReactWindowsCore/IRedBoxHandler.h similarity index 94% rename from vnext/ReactWindowsCore/RedBoxHandler.h rename to vnext/ReactWindowsCore/IRedBoxHandler.h index aeabb4f9f57..fea578a782b 100644 --- a/vnext/ReactWindowsCore/RedBoxHandler.h +++ b/vnext/ReactWindowsCore/IRedBoxHandler.h @@ -28,7 +28,7 @@ struct ErrorInfo { struct IRedBoxHandler { virtual void showNewError(ErrorInfo &&, ErrorType) = 0; - virtual bool isDevSupportEnabled() = 0; + virtual bool isDevSupportEnabled() const = 0; virtual void updateError(ErrorInfo &&) = 0; virtual void dismissRedbox() = 0; }; diff --git a/vnext/ReactWindowsCore/Modules/ExceptionsManagerModule.h b/vnext/ReactWindowsCore/Modules/ExceptionsManagerModule.h index be44080f41e..80f314a5918 100644 --- a/vnext/ReactWindowsCore/Modules/ExceptionsManagerModule.h +++ b/vnext/ReactWindowsCore/Modules/ExceptionsManagerModule.h @@ -4,7 +4,7 @@ #pragma once #include -#include +#include #include #include #include diff --git a/vnext/ReactWindowsCore/ReactWindowsCore.vcxitems b/vnext/ReactWindowsCore/ReactWindowsCore.vcxitems index 45f57133a2e..0380d8cc221 100644 --- a/vnext/ReactWindowsCore/ReactWindowsCore.vcxitems +++ b/vnext/ReactWindowsCore/ReactWindowsCore.vcxitems @@ -168,7 +168,7 @@ - + diff --git a/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj.filters b/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj.filters index 7db04cf3419..4c1a4081cd6 100644 --- a/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj.filters +++ b/vnext/ReactWindowsCore/ReactWindowsCore.vcxproj.filters @@ -239,7 +239,7 @@ Header Files\Pch - + Header Files diff --git a/vnext/Scripts/ReactWin32.nuspec b/vnext/Scripts/ReactWin32.nuspec index a61bbe5631d..c54093c805e 100644 --- a/vnext/Scripts/ReactWin32.nuspec +++ b/vnext/Scripts/ReactWin32.nuspec @@ -34,7 +34,7 @@ - + From a15b3bfac7ebc29d3a9b642ab5235609b3b1a936 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 11 May 2020 13:41:32 -0700 Subject: [PATCH 082/209] Bump fp-ts from 2.5.4 to 2.6.0 (#4871) Bumps [fp-ts](https://github.com/gcanti/fp-ts) from 2.5.4 to 2.6.0. - [Release notes](https://github.com/gcanti/fp-ts/releases) - [Changelog](https://github.com/gcanti/fp-ts/blob/master/CHANGELOG.md) - [Commits](https://github.com/gcanti/fp-ts/compare/2.5.4...2.6.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 8dccb129849..5c28f727177 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6999,9 +6999,9 @@ forwarded@~0.1.2: integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= fp-ts@^2.5.0: - version "2.5.4" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.5.4.tgz#f184079aaa78403ea66458517be7787e0d593429" - integrity sha512-cZlLeEneRYypc2dOzB9h8+bd9mQhJVyt2g0Dny2gKR7uWNgA4EmLSJyguLYsTU44nJSSG9EjurUalEc0wQqeKw== + version "2.6.0" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.6.0.tgz#55dc9e82612a44a7bfed3484b18c535514d63e51" + integrity sha512-4EKVa3EOP3NoDwXCLgSCT2t+E2wPCWDXCuj3wEcQ1ovkLfdCMxKxCuElpXptIPBmtA+KbjnUl5Ta/1U3jsCmkg== fragment-cache@^0.2.1: version "0.2.1" From e596d14d5f7b9934543469a04ee8d20ba3785a93 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Tue, 12 May 2020 00:04:39 +0000 Subject: [PATCH 083/209] applying package updates ***NO_CI*** --- ...ndows-2020-04-29-15-37-41-imageonload.json | 9 -------- ...020-05-04-12-54-41-publiccustomredbox.json | 8 ------- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- vnext/CHANGELOG.json | 21 +++++++++++++++++++ vnext/CHANGELOG.md | 11 +++++++++- vnext/package.json | 2 +- 8 files changed, 35 insertions(+), 22 deletions(-) delete mode 100644 change/react-native-windows-2020-04-29-15-37-41-imageonload.json delete mode 100644 change/react-native-windows-2020-05-04-12-54-41-publiccustomredbox.json diff --git a/change/react-native-windows-2020-04-29-15-37-41-imageonload.json b/change/react-native-windows-2020-04-29-15-37-41-imageonload.json deleted file mode 100644 index 714ebefda8d..00000000000 --- a/change/react-native-windows-2020-04-29-15-37-41-imageonload.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "type": "prerelease", - "comment": "Fire onLoad event when a bitmap image is opeed", - "packageName": "react-native-windows", - "email": "lamdoan@microsoft.com", - "commit": "22edad7ea69232ae7636424c237df4eee7577f54", - "dependentChangeType": "patch", - "date": "2020-04-29T22:37:41.642Z" -} \ No newline at end of file diff --git a/change/react-native-windows-2020-05-04-12-54-41-publiccustomredbox.json b/change/react-native-windows-2020-05-04-12-54-41-publiccustomredbox.json deleted file mode 100644 index dc9e8030a2f..00000000000 --- a/change/react-native-windows-2020-05-04-12-54-41-publiccustomredbox.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Expose ability for apps to provide their own RedBox implementation", - "packageName": "react-native-windows", - "email": "acoates@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-04T19:54:41.414Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index 39106f4510a..a2448e2e4ba 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.63" + "react-native-windows": "0.0.0-master.64" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index faf33dc0167..a994357bb72 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.63" + "react-native-windows": "0.0.0-master.64" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index 449e7089930..55d1d381182 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.63" + "react-native-windows": "0.0.0-master.64" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index f1ddb330210..a53ac0d9280 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,27 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Tue, 12 May 2020 00:04:39 GMT", + "tag": "react-native-windows_v0.0.0-master.64", + "version": "0.0.0-master.64", + "comments": { + "prerelease": [ + { + "comment": "Fire onLoad event when a bitmap image is opeed", + "author": "lamdoan@microsoft.com", + "commit": "c40cc0ea1de8b4acb830939ba79146739f438111", + "package": "react-native-windows" + }, + { + "comment": "Expose ability for apps to provide their own RedBox implementation", + "author": "acoates@microsoft.com", + "commit": "55091b9447d741fc0e9c23acb8dfdee53ad11598", + "package": "react-native-windows" + } + ] + } + }, { "date": "Sun, 10 May 2020 00:05:02 GMT", "tag": "react-native-windows_v0.0.0-master.63", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index c340b96fa98..b680713a308 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,18 @@ # Change Log - react-native-windows -This log was last generated on Sun, 10 May 2020 00:05:02 GMT and should not be manually modified. +This log was last generated on Tue, 12 May 2020 00:04:39 GMT and should not be manually modified. +## 0.0.0-master.64 + +Tue, 12 May 2020 00:04:39 GMT + +### Changes + +- Fire onLoad event when a bitmap image is opeed (lamdoan@microsoft.com) +- Expose ability for apps to provide their own RedBox implementation (acoates@microsoft.com) + ## 0.0.0-master.63 Sun, 10 May 2020 00:05:02 GMT diff --git a/vnext/package.json b/vnext/package.json index c3e32b9805b..228a39cb384 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.63", + "version": "0.0.0-master.64", "license": "MIT", "repository": { "type": "git", From d5e8bdcbf63a8ee2e9221bfa344faa227ef892e3 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Mon, 11 May 2020 17:52:18 -0700 Subject: [PATCH 084/209] Fixed ReactContext copy/move semantic (#4870) * Fixed ReactContext copy/move semantic * Change files * Fixed formatting * Test to show how to use a delegate in ReactPropertyBag --- ...s-2020-05-11-11-06-42-FixReactContext.json | 8 ++ ...icrosoft.ReactNative.Cxx.UnitTests.vcxproj | 1 + .../ReactContextTest.cpp | 113 ++++++++++++++++++ .../Microsoft.ReactNative.Cxx/JSValueWriter.h | 3 +- .../Microsoft.ReactNative.Cxx/ReactContext.h | 28 ++++- .../ReactNativeHostTests.cpp | 2 + .../ReactPropertyBagTests.cpp | 20 +++- .../pch.h | 1 - 8 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 change/react-native-windows-2020-05-11-11-06-42-FixReactContext.json create mode 100644 vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactContextTest.cpp diff --git a/change/react-native-windows-2020-05-11-11-06-42-FixReactContext.json b/change/react-native-windows-2020-05-11-11-06-42-FixReactContext.json new file mode 100644 index 00000000000..d3bc77290fd --- /dev/null +++ b/change/react-native-windows-2020-05-11-11-06-42-FixReactContext.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Fixed ReactContext copy/move semantic", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-11T18:06:42.425Z" +} diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj b/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj index 1849911ed19..79d66fa1e3a 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj @@ -126,6 +126,7 @@ Create + diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactContextTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactContextTest.cpp new file mode 100644 index 00000000000..c2d28914c93 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactContextTest.cpp @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" +#include +#include "ReactModuleBuilderMock.h" + +using namespace winrt::Microsoft::ReactNative; + +struct ReactContextStub : implements { + IReactPropertyBag Properties() noexcept { + VerifyElseCrashSz(false, "Not implemented"); + } + + void DispatchEvent( + xaml::FrameworkElement const & /*view*/, + hstring const & /*eventName*/, + JSValueArgWriter const & /*eventDataArgWriter*/) noexcept { + VerifyElseCrashSz(false, "Not implemented"); + } + + void CallJSFunction( + hstring const & /*moduleName*/, + hstring const & /*functionName*/, + JSValueArgWriter const & /*paramsArgWriter*/) noexcept { + VerifyElseCrashSz(false, "Not implemented"); + } + + void EmitJSEvent( + hstring const & /*eventEmitterName*/, + hstring const & /*eventName*/, + JSValueArgWriter const & /*paramsArgWriter*/) noexcept { + VerifyElseCrashSz(false, "Not implemented"); + } +}; + +namespace ReactNativeTests { + +TEST_CLASS (ReactContextTest) { + TEST_METHOD(Test_ctor_Default) { + ReactContext context; + TestCheck(!context); + } + + TEST_METHOD(Test_ctor_IReactContext) { + auto reactContextMock = winrt::make(); + ReactContext context{reactContextMock}; + TestCheck(context); + } + + TEST_METHOD(Test_ctor_copy) { + auto reactContextMock = winrt::make(); + ReactContext context1{reactContextMock}; + ReactContext context2{context1}; + TestCheck(context1); + TestCheck(context2); + TestCheckEqual(context1, context2); + } + + TEST_METHOD(Test_ctor_move) { + auto reactContextMock = winrt::make(); + ReactContext context1{reactContextMock}; + ReactContext context2{std::move(context1)}; + TestCheck(!context1); + TestCheck(context2); + } + + TEST_METHOD(Test_assign_nullptr) { + ReactContext context; + context = nullptr; + TestCheck(!context); + } + + TEST_METHOD(Test_assign_copy) { + auto reactContextMock = winrt::make(); + ReactContext context1{reactContextMock}; + ReactContext context2; + context2 = context1; + TestCheck(context1); + TestCheck(context2); + TestCheckEqual(context1, context2); + } + + TEST_METHOD(Test_assign_move) { + auto reactContextMock = winrt::make(); + ReactContext context1{reactContextMock}; + ReactContext context2; + context2 = std::move(context1); + TestCheck(!context1); + TestCheck(context2); + } + + TEST_METHOD(Test_compare) { + auto reactContextMock1 = winrt::make(); + auto reactContextMock2 = winrt::make(); + ReactContext context11{reactContextMock1}; + ReactContext context12{context11}; + ReactContext context2{reactContextMock2}; + ReactContext context3; + TestCheck(context11 == context12); + TestCheck(context12 == context11); + TestCheck(context11 != context2); + TestCheck(context11 != context3); + TestCheck(context2 != context11); + TestCheck(context3 != context11); + TestCheck(context3 == nullptr); + TestCheck(nullptr == context3); + TestCheck(context11 != nullptr); + TestCheck(nullptr != context11); + } +}; + +} // namespace ReactNativeTests diff --git a/vnext/Microsoft.ReactNative.Cxx/JSValueWriter.h b/vnext/Microsoft.ReactNative.Cxx/JSValueWriter.h index 547ac7ead65..80b6cb68748 100644 --- a/vnext/Microsoft.ReactNative.Cxx/JSValueWriter.h +++ b/vnext/Microsoft.ReactNative.Cxx/JSValueWriter.h @@ -5,8 +5,9 @@ #ifndef MICROSOFT_REACTNATIVE_JSVALUEWRITER #define MICROSOFT_REACTNATIVE_JSVALUEWRITER +#include +#include "JSValue.h" #include "StructInfo.h" -#include "winrt/Microsoft.ReactNative.h" namespace winrt::Microsoft::ReactNative { diff --git a/vnext/Microsoft.ReactNative.Cxx/ReactContext.h b/vnext/Microsoft.ReactNative.Cxx/ReactContext.h index a40c869f3c6..3dc09ee14ad 100644 --- a/vnext/Microsoft.ReactNative.Cxx/ReactContext.h +++ b/vnext/Microsoft.ReactNative.Cxx/ReactContext.h @@ -16,6 +16,8 @@ namespace winrt::Microsoft::ReactNative { // It wraps up the IReactContext and adds convenience methods for // working with C++ types. struct ReactContext { + ReactContext(std::nullptr_t = nullptr) noexcept {} + ReactContext(IReactContext const &handle) noexcept : m_handle{handle} {} IReactContext const &Handle() const noexcept { @@ -66,8 +68,32 @@ struct ReactContext { m_handle.DispatchEvent(view, eventName, paramsArgWriter); } + friend bool operator==(ReactContext const &left, ReactContext const &right) noexcept { + return left.m_handle == right.m_handle; + } + + friend bool operator!=(ReactContext const &left, ReactContext const &right) noexcept { + return left.m_handle != right.m_handle; + } + + friend bool operator==(ReactContext const &left, std::nullptr_t) noexcept { + return !static_cast(left.m_handle); + } + + friend bool operator!=(ReactContext const &left, std::nullptr_t) noexcept { + return static_cast(left.m_handle); + } + + friend bool operator==(std::nullptr_t, ReactContext const &right) noexcept { + return !static_cast(right.m_handle); + } + + friend bool operator!=(std::nullptr_t, ReactContext const &right) noexcept { + return static_cast(right.m_handle); + } + private: - const IReactContext m_handle; + IReactContext m_handle; }; } // namespace winrt::Microsoft::ReactNative diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp b/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp index 11d16009c32..2f11c1d9291 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp +++ b/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp @@ -1,5 +1,7 @@ #include "pch.h" +#include + using namespace React; namespace ReactNativeIntegrationTests { diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp b/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp index 7553d4be66a..27168257d81 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp +++ b/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp @@ -491,7 +491,6 @@ TEST_CLASS (ReactPropertyBagTests) { } TEST_METHOD(PropertyBag_Property_string) { - // We only support enums defined in IDL. ReactPropertyId fooName{L"Foo"}; ReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; @@ -504,6 +503,25 @@ TEST_CLASS (ReactPropertyBagTests) { pb.Remove(fooName); TestCheck(!pb.Get(fooName)); } + + TEST_METHOD(PropertyBag_Property_delegate) { + ReactPropertyId fooName{L"Foo"}; + ReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + + TestCheck(!pb.Get(fooName)); + ReactCreatePropertyValue createValue1 = []() { return winrt::box_value(5); }; + TestCheckEqual(createValue1, *pb.GetOrCreate(fooName, [&createValue1]() { return createValue1; })); + TestCheckEqual(createValue1, *pb.Get(fooName)); + TestCheckEqual(5, winrt::unbox_value((*pb.Get(fooName))())); + + ReactCreatePropertyValue createValue2 = []() { return winrt::box_value(10); }; + pb.Set(fooName, createValue2); + TestCheckEqual(createValue2, *pb.Get(fooName)); + TestCheckEqual(10, winrt::unbox_value((*pb.Get(fooName))())); + TestCheck(createValue1 != *pb.Get(fooName)); + pb.Remove(fooName); + TestCheck(!pb.Get(fooName)); + } }; } // namespace ReactNativeIntegrationTests diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/pch.h b/vnext/Microsoft.ReactNative.IntegrationTests/pch.h index cde08a53662..19f70f55b7b 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/pch.h +++ b/vnext/Microsoft.ReactNative.IntegrationTests/pch.h @@ -3,7 +3,6 @@ #define NOMINMAX #include -#include "NativeModules.h" #include "functional/functor.h" #include "motifCpp/testCheck.h" From 49e65479d70ab1df738cb7bf21e915e9453eaf13 Mon Sep 17 00:00:00 2001 From: Andreas Eulitz <44379427+aeulitz@users.noreply.github.com> Date: Mon, 11 May 2020 18:51:34 -0700 Subject: [PATCH 085/209] Add ReactNativeHost to Win32 C++/WinRT ABI (#4848) * create MS.ReactNative.IntegrationTests project * RNHost activation succeeds * update * update * Change files * add JS function call test * Change files * fix formatting * submit current state * ReactNativeHost activation test succeeds * Change files * account for property bag addition * sync, address code review feedback --- ...indows-2020-04-30-18-28-03-abi-safety.json | 8 +++ ...indows-2020-05-09-17-42-52-abi-safety.json | 8 +++ vnext/Desktop.ABITests/ActivationFactory.cpp | 2 +- vnext/Desktop.ABITests/ActivationFactory.h | 10 +++ vnext/Desktop.ABITests/MemoryTrackerTests.cpp | 3 +- .../Desktop.ABITests/NativeLogEventTests.cpp | 3 +- .../NativeTraceEventTests.cpp | 3 +- .../React.Windows.Desktop.ABITests.vcxproj | 5 ++ ...t.Windows.Desktop.ABITests.vcxproj.filters | 6 ++ .../Desktop.ABITests/ReactNativeHostTests.cpp | 29 ++++++++ vnext/Desktop/ABI/ReactNativeHost.cpp | 66 +++++++++++++++++++ vnext/Desktop/ABI/ReactNativeHost.h | 42 ++++++++++++ vnext/Desktop/React.Windows.Desktop.vcxproj | 22 +++++++ .../React.Windows.Desktop.vcxproj.filters | 33 ++++++++++ vnext/Desktop/module.g.cpp | 8 +++ 15 files changed, 241 insertions(+), 7 deletions(-) create mode 100644 change/react-native-windows-2020-04-30-18-28-03-abi-safety.json create mode 100644 change/react-native-windows-2020-05-09-17-42-52-abi-safety.json create mode 100644 vnext/Desktop.ABITests/ActivationFactory.h create mode 100644 vnext/Desktop.ABITests/ReactNativeHostTests.cpp create mode 100644 vnext/Desktop/ABI/ReactNativeHost.cpp create mode 100644 vnext/Desktop/ABI/ReactNativeHost.h diff --git a/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json b/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json new file mode 100644 index 00000000000..7cf31717cd8 --- /dev/null +++ b/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json @@ -0,0 +1,8 @@ +{ + "type": "none", + "comment": "test bundle build logic, JS function call test", + "packageName": "react-native-windows", + "email": "aeulitz@microsoft.com", + "dependentChangeType": "none", + "date": "2020-05-01T01:28:03.315Z" +} diff --git a/change/react-native-windows-2020-05-09-17-42-52-abi-safety.json b/change/react-native-windows-2020-05-09-17-42-52-abi-safety.json new file mode 100644 index 00000000000..ef25becd822 --- /dev/null +++ b/change/react-native-windows-2020-05-09-17-42-52-abi-safety.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "add ReactNativeHost to Win32 C++/WinRT ABI", + "packageName": "react-native-windows", + "email": "aeulitz@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-10T00:42:52.866Z" +} diff --git a/vnext/Desktop.ABITests/ActivationFactory.cpp b/vnext/Desktop.ABITests/ActivationFactory.cpp index 81ff78b6cf7..19915c7e683 100644 --- a/vnext/Desktop.ABITests/ActivationFactory.cpp +++ b/vnext/Desktop.ABITests/ActivationFactory.cpp @@ -26,7 +26,7 @@ int32_t __stdcall WINRT_RoGetActivationFactory(void *classId, guid const &iid, v std::wstring_view const name{*reinterpret_cast(&classId)}; HMODULE library{nullptr}; - if (starts_with(name, L"facebook.react.")) { + if (starts_with(name, L"facebook.react.") || starts_with(name, L"Microsoft.React")) { library = LoadLibraryExW(RNDLLPATH, NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); } else { return OS_RoGetActivationFactory(classId, iid, factory); diff --git a/vnext/Desktop.ABITests/ActivationFactory.h b/vnext/Desktop.ABITests/ActivationFactory.h new file mode 100644 index 00000000000..e53f76d24ce --- /dev/null +++ b/vnext/Desktop.ABITests/ActivationFactory.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "pch.h" +#include +#include + +extern int32_t __stdcall WINRT_RoGetActivationFactory(void *classId, winrt::guid const &iid, void **factory) noexcept; diff --git a/vnext/Desktop.ABITests/MemoryTrackerTests.cpp b/vnext/Desktop.ABITests/MemoryTrackerTests.cpp index ce3da0f7549..79ad888716c 100644 --- a/vnext/Desktop.ABITests/MemoryTrackerTests.cpp +++ b/vnext/Desktop.ABITests/MemoryTrackerTests.cpp @@ -7,14 +7,13 @@ #include #include +#include "ActivationFactory.h" #include "MessageQueueShim.h" using namespace Microsoft::React::Test; using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace winrt::facebook::react; -int32_t __stdcall WINRT_RoGetActivationFactory(void *classId, winrt::guid const &iid, void **factory) noexcept; - namespace ABITests { // We turn clang format off here because it does not work with some of the diff --git a/vnext/Desktop.ABITests/NativeLogEventTests.cpp b/vnext/Desktop.ABITests/NativeLogEventTests.cpp index d23fd4ae2ad..859b84dca56 100644 --- a/vnext/Desktop.ABITests/NativeLogEventTests.cpp +++ b/vnext/Desktop.ABITests/NativeLogEventTests.cpp @@ -5,13 +5,12 @@ #include #include #include +#include "ActivationFactory.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace winrt::facebook::react; using namespace winrt; -int32_t __stdcall WINRT_RoGetActivationFactory(void *classId, winrt::guid const &iid, void **factory) noexcept; - namespace ABITests { TEST_CLASS (NativeLogEventTests) { diff --git a/vnext/Desktop.ABITests/NativeTraceEventTests.cpp b/vnext/Desktop.ABITests/NativeTraceEventTests.cpp index 371589c30a1..16348920fa3 100644 --- a/vnext/Desktop.ABITests/NativeTraceEventTests.cpp +++ b/vnext/Desktop.ABITests/NativeTraceEventTests.cpp @@ -6,13 +6,12 @@ #include #include #include +#include "ActivationFactory.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace winrt::facebook::react; using namespace winrt; -int32_t __stdcall WINRT_RoGetActivationFactory(void *classId, winrt::guid const &iid, void **factory) noexcept; - namespace ABITests { TEST_CLASS (NativeTraceEventTests) { diff --git a/vnext/Desktop.ABITests/React.Windows.Desktop.ABITests.vcxproj b/vnext/Desktop.ABITests/React.Windows.Desktop.ABITests.vcxproj index ec0af2a58ba..c4972ba5924 100644 --- a/vnext/Desktop.ABITests/React.Windows.Desktop.ABITests.vcxproj +++ b/vnext/Desktop.ABITests/React.Windows.Desktop.ABITests.vcxproj @@ -103,6 +103,9 @@ $(OutputPath)..\React.Windows.Desktop\facebook.react.winmd + + $(OutputPath)..\React.Windows.Desktop\Microsoft.ReactNative.winmd + @@ -133,9 +136,11 @@ Create + + diff --git a/vnext/Desktop.ABITests/React.Windows.Desktop.ABITests.vcxproj.filters b/vnext/Desktop.ABITests/React.Windows.Desktop.ABITests.vcxproj.filters index 49daa4eb2a2..76bd4b11819 100644 --- a/vnext/Desktop.ABITests/React.Windows.Desktop.ABITests.vcxproj.filters +++ b/vnext/Desktop.ABITests/React.Windows.Desktop.ABITests.vcxproj.filters @@ -36,6 +36,9 @@ Source Files + + Source Files + @@ -44,6 +47,9 @@ Header Files + + Header Files + diff --git a/vnext/Desktop.ABITests/ReactNativeHostTests.cpp b/vnext/Desktop.ABITests/ReactNativeHostTests.cpp new file mode 100644 index 00000000000..7206f5b8daf --- /dev/null +++ b/vnext/Desktop.ABITests/ReactNativeHostTests.cpp @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" +#include +#include +#include "ActivationFactory.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace ABITests { + +TEST_CLASS (ReactNativeHostTests) { + public: + ReactNativeHostTests() noexcept { + winrt_activation_handler = WINRT_RoGetActivationFactory; + } + + TEST_METHOD(Activation_Succeeds) { + try { + winrt::Microsoft::ReactNative::ReactNativeHost host{}; + Assert::IsTrue(true); + } catch (...) { + Assert::Fail(); + } + } +}; + +} // namespace ABITests diff --git a/vnext/Desktop/ABI/ReactNativeHost.cpp b/vnext/Desktop/ABI/ReactNativeHost.cpp new file mode 100644 index 00000000000..4486d9a209f --- /dev/null +++ b/vnext/Desktop/ABI/ReactNativeHost.cpp @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include "ReactNativeHost.h" + +#include "Microsoft.ReactNative.ReactNativeHost.g.cpp" + +using namespace winrt::Windows::Foundation::Collections; + +namespace winrt::Microsoft::ReactNative::implementation { + +ReactNativeHost::ReactNativeHost() noexcept { + // TODO: implement +} + +IVector ReactNativeHost::PackageProviders() noexcept { + if (!m_packageProviders) { + m_packageProviders = single_threaded_vector(); + } + + return m_packageProviders; +} + +void ReactNativeHost::PackageProviders(IVector const &value) noexcept { + m_packageProviders = value; +} + +ReactNative::ReactInstanceSettings ReactNativeHost::InstanceSettings() noexcept { + if (!m_instanceSettings) { + // TODO: implement + // m_instanceSettings = make(); + } + + return m_instanceSettings; +} + +void ReactNativeHost::InstanceSettings(ReactNative::ReactInstanceSettings const &value) noexcept { + m_instanceSettings = value; +} + +void ReactNativeHost::ReloadInstance() noexcept { + // TODO: implement +} + +void ReactNativeHost::OnSuspend() noexcept { + // TODO: implement +} + +void ReactNativeHost::OnEnteredBackground() noexcept { + // TODO: implement +} + +void ReactNativeHost::OnLeavingBackground() noexcept { + // TODO: implement +} + +void ReactNativeHost::OnResume(OnResumeAction const & /*action*/) noexcept { + // TODO: implement +} + +void ReactNativeHost::OnBackPressed() noexcept { + // TODO: implement +} + +} // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Desktop/ABI/ReactNativeHost.h b/vnext/Desktop/ABI/ReactNativeHost.h new file mode 100644 index 00000000000..f1596c4b49b --- /dev/null +++ b/vnext/Desktop/ABI/ReactNativeHost.h @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include + +#include "Microsoft.ReactNative.ReactNativeHost.g.h" + +namespace winrt::Microsoft::ReactNative::implementation { + +struct ReactNativeHost : ReactNativeHostT { + ReactNativeHost() noexcept; + + // property PackageProviders + Windows::Foundation::Collections::IVector PackageProviders() noexcept; + void PackageProviders(Windows::Foundation::Collections::IVector const &value) noexcept; + + // property InstanceSettings + ReactNative::ReactInstanceSettings InstanceSettings() noexcept; + void InstanceSettings(ReactNative::ReactInstanceSettings const &value) noexcept; + + void ReloadInstance() noexcept; + + void OnSuspend() noexcept; + void OnEnteredBackground() noexcept; + void OnLeavingBackground() noexcept; + void OnResume(OnResumeAction const &action) noexcept; + void OnBackPressed() noexcept; + + private: + ReactNative::ReactInstanceSettings m_instanceSettings{nullptr}; + Windows::Foundation::Collections::IVector m_packageProviders; +}; + +} // namespace winrt::Microsoft::ReactNative::implementation + +namespace winrt::Microsoft::ReactNative::factory_implementation { + +struct ReactNativeHost : ReactNativeHostT {}; + +} // namespace winrt::Microsoft::ReactNative::factory_implementation diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj b/vnext/Desktop/React.Windows.Desktop.vcxproj index 556cb33f4db..304f44e661b 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj @@ -90,6 +90,9 @@ Shlwapi.lib;%(AdditionalDependencies) -minpdbpathlen:256 + + $(ReactNativeWindowsDir)\Microsoft.ReactNative;$(ReactNativeWindowsDir)\Microsoft.ReactNative.Cxx; + @@ -97,6 +100,17 @@ + + + + + + + + + + + @@ -115,6 +129,10 @@ ABI\NativeTracing.idl $(IntDir)\ABI\ + + ..\Microsoft.ReactNative\ReactNativeHost.idl + $(IntDir)\ABI\ + @@ -145,6 +163,10 @@ ABI\NativeTracing.idl + + ..\Microsoft.ReactNative\ReactNativeHost.idl + Code + diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj.filters b/vnext/Desktop/React.Windows.Desktop.vcxproj.filters index e150e18d4fa..6a4be8c5886 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj.filters +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj.filters @@ -42,6 +42,39 @@ ABI + + ABI + + + ABI + + + ABI + + + ABI + + + ABI + + + ABI + + + ABI + + + ABI + + + ABI + + + ABI + + + ABI + diff --git a/vnext/Desktop/module.g.cpp b/vnext/Desktop/module.g.cpp index 84d71805b03..a1ed4613ebe 100644 --- a/vnext/Desktop/module.g.cpp +++ b/vnext/Desktop/module.g.cpp @@ -1,8 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +// WARNING: Please don't edit this file. It was generated by C++/WinRT v2.0.200316.3 + #include "pch.h" #include "winrt/base.h" +void* winrt_make_Microsoft_ReactNative_ReactNativeHost(); void* winrt_make_facebook_react_MemoryTracker(); void* winrt_make_facebook_react_NativeLogEventSource(); void* winrt_make_facebook_react_NativeTraceEventSource(); @@ -25,6 +28,11 @@ void* __stdcall winrt_get_activation_factory([[maybe_unused]] std::wstring_view return std::equal(left.rbegin(), left.rend(), right.rbegin(), right.rend()); }; + if (requal(name, L"Microsoft.ReactNative.ReactNativeHost")) + { + return winrt_make_Microsoft_ReactNative_ReactNativeHost(); + } + if (requal(name, L"facebook.react.MemoryTracker")) { return winrt_make_facebook_react_MemoryTracker(); From 8033b548f81e48d904b4dd1b1f81df33dbb232c4 Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Tue, 12 May 2020 14:41:11 -0700 Subject: [PATCH 086/209] Use spec file for DevSettings NativeModule (#4873) * Use spec file for DevSettings NativeModule * Change files * minor change --- ...s-2020-05-11-13-26-08-devsettingsspec.json | 8 +++ .../Modules/DevSettingsModule.cpp | 69 +++++++++++-------- .../Modules/DevSettingsModule.h | 36 +++++----- .../ReactHost/ReactInstanceWin.cpp | 25 ++++--- 4 files changed, 81 insertions(+), 57 deletions(-) create mode 100644 change/react-native-windows-2020-05-11-13-26-08-devsettingsspec.json diff --git a/change/react-native-windows-2020-05-11-13-26-08-devsettingsspec.json b/change/react-native-windows-2020-05-11-13-26-08-devsettingsspec.json new file mode 100644 index 00000000000..bf2f07e8b92 --- /dev/null +++ b/change/react-native-windows-2020-05-11-13-26-08-devsettingsspec.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Use spec file for DevSettings NativeModule", + "packageName": "react-native-windows", + "email": "acoates@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-11T20:26:08.523Z" +} diff --git a/vnext/Microsoft.ReactNative/Modules/DevSettingsModule.cpp b/vnext/Microsoft.ReactNative/Modules/DevSettingsModule.cpp index 6d4312211c7..90a86c23900 100644 --- a/vnext/Microsoft.ReactNative/Modules/DevSettingsModule.cpp +++ b/vnext/Microsoft.ReactNative/Modules/DevSettingsModule.cpp @@ -6,53 +6,66 @@ namespace Microsoft::ReactNative { -auto DevSettingsModule::getConstants() -> std::map { - return {}; +void DevSettings::Initialize(winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept { + m_context = reactContext; } -const char *DevSettingsModule::name = "DevSettings"; -std::string DevSettingsModule::getName() { - return name; +struct ReloadFunctor + : winrt::implements> { + ReloadFunctor(Mso::VoidFunctor &&func) : m_func(std::move(func)) {} + + void operator()() { + m_func(); + } + + private: + Mso::VoidFunctor m_func; +}; + +/*static*/ void DevSettings::SetReload(Mso::React::ReactOptions const &options, Mso::VoidFunctor &&func) noexcept { + options.Properties.Set(ReloadProperty(), winrt::make(std::move(func))); } -DevSettingsModule::DevSettingsModule(Mso::VoidFunctor &&reload) : m_reload(std::move(reload)) {} +/*static*/ winrt::Microsoft::ReactNative::IReactPropertyName DevSettings::ReloadProperty() noexcept { + return winrt::Microsoft::ReactNative::ReactPropertyBagHelper::GetName( + winrt::Microsoft::ReactNative::ReactPropertyBagHelper::GetNamespace(L"DevSettings"), L"Reload"); +} -void DevSettingsModule::reload() { - m_reload(); +void DevSettings::reload() noexcept { + (*winrt::get_self(m_context.Properties().Get( + winrt::Microsoft::ReactNative::ReactPropertyId(ReloadProperty()))))(); } -void DevSettingsModule::setHotLoadingEnabled(bool /*isHotLoadingEnabled*/) { - assert(false); + +void DevSettings::reloadWithReason(std::string /*reason*/) noexcept { + reload(); } -void DevSettingsModule::setIsDebuggingRemotely(bool /*isDebuggingRemotelyEnabled*/) { + +void DevSettings::onFastRefresh() noexcept { + // noop +} + +void DevSettings::setHotLoadingEnabled(bool isHotLoadingEnabled) noexcept { assert(false); } -void DevSettingsModule::setLiveReloadEnabled(bool /*setLiveReloadEnabled*/) { + +void DevSettings::setIsDebuggingRemotely(bool isDebuggingRemotelyEnabled) noexcept { assert(false); } -void DevSettingsModule::setProfilingEnabled(bool /*setProfilingEnabled*/) { + +void DevSettings::setProfilingEnabled(bool isProfilingEnabled) noexcept { assert(false); } -void DevSettingsModule::toggleElementInspector() { + +void DevSettings::toggleElementInspector() noexcept { assert(false); } -// iOS only. -void DevSettingsModule::setIsShakeToShowDevMenuEnabled(bool /*enabled*/) { +void DevSettings::addMenuItem(std::string title) noexcept { assert(false); } -auto DevSettingsModule::getMethods() -> std::vector { - return { - Method("reload", [this](folly::dynamic args) { reload(); }), - Method("setHotLoadingEnabled", [this](folly::dynamic args) { setHotLoadingEnabled(args[0].getBool()); }), - Method("setIsDebuggingRemotely", [this](folly::dynamic args) { setIsDebuggingRemotely(args[0].getBool()); }), - Method("setLiveReloadEnabled", [this](folly::dynamic args) { setLiveReloadEnabled(args[0].getBool()); }), - Method("setProfilingEnabled", [this](folly::dynamic args) { setProfilingEnabled(args[0].getBool()); }), - Method("toggleElementInspector", [this](folly::dynamic args) { toggleElementInspector(); }), - Method( - "setIsShakeToShowDevMenuEnabled", - [this](folly::dynamic args) { setIsShakeToShowDevMenuEnabled(args[0].getBool()); }), - }; +void DevSettings::setIsShakeToShowDevMenuEnabled(bool enabled) noexcept { + assert(false); } } // namespace Microsoft::ReactNative diff --git a/vnext/Microsoft.ReactNative/Modules/DevSettingsModule.h b/vnext/Microsoft.ReactNative/Modules/DevSettingsModule.h index 531aec8024a..aeddf6a7c3d 100644 --- a/vnext/Microsoft.ReactNative/Modules/DevSettingsModule.h +++ b/vnext/Microsoft.ReactNative/Modules/DevSettingsModule.h @@ -5,30 +5,30 @@ #include #include -namespace Microsoft::ReactNative { - -class DevSettingsModule : public facebook::xplat::module::CxxModule { - public: - DevSettingsModule(Mso::VoidFunctor &&reload); +#include +#include - static const char *name; +namespace Microsoft::ReactNative { - std::string getName() override; - std::map getConstants() override; - std::vector getMethods() override; +REACT_MODULE(DevSettings) +struct DevSettings { + REACT_INIT(Initialize) void Initialize(winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept; - void reload(); - void setHotLoadingEnabled(bool isHotLoadingEnabled); - void setIsDebuggingRemotely(bool isDebuggingRemotelyEnabled); - void setLiveReloadEnabled(bool setLiveReloadEnabled); - void setProfilingEnabled(bool setProfilingEnabled); - void toggleElementInspector(); + REACT_METHOD(reload) void reload() noexcept; + REACT_METHOD(reloadWithReason) void reloadWithReason(std::string reason) noexcept; + REACT_METHOD(onFastRefresh) void onFastRefresh() noexcept; + REACT_METHOD(setHotLoadingEnabled) void setHotLoadingEnabled(bool isHotLoadingEnabled) noexcept; + REACT_METHOD(setIsDebuggingRemotely) void setIsDebuggingRemotely(bool isDebuggingRemotelyEnabled) noexcept; + REACT_METHOD(setProfilingEnabled) void setProfilingEnabled(bool isProfilingEnabled) noexcept; + REACT_METHOD(toggleElementInspector) void toggleElementInspector() noexcept; + REACT_METHOD(addMenuItem) void addMenuItem(std::string title) noexcept; + REACT_METHOD(setIsShakeToShowDevMenuEnabled) void setIsShakeToShowDevMenuEnabled(bool enabled) noexcept; - // iOS only. - void setIsShakeToShowDevMenuEnabled(bool enabled); + static void SetReload(Mso::React::ReactOptions const &options, Mso::VoidFunctor &&func) noexcept; private: - Mso::VoidFunctor m_reload; + static winrt::Microsoft::ReactNative::IReactPropertyName ReloadProperty() noexcept; + winrt::Microsoft::ReactNative::ReactContext m_context; }; } // namespace Microsoft::ReactNative diff --git a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp index 0218b9b075c..d5e8e48bba8 100644 --- a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +++ b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp @@ -14,6 +14,7 @@ #include "Microsoft.ReactNative/Threading/MessageQueueThreadFactory.h" #include "../../codegen/NativeClipboardSpec.g.h" +#include "../../codegen/NativeDevSettingsSpec.g.h" #include "NativeModules.h" #include "NativeModulesProvider.h" #include "Unicode.h" @@ -218,21 +219,23 @@ void ReactInstanceWin::Initialize() noexcept { ::Microsoft::ReactNative::Clipboard, ::Microsoft::ReactNativeSpecs::ClipboardSpec>()); + ::Microsoft::ReactNative::DevSettings::SetReload( + strongThis->Options(), [weakReactHost = m_weakReactHost]() noexcept { + if (auto reactHost = weakReactHost.GetStrongPtr()) { + reactHost->ReloadInstance(); + } + }); + + nmp->AddModuleProvider( + L"DevSettings", + winrt::Microsoft::ReactNative::MakeTurboModuleProvider< + ::Microsoft::ReactNative::DevSettings, + ::Microsoft::ReactNativeSpecs::DevSettingsSpec>()); + auto modules = nmp->GetModules(m_reactContext, m_batchingUIThread); cxxModules.insert( cxxModules.end(), std::make_move_iterator(modules.begin()), std::make_move_iterator(modules.end())); - cxxModules.emplace_back( - Microsoft::ReactNative::DevSettingsModule::name, - [weakReactHost = strongThis->m_weakReactHost]() { - return std::make_unique([weakReactHost]() noexcept { - if (auto reactHost = weakReactHost.GetStrongPtr()) { - reactHost->ReloadInstance(); - } - }); - }, - m_batchingUIThread); - if (m_options.ModuleProvider != nullptr) { std::vector customCxxModules = m_options.ModuleProvider->GetModules(m_reactContext, m_batchingUIThread); From dbe875f5f1445d4a3967b466ad83d0c33d76a53c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20C=C3=A9sar=20Rocha?= Date: Tue, 12 May 2020 15:09:12 -0700 Subject: [PATCH 087/209] Handle HTTP errors in DevSupportManager. (#4880) * Handle HTTP connect exceptions in DevSupportManager * Change files --- ...2020-05-12-14-18-36-OC-4094136-connectxcpt.json | 8 ++++++++ vnext/Desktop/DevSupportManager.cpp | 14 ++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 change/react-native-windows-2020-05-12-14-18-36-OC-4094136-connectxcpt.json diff --git a/change/react-native-windows-2020-05-12-14-18-36-OC-4094136-connectxcpt.json b/change/react-native-windows-2020-05-12-14-18-36-OC-4094136-connectxcpt.json new file mode 100644 index 00000000000..6d5da5b4ecf --- /dev/null +++ b/change/react-native-windows-2020-05-12-14-18-36-OC-4094136-connectxcpt.json @@ -0,0 +1,8 @@ +{ + "type": "none", + "comment": "Handle HTTP connect exceptions in DevSupportManager", + "packageName": "react-native-windows", + "email": "julio.rocha@microsoft.com", + "dependentChangeType": "none", + "date": "2020-05-12T21:18:36.538Z" +} diff --git a/vnext/Desktop/DevSupportManager.cpp b/vnext/Desktop/DevSupportManager.cpp index d5c8d5c7dba..2877c043fa2 100644 --- a/vnext/Desktop/DevSupportManager.cpp +++ b/vnext/Desktop/DevSupportManager.cpp @@ -59,7 +59,12 @@ string DevSupportManager::GetJavaScriptFromServer( Url url(bundleUrl); auto const resolveResult = m_resolver.resolve(url.host, url.port); tcp::socket socket{m_context}; - connect(socket, resolveResult); + boost::system::error_code ec; + connect(socket, resolveResult, ec); + if (ec) { + m_exceptionCaught = true; + return R"({"error:")"s + ec.message() + R"("})"s; + } request request{verb::get, url.Target(), 11}; request.set(field::host, url.host); @@ -119,7 +124,12 @@ task DevSupportManager::LaunchDevToolsAsync(const string &debugHost, const Url url(DevServerHelper::get_LaunchDevToolsCommandUrl(debugHost)); auto const resolveResult = m_resolver.resolve(url.host, url.port); tcp::socket socket{m_context}; - connect(socket, resolveResult); + boost::system::error_code ec; + connect(socket, resolveResult, ec); + if (ec) { + m_exceptionCaught = true; + return; + } request request{verb::get, url.Target(), 11}; request.set(field::host, url.host); From be556508b69e022ce99ea0475ee354962d8e200c Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Wed, 13 May 2020 00:04:21 +0000 Subject: [PATCH 088/209] applying package updates ***NO_CI*** --- ...indows-2020-04-30-18-28-03-abi-safety.json | 8 ---- ...indows-2020-05-09-17-42-52-abi-safety.json | 8 ---- ...s-2020-05-11-11-06-42-FixReactContext.json | 8 ---- ...s-2020-05-11-13-26-08-devsettingsspec.json | 8 ---- ...05-12-14-18-36-OC-4094136-connectxcpt.json | 8 ---- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- vnext/CHANGELOG.json | 41 +++++++++++++++++++ vnext/CHANGELOG.md | 12 +++++- vnext/package.json | 2 +- 11 files changed, 56 insertions(+), 45 deletions(-) delete mode 100644 change/react-native-windows-2020-04-30-18-28-03-abi-safety.json delete mode 100644 change/react-native-windows-2020-05-09-17-42-52-abi-safety.json delete mode 100644 change/react-native-windows-2020-05-11-11-06-42-FixReactContext.json delete mode 100644 change/react-native-windows-2020-05-11-13-26-08-devsettingsspec.json delete mode 100644 change/react-native-windows-2020-05-12-14-18-36-OC-4094136-connectxcpt.json diff --git a/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json b/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json deleted file mode 100644 index 7cf31717cd8..00000000000 --- a/change/react-native-windows-2020-04-30-18-28-03-abi-safety.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "none", - "comment": "test bundle build logic, JS function call test", - "packageName": "react-native-windows", - "email": "aeulitz@microsoft.com", - "dependentChangeType": "none", - "date": "2020-05-01T01:28:03.315Z" -} diff --git a/change/react-native-windows-2020-05-09-17-42-52-abi-safety.json b/change/react-native-windows-2020-05-09-17-42-52-abi-safety.json deleted file mode 100644 index ef25becd822..00000000000 --- a/change/react-native-windows-2020-05-09-17-42-52-abi-safety.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "add ReactNativeHost to Win32 C++/WinRT ABI", - "packageName": "react-native-windows", - "email": "aeulitz@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-10T00:42:52.866Z" -} diff --git a/change/react-native-windows-2020-05-11-11-06-42-FixReactContext.json b/change/react-native-windows-2020-05-11-11-06-42-FixReactContext.json deleted file mode 100644 index d3bc77290fd..00000000000 --- a/change/react-native-windows-2020-05-11-11-06-42-FixReactContext.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Fixed ReactContext copy/move semantic", - "packageName": "react-native-windows", - "email": "vmorozov@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-11T18:06:42.425Z" -} diff --git a/change/react-native-windows-2020-05-11-13-26-08-devsettingsspec.json b/change/react-native-windows-2020-05-11-13-26-08-devsettingsspec.json deleted file mode 100644 index bf2f07e8b92..00000000000 --- a/change/react-native-windows-2020-05-11-13-26-08-devsettingsspec.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Use spec file for DevSettings NativeModule", - "packageName": "react-native-windows", - "email": "acoates@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-11T20:26:08.523Z" -} diff --git a/change/react-native-windows-2020-05-12-14-18-36-OC-4094136-connectxcpt.json b/change/react-native-windows-2020-05-12-14-18-36-OC-4094136-connectxcpt.json deleted file mode 100644 index 6d5da5b4ecf..00000000000 --- a/change/react-native-windows-2020-05-12-14-18-36-OC-4094136-connectxcpt.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "none", - "comment": "Handle HTTP connect exceptions in DevSupportManager", - "packageName": "react-native-windows", - "email": "julio.rocha@microsoft.com", - "dependentChangeType": "none", - "date": "2020-05-12T21:18:36.538Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index a2448e2e4ba..c25b4a7209c 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.64" + "react-native-windows": "0.0.0-master.65" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index a994357bb72..9192adc47a2 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.64" + "react-native-windows": "0.0.0-master.65" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index 55d1d381182..64b1cc263d6 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.64" + "react-native-windows": "0.0.0-master.65" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index a53ac0d9280..f5bd3760b42 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,47 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Wed, 13 May 2020 00:04:21 GMT", + "tag": "react-native-windows_v0.0.0-master.65", + "version": "0.0.0-master.65", + "comments": { + "none": [ + { + "comment": "test bundle build logic, JS function call test", + "author": "aeulitz@microsoft.com", + "commit": "56e08530db3e751a8813785bb51aeb728aad98b0", + "package": "react-native-windows" + }, + { + "comment": "Handle HTTP connect exceptions in DevSupportManager", + "author": "julio.rocha@microsoft.com", + "commit": "dbe875f5f1445d4a3967b466ad83d0c33d76a53c", + "package": "react-native-windows" + } + ], + "prerelease": [ + { + "comment": "add ReactNativeHost to Win32 C++/WinRT ABI", + "author": "aeulitz@microsoft.com", + "commit": "49e65479d70ab1df738cb7bf21e915e9453eaf13", + "package": "react-native-windows" + }, + { + "comment": "Fixed ReactContext copy/move semantic", + "author": "vmorozov@microsoft.com", + "commit": "d5e8bdcbf63a8ee2e9221bfa344faa227ef892e3", + "package": "react-native-windows" + }, + { + "comment": "Use spec file for DevSettings NativeModule", + "author": "acoates@microsoft.com", + "commit": "8033b548f81e48d904b4dd1b1f81df33dbb232c4", + "package": "react-native-windows" + } + ] + } + }, { "date": "Tue, 12 May 2020 00:04:39 GMT", "tag": "react-native-windows_v0.0.0-master.64", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index b680713a308..2ebe842eed9 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,19 @@ # Change Log - react-native-windows -This log was last generated on Tue, 12 May 2020 00:04:39 GMT and should not be manually modified. +This log was last generated on Wed, 13 May 2020 00:04:21 GMT and should not be manually modified. +## 0.0.0-master.65 + +Wed, 13 May 2020 00:04:21 GMT + +### Changes + +- add ReactNativeHost to Win32 C++/WinRT ABI (aeulitz@microsoft.com) +- Fixed ReactContext copy/move semantic (vmorozov@microsoft.com) +- Use spec file for DevSettings NativeModule (acoates@microsoft.com) + ## 0.0.0-master.64 Tue, 12 May 2020 00:04:39 GMT diff --git a/vnext/package.json b/vnext/package.json index 228a39cb384..e8d93f226d0 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.64", + "version": "0.0.0-master.65", "license": "MIT", "repository": { "type": "git", From d1abb363bfcd8dc7f84fec768f32525002109919 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Tue, 12 May 2020 21:44:50 -0700 Subject: [PATCH 089/209] Allow storing non-WinRT types in ReactPropertyBag (#4884) * Allow storing non-WinRT types in ReactPropertyBag * Change files * Addressed PR feedback --- ...-2020-05-12-18-57-59-UnsafePropertyId.json | 8 +++++ vnext/Microsoft.ReactNative.Cxx/BoxedValue.h | 31 +++++++++++++++++++ .../Microsoft.ReactNative.Cxx.vcxitems | 1 + .../Microsoft.ReactNative.Cxx/NativeModules.h | 18 +---------- .../ReactPropertyBag.h | 24 +++++++++++--- .../ReactPropertyBagTests.cpp | 22 +++++++++++++ 6 files changed, 82 insertions(+), 22 deletions(-) create mode 100644 change/react-native-windows-2020-05-12-18-57-59-UnsafePropertyId.json create mode 100644 vnext/Microsoft.ReactNative.Cxx/BoxedValue.h diff --git a/change/react-native-windows-2020-05-12-18-57-59-UnsafePropertyId.json b/change/react-native-windows-2020-05-12-18-57-59-UnsafePropertyId.json new file mode 100644 index 00000000000..2841e2d184d --- /dev/null +++ b/change/react-native-windows-2020-05-12-18-57-59-UnsafePropertyId.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Allow storing non-WinRT types in ReactPropertyBag", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-13T01:57:59.370Z" +} diff --git a/vnext/Microsoft.ReactNative.Cxx/BoxedValue.h b/vnext/Microsoft.ReactNative.Cxx/BoxedValue.h new file mode 100644 index 00000000000..841391a718b --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/BoxedValue.h @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#ifndef MICROSOFT_REACTNATIVE_BOXEDVALUE +#define MICROSOFT_REACTNATIVE_BOXEDVALUE + +#include + +namespace winrt::Microsoft::ReactNative { + +template +struct BoxedValue : implements, IBoxedValue> { + template + BoxedValue(TArgs &&... args) noexcept : m_value(std::forward(args)...) {} + + int64_t GetPtr() const noexcept { + return reinterpret_cast(&m_value); + } + + static T &GetValueUnsafe(IBoxedValue const &boxedValue) noexcept { + return *reinterpret_cast(boxedValue.GetPtr()); + } + + private: + T m_value{}; +}; + +} // namespace winrt::Microsoft::ReactNative + +#endif // MICROSOFT_REACTNATIVE_BOXEDVALUE diff --git a/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems b/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems index 9a476a959fb..38328ca6aa6 100644 --- a/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +++ b/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems @@ -17,6 +17,7 @@ + diff --git a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h index 19ab45c0080..23532730abc 100644 --- a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h +++ b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h @@ -4,6 +4,7 @@ #pragma once #include "winrt/Microsoft.ReactNative.h" +#include "BoxedValue.h" #include "JSValueReader.h" #include "JSValueWriter.h" #include "ModuleRegistration.h" @@ -1105,23 +1106,6 @@ struct TurboModuleSpec { } }; -template -struct BoxedValue : implements, IBoxedValue> { - template - BoxedValue(TArgs &&... args) noexcept : m_value(std::forward(args)...) {} - - int64_t GetPtr() noexcept { - return reinterpret_cast(&m_value); - } - - static T &GetValueUnsafe(IBoxedValue const &boxedValue) noexcept { - return *reinterpret_cast(boxedValue.GetPtr()); - } - - private: - T m_value{}; -}; - template inline ReactModuleProvider MakeModuleProvider() noexcept { return [](IReactModuleBuilder const &moduleBuilder) noexcept { diff --git a/vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h b/vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h index 1dc6d09bcdf..fcf75ff7a22 100644 --- a/vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h +++ b/vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h @@ -37,12 +37,14 @@ // directly because their null value may indicated absent property value. // For other types we return std::optional. It has std::nullopt value in case if // no property value is found or if it has a wrong type. -// To avoid compilation errors the non-IInspectable types must be WinRT types which are described here: +// To pass values through the ABI boundary the non-IInspectable types must be WinRT types +// which are described here: // https://docs.microsoft.com/en-us/uwp/api/windows.foundation.propertytype?view=winrt-18362 // #include #include +#include "BoxedValue.h" namespace winrt::Microsoft::ReactNative { @@ -113,10 +115,10 @@ struct ReactPropertyId { IReactPropertyName m_handle; }; -// ReactPropertyBag is a wrapper for IReactPropertyBag to stores strongly-typed properties in a thread-safe way. +// ReactPropertyBag is a wrapper for IReactPropertyBag to store strongly-typed properties in a thread-safe way. // Types inherited from IInspectable are stored directly. // Values of other types are boxed with help of winrt::box_value. -// Only WinRT types can be stored. +// Non-WinRT types are wrapped with the help of BoxedValue template. struct ReactPropertyBag { // Property result type is either T or std::optional. // T is returned for types inherited from IInspectable. @@ -235,7 +237,11 @@ struct ReactPropertyBag { private: template static Windows::Foundation::IInspectable ToObject(T const &value) noexcept { - return winrt::box_value(value); + if constexpr (impl::has_category_v) { + return box_value(value); + } else { + return make>(value); + } } template @@ -247,7 +253,7 @@ struct ReactPropertyBag { static auto FromObject(Windows::Foundation::IInspectable const &obj) noexcept { if constexpr (std::is_base_of_v) { return obj.try_as(); - } else { + } else if constexpr (impl::has_category_v) { if (obj) { #ifdef WINRT_IMPL_IUNKNOWN_DEFINED if constexpr (std::is_same_v) { @@ -267,6 +273,14 @@ struct ReactPropertyBag { } } + return std::optional{}; + } else { + if (obj) { + if (auto temp = obj.try_as()) { + return std::optional{BoxedValue::GetValueUnsafe(temp)}; + } + } + return std::optional{}; } } diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp b/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp index 27168257d81..f96cee63e26 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp +++ b/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp @@ -6,6 +6,7 @@ using namespace winrt; using namespace Microsoft::ReactNative; +using namespace Windows::Foundation; namespace ReactNativeIntegrationTests { @@ -522,6 +523,27 @@ TEST_CLASS (ReactPropertyBagTests) { pb.Remove(fooName); TestCheck(!pb.Get(fooName)); } + + TEST_METHOD(PropertyBag_Property_Functor) { + ReactPropertyId> fooName{L"Foo"}; + ReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; + + TestCheck(!pb.Get(fooName)); + Mso::Functor createValue1 = []() noexcept { + return winrt::box_value(5); + }; + TestCheckEqual(createValue1, *pb.GetOrCreate(fooName, [&createValue1]() { return createValue1; })); + TestCheckEqual(createValue1, *pb.Get(fooName)); + TestCheckEqual(5, winrt::unbox_value((*pb.Get(fooName))())); + + Mso::Functor createValue2 = []() { return winrt::box_value(10); }; + pb.Set(fooName, createValue2); + TestCheckEqual(createValue2, *pb.Get(fooName)); + TestCheckEqual(10, winrt::unbox_value((*pb.Get(fooName))())); + TestCheck(createValue1 != *pb.Get(fooName)); + pb.Remove(fooName); + TestCheck(!pb.Get(fooName)); + } }; } // namespace ReactNativeIntegrationTests From e6337047f6085b32951eeff4f5063d21e5c7da2f Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Wed, 13 May 2020 11:14:26 -0700 Subject: [PATCH 090/209] Use DispatcherQueue instead of CoreDispatcher for Mso::DispatchQueue (#4877) * Use DispatcherQueue instead of CoreDispatcher for Mso::DispatchQueue * Change files * Removed 'Thread' from some new API names. * Removed extra 'private' section in AppearanceModule * Temporary: use CoreDispatcher to check the E2E test * Avoid using DispatcherQueue::HasThreadAccess in earlier Windows versions. --- ...indows-2020-05-12-11-18-16-MS_UIQueue.json | 8 ++ .../SampleLibraryCPP/SampleModuleCPP.h | 4 +- .../windows/SampleLibraryCS/SampleModuleCS.cs | 4 +- .../playground/windows/playground-win32.sln | 3 + .../IReactDispatcher.cpp | 44 +++++++ .../Microsoft.ReactNative/IReactDispatcher.h | 52 ++++++++ .../IReactDispatcher.idl | 32 +++++ .../Microsoft.ReactNative.vcxproj | 9 +- .../Microsoft.ReactNative.vcxproj.filters | 5 +- .../Modules/AppStateData.cpp | 8 +- .../Modules/AppStateData.h | 4 +- .../ReactApplication.cpp | 2 + .../ReactHost/ReactInstanceWin.cpp | 15 ++- .../ReactHost/ReactInstanceWin.h | 1 + .../ReactInstanceSettings.idl | 2 +- vnext/Microsoft.ReactNative/RedBox.cpp | 54 +++++---- vnext/Microsoft.ReactNative/RedBox.h | 4 +- vnext/Microsoft.ReactNative/RedBoxHandler.cpp | 4 +- .../Threading/MessageQueueThreadFactory.cpp | 3 +- vnext/Mso/dispatchQueue/dispatchQueue.h | 13 +- vnext/Mso/src/dispatchQueue/queueService.cpp | 5 - vnext/Mso/src/dispatchQueue/queueService.h | 2 - .../src/dispatchQueue/uiScheduler_winrt.cpp | 114 +++++++++--------- vnext/ReactUWP/Base/UwpReactInstance.cpp | 2 +- vnext/ReactUWP/Modules/AppearanceModule.cpp | 8 +- vnext/ReactUWP/Modules/AppearanceModule.h | 2 +- vnext/ReactUWP/ReactUWP.vcxproj.filters | 10 +- 27 files changed, 280 insertions(+), 134 deletions(-) create mode 100644 change/react-native-windows-2020-05-12-11-18-16-MS_UIQueue.json create mode 100644 vnext/Microsoft.ReactNative/IReactDispatcher.cpp create mode 100644 vnext/Microsoft.ReactNative/IReactDispatcher.h create mode 100644 vnext/Microsoft.ReactNative/IReactDispatcher.idl diff --git a/change/react-native-windows-2020-05-12-11-18-16-MS_UIQueue.json b/change/react-native-windows-2020-05-12-11-18-16-MS_UIQueue.json new file mode 100644 index 00000000000..aeec541b06c --- /dev/null +++ b/change/react-native-windows-2020-05-12-11-18-16-MS_UIQueue.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Use DispatcherQueue instead of CoreDispatcher for Mso::DispatchQueue", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-12T18:18:15.956Z" +} diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleModuleCPP.h b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleModuleCPP.h index 87f071637f2..161adc8f9c8 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleModuleCPP.h +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleModuleCPP.h @@ -36,8 +36,8 @@ struct SampleModuleCppImpl { void Initialize(ReactContext const &reactContext) noexcept { const ReactPropertyId myProp1{L"Prop1"}; const ReactPropertyId myProp2{L"Prop2"}; - DEBUG_OUTPUT("globalProps.Prop1:", *reactContext.Properties().Get(myProp1)); - DEBUG_OUTPUT("instanceProps.Prop2:", winrt::to_string(*reactContext.Properties().Get(myProp2))); + DEBUG_OUTPUT("C++ Properties.Prop1:", *reactContext.Properties().Get(myProp1)); + DEBUG_OUTPUT("C++ Properties.Prop2:", winrt::to_string(*reactContext.Properties().Get(myProp2))); m_timer = winrt::Windows::System::Threading::ThreadPoolTimer::CreatePeriodicTimer( [this](const winrt::Windows::System::Threading::ThreadPoolTimer) noexcept { diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs index 655e8391d7b..732219ba1e4 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs @@ -26,8 +26,8 @@ internal sealed class SampleModuleCS [ReactInitializer] public void Initialize(ReactContext reactContext) { - Debug.WriteLine($"C# globalProps.Prop1: {reactContext.Handle.Properties.Get(ReactPropertyBagHelper.GetName(null, "Prop1"))}"); - Debug.WriteLine($"C# instanceProps.Prop2: {reactContext.Handle.Properties.Get(ReactPropertyBagHelper.GetName(null, "Prop2"))}"); + Debug.WriteLine($"C# Properties.Prop1: {reactContext.Handle.Properties.Get(ReactPropertyBagHelper.GetName(null, "Prop1"))}"); + Debug.WriteLine($"C# Properties.Prop2: {reactContext.Handle.Properties.Get(ReactPropertyBagHelper.GetName(null, "Prop2"))}"); _timer = ThreadPoolTimer.CreatePeriodicTimer(new TimerElapsedHandler((timer) => { diff --git a/packages/playground/windows/playground-win32.sln b/packages/playground/windows/playground-win32.sln index 3339e428ab1..705febd73f7 100644 --- a/packages/playground/windows/playground-win32.sln +++ b/packages/playground/windows/playground-win32.sln @@ -40,6 +40,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "..\..\..\vnext\Co EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", "..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems", "{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso", "..\..\..\vnext\Mso\Mso.vcxitems", "{84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ..\..\..\vnext\ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4 @@ -47,6 +49,7 @@ Global ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 ..\..\..\vnext\Mso\Mso.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 ..\..\..\vnext\Shared\Shared.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 + ..\..\..\vnext\Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{8b88ffae-4dbc-49a2-afa5-d2477d4ad189}*SharedItemsImports = 4 ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9 diff --git a/vnext/Microsoft.ReactNative/IReactDispatcher.cpp b/vnext/Microsoft.ReactNative/IReactDispatcher.cpp new file mode 100644 index 00000000000..4c394e94825 --- /dev/null +++ b/vnext/Microsoft.ReactNative/IReactDispatcher.cpp @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" +#include "IReactDispatcher.h" +#include "ReactDispatcherHelper.g.cpp" + +using namespace winrt; +using namespace Windows::Foundation; + +namespace winrt::Microsoft::ReactNative { + +ReactDispatcher::ReactDispatcher(Mso::DispatchQueue &&queue) noexcept : m_queue{std::move(queue)} {} + +bool ReactDispatcher::HasThreadAccess() noexcept { + return m_queue.HasThreadAccess(); +} + +void ReactDispatcher::Post(ReactDispatcherCallback const &callback) noexcept { + return m_queue.Post([callback]() noexcept { callback(); }); +} + +/*static*/ Mso::DispatchQueue ReactDispatcher::GetUIDispatchQueue(IReactPropertyBag const &properties) noexcept { + return GetUIDispatcher(properties).as()->m_queue; +} + +/*static*/ IReactDispatcher ReactDispatcher::UIThreadDispatcher() noexcept { + return make(Mso::DispatchQueue::MakeCurrentThreadUIQueue()); +} + +/*static*/ ReactPropertyId ReactDispatcher::UIDispatcherProperty() noexcept { + static ReactPropertyId uiThreadDispatcherProperty{L"ReactNative.Dispatcher", L"UIDispatcher"}; + return uiThreadDispatcherProperty; +} + +/*static*/ IReactDispatcher ReactDispatcher::GetUIDispatcher(IReactPropertyBag const &properties) noexcept { + return ReactPropertyBag{properties}.Get(UIDispatcherProperty()); +} + +/*static*/ void ReactDispatcher::SetUIThreadDispatcher(IReactPropertyBag const &properties) noexcept { + ReactPropertyBag{properties}.Set(UIDispatcherProperty(), UIThreadDispatcher()); +} + +} // namespace winrt::Microsoft::ReactNative diff --git a/vnext/Microsoft.ReactNative/IReactDispatcher.h b/vnext/Microsoft.ReactNative/IReactDispatcher.h new file mode 100644 index 00000000000..e71c0526012 --- /dev/null +++ b/vnext/Microsoft.ReactNative/IReactDispatcher.h @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#include "ReactDispatcherHelper.g.h" +#include +#include +#include + +namespace winrt::Microsoft::ReactNative { + +struct ReactDispatcher : implements { + ReactDispatcher() = default; + ReactDispatcher(Mso::DispatchQueue &&queue) noexcept; + + bool HasThreadAccess() noexcept; + void Post(ReactDispatcherCallback const &callback) noexcept; + + static Mso::DispatchQueue GetUIDispatchQueue(IReactPropertyBag const &properties) noexcept; + + static IReactDispatcher UIThreadDispatcher() noexcept; + static ReactPropertyId UIDispatcherProperty() noexcept; + static IReactDispatcher GetUIDispatcher(IReactPropertyBag const &properties) noexcept; + static void SetUIThreadDispatcher(IReactPropertyBag const &properties) noexcept; + + private: + Mso::DispatchQueue m_queue; +}; + +} // namespace winrt::Microsoft::ReactNative + +namespace winrt::Microsoft::ReactNative::implementation { + +struct ReactDispatcherHelper { + ReactDispatcherHelper() = default; + + static IReactDispatcher UIThreadDispatcher() noexcept { + return ReactDispatcher::UIThreadDispatcher(); + } + + static IReactPropertyName UIDispatcherProperty() noexcept { + return ReactDispatcher::UIDispatcherProperty().Handle(); + } +}; + +} // namespace winrt::Microsoft::ReactNative::implementation + +namespace winrt::Microsoft::ReactNative::factory_implementation { + +struct ReactDispatcherHelper : ReactDispatcherHelperT {}; + +} // namespace winrt::Microsoft::ReactNative::factory_implementation diff --git a/vnext/Microsoft.ReactNative/IReactDispatcher.idl b/vnext/Microsoft.ReactNative/IReactDispatcher.idl new file mode 100644 index 00000000000..e5f3d9b6d5f --- /dev/null +++ b/vnext/Microsoft.ReactNative/IReactDispatcher.idl @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import "IReactPropertyBag.idl"; + +namespace Microsoft.ReactNative { + + // The delegate is used to create property value on-demand. + [webhosthidden] + delegate void ReactDispatcherCallback(); + + [webhosthidden] + interface IReactDispatcher + { + // True if dispatcher uses current thread. + Boolean HasThreadAccess { get; }; + + // Post task for the asynchronous execution. + void Post(ReactDispatcherCallback callback); + } + + // Helper methods for the property bag implementation. + [webhosthidden] + static runtimeclass ReactDispatcherHelper + { + // Get or create IReactDispatcher for the current UI thread. + static IReactDispatcher UIThreadDispatcher{ get; }; + + // Get name of the UIDispatcher property for the IReactPropertyBag. + static IReactPropertyName UIDispatcherProperty(); + } +} // namespace ReactNative diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj index 68d21f19ac0..3a981cd2ef6 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj @@ -1,4 +1,4 @@ - + @@ -299,6 +299,9 @@ IJSValueWriter.idl + + IReactDispatcher.idl + IReactModuleBuilder.idl @@ -467,6 +470,9 @@ IJSValueWriter.idl + + IReactDispatcher.idl + IReactModuleBuilder.idl @@ -547,6 +553,7 @@ + diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters index de2019f2870..49caa030be9 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters @@ -265,6 +265,7 @@ + Modules @@ -298,7 +299,6 @@ ReactHost - @@ -599,6 +599,7 @@ Base + Modules @@ -648,7 +649,6 @@ ReactHost - @@ -685,6 +685,7 @@ + diff --git a/vnext/Microsoft.ReactNative/Modules/AppStateData.cpp b/vnext/Microsoft.ReactNative/Modules/AppStateData.cpp index 3f980dcbd45..b3e32f5ca5b 100644 --- a/vnext/Microsoft.ReactNative/Modules/AppStateData.cpp +++ b/vnext/Microsoft.ReactNative/Modules/AppStateData.cpp @@ -11,8 +11,8 @@ using namespace xaml; namespace react::uwp { -AppStateData::AppStateData(Mso::React::IReactContext &reactContext) noexcept - : Super(Mso::DispatchQueue::MainUIQueue()), m_lastState{"active"}, m_reactContext{&reactContext} {} +AppStateData::AppStateData(Mso::React::IReactContext &reactContext, Mso::DispatchQueue const &uiQueue) noexcept + : Super(uiQueue), m_lastState{"active"}, m_reactContext{&reactContext} {} AppStateData::~AppStateData() = default; @@ -59,8 +59,8 @@ void AppStateData::RaiseEvent(char const *newState) noexcept { "RCTDeviceEventEmitter", "emit", folly::dynamic::array("appStateDidChange", std::move(parameters))); } -AppState2::AppState2(Mso::React::IReactContext &reactContext) noexcept - : m_data{Mso::Make(reactContext)} {} +AppState2::AppState2(Mso::React::IReactContext &reactContext, Mso::DispatchQueue const &uiQueue) noexcept + : m_data{Mso::Make(reactContext, uiQueue)} {} AppState2::~AppState2() = default; diff --git a/vnext/Microsoft.ReactNative/Modules/AppStateData.h b/vnext/Microsoft.ReactNative/Modules/AppStateData.h index ff400f8af81..48bc55672c5 100644 --- a/vnext/Microsoft.ReactNative/Modules/AppStateData.h +++ b/vnext/Microsoft.ReactNative/Modules/AppStateData.h @@ -15,7 +15,7 @@ namespace react::uwp { struct AppStateData : Mso::ActiveObject<> { using Super = ActiveObjectType; - AppStateData(Mso::React::IReactContext &reactContext) noexcept; + AppStateData(Mso::React::IReactContext &reactContext, Mso::DispatchQueue const &uiQueue) noexcept; ~AppStateData() override; void Initialize() noexcept override; void Finalize() noexcept override; @@ -36,7 +36,7 @@ struct AppStateData : Mso::ActiveObject<> { // It is a temporary class that we need to keep until we remove ReactUWP class AppState2 : public facebook::react::AppState { public: - AppState2(Mso::React::IReactContext &reactContext) noexcept; + AppState2(Mso::React::IReactContext &reactContext, Mso::DispatchQueue const &uiQueue) noexcept; public: // facebook::react::AppState ~AppState2() override; diff --git a/vnext/Microsoft.ReactNative/ReactApplication.cpp b/vnext/Microsoft.ReactNative/ReactApplication.cpp index a4f2d1d4e93..ee7263ae52f 100644 --- a/vnext/Microsoft.ReactNative/ReactApplication.cpp +++ b/vnext/Microsoft.ReactNative/ReactApplication.cpp @@ -5,6 +5,7 @@ #include "ReactApplication.h" #include "ReactApplication.g.cpp" +#include "IReactDispatcher.h" #include "Modules/LinkingManagerModule.h" #include "ReactNativeHost.h" @@ -48,6 +49,7 @@ ReactApplication::ReactApplication(IInspectable const &outer) noexcept : ReactAp ReactNative::ReactInstanceSettings ReactApplication::InstanceSettings() noexcept { if (!m_instanceSettings) { m_instanceSettings = make(); + ReactDispatcher::SetUIThreadDispatcher(m_instanceSettings.Properties()); } return m_instanceSettings; diff --git a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp index d5e8e48bba8..6676d038690 100644 --- a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +++ b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp @@ -21,6 +21,7 @@ #include #include +#include "IReactDispatcher.h" #include "Modules/AppStateData.h" #include "Modules/ClipboardModule.h" #include "Modules/DevSettingsModule.h" @@ -154,7 +155,7 @@ void ReactInstanceWin::Initialize() noexcept { InitUIManager(); Mso::PostFuture( - Mso::DispatchQueue::MainUIQueue(), + m_uiQueue, [weakThis = Mso::WeakPtr{this}]() noexcept { // Objects that must be created on the UI thread if (auto strongThis = weakThis.GetStrongPtr()) { @@ -163,7 +164,8 @@ void ReactInstanceWin::Initialize() noexcept { strongThis->m_appTheme = std::make_shared(legacyInstance, strongThis->m_uiMessageThread.LoadWithLock()); react::uwp::I18nHelper().Instance().setInfo(react::uwp::I18nModule::GetI18nInfo()); - strongThis->m_appearanceListener = Mso::Make(legacyInstance); + strongThis->m_appearanceListener = + Mso::Make(legacyInstance, strongThis->m_uiQueue); } }) .Then(Queue(), [ this, weakThis = Mso::WeakPtr{this} ]() noexcept { @@ -199,7 +201,7 @@ void ReactInstanceWin::Initialize() noexcept { devSettings->debuggerConsoleRedirection = false; // JSHost::ChangeGate::ChakraCoreDebuggerConsoleRedirection(); - m_appState = std::make_shared(*m_reactContext); + m_appState = std::make_shared(*m_reactContext, m_uiQueue); // Acquire default modules and then populate with custom modules std::vector cxxModules = react::uwp::GetCoreModules( @@ -457,8 +459,9 @@ void ReactInstanceWin::InitNativeMessageThread() noexcept { void ReactInstanceWin::InitUIMessageThread() noexcept { // Native queue was already given us in constructor. - m_uiMessageThread.Exchange(std::make_shared( - Mso::DispatchQueue::MainUIQueue(), Mso::MakeWeakMemberFunctor(this, &ReactInstanceWin::OnError))); + m_uiQueue = winrt::Microsoft::ReactNative::ReactDispatcher::GetUIDispatchQueue(m_options.Properties); + m_uiMessageThread.Exchange( + std::make_shared(m_uiQueue, Mso::MakeWeakMemberFunctor(this, &ReactInstanceWin::OnError))); m_batchingUIThread = react::uwp::MakeBatchingQueueThread(m_uiMessageThread.Load()); } @@ -520,7 +523,7 @@ std::shared_ptr ReactInstanceWin::GetRedBoxHandler() noexcept { return m_options.RedBoxHandler; } else if (m_options.DeveloperSettings.IsDevModeEnabled) { auto localWkReactHost = m_weakReactHost; - return CreateDefaultRedBoxHandler(std::move(localWkReactHost)); + return CreateDefaultRedBoxHandler(std::move(localWkReactHost), Mso::Copy(m_uiQueue)); } else { return {}; } diff --git a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h index 7a90f7da41b..5f2957f8389 100644 --- a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +++ b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h @@ -161,6 +161,7 @@ class ReactInstanceWin final : public Mso::ActiveObject m_appTheme; Mso::CntPtr m_appearanceListener; std::string m_bundleRootPath; + Mso::DispatchQueue m_uiQueue; }; } // namespace Mso::React diff --git a/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl b/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl index f388e735f29..fff4532c2d4 100644 --- a/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl +++ b/vnext/Microsoft.ReactNative/ReactInstanceSettings.idl @@ -30,6 +30,6 @@ namespace Microsoft.ReactNative { String DebugBundlePath { get; set; }; String BundleRootPath { get; set; }; UInt16 DebuggerPort { get; set; }; - Microsoft.ReactNative.IRedBoxHandler RedBoxHandler { get; set; }; + IRedBoxHandler RedBoxHandler { get; set; }; } } diff --git a/vnext/Microsoft.ReactNative/RedBox.cpp b/vnext/Microsoft.ReactNative/RedBox.cpp index 699454c743e..0491a64fc9a 100644 --- a/vnext/Microsoft.ReactNative/RedBox.cpp +++ b/vnext/Microsoft.ReactNative/RedBox.cpp @@ -358,19 +358,19 @@ struct RedBox : public std::enable_shared_from_this { * This class is implemented such that the methods on IRedBoxHandler are thread safe. */ struct DefaultRedBoxHandler : public std::enable_shared_from_this, IRedBoxHandler { - DefaultRedBoxHandler(Mso::WeakPtr &&weakReactHost) noexcept - : m_weakReactHost(std::move(weakReactHost)) {} + DefaultRedBoxHandler(Mso::WeakPtr &&weakReactHost, Mso::DispatchQueue &&uiQueue) noexcept + : m_weakReactHost{std::move(weakReactHost)}, m_uiQueue{std::move(uiQueue)} {} ~DefaultRedBoxHandler() { - // Hide any currently showing redboxes - std::vector> redboxes; + // Hide any currently showing redBoxes + std::vector> redBoxes; { std::scoped_lock lock{m_lockRedBox}; - std::swap(m_redboxes, redboxes); + std::swap(m_redBoxes, redBoxes); } - Mso::DispatchQueue::MainUIQueue().Post([redboxes = std::move(redboxes)]() { - for (const auto redbox : redboxes) { - redbox->Dismiss(); + m_uiQueue.Post([redBoxes = std::move(redBoxes)]() { + for (const auto redBox : redBoxes) { + redBox->Dismiss(); } }); } @@ -386,7 +386,7 @@ struct DefaultRedBoxHandler : public std::enable_shared_from_this redbox; { std::scoped_lock lock{m_lockRedBox}; - for (auto it = m_redboxes.begin(); it != m_redboxes.end(); ++it) { + for (auto it = m_redBoxes.begin(); it != m_redBoxes.end(); ++it) { if ((*it)->GetId() == info.Id) { redbox = *it; break; } } } + if (redbox) { - Mso::DispatchQueue::MainUIQueue().Post([redboxCaptured = std::move(redbox), errorInfo = std::move(info)]() { + m_uiQueue.Post([redboxCaptured = std::move(redbox), errorInfo = std::move(info)]() { redboxCaptured->UpdateError(std::move(errorInfo)); }); } } virtual void dismissRedbox() override { - Mso::DispatchQueue::MainUIQueue().Post([wkthis = std::weak_ptr(shared_from_this())]() { + m_uiQueue.Post([wkthis = std::weak_ptr(shared_from_this())]() { if (auto pthis = wkthis.lock()) { std::scoped_lock lock{pthis->m_lockRedBox}; - if (!pthis->m_redboxes.empty()) - pthis->m_redboxes[0]->Dismiss(); + if (!pthis->m_redBoxes.empty()) + pthis->m_redBoxes[0]->Dismiss(); } }); } private: - // When notified by a redbox that its been dismisssed + // When notified by a redbox that its been dismissed void onDismissedCallback(uint32_t id) noexcept { // Save a local ref, so if we are removing the last redbox which could hold the last ref to the DefaultRedBoxHandler // We ensure that we exit the mutex before the handler is destroyed. @@ -436,10 +437,10 @@ struct DefaultRedBoxHandler : public std::enable_shared_from_thisGetId() == id) { redbox = *it; - it = m_redboxes.erase(it); + it = m_redBoxes.erase(it); break; } } @@ -453,8 +454,8 @@ struct DefaultRedBoxHandler : public std::enable_shared_from_this redbox; { std::scoped_lock lock{m_lockRedBox}; - if (!m_redboxes.empty()) { - redbox = m_redboxes[0]; + if (!m_redBoxes.empty()) { + redbox = m_redBoxes[0]; } } @@ -462,13 +463,14 @@ struct DefaultRedBoxHandler : public std::enable_shared_from_thisShowNewJSError(); }); + m_uiQueue.Post([redboxCaptured = std::move(redbox)]() { redboxCaptured->ShowNewJSError(); }); } - bool m_showingRedBox = false; // Access from UI Thread only + private: + const Mso::DispatchQueue m_uiQueue; + bool m_showingRedBox{false}; // Access from UI Thread only std::mutex m_lockRedBox; - std::vector> m_redboxes; // Protected by m_lockRedBox + std::vector> m_redBoxes; // Protected by m_lockRedBox const Mso::WeakPtr m_weakReactHost; }; @@ -564,8 +566,10 @@ std::shared_ptr CreateRedBoxHandler( return std::make_shared(redBoxHandler); } -std::shared_ptr CreateDefaultRedBoxHandler(Mso::WeakPtr &&weakReactHost) noexcept { - return std::make_shared(std::move(weakReactHost)); +std::shared_ptr CreateDefaultRedBoxHandler( + Mso::WeakPtr &&weakReactHost, + Mso::DispatchQueue &&uiQueue) noexcept { + return std::make_shared(std::move(weakReactHost), std::move(uiQueue)); } } // namespace Mso::React diff --git a/vnext/Microsoft.ReactNative/RedBox.h b/vnext/Microsoft.ReactNative/RedBox.h index 0a14590aaea..8d0672a2a54 100644 --- a/vnext/Microsoft.ReactNative/RedBox.h +++ b/vnext/Microsoft.ReactNative/RedBox.h @@ -10,6 +10,8 @@ namespace Mso::React { std::shared_ptr CreateRedBoxHandler( winrt::Microsoft::ReactNative::IRedBoxHandler const &redBoxHandler) noexcept; -std::shared_ptr CreateDefaultRedBoxHandler(Mso::WeakPtr &&weakReactHost) noexcept; +std::shared_ptr CreateDefaultRedBoxHandler( + Mso::WeakPtr &&weakReactHost, + Mso::DispatchQueue &&uiQueue) noexcept; } // namespace Mso::React diff --git a/vnext/Microsoft.ReactNative/RedBoxHandler.cpp b/vnext/Microsoft.ReactNative/RedBoxHandler.cpp index 945bece5241..a368c5bb21f 100644 --- a/vnext/Microsoft.ReactNative/RedBoxHandler.cpp +++ b/vnext/Microsoft.ReactNative/RedBoxHandler.cpp @@ -7,6 +7,7 @@ #include "RedBoxHelper.g.cpp" #endif +#include #include #include #include @@ -32,7 +33,8 @@ struct DefaultRedBoxHandler : winrt::implements(host); Mso::WeakPtr wkHost(hostImpl->ReactHost()); - m_redBoxHandler = Mso::React::CreateDefaultRedBoxHandler(std::move(wkHost)); + m_redBoxHandler = Mso::React::CreateDefaultRedBoxHandler( + std::move(wkHost), ReactDispatcher::GetUIDispatchQueue(host.InstanceSettings().Properties())); } void ShowNewError(IRedBoxErrorInfo const &info, RedBoxErrorType type) noexcept { diff --git a/vnext/Microsoft.ReactNative/Threading/MessageQueueThreadFactory.cpp b/vnext/Microsoft.ReactNative/Threading/MessageQueueThreadFactory.cpp index cae018a7568..1dfd9e4f3c5 100644 --- a/vnext/Microsoft.ReactNative/Threading/MessageQueueThreadFactory.cpp +++ b/vnext/Microsoft.ReactNative/Threading/MessageQueueThreadFactory.cpp @@ -12,7 +12,8 @@ std::shared_ptr MakeJSQueueThread() noexcep } std::shared_ptr MakeUIQueueThread() noexcept { - return std::make_shared(Mso::DispatchQueue::MainUIQueue(), nullptr, nullptr); + return std::make_shared( + Mso::DispatchQueue::MakeCurrentThreadUIQueue(), nullptr, nullptr); } std::shared_ptr MakeSerialQueueThread() noexcept { diff --git a/vnext/Mso/dispatchQueue/dispatchQueue.h b/vnext/Mso/dispatchQueue/dispatchQueue.h index a7c1c0a4a20..50e2ecbe1e0 100644 --- a/vnext/Mso/dispatchQueue/dispatchQueue.h +++ b/vnext/Mso/dispatchQueue/dispatchQueue.h @@ -113,9 +113,6 @@ struct DispatchQueue { //! demand. static DispatchQueue const &ConcurrentQueue() noexcept; - //! Get DispatchQueue associated with the main UI thread. It is created on demand. - static DispatchQueue const &MainUIQueue() noexcept; - //! Create new serial DispatchQueue on top of platform specific thread pool. static DispatchQueue MakeSerialQueue() noexcept; @@ -158,8 +155,7 @@ struct DispatchQueue { //! True if tasks are invoked in a serial order by the queue. bool IsSerial() const noexcept; - //! True if queue is running on current thread or associated with it. E.g. MainUIQueue always returns true for the - //! main UI thread. + //! True if queue is running on current thread or associated with it. bool HasThreadAccess() const noexcept; //! Check if a long running task should yield. @@ -416,9 +412,6 @@ struct IDispatchQueueStatic : IUnknown { //! demand. virtual DispatchQueue const &ConcurrentQueue() noexcept = 0; - //! Get DispatchQueue associated with the main UI thread. It is created on demand. - virtual DispatchQueue const &MainUIQueue() noexcept = 0; - //! Create new serial DispatchQueue on top of platform specific thread pool. virtual DispatchQueue MakeSerialQueue() noexcept = 0; @@ -545,10 +538,6 @@ inline /*static*/ DispatchQueue const &DispatchQueue::ConcurrentQueue() noexcept return IDispatchQueueStatic::Instance()->ConcurrentQueue(); } -inline /*static*/ DispatchQueue const &DispatchQueue::MainUIQueue() noexcept { - return IDispatchQueueStatic::Instance()->MainUIQueue(); -} - inline /*static*/ DispatchQueue DispatchQueue::MakeSerialQueue() noexcept { return IDispatchQueueStatic::Instance()->MakeSerialQueue(); } diff --git a/vnext/Mso/src/dispatchQueue/queueService.cpp b/vnext/Mso/src/dispatchQueue/queueService.cpp index b560a732173..d30f444bdc0 100644 --- a/vnext/Mso/src/dispatchQueue/queueService.cpp +++ b/vnext/Mso/src/dispatchQueue/queueService.cpp @@ -269,11 +269,6 @@ DispatchQueue const &DispatchQueueStatic::ConcurrentQueue() noexcept { return *static_cast(static_cast(&concurrentQueue)); } -DispatchQueue const &DispatchQueueStatic::MainUIQueue() noexcept { - static auto mainUIQueue{Mso::Make(MakeMainUIScheduler())}; - return *static_cast(static_cast(&mainUIQueue)); -} - DispatchQueue DispatchQueueStatic::MakeSerialQueue() noexcept { return Mso::Make(MakeThreadPoolScheduler(/*maxThreads:*/ 1)); } diff --git a/vnext/Mso/src/dispatchQueue/queueService.h b/vnext/Mso/src/dispatchQueue/queueService.h index 0d1b30a9734..a80f72a669b 100644 --- a/vnext/Mso/src/dispatchQueue/queueService.h +++ b/vnext/Mso/src/dispatchQueue/queueService.h @@ -82,14 +82,12 @@ struct QueueLocalValueEntry { struct DispatchQueueStatic : Mso::UnknownObject { static DispatchQueueStatic *Instance() noexcept; static Mso::CntPtr MakeLooperScheduler() noexcept; - static Mso::CntPtr MakeMainUIScheduler() noexcept; static Mso::CntPtr MakeCurrentThreadUIScheduler() noexcept; static Mso::CntPtr MakeThreadPoolScheduler(uint32_t maxThreads) noexcept; public: // IDispatchQueueStatic DispatchQueue CurrentQueue() noexcept override; DispatchQueue const &ConcurrentQueue() noexcept override; - DispatchQueue const &MainUIQueue() noexcept override; DispatchQueue MakeSerialQueue() noexcept override; DispatchQueue MakeLooperQueue() noexcept override; DispatchQueue MakeCurrentThreadUIQueue() noexcept override; diff --git a/vnext/Mso/src/dispatchQueue/uiScheduler_winrt.cpp b/vnext/Mso/src/dispatchQueue/uiScheduler_winrt.cpp index 1753023d3a1..70981a780a1 100644 --- a/vnext/Mso/src/dispatchQueue/uiScheduler_winrt.cpp +++ b/vnext/Mso/src/dispatchQueue/uiScheduler_winrt.cpp @@ -5,38 +5,36 @@ #include "object/refCountedObject.h" #include "queueService.h" #include "taskQueue.h" -#include "winrt/Windows.ApplicationModel.Core.h" -#include "winrt/Windows.UI.Core.h" +#include "winrt/Windows.System.h" using namespace winrt; -using namespace Windows::ApplicationModel::Core; -using namespace Windows::UI::Core; +using namespace Windows::System; namespace Mso { -struct UISchdulerWinRT; +struct UISchedulerWinRT; -//! TaskDispatchedHandler is a DispatchedHandler delegate that we pass to CoreDispatcher. +//! TaskDispatcherHandler is a DispatcherQueueHandler delegate that we pass to DispatcherQueue. //! We use custom ref counting to avoid extra memory allocations and to handle reference to DispatchTask. -struct TaskDispatchedHandler final : impl::abi_t { - TaskDispatchedHandler(UISchdulerWinRT *scheduler) noexcept; +struct TaskDispatcherHandler final : impl::abi_t { + TaskDispatcherHandler(UISchedulerWinRT *scheduler) noexcept; int32_t __stdcall QueryInterface(guid const &id, void **result) noexcept final; uint32_t __stdcall AddRef() noexcept final; uint32_t __stdcall Release() noexcept final; int32_t __stdcall Invoke() noexcept final; private: - UISchdulerWinRT *m_scheduler; + UISchedulerWinRT *m_scheduler; }; -struct UISchdulerWinRT : Mso::UnknownObject { - UISchdulerWinRT(CoreDispatcher &&coreDispatcher) noexcept; - ~UISchdulerWinRT() noexcept override; +struct UISchedulerWinRT : Mso::UnknownObject { + UISchedulerWinRT(DispatcherQueue &&dispatcher) noexcept; + ~UISchedulerWinRT() noexcept override; uint32_t AddHandlerRef() noexcept; uint32_t ReleaseHandlerRef() noexcept; - DispatchedHandler MakeDispatchedHandler() noexcept; + DispatcherQueueHandler MakeDispatcherQueueHandler() noexcept; bool TryTakeTask(Mso::CntPtr &queue, DispatchTask &task) noexcept; public: // IDispatchQueueScheduler @@ -49,39 +47,40 @@ struct UISchdulerWinRT : Mso::UnknownObject m_queue; - Mso::CntPtr m_self; + Mso::CntPtr m_self; uint32_t m_handlerRefCount{0}; uint32_t m_taskCount{0}; bool m_isShutdown{false}; + std::thread::id m_threadId{std::this_thread::get_id()}; }; //============================================================================= -// TaskDispatchedHandler implementation +// TaskDispatcherHandler implementation //============================================================================= -TaskDispatchedHandler::TaskDispatchedHandler(UISchdulerWinRT *scheduler) noexcept : m_scheduler{scheduler} {} +TaskDispatcherHandler::TaskDispatcherHandler(UISchedulerWinRT *scheduler) noexcept : m_scheduler{scheduler} {} -int32_t __stdcall TaskDispatchedHandler::QueryInterface(guid const &id, void **result) noexcept { - if (is_guid_of(id) || is_guid_of(id) || +int32_t __stdcall TaskDispatcherHandler::QueryInterface(guid const &id, void **result) noexcept { + if (is_guid_of(id) || is_guid_of(id) || is_guid_of(id)) { - *result = static_cast *>(this); + *result = static_cast *>(this); AddRef(); return impl::error_ok; } @@ -94,15 +93,15 @@ int32_t __stdcall TaskDispatchedHandler::QueryInterface(guid const &id, void **r return impl::error_no_interface; } -uint32_t __stdcall TaskDispatchedHandler::AddRef() noexcept { +uint32_t __stdcall TaskDispatcherHandler::AddRef() noexcept { return m_scheduler->AddHandlerRef(); } -uint32_t __stdcall TaskDispatchedHandler::Release() noexcept { +uint32_t __stdcall TaskDispatcherHandler::Release() noexcept { return m_scheduler->ReleaseHandlerRef(); } -int32_t __stdcall TaskDispatchedHandler::Invoke() noexcept { +int32_t __stdcall TaskDispatcherHandler::Invoke() noexcept { Mso::CntPtr queue; DispatchTask task; if (m_scheduler->TryTakeTask(queue, task)) { @@ -113,23 +112,22 @@ int32_t __stdcall TaskDispatchedHandler::Invoke() noexcept { } //============================================================================= -// UISchdulerWinRT implementation +// UISchedulerWinRT implementation //============================================================================= -UISchdulerWinRT::UISchdulerWinRT(CoreDispatcher &&coreDispatcher) noexcept - : m_coreDispatcher{std::move(coreDispatcher)} {} +UISchedulerWinRT::UISchedulerWinRT(DispatcherQueue &&dispatcher) noexcept : m_dispatcher{std::move(dispatcher)} {} -UISchdulerWinRT::~UISchdulerWinRT() noexcept { +UISchedulerWinRT::~UISchedulerWinRT() noexcept { AwaitTermination(); } -uint32_t UISchdulerWinRT::AddHandlerRef() noexcept { +uint32_t UISchedulerWinRT::AddHandlerRef() noexcept { std::lock_guard lock{m_mutex}; return ++m_handlerRefCount; } -uint32_t UISchdulerWinRT::ReleaseHandlerRef() noexcept { - Mso::CntPtr self; +uint32_t UISchedulerWinRT::ReleaseHandlerRef() noexcept { + Mso::CntPtr self; CleanupContext context{this}; { @@ -147,7 +145,7 @@ uint32_t UISchdulerWinRT::ReleaseHandlerRef() noexcept { } } -bool UISchdulerWinRT::TryTakeTask(Mso::CntPtr &queue, DispatchTask &task) noexcept { +bool UISchedulerWinRT::TryTakeTask(Mso::CntPtr &queue, DispatchTask &task) noexcept { { std::lock_guard lock{m_mutex}; VerifyElseCrashSz(m_taskCount, "Task count cannot be negative"); @@ -161,45 +159,47 @@ bool UISchdulerWinRT::TryTakeTask(Mso::CntPtr &queue, Dis return false; } -DispatchedHandler UISchdulerWinRT::MakeDispatchedHandler() noexcept { +DispatcherQueueHandler UISchedulerWinRT::MakeDispatcherQueueHandler() noexcept { VerifyElseCrash(m_mutex.IsLockedByMe()); if (m_handlerRefCount == 0) { - m_self = this; // Keep reference to self while CoreDispatcher owns DispatchedHandler. + m_self = this; // Keep reference to self while DispatcherQueue owns DispatcherQueueHandler. } ++m_handlerRefCount; - return {static_cast(&m_dispatchedHandler), take_ownership_from_abi}; + return {static_cast(&m_dispatcherHandler), take_ownership_from_abi}; } -void UISchdulerWinRT::IntializeScheduler(Mso::WeakPtr &&queue) noexcept { +void UISchedulerWinRT::IntializeScheduler(Mso::WeakPtr &&queue) noexcept { m_queue = std::move(queue); } -bool UISchdulerWinRT::HasThreadAccess() noexcept { - return m_coreDispatcher.HasThreadAccess(); +bool UISchedulerWinRT::HasThreadAccess() noexcept { + // m_dispatcher.HasThreadAccess() is implemented only in Windows 19H1. + // We must use an alternative implementation. + return m_threadId == std::this_thread::get_id(); } -bool UISchdulerWinRT::IsSerial() noexcept { +bool UISchedulerWinRT::IsSerial() noexcept { return true; } -void UISchdulerWinRT::Post() noexcept { - DispatchedHandler handler; +void UISchedulerWinRT::Post() noexcept { + DispatcherQueueHandler handler; { std::lock_guard lock{m_mutex}; if (!m_isShutdown) { ++m_taskCount; - handler = MakeDispatchedHandler(); + handler = MakeDispatcherQueueHandler(); } } if (handler) { - m_coreDispatcher.RunAsync(CoreDispatcherPriority::Normal, std::move(handler)); + m_dispatcher.TryEnqueue(handler); } } -void UISchdulerWinRT::Shutdown() noexcept { +void UISchedulerWinRT::Shutdown() noexcept { CleanupContext context{this}; { std::lock_guard lock{m_mutex}; @@ -208,18 +208,18 @@ void UISchdulerWinRT::Shutdown() noexcept { } } -void UISchdulerWinRT::AwaitTermination() noexcept { +void UISchedulerWinRT::AwaitTermination() noexcept { Shutdown(); m_terminationEvent.Wait(); } //============================================================================= -// UISchdulerWinRT::CleanupContext implementation +// UISchedulerWinRT::CleanupContext implementation //============================================================================= -UISchdulerWinRT::CleanupContext::CleanupContext(UISchdulerWinRT *scheduler) noexcept : m_scheduler{scheduler} {} +UISchedulerWinRT::CleanupContext::CleanupContext(UISchedulerWinRT *scheduler) noexcept : m_scheduler{scheduler} {} -UISchdulerWinRT::CleanupContext::~CleanupContext() noexcept { +UISchedulerWinRT::CleanupContext::~CleanupContext() noexcept { if (m_isTerminated) { m_scheduler->m_terminationEvent.Set(); } @@ -231,8 +231,8 @@ UISchdulerWinRT::CleanupContext::~CleanupContext() noexcept { } } -void UISchdulerWinRT::CleanupContext::CheckShutdown() noexcept { - // See if core dispatcher released all handlers without invoking them. +void UISchedulerWinRT::CleanupContext::CheckShutdown() noexcept { + // See if dispatcher queue released all handlers without invoking them. if (m_scheduler->m_taskCount != 0 && m_scheduler->m_handlerRefCount == 0) { m_isShutdown = true; m_scheduler->m_taskCount = 0; @@ -240,20 +240,16 @@ void UISchdulerWinRT::CleanupContext::CheckShutdown() noexcept { } } -void UISchdulerWinRT::CleanupContext::CheckTermination() noexcept { +void UISchedulerWinRT::CleanupContext::CheckTermination() noexcept { m_isTerminated = m_scheduler->m_isShutdown && (m_scheduler->m_handlerRefCount == 0); } //============================================================================= -// DispatchQueueStatic::MakeThreadPoolScheduler implementation +// DispatchQueueStatic::MakeCurrentThreadUIScheduler implementation //============================================================================= -/*static*/ Mso::CntPtr DispatchQueueStatic::MakeMainUIScheduler() noexcept { - return Mso::Make(CoreApplication::MainView().CoreWindow().Dispatcher()); -} - /*static*/ Mso::CntPtr DispatchQueueStatic::MakeCurrentThreadUIScheduler() noexcept { - return Mso::Make(CoreWindow::GetForCurrentThread().Dispatcher()); + return Mso::Make(DispatcherQueue::GetForCurrentThread()); } } // namespace Mso diff --git a/vnext/ReactUWP/Base/UwpReactInstance.cpp b/vnext/ReactUWP/Base/UwpReactInstance.cpp index ce74a02918b..3f447c313b0 100644 --- a/vnext/ReactUWP/Base/UwpReactInstance.cpp +++ b/vnext/ReactUWP/Base/UwpReactInstance.cpp @@ -115,7 +115,7 @@ void UwpReactInstance::Start(const std::shared_ptr &spThis, cons std::shared_ptr appTheme = std::make_shared(spThis, m_defaultNativeThread); I18nHelper::Instance().setInfo(I18nModule::GetI18nInfo()); - auto appearanceListener = Mso::Make(spThis); + auto appearanceListener = Mso::Make(spThis, Mso::DispatchQueue::MakeCurrentThreadUIQueue()); // TODO: Figure out threading. What thread should this really be on? m_initThread = std::make_unique(); diff --git a/vnext/ReactUWP/Modules/AppearanceModule.cpp b/vnext/ReactUWP/Modules/AppearanceModule.cpp index 8f4bba5fa6e..0405de975a2 100644 --- a/vnext/ReactUWP/Modules/AppearanceModule.cpp +++ b/vnext/ReactUWP/Modules/AppearanceModule.cpp @@ -14,10 +14,12 @@ using Method = facebook::xplat::module::CxxModule::Method; namespace react::uwp { -AppearanceChangeListener::AppearanceChangeListener(std::weak_ptr &&reactInstance) noexcept - : Mso::ActiveObject<>(Mso::DispatchQueue::MainUIQueue()), m_weakReactInstance(std::move(reactInstance)) { +AppearanceChangeListener::AppearanceChangeListener( + std::weak_ptr &&reactInstance, + Mso::DispatchQueue const &uiQueue) noexcept + : Mso::ActiveObject<>(uiQueue), m_weakReactInstance(std::move(reactInstance)) { // Ensure we're constructed on the UI thread - VerifyIsInQueueElseCrash(); + VerifyElseCrash(uiQueue.HasThreadAccess()); m_currentTheme = Application::Current().RequestedTheme(); diff --git a/vnext/ReactUWP/Modules/AppearanceModule.h b/vnext/ReactUWP/Modules/AppearanceModule.h index 275c36a3819..1e3b7c6268e 100644 --- a/vnext/ReactUWP/Modules/AppearanceModule.h +++ b/vnext/ReactUWP/Modules/AppearanceModule.h @@ -17,7 +17,7 @@ class AppearanceChangeListener final : public Mso::ActiveObject<> { using UISettings = winrt::Windows::UI::ViewManagement::UISettings; public: - AppearanceChangeListener(std::weak_ptr &&reactInstance) noexcept; + AppearanceChangeListener(std::weak_ptr &&reactInstance, Mso::DispatchQueue const &uiQueue) noexcept; const char *GetColorScheme() const noexcept; private: diff --git a/vnext/ReactUWP/ReactUWP.vcxproj.filters b/vnext/ReactUWP/ReactUWP.vcxproj.filters index 30f2d7c7f54..cc8de5168af 100644 --- a/vnext/ReactUWP/ReactUWP.vcxproj.filters +++ b/vnext/ReactUWP/ReactUWP.vcxproj.filters @@ -106,6 +106,9 @@ Modules\Animated + + Modules + Modules @@ -166,6 +169,7 @@ Polyester + Threading @@ -322,8 +326,6 @@ Views - - @@ -482,6 +484,9 @@ Modules\Animated + + Modules + Modules @@ -657,7 +662,6 @@ Views - From 64aede7aedb329e97df0f6d4f8c946e6454b573c Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Wed, 13 May 2020 12:24:24 -0700 Subject: [PATCH 091/209] RNW dependencies (#4876) * add rnw-dependencies.ps1 * Change files * --sln * run in CI * print * desktop appium is optional * use agent directory * 15GB is a ballpark estimate * optional space * . --- .ado/windows-vs-pr.yml | 7 + ...-2020-05-11-17-22-16-rnw-dependencies.json | 8 + docs/building-rnw.md | 4 +- vnext/Scripts/rnw-dependencies.ps1 | 147 ++++++++++++++++++ 4 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 change/react-native-windows-2020-05-11-17-22-16-rnw-dependencies.json create mode 100644 vnext/Scripts/rnw-dependencies.ps1 diff --git a/.ado/windows-vs-pr.yml b/.ado/windows-vs-pr.yml index 3a9f922b1bd..5bdccb68324 100644 --- a/.ado/windows-vs-pr.yml +++ b/.ado/windows-vs-pr.yml @@ -65,6 +65,13 @@ jobs: clean: false submodules: false + - task: PowerShell@2 + displayName: "Check if this environment meets the development dependencies" + inputs: + targetType: filePath + filePath: $(Build.SourcesDirectory)\vnext\Scripts\rnw-dependencies.ps1 + arguments: -NoPrompt + - template: templates/build-rnw.yml parameters: yarnBuildCmd: build diff --git a/change/react-native-windows-2020-05-11-17-22-16-rnw-dependencies.json b/change/react-native-windows-2020-05-11-17-22-16-rnw-dependencies.json new file mode 100644 index 00000000000..c4d7af43b9f --- /dev/null +++ b/change/react-native-windows-2020-05-11-17-22-16-rnw-dependencies.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "add rnw-dependencies.ps1", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-12T00:22:16.000Z" +} diff --git a/docs/building-rnw.md b/docs/building-rnw.md index 3dd61b188ae..7b09e5cbbbf 100644 --- a/docs/building-rnw.md +++ b/docs/building-rnw.md @@ -22,7 +22,7 @@ Note that react-native-windows is a monorepo and relies on monorepo tools like y There are two ways to run the app. In a fully managed easy way, or by manually running all the required steps: ## Automatic -The playground app can be run in a completely automatic way by using `react-native run-windows`. +The playground app can be run in a completely automatic way by using `react-native run-windows --sln windows\playground.sln`. If you haven't already, install the react-native-cli (One time only!) ```cmd @@ -33,7 +33,7 @@ Then ```cmd cd packages\playground -react-native run-windows +react-native run-windows --sln windows\playground.sln ``` ## Manual diff --git a/vnext/Scripts/rnw-dependencies.ps1 b/vnext/Scripts/rnw-dependencies.ps1 new file mode 100644 index 00000000000..ab27b0519ff --- /dev/null +++ b/vnext/Scripts/rnw-dependencies.ps1 @@ -0,0 +1,147 @@ +# Troubleshoot RNW dependencies +param([switch]$Install = $false, [switch]$NoPrompt = $false) +$vsWorkloads = @( 'Microsoft.Component.MSBuild', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', 'Microsoft.VisualStudio.ComponentGroup.UWP.Support'); + +$v = [System.Environment]::OSVersion.Version; +if ($env:Agent_BuildDirectory) { + $drive = (Resolve-Path $env:Agent_BuildDirectory).Drive +} else { + $drive = (Resolve-Path $PSCommandPath).Drive +} + +function CheckVS { + $vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + if (!(Test-Path $vsWhere)) { + return $false; + } + $output = & $vsWhere -version 16 -requires $vsWorkloads -property productPath + return Test-Path $output; +} + +function InstallVS { + $installerPath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer"; + $vsWhere = "$installerPath\vswhere.exe" + if (!(Test-Path $vsWhere)) { + # No VSWhere / VS_Installer + & choco install -y visualstudio2019community + } + $channelId = & $vsWhere -version 16 -property channelId + $productId = & $vsWhere -version 16 -property productId + $vsInstaller = "$installerPath\vs_installer.exe" + $addWorkloads = $vsWorkloads | % { '--add', $_ }; + Start-Process -PassThru -Wait -Path $vsInstaller -ArgumentList ("install --channelId $channelId --productId $productId $addWorkloads --quiet" -split ' ') + +} + +function CheckNode { + try { + $v = (Get-Command node).Version.Major + return $v -eq 12 -or $v -eq 13 + } catch { + return $false; + } +} + +function GetChocoPkgVersion{ + params([string]$packageId) + [version]$version = (& choco list --local-only $packageId -r -e).Substring($packageId.Length + 1); + return $version; +} + +$requiredFreeSpaceGB = 15; + +$requirements = @( + @{ + Name = "Free space on $drive`: > $requiredFreeSpaceGB GB"; + Valid = $drive.Free/1GB -gt $requiredFreeSpaceGB; + Optional = $true # this requirement is fuzzy + }, + @{ + Name = 'Windows version > 10.0.16299.0'; + Valid = ($v.Major -eq 10 -and $v.Minor -eq 0 -and $v.Build -ge 16299) + }, + @{ + Name = 'Developer mode is on'; + Valid = try { (Get-WindowsDeveloperLicense).IsValid } catch { $false } + }, + @{ + Name = 'git'; + Valid = try { (Get-Command git.exe) -ne $null } catch { $false } + } + @{ + Name = 'Choco'; + Valid = try { (Get-Command choco) -ne $null } catch { $false }; + Install = { + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; + iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) + }; + }, + @{ + Name = 'VS 2019 with UWP and Desktop/C++'; + Valid = CheckVS + }, + @{ + Name = 'NodeJS 12 or 13 installed'; + Valid = CheckNode + Install = { choco install -y nodejs.install --version=12.9.1 } + }, + @{ + Name = 'Chrome'; + Valid = try { ((Get-Item (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe').'(Default)').VersionInfo).ProductMajorPart + } catch { $false } ; + Install = { choco install -y GoogleChrome } + }, + @{ + Name = 'Yarn'; + Valid = try { (Get-Command yarn) -ne $null } catch { $false }; + Install = { choco install -y yarn } + }, + @{ + Name = 'Appium'; + Valid = (Test-Path "${env:ProgramFiles}\Appium\Appium.exe"); + Install = { choco install -y Appium-desktop }; + Optional = $true + }, + @{ + Name = 'WinAppDriver'; + Valid = (Test-Path "${env:ProgramFiles(x86)}\Windows Application Driver\WinAppDriver.exe"); + Install = { choco install -y WinAppDriver }; + } + + ); + +function IsElevated { + return [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544"); +} + +if (!(IsElevated)) { + Write-Output "rnw-dependencies - this script must run elevated. Exiting."; + return; +} + +$NeedsRerun = $false +foreach ($req in $requirements) +{ + Write-Output "Checking $($req.Name)"; + if (!($req.Valid)) { + Write-Output "Requirement failed: $($req.Name)"; + if ($req.Install) { + if ($Install -or (!$NoPrompt -and (Read-Host "Do you want to install? ").ToUpperInvariant() -eq 'Y')) { + Invoke-Command $req.Install -ErrorAction Stop + if ($LASTEXITCODE -ne 0) { throw "Last exit code was non-zero: $LASTEXITCODE"; } + } elseif (!$req.Optional) { + $NeedsRerun = $true; + } + } else { + $NeedsRerun = !($req.Optional); + } + } +} + +if ($NeedsRerun) { + Write-Output "Some dependencies are not met. Re-run with -Install to install them."; + exit 1; +} else { + Write-Output "All mandatory requirements met"; + exit 0; +} From c27b5854a1f0d8e84f31d55284bc3f6b9347cefc Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Wed, 13 May 2020 13:00:52 -0700 Subject: [PATCH 092/209] support running from web (#4892) --- vnext/Scripts/rnw-dependencies.ps1 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/vnext/Scripts/rnw-dependencies.ps1 b/vnext/Scripts/rnw-dependencies.ps1 index ab27b0519ff..d91ee41d40d 100644 --- a/vnext/Scripts/rnw-dependencies.ps1 +++ b/vnext/Scripts/rnw-dependencies.ps1 @@ -6,7 +6,11 @@ $v = [System.Environment]::OSVersion.Version; if ($env:Agent_BuildDirectory) { $drive = (Resolve-Path $env:Agent_BuildDirectory).Drive } else { - $drive = (Resolve-Path $PSCommandPath).Drive + if ($PSCommandPath) { + $drive = (Resolve-Path $PSCommandPath).Drive + } else { + $drive = (Resolve-Path $env:SystemDrive).Drive + } } function CheckVS { @@ -122,9 +126,9 @@ if (!(IsElevated)) { $NeedsRerun = $false foreach ($req in $requirements) { - Write-Output "Checking $($req.Name)"; + Write-Host -NoNewline "Checking $($req.Name) "; if (!($req.Valid)) { - Write-Output "Requirement failed: $($req.Name)"; + Write-Host -ForegroundColor Red " Failed"; if ($req.Install) { if ($Install -or (!$NoPrompt -and (Read-Host "Do you want to install? ").ToUpperInvariant() -eq 'Y')) { Invoke-Command $req.Install -ErrorAction Stop @@ -135,6 +139,8 @@ foreach ($req in $requirements) } else { $NeedsRerun = !($req.Optional); } + } else { + Write-Host -ForegroundColor Green " OK"; } } From 5c024c0a5a204628c108ab6be7575333cbcda47a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 13 May 2020 21:29:43 +0000 Subject: [PATCH 093/209] Bump typescript from 3.8.3 to 3.9.2 (#4890) --- yarn.lock | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5c28f727177..578a5f9233a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6307,9 +6307,9 @@ eslint-plugin-react-native@3.8.1: eslint-plugin-react-native-globals "^0.1.1" eslint-plugin-react@7.19.0, eslint-plugin-react@^7.14.1: - version "7.19.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz#6d08f9673628aa69c5559d33489e855d83551666" - integrity sha512-SPT8j72CGuAP+JFbT0sJHOB80TX/pu44gQ4vXH/cq+hQTiY2PuZ6IHkqXJV6x1b28GDdo1lbInjKUrrdUf0LOQ== + version "7.20.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.0.tgz#f98712f0a5e57dfd3e5542ef0604b8739cd47be3" + integrity sha512-rqe1abd0vxMjmbPngo4NaYxTcR3Y4Hrmc/jg4T+sYz63yqlmJRknpEQfmWY+eDWPuMmix6iUIK+mv0zExjeLgA== dependencies: array-includes "^3.1.1" doctrine "^2.1.0" @@ -6320,7 +6320,6 @@ eslint-plugin-react@7.19.0, eslint-plugin-react@^7.14.1: object.values "^1.1.1" prop-types "^15.7.2" resolve "^1.15.1" - semver "^6.3.0" string.prototype.matchall "^4.0.2" xregexp "^4.3.0" @@ -13420,9 +13419,9 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= typescript@^3.5.3, typescript@^3.8.3: - version "3.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" - integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== + version "3.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.2.tgz#64e9c8e9be6ea583c54607677dd4680a1cf35db9" + integrity sha512-q2ktq4n/uLuNNShyayit+DTobV2ApPEo/6so68JaD5ojvc/6GClBipedB9zNWYxRSAlZXAe405Rlijzl6qDiSw== typescript@~3.7.2: version "3.7.2" From a8cd1704446f0626be620271b719b5e2be64fdd6 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 13 May 2020 21:29:58 +0000 Subject: [PATCH 094/209] Bump lerna from 3.20.2 to 3.21.0 (#4889) --- yarn.lock | 210 +++++++++++++++++++++++++++--------------------------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/yarn.lock b/yarn.lock index 578a5f9233a..6633ac2c3d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1722,14 +1722,14 @@ dependencies: core-js "^2.5.7" -"@lerna/add@3.20.0": - version "3.20.0" - resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.20.0.tgz#bea7edf36fc93fb72ec34cb9ba854c48d4abf309" - integrity sha512-AnH1oRIEEg/VDa3SjYq4x1/UglEAvrZuV0WssHUMN81RTZgQk3we+Mv3qZNddrZ/fBcZu2IAdN/EQ3+ie2JxKQ== +"@lerna/add@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.21.0.tgz#27007bde71cc7b0a2969ab3c2f0ae41578b4577b" + integrity sha512-vhUXXF6SpufBE1EkNEXwz1VLW03f177G9uMOFMQkp6OJ30/PWg4Ekifuz9/3YfgB2/GH8Tu4Lk3O51P2Hskg/A== dependencies: "@evocateur/pacote" "^9.6.3" - "@lerna/bootstrap" "3.20.0" - "@lerna/command" "3.18.5" + "@lerna/bootstrap" "3.21.0" + "@lerna/command" "3.21.0" "@lerna/filter-options" "3.20.0" "@lerna/npm-conf" "3.16.0" "@lerna/validation-error" "3.13.0" @@ -1738,12 +1738,12 @@ p-map "^2.1.0" semver "^6.2.0" -"@lerna/bootstrap@3.20.0": - version "3.20.0" - resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.20.0.tgz#635d71046830f208e851ab429a63da1747589e37" - integrity sha512-Wylullx3uthKE7r4izo09qeRGL20Y5yONlQEjPCfnbxCC2Elu+QcPu4RC6kqKQ7b+g7pdC3OOgcHZjngrwr5XQ== +"@lerna/bootstrap@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.21.0.tgz#bcd1b651be5b0970b20d8fae04c864548123aed6" + integrity sha512-mtNHlXpmvJn6JTu0KcuTTPl2jLsDNud0QacV/h++qsaKbhAaJr/FElNZ5s7MwZFUM3XaDmvWzHKaszeBMHIbBw== dependencies: - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/filter-options" "3.20.0" "@lerna/has-npm-version" "3.16.5" "@lerna/npm-install" "3.16.5" @@ -1767,13 +1767,13 @@ read-package-tree "^5.1.6" semver "^6.2.0" -"@lerna/changed@3.20.0": - version "3.20.0" - resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.20.0.tgz#66b97ebd6c8f8d207152ee524a0791846a9097ae" - integrity sha512-+hzMFSldbRPulZ0vbKk6RD9f36gaH3Osjx34wrrZ62VB4pKmjyuS/rxVYkCA3viPLHoiIw2F8zHM5BdYoDSbjw== +"@lerna/changed@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.21.0.tgz#108e15f679bfe077af500f58248c634f1044ea0b" + integrity sha512-hzqoyf8MSHVjZp0gfJ7G8jaz+++mgXYiNs9iViQGA8JlN/dnWLI5sWDptEH3/B30Izo+fdVz0S0s7ydVE3pWIw== dependencies: "@lerna/collect-updates" "3.20.0" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/listable" "3.18.5" "@lerna/output" "3.13.0" @@ -1795,12 +1795,12 @@ execa "^1.0.0" strong-log-transformer "^2.0.0" -"@lerna/clean@3.20.0": - version "3.20.0" - resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.20.0.tgz#ba777e373ddeae63e57860df75d47a9e5264c5b2" - integrity sha512-9ZdYrrjQvR5wNXmHfDsfjWjp0foOkCwKe3hrckTzkAeQA1ibyz5llGwz5e1AeFrV12e2/OLajVqYfe+qdkZUgg== +"@lerna/clean@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.21.0.tgz#c0b46b5300cc3dae2cda3bec14b803082da3856d" + integrity sha512-b/L9l+MDgE/7oGbrav6rG8RTQvRiZLO1zTcG17zgJAAuhlsPxJExMlh2DFwJEVi2les70vMhHfST3Ue1IMMjpg== dependencies: - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/filter-options" "3.20.0" "@lerna/prompt" "3.18.5" "@lerna/pulse-till-done" "3.13.0" @@ -1840,14 +1840,14 @@ npmlog "^4.1.2" slash "^2.0.0" -"@lerna/command@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.18.5.tgz#14c6d2454adbfd365f8027201523e6c289cd3cd9" - integrity sha512-36EnqR59yaTU4HrR1C9XDFti2jRx0BgpIUBeWn129LZZB8kAB3ov1/dJNa1KcNRKp91DncoKHLY99FZ6zTNpMQ== +"@lerna/command@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.21.0.tgz#9a2383759dc7b700dacfa8a22b2f3a6e190121f7" + integrity sha512-T2bu6R8R3KkH5YoCKdutKv123iUgUbW8efVjdGCDnCMthAQzoentOJfDeodBwn0P2OqCl3ohsiNVtSn9h78fyQ== dependencies: "@lerna/child-process" "3.16.5" "@lerna/package-graph" "3.18.5" - "@lerna/project" "3.18.0" + "@lerna/project" "3.21.0" "@lerna/validation-error" "3.13.0" "@lerna/write-log-file" "3.13.0" clone-deep "^4.0.1" @@ -1882,14 +1882,14 @@ fs-extra "^8.1.0" npmlog "^4.1.2" -"@lerna/create@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.18.5.tgz#11ac539f069248eaf7bc4c42e237784330f4fc47" - integrity sha512-cHpjocbpKmLopCuZFI7cKEM3E/QY8y+yC7VtZ4FQRSaLU8D8i2xXtXmYaP1GOlVNavji0iwoXjuNpnRMInIr2g== +"@lerna/create@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.21.0.tgz#e813832adf3488728b139e5a75c8b01b1372e62f" + integrity sha512-cRIopzKzE2vXJPmsiwCDMWo4Ct+KTmX3nvvkQLDoQNrrRK7w+3KQT3iiorbj1koD95RsVQA7mS2haWok9SIv0g== dependencies: "@evocateur/pacote" "^9.6.3" "@lerna/child-process" "3.16.5" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/npm-conf" "3.16.0" "@lerna/validation-error" "3.13.0" camelcase "^5.0.0" @@ -1914,23 +1914,23 @@ "@lerna/child-process" "3.16.5" npmlog "^4.1.2" -"@lerna/diff@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.18.5.tgz#e9e2cb882f84d5b84f0487c612137305f07accbc" - integrity sha512-u90lGs+B8DRA9Z/2xX4YaS3h9X6GbypmGV6ITzx9+1Ga12UWGTVlKaCXBgONMBjzJDzAQOK8qPTwLA57SeBLgA== +"@lerna/diff@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.21.0.tgz#e6df0d8b9916167ff5a49fcb02ac06424280a68d" + integrity sha512-5viTR33QV3S7O+bjruo1SaR40m7F2aUHJaDAC7fL9Ca6xji+aw1KFkpCtVlISS0G8vikUREGMJh+c/VMSc8Usw== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/validation-error" "3.13.0" npmlog "^4.1.2" -"@lerna/exec@3.20.0": - version "3.20.0" - resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.20.0.tgz#29f0c01aee2340eb46f90706731fef2062a49639" - integrity sha512-pS1mmC7kzV668rHLWuv31ClngqeXjeHC8kJuM+W2D6IpUVMGQHLcCTYLudFgQsuKGVpl0DGNYG+sjLhAPiiu6A== +"@lerna/exec@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.21.0.tgz#17f07533893cb918a17b41bcc566dc437016db26" + integrity sha512-iLvDBrIE6rpdd4GIKTY9mkXyhwsJ2RvQdB9ZU+/NhR3okXfqKc6py/24tV111jqpXTtZUW6HNydT4dMao2hi1Q== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/filter-options" "3.20.0" "@lerna/profiler" "3.20.0" "@lerna/run-topologically" "3.18.5" @@ -2006,13 +2006,13 @@ "@lerna/child-process" "3.16.5" semver "^6.2.0" -"@lerna/import@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.18.5.tgz#a9c7d8601870729851293c10abd18b3707f7ba5e" - integrity sha512-PH0WVLEgp+ORyNKbGGwUcrueW89K3Iuk/DDCz8mFyG2IG09l/jOF0vzckEyGyz6PO5CMcz4TI1al/qnp3FrahQ== +"@lerna/import@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.21.0.tgz#87b08f2a2bfeeff7357c6fd8490e638d3cd5b32d" + integrity sha512-aISkL4XD0Dqf5asDaOZWu65jgj8fWUhuQseZWuQe3UfHxav69fTS2YLIngUfencaOSZVOcVCom28YCzp61YDxw== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/prompt" "3.18.5" "@lerna/pulse-till-done" "3.13.0" "@lerna/validation-error" "3.13.0" @@ -2020,43 +2020,43 @@ fs-extra "^8.1.0" p-map-series "^1.0.0" -"@lerna/info@3.20.0": - version "3.20.0" - resolved "https://registry.yarnpkg.com/@lerna/info/-/info-3.20.0.tgz#3a5212f3029f2bc6255f9533bdf4bcb120ef329a" - integrity sha512-Rsz+KQF9mczbGUbPTrtOed1N0C+cA08Qz0eX/oI+NNjvsryZIju/o7uedG4I3P55MBiAioNrJI88fHH3eTgYug== +"@lerna/info@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/info/-/info-3.21.0.tgz#76696b676fdb0f35d48c83c63c1e32bb5e37814f" + integrity sha512-0XDqGYVBgWxUquFaIptW2bYSIu6jOs1BtkvRTWDDhw4zyEdp6q4eaMvqdSap1CG+7wM5jeLCi6z94wS0AuiuwA== dependencies: - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/output" "3.13.0" envinfo "^7.3.1" -"@lerna/init@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.18.5.tgz#86dd0b2b3290755a96975069b5cb007f775df9f5" - integrity sha512-oCwipWrha98EcJAHm8AGd2YFFLNI7AW9AWi0/LbClj1+XY9ah+uifXIgYGfTk63LbgophDd8936ZEpHMxBsbAg== +"@lerna/init@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.21.0.tgz#1e810934dc8bf4e5386c031041881d3b4096aa5c" + integrity sha512-6CM0z+EFUkFfurwdJCR+LQQF6MqHbYDCBPyhu/d086LRf58GtYZYj49J8mKG9ktayp/TOIxL/pKKjgLD8QBPOg== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" fs-extra "^8.1.0" p-map "^2.1.0" write-json-file "^3.2.0" -"@lerna/link@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.18.5.tgz#f24347e4f0b71d54575bd37cfa1794bc8ee91b18" - integrity sha512-xTN3vktJpkT7Nqc3QkZRtHO4bT5NvuLMtKNIBDkks0HpGxC9PRyyqwOoCoh1yOGbrWIuDezhfMg3Qow+6I69IQ== +"@lerna/link@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.21.0.tgz#8be68ff0ccee104b174b5bbd606302c2f06e9d9b" + integrity sha512-tGu9GxrX7Ivs+Wl3w1+jrLi1nQ36kNI32dcOssij6bg0oZ2M2MDEFI9UF2gmoypTaN9uO5TSsjCFS7aR79HbdQ== dependencies: - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/package-graph" "3.18.5" "@lerna/symlink-dependencies" "3.17.0" p-map "^2.1.0" slash "^2.0.0" -"@lerna/list@3.20.0": - version "3.20.0" - resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.20.0.tgz#7e67cc29c5cf661cfd097e8a7c2d3dcce7a81029" - integrity sha512-fXTicPrfioVnRzknyPawmYIVkzDRBaQqk9spejS1S3O1DOidkihK0xxNkr8HCVC0L22w6f92g83qWDp2BYRUbg== +"@lerna/list@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.21.0.tgz#42f76fafa56dea13b691ec8cab13832691d61da2" + integrity sha512-KehRjE83B1VaAbRRkRy6jLX1Cin8ltsrQ7FHf2bhwhRHK0S54YuA6LOoBnY/NtA8bHDX/Z+G5sMY78X30NS9tg== dependencies: - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/filter-options" "3.20.0" "@lerna/listable" "3.18.5" "@lerna/output" "3.13.0" @@ -2202,10 +2202,10 @@ npmlog "^4.1.2" upath "^1.2.0" -"@lerna/project@3.18.0": - version "3.18.0" - resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.18.0.tgz#56feee01daeb42c03cbdf0ed8a2a10cbce32f670" - integrity sha512-+LDwvdAp0BurOAWmeHE3uuticsq9hNxBI0+FMHiIai8jrygpJGahaQrBYWpwbshbQyVLeQgx3+YJdW2TbEdFWA== +"@lerna/project@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.21.0.tgz#5d784d2d10c561a00f20320bcdb040997c10502d" + integrity sha512-xT1mrpET2BF11CY32uypV2GPtPVm6Hgtha7D81GQP9iAitk9EccrdNjYGt5UBYASl4CIDXBRxwmTTVGfrCx82A== dependencies: "@lerna/package" "3.16.0" "@lerna/validation-error" "3.13.0" @@ -2228,10 +2228,10 @@ inquirer "^6.2.0" npmlog "^4.1.2" -"@lerna/publish@3.20.2": - version "3.20.2" - resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.20.2.tgz#a45d29813099b3249657ea913d0dc3f8ebc5cc2e" - integrity sha512-N7Y6PdhJ+tYQPdI1tZum8W25cDlTp4D6brvRacKZusweWexxaopbV8RprBaKexkEX/KIbncuADq7qjDBdQHzaA== +"@lerna/publish@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.21.0.tgz#0112393125f000484c3f50caba71a547f91bd7f4" + integrity sha512-JZ+ehZB9UCQ9nqH8Ld/Yqc/If++aK/7XIubkrB9sQ5hf2GeIbmI/BrJpMgLW/e9T5bKrUBZPUvoUN3daVipA5A== dependencies: "@evocateur/libnpmaccess" "^3.1.2" "@evocateur/npm-registry-fetch" "^4.0.0" @@ -2239,7 +2239,7 @@ "@lerna/check-working-tree" "3.16.5" "@lerna/child-process" "3.16.5" "@lerna/collect-updates" "3.20.0" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/describe-ref" "3.16.5" "@lerna/log-packed" "3.16.0" "@lerna/npm-conf" "3.16.0" @@ -2254,7 +2254,7 @@ "@lerna/run-lifecycle" "3.16.2" "@lerna/run-topologically" "3.18.5" "@lerna/validation-error" "3.13.0" - "@lerna/version" "3.20.2" + "@lerna/version" "3.21.0" figgy-pudding "^3.5.1" fs-extra "^8.1.0" npm-package-arg "^6.1.0" @@ -2317,12 +2317,12 @@ figgy-pudding "^3.5.1" p-queue "^4.0.0" -"@lerna/run@3.20.0": - version "3.20.0" - resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.20.0.tgz#a479f7c42bdf9ebabb3a1e5a2bdebb7a8d201151" - integrity sha512-9U3AqeaCeB7KsGS9oyKNp62s9vYoULg/B4cqXTKZkc+OKL6QOEjYHYVSBcMK9lUXrMjCjDIuDSX3PnTCPxQ2Dw== +"@lerna/run@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.21.0.tgz#2a35ec84979e4d6e42474fe148d32e5de1cac891" + integrity sha512-fJF68rT3veh+hkToFsBmUJ9MHc9yGXA7LSDvhziAojzOb0AI/jBDp6cEcDQyJ7dbnplba2Lj02IH61QUf9oW0Q== dependencies: - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/filter-options" "3.20.0" "@lerna/npm-run-script" "3.16.5" "@lerna/output" "3.13.0" @@ -2367,15 +2367,15 @@ dependencies: npmlog "^4.1.2" -"@lerna/version@3.20.2": - version "3.20.2" - resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.20.2.tgz#3709141c0f537741d9bc10cb24f56897bcb30428" - integrity sha512-ckBJMaBWc+xJen0cMyCE7W67QXLLrc0ELvigPIn8p609qkfNM0L0CF803MKxjVOldJAjw84b8ucNWZLvJagP/Q== +"@lerna/version@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.21.0.tgz#5bcc3d2de9eb8f4db18efb0d88973f9a509eccc3" + integrity sha512-nIT3u43fCNj6uSMN1dRxFnF4GhmIiOEqSTkGSjrMU+8kHKwzOqS/6X6TOzklBmCyEZOpF/fLlGqH3BZHnwLDzQ== dependencies: "@lerna/check-working-tree" "3.16.5" "@lerna/child-process" "3.16.5" "@lerna/collect-updates" "3.20.0" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/conventional-commits" "3.18.5" "@lerna/github-client" "3.16.5" "@lerna/gitlab-client" "3.15.0" @@ -9019,26 +9019,26 @@ left-pad@^1.3.0: integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== lerna@^3.16.1: - version "3.20.2" - resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.20.2.tgz#abf84e73055fe84ee21b46e64baf37b496c24864" - integrity sha512-bjdL7hPLpU3Y8CBnw/1ys3ynQMUjiK6l9iDWnEGwFtDy48Xh5JboR9ZJwmKGCz9A/sarVVIGwf1tlRNKUG9etA== - dependencies: - "@lerna/add" "3.20.0" - "@lerna/bootstrap" "3.20.0" - "@lerna/changed" "3.20.0" - "@lerna/clean" "3.20.0" + version "3.21.0" + resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.21.0.tgz#c81a0f8df45c6b7c9d3fc9fdcd0f846aca2375c6" + integrity sha512-ux8yOwQEgIXOZVUfq+T8nVzPymL19vlIoPbysOP3YA4hcjKlqQIlsjI/1ugBe6b4MF7W4iV5vS3gH9cGqBBc1A== + dependencies: + "@lerna/add" "3.21.0" + "@lerna/bootstrap" "3.21.0" + "@lerna/changed" "3.21.0" + "@lerna/clean" "3.21.0" "@lerna/cli" "3.18.5" - "@lerna/create" "3.18.5" - "@lerna/diff" "3.18.5" - "@lerna/exec" "3.20.0" - "@lerna/import" "3.18.5" - "@lerna/info" "3.20.0" - "@lerna/init" "3.18.5" - "@lerna/link" "3.18.5" - "@lerna/list" "3.20.0" - "@lerna/publish" "3.20.2" - "@lerna/run" "3.20.0" - "@lerna/version" "3.20.2" + "@lerna/create" "3.21.0" + "@lerna/diff" "3.21.0" + "@lerna/exec" "3.21.0" + "@lerna/import" "3.21.0" + "@lerna/info" "3.21.0" + "@lerna/init" "3.21.0" + "@lerna/link" "3.21.0" + "@lerna/list" "3.21.0" + "@lerna/publish" "3.21.0" + "@lerna/run" "3.21.0" + "@lerna/version" "3.21.0" import-local "^2.0.0" npmlog "^4.1.2" From 904f7c0080511f264274b1db48b0774f813cb163 Mon Sep 17 00:00:00 2001 From: kmelmon <33470154+kmelmon@users.noreply.github.com> Date: Wed, 13 May 2020 15:09:23 -0700 Subject: [PATCH 095/209] BugFix: fix default tabindex stomping over acceptsKeyboardFocus (#4893) * Change files * revert dfc57fcf2504f57baab20f550b36a618eaa99e56 * set default tab index to -1, the hope is to be in line with xbox assumption * xbox doesn't seem to rely on this, changing default back to match xaml default --- ...-windows-2020-05-13-12-47-43-tabfocus-fix.json | 8 ++++++++ vnext/ReactUWP/Views/ControlViewManager.cpp | 12 +++--------- vnext/ReactUWP/Views/ViewViewManager.cpp | 15 ++++----------- 3 files changed, 15 insertions(+), 20 deletions(-) create mode 100644 change/react-native-windows-2020-05-13-12-47-43-tabfocus-fix.json diff --git a/change/react-native-windows-2020-05-13-12-47-43-tabfocus-fix.json b/change/react-native-windows-2020-05-13-12-47-43-tabfocus-fix.json new file mode 100644 index 00000000000..3832af20367 --- /dev/null +++ b/change/react-native-windows-2020-05-13-12-47-43-tabfocus-fix.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "revert dfc57fcf2504f57baab20f550b36a618eaa99e56", + "packageName": "react-native-windows", + "email": "kmelmon@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-13T19:47:43.325Z" +} diff --git a/vnext/ReactUWP/Views/ControlViewManager.cpp b/vnext/ReactUWP/Views/ControlViewManager.cpp index 0b26c602d03..e91cb4a0226 100644 --- a/vnext/ReactUWP/Views/ControlViewManager.cpp +++ b/vnext/ReactUWP/Views/ControlViewManager.cpp @@ -58,15 +58,9 @@ bool ControlViewManager::UpdateProperty( } else if (propertyName == "tabIndex") { if (propertyValue.isNumber()) { auto tabIndex = propertyValue.asDouble(); - if (tabIndex == static_cast(tabIndex)) { - if (tabIndex < 0) { - control.IsTabStop(false); - control.ClearValue(xaml::Controls::Control::TabIndexProperty()); - } else { - control.IsTabStop(true); - control.TabIndex(static_cast(tabIndex)); - } - } + if (tabIndex == static_cast(tabIndex)) + control.ClearValue(xaml::Controls::Control::TabIndexProperty()); + control.TabIndex(static_cast(tabIndex)); } else if (propertyValue.isNull()) { control.ClearValue(xaml::Controls::Control::TabIndexProperty()); } diff --git a/vnext/ReactUWP/Views/ViewViewManager.cpp b/vnext/ReactUWP/Views/ViewViewManager.cpp index efc490184a1..74b4efe12a8 100644 --- a/vnext/ReactUWP/Views/ViewViewManager.cpp +++ b/vnext/ReactUWP/Views/ViewViewManager.cpp @@ -87,15 +87,8 @@ class ViewShadowNode : public ShadowNodeBase { void TabIndex(int32_t tabIndex) { m_tabIndex = tabIndex; - if (IsControl()) { - if (tabIndex < 0) { - GetControl().IsTabStop(false); - GetControl().ClearValue(xaml::Controls::Control::TabIndexProperty()); - } else { - GetControl().IsTabStop(true); - GetControl().TabIndex(tabIndex); - } - } + if (IsControl()) + GetControl().TabIndex(m_tabIndex); } bool OnClick() { @@ -213,7 +206,7 @@ class ViewShadowNode : public ShadowNodeBase { bool m_enableFocusRing = true; bool m_onClick = false; - int32_t m_tabIndex = -1; + int32_t m_tabIndex = std::numeric_limits::max(); xaml::Controls::ContentControl::GotFocus_revoker m_contentControlGotFocusRevoker{}; xaml::Controls::ContentControl::LostFocus_revoker m_contentControlLostFocusRevoker{}; @@ -375,7 +368,7 @@ bool ViewViewManager::UpdateProperty( pViewShadowNode->TabIndex(static_cast(tabIndex)); } } else if (propertyValue.isNull()) { - pViewShadowNode->TabIndex(-1); + pViewShadowNode->TabIndex(std::numeric_limits::max()); } } else { ret = Super::UpdateProperty(nodeToUpdate, propertyName, propertyValue); From 5b96a1fc16bd6dc5ffbd5d3e7c272989f1dd5f98 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Wed, 13 May 2020 15:42:03 -0700 Subject: [PATCH 096/209] Update e2e testing doc with CI debugging info (#4897) * add instructions for CI debugging for e2e test app * point e2e readme to e2e testing doc --- docs/e2e-testing.md | 20 ++++++++++++++++++++ docs/img/e2e-artifacts.png | Bin 0 -> 94953 bytes docs/img/e2e-crashdumps.png | Bin 0 -> 109748 bytes docs/img/e2e-syms.png | Bin 0 -> 95206 bytes packages/E2ETest/README.md | 4 +++- 5 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 docs/img/e2e-artifacts.png create mode 100644 docs/img/e2e-crashdumps.png create mode 100644 docs/img/e2e-syms.png diff --git a/docs/e2e-testing.md b/docs/e2e-testing.md index 83407a939a9..bda97c8cf67 100644 --- a/docs/e2e-testing.md +++ b/docs/e2e-testing.md @@ -436,3 +436,23 @@ this.submitButton.click(); You can easily to use By(string) to locate a element which associated with testID in the app. It's recommended to define a `get` for each locator like above. + +## Debugging E2E Tests in CI +If you have access to the AzureDevOps pipeline you'll be able to see test failures and debug crashes. +Here are the artifacts that are produced during the build: +- error screenshots of the app when a test failed +- test run XML - this contains some information like the name of the wdio test that failed and the JS stack +- tree dump outputs - you can compare these to the masters to see if there is a the difference responsible for the test failing. +- crash dumps of the e2e test app (ReactUWPTestApp) + +You can access these by going to the AzureDevOps run for your PR and clicking on the artifacts link: + +![Artifacts](img/e2e-artifacts.png) + +Then you can access crash dumps under the `ReactUWPTestAppTreeDump\CrashDumps` folder. +![CrashDumps](img/e2e-crashdumps.png) + +You can get the symbols from the `appxsym` (just download it and rename it to `.zip`): +![SymbolsPackage](img/e2e-syms.png) + + The `ReactUWPTestAppTreeDump` folder will also contain any tree dump outputs that were produced that did not match the masters. \ No newline at end of file diff --git a/docs/img/e2e-artifacts.png b/docs/img/e2e-artifacts.png new file mode 100644 index 0000000000000000000000000000000000000000..d722dad25432389b0243df6fa911baa76d0e8cfa GIT binary patch literal 94953 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 literal 0 HcmV?d00001 diff --git a/docs/img/e2e-crashdumps.png b/docs/img/e2e-crashdumps.png new file mode 100644 index 0000000000000000000000000000000000000000..3cb5ddf764c12c5ae2310e114a221423f7cd8a8a GIT binary patch literal 109748 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

WlxMdocotTfJ9yH75U8Bb)08 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

#H)`g=3e6FPq4oeZk6LGfZK%L@DLE-(YE;H_ zw;Z4reXAd?oI0Bh|FG9S95fnQx^EXI+%s(`a<<*q2bh*lolX8cTzY$fUcVM^T2CDW&QJf9DSnTD(E3l-Ig$zt$FJnKRU)q8SW_IAs zru8WlWdY=Z^@ph)uyj90ws(;-hva|bOL*$fU|l-SY=c)0-p~kz2&pAh3A9^Ir|K;o z0cveB;4E$m>iTTL9+!b-`>Rnl&?_=tD}Ls~2cN_ai-gcE4}&&eQ&nDu%O(^Q(>$+v zL8e~KZaG_a+r|wn*{mSFb+>&+j}XKxsQCh>WIjhKI^clte}$ARf(l04yzPJ)^J)~5h!k1RI^SvUDY*0as`wi|svf>JqhK4xoJ4@^}wW%DwI zeI>kK1xkD`faFEg?sdxctaWTvPInHC5xD)3f;a*(`@3s(^DDluAlVI|w2BH>q~N+X z5pY4Y@#0BeXXI)Czc*`CTlW!QS*A?p43oED4*QR*iU6@w#C)SJ;KhID&|(yT=y*4QE9IiWD@h5m zXh!H!_yT+(OJ-K3ppB|oAXUoa6(>tt`RuMn5~04Va|4X}XFMMPZky|F;071fO;cnG zS%ouSih!g|_?y$%E8y}0=44ka6pkm-$7BBu@ilx3EpI$i{h^NAwPIJ~8^ zb*-bmlrJUJ4t2mBlT){Gy=u|vMVrt}4+;JGrDzwG6-XXM!lX)gJALG2*~a%t(JFe3 zh-FS4nfIr|u~mCjJ~-dWc_8E}ge*U-CAjb|1@G~Hh>FdIz$s#lvJ;(Epk}%b(?n2P zty-(RanyPv2s;f^*N)r_eTAGj*{s7bm#0?cyDh&p7cTiV$KYe#D^0)_g#Qs0)ArV6 zSpbtj;f}|HjzbG$dYz!z3 zo9PBj>TGn%mWBH~2P?Y1BQz$$Z>fDaciQg$Z`u>+p~eZd#j$tuP;HP!j>^wHpNJLIfGR=#QH#u*!V~-L>rsdovGX)-)g-582k~blVb?<32S@?Il&r?8D zhMed#gRkYpm}j0cc^3+f5ON1lHeZ+^&L)k34(_v*vy*zve*;68#rLOR7(v^^<2D_s zawDT!Gr}y_)F)`DIh=4RXHS!i)GuG%;YmIPw3_RpvKyjgJ3ZX+;+!pRRbQu(t2wU# zTP69+cC&mxieS`C`EDA;N{v1!sd4Yxnt+$0?eor&b8WZG2MT5B?hA2}B=nK#uoRps zD-}vSJ&%5!@jxZs6f5z~zUJ#BvKsChBzV z3#c(rYkAj$p_N)j1rLD7)dg)rYB^mVa5P1ApDT`JD5C7usOOT9I?O<)u8UH~*GcQN zif`Q)dfXNGTab_X!(r3Dms>oX&qZ6Tq&ZT%>C|bzHu`>gXG~tH%LXh7M`}=YwEJ+0 z4s%-P_IZYk4^2SV7{4C^)5O`CPv$kmQ3cC|>t}@_UP3>$Pux0~RPZlJ8d1ID+X= zFs%5R<_6Rp4^_)rn_+EVD4zh;Rlb3dyhl7qrJ86$URR%pS}WKrX^UCR-3I z?MAp_x96F>4q$taO9GuR)6t8*f*v-B0>%BAsl$N!u2GB^QJ36{xC6k3wTQ2O3{cFJ z^}bI72q<)&XWv1ldT(a?7`N87L5t`MH6?wtCA-k3w50q#;}h0t9RYY%P5+CuxOcU zJEEX^Rs0E#HMdsrHg1T@d`8feL+;kyQ3`1i)YHhg5sO!V+l4w(yPOZZ26DF2<+)R~ zM)4XPG~MO|>u3!5X=P8jj9Y}&^Z(pFW8(a8+GlW7hY3lIuhzWJ2$$f7d#^JOMvfPp zLaAlWar=tUI>5A7vT_3wh;a<%oK?)_qTMPW+I96;w5wCrah?xG%EF>`|?^TFBZ_3=_sRUeG4jNAB+^=P3UvC7y^e zB6w8p{g7J9i(zkNGMvLpR3)DVSgw=wi&K8ginS^7O3ogAezKoq>P^u{7jxABmYKKK zk#MzL_1ESpjxs+;^ACAH4*O`B%-ryr`~dqSw|;wzEek1Bz;9+BDu(2}t#utN>dWHx zD_v6q`<1Tzhc#y4-7qcM2~@f)ri)C@l7Ss%P|uM51`5rHp#6&*XV$!)|k9vA(71^ZAQ-UF9l+MG`f`T-Ugx5tk@AYI(}|m zWx*(0HjJye3HPDJ)@xR~T1VanB-rMP6`5&h1t`BZ*OxCb;BMQ*D^?kf1}e0I9R(Bj zG%Lx)Avj`*)^lOIPu8QHb}r?(_-3wQqXaQ8%mW@aeL}m4*-o|c)J*mIdy3}h$n^9e zx7riLjXK<-?;6#{+{`>+k3D9QLn(7Hq()#fv8N4qt|PINFVODPCyG(>XE`6cJF+VZ zk3#;D1)-D{IDOl2FQE>vGo#~+xA%OS3u?(R9-p_|z#7z&E<9R+Q8a8Yv9mTfjT?Ph zPc@YdpeWz7ke8I~UK>`#T?cW$JuRTI6uN$beULnQ znmDgE2gY7fH?4nWR1Gj>SE%YTf)}K*Hkk!Le8hgClOjHs9|{Tsi_n|4M#r_;zBIvL zRtj+&?aNBH#T6q{uF4XpfZwJxo}g$M)DC&C)x#nj$%@;janw!1Soj`>0{6f8j~EKY zO7=d6VoD@;pMx0oc)YhBe&C&jAw@lRI4w0ZT&L9WV)6T*6bf84XX_-$ca%DQ5W1o- zZ0w!;lr0E%O2ip(%f~pT?5@BbS?XW$?4}B8yyT!z%G&r?WS$1i-Ot>hP|Qk#W^;ZQ zIe#Wv2FeS~q9O=k=Sb|)5sa81i*;%4Vo+7=Kd~8F6|HmTI|&A+U>CAFsxJkOPHG~9 zbcR6V)G5tcn_@CX5=cvHFEEmMqNC0|G7QC2Pb?2IW?ic#@jxF6zgY!NJZi`f>vS$Y zM4<5sFFbS};4D->1P+%`SmZQ;1MnBNhhptPzh0I`w_efGp2h4VXapnKaEynt{ptC^bUl)El0{XVJ^nO$s7~v4jv>3qTOt(Reuk+rSPU)W zMg<`%C{DeQiJW3^fiI-LJREC8GNYssuqCBTkW9Qb<#m)wnrJ8++1_b%`;%BBnfgx4 zM`U`yMq4RMCTh~LfK}i4K7oyr_p|g&G<)fRsGQ(N{t}9Avy~;(V`OhKN$Xo@xCHs* z_AYQ$*O28o3#o;ePbaARK1X+|Xku$8iwR+ON>m=6hEkZU0y|UI*UUFEZ8|fC=JBnhDd=vx zSarBG{V4zNKrRhTdumvS@qQ^Rtbckp; zqWaVswc(nNnHru*1Ul9l%!%0pL&^2M7wg<_0>y`zc0a4NNv-_MaZSq2-c#=k^^8$& zVO9SiKM04g73bfv6;AnbtgV33ZCjcdh1ip5#4(!l`4I%PwY;QIp7ujN-E~eHHD&j_ zsjm5)00`JToR}yse$hr@ZxQ7?)rie{m$-)c0|rkNyd2Gk8_+4ZCN8 zgZV&%dkT6x2^c`gU#&tWF?h>!ro4V&htxWz)Yy}>)hpjZ5 z@w>t~OYl^DtMvk?9Ey<4_0+yN(jUn!gqG4FwzOi9Wcrr#!WaL&u9yE^X$PzE@sz(N zw*=xra;x^Yn>xDgn|9y!>@d3vj01Pg zBZ6xM^N+jG7xFf~6_kF$4esxsP=)l?mE=qXm>rC# z3u-q9!M5J11~@j0Hz7fLW(?>na~Hxkz22yrE|^qv+yQz&xmP z_Slna`{;k}E%LGSXfY>prQ>-byZXU&j2Q?DLbl|nhRr3>`|LehWD+StPmZu3)15hQ z%s-0M38P4{#IyQ#$;mKnWOJ>Dw& zg;47ctjfCOCkzZXYUb^%xqWk7RrnnNs)BTIF5ozLzCFPfl?nNySm%-aVb^lfTtHR4D9R%VGBy(}@H4WSwT|I3RQ39@5w@IP(e5&CfZm~+yfroh&RI$z^xpAXnGGNvYxsI*Q) zQEZuX{qu7vh*Eh)86*lQm0B?+ykQUzg)E!fD==VJJno|lj)!vRF@h0-b;i42D7Z}3>jB#5zOK$&OB}yCDJM7sjZ+h!f?0N}+y{Cl zI8p6f)HrHtK_zOz{3B{DX5Y>fVXycm*}jd@f>#xH7fwjbmY3GGhowvr(Yln-r<{t; zwu~bT8xmn*jUS@B`X9xygn!1d=(-|4M7sVK$8zmBj#a5WP5J^QJoXDo5y!iks?GdD zQa~H|HzbAh%-df`%GGOfI20tD5WC+iYDw0^KPol`?vV9cu<2QbNi%k*w`(mC)!Ps_ zVA)Grj#;a#`s`76f~lSMBVFCRDqC2)Wy(@2EoF-G=0wHlbpzQv*|JW!IGt85bn1c0 zYX{r-mDh(CQu(w4-j2We{WgI&PQO(RwFc#@%ZpLzgh^K*4U4t;Uir!a%v?6E4g2kO ze2x=CNiZEjoWr@160B z2J5a$i_ ztkLc41#(>vzVQ7+0W0p5ZKO{DII{~-k%ZMcVb9|<;P`2e+6za~N^7*;H;Z`I2t{=% z1_ClUseSTqND#81lC=~K=AzpC>Q6ADIl*1rIGh4Dah|GZz%D2fYsg4G<$q?nt1aHJ z5NP+!`y$_{2TU1$T-*euQqM}0TVy7g-5@*{HWo1^>Zkt619J>J5a>fWRhu#Aobl@P zx&EK8d&*ML>I*g`9J{CEMKHY-b%$LIv$PQ)XO$5xvzSkJB^1knBWKs6Qr2e^QRL0I zwxP$eqdH}^m$O0~B1iO;GU;27O5mNaHWV*%sjutK>`6kvt4MU$NIrx%kTo%kX&h>X z6d?>}U+Qd%0d)@Y2;rU06DX(tm2j{Q!V1LM+>6z@8oD6ve-evHcY&DhWq7JdW3-J(1vF|?t5)|ETm*e)I zz_#GmH3LTe;vTKN*LxdN)+`Y)7GVd*VM!N*0pP*|@z5_$?JNYEN@N*A2F2N6o~P5E z(h(3fo$!NDF%IZG0SwDq%k5NpsY>bwJt}d$`FYhiv+9F9TJC^@l5dKBZV3uRBnk)HvVpXf`T@qL|nF zN~JbefvU!@)IG~@?9i&;?n_6F=&-MWv?lJXUeMg}JpAAVe_kp0+cn^*nFSSrX(&~)HN6p zK75pfsF6PzAal(?ePT0Evk^bZ)>?oWcn$V3zg*7i-^((vr z$n)k7Nsir@z|>Q=bmq8n#^#*~;653OEH@nhgo^CrEyXAG7pUi^f#z_|mU7D%IB)|J zlAxm|xTp3YN#_tm2RX8fUhm0Yknki0DjQ2v`Zmf928p~nXudr1JzHPf^=r*r>Kcy$ z%rD@z(y7d&+Kx<^e1S^sMBKh94NaW`6fSS(g}UsvD`oEfKH4RUDfYD3dR+h^&HMYm zqpe&BAb+|315r_$Var+qN5ocO8D{^ov;}-O9x%Cf$i;F@rA6=LW+$ICb9asBI$8^? zDB*3c+~5T_Bq6VZEvn8F7V)?NY^B747b5#KcHf_6r&+M>CuYA&F}3maR+W*##R?## zy-%drNX877GQPZOi3{I=wa5+})QrH@1(gk^ndC2q*vm&muvP7>K0|i*fhPqsE+j^g zmX&@5B-A8zvOC|U)8tjHZ$Vkyym&}0T)-ewKyTcVD+ZJ(zlWW=g^cV96t5}U2(wn* zfNE*r??wwV(m4b+j&)M!0H&DMKvi3nu8|_s2WY6zb`jERM55Ag32kpuQRT#DeUa~P z{|9+*85d>W?t2@cfPgeZH%NDf0@6qhNC}bxk|IcRfkQ}lNlHj69ZJX$LpMkX!bqqf zDIxXzPvctmeXqUNzF+L;#a{cJd@e76b7uZ=9N**nQ<5R_CXBnW62ji;zuKtjyF@&F zw`C{kmF3g-g5&I~EFo8O`ptel+IqehgYUtQjk(0J={4k2C66!uQ)CwA>h9s85Bh7B zyz#f;PMME-*%?H19TV9k2n2<%xhfRS8-ly$+a(VEkbe(V8FTs_Xj1t8S(Acb zoREMtDMkGZ|CJ_1xm!y{LkDqHg*={Knw{bUyJsG4uv2q&>x{bLK=XCf1!+eOHa;)%OWx}tsjFMbsF zPAkgVQB_WND)u|g?Vv)-n0Vo7zUDlb93fmGn*rf;$YDE>&BUP!%yNHcGqF($*=jX- zj(g*+Ro+^j1UZavSc^XeJp#t*(ABn+yHYoS#AwSIB(>03yIaYd?Bv-Vv1_e$&`Rw=|&HDxr z<-o=G6@?b+3HO>**i4t3*Vx-d)PQ%k_l@9!*+^_4Gu9DpD9C`nG!f2~O?&mk!J}$Y zs!n(|zV4^aA!`5`n+A{X%GW3K)~P(b(fay{uibo#waOb;H*(iV{tPZsYlU|AE}Zrk zZaQhc#+nCr(rThAvv4UWX0c~888p#PqK^HcoW|p2pypb+gpwxH|3fg~^Wy?HiqIc7 zibh8V1r)!OXTHad16#6{@rtzg9(dh1hYw0%5>+IYt39Mrp5zx|>b&qh5}}81eE0Nd z+=y@t?g!c%+_xA*=ds{nu`pFa5*w2_XnXMiRB1J6@9;B=D`W99Q@P>sXB&nmaP(=J z_Itj;eXjT?fr;GcmlnlFCjVFd(jO@byt?E2rw19#RTI0;+JDC{g;N1^h2$5yg7}g; z4q+=q*MDIv?*Bcua`}Iat(3&?%$8&ITvP3*_!8q$1%CL@e{!NEGMxT4q7ZEVgAv72 z%}t(URs=0vJurG;ktI7L*~6Em>3mx`od1AK6c0K@)t8iuVRND30c-MfIN5Fc532N6 zzJ+6>ZTL|P*i^k6V>?ISj35p7*q(bk|NT{O^#|8HR1}5E5|F1=?l`#5b;LQW_>EC9 z$D8f-TO5B%FrapRGVk@kmWi3@tL&xiFs5iMM`>0|J0|983W@k!=~9L`1-Y*k?fBOg z65fxQ!uI!S#x$;N4pj;P4BN$&Qou_2P_oBT0)vFbex&zL8=Kog{;?CQhl&Xs^ zDyf`tR+ii~-~U%Qi?mAqb|ZXa+q+Iu)FT50mA7L5TbxBvkufCA;|lAy9dNP>o}%C< zK3kwuVqj!NhTS>R4qGD`3KM)>!5hK3MR_*QC2>iYMsY3}W}+<>+Cc4kLjpI&J>yl# z;C6@gnw9$8Gg#U$-2z-#+m0U^#=C#xHisA1JW+n(B_-3`HKso^5w1j4)<8gtcpb9-TqCYh5A1eEzHqSiR-0R@n7x1+klz3 z@v!Q8TBOjDWECA{W&?4PXb*)G{Z!2Mm7oKwY&ZFL3UA6#xG>Q)=FWG4m&sH4z8B?1 z^R$R}3k@mz~G;k`1Gm=0_u;mSnX#mTRDvlU*`m82AP z178XoXFxFz{t@b_6*Z|QyjYtwl};z_R6ah^dKcx?vFqSQgsNTXL3hP<&@Q~?n(mZ{ zHDInBBnYYD<-lXp%%a|({+Y`nnqh7Gb*_J8Fl|kwyea>~t`uqL#Flu*y(s5J(TyTPwF>%P&ij0mOO4n=8wz|=)32>_tUsO(LFD+#iwtDze zSjm&340?iY$woqgku9~S(&T}KT0#Am23hVZSh-mA9)JX-pv;-2Bf?~NJ=QiCN8T=Z1{;m?Dz*)KttfmPQxSAcbVA3@ zwlnz!P7FHQ9DCZv&~BcM=f`poU5MQr==Qkrf}EzT=LC6&a@Xf?9>0VQb#4y@XPm-c zS!G^`ppW??=iUCP{OWA{0m|EIb;`m^j*%l>%;`{0E>(5e#zSDNCexrr?A@i~*wqJ; zgj{!ncn$4f>UF!Iflef^fZSQy7|{9)-bY9#{5?2~pafn^acBWu?O@)!GS~#WNFEtA zw#>&mxMx^e*ii<_x!8vm3f)Q|9a3n4W>Zk|u{E;pVF@`g%3}UO)M@Xr_3`qlwBDr_ zFqXCbpwfu?ccX1%Sfow)PXB}Xa^reF;DAq)fQ_Z4YIMFgal1neB{9LgLR`3_2yP!= zVlYnMrK@2ZwM(fBG&}ur*R_LLqMtZxq!5WETBA|}URLI0{p zzv@U?Jn)Pl`ko0iVRWK|BdG6$!}2QlsDMBNa#y8nWs zYnLyZd>5}UT(HGK;DAy(^-xFQHK(`TG9G4ZMY-3VeapsNisvQDmal4?zJK!D@fRQ5 zL9VPHqP^^0PkzCTb+VzBE1VA+ZgaGy&g25sT5#)NWZi4aXmOhmV05un$5Jr9>Q+4l z436atcP!qev6l_yQV%+{q@$IDzvOBf1iE_s*=2VV}h$nWY0W-$7R8|a#LOzz-ezbE0jg`vm(Cwa-i9cwlr zm%=bQ=W_86E~>(1^PBk*IHD`fOUR`6_sxp!L0YH0+!z?`>RP~NFIuwDc&S>NQgvh6 zhDT7#UL!RL&+kxl;?WIZ6Gl}`lBA+eSDb}n7=jbr=<3q+8Fr(8& zUv+p&aLYB4G_=sG-hP4jbq^Z*<>8!QlO@jH)WX~vjY4;3D6b~hP^HR*IavVuR2y4S zkMtsEl6gUh6LZ)dbJ%L|x;SF>Wj#q7lXUG42S$QXru-q&@SB@axlz{ppXF|yujclc z5@%x}ZI1~fLv%~V_!eO_YoAF5ij+ES-IRZNUS=6mMF?l;?1=Ln<3yed>0NbvUPG>p zr$0wFMqNgnS&ZFz!{CCWABG8Tb@v`QcN};TR&$x8Cft@Kq)R<;!Q{ZlPyHaojHx%E zdUt6{lrrjb?Ja91kq-8j5x2iW0{CQ?L3L_s%I7chWwAzG7UXVzglxQN=&hG?8SnuG zYjPdEyX-=T#J<`CaZhp?ta?Mt5Po}MA77-HGUbY1=^LAUS`o^Txx`mq3x9ilOG_@t z4FsbGLz@u(QzcR&Gn{Zv{O9qib;X5?NK@*47qtJG#=H1ST`Tm==2;Co#}yeu*U68g zHuP}J^s!Q>Pdus`IdVEY>6qF6N-X_O1efmA8CTk<>VD59*Y8^`v z%<6`ANrR3ar7W{KZ6Jx;*s{3~|4aJz7dn`!Tc)0x@K}Ba2IvJrVFc2@j?!TeKrv@a zhn(e;>*?D2;oIRQ(f(fl+(%lJg2{P6twij#ZzKL3;`Zaj<@1Ar8F@0`E}nw;nWQ>% zf}#;f`%=7Gj`3CDr7yvc5ms;D670P75LEUYfc6FPUCps|S&>7>kpf()IU^a`9ndb@*o8^h<_#jA)cX`jL2*sM#%W$RzZt8hgJm~Ib6JR+x| zgb14N_zY@UP`Q!+Wa$Vd7uR*XghLTT8+3L4>X1rBGI?Qbi2Z>X*=EdkIQxc8sya_P z?!`2Y7>>A=@E06mIo!Nki~bxFSVCh8Z(wce>7wORtJwjxW_jZ>R#b^!8j+aKhr=0! z`}9sKxTjhXo_8=`cNX;nrFW@CFiRW1SqV%h?)|_EqVQWu-?_h=K8!j@YPr8HIU9>k zHaFOH@u#ogpp{D;!dMhDtHZiiOvDv>8n^FOjDBWaWQ!IwDyhON6V0WWjpD0HOx91* zFC|0$8ZEc~h0(03_X`OmsT0c20uM~h^ZZ5Jh!H2*x7Qp!k{<6B-bq*_#LgPcSmTzh zh3Q$6sPgHMZMZx(eeLmvycXaiI(RNGUQ#C$qd}?$6&2_|-&P=$z0IPdr)v6?mprJ+ z>t&G`!(0w-N_fu7jfr;}Ic+}#GpH8zY3EnLjh1lL&QckvV-6^q!YwE+$-Q<$pYz0B z!uu&f7GcO%hRNOzvSw0e;H*!cHw}y`-n_zu`%r0Fzq0A{T}wXV`Gvo(If?YNC3A(Hetn8l@P7n%v<@Os50X-r=;X$0-?=Ozx=7uLLV@nvVgs0(F#XOmV!P8<%4 zDVupSIF!Ol=hn*QgUOC_V5pxsO-viY-TEy7gwrtCAw9&G!kCbdLPBjO!Rf=B&e#al z*3{C08Ub?7e>x}SeyZaTKY(f8b`DXZMuFmvNEAy& zpA0$b6p(r3k{4@&SN<$;8(Zg3BwSO{jmxNKBy3|io!;k4hiJU72^{v1bL7p(3w;sn zU!HWoe~`)an7xQe=CSTNLa|DZLVTw4VpF5w%<)Jb;8_5uhVR|Cx;`a0?3zx>*c zR|S)3bYeGdyY#vC{MeCc+h48jkg+kVc5VQ(wffr&k=O%P)%V_dMD?-xl1-aRMIUra zY>7=ib-dF__BEwE+6pFri8F{trv7v7j*~+K;>SJ~Hz7@qKpJ?{UY`04&TGUms z>sqHhoY00s-7n$01ZG0ll!Mg}UK6^e>@CEsdOj#O7#MHE1*pjMv3A zj~oee*3ygwrhAagj2J}krvf=(ryY;&-5w2dSt@*a34u{E$9r6wR9g0G5+HVg1Ed{c zFxeF}e)Gz-=NMm8hKOPjr>iraw#G7`3u*C|V&ieAqei+rIHgcB9Of)0D|(mk-&nHB^CO~*YJy7h$%>q2yhGH65hm*$92^Y!ZIo{UAm_3dL)TreXUd>yQbDj zdcN|cuDwV*kMcl#c^RHu8QnjTbnoWA!a|FmWdV)37A0e>s^BGl@A)m3r?GLT3hp#0 z(&MMRdf2nUS_$DYlcEC`yLWe4!gEsnWLa2-WIONaqNGtrV44uUZ*HJWt2V@j{M2Mg z&roDJ{iuH32 ziUuzn!|NiOmLCT0n@N<8nd;pMrpyZ+=}NByHW@KH|$f5H<*88MEC^JNNEu zQ}eti5gd^G(Yoa4)dKoHe7=WUhf`o>u5;P!2Xh(hhO4*jotp}3}_>|{nY0-Kx5cFWAl}?`SVP#l{DAWXkba(0;fsxvloV+!Q{sE z6jN`zH4tTh-mV14udYUd-6k+Qv6$gD_-yrR^71OQ@WxgYyP0bbt)6bJMn>Irgs_&7{Kf89<@TO(j=>PfDoY{xlopj|dy% z7cLNl3L;J121x0ufz764E8>{9@l*U9Z!GmJ zH5yXac>;iG>Bt$lIIlrBDXBAY#a|1P5%ESKl&l1kcx-EF+-qN2PByE)mM8IgblGQ8LEq&R+1d+KEszDp;Fgw#E0v(*bMS_A7K7wRDr}i>kJ+Mq+@8JWSY(U> znPI+*CKfRMJW<~W0NElT;F~tOIQMY@ZR9rd8Gstt=dnbfF;{~T`OEv=aZK&ty=G?c z#?J?wmn;-?itm@Otbq5}R(19%*O@8Li8mzJg1V*wt4l`!&FEZ+sH7f}SB6fmq~9`~ z0Gez+#|Fjac!HIoox6UHh*yBz#6=bt7mHW&$v5h!<278O`)tRx#`R8>PgJ)T$V^Mh2B~6pR(@)fz$mjOE9@ zKC?4{I%Ck%k`69-FmB|?pG4nnA#E2^+EMzth4Kun1zpjH%Ov&upfvMg5kO86O!r3y z-9Vdz(N`Vg-~U6V7rl6Y!b+E*I`S`>_C(5m0uiy zeKdLzWd3+zJ%xmH9bbgJjf8@~@S2_@h&96WgrQ#UTY$DuLTHN-c=NRD8#|H)?98hM zN7z%;iJGaeaX$vPyih1t)4`e{m$W_b5trcHS3vO4N<3a8IPXH&0b9wGakzCjCzrVC z(W8z=F6k>!KJ$uzY*d?jY4{10^LTPC#0r@T>*L2sp4zf#9#!)AF7#Jd?p3 z0wGVVI!adVXQmk1q={`@!Mp@it7RPHx<8NP_kTwFSk}o&jIQ+o%W}pvk3$tt9s_uRtle{yuobxNA)r`r^ zUL7*x#Qah(ji(pA<8UffPMt?AV%qU?;RhL2a~BfTpoUwJQua`Q*W$b{h7Y{=^kns> zvqOU2D@-zj`yp|o;}Xy<16WiLGMz182NbIx2D<`TsD>J`o{pjmDQ{{Y zeEWdz%qvFyMSBhI1S0Cne!5gZ{#f_{NbYF}06F&CP;$@Qp>a6@M5b{3B2zfaYjjKi znSwCyBv)GD&Wp>Apeg7ckk#S?v^e>hUNg8^>|b64bjrbRIt2%}box4OdAI+kr9qb$ zQfw%QPT3W^{!esD0Ys;;VlGRQ-1$r)<`XuX!b8dM2&Dc!@j9 zb!^gfcQW(nY$pVlnf{X>6q+fh$64jO@AhtJMSZf@dpPge$8h(ePhu8yTHDIDgWT7X z5^kPt$GEj(B_p*m9IB62fnKOl?eG_$;??e6h|}KWro-Ne^7dFrjF;{*&CwHFj3B#xuIc>T<`%F|^W4o69o`w+v9j zktCPl0z~?>br(ffbW0VU7jjsFD#8U>{AR+UEJj%G3++@_*8{NDf>IhC0-{hts4?Uq zPj<$`u%rH}UjmiLmwgp>@Y~yzP-b|>wQ|@{o15#>8Q3{t$p#kB4#i4}4YIndwtT_G zYBC|)F237ns8s>*2Ek3BU=Zt-iq(qM?f+veyK9~ijBtZt5YvG2y&49vsjvohVzna=P%eeIpHU(o!186;&~vQLU|b*z;(3OHD+`X~ z5~Cfv9@;#&&W`Z9B0i7Z-f;6+0ihMySbsR`0*)(P7uZ#P8dNm>cM=XMA%lwbw^t;v zl=fX>+>z>MIfde$W?s2WQ^_Y$1e;(r0jsyT8;1C@WPy`Vcu(u_j%PG^h_p1A?n3YG8d3s@ zkQ6WAxjeQv5va#lH|huM|9-U z9QBzY!GJ$4m2X-@yggnC7bx=p&+#i4;8p7)_(hz2jKIOA1jNY>kPvckNpCQ#(%-r) z#AeymV@*Me(mWdoz6!VCGoxy|beOgRsFT{C)XCCTM8#A3SeM8yr%OL&Do_T7d9hup z<}+FbDNQ#Xdg?UTUT2nGTTgbWx`S6xH3QnwcMup7n8&zb_H_y*_P4mUO#PMUm5p4_L z$l|od)G-i@O?}+Rj&OnZRBE0B7P;d+8n)bEsbIO8fR*{Q#_g8V?V zM`1}Envv!$^#R6nhx$jLW+h~rQX)+Yv?>uatCdh0C^mIS?uR6bSXLm0z4jm96~~u1 zu0}@Qrn0FMbn&r^U{_SSU(#;-Bo~k8_y_jJqZ%ldXaCL03pc3^fyV+i9n3S`_N3_3mXXzr+S_RdQfVG<=%j$ zHTt}B>W#X=5!hY3TzGOrFD~M=;j)blW=fKu3E-Wxs@plj{k0kNsQq1+UJ^xo;io*r zmbbm3v>&9niBH+8o2rk^1IJ)MV91B!N0F=U>lMd;eFR=}M2d;;bf~&w`WEf<^#MSd zNQtt1@D03wvyhiS3MBLJVwmKseNVlJW+m2f0ArhicT&B<2^mEYau64?)@N~(K;0^) zbZ^F_0lRSR&KOCHI)T$x>eBa*jm7#FvxI-KIIKc$$XDdD*EZu$)eMj+>>S4i_T5Odk3qCd9axegA`G?0Pj{2q3T7}5H6i(2qKUlA-a>`4k_EIL9}-Za}?285z= za15;)toBi(fJw!MlUMv(V|IA^BTt&az-e?AZyg+q=7|VA*Bo5Q65kj4>;~sp7PALlo<|z_23Gncd>1bY%-PX^(1K_E86c3Z%3s zns%b9fvV9aO_RMoOd#KE*zTfQH7%OfkP>B3+zzH~3fR}=&x%0*RHT^nNL(b7rJV@g z3+XYwUdOT-^SyhpvU3M<8!qHJw-t=wOX?k1w<@%gtdv^R=HF)+8uDN?;8_KujnSmB z5MjYp@RBmYo~m>jA;>c%E#1SiJ3@B-(9!EWv&S*RRf?h{ zm3O99`YV;(V|(Ub;g8O(P=wEjhr3i-k zYFMNn!C2!L4^rJCH{v>7+hx$32oA5;ZCXLfC=1=Gc_3l$$JJAZ7i@Qi@^bfIRlJo{ z@yc#ZJz8F-eZ5s9Q=(J+^WkV$ofUFwycInuJIg zKjSMw(HSQlW5Er#n$1KI!80SkoKSMx`6@>}Y%(efr*oHjWJ}#Lz;)=aCaS1|>D<-- z9j)P&tKtSSc#2dP$!Ejt`MtfY{s>MmXp|=&O!IMHKW4ZGZ{Xh~C4bd)bnk_LF|`^ zLwfpVqd#|5nl!bFN5kr3c;&9~G~CB!j9AbF^)RWfaQU$&W8KYXyjF-h3|IIJspaV? zK`w^SG(os!pk)?17M->$Pe~g;MEq6xI&%qrwI}{OUDAEH9$|$Jh5lSM2gBd!hGq7= zP7~|Dhi=HvYGu{gM%dv`KI0IUgB&KtbQgicMBr3GEx*oY#%m2r^Seo-#!v~3yg)Ig zn7G@c{L!$Tg>@)+N72%oTWdNF&o$h6k2+_OPF>3j6s<(|Y400|YkY%0+miZh5u5*> zVVGT%P0vkx8k2`{nZTdmzXdYB6#W4*#1#J#$an(kIbFP%our|6R9I%=V=m@H*L)kY zTZt?3|Ed(nQb}cdH7>&yio=iO-KUx@C21)mu&<0!ilNPXOEVVrrFiLkj(zyXJO1_u zKwz@Oi_>)FtE`>$tn_B%Sk#cCxGz6L20Qr)-zx29sJSfX>H0QHG&=j8-c`35Kqmy?W7=cf>9XpM-b~w>mxfX z&!Fcp+AlGGoN_`QQzvx9j3;#Fz_@BMX(&@nX~`lKYkOrzw*LNCOcm-e?8@|S;w z?O63xcTqkR3Ne$SlfN?PObZAoDnE}2u6CsLA z@uvpGLU&2@WHB7Q0-<|gZeerE!RVZtxIE&My0vpQOG5M9X z6ZRgyWfbXJ`WkQ-2IeX*{V5zF@K5g5MF>VMYd^K-_o~}og`otCIvlyYiY_SrURNEJ zhVIp{c;A-we6I!~8Da$5cbf5WfocWyzS7K4K{Q*k`INp)-U(N*U%N?&gXp|2J9jxp zx&GfEfcMWB9zFqrv2M74g8IYyPWV%M{*ta6iTCrlW)|0)OgA3$+S5U|<&U>D#kttJ zz!Z4etir~B~nbdi{g!I%fWW#1?i_Lp{4>LH`agsGqS=1 z?nK%*dwpF^wE_D=!^hQ6VN^k(& zqhzYrB4ArI87)?f5x8o0wv%Ge*~OQJy}1bH|683%*%j3FQM5$U_n(IBfr_{YE}e{2RtKUtDf%oCY? zM(}D1)E1{ z`1)BqHJj?!{d3a8y}lhr+VH1PF))*QO)ndoMF%deE_q@7D6&BxcGKojU&C0QKIq!P zSnD@yfa0pb6rOv?5YBAasa&j431u~G`Jjw0n`sga)Wg|}!v9KA43gstgWKS?DNH2! z9nY}|^#N3_^u6ww+xUlGl7##ua|J78oG)uJO4B`;zOc)Kz6OMqsK#YcH9{a04v!Da}0+<4kTHuDCmAhDvhUAd!T;IjHJ5 zK?@BAD5L5f6v*X&Y{P=+{i`%^iN&qDV`0DKBg}aJL`d*O{+onELQM<8!+~v|=GeBh zybkB|$M=YK-5n!pHtgdlbBv;IR>xIRub)psmD<$etEBBPA_Kz5+l|Zo1^*e37{tsV z7TXt-dFS=l7tI!1B79a{JugstLIDLywB#$-1sAkIAx>P6`>dQ>%x|K~1FL7PNsVd< zbWVhIXBGDqSKpUS+DF)7D~`S>$7s?JCbfT@e-nt6sOm3oSk!RSxsPjCeu(sV^XlGP zvgFCKpV&;>RlItkQQat6ab7X6vA)G|UCpQo>OBXTsFMlq1=~bc>Yn|QoXQ`Of`egg z7d^QqOirE?TNQgf@uW_YlcFPK-vf*a56ND74x1two5|#}1U{C2K-^y6RXkK=g0v#v z-a7mCgYmj0m#{tL$L*$UJkhy|o-91}lS_*_#q(4q2BX8y%K(-c1%z&JLm~d6)F?8${=@o~lTC4~Js#=R)p&Kj$whB1R-xApCjG%tltX{zQ zs&@a5C+NO8cZRFBgc0IaE0=h~X|3&}i)OO1SQ-Ed9R) zKK%Gk;KPh!_^e1(eUqIfRB1MZ`LuO>{7IN=Ih&(TxG18Ny zVZD_;v3pjCITL6t= z(BZbY4;m(+6#o%zbY|_A)ihI2Q9eu?b z`0|#4_?8$NEJ-$b)YEVZHP(@4e-e;%%3<+#$vJE@P((!(v z{i_VvXk5jUS6!vfz9kiT%nf0=@Y=?BS6s?g&F{D^6j8@8J1h6;~-ar zga;^9VLX#^<=MYe!*m>*0VM)8vUAN^{TBi4aUJw3^c^fstl|_b;%>Q8@jE60LQ=^g zftf_jF@Cf4+#kY6#6IUIP+l(n1ThaFK+U1yQ@k1yG^J@$Uiu}8i~#caW(JT52uc^S z7%0iz#F6s{U5qXy0+c++&Ljpv(~}(RUCj+VbIG9l>;hh{5P&y`9Y_~}*@5DfB3dRI zwpbOcZZUCJIr?ed3AK-J?}KK344a2W&EAC~QXX6kL+H|kTWKGhAQU*2`DC6V;1LrH zE!U2He9(IC2S5%{95u~dK$Re%KK?fIO+XxX4S$0UV~Z5z!pK3*o2NBfVLNN5u1IXQ z@%2kuUsr!`8E{EpXOR^HJ@9t$3sTGygTmf^SDlIzbXLvPpM*N?P)!+FW9T|BMUJzo zu$=+qq>CP+hM(uQ-*g-S!+T@6j;SZi4on>{@=l=+BXX4c0I2Y~w8x6{^TNx1P9mw- zgF9L%G(yz!9ty>rd$QoSNZxv=;CnriwQ#>ZR$aIr%;OBY5OvRsnHNiGtkXz5zHw5z z{IhFEdkrHAd#Du(Isy+sT8;{dhI~tZFbc%)aVa! z0@6o|Mc&^ZVIjviltCOp3?)sr#Am>1qILLCCg?Tf+=R~Qi_pL*)QksBDUNDjGi7~D;eM;#LDqv3Sc>83RGa-k)vjJ1X>mx6wMP81CacR z6Tlu*XP|g3k3MiI>=`ke#JYu~1?YLQb1W6Dw?i+{q2S_D6;x^taW@%WV{fyBG3xyO zDT!uqv8z4iTu~L^$a5D?aBEAUbAt7`1ChR&-*-SZX=f_kL5ZaEho@%eKklk8epY#B z6%G73-iKhRL09#ccVa~0MsyRze%_4Kdmg%Y427MFQ84$tRH03S^ZPJbk1C!Gs)$Dj z-2b-vVEdt45S_I5p8D%d+G=nuM+Ia9kZOBjE}Sj&)2V>7q0vpJlR>{}T9PCS1BETA zfwo{wC>jbqq|@6h%3As9`w$2fICNIcj#yR9Q|bix8rr`B5L@ZKGCuczulbG~^#wb1Pfsw3(?L8zX6!(y>7kwu(ORK^=HVTzSMd4<`hFzs z`Fl?;B`qD*tl_=89iOo#7N`^b7DQup3Cw`^SB@b|W7&1|sz4pjMSNL9P=;K0guwpL zp_}JT6;@av^1+!JKkgZ)toz;c@wo6;h;65O@cx2PZXbd+2`9df@+Rgt^g{oH9{W76 z<*o-{$4q@WI_u2w1yvEdU2_8*2lH#fZ3MA^#eX;j^eITvyC#IDAmggRB)*Gi9$cxH z1nx+iafcQs{sNiCrD}3zz?9MAgPX^OWlJUF;FCo)>t^?oi!vmFjt5GG}yib7n+bFUj&lQnoaXQgsW`rf1Ul;$zaM*c z`fmcDnfe%+A2*`&)Cx%IK~)L$-o{BpuAceB6R-ev1PCfRr?*GBU}3mJX+bBaP#})4 z8HUr|{rjVR5Fw;L?rK)@f-~5j^HM#OC7P9ZUHnrlgo2Ts%?JgF)nV&-WlBEbnS1_v z&WEX+xyH)(BWQm~H-Rz+KLHwfS*{-nm@TUrRjo{qxm6zjXT2L2DVl>$&F#>3E7?R0 zAE`qrYe!;CzBX%}y7ChaVJcJ^YfF6i^iBY}vXe=NrG^{&e3>6^Emqz+1erv55Dvch zdZ7K`aJ2de=1?_w3!y}MS6*Z$h&ZeWGTD~a5#6Z{0hC^~nCt$=?2|$j>f%>Rt6-;~ z!>r-4fs?AzF#K&q>l@*cyQr6=%l__$SMT?2LKO_LVU9Qj^J76avTga696{sswHL0wOMg*<-Bd&^bcbBN+w#zlRC?eL7h4STiugi2XU{J45Z3 zb_>>z`M%}F29DI1VAs8CvPU?A_0tQ2ov{@&-$%;K z0Wr#@!IQW_#)QR$wPck_eu1!o4^Ge0WQWh`&A>;-#m0B3YzbJ@YXJ(dg0G+)gFX4& ztA~T8CGHwV+k1#ca`qCd6qsXP{0N1C>0VF@)}u_0r2*JjR^7IQ8p9>0R96Uyp#fHlW5wV3ah^j9(95mYB(bpNNF! z)8`sZDt0DM>j)TRSvstaA89gRmHfnjiHXoI-bfHJFZ3`^r}Y=`Qy131=RP5JopQpZ zDO+_$OO|Q_d~!tFe+<`oLtqEHf7Pb3BWQju7~&Fkn^<Hcc+_HiAxdyFYac-&rQ%9AaWBy){YG6&)?w|-$;LeWH_uOkeI6tuWqIT}+5C|m zLR<{>V9nsv&vdnTITO7|u4Yc*?Wq-b0Fnd|{FYrEjUy#AsCp8Pvwe{I>;fuTonDI# ze50lL`V;oQHy)#_o!IIJNHE|>6PJDRyo5`Rsjx&P^K|SnU*x_X&P8h7x?%kEOpoCG zk3Z*t{RD0=LC3T=;Cv~0DmZQ~ywL1Q&WM(h zrN0&!LOJVD8VB|u=9PCA4T>Q@EDvvjKNYpF?28oTqvQ*2(6HV>TbVg^qe$=tR-8*> zIfFOqKq^XSV>1@+=e9QH;yo zGidC8-L<*gh2g}`gR|H5F-T#E5UJvw_cLot=F-&IC;7C)smNUb_7mkrycop7n zy{e}>3);8gE>%nUzL0wfh{0J;06P~$YBRAf>`D|Ln24{tGZSG~ zJqK-aLLyMN+aY4&;3=3vykb5LKIFPPpXMmn^ki$_gWpv5(VTG*bIC$Q59@Qd)EpWz zP(h9iPxIWXN=VGmTvG9Ew~Iv+Tj7bfSCa^JYr86<;ol$;-cODkbS*4RLLXV4CVR{L zzB!f0c&N;)Zq!eHdq8KEDqF;0;nS%W$9qLoH4rn z`c3Lk_4T<%x5fD{TKC^+JyRdr1!%c&2B5kd$KEH(52wsXU}IMAmK1Nm;#JPSLq~K7 z!zyfSS|fa?@?5}xyoe?IJ(0N85gj@f* zH}+ZFYp6H@vap|MW?4E~T9AzbO%6pC2;yNHemnZJ`q3a?K|`L=WD2OW@njXrkI?O} zE1HH%vggUyN$&aUGnb(=jhGyG0X- zr262*zGNsI2#wfr!NO2SDu_d#dB#bD8R79@GRge~ z{WQtkG%HIk;2_@dOrRL+E0`#3a^+{ZfWCwjdjry}%ohpA@*@ZmvHfo0Te&0&KwQgO62~-1XyKrizY(+G+Ru+dfY)5=ENeK#YgqPbr+q0jVd>EdT~8dq z)Pk!K^$KPm8P;DSDwi4|R=#o|9;NLn;=Q*frZWk~mhQST+|n&lg=!+y9PtEO;OLc6 zY!uD$2AqnjT>WfQ3d(oE%_Te-Ce;E?#=!*>lc1k>Zc%2UVUTzU3I#U@YRGN2k>Ga=vw7l|#f?U0`7{5ayEvH86|jF!nSlQEf%jGRMcgX6Or%pK=KgIt4SAHIIb?gMKn9ISX{&mG;#|o#K zI~L%KCU}Qjet8yD!6|383}5T%8?w})bnYn5+8NggKU9S3p5sf{epM=V&@@-_3f>YM z-j}()&;KH;H z@AmO;CjQ6xn7!IRRa^)EAr<@$fL{OpC;ngkV$6IrUq$y?>s`k$sR&4rs%fG6hXgYKHRy??%e&fBF7t8{CS3{MquosL!!KyH^sklKGDw#e}H5z<@x%_2f&<>q~oPhZ3Yk)I#yqomsb@RRv?lmwF)`gVj-UZ(`7+_8G zAq~GDsQuIZPO!o7tb+&1pUANa=A3Y#Vu0A6QKwnCy9VaLEW49yiut;hY_^P#n7>ch zB^PI=&(027Q7&bmwpw{w&JK?#2N%#quzzELYHf^TE{4MiG!_~PZnC^mU`q-v;QYH7 zSoeDV@97bFuxMHYN_he7iI*=lpUsB;699I-*OBG|{+CJ>VhD}t*^dC{!o zE~u+%Sa2D4y|8W(RCT17uY53+1-~=LhK8aNsb{Kf(Mz=Zfyc$H<-iw*wf;=~4Xi z-h=K@pBpmS@^wVt{5QtWSdwF3Bz^*}t{0m&OYrlAk28Q*s2{2SJh{I3aej~InIrT5 z%zmz27aQ09^XiS|J%w|wB?1$6e|$#ub>kQD}MrSq+DBY(N!FHS-X+XZl~&3 zz~jEvl|xY z-U3JcLnDf2ZTSN{Q$rd!W;$&H@Lbte(8m2g!1eGwsr!K$rz-JeW^wGr{{4>e-G0W+SouCC1z^;#f1n^9a!=QsXn3sZXjOjai`d4`Of#*|# z{W#fWO9JK?_jsyT*8KstW_W>}xRShpu#?{&I9=YFeSO14H|e9lcYd^9fAH^3Zo&5t zfj3)sHa-P)Zq4qNT&`gBIe&a#qV*HjRD~O$d&?isNtojE`F&8L%I}uah}5Z}kM{qZ zsdnc{{u=Sg6`R(9COj&Dn<5_KNi?%dUSuLvA*s6y&jMR zxa3=7nX}b*{jFDmOgXn?tX{JAL$CS04p&CtsVC_V^;hXD{;_|3#Bj9$lWYV75O})! KxvX*C2*}uK_xk6tm$q?dE;$69Ng;4gzGnFe> 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 US_x~@2f&x^H3O|84TrG*0gSP~VgLXD literal 0 HcmV?d00001 diff --git a/packages/E2ETest/README.md b/packages/E2ETest/README.md index 0cf38b0e805..9d4b5ead9fe 100644 --- a/packages/E2ETest/README.md +++ b/packages/E2ETest/README.md @@ -1,3 +1,5 @@ # E2ETest project -This package is not published, and is just used to verify a standalone app \ No newline at end of file +This package is not published, and is just used to verify a standalone app + +For information on how to run and debug this project, see [e2e-testing](https://github.com/microsoft/react-native-windows/blob/master/docs/e2e-testing.md). \ No newline at end of file From 525bbe2667b4ed5f98d5fdd937768f24a84e3548 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Wed, 13 May 2020 15:46:51 -0700 Subject: [PATCH 097/209] Update rnw-dependencies (#4894) * don't exit the powershell session and pause for keyboard input if interactive * Change files --- ...tive-windows-2020-05-13-14-16-07-rnw-dep-dontexit.json | 8 ++++++++ vnext/Scripts/rnw-dependencies.ps1 | 8 +++++--- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 change/react-native-windows-2020-05-13-14-16-07-rnw-dep-dontexit.json diff --git a/change/react-native-windows-2020-05-13-14-16-07-rnw-dep-dontexit.json b/change/react-native-windows-2020-05-13-14-16-07-rnw-dep-dontexit.json new file mode 100644 index 00000000000..bf1bca20445 --- /dev/null +++ b/change/react-native-windows-2020-05-13-14-16-07-rnw-dep-dontexit.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "don't exit the powershell session and pause for keyboard input if interactive", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-13T21:16:07.200Z" +} diff --git a/vnext/Scripts/rnw-dependencies.ps1 b/vnext/Scripts/rnw-dependencies.ps1 index d91ee41d40d..c274c09006f 100644 --- a/vnext/Scripts/rnw-dependencies.ps1 +++ b/vnext/Scripts/rnw-dependencies.ps1 @@ -145,9 +145,11 @@ foreach ($req in $requirements) } if ($NeedsRerun) { - Write-Output "Some dependencies are not met. Re-run with -Install to install them."; - exit 1; + Write-Error "Some dependencies are not met. Re-run with -Install to install them."; + if (!$NoPrompt) { + [System.Console]::ReadKey(); + } + throw; } else { Write-Output "All mandatory requirements met"; - exit 0; } From 78492792b5b6f9e481a2959bb4e15e21d323e730 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Thu, 14 May 2020 00:04:37 +0000 Subject: [PATCH 098/209] applying package updates ***NO_CI*** --- ...-2020-05-11-17-22-16-rnw-dependencies.json | 8 ---- ...indows-2020-05-12-11-18-16-MS_UIQueue.json | 8 ---- ...-2020-05-12-18-57-59-UnsafePropertyId.json | 8 ---- ...dows-2020-05-13-12-47-43-tabfocus-fix.json | 8 ---- ...-2020-05-13-14-16-07-rnw-dep-dontexit.json | 8 ---- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- vnext/CHANGELOG.json | 39 +++++++++++++++++++ vnext/CHANGELOG.md | 14 ++++++- vnext/package.json | 2 +- 11 files changed, 56 insertions(+), 45 deletions(-) delete mode 100644 change/react-native-windows-2020-05-11-17-22-16-rnw-dependencies.json delete mode 100644 change/react-native-windows-2020-05-12-11-18-16-MS_UIQueue.json delete mode 100644 change/react-native-windows-2020-05-12-18-57-59-UnsafePropertyId.json delete mode 100644 change/react-native-windows-2020-05-13-12-47-43-tabfocus-fix.json delete mode 100644 change/react-native-windows-2020-05-13-14-16-07-rnw-dep-dontexit.json diff --git a/change/react-native-windows-2020-05-11-17-22-16-rnw-dependencies.json b/change/react-native-windows-2020-05-11-17-22-16-rnw-dependencies.json deleted file mode 100644 index c4d7af43b9f..00000000000 --- a/change/react-native-windows-2020-05-11-17-22-16-rnw-dependencies.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "add rnw-dependencies.ps1", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-12T00:22:16.000Z" -} diff --git a/change/react-native-windows-2020-05-12-11-18-16-MS_UIQueue.json b/change/react-native-windows-2020-05-12-11-18-16-MS_UIQueue.json deleted file mode 100644 index aeec541b06c..00000000000 --- a/change/react-native-windows-2020-05-12-11-18-16-MS_UIQueue.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Use DispatcherQueue instead of CoreDispatcher for Mso::DispatchQueue", - "packageName": "react-native-windows", - "email": "vmorozov@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-12T18:18:15.956Z" -} diff --git a/change/react-native-windows-2020-05-12-18-57-59-UnsafePropertyId.json b/change/react-native-windows-2020-05-12-18-57-59-UnsafePropertyId.json deleted file mode 100644 index 2841e2d184d..00000000000 --- a/change/react-native-windows-2020-05-12-18-57-59-UnsafePropertyId.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Allow storing non-WinRT types in ReactPropertyBag", - "packageName": "react-native-windows", - "email": "vmorozov@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-13T01:57:59.370Z" -} diff --git a/change/react-native-windows-2020-05-13-12-47-43-tabfocus-fix.json b/change/react-native-windows-2020-05-13-12-47-43-tabfocus-fix.json deleted file mode 100644 index 3832af20367..00000000000 --- a/change/react-native-windows-2020-05-13-12-47-43-tabfocus-fix.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "revert dfc57fcf2504f57baab20f550b36a618eaa99e56", - "packageName": "react-native-windows", - "email": "kmelmon@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-13T19:47:43.325Z" -} diff --git a/change/react-native-windows-2020-05-13-14-16-07-rnw-dep-dontexit.json b/change/react-native-windows-2020-05-13-14-16-07-rnw-dep-dontexit.json deleted file mode 100644 index bf1bca20445..00000000000 --- a/change/react-native-windows-2020-05-13-14-16-07-rnw-dep-dontexit.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "don't exit the powershell session and pause for keyboard input if interactive", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-13T21:16:07.200Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index c25b4a7209c..e323ad48961 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.65" + "react-native-windows": "0.0.0-master.66" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 9192adc47a2..84d9aed98f0 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.65" + "react-native-windows": "0.0.0-master.66" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index 64b1cc263d6..cbbc35ea54a 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.65" + "react-native-windows": "0.0.0-master.66" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index f5bd3760b42..0c2b77d662f 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,45 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Thu, 14 May 2020 00:04:37 GMT", + "tag": "react-native-windows_v0.0.0-master.66", + "version": "0.0.0-master.66", + "comments": { + "prerelease": [ + { + "comment": "add rnw-dependencies.ps1", + "author": "asklar@microsoft.com", + "commit": "64aede7aedb329e97df0f6d4f8c946e6454b573c", + "package": "react-native-windows" + }, + { + "comment": "Use DispatcherQueue instead of CoreDispatcher for Mso::DispatchQueue", + "author": "vmorozov@microsoft.com", + "commit": "e6337047f6085b32951eeff4f5063d21e5c7da2f", + "package": "react-native-windows" + }, + { + "comment": "Allow storing non-WinRT types in ReactPropertyBag", + "author": "vmorozov@microsoft.com", + "commit": "d1abb363bfcd8dc7f84fec768f32525002109919", + "package": "react-native-windows" + }, + { + "comment": "revert dfc57fcf2504f57baab20f550b36a618eaa99e56", + "author": "kmelmon@microsoft.com", + "commit": "904f7c0080511f264274b1db48b0774f813cb163", + "package": "react-native-windows" + }, + { + "comment": "don't exit the powershell session and pause for keyboard input if interactive", + "author": "asklar@microsoft.com", + "commit": "525bbe2667b4ed5f98d5fdd937768f24a84e3548", + "package": "react-native-windows" + } + ] + } + }, { "date": "Wed, 13 May 2020 00:04:21 GMT", "tag": "react-native-windows_v0.0.0-master.65", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 2ebe842eed9..bf33c0136ab 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,21 @@ # Change Log - react-native-windows -This log was last generated on Wed, 13 May 2020 00:04:21 GMT and should not be manually modified. +This log was last generated on Thu, 14 May 2020 00:04:37 GMT and should not be manually modified. +## 0.0.0-master.66 + +Thu, 14 May 2020 00:04:37 GMT + +### Changes + +- add rnw-dependencies.ps1 (asklar@microsoft.com) +- Use DispatcherQueue instead of CoreDispatcher for Mso::DispatchQueue (vmorozov@microsoft.com) +- Allow storing non-WinRT types in ReactPropertyBag (vmorozov@microsoft.com) +- revert dfc57fcf2504f57baab20f550b36a618eaa99e56 (kmelmon@microsoft.com) +- don't exit the powershell session and pause for keyboard input if interactive (asklar@microsoft.com) + ## 0.0.0-master.65 Wed, 13 May 2020 00:04:21 GMT diff --git a/vnext/package.json b/vnext/package.json index e8d93f226d0..615573c49b6 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.65", + "version": "0.0.0-master.66", "license": "MIT", "repository": { "type": "git", From 579a25b0079e62375e2ab94d4f8680e14d19c0c8 Mon Sep 17 00:00:00 2001 From: Patrick Boyd Date: Wed, 13 May 2020 17:32:36 -0700 Subject: [PATCH 099/209] ViewWin32 Accessibility: labeledBy, describedBy (#4883) * Initial steps for accessibilityLabeledBy as a RefObject * steps towards function component ViewWin32 * Add focus function to the reference while maintaining ref-erability of the forwarded ref * use setAndForwardRef to avoid awkward ref assignment * Disambiguate ref being used for findNodeHandle * Remove stray submodules added on accident. * Restrict new accessibility props to win32; if UWP adds support later it can be shared * Move new accessibility props to the win32-specific group * Change files * Remove accessibilityDescription, improperly added * Update ViewWin32 api md --- ...05-12-21-44-51-accessibilityLabeledBy.json | 8 ++ .../etc/react-native-win32.api.md | 15 +-- packages/react-native-win32/package.json | 2 +- .../View/ReactNativeViewViewConfig.win32.js | 2 + .../Components/View/Tests/ViewWin32Test.tsx | 8 +- .../Components/View/ViewWin32.Props.ts | 11 +- .../Libraries/Components/View/ViewWin32.tsx | 101 ++++++++++++++---- 7 files changed, 115 insertions(+), 32 deletions(-) create mode 100644 change/@office-iss-react-native-win32-2020-05-12-21-44-51-accessibilityLabeledBy.json diff --git a/change/@office-iss-react-native-win32-2020-05-12-21-44-51-accessibilityLabeledBy.json b/change/@office-iss-react-native-win32-2020-05-12-21-44-51-accessibilityLabeledBy.json new file mode 100644 index 00000000000..ca92f8b3916 --- /dev/null +++ b/change/@office-iss-react-native-win32-2020-05-12-21-44-51-accessibilityLabeledBy.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Add win32-specific accessibility props Description, DescribedBy, and LabeledBy", + "packageName": "@office-iss/react-native-win32", + "email": "ppatboyd@outlook.com", + "dependentChangeType": "patch", + "date": "2020-05-13T04:44:51.679Z" +} diff --git a/packages/react-native-win32/etc/react-native-win32.api.md b/packages/react-native-win32/etc/react-native-win32.api.md index 656bdd6c40c..e65a70401da 100644 --- a/packages/react-native-win32/etc/react-native-win32.api.md +++ b/packages/react-native-win32/etc/react-native-win32.api.md @@ -10,6 +10,7 @@ import { NativeSyntheticEvent } from 'react-native'; import * as React_2 from 'react'; import RN = require('react-native'); import { StyleProp } from 'react-native'; +import { View } from 'react-native'; import { ViewProps } from 'react-native'; import { ViewStyle } from 'react-native'; @@ -49,6 +50,8 @@ export type BasePropsWin32 = { accessibilityRole?: RN.AccessibilityRole | ARIARole; accessibilityStates?: AccessibilityStates[]; accessibilityActions?: ReadonlyArray; + accessibilityDescribedBy?: React_2.RefObject; + accessibilityLabeledBy?: React_2.RefObject; }; // Warning: (ae-forgotten-export) The symbol "IButtonWin32State" needs to be exported by the entry point typings-index.d.ts @@ -440,12 +443,12 @@ export class TouchableWin32 extends React_2.Component = Pick> & Pick; // @public (undocumented) -export class ViewWin32 extends React_2.Component implements IViewWin32 { - constructor(props: IViewWin32Props); - focus(): void; - // (undocumented) - render(): JSX.Element; -} +export const ViewWin32: React_2.ForwardRefExoticComponent>; + +// Warning: (ae-forgotten-export) The symbol "ViewWin32Type" needs to be exported by the entry point typings-index.d.ts +// +// @public (undocumented) +export type ViewWin32 = ViewWin32Type; // @public (undocumented) export type ViewWin32OmitTypes = RN.ViewPropsAndroid & RN.ViewPropsIOS & RN.AccessibilityPropsAndroid & Omit_2 & OmittedAccessibilityPropsWin32; diff --git a/packages/react-native-win32/package.json b/packages/react-native-win32/package.json index 2344d647958..25955c93fb8 100644 --- a/packages/react-native-win32/package.json +++ b/packages/react-native-win32/package.json @@ -14,7 +14,7 @@ "lint:fix": "just-scripts lint:fix", "lint": "just-scripts lint", "api": "just-scripts api", - "run-win32-dev-web": "rex-win32 --bundle RNTester --component RNTesterApp --basePath ./dist/win32/dev --useWebDebugger", + "run-win32-dev-web": "rex-win32 --bundle RNTester --component RNTesterApp --basePath ./dist/win32/dev --useDevMain --useWebDebugger", "run-win32-devmain": "rex-win32 --bundle RNTester --component RNTesterApp --basePath ./dist/win32/dev --useDevMain", "run-win32": "rex-win32 --bundle RNTester --component RNTesterApp --basePath ./dist/win32/dev", "start": "react-native start", diff --git a/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewViewConfig.win32.js b/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewViewConfig.win32.js index 0d58f3aaefe..54cc446d5ed 100644 --- a/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewViewConfig.win32.js +++ b/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewViewConfig.win32.js @@ -375,6 +375,8 @@ const ReactNativeViewConfig = { onMouseLeave: true, tooltip: true, cursor: true, + accessibilityDescribedBy: true, + accessibilityLabeledBy: true, // Windows] }, }; diff --git a/packages/react-native-win32/src/Libraries/Components/View/Tests/ViewWin32Test.tsx b/packages/react-native-win32/src/Libraries/Components/View/Tests/ViewWin32Test.tsx index 748cf3b6485..a66177d5905 100644 --- a/packages/react-native-win32/src/Libraries/Components/View/Tests/ViewWin32Test.tsx +++ b/packages/react-native-win32/src/Libraries/Components/View/Tests/ViewWin32Test.tsx @@ -31,17 +31,22 @@ interface IFocusableComponentState { class FocusMoverTestComponent extends React.Component<{}, IFocusableComponentState> { private _focusTarget: ViewWin32 = null; + private _labeledBy: React.RefObject; + public constructor(props) { super(props); this.state = { hasFocus: false, }; + this._labeledBy = React.createRef(); } public render() { return ( + + - + {this.state.hasFocus ? 'Focus: Yes' : 'Focus: No'} + ); } diff --git a/packages/react-native-win32/src/Libraries/Components/View/ViewWin32.Props.ts b/packages/react-native-win32/src/Libraries/Components/View/ViewWin32.Props.ts index 7c02b5c8092..61468c94549 100644 --- a/packages/react-native-win32/src/Libraries/Components/View/ViewWin32.Props.ts +++ b/packages/react-native-win32/src/Libraries/Components/View/ViewWin32.Props.ts @@ -110,7 +110,7 @@ export type AccessibilityActionName = export type Cursor = | 'auto' | 'pointer' - + export type AccessibilityActionInfo = Readonly<{ name: AccessibilityActionName; label?: string; @@ -148,6 +148,15 @@ export type BasePropsWin32 = { accessibilityRole?: RN.AccessibilityRole | ARIARole; accessibilityStates?: AccessibilityStates[]; accessibilityActions?: ReadonlyArray; + + /** + * Windows Accessibility extensions for allowing other DOM elements to label or describe a given element. + * + * Defined as a reference to another DOM element inheriting from the primary base classes of React-Native elements. + * The reference will be converted to a native reference (tag) before passing to the native platform. + */ + accessibilityDescribedBy?: React.RefObject; + accessibilityLabeledBy?: React.RefObject; }; export type ViewWin32OmitTypes = RN.ViewPropsAndroid & diff --git a/packages/react-native-win32/src/Libraries/Components/View/ViewWin32.tsx b/packages/react-native-win32/src/Libraries/Components/View/ViewWin32.tsx index 5ef8783b2b8..946699fe553 100644 --- a/packages/react-native-win32/src/Libraries/Components/View/ViewWin32.tsx +++ b/packages/react-native-win32/src/Libraries/Components/View/ViewWin32.tsx @@ -6,42 +6,97 @@ import * as React from 'react'; import RN = require('react-native'); -import { NativeModules, findNodeHandle } from 'react-native'; -import { IViewWin32Props, IViewWin32, UseFrom } from './ViewWin32.Props'; +import { View, findNodeHandle, NativeModules } from 'react-native'; +import { IViewWin32Props, UseFrom } from './ViewWin32.Props'; +const setAndForwardRef = require('../../Utilities/setAndForwardRef'); /** * Basic View component with additional Win32 specific functionality */ -type InnerViewProps = UseFrom & +type InnerViewWin32Props = UseFrom & UseFrom & UseFrom & UseFrom; -export class ViewWin32 extends React.Component implements IViewWin32 { - constructor(props: IViewWin32Props) { - super(props); - } +type ViewWin32Type = React.ForwardRefExoticComponent< +IViewWin32Props & React.RefAttributes +> & + View; - public render() { +export const ViewWin32 = React.forwardRef( + (props: IViewWin32Props, ref: React.Ref) => { + + /** + * Check for raw text in the DOM. + */ if (__DEV__) { - React.Children.toArray(this.props.children).forEach(item => { + React.Children.toArray(props.children).forEach(item => { if (typeof item === 'string') { console.error(`Unexpected text node: ${item}. A text node cannot be a child of a .`); } }); } - return ; - } - - /** - * Moves focus to this view - */ - public focus() { - NativeModules.UIManager.dispatchViewManagerCommand( - findNodeHandle(this), - NativeModules.UIManager.getViewManagerConfig('RCTView').Commands.focus, - null - ); - } -} + + /** + * Process accessibility refs into node handles after initial DOM render, before sent across the bridge. + * useLayoutEffect will invalidate the render to assess the ref-based accessibility properties. + */ + + const [labeledByTarget, setLabeledByTarget] = React.useState(null); + const [describedByTarget, setDescribedByTarget] = React.useState(null); + const {accessibilityLabeledBy, accessibilityDescribedBy, ...rest} = props; + React.useLayoutEffect(() => { + if (accessibilityLabeledBy !== undefined && accessibilityLabeledBy?.current !== null) + { + setLabeledByTarget(findNodeHandle(accessibilityLabeledBy.current as + | null + | number + | React.Component + | React.ComponentClass)); + } + + if (accessibilityDescribedBy !== undefined && accessibilityDescribedBy?.current !== null) + { + setDescribedByTarget(findNodeHandle(accessibilityDescribedBy.current as + | null + | number + | React.Component + | React.ComponentClass)); + } + }, [accessibilityLabeledBy, accessibilityDescribedBy]); + + /** + * Set up the forwarding ref to enable adding the focus method. + */ + let focusRef = React.useRef(); + + const _setNativeRef = setAndForwardRef({ + getForwardedRef: () => ref, + setLocalRef: localRef => { + focusRef.current = localRef; + + /** + * Add focus() as a callable function to the forwarded reference. + */ + if (localRef) + { + localRef.focus = () => { + NativeModules.UIManager.dispatchViewManagerCommand( + findNodeHandle(localRef), + NativeModules.UIManager.getViewManagerConfig('RCTView').Commands.focus, + null + ); + }; + } + }, + }); + + return ; + }); + +export type ViewWin32 = ViewWin32Type; From a8cf72c8ce76c2b140c860990a9cdfd753085325 Mon Sep 17 00:00:00 2001 From: Kai Guo Date: Wed, 13 May 2020 17:57:40 -0700 Subject: [PATCH 100/209] Remove unused life cycle event callbacks in ReactNativeHost (#4891) * Hook up life cycle events in ReactNativeHost * Change files * Remove life cycle events in ReactnativeHost * Update change file --- ...-53-42-remove-unused-lifecycle-events.json | 8 +++ .../ReactApplicationDelegate.cpp | 6 -- .../Microsoft.ReactNative/ReactNativeHost.cpp | 69 ------------------- vnext/Microsoft.ReactNative/ReactNativeHost.h | 6 -- .../Microsoft.ReactNative/ReactNativeHost.idl | 6 -- 5 files changed, 8 insertions(+), 87 deletions(-) create mode 100644 change/react-native-windows-2020-05-13-12-53-42-remove-unused-lifecycle-events.json diff --git a/change/react-native-windows-2020-05-13-12-53-42-remove-unused-lifecycle-events.json b/change/react-native-windows-2020-05-13-12-53-42-remove-unused-lifecycle-events.json new file mode 100644 index 00000000000..11b48218652 --- /dev/null +++ b/change/react-native-windows-2020-05-13-12-53-42-remove-unused-lifecycle-events.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Remove unused lifecycle events in ReactNativeHost", + "packageName": "react-native-windows", + "email": "kaigu@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-13T19:53:42.358Z" +} diff --git a/vnext/Microsoft.ReactNative/ReactApplicationDelegate.cpp b/vnext/Microsoft.ReactNative/ReactApplicationDelegate.cpp index 4413345823c..fc16f11cd2b 100644 --- a/vnext/Microsoft.ReactNative/ReactApplicationDelegate.cpp +++ b/vnext/Microsoft.ReactNative/ReactApplicationDelegate.cpp @@ -83,7 +83,6 @@ void ReactApplicationDelegate::OnActivated(IActivatedEventArgs const &args) noex // Create the root view for the ReactNative app UIElement ReactApplicationDelegate::OnCreate(hstring const &arguments) noexcept { auto host = m_reactApplication.Host(); - host.OnResume([=]() { m_application.Exit(); }); ApplyArguments(host, arguments.c_str()); @@ -106,28 +105,23 @@ UIElement ReactApplicationDelegate::OnCreate(hstring const &arguments) noexcept } void ReactApplicationDelegate::OnResuming(IInspectable const & /*sender*/, IInspectable const & /*args*/) noexcept { - m_reactApplication.Host().OnResume([=]() { m_application.Exit(); }); - OutputDebugStringW(L"ReactApplicationDelegate::OnResuming"); } void ReactApplicationDelegate::OnSuspending(IInspectable const & /*sender*/, IInspectable const & /*args*/) noexcept { OutputDebugStringW(L"ReactApplicationDelegate::OnSuspending"); - m_reactApplication.Host().OnSuspend(); } void ReactApplicationDelegate::OnLeavingBackground( IInspectable const & /*sender*/, LeavingBackgroundEventArgs const & /*args*/) noexcept { OutputDebugStringW(L"ReactApplicationDelegate::OnLeavingBackground"); - m_reactApplication.Host().OnLeavingBackground(); } void ReactApplicationDelegate::OnEnteredBackground( IInspectable const & /*sender*/, EnteredBackgroundEventArgs const & /*args*/) noexcept { OutputDebugStringW(L"ReactApplicationDelegate::OnEnteredBackground"); - m_reactApplication.Host().OnEnteredBackground(); } } // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp index a7a1c9f3c99..ee972fdebac 100644 --- a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp +++ b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp @@ -122,73 +122,4 @@ Mso::React::IReactHost *ReactNativeHost::ReactHost() noexcept { return m_reactHost.Get(); } -// TODO: Create a LifeCycleStateMachine in constructor to raise events in response -// to events from the application and associate it with the ReactContext. -// Define the ILifecycleEventListener and add support to ReactContext to -// register a lifecycle listener. Define the IBackgroundEventListener and add -// support to ReactContext to register modules as background event listeners. - -void ReactNativeHost::OnSuspend() noexcept { - OutputDebugStringW(L"TODO: ReactNativeHost::OnSuspend not implemented"); - - // DispatcherHelpers.AssertOnDispatcher(); - - //_defaultBackButtonHandler = null; - //_suspendCancellation?.Dispose(); - - // if (_useDeveloperSupport) - //{ - // _devSupportManager.IsEnabled = false; - //} - - //_lifecycleStateMachine.OnSuspend(); -} - -void ReactNativeHost::OnEnteredBackground() noexcept { - OutputDebugStringW(L"TODO: ReactNativeHost::OnEnteredBackground not implemented"); - - // DispatcherHelpers.AssertOnDispatcher(); - //_lifecycleStateMachine.OnEnteredBackground(); -} - -void ReactNativeHost::OnLeavingBackground() noexcept { - OutputDebugStringW(L"TODO: ReactNativeHost::OnLeavingBackground not implemented"); - - // DispatcherHelpers.AssertOnDispatcher(); - //_lifecycleStateMachine.OnLeavingBackground(); -} - -void ReactNativeHost::OnResume(OnResumeAction const & /*action*/) noexcept { - OutputDebugStringW(L"TODO: ReactNativeHost::OnResume not implemented"); - - // see the ReactInstanceManager.cs from the C# implementation - - //_defaultBackButtonHandler = onBackPressed; - //_suspendCancellation = new CancellationDisposable(); - - // if (_useDeveloperSupport) - //{ - // _devSupportManager.IsEnabled = true; - //} - - //_lifecycleStateMachine.OnResume(); -} - -void ReactNativeHost::OnBackPressed() noexcept { - OutputDebugStringW(L"TODO: ReactNativeHost::OnBackPressed not implemented"); - - // DispatcherHelpers.AssertOnDispatcher(); - // var reactContext = _currentReactContext; - // if (reactContext == null) - //{ - // RnLog.Warn(ReactConstants.RNW, $"ReactInstanceManager: OnBackPressed: - // Instance detached from instance manager."); - // InvokeDefaultOnBackPressed(); - //} - // else - //{ - // reactContext.GetNativeModule().EmitHardwareBackPressed(); - //} -} - } // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Microsoft.ReactNative/ReactNativeHost.h b/vnext/Microsoft.ReactNative/ReactNativeHost.h index 1f1eeccdc52..0fb6ea30948 100644 --- a/vnext/Microsoft.ReactNative/ReactNativeHost.h +++ b/vnext/Microsoft.ReactNative/ReactNativeHost.h @@ -28,12 +28,6 @@ struct ReactNativeHost : ReactNativeHostT { void ReloadInstance() noexcept; - void OnSuspend() noexcept; - void OnEnteredBackground() noexcept; - void OnLeavingBackground() noexcept; - void OnResume(OnResumeAction const &action) noexcept; - void OnBackPressed() noexcept; - public: Mso::React::IReactHost *ReactHost() noexcept; diff --git a/vnext/Microsoft.ReactNative/ReactNativeHost.idl b/vnext/Microsoft.ReactNative/ReactNativeHost.idl index 6c8d1231739..b170f18e0d8 100644 --- a/vnext/Microsoft.ReactNative/ReactNativeHost.idl +++ b/vnext/Microsoft.ReactNative/ReactNativeHost.idl @@ -18,11 +18,5 @@ namespace Microsoft.ReactNative { ReactInstanceSettings InstanceSettings { get; set; }; void ReloadInstance(); - - void OnSuspend(); - void OnEnteredBackground(); - void OnLeavingBackground(); - void OnResume(OnResumeAction action); - void OnBackPressed(); } } // namespace Microsoft.ReactNative From f6f43e1d51a67cbe27cab77684bab6cce3869c03 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 13 May 2020 18:37:05 -0700 Subject: [PATCH 101/209] Reduce PCH Sizes (#4886) * Reduce PCH Sizes Fixes #4652 (hopefully) Many users have reported being unable to build do to OOM issues when compiling their PCH. Preferring a 64-bit toolset does not seem to help the issue (PreferredToolArchitecture was already x64 on my local installation). This change instead reduces PCH size to attempt to mitigate the issue. This should also ease complaints around disk space usage. We include the STL, winrt foundation, and `Windows.UI.Xaml`. We do not include the commonly used `Windows.UI.Xaml.Controls` since it ends up eating a whopping 400MB in our PCH. We see a reduction from the Microsoft.ReactNative PCH of 1.55GB to 925MB. Build time for the SampleApps solution sees a slight increase in build time from 2m30s to 3m on my machine. PCH sizes are also reduced for ReactUwp (build in Unviersal Solution) abd Microsoft.ReactNative integration Tests. PCH sizes for the template seem potentially chunky, but are less large than our others were and are user editable which lowers impact. Valdiated we can build the universal solution and WINUI3 Playground. Will rely on CI for the rest. Not attmepting to change how we're handling global namespces in this change. That work is tracked by #4841. * Change files * Fix Definition Comments * Fix Non-WinUI Playground * Fix merge issue --- ...ndows-2020-05-13-03-45-39-smaller-pch.json | 8 +++ packages/playground/windows/playground/pch.h | 4 ++ .../CppWinRTIncludes.h | 70 ------------------- .../Microsoft.ReactNative.Cxx.vcxitems | 17 +++++ .../UI.Composition.Effects.h | 10 +++ .../UI.Composition.h | 10 +++ vnext/Microsoft.ReactNative.Cxx/UI.Input.h | 10 +++ vnext/Microsoft.ReactNative.Cxx/UI.Popups.h | 10 +++ vnext/Microsoft.ReactNative.Cxx/UI.Text.h | 10 +++ .../UI.Xaml.Automation.Peers.h | 10 +++ .../UI.Xaml.Automation.h | 10 +++ .../UI.Xaml.Controls.Primitives.h | 10 +++ .../UI.Xaml.Controls.h | 10 +++ .../UI.Xaml.Documents.h | 10 +++ .../Microsoft.ReactNative.Cxx/UI.Xaml.Input.h | 10 +++ .../UI.Xaml.Markup.h | 10 +++ .../UI.Xaml.Media.Imaging.h | 10 +++ .../UI.Xaml.Media.Media3D.h | 10 +++ .../Microsoft.ReactNative.Cxx/UI.Xaml.Media.h | 10 +++ .../UI.Xaml.Navigation.h | 10 +++ .../UI.Xaml.Shapes.h | 10 +++ .../ReactNativeHostTests.cpp | 1 + .../ReactApplication.cpp | 3 + vnext/Microsoft.ReactNative/RedBox.cpp | 7 ++ .../Views/ReactRootControl.cpp | 7 +- vnext/ReactUWP/ABI/ReactControl_rt.h | 1 - vnext/ReactUWP/Base/UwpReactInstance.cpp | 1 + vnext/ReactUWP/Modules/AlertModuleUwp.cpp | 2 + .../Modules/Animated/AdditionAnimatedNode.cpp | 1 + .../Modules/Animated/AnimationDriver.cpp | 1 + .../Modules/Animated/ValueAnimatedNode.h | 1 + vnext/ReactUWP/Modules/AppearanceModule.h | 2 + .../Modules/ImageViewManagerModule.cpp | 10 +-- vnext/ReactUWP/Modules/NativeUIManager.cpp | 3 + vnext/ReactUWP/Modules/TimingModule.cpp | 1 + vnext/ReactUWP/Pch/pch.h | 6 -- .../Polyester/ButtonContentViewManager.cpp | 1 + .../ReactUWP/Polyester/ButtonViewManager.cpp | 2 + .../Polyester/ContentControlViewManager.cpp | 1 + .../Polyester/HyperlinkViewManager.cpp | 2 + vnext/ReactUWP/Polyester/IconViewManager.cpp | 1 + vnext/ReactUWP/Utils/AccessibilityUtils.cpp | 4 +- vnext/ReactUWP/Utils/Helpers.cpp | 1 + vnext/ReactUWP/Utils/ValueUtils.cpp | 1 + .../Views/ActivityIndicatorViewManager.cpp | 1 + vnext/ReactUWP/Views/CheckboxViewManager.cpp | 2 + vnext/ReactUWP/Views/ControlViewManager.cpp | 2 + .../ReactUWP/Views/DatePickerViewManager.cpp | 1 + .../ReactUWP/Views/DynamicAutomationPeer.cpp | 2 + .../Views/DynamicAutomationProperties.cpp | 2 + .../Views/ExpressionAnimationStore.cpp | 2 + vnext/ReactUWP/Views/FlyoutViewManager.cpp | 4 ++ .../Views/FrameworkElementViewManager.cpp | 3 +- .../Microsoft.UI.Composition.Effects_Impl.h | 1 - vnext/ReactUWP/Views/Image/ReactImage.cpp | 8 +-- vnext/ReactUWP/Views/Image/ReactImage.h | 3 +- .../ReactUWP/Views/Image/ReactImageBrush.cpp | 3 +- vnext/ReactUWP/Views/Image/ReactImageBrush.h | 1 + .../Impl/ScrollViewUWPImplementation.cpp | 1 + .../Views/Impl/ScrollViewUWPImplementation.h | 1 - .../Impl/SnapPointManagingContentControl.h | 6 +- vnext/ReactUWP/Views/KeyboardEventHandler.cpp | 1 + vnext/ReactUWP/Views/PickerViewManager.cpp | 3 + vnext/ReactUWP/Views/PopupViewManager.cpp | 4 ++ vnext/ReactUWP/Views/RawTextViewManager.cpp | 2 + vnext/ReactUWP/Views/ReactControl.cpp | 5 +- .../ReactUWP/Views/RefreshControlManager.cpp | 1 + vnext/ReactUWP/Views/RootViewManager.cpp | 1 + vnext/ReactUWP/Views/SIPEventHandler.cpp | 2 +- vnext/ReactUWP/Views/ShadowNodeBase.cpp | 1 + vnext/ReactUWP/Views/SliderViewManager.cpp | 3 + vnext/ReactUWP/Views/SwitchViewManager.cpp | 2 + vnext/ReactUWP/Views/TextInputViewManager.cpp | 4 +- vnext/ReactUWP/Views/TextViewManager.cpp | 4 ++ vnext/ReactUWP/Views/TouchEventHandler.cpp | 3 + vnext/ReactUWP/Views/ViewPanel.cpp | 2 + .../ReactUWP/Views/VirtualTextViewManager.cpp | 4 +- .../UniversalTestInstance.cpp | 2 +- .../UniversalTestRunner.cpp | 2 +- vnext/include/ReactUWP/Utils/PropertyUtils.h | 1 + .../ReactUWP/Utils/ResourceBrushUtils.h | 1 + 81 files changed, 312 insertions(+), 108 deletions(-) create mode 100644 change/react-native-windows-2020-05-13-03-45-39-smaller-pch.json create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Composition.Effects.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Composition.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Input.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Popups.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Text.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Automation.Peers.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Automation.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Controls.Primitives.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Controls.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Documents.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Input.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Markup.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.Imaging.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.Media3D.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Navigation.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Shapes.h diff --git a/change/react-native-windows-2020-05-13-03-45-39-smaller-pch.json b/change/react-native-windows-2020-05-13-03-45-39-smaller-pch.json new file mode 100644 index 00000000000..73f7f872090 --- /dev/null +++ b/change/react-native-windows-2020-05-13-03-45-39-smaller-pch.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Reduce PCH Sizes", + "packageName": "react-native-windows", + "email": "ngerlem@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-13T10:45:39.135Z" +} diff --git a/packages/playground/windows/playground/pch.h b/packages/playground/windows/playground/pch.h index 28f6bb4ffec..a29fcd13fd1 100644 --- a/packages/playground/windows/playground/pch.h +++ b/packages/playground/windows/playground/pch.h @@ -18,6 +18,10 @@ #include #include +#include +#include +#include +#include #include "CppWinRTIncludes.h" #include diff --git a/vnext/Microsoft.ReactNative.Cxx/CppWinRTIncludes.h b/vnext/Microsoft.ReactNative.Cxx/CppWinRTIncludes.h index 5802ea8562d..2a9f063f750 100644 --- a/vnext/Microsoft.ReactNative.Cxx/CppWinRTIncludes.h +++ b/vnext/Microsoft.ReactNative.Cxx/CppWinRTIncludes.h @@ -6,40 +6,11 @@ #include "NamespaceRedirect.h" #include -#include #include -#include -#include - -// xaml::Interop::TypeName does not exist, always use WUX -#include #ifndef USE_WINUI3 -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include #include namespace xaml = winrt::Windows::UI::Xaml; @@ -51,50 +22,9 @@ using Colors = winrt::Windows::UI::Colors; } // namespace winrt #else -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - #include #include -//////////////// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - namespace xaml = winrt::Microsoft::UI::Xaml; namespace comp = winrt::Microsoft::UI::Composition; namespace winrt { diff --git a/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems b/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems index 38328ca6aa6..076e18d46d5 100644 --- a/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +++ b/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems @@ -34,6 +34,23 @@ + + + + + + + + + + + + + + + + + diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Composition.Effects.h b/vnext/Microsoft.ReactNative.Cxx/UI.Composition.Effects.h new file mode 100644 index 00000000000..5fb159ca9a5 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Composition.Effects.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Composition.h b/vnext/Microsoft.ReactNative.Cxx/UI.Composition.h new file mode 100644 index 00000000000..10020bb2afd --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Composition.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Input.h b/vnext/Microsoft.ReactNative.Cxx/UI.Input.h new file mode 100644 index 00000000000..dac933465f1 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Input.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Popups.h b/vnext/Microsoft.ReactNative.Cxx/UI.Popups.h new file mode 100644 index 00000000000..3d3ee560f55 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Popups.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Text.h b/vnext/Microsoft.ReactNative.Cxx/UI.Text.h new file mode 100644 index 00000000000..c016fc08e9f --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Text.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Automation.Peers.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Automation.Peers.h new file mode 100644 index 00000000000..98de8ab169d --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Automation.Peers.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Automation.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Automation.h new file mode 100644 index 00000000000..7465b4e5cfb --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Automation.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Controls.Primitives.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Controls.Primitives.h new file mode 100644 index 00000000000..769164d282c --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Controls.Primitives.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Controls.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Controls.h new file mode 100644 index 00000000000..a18017805d5 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Controls.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Documents.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Documents.h new file mode 100644 index 00000000000..53db6bda571 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Documents.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Input.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Input.h new file mode 100644 index 00000000000..7daf7354279 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Input.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Markup.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Markup.h new file mode 100644 index 00000000000..3730622835d --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Markup.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.Imaging.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.Imaging.h new file mode 100644 index 00000000000..7b57b3f46b2 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.Imaging.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.Media3D.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.Media3D.h new file mode 100644 index 00000000000..9e1adfe4dea --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.Media3D.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.h new file mode 100644 index 00000000000..eb2a8799bd9 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Media.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Navigation.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Navigation.h new file mode 100644 index 00000000000..36840095fad --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Navigation.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Shapes.h b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Shapes.h new file mode 100644 index 00000000000..9410d3ed8e8 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/UI.Xaml.Shapes.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#ifdef USE_WINUI3 +#include +#else +#include +#endif // USE_WINUI3 diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp b/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp index 2f11c1d9291..81e230fcf1a 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp +++ b/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp @@ -1,4 +1,5 @@ #include "pch.h" +#include "NativeModules.h" #include diff --git a/vnext/Microsoft.ReactNative/ReactApplication.cpp b/vnext/Microsoft.ReactNative/ReactApplication.cpp index ee7263ae52f..17fe4ade491 100644 --- a/vnext/Microsoft.ReactNative/ReactApplication.cpp +++ b/vnext/Microsoft.ReactNative/ReactApplication.cpp @@ -9,6 +9,9 @@ #include "Modules/LinkingManagerModule.h" #include "ReactNativeHost.h" +#include +#include +#include #include #include diff --git a/vnext/Microsoft.ReactNative/RedBox.cpp b/vnext/Microsoft.ReactNative/RedBox.cpp index 0491a64fc9a..e7eb49bad95 100644 --- a/vnext/Microsoft.ReactNative/RedBox.cpp +++ b/vnext/Microsoft.ReactNative/RedBox.cpp @@ -7,12 +7,19 @@ #include #include #include +#include #include #include #include #include "CppWinRTIncludes.h" #include "Unicode.h" +#include +#include +#include +#include +#include + using namespace winrt::Windows::Foundation; namespace Mso::React { diff --git a/vnext/Microsoft.ReactNative/Views/ReactRootControl.cpp b/vnext/Microsoft.ReactNative/Views/ReactRootControl.cpp index d61d17c6bf1..ef076ed36f5 100644 --- a/vnext/Microsoft.ReactNative/Views/ReactRootControl.cpp +++ b/vnext/Microsoft.ReactNative/Views/ReactRootControl.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -29,6 +28,12 @@ #include +#include +#include +#include +#include +#include + namespace react::uwp { //=========================================================================== diff --git a/vnext/ReactUWP/ABI/ReactControl_rt.h b/vnext/ReactUWP/ABI/ReactControl_rt.h index e74cda76177..2d7ac5ed452 100644 --- a/vnext/ReactUWP/ABI/ReactControl_rt.h +++ b/vnext/ReactUWP/ABI/ReactControl_rt.h @@ -5,7 +5,6 @@ #include #include -#include #include #include diff --git a/vnext/ReactUWP/Base/UwpReactInstance.cpp b/vnext/ReactUWP/Base/UwpReactInstance.cpp index 3f447c313b0..0af2c9c76b2 100644 --- a/vnext/ReactUWP/Base/UwpReactInstance.cpp +++ b/vnext/ReactUWP/Base/UwpReactInstance.cpp @@ -55,6 +55,7 @@ #include #include "ChakraRuntimeHolder.h" +#include #include namespace react { diff --git a/vnext/ReactUWP/Modules/AlertModuleUwp.cpp b/vnext/ReactUWP/Modules/AlertModuleUwp.cpp index 806a1bc9a26..6c584f01a00 100644 --- a/vnext/ReactUWP/Modules/AlertModuleUwp.cpp +++ b/vnext/ReactUWP/Modules/AlertModuleUwp.cpp @@ -5,6 +5,8 @@ #include +#include + #pragma warning(push) #pragma warning(disable : 4146) #include diff --git a/vnext/ReactUWP/Modules/Animated/AdditionAnimatedNode.cpp b/vnext/ReactUWP/Modules/Animated/AdditionAnimatedNode.cpp index d2857ddad0e..20b9555bf1d 100644 --- a/vnext/ReactUWP/Modules/Animated/AdditionAnimatedNode.cpp +++ b/vnext/ReactUWP/Modules/Animated/AdditionAnimatedNode.cpp @@ -3,6 +3,7 @@ #include "pch.h" +#include #include "AdditionAnimatedNode.h" #include "NativeAnimatedNodeManager.h" diff --git a/vnext/ReactUWP/Modules/Animated/AnimationDriver.cpp b/vnext/ReactUWP/Modules/Animated/AnimationDriver.cpp index b7ea23237d0..8cbe2ea65e1 100644 --- a/vnext/ReactUWP/Modules/Animated/AnimationDriver.cpp +++ b/vnext/ReactUWP/Modules/Animated/AnimationDriver.cpp @@ -3,6 +3,7 @@ #include "pch.h" +#include #include "AnimationDriver.h" namespace react { diff --git a/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.h b/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.h index 7130a48284c..08a3051fd0e 100644 --- a/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.h +++ b/vnext/ReactUWP/Modules/Animated/ValueAnimatedNode.h @@ -2,6 +2,7 @@ // Licensed under the MIT License. #pragma once +#include #include #include "AnimatedNode.h" diff --git a/vnext/ReactUWP/Modules/AppearanceModule.h b/vnext/ReactUWP/Modules/AppearanceModule.h index 1e3b7c6268e..23dda14ee73 100644 --- a/vnext/ReactUWP/Modules/AppearanceModule.h +++ b/vnext/ReactUWP/Modules/AppearanceModule.h @@ -7,6 +7,8 @@ #include #include +#include + #include "IReactInstance.h" namespace react::uwp { diff --git a/vnext/ReactUWP/Modules/ImageViewManagerModule.cpp b/vnext/ReactUWP/Modules/ImageViewManagerModule.cpp index 8fdee37a63d..ac41331769e 100644 --- a/vnext/ReactUWP/Modules/ImageViewManagerModule.cpp +++ b/vnext/ReactUWP/Modules/ImageViewManagerModule.cpp @@ -10,17 +10,11 @@ #include "ImageViewManagerModule.h" -#include - +#include #include - +#include #include "Unicode.h" -#if _MSC_VER <= 1913 -// VC 19 (2015-2017.6) cannot optimize co_await/cppwinrt usage -#pragma optimize("", off) -#endif - namespace winrt { using namespace Windows::Foundation; using namespace Windows::Storage::Streams; diff --git a/vnext/ReactUWP/Modules/NativeUIManager.cpp b/vnext/ReactUWP/Modules/NativeUIManager.cpp index 14550121ac7..5804d60c1f6 100644 --- a/vnext/ReactUWP/Modules/NativeUIManager.cpp +++ b/vnext/ReactUWP/Modules/NativeUIManager.cpp @@ -7,6 +7,9 @@ #include "NativeUIManager.h" #include +#include +#include +#include #include #include "CppWinRTIncludes.h" diff --git a/vnext/ReactUWP/Modules/TimingModule.cpp b/vnext/ReactUWP/Modules/TimingModule.cpp index e86efc7d88a..96a831c3c47 100644 --- a/vnext/ReactUWP/Modules/TimingModule.cpp +++ b/vnext/ReactUWP/Modules/TimingModule.cpp @@ -7,6 +7,7 @@ #include "TimingModule.h" #include +#include #include #include diff --git a/vnext/ReactUWP/Pch/pch.h b/vnext/ReactUWP/Pch/pch.h index e5c6ee216e5..ff156c66e5a 100644 --- a/vnext/ReactUWP/Pch/pch.h +++ b/vnext/ReactUWP/Pch/pch.h @@ -23,12 +23,6 @@ #include #include -#include -#include -#include -#include -#include -#include #include "CppWinRTIncludes.h" #include diff --git a/vnext/ReactUWP/Polyester/ButtonContentViewManager.cpp b/vnext/ReactUWP/Polyester/ButtonContentViewManager.cpp index a9374a9da53..62bebb0f09e 100644 --- a/vnext/ReactUWP/Polyester/ButtonContentViewManager.cpp +++ b/vnext/ReactUWP/Polyester/ButtonContentViewManager.cpp @@ -5,6 +5,7 @@ #include "ButtonContentViewManager.h" +#include #include namespace react { diff --git a/vnext/ReactUWP/Polyester/ButtonViewManager.cpp b/vnext/ReactUWP/Polyester/ButtonViewManager.cpp index 4137b60871e..e63f3dc2450 100644 --- a/vnext/ReactUWP/Polyester/ButtonViewManager.cpp +++ b/vnext/ReactUWP/Polyester/ButtonViewManager.cpp @@ -5,6 +5,8 @@ #include "ButtonViewManager.h" +#include +#include #include #include diff --git a/vnext/ReactUWP/Polyester/ContentControlViewManager.cpp b/vnext/ReactUWP/Polyester/ContentControlViewManager.cpp index 8cd4011c790..64fcf60bf5d 100644 --- a/vnext/ReactUWP/Polyester/ContentControlViewManager.cpp +++ b/vnext/ReactUWP/Polyester/ContentControlViewManager.cpp @@ -6,6 +6,7 @@ #include #include "ContentControlViewManager.h" +#include #include namespace winrt { diff --git a/vnext/ReactUWP/Polyester/HyperlinkViewManager.cpp b/vnext/ReactUWP/Polyester/HyperlinkViewManager.cpp index d8dd2cc9b7f..0463e3160ca 100644 --- a/vnext/ReactUWP/Polyester/HyperlinkViewManager.cpp +++ b/vnext/ReactUWP/Polyester/HyperlinkViewManager.cpp @@ -5,6 +5,8 @@ #include "HyperlinkViewManager.h" +#include +#include #include #include diff --git a/vnext/ReactUWP/Polyester/IconViewManager.cpp b/vnext/ReactUWP/Polyester/IconViewManager.cpp index 42b31ffb6c9..3565829cc30 100644 --- a/vnext/ReactUWP/Polyester/IconViewManager.cpp +++ b/vnext/ReactUWP/Polyester/IconViewManager.cpp @@ -9,6 +9,7 @@ #include "IconViewManager.h" +#include #include #include diff --git a/vnext/ReactUWP/Utils/AccessibilityUtils.cpp b/vnext/ReactUWP/Utils/AccessibilityUtils.cpp index 83a02432f3e..29837d4f21b 100644 --- a/vnext/ReactUWP/Utils/AccessibilityUtils.cpp +++ b/vnext/ReactUWP/Utils/AccessibilityUtils.cpp @@ -5,7 +5,9 @@ #include -#include +#include +#include +#include namespace react { namespace uwp { diff --git a/vnext/ReactUWP/Utils/Helpers.cpp b/vnext/ReactUWP/Utils/Helpers.cpp index b2fcad03c61..c169f301d8a 100644 --- a/vnext/ReactUWP/Utils/Helpers.cpp +++ b/vnext/ReactUWP/Utils/Helpers.cpp @@ -4,6 +4,7 @@ #include "pch.h" #include +#include #include #include diff --git a/vnext/ReactUWP/Utils/ValueUtils.cpp b/vnext/ReactUWP/Utils/ValueUtils.cpp index 9ce91c8da29..9c407ca9ec9 100644 --- a/vnext/ReactUWP/Utils/ValueUtils.cpp +++ b/vnext/ReactUWP/Utils/ValueUtils.cpp @@ -3,6 +3,7 @@ #include "pch.h" +#include #include #include "Unicode.h" diff --git a/vnext/ReactUWP/Views/ActivityIndicatorViewManager.cpp b/vnext/ReactUWP/Views/ActivityIndicatorViewManager.cpp index e05fe855097..8e66e8cdb4f 100644 --- a/vnext/ReactUWP/Views/ActivityIndicatorViewManager.cpp +++ b/vnext/ReactUWP/Views/ActivityIndicatorViewManager.cpp @@ -5,6 +5,7 @@ #include "ActivityIndicatorViewManager.h" +#include #include #include diff --git a/vnext/ReactUWP/Views/CheckboxViewManager.cpp b/vnext/ReactUWP/Views/CheckboxViewManager.cpp index e24fe036628..1d8fae3c4e5 100644 --- a/vnext/ReactUWP/Views/CheckboxViewManager.cpp +++ b/vnext/ReactUWP/Views/CheckboxViewManager.cpp @@ -6,6 +6,8 @@ #include #include "CheckboxViewManager.h" +#include +#include #include #include diff --git a/vnext/ReactUWP/Views/ControlViewManager.cpp b/vnext/ReactUWP/Views/ControlViewManager.cpp index e91cb4a0226..6d568e01d63 100644 --- a/vnext/ReactUWP/Views/ControlViewManager.cpp +++ b/vnext/ReactUWP/Views/ControlViewManager.cpp @@ -3,6 +3,8 @@ #include "pch.h" +#include + #include #include diff --git a/vnext/ReactUWP/Views/DatePickerViewManager.cpp b/vnext/ReactUWP/Views/DatePickerViewManager.cpp index 04dfa0c3991..0eead21edb8 100644 --- a/vnext/ReactUWP/Views/DatePickerViewManager.cpp +++ b/vnext/ReactUWP/Views/DatePickerViewManager.cpp @@ -6,6 +6,7 @@ #include #include "DatePickerViewManager.h" +#include #include #include diff --git a/vnext/ReactUWP/Views/DynamicAutomationPeer.cpp b/vnext/ReactUWP/Views/DynamicAutomationPeer.cpp index f4d91f2b453..033a4973533 100644 --- a/vnext/ReactUWP/Views/DynamicAutomationPeer.cpp +++ b/vnext/ReactUWP/Views/DynamicAutomationPeer.cpp @@ -6,6 +6,8 @@ #include "DynamicAutomationPeer.h" #include "DynamicAutomationProperties.h" +#include + // Needed for latest versions of C++/WinRT #if __has_include("DynamicAutomationPeer.g.cpp") #include "DynamicAutomationPeer.g.cpp" diff --git a/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp b/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp index b5170f9228e..24658daa8ac 100644 --- a/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp +++ b/vnext/ReactUWP/Views/DynamicAutomationProperties.cpp @@ -5,6 +5,8 @@ #include "DynamicAutomationProperties.h" +#include + // Needed for latest versions of C++/WinRT #if __has_include("DynamicAutomationProperties.g.cpp") #include "DynamicAutomationProperties.g.cpp" diff --git a/vnext/ReactUWP/Views/ExpressionAnimationStore.cpp b/vnext/ReactUWP/Views/ExpressionAnimationStore.cpp index d14b494bd51..d88f3001847 100644 --- a/vnext/ReactUWP/Views/ExpressionAnimationStore.cpp +++ b/vnext/ReactUWP/Views/ExpressionAnimationStore.cpp @@ -6,6 +6,8 @@ #include "ExpressionAnimationStore.h" #include "XamlFeatures.h" +#include + namespace react { namespace uwp { diff --git a/vnext/ReactUWP/Views/FlyoutViewManager.cpp b/vnext/ReactUWP/Views/FlyoutViewManager.cpp index b2d0b6d697a..8f15f78ddeb 100644 --- a/vnext/ReactUWP/Views/FlyoutViewManager.cpp +++ b/vnext/ReactUWP/Views/FlyoutViewManager.cpp @@ -9,6 +9,10 @@ #include "ViewPanel.h" #include +#include +#include +#include +#include #include #include diff --git a/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp b/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp index 9792ac582fa..605f6a2da66 100644 --- a/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp +++ b/vnext/ReactUWP/Views/FrameworkElementViewManager.cpp @@ -14,8 +14,9 @@ #include #include -#include +#include +#include #include "Utils/PropertyHandlerUtils.h" #include "DynamicAutomationProperties.h" diff --git a/vnext/ReactUWP/Views/Image/Microsoft.UI.Composition.Effects_Impl.h b/vnext/ReactUWP/Views/Image/Microsoft.UI.Composition.Effects_Impl.h index ccd7f19c313..f57d7c36b2b 100644 --- a/vnext/ReactUWP/Views/Image/Microsoft.UI.Composition.Effects_Impl.h +++ b/vnext/ReactUWP/Views/Image/Microsoft.UI.Composition.Effects_Impl.h @@ -7,7 +7,6 @@ #include #include -#include #define CATCH_RETURN \ return S_OK; \ diff --git a/vnext/ReactUWP/Views/Image/ReactImage.cpp b/vnext/ReactUWP/Views/Image/ReactImage.cpp index 7ec70a89aca..905db667b1b 100644 --- a/vnext/ReactUWP/Views/Image/ReactImage.cpp +++ b/vnext/ReactUWP/Views/Image/ReactImage.cpp @@ -5,7 +5,10 @@ #include "ReactImage.h" +#include + #include +#include #include #include @@ -24,11 +27,6 @@ using namespace Windows::Web::Http; using Microsoft::Common::Unicode::Utf8ToUtf16; -#if _MSC_VER <= 1913 -// VC 19 (2015-2017.6) cannot optimize co_await/cppwinrt usage -#pragma optimize("", off) -#endif - namespace react { namespace uwp { diff --git a/vnext/ReactUWP/Views/Image/ReactImage.h b/vnext/ReactUWP/Views/Image/ReactImage.h index e73ca246581..b2b7b2117c2 100644 --- a/vnext/ReactUWP/Views/Image/ReactImage.h +++ b/vnext/ReactUWP/Views/Image/ReactImage.h @@ -5,8 +5,7 @@ #include "ReactImageBrush.h" -#include -#include +#include #include diff --git a/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp b/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp index 2876e8749cb..53f4adc110c 100644 --- a/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp +++ b/vnext/ReactUWP/Views/Image/ReactImageBrush.cpp @@ -5,10 +5,9 @@ #include "ReactImageBrush.h" +#include #include -#include -#include #include "BorderEffect.h" namespace winrt { diff --git a/vnext/ReactUWP/Views/Image/ReactImageBrush.h b/vnext/ReactUWP/Views/Image/ReactImageBrush.h index 86cd626d564..d5dacf7dc48 100644 --- a/vnext/ReactUWP/Views/Image/ReactImageBrush.h +++ b/vnext/ReactUWP/Views/Image/ReactImageBrush.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include "CppWinRTIncludes.h" diff --git a/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.cpp b/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.cpp index 40ea7ed5459..f11c9c3a299 100644 --- a/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.cpp +++ b/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include #include "ScrollViewUWPImplementation.h" namespace react { diff --git a/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.h b/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.h index 385101f457d..c33f37b1b81 100644 --- a/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.h +++ b/vnext/ReactUWP/Views/Impl/ScrollViewUWPImplementation.h @@ -8,7 +8,6 @@ #include #include -#include namespace winrt { using namespace Windows::Foundation; diff --git a/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.h b/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.h index 4bddeb71a48..f26ad0ea2f4 100644 --- a/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.h +++ b/vnext/ReactUWP/Views/Impl/SnapPointManagingContentControl.h @@ -1,7 +1,9 @@ #pragma once -#include "winrt/Windows.Foundation.Collections.h" -#include "winrt/Windows.Foundation.h" +#include +#include +#include +#include namespace winrt { using namespace Windows::Foundation; diff --git a/vnext/ReactUWP/Views/KeyboardEventHandler.cpp b/vnext/ReactUWP/Views/KeyboardEventHandler.cpp index c3a9a70fd91..afd5e9fa814 100644 --- a/vnext/ReactUWP/Views/KeyboardEventHandler.cpp +++ b/vnext/ReactUWP/Views/KeyboardEventHandler.cpp @@ -3,6 +3,7 @@ #include "pch.h" +#include #include #include #include "Utils/Helpers.h" diff --git a/vnext/ReactUWP/Views/PickerViewManager.cpp b/vnext/ReactUWP/Views/PickerViewManager.cpp index ffa863aebfc..ef54d001539 100644 --- a/vnext/ReactUWP/Views/PickerViewManager.cpp +++ b/vnext/ReactUWP/Views/PickerViewManager.cpp @@ -3,6 +3,9 @@ #include "pch.h" +#include +#include +#include #include #include #include "PickerViewManager.h" diff --git a/vnext/ReactUWP/Views/PopupViewManager.cpp b/vnext/ReactUWP/Views/PopupViewManager.cpp index 859e378aeff..883a74c122a 100644 --- a/vnext/ReactUWP/Views/PopupViewManager.cpp +++ b/vnext/ReactUWP/Views/PopupViewManager.cpp @@ -8,6 +8,10 @@ #include "TouchEventHandler.h" #include +#include +#include +#include +#include #include #include #include diff --git a/vnext/ReactUWP/Views/RawTextViewManager.cpp b/vnext/ReactUWP/Views/RawTextViewManager.cpp index 49f82c84c5c..06ce181ff8b 100644 --- a/vnext/ReactUWP/Views/RawTextViewManager.cpp +++ b/vnext/ReactUWP/Views/RawTextViewManager.cpp @@ -11,6 +11,8 @@ #include #include +#include +#include #include namespace winrt { diff --git a/vnext/ReactUWP/Views/ReactControl.cpp b/vnext/ReactUWP/Views/ReactControl.cpp index 029aa61bb55..8f3d80dc512 100644 --- a/vnext/ReactUWP/Views/ReactControl.cpp +++ b/vnext/ReactUWP/Views/ReactControl.cpp @@ -14,11 +14,14 @@ #include #include +#include +#include +#include +#include #include #include #include #include -#include namespace react { namespace uwp { diff --git a/vnext/ReactUWP/Views/RefreshControlManager.cpp b/vnext/ReactUWP/Views/RefreshControlManager.cpp index a0230b10362..d2791137ed6 100644 --- a/vnext/ReactUWP/Views/RefreshControlManager.cpp +++ b/vnext/ReactUWP/Views/RefreshControlManager.cpp @@ -6,6 +6,7 @@ #include "RefreshControlManager.h" #include +#include #include namespace winrt { diff --git a/vnext/ReactUWP/Views/RootViewManager.cpp b/vnext/ReactUWP/Views/RootViewManager.cpp index 3b74356dd51..70b9e88df4d 100644 --- a/vnext/ReactUWP/Views/RootViewManager.cpp +++ b/vnext/ReactUWP/Views/RootViewManager.cpp @@ -6,6 +6,7 @@ #include "RootViewManager.h" #include +#include namespace winrt { using namespace Windows::UI; diff --git a/vnext/ReactUWP/Views/SIPEventHandler.cpp b/vnext/ReactUWP/Views/SIPEventHandler.cpp index e8cf8d6b6b3..bf75779af01 100644 --- a/vnext/ReactUWP/Views/SIPEventHandler.cpp +++ b/vnext/ReactUWP/Views/SIPEventHandler.cpp @@ -6,8 +6,8 @@ #include "SIPEventHandler.h" #include - #include +#include namespace winrt { using namespace Windows::Foundation; diff --git a/vnext/ReactUWP/Views/ShadowNodeBase.cpp b/vnext/ReactUWP/Views/ShadowNodeBase.cpp index f4d22f70f03..bd21641ff1e 100644 --- a/vnext/ReactUWP/Views/ShadowNodeBase.cpp +++ b/vnext/ReactUWP/Views/ShadowNodeBase.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include diff --git a/vnext/ReactUWP/Views/SliderViewManager.cpp b/vnext/ReactUWP/Views/SliderViewManager.cpp index ba7223d67a1..b49f3c90181 100644 --- a/vnext/ReactUWP/Views/SliderViewManager.cpp +++ b/vnext/ReactUWP/Views/SliderViewManager.cpp @@ -9,6 +9,9 @@ #include #include +#include +#include +#include namespace winrt { using ToggleButton = xaml::Controls::Primitives::ToggleButton; diff --git a/vnext/ReactUWP/Views/SwitchViewManager.cpp b/vnext/ReactUWP/Views/SwitchViewManager.cpp index e8401f38a4c..1c2fd41b1be 100644 --- a/vnext/ReactUWP/Views/SwitchViewManager.cpp +++ b/vnext/ReactUWP/Views/SwitchViewManager.cpp @@ -4,6 +4,8 @@ #include "pch.h" #include +#include +#include #include #include #include diff --git a/vnext/ReactUWP/Views/TextInputViewManager.cpp b/vnext/ReactUWP/Views/TextInputViewManager.cpp index d3b6cc22697..993c7cbac07 100644 --- a/vnext/ReactUWP/Views/TextInputViewManager.cpp +++ b/vnext/ReactUWP/Views/TextInputViewManager.cpp @@ -7,12 +7,14 @@ #include "Unicode.h" +#include +#include +#include #include #include #include #include -#include "CppWinRTIncludes.h" namespace winrt { using namespace xaml; diff --git a/vnext/ReactUWP/Views/TextViewManager.cpp b/vnext/ReactUWP/Views/TextViewManager.cpp index 7f286249ede..e3176a33f38 100644 --- a/vnext/ReactUWP/Views/TextViewManager.cpp +++ b/vnext/ReactUWP/Views/TextViewManager.cpp @@ -7,6 +7,10 @@ #include +#include +#include +#include +#include #include #include diff --git a/vnext/ReactUWP/Views/TouchEventHandler.cpp b/vnext/ReactUWP/Views/TouchEventHandler.cpp index 53f9e87c60d..91b9622393c 100644 --- a/vnext/ReactUWP/Views/TouchEventHandler.cpp +++ b/vnext/ReactUWP/Views/TouchEventHandler.cpp @@ -7,6 +7,9 @@ #include "TouchEventHandler.h" #include +#include +#include +#include #include #include diff --git a/vnext/ReactUWP/Views/ViewPanel.cpp b/vnext/ReactUWP/Views/ViewPanel.cpp index c24a5e396c2..e0a78ff3cef 100644 --- a/vnext/ReactUWP/Views/ViewPanel.cpp +++ b/vnext/ReactUWP/Views/ViewPanel.cpp @@ -6,7 +6,9 @@ #include "DynamicAutomationPeer.h" #include "ViewPanel.h" +#include #include +#include // Needed for latest versions of C++/WinRT #if __has_include("ViewPanel.g.cpp") diff --git a/vnext/ReactUWP/Views/VirtualTextViewManager.cpp b/vnext/ReactUWP/Views/VirtualTextViewManager.cpp index 01bef7a4915..2b04b649624 100644 --- a/vnext/ReactUWP/Views/VirtualTextViewManager.cpp +++ b/vnext/ReactUWP/Views/VirtualTextViewManager.cpp @@ -5,11 +5,11 @@ #include "VirtualTextViewManager.h" +#include +#include #include #include -#include - namespace winrt { using namespace Windows::UI; using namespace xaml; diff --git a/vnext/Universal.IntegrationTests/UniversalTestInstance.cpp b/vnext/Universal.IntegrationTests/UniversalTestInstance.cpp index eed2050fd1c..fedd4a24054 100644 --- a/vnext/Universal.IntegrationTests/UniversalTestInstance.cpp +++ b/vnext/Universal.IntegrationTests/UniversalTestInstance.cpp @@ -4,7 +4,7 @@ #include "UniversalTestInstance.h" -#include // C++/CX +#include #include namespace cx { diff --git a/vnext/Universal.IntegrationTests/UniversalTestRunner.cpp b/vnext/Universal.IntegrationTests/UniversalTestRunner.cpp index 52193fa8a89..5dcd01ac05c 100644 --- a/vnext/Universal.IntegrationTests/UniversalTestRunner.cpp +++ b/vnext/Universal.IntegrationTests/UniversalTestRunner.cpp @@ -9,7 +9,7 @@ #include #include "UniversalTestInstance.h" -#include // C++/CX +#include #include #include // Concurrency namespace. diff --git a/vnext/include/ReactUWP/Utils/PropertyUtils.h b/vnext/include/ReactUWP/Utils/PropertyUtils.h index 3a8024c6092..c11c130a6c9 100644 --- a/vnext/include/ReactUWP/Utils/PropertyUtils.h +++ b/vnext/include/ReactUWP/Utils/PropertyUtils.h @@ -10,6 +10,7 @@ #include #include #include +#include #include diff --git a/vnext/include/ReactUWP/Utils/ResourceBrushUtils.h b/vnext/include/ReactUWP/Utils/ResourceBrushUtils.h index ecdb28ec7cc..ae11d87d299 100644 --- a/vnext/include/ReactUWP/Utils/ResourceBrushUtils.h +++ b/vnext/include/ReactUWP/Utils/ResourceBrushUtils.h @@ -2,6 +2,7 @@ // Licensed under the MIT License. #pragma once +#include #include "CppWinRTIncludes.h" namespace react { From fdcffd4ccfa7a0554f3f1b8b6435cf94b74b0a02 Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Thu, 14 May 2020 00:40:07 -0700 Subject: [PATCH 102/209] Playground app not specifying the UIDispatcher (#4896) --- packages/playground/windows/playground/MainPage.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/playground/windows/playground/MainPage.cpp b/packages/playground/windows/playground/MainPage.cpp index 57ad5438409..aaade330325 100644 --- a/packages/playground/windows/playground/MainPage.cpp +++ b/packages/playground/windows/playground/MainPage.cpp @@ -42,6 +42,9 @@ void MainPage::OnLoadClick( host.InstanceSettings().DebuggerBreakOnNextLine(x_BreakOnFirstLineCheckBox().IsChecked().GetBoolean()); host.InstanceSettings().UseFastRefresh(x_UseFastRefreshCheckBox().IsChecked().GetBoolean()); host.InstanceSettings().DebuggerPort(static_cast(std::stoi(std::wstring(x_DebuggerPort().Text())))); + host.InstanceSettings().Properties().Set( + winrt::Microsoft::ReactNative::ReactDispatcherHelper::UIDispatcherProperty(), + winrt::Microsoft::ReactNative::ReactDispatcherHelper::UIThreadDispatcher()); // Nudge the ReactNativeHost to create the instance and wrapping context host.ReloadInstance(); From 069073f204e6ab63b1eeb6115c6b733ddf093b5f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 14 May 2020 10:00:52 +0000 Subject: [PATCH 103/209] Bump @types/react-native from 0.62.7 to 0.62.8 (#4888) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6633ac2c3d6..5ded29c992f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2885,9 +2885,9 @@ integrity sha1-Hs9SYhKZ5luFU3Qzf7Ef0tEGb8E= "@types/react-native@^0.62.2": - version "0.62.7" - resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.62.7.tgz#bfc5ed03ba576f288603daa3f67f0f67d9a8bf57" - integrity sha512-FGFEt9GcFVl//XxWmxkeBxAx0YnzyEhJpR8hOJrjfaFKZm0KjHzzyCmCksBAP2qHSTrcJCiBkIvYCX/kGiOgww== + version "0.62.8" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.62.8.tgz#224602561f75b838ed6e3b5ea37093bb84cffd74" + integrity sha512-YEf0tH3xYJpQB12Vvzoy7cqPY3mvbbulTnG3G7ToKOuJuqigAN3K9NNAaxNAAm1zCj+UtObhzcaJtPRwX1z6Fw== dependencies: "@types/react" "*" From 204bc9e292a9889111f72e143555c3be57bf5a99 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Thu, 14 May 2020 03:40:21 -0700 Subject: [PATCH 104/209] Move Microsoft.ReactNative pch files in a Pch subfolder (#4898) * Move pch files into a Pch subfolder. * Change files --- ...-windows-2020-05-13-17-33-52-Move_pch.json | 8 +++++++ .../Microsoft.ReactNative.vcxproj | 5 +++-- .../Microsoft.ReactNative.vcxproj.filters | 21 ++++++++++++++----- vnext/Microsoft.ReactNative/{ => Pch}/pch.cpp | 0 vnext/Microsoft.ReactNative/{ => Pch}/pch.h | 0 5 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 change/react-native-windows-2020-05-13-17-33-52-Move_pch.json rename vnext/Microsoft.ReactNative/{ => Pch}/pch.cpp (100%) rename vnext/Microsoft.ReactNative/{ => Pch}/pch.h (100%) diff --git a/change/react-native-windows-2020-05-13-17-33-52-Move_pch.json b/change/react-native-windows-2020-05-13-17-33-52-Move_pch.json new file mode 100644 index 00000000000..0621be3bc56 --- /dev/null +++ b/change/react-native-windows-2020-05-13-17-33-52-Move_pch.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Move pch files into a Pch subfolder.", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-14T00:33:52.732Z" +} diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj index 3a981cd2ef6..8586d47ef81 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj @@ -123,6 +123,7 @@ /await %(AdditionalOptions) /bigobj $(ReactNativeWindowsDir)Microsoft.ReactNative; + $(ReactNativeWindowsDir)Microsoft.ReactNative\Pch; $(ReactNativeWindowsDir)Microsoft.ReactNative\Views; $(ReactNativeWindowsDir)ReactUWP; $(ReactNativeWindowsDir)ReactUWP\Views; @@ -310,7 +311,7 @@ - + ReactApplication.idl @@ -480,7 +481,7 @@ - + Create diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters index 49caa030be9..69b37cc4be2 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters @@ -269,12 +269,16 @@ Modules - + + Modules + Modules - + + Pch + ReactHost @@ -604,12 +608,16 @@ Modules - + + Modules + Modules - + + Pch + ReactHost @@ -689,7 +697,6 @@ - @@ -699,6 +706,7 @@ + @@ -725,6 +733,9 @@ {1fe62423-356b-44a9-a97c-79950d299afe} + + {cabb286d-fae0-4cfa-b793-79d13f559b41} + {c7bc39da-51b4-4410-846f-ffc20dfa57cc} diff --git a/vnext/Microsoft.ReactNative/pch.cpp b/vnext/Microsoft.ReactNative/Pch/pch.cpp similarity index 100% rename from vnext/Microsoft.ReactNative/pch.cpp rename to vnext/Microsoft.ReactNative/Pch/pch.cpp diff --git a/vnext/Microsoft.ReactNative/pch.h b/vnext/Microsoft.ReactNative/Pch/pch.h similarity index 100% rename from vnext/Microsoft.ReactNative/pch.h rename to vnext/Microsoft.ReactNative/Pch/pch.h From 1d277096c3b1a4a47e41de38ad590ec6e04bedf0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 14 May 2020 13:58:17 +0000 Subject: [PATCH 105/209] [Security] Bump handlebars from 4.5.3 to 4.7.6 (#4903) --- yarn.lock | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5ded29c992f..4d224c615cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7419,13 +7419,14 @@ growly@^1.3.0: integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= handlebars@^4.0.12, handlebars@^4.1.2: - version "4.5.3" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" - integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA== + version "4.7.6" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" + integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== dependencies: + minimist "^1.2.5" neo-async "^2.6.0" - optimist "^0.6.1" source-map "^0.6.1" + wordwrap "^1.0.0" optionalDependencies: uglify-js "^3.1.4" @@ -9987,11 +9988,6 @@ minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= - minipass@^2.2.1, minipass@^2.3.5: version "2.4.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.4.0.tgz#38f0af94f42fb6f34d3d7d82a90e2c99cd3ff485" @@ -10684,14 +10680,6 @@ openssl-wrapper@^0.3.4: resolved "https://registry.yarnpkg.com/openssl-wrapper/-/openssl-wrapper-0.3.4.tgz#c01ec98e4dcd2b5dfe0b693f31827200e3b81b07" integrity sha1-wB7Jjk3NK13+C2k/MYJyAOO4Gwc= -optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - optionator@^0.8.1, optionator@^0.8.2: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -13452,12 +13440,11 @@ uglify-es@^3.1.9: source-map "~0.6.1" uglify-js@^3.1.4: - version "3.7.2" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.2.tgz#cb1a601e67536e9ed094a92dd1e333459643d3f9" - integrity sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA== + version "3.9.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.9.3.tgz#4a285d1658b8a2ebaef9e51366b3a0f7acd79ec2" + integrity sha512-r5ImcL6QyzQGVimQoov3aL2ZScywrOgBXGndbWrdehKoSvGe/RmiE5Jpw/v+GvxODt6l2tpBXwA7n+qZVlHBMA== dependencies: commander "~2.20.3" - source-map "~0.6.1" uid-number@0.0.6: version "0.0.6" @@ -13895,11 +13882,6 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - wordwrapjs@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-3.0.0.tgz#c94c372894cadc6feb1a66bff64e1d9af92c5d1e" From c39343857935b75550412e0d481f60c6366bef65 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Thu, 14 May 2020 07:50:01 -0700 Subject: [PATCH 106/209] improve treedump capabilities (#4844) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * improve treedump capabilities * Reenable V8 for desktop projects (#4840) * Delay load ChakraCore.dll * Change files * clean up unneeded project references * Overwrite property after React.Cpp.props gets included * Change files * change file * Fix WinUI3 * Reverse the conditional logic * Revert some unnecessary changes. Consolidate the preprocessor defines in the props Co-authored-by: tudorm * applying package updates ***NO_CI*** * update masters * Improve run_wdio to print out failed tests (#4843) * Improve run_wdio to print out failed tests * Fire onLoad event when a bitmap image is opened (#4750) * Fire onLoad event when a bitmap image is opeed * Change files * add imageFailed * remove firing of onload events in the createImageBrush block so that load events don't fire twice. * Expose ability for apps to provide their own RedBox implementation (#4786) * Expose ability for apps to provide their own RedBox implementation * Change files * minor changes * Code review feedback * minor fix * format fixes * minor change * minor fix * minor fix * minor fix * Bump fp-ts from 2.5.4 to 2.6.0 (#4871) Bumps [fp-ts](https://github.com/gcanti/fp-ts) from 2.5.4 to 2.6.0. - [Release notes](https://github.com/gcanti/fp-ts/releases) - [Changelog](https://github.com/gcanti/fp-ts/blob/master/CHANGELOG.md) - [Commits](https://github.com/gcanti/fp-ts/compare/2.5.4...2.6.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * applying package updates ***NO_CI*** * Fixed ReactContext copy/move semantic (#4870) * Fixed ReactContext copy/move semantic * Change files * Fixed formatting * Test to show how to use a delegate in ReactPropertyBag * Add ReactNativeHost to Win32 C++/WinRT ABI (#4848) * create MS.ReactNative.IntegrationTests project * RNHost activation succeeds * update * update * Change files * add JS function call test * Change files * fix formatting * submit current state * ReactNativeHost activation test succeeds * Change files * account for property bag addition * sync, address code review feedback * Use spec file for DevSettings NativeModule (#4873) * Use spec file for DevSettings NativeModule * Change files * minor change * Handle HTTP errors in DevSupportManager. (#4880) * Handle HTTP connect exceptions in DevSupportManager * Change files * applying package updates ***NO_CI*** * Allow storing non-WinRT types in ReactPropertyBag (#4884) * Allow storing non-WinRT types in ReactPropertyBag * Change files * Addressed PR feedback * Use DispatcherQueue instead of CoreDispatcher for Mso::DispatchQueue (#4877) * Use DispatcherQueue instead of CoreDispatcher for Mso::DispatchQueue * Change files * Removed 'Thread' from some new API names. * Removed extra 'private' section in AppearanceModule * Temporary: use CoreDispatcher to check the E2E test * Avoid using DispatcherQueue::HasThreadAccess in earlier Windows versions. * RNW dependencies (#4876) * add rnw-dependencies.ps1 * Change files * --sln * run in CI * print * desktop appium is optional * use agent directory * 15GB is a ballpark estimate * optional space * . * support running from web (#4892) * Bump typescript from 3.8.3 to 3.9.2 (#4890) * Bump lerna from 3.20.2 to 3.21.0 (#4889) * BugFix: fix default tabindex stomping over acceptsKeyboardFocus (#4893) * Change files * revert dfc57fcf2504f57baab20f550b36a618eaa99e56 * set default tab index to -1, the hope is to be in line with xbox assumption * xbox doesn't seem to rely on this, changing default back to match xaml default * Update e2e testing doc with CI debugging info (#4897) * add instructions for CI debugging for e2e test app * point e2e readme to e2e testing doc * Update rnw-dependencies (#4894) * don't exit the powershell session and pause for keyboard input if interactive * Change files * enable Switch (fixed 4596) * improve treedump capabilities * update masters * enable Switch (fixed 4596) * protect against exceptions in run_wdio * add another try block * update e2e testing and masters, fixes 4680 * publish wdio report and fix run_wdio typo bug * TreeDump should ignore collapsed object elements in an array * add info about run_wdio Co-authored-by: tudorms <48035227+tudorms@users.noreply.github.com> Co-authored-by: tudorm Co-authored-by: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Co-authored-by: lamxdoan Co-authored-by: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Vladimir Morozov Co-authored-by: Andreas Eulitz <44379427+aeulitz@users.noreply.github.com> Co-authored-by: Julio César Rocha Co-authored-by: kmelmon <33470154+kmelmon@users.noreply.github.com> --- .ado/templates/e2e-test-job.yml | 7 + docs/e2e-testing.md | 49 +++ docs/img/e2e-errors.png | Bin 0 -> 67545 bytes docs/img/e2e-testfail.png | Bin 0 -> 135574 bytes packages/E2ETest/app/ControlStyleTestPage.tsx | 7 +- packages/E2ETest/run_wdio.js | 20 +- .../masters/ControlStyleRegularBorder.json | 337 ++++++++++++------ .../masters/ControlStyleRoundBorder.json | 337 ++++++++++++------ .../Assets/TreeDump/masters/ImageRTL.json | 1 + .../TreeDump/masters/ImageWithBorder.json | 1 + .../ImageWithoutBorder-Subsequent.json | 1 + .../TreeDump/masters/ImageWithoutBorder.json | 1 + .../TreeDumpControlViewManager.cs | 170 +-------- .../windows/TreeDumpLibrary/TreeDumpHelper.cs | 249 +++++++++++++ .../TreeDumpLibrary/TreeDumpLibrary.csproj | 4 +- .../TreeDumpLibrary/VisualTreeDumper.cs | 103 +++++- 16 files changed, 894 insertions(+), 393 deletions(-) create mode 100644 docs/img/e2e-errors.png create mode 100644 docs/img/e2e-testfail.png create mode 100644 packages/E2ETest/windows/TreeDumpLibrary/TreeDumpHelper.cs diff --git a/.ado/templates/e2e-test-job.yml b/.ado/templates/e2e-test-job.yml index 2dfe9f642a6..7f073952b61 100644 --- a/.ado/templates/e2e-test-job.yml +++ b/.ado/templates/e2e-test-job.yml @@ -91,6 +91,13 @@ jobs: script: yarn run e2etest workingDirectory: packages/E2ETest + - task: CopyFiles@2 + displayName: Copy test report + inputs: + sourceFolder: $(Build.SourcesDirectory)\packages\E2ETest\reports + targetFolder: $(Build.StagingDirectory)/ReactUWPTestAppTreeDump/reports + condition: succeededOrFailed() + - task: CopyFiles@2 displayName: Copy tree dump output files inputs: diff --git a/docs/e2e-testing.md b/docs/e2e-testing.md index bda97c8cf67..4fc59c96901 100644 --- a/docs/e2e-testing.md +++ b/docs/e2e-testing.md @@ -437,6 +437,55 @@ You can easily to use By(string) to locate a element which associated with testI It's recommended to define a `get` for each locator like above. +## E2E Tests and masters + +E2E tests can be summarized as follows: +- they are tests that run the ReactUWPTestApp +- use UI Automation to navigate between pages, query the state of elements, click on them, etc. +- the ReactUWPTestApp has code to produce a dump of the its own visual tree ("tree dump output") and compares it with a checked in copy ("tree dump masters") to make sure nothing has regressed. The tree dumps are produced in Json format (there is also an option to produce them in a custom text format of key=value, but that is deprecated now). + +So you've added or updated some tests: great! you get a cookie*. But now you probably need to update the masters, or the tests will fail and break the CI. + +\* void where prohibited, prizes and participation may vary. + +![testFail](img/e2e-testfail.png) + +The best way to do this is by letting the CI run and fail, then downloading the generated tree dump output files, and comparing to the masters. Make sure the differences are expected, copy over them and check them in. The reason is that the masters will include things like the size elements rendered at, which can be dependent on DPI, scale factor, resolution, and in some cases (due to bugs) even differ based on bitness (see #4628). + +When an output doesn't match its master, a file with `.err` extension will be produced under the `TreeDump` folder in the `ReactUWPTestAppTreeDump` artifact. The content of the `.err` file will usually just say: + +```txt +Tree dump file does not match master at C:\Program Files\WindowsApps\ReactUWPTestApp_1.0.0.0_x64__kc2bncckyf4ap\Assets\TreeDump\masters\ControlStyleRoundBorder.json - See output at C:\Users\VssAdministrator\AppData\Local\Packages\ReactUWPTestApp_kc2bncckyf4ap\LocalState\TreeDump\ControlStyleRoundBorder.json +``` + +![Errors](img/e2e-errors.png) + +Find the corresponding `.json` file in that folder and compare it to its master. The masters live in [e2etest\windows\ReactUWPTestApp\Assets\TreeDump\masters](https://github.com/microsoft/react-native-windows/tree/master/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters). + +Sometimes you'll have an element in your test that produces output that should not be used for comparison. You can manually edit the generated json and set the output that you want to ignore to the `` value: + +```json +... +"Windows.UI.Xaml.Button": +{ + "Text": "", + ... +} +... +``` + +## run_wdio + +WDIO is not really built to be run within Azure DevOps, so I wrote a utility called `run_wdio` to adapt it to something that can run in ADO. +It can be found in [\packages\e2etest\run_wdio.js](https://github.com/microsoft/react-native-windows/blob/master/packages/E2ETest/run_wdio.js) +Its main features (which WDIO lacks) are: + +* reports success/failure to ADO so that test failures will break the CI +* supports test selection on the command line +* supports test metadata and filtering (e.g. you can mark a test as "do not run in the lab") +* prints out the list of tests and test cases that failed in the CI console + + ## Debugging E2E Tests in CI If you have access to the AzureDevOps pipeline you'll be able to see test failures and debug crashes. Here are the artifacts that are produced during the build: diff --git a/docs/img/e2e-errors.png b/docs/img/e2e-errors.png new file mode 100644 index 0000000000000000000000000000000000000000..6a49cbd1d5bd12b463f58368c8b7b6c64643a5e8 GIT binary patch literal 67545 zcmdSBcT|&GyDy5$!W9*Dh0g+th*G2@Rl0(W0MbIQ8UjKnN)-r2L2MM2gbo3z0Rqyc zTR}ooTIf+BAVdf)K&WTFtmU`&{^Ojz?-=LaF>c0i2ns3lo%4Bq?RlRV+_=WMk7pkn z8ylzg^~*+VY%oJMw%vFC&SDV$6Y$-&KUh`YEGMBvSG}gb?%D6)F*>K{$+3x{-<`s#%SBe7DvSa zz1;$d>kUO-GaZStUgWl`ovne*f^7xbVE+Ux!u- zU4}m3&ZAtOU-b9a=_HupuHWCd={<(lZs&0uqlx_e^+hYLSG#|IGnjPv$nUSe^!?v^ z3A+64FX`XU;`-42uW$NrD|_GOmT|bwt$Ody6tyvAOmJo@#j8Waqk-i(_BA~DZWDLw z8ok&qhY-Bh#Pj?8q}OsBJZZkhq?@fR&seQ3O&JHQ%-Y1;)(1pY%2jNQzCa*HmWHTX zm36B>o<&{b5@N)z1g?zuoxuElhR{RLz|WKqI40vq{HXQf)#ERtk%TGw8YfS&E=vho9-z%sQQcjY zoOQ00f$wtDbUKJ)@ix8|7HGT)*;rrAL@a~%-naYcnF@+zr^YrG_3SIU)|D_*8g#9F zrQbe`liVuRXiY)$@fJ^-HLmq~ez~+4KbaO-n}=LC)Dg{n!HoJ9+eH6~#1oytbDk%aB5)%-e6X)_IzCawI#TuJZF1eZOh-xn zWS9lqTRU$onY!Va=sW0qBJii>d){jP6mWf~^+qTS%N3==o~`(h?R6@R(zxZrd5m_K z9ILm_^DOo=|07&X&@U7-r%Z(KodJGiq3MK2By*V0fBePZ!W~jYpJ-XTf|Wm5O0siq zs;Q~1KTW1nby2QzjS$GFuSyA+CZdy^b40{Q^S7hQ(B#tQPsr&)3wAKA2GKLV{SooHVS|=bz~Jpwe9OiPOw>h3e|g zb&1OUTbb(5#0l%eljLI!a}Q;hJ;sX5$~U_Zi}?jbqPc|N05^W6N``jFHh9b8UTx>E zB?hle(eGlvEHEx_b;Q{QOa-XL+4v49f0kYu_KNoiSsy|_JYt$hKW5|owe<6uXFX#Z zr_mS3!QLV^&yhTWFg=qBW0A6PwTy<^;E>t6#f~*z)@rlH=)Ij&DqW&F_jV6DR!>31 zt3%0YAb?J4jk9vM0M!QBJOLI4ubh*xd;-;dQcS-#Ix^8Q(!;g5<=$3{Fu{6jV^RYu zKQRiDBLi>NWm?6Jx3*RqF1hJ6QbbZ9@dk!1~+W{Yn&9(Idi@a*nd70Dgvnq@_V``NT;l;(iiDVDkXw`+! zJn2uO*Kd>C{fh2Bkh{hgF!l6&T zXFNKUpOGUNXMU^axJT2rtZDN3S=o*YnOK^b9g$w!b&{ZWczV8>PpWbClhkxLrAR=v zf?^xkd$%z%u`;^CSH3S9)z806LPNi?YEe1fO(@Yl>3bxTJ=&~oYA`~8Z2 z-V!(8Vbw!6>2`rjHtVnJz(3NKhdhe$r7~jE15SiZgF%{J$ATZu!cjQoj^<`Cje#V( zL!~L``?Xxwf-q@Zt+75+G?kNFWcmq_ zAj;*pi!F5dyhTq&yKc;fLmG8kqa&wHWG^1^pTQ|x3G8~_F?cekri0gS*su~5`2g9( zW$(nhvE-|~Xq)^$f|vz%q?wfkS+{W`y}ZnDovuUb_|%04i-mPAeO1E`Dg}k52$JRz zdSTg(pvLI>i9k_wY`3F?EFR9|g6~vX-)d59Fx+FH6wx=w$z9;z-fbi;vDcU-AzLhS`_63jWZ&{5 zrDfOHecHUVVIv8#-g0$t7W&f7&Gzi|r()Hsufm>W%NVOSp2S46J{_}jbyYGFy@zgO zB`%UzgsGY0iHZ2Q$7=Xa6u1;boibkZsMM~UoHVRoVCl@8aVDmy+Oc}3a_DNkI&}ye zqEfq@szwP2-Ug?hu3KSEJ!vMIOjE%heL+l#BfC^Luo4mGut0^12K_<19JpPy#L(oV z(qxM4;L1tpVhNcMMe*mqrLo7sUy;oxLEke@!!EQm4Sq!jrP=xPngk-NHBbfITB%NH z{$$s(_CBbGmWQ?EB>L$;K+eF^pCUW7Ki^uL%JnGZw%DyiT7o;0s|lbxRG3)oz77th z7bma0;GZwkuZmh^n~YvLW`pdr4V;m&e;aD4UM(NFI9*WOR~Z2#3Y5pL=v^1!Cv1aq zRgr34v~nu&mtmF0kH=@pg7MZyd{w8YtJfp-^TwVXK_O1|EUX{)s)+{#-YW>O17t3f07b zcBwbt9+Y+=#CjLHt4CoYSv*~!cQGw(rhk=n7E#WBPc%)0F+;XjLVS*zAPk%$khY*7 ztwj5BDkH9+laO4j!8TD@9e!jz#Sx^H&_us7nW=MIbXQttyca=C(m4mAmUpGsaO>*%e6Kq^=|WS zHDU+hJXQCyTWb1o{}kqw?elqhylnt+zO5hKCeOv=QB8|0-CQ2hzoQ6%r~QJ=KzQCO zl}q`)`wRr_UmVtUP|!1ee|+i>g5Z&yu6)-pPK9$C+pNykYZ_}`7eM#VF;#tvEFE+y zAi3n79m<--?v^F~T7)3l#u(pr-jLw<%fp`m60<2l3KqUxX?G=9Go*s&pUHdU4(so} z{^DC#Joq%0(f-rK+#-6D*#o0z;-%NsswPT=FTOR{HLb*2RV7<@@zj?FIqSA zZT`H*RL;5P)KKQEpKvrhk-y?2T&IWr=I!qNJru=kOQWJ|9Q%_d;}+XO-v+IWnDP1H zLJc_BZYa@kr2vohcB=3fhku8E)-f+Y9VuYUT@8mgGWT~lYd?}4u9xG3rw_ap+p3XV*9No8P{zdef{d75L<1>tMl9l_aQ_RkCK1P#s2ywSN#f5X z<|O5hmQQe0T4=Js`V!rK7^yiWqT`5k_3N-t0^;~-P1yS7GBWbL35-uZ%(VJOyENi~ z0*pWVOizE7jL`#GfM#7e-)8Zc={s^~tJxMA+EV5%bI8cu`Xp*E`&(txzYu?t%K9Qx zojbA+`#)e!^k*<{yJ?L+{9PQ+YA+&PCYhLg3?d8Q}a-`wQHSCHAR zbjVZuu)D7jYbuz1RuqQYqRL<_!(G2|lCL~`)bl|57b$1T z4z%algu@2;hBTfWrn&o3qW6nw!5WpWsL=(BMB0dpQTHo)N zvgT6^GaV4RQ~-4=Qx)=JDzm85*O?kef6374ka(Ap8Lga;T}-CBy7sF17qdT2Vo+)X zQkDQ5i`jQVa2$7HzJ6u2w$d3B@jl?p_jHZTDSi3NJ%gQ%c8$S45lG8rpS~oijBLkm zMJ604jU;Qw{LXrADzCRKZt56_%p3|7WhAnh7l7U0JQ+C3%l$?h|2jNP=yC^%>GcGe z{51N=r_$mHFVGPe>SxdGYAo+*i>!%$CkAz(gdX%SNz^@nlnqJZ8Vy{2vVDpBm{XEp z3KIzP>zLyDN>d`);mh5Y%S}jn=Rz3YM!N5j3s6%i4rUf83mpROD5gc`@)6Rdd`9p} ztR#1yz)_UWiqkBegUS6$~ZiK^k!UvI{unXDXS5F$Gl?EmVLoJshcGwE%&F)XT0 znO;bHx0kQ5*U#v#D5ci_Y)ZOG{-P?V%koS3Z$|I+V5Vp)FO6qBFqZpj_07(TYCz4% zHT0sPvBP?rYSjZbh?CKj+G>Hhf5E;w95vR|S^rh0t^PZz#V2p@F^AkXrl_#~C* z^xEi3gV~;|Fbf|X*xpuRzDMQ~4-*@D=7RzkMrNi~>S~S7i-+j*?y*(F8(5m%{4i^J z;+b_OjMEzesBg0bP{~8CWqQ1a>H&_Uj}OeJzDX|W=ryyeH%%i8P(H6aL5wy)?kELE zHgVq5U%0B_@cDU@EcjiVdnu>k71`@}d;PdWXD%Lr$!94BUsd__TB}}x#OUR!Rww?%ha#KlBi5FUCt!bN3qlvqsB*}?c7blUUBi(t zqvK)?KTU2A?2zv*Ov=u&(z)Rj;=DphUBMs>BqzU)+<%BnCp*a%dG?R=LKUQPrl{Pk zt*tctd)LvsMsbZJ*4rfyE1>;qZxnmC9csdbWgW^sx15C@-pG@}e&3HS`E<0PH`j=% zF-B{ZsIpG|sN4YWKq%fvk~;5+@6-qSVH1G_&+!-6`j&n9E{BT1bqD+>Q!#h)tFvBq z%XX@E_x}ic!L5KHRhZ74*dCA7@AK)_Q?zm0wY)kO6H``d_&`@*jft#(2Q(F>6PRm= z^c<5i8U1|KD4q8bHZ2taOJA?igH>V`d}7p=%}L7mI5Y|VSlfhH{#@rsJ~9#UEnEKb z%Y5B|W^me7L>-uyuu`5{X^A(8@IEf3QFh8frSa!Hc`m`xO1VYvbzzSLmnxfhFgQT; ze2~PczL(v}Zj}}!B%X1pz`CriAromw_OZG1?vLi%K?$7&nFmg0oiP^;(JQ16{k?|K z;fISGx7KP3>z4;J8vcDbmX zRhFJYn1$pUzht5na}@|_I;zfsrDW-s*Z6Du?*F!4E>@7#O90UdYa8o-D$ z$Om>ig3ru#rM|YK2~=kUHM#gXUpuD$Op!WUvbH_@FL}ilF>u3 zGDw=LunXR;NHX#lqsHX0e@eoCICGy^ZkPf|3X{iRO%68d@qL{_Mo+{pxdifF(h8?y_?g+nk3kXdCSwxWmLo{>V&(^(|V8~#eLz9{n*#*&PVRee>xUVi?<7o z{L;HR-QwqmZJ4yt4*k_*tWPqjgRARYC=nrO=a&LOi{(Cu-kn-8= zC9AE7dftBC3LFnI#c6wUMdS7S`Z<`1T>P-~xW>2Kddu2caO^REWFhajaQ3W9!nkP@ z1-0<#8c-5ldS68sum8NJVJW7O3do1NLHQTW{k;Yj`HLq*Hs&iz4b$}Th3xSM0Ryvq zcaDKiREKRi1O-nxN@pa;-cTlTyodK`*VeiwPj=-?D%Jpf&7IShR{P>@?;ppk4L;~p zYe$9qdZxnfuplvL&pE3(Os#9I&8x0deVZu;az3w&4Gi?xxHjv2wmhVb|tc6 z_g$|(1yl)7)`ViCk|nJm{3%>n`Fl8*%XNA!b<}13Q$;>fsKpP6;b*uKDHOZCi~@k_X-m(BPge zu7hn($(?70#)rLb0C?|A+K78<$0}5gC^|DqpdTIxS(Kf22{QI;tW_IPpvVxeL~Bse z!OKZIeHQrgH*u=n9fK*tDj zxhSCckcf>PP_|={&88Jd@ItbBC6FbX2WYZ7Hy@E7gs3Sd8m^)S8c!eMMB z$E$`dW--O(`U#J^yCc+_k9bY_gxhd;Ox!)KJ_wVHOhkLL&uFL=nBt`^++P~Mm=4Q7 z7}v?~_DvEfDazf>Z$o!6Io5NM-Sa78-&1mshsbw@tt;Mfoan(+Ll~s9u;SwqC@Dyd zXTzU!_3YMIlZ$#6B}|Hq{vwINR ziZ~z=w)c?a=K6|99sA#}#>V#TgZ!OuZ@Y@^8oR1Is9m}GgsxgYM$OW6FQ$BFGa~=r zaa;bI_ZR-eZH^Ia76BZT2-UfZD9-XkVy~-&IL^*6)dsFh3WeLELD2YpN4w;qZfXrFHnv3-BfoA zT`r!=5i^!}W1r|U>aRoapCIlkAi_%#Z>Nn3F0Q{VE?trEyqv>QQkCZ1%bg(#r*<)t zi8-P{8jFctfpHdy;=gnlG1#o7H0PWy%txc4y%Y0~31_!VB4f-tI*_cG)*K%eQTAYZJ2Bbk^R}Ov|)e*Ej&J{l?|v*jnIj)AlbW zeHE%jjf#6L+oetEopt(^mzg_|z#ovHSTOX@sclT`obYKSC~( zdvqi%hQvDFP=lk6L0lg^-hPxluZ1K(#a>@)Q}as<7(kzhVH4s4mg2%_AbPcy5%)ce z1OI({(}R0!A{pI(!UK1+xY0JEe$Bx>P7=M=DRR8Q{*r4wl1zMk8Vz9$4i!h zt~vJCKQF3#fnPNARDN%Mm!x!S$kt+G-2L`uXW|HOZ1)GIDb)-s|u5}9X% zJ3DKNm@9sx+^kqhW+EzDrn{s$&Not!MHkbcF?PPy_ zbwkTi%QRDsYE2-(Q0SqFF;#+rX&-H+E~i>ASfR?f$RlX@Pd|A|%yKYG>BpOCuL0kW zjq^TyO3NGSKb(S6#y&GFDE*G*lY!|B;AiEm0oO`*FQ0WlJ0MCDf4?-F?n&SSV=ut- zTsGRaZF}rZf)zse`04cR!>}9wEY+NPQUZVeXcU1>+WqWSbB?63o=HH|Dqn^z_%4r9 z-W_M#t!JiXY!MJLes=e7vsBmg|DJdJKeVUiVM?=a#>m!Q?Y$&GQcXpG^=mhV|L2pk zy4cL;UE2Dw&087-X zZZ37x9-oaqob}syPbcZN9me|x#}bLTX*Cff$TTYj{-n#y-ruh`rv2DOMxhsJjOX?3 zzx4dyUcOK$aHXe#D=if`TkSM(>zM=@Vzp_&;3@4?U&rnE#8*~m^$LL6%TTPnd}^!# zn~9Rp*{mO1By9e2!k8377I9_RuXAquR2m$CO)R?i)IEEDU{ml|MNNU`E>Sh&Yc&A0 zuIc4=3T+;|I}@uLzK+-xij7hcBuzr_uA&$1q^uGlUfoeWN?Hg8#+BQ^?aZiY1-s2@ zv(_iVY38=TdTlzo9ZOH9r_fXBY3Snm<>@|uw1x&SKggm5g+^AI(R$0Ni)^Lz+86UUW0xtsu-;)HVbg$Y zAlbOR$-sopq=y~ksffw(8}-jE3i+AwXopg)yDPL`7>i^M>S=5)G4GBp;*4()DQ+J) z6~zmR8v^`+hR_Nwi`4`nWXrS1@ERW4*zU=V?I~vOJ*(%p`>GmDwl*0dl+JNL!}BKV zAuZiaB^E^mS_WPIv-)JRM?;hB_9Bqh`Y^#w+)h3BABI<#5~7Wmu0YNpHK*JUHziTy zFMz{Bzbjeu^A*!lZS`9i?ZJM@<6|4ju?*&}y(bNduf4xT3OND0SYRI~CjSJty z7pC+>YKp*F72*U{p>W$qeIRn&_P^v))FZ<4MuXR9KyPM*JZc0o*N1DvZx3vPP>1XW zIKF&aAf9~QK znOm!GU59jr58I6GEsxbN8CoYgBXMrmh8-xApmtK%M%;S4H+`A`k-xAZ23XJBA4kpY zS05+S12~t#@%kQh_{Z&1$xhxoZ+Cs5f<4tV*g*?|oa=)cAR6)L5CF<0zN>T4ZYvkM`{q%|494z6@Q)|L2l+q>2zo0kYhY0tTgRS22YB^R@LbqhT53@6JdouA zRw3oO(+eOIZguc1eVw(ktTbA^=f+s3fAD0gpDjvnG8ilvWyW))cD?Fr-4<_g^W%^U zk30Y^WY$$ugV)!1r+x*(!G{mo3Dc(p*CO>X`6 zF09tNd=d330Tr!8=D`#irh%l4%#UXS<|@7fR-2Pcc21iD&-^D6{VKK*^G60U8PQsW zv_@#Y?ggTYjgwIJ8DmFr^w8{2*N_qXQ`f{1TxB3pbEzaIsBpe5!Sf*TheEfmY?SH4 zd|BLOCc+1#3^E6RWd)~c zYkm{ptVv4MFBt(FvZ32t7SxZT+F47nByNR=|;i zEFa3AL#hUlkXAYxK#wy0L)0V>pnCn@eaIcVPZ(71CfUr^>TGf^6pVpP(x^4-1=$$m zBQt$g9=s$IJN*Ve=umwrQvZDZb4Qk&o#@&&2;&sGZ8Vt*Hkx>;mgSC-Avf#Fc^YddIMXzEo>l=f7yR-v)Buy7EtWb{Tx-OmoKaNXiivQk zd5Q7|{rf~rlcbvrbdD(SKGMPki8af;f5P(+7bY|LHgBWax3hkE?>0?+m!45Dt$*e&oU@so;_l-z?lf zhtr!LBb_K_;Pbc_khk3G1hOJL1{i#^1!2yL9;yvKHSY*e7b;Hr2de`Mr^4;#@(V%1 zPf(btDef%oB-iP-mkLi{NhHXlR8ttdow@KxVOf!X%3o*fm8u0Swb#w395bQHP!vK|acb5xuBV%XvKCH;~-TaT!00c1@> zStcA%7aK}^fBY2v(#uP{h+nk!Y!N(xxf-8u1u2pB3dEniHY`bj@Txvb4796-7i`FE zdYWdudkldYO?-)G>;8yC>E9N;nP<1XMv)g__M>8Yr*Fc{eQ=$sLo@~&6dh7;#R6-4 z?vaLg2+)H7TJfgX`1K|R9a38|2%?5hPXGWnoP#fa*1K)lE|_v&5@sWKE>_ftx-p@6 z&16ISA%VT5#swtO?#Cfb5e7d~{YIS&XROWE12wWV4d07X*GE@eP77TkwiO}X2)~Or zC6<>%;!^T56dc6<;3DLa=thRqPy;5Vc<;UjV{9x}HImA5l8h36zIrB^ueeC^>`)xO zqeaRu?=`iG^2^JUh4E~Hja!T^^xDb$an3s^^z~<1`wbq1(hlfe6Eg`N@si79iQC%8 zrM{=Le-7wslAr8wxHaj90 z9;$O(DollyR)xqeVy7QeTl!*&moUkTR$K0unE{X=@`5Xp%s`lATf`~V$8@u>Lw)_% zT7%vCAcY(gyp&m^3gk;473jz(;365v9h}^2XDU70&Nt)KR)))>`JzclSg)5J%Zc-Y zu7rFO2&C}V0^pTnt%;0$>FZE^-ql7KvxsMFft2hU%2Qc2S*7hj2(t|1hS9xEX(Ec1 zPAPYr@+iMbTP11h)a~E_psu;(5k zdZSuj7~MR#XOF+0KEl|q8S4BoD$U6Rn2O*kF0=!bNZ{XQIj&b@3GhEb;)5E0z})+Q zFM22?WN^lRG-&>0Vpx~TGq zxbXn!JY#8*k76y9iw}c%=+)Y*FuolKw3>9kKK!TA6H#hnpMmYTmla6d{msekyS~Pr z|6Jm~JmAy{iFwVbP;ritzj%aid$k!e^saoPwG?C#DD!iX40X_;qevi=Ci3F&k<3C+ zeKOq-Bx1OHCwM&esV4C_ z4)gq?p{zH448lSfpI6qIko;#2kTKIsC%d2!gIEKA{S-zxW_4$eO_lL)3z1f7{<(IF~SA%|08@G=i>0RJ$u{YRl*3Qs- zk7nI)>a)Jas`G4zwy?cXH?*|cieYsM#VVj)UQ2#6m>8+!2)`{f;kc7wEUKB#A2gL7 zdqdnf2nt7Hc;0bAi7!ct5$%HCBL|xpZ)zA_x2>ukY-eA3rJqUDE1%FsoHr$Zo z5ZtA;lDf5A)%<5vy`B1EVrNe%a<>Mtt`|pk5UEam7kvN=@wuHS@P`P_f*E>J*g@7- zmZzzxAG6%E4~W@@L-HW7St|cgfnVnMOU6C&LqGH_qz?TYV}Pr=Xe>$om{Lp%fGh1i z<~zz&Y;IB0>1M&P(nPtG^JCuoKli)pJDj=oz=S&tJCW$bg8|~bNYvpYTmsoqTo(`p z)i|S56!Elhb)!#^PgEQOno-+V#{=1x9cP}28-2JmmVXsLr$<)EeW2g`R8?zJrA83cSLpMV91>KG+nnUda_Kr^W^LFBrK?ZPByhb& zBoq#~%j_zNJ_Xz-PvAo1paN_4?p2BQLt^*>{4M?5k>VtLsv~ein+8|RL=9*OT|e$% zX&%m+1+_c9{1HhQ^_*9ttWBoE>TPzst)-ZePt{A4ZV*B@5-x23r!`6*^470DehQ02 z7^uvY8*?(UG>v2h|}QKyN6ZE62`wfcy?mCE|Eq z*`RyX_VS{o-+NhDEG-2d378P&HOi`KqI7GG z9y2}FINx-FVo&+_5|f0wq0{V~lb8b}dm|GOlPqPGiSQ+(#C)&-_v@pLM#ShlbS`N= z-oR>9*rZjNqkn-V7#$Ln1?+~tr(+6r|7(QAzJqtHmE@9 zQl1@I(Y{N8AN3q&pZ&BK!ll9)j_=+4no5&Psga~*??wn7Y5{n73-Eq1$YP$kLUlD$ zlmxun1qyYyPURA8p&0>+pl(@aspA&Ii(tpp-f(7|*a<>|cbaaM5Hnu(5kFYUd%Ig2GA}pHijB zQ4{A$SSEx!Z5!+K>Az|wSOSlCM9|o}WKp$eJhJG;nmwsCvQvrAhzswAu3(y}v3&t07>n9Mm2g=BzITda^aW$CzI@N}&G zS14U?Rda=WetRibgY+(@&MB_^PHV}59H+-i;T zBWr?9NTYSAFvKB$wO(YKCKX}nib2U!Ym^ ziJCc!B%oY4BH@EA)dCydn@kF2#w(bm%aw(=Qizr0Iy1x8-63_e?8y;V@@ZX7XGkqm z8=bhD3paiLfYsJ?P16WU{wjS7-P5$Xl?^w`cNct|(5bktb6t9!%;ceZwK~0Im^DbT z)U$c4)XT8fcH)u1i<7H_+@DZwEq!n)M8{rm+jX#0&PHE&1qm%tPFKnO%K*e^xL`M) zYaJ8;@7xzs*2o7{en}e&c>)PAR){}eTi4QE@LqQ}4KQmGsY&P~6cYtM^7?!nfGGu5 zo3u&5EP1-Fqm$Vm*T{wmzaxN&gjXFus)3RKsD33?1(;$k{UY@fTqnsT0&ELl;j2wO z1_87RJo$FYC4|d3UxntS`%P#Up6kYijE<*>;}X4b@H7{My}05J*rn`S#)D@jIMn#l zkVS~sIU-@ZL0S<-1qvS7@EWhl9*cqCDEYqQGeJ~+ps@I;&8FzTSA&&hubFr7PrjT? zItqpucsLM4Z`dD{2JO~_8VqJt%xz5w`Q97?=ZNjC%@Y_Q>jpE}f?yAh;Tf$Gwv(ra zNLMZIF#QP<*7~g-;^Z1sWDdEaor$T>QNuH?Jg_3ZjawM!{;6#*HM8rG`sz1WfCto= z?`bSK9Pq@BGuLOT?08%Cn#1~T?2>BS@Z|K6Z*G=#Rv0UG-mU`UK#G-MnR71xE$ZEj z?-QKqE)}>CyYDhFLFW9PecqBcpMYF@&HU{RYry??1U%qJ`M^2_$Cqwy%uG;M4zLR@ z#fO?(>i#3yz8ycqoAG-X=~?&E>`1Mo$c3(&e; zO&t%S(q)hgwIl99nfd_$q*_7t<7@x#QK`XLU@81d+-(iaMIvtUT zs`5ZWiCgT{X#7>)eFL3O%yDt${QKqDW{8yZOJNZ)2A1(RKScDRe}2h8e}2x7p8NJL zJ7jw+D*m6JV`Ia<`EN(De*f(MC*x)RLyO?IgUI$@hvb+%a<{+C{e_^*xc0xUIl!x2 zet=sh>%b}1H*J8`>?p@|2Y!E^Z(+dp>c)ds({KP7%S&`h@zTst)zVaV?#>>l4`A}R zIlFAuXS$ocB1eOP!`~0S2**&DTXbK+{2dYbxAf08_kGPk^grhGAkz8!SN?x6*~j%N zDf}czhoC{4V!E#si1;{=;3=L*{QeB~*#G_dE-|Q$^YBqAm|;CQq-c=+!xT;p1Ga_y zH`Uy=hXV)ZAL{1+eFe%N-QTk}E_ibd-w?DOryjJ18?6tdWSbS+W=cTgNdlMUVcL&H zeStc#Rwf1|;RZkrYy~NO+cXfK^8EPMwLgviaktpMm&To_|IJgihDtU5i%-9 zt*`&p`hqP4RT9BKhO!L=nVaIWw?^k#ox#gx6{3A$ip6^9k}po-A+KE-5R>qLN4{2t z;6G_68WRVaBIy@sjXvuW^aY5r=1T~x$TqCgi%wD?bqbiZjf2yrvZ=gUan_U83{(F` zC=3flVtkUJu1@>Nr7vFGu;zk#w%x*P_vv7E_;i*+td3q+N+4{E3qx)hQG&l&XuX3~ z5xh)VSgX@-UTp1}mj~}dUu`tSEUmK>Dv#ZZnCW|I{v%*M%>v9DXvkF_H}+GH&%ye+ zLts<$*Q&oa0P|@g;7z-!#dnNbFC>ycERSg}Jh8G`;yuc=qGHI|G80|R325XAS<~>kBpzx`O=Lu;+7~UdelSyxkeIGUt&`M9j)BDT1u%kGJOA`6(>r8j9<=7( z!=0v9ZYCamj}Gz<-gESZv~(7bK`i0`P=O4-8083YNUp+&HRaSz0yoc+D%FgA_s6jw zd+YZXmA32jjX5}q-u!rK=`X$xwDMrXgP@-+0F4_5Zf#6ZkGzA}aYIYJ1)8Awkhe$vI6&Y;WfvNS10AQW80yAQ9A<6@rX$=-W zsv>h88aeHxfiSWdly_5W4lje^#_mCq&=L4@qeg|pA83k{^No>Td3|~eeOee6@smQA zn|?virL_Onv)=Qcp!qGJV2@GTOK6eIO`!C9Kw%EuCjlT*bNk+VZj#Oe4h#6z>(as| zHva?z;*nBMhs&AB{3%G^VOGExOP3cb{72p_rzTzyCSX0m=!G#EyVy=Kw<1FY!)o6$ zXu%s`c2f+bLygB0UrgfnsY6~F@YpPPFglQ9g;^C)%qKqYIdBZkVf6kQtoCH^>UVTD z-ZY;vgnOz5nQ+|F_F$?|P`5WAb_lp1*B)G~zFMuVer4Ix3Xwt@xAEwt3YB#uh{66nfH`eK5&qW_E?qyWs0+@c` z%*nIws;$F*6_<@YIiTy1j9g9v)2Yp?8)t47S=XvILesH;dE}a!tpOjcxBo|oXONdT zC@Q{?@yCOyE%py)rEtB+_<&8&H|fbqvGS<@s=gi_uuz?qgj|llV_fORk*6H2e}=yT z_z^j2)Q!c?zp1|c5Z=sIsflW)iBy`1-c^0zqk}z~*=trzK!K5So=)h(UJRU`J?_w? zDjSzP-xZ#lG}hkUQU!Q~7q3bh7^$6JEAm!IOMQ~cEgV_50u|Pfn4+e}8@t= z<&q{@6j@0iG~vX0$sc)VLfT+#62LCZ+{_4`^&*G?dwT9RWdZWef*QkpKmuhI%6Aro zqL)pILY&+iSQ9+nI`#!(O3lF6t}uOq$Sy8vVWHDeJJV`Yi4!bZf~DYd?@|BB-bD)# zyKdr1f0~Asghd2{U{Zc>osrFSEMdc8Eb%-|wygmuI$zd!b@sn68ux;bU-O?dw4Deu zRoX&QkdcSuS?}!H#D_)wPc7-eL!{`2aMG>;-IBKR29SZ8u3POR|YbKC%$8uVncMt z8JJnlMoHk0E5!j;TQYz9m(h0#T86PmzR4-4N)ya=kv)631y(_zcF=rL1Gp4^oaR19 zUm>1Mb>C1Sff+sp`TlM^F7L*}f@qUOEPlirO~#hbk`6PqyF22{eAE9v5GRcaSHLQA*dgRt^norv@Azb zNn3avsK)h8gD-6M!Cxc($WM#DHW}1)bq-iXg}m%CIsG=oP$sCVJx^*N?yCcIgEJXX zZKK-X9KdwAb0KeShx+-raJ&qw1^Y#dH5f)CDN?` zK3NO*PE@;gb3ql3^k65sYg)yKj-)uAxz*$$+fW0Vt6UlYMLCyue51f|Avw|nyyJL$ zcu`lHq+;EU*QG9ujuH&3B&QfWLJsOIHEP#4 z0enj^RsEz%_AEi?A=qLp-Mt5n8x&lX7ZcBRLvct5?X6yB6$x(Oo;r`Y(2o<(`G7kO z^qlU6kOfZ~f=%*f-GSNhr1Bat_=0&YDY3UK#yS%qxJq3hy3xRNw~br%apxEJfVSM* zxij&}Sg$A!B5i=&-VqmxsNIj%1>w7(tz&BtO7 zBDVA-6&lly1`}F5Y4q994zOL#k6PZ&Xv%!im2(%|-JuAdtz2oau@K*AtpIM35#W{t zzi8$C^$G@G>}W5=UxR!_W@0#LSJbP3EL-w-Bv6Qx8`YZC6PZ|4(P!zCA|HELmL<(4 z2mB8Wh02pvP=*HLDn7$3;5~1c??KLkI~3Ga^6IuWibEsFyoWkhXMwoU+YjPZ32;zz z$-q@roo;$vomGl#zG%Fg2f`kliw-T~X~W@Aa>u6Q1v z_rBlQdk0>KC}@nPHbb|EFf^1{C;#J%h~j7}sTN>9Z!rmgir<>;+)}qb1s2Cm)%~;; zS>{+M9g9!|k$B~X{t}rGv#$2jWAWVkTLUX^SkJV9VJJ)C`;NEV;~?TegYKIF4d2o) zxQjM|0>DFM5^L72hBSExEwP%eb2)P<}|g@Sat0#jM2!vT%0?%Y6jvfA9tT%&_Da zH3=~KE4R$_77>X{?w{pAF9cT;Q=wawV6INjZk>@B19Nyb%fL83-w~)O@VF8{XdL9L z+m>CgAeMi$LPg16#bAypjUt7}i=?n!{)F&X@SYZC=j8K!TFwvS?^u-`vDI`NScXbe zm6j^kv@C(8%XwXJE|zSiN7Rio^@M>1M*&bQ1~`?QTYLPn5AR-HBVLiPGo<^k!WZE` zYqz)7oAW-)5my1ev2kh=9QS<>6Yk-5;ob8X6+34PhR>rheb!mbTO9WsL38^1mNyCI zBOoc|qbrTdCygbu)KJgop=iL?ujt5D$F4g~k=+ufQDtf`o;-$`f|?VOk6(g36d?Wl z+e0b0IkDrRsDuBH2i|?7x;o$y*9t6gE=tfOHRs-_0v?n1iq5?8`_y^G7UZHZAuoc2 zzIE4#H?00p+xOPHIa0R6JVsVx|JirB?ACC1?TVaecorfwUqx{VVoIC_?Vtzwoc;zb ztSHo6z@*)g$}Y>-1Kk?;bDmfPD^rx4QxewIC@=IoI?D5Y?tSljPEIVO7rQ4!o+bk|oHuapX< zqJA3)2+kb6GnF0R_Y}$7{G=JW83>Wf0*aYI3u%uyd-)T)j$j@%ix=T%#82dg^CYt; zcTN8SG*$%i)@SbWLAR8#0KzrB1`;od=(?4V`GM&dy_w#jd7V@X1Zx7 zDF9{pl%R?LZaqb>LGmN?*ULk6idm5CP#J{5zcqYs>94L>mw2g%7lcB>UZOe<eTld#YLM8+GO-wMHi4RcLUy01h6<)uykrOnWwV1#)@synoMLW-HVz}?TfhN3e=U2Ol1L!XA5GQI$+H*YdNSu$-R*6l_ zp$}s*8n%tOC)~;nIsK!GTP15#$23tWpwS^L&Mc*@!>?&aL7=te;|5w|2!L}o?nQ?3Q zw;JI1(U+APu{kiK>@%i7(`g%D15p$k4f+JeGp+g{ki`5p>yjxbqZg(CLivGbj9&KZ zu94I7glUt&h$}60&%xtk>s5fR_w^;f&P*(}`yj4MQ)8@)C*)^{SRq!hd@(A&geKeS zw*={ACtP1&g6=T|8m*ke0=lUbQVf)D+yi$fpxphUdq54$Zi7_2Bi2DxW~?>wTha>o z4XPm0%_*e4q+aWwQWi8VN(0+R4E){)0Y!Cam#bSod#uE4{(i@+q+U`fBxG?S+8S9LeWo4H<6p=0G3xpx_?Pc1>d>*l6f zv2)raC~uURd=y_fnBlCBAS-Xp$i;(uujG`VDMo0qFhv-Owy5{N*n1DCD6_3?5VN4R zHi!y}m_RZL0s;bxsN`JapdvX60!maA6(xuy$w;Q4idf{Js32KFQDjg=GDyxa`;>aS z``+pM-T7wbU*D|xYpvVeR|!?`d){;Qe$qC?>U8RqwVHRREa{!f52CUNC4@YP+B)BK z^n2gKy-_g>$b@iz;WBeQQuo<&oTG8!Wj%W%(c9lhH)_;WxJ-?X2JpqT5e+M$qd5*# zL+4vVq_XMUo0Z1(Mg2e}cQMUI)pVdMe*v=mGK6DU1oV(W@6%?o$on z;lRZ~eRPsA-3c{F?>}PO#;-l4irG^FTloNpsM!3(*6&&}y^KYvPM+nH@L;iYiKBqH6MAsDDx z&_dp$fX=}I09m*ZNgoPmF}?Or1R21T|H64d{@~~zjQD>KZ3BGr>udj?Oy~Q*N1yy{ z#^B#u(y|*wo$o=3dzky@HKL$c?EB>>;{Nx(iezvPW%ZL&iOARD&6C%3F=1_mx?b3S zCaFXN|CHXRa^intFygs49q;vf78o%*h`TXR>sbimkGQ4DcjGStSRNy=S zMTejOo+G#4|L*b2|3i@z9c2^>g)Zig~`=q0(X!2y4_(4x@Ys zlmls*hACx^F6&@Qw!l4`L!ges3x))_8j41k)jg9<^r zyL74WLMh6Tsi~^>o?I_vue1kwSTMvMrRNro$r@L_U?K^UiZDHsC>aqIAl=`QU`>Q zil4w>(BRC>P@Lb<{?&>(5eu$+WxmsT1x9tQUuQ%C8!{Je!h4T8&3@&zppWiHm+ij8 zxwDnWie8Qv(r?rpva6W1-3^bis5ryZO#|*62ozx-N!{O?-VR1A-@o&Bp;#lo{VsP|H(u zu613Zl@q#wxrHu?qaYGB1P+=T1WPiy3vfMxkcze#6bNK+3<+^`djn?*A<3v3{#JKI zu>u}-ZGB!)Rs~=d5mRc zm<7|o56rMrEuEwZaoN=inEsNZgK++6r4vyTjzp+u>nFi;V_h)YBr|&UPM}>G6o(^o zC@Y{EK=H=AMqe|(hQ)svKzjG|OTHp2T|kRfF1mzOIEXk+)A9RE-bU--qVPSj3Rnl3 z&EA6!M>d?nNilMM74TKv%GcorfssD$0+qpVS$c%{m;T9^A|kq>D^?KluZ-!i)l)2Q z-7!@?;nL&SVk@1MiIKz^P()!lx6NExMMe~IYs!1Fft~n}TFk4PB>-kFXi+4^6*r)W&gC9xNXC=JTE$jB?X=x@14GAP`-exfrzOI`gq7T_F$-k&&?noZsie^&!LiHP2V9KiPN>MwrG zzjcOba1}9!IsH`&T$2G8)$sNn4&7(*qm2O#XDSxXqw5|M>GHzhMPvKjc_ghB;-bR^ zT!>2rBhXzVX2WlWd)8yb4H!aW$mGrGxl>1wz+UQddtM3t*G* z-`9(3{#3by0c~+*+$O9fv=qdY;BAe9Ba=n7g#co zKf{g*)7nrJTPSD<0v7mgj`>oO*jh?yFN&m7`pIx0*i1{4l~l%y!oc<{pUNNx{nhco z^QkeDUd55GfxGe?S33!+SalS98kp`nZVv9L^ckctylhXYK6fhr9Qjh%i2ITcjE<@u zg4^3ebH-(!vR}gHOquUd^pX1~7l&7Al%z?r!9_MqrWI`A9lu!u7G{~oprRLkAJehQ zv@f9gQh!rBY`K^u>JjPZxtR&nCo8AFJm=;=>Z8k6>jm@?m@Rg%iyEmG!n{8DyKx~y{r zxT0{G^X|Ptj~1viM(`6leo-!u`<;)-g(`*EeqH)ob|Mq86S&R1+Sb4k<0t*u3`1!{ zuB%`B2SK6pd^bJ(cB8oqXo>W#&ED|6R0^Bb00{3mkevy~9G%%S;RN4a4OEok=@Gz+ zRk)6`F+Y36&*OaBa_*-&LuMcf6|`y-rrR@+d-E4D(J`K|xf%It=y`_a=ThtE7u>?2 z(x)%8=X?;1;xAD8$-w%`WV+=!l~A^lIo@4nNJ(L#X%@pKFe>=O*VYOGsM*N$Z=GbQ zW)O8dt0M~15NMS@qPwlI@FXV2HmcuDBysq9I(dGqy{n0W6jK2M1UYL#`8deU7mBL zIS~##W(_>MY7@xit%k1A8Pm`gXFvMlOP5D%f&U0X9#q2UMaNsk{4~Gwx`j`@r&ZH< zjRYTOn5biK#!9xG6nJgQ7h+S9f9goU{GF5&b9L5k+1q1JV4hIFU;cVpOq0=1ZZmtz zsle;C0OK}mbQXZ%)lE`r@R26Uj3r)_^-vDg4KlkzS(+oQT?);0Zck1+pc90bjbNBn zW0z*Q^XXDtP=I{j5a@w9%htxNN7GUgRha>d_(4d_KtP+~KPZWLipamABnl?}g_4Mr znTvNxN0wf#%v6kr2HnLf<9lH3Y#9wPkfPu|{@R6GYwjyL=*Na{-(jLnAm=N^FITIV zD!)^qbYc1!^fuCW(hka!*6ZEK@tK;HKt)8fej=b+suT1W&YDkM$uq^nNQIoz}h8c znxlvwCW#L$rs^Sw-?b)W^XpSiqtMtN@qlcd7KOu!e6Rd%q>V9Awg%4N-}H8>Lm9rM z;BO28i}LHoVPVw2N$c#M8ZzHShqZv{aui%w>gh}U)XSpocmduDictxC9elp+P76{e} zXvj#aYz%_ioq+%pl0TO@V(Qc^huz`l=9+U z7k?bgh1v%)DPWnuiH`$yx4{hX}$sT?iVa&Xsz@{`QsXe(4V}IuEyE!yZH)SpXrCek#oXJp*{t24D}yM{8qG z8S1K(t1o%m9-X{q!V%=xWOfD|FW`kwCY^nqe8kz@BpEV63=yLBkRc^E2b^5Q>q@?Y z(K71FmsoMD%FMzyV(a6V)$opNqD+c`qmc{sQ@7khQx1rf92HsG9amI&mLE1no1`u0 zDb*5)`jwLgP^nfXCkIbTZhuIfZ{}ugYw^pB@eKs96(`XS^6C!KeOdswkX|?Xo7n32 zMrOPNGDqVAF7logs6hdlwqS%Jn$6Nx*5xz7PGSf3^&PrO_PFv3cuM zcY@ZN8m|fLLWPNWNWYw6?1kQrMDEFeeTr;H2bKrzBt2i}RLSIX20i7u`$ADWcMZTc zk*g+SYtx|(E{WUYsTZY)iLn33RE_U;xYhR$eu0kPLc>y@M2vX{^`&kq%Ru&6TA`*2 z8z15E0<}bS=>ZUkIB}TP37o}WGmgHIdYj=|2c@rExq^tlIS*db&Od9At}hg%{PggI z!!thJLOk>}|CTIwz++ych-cGu;p1Mi60#X1NG^e@m%n#r{1dAXeim2-%E(hk&f(2e zDSP8B?AR9XqbZ3?PnBmQ*q1EJfTZ!Ji71`+d zG}<(UOD80Ea(>QG;yBq0q>^#SO;5Q>vFs$6FbqPmpv-X`;P=(tlY zd$pJXUuLL9HSDoA+Gl^wcx5H#>nq-Otj8lBy+1+g1Hf>B{1yY`Q7(YxVt&R9`ZN%9 zsPrs=kuzme1Ts$Qm2IsM$~Cm$GA(Hv8;(|NCs)YAa`|Ldf&O1ug>Bj2a&eIBnlAUe zYPZ!L=JcA5Qce2q|c>!31$KkU63`|WDADge`3KvaruO~uC}k=ct0m~ zU0fegFT;-4R4`?GqWE%pX+c+LU4ulGc1S4InHTWA~X&JO$&lPT~!DHCV4W*l3H}Qes|PXcX%3}3q2nM$2&AR?QWAOG2=#3j-8AR zOC=0AK;Ch!5>p@&CeGdG@f9ZTT=?O>YMQJMGP|Ch-Wv2w z&h+`K!?U&V(!{u}=3zW6FR)UA^FI6?$w!cGpf+Hf1VTD4c78dF|Jajp#`M9q111)N zg*nkOrehJ4ZAgU;R$4lOvdVm!1`aNcIAv@&!3do_UUmCU`@7-R}Kat&08+D?1^82XdOYw zT`>lc9qE{f?Er4zA-mKT;Fe&ZbMsIJ$G{^Rc^2SJTs3ccG5v`LppM=A$|FIp7Y*Au z3d++g$mR*$!`~M3I0^aGZDFqqK{T~2A5ql@_fw)CBl2JA=g~oqUibHs{`~+UWv_pv z2K_Ie0Q7Hw?jP?S-v3|b7!m${Y7(?JCB*>H`h@(vM&L;K4&LxW9$>OV{yl}#GA^y! zej7ZxKVN~sgrjLtSNZTol4<^5JtrE=fa*B`q!}c? z?$4k3_qm6#r5>kL`T%ApJ$HuzI9Prp69N2MgGyOYg6+KYkIUUrO~%m#Lc<_8%e>7D zbdQ`!nbGR@^Vd?=l1lqhM}B5Z`l>BtKY^l+3F|1aCK$~pm|KV0rD_EsLkBrSWC=oR zw6wJyW=CLR#TxQI*smZX<`I|xh4^Z73-UF)XpGz-Limo`h$ldN3K2x*-VLI_D-up# zuCOGN2?pLDzS-Y%HJqjR0q|C9!jgJL1Sd?s`i{W5D-&%FF}@V;AH>#1m7s-YMt~ zb4bhquNR~uFPMO4n;FO!TKW==E|l8KioH(t-ZFTEhjNi7dQk#J;q|SZfjG*JrAs?P z$8!)BV5Wc^F_1ijOc;^JiJ+8MEth6WeU!2etPOuF+4c6RCE`tFRRTk$hA<=+t*dTq zkz~%{-=gZ@M?~1lJ0&pt%L1IwlQM@UL6JchRDoA?Ow>#zW?vLng}q?%{ACTf(7^Bv zOt~tqzXstg3QwPDHL{j;%*;TY$Bu@rjP&QE6#<|%T6eRf3u$r~h|cS9QPKtiv<-`j zMS1PB>QH_HKQxV6h50E3>8+*HxRnNuc=W`V^1qFTI@>!p+Nfc*_6W+T(ia8D-Dk?J zK(MYh21j2WoKZ)~w*d^wG#tcLb zP+vPgg)19d2}nRI&2(fl$x5?kP8f1c*rBQ ztj!jHMWyc`M^`))Crg>2Y}KuY#JB0^`l~l{L}!pS+m$Q(!L&~G;f6Esb`QW~ZenrP zfl`s_+#E`qL$P{f4H>Y%%O)#Q8EhgmH1*XElrjUiTagpXFAJC)qQgBDm|Tqp`XHwh z{re6GBr<1QyS*)?2mCu)6P(243N_`zVOZ>JWKAI-pZ11*V88Ij>da_uN^3vz514zV zBD*sZdqXa|%66*hu-dfh+Jv8%?*hqb0xf!qfI<*i8$`TLLV05_yi*+`2(9d0H_IT`emhiqHE5PyN3SbvzbOx*;eO+-0uHyLoh1#neM0XFiZle( zmvtao!+g7m43rnvP+n6|MppD}PJ`QYDT;a<?Ef7iGCN`Z~kTn%t1Ie-?3y50y}7?b@sQT3UZ?YqN5XP$xQFdQMN0E;ypgcV9{q z>;OHXTwCaREgg6yYf2vZX>kH5JMaq@uYrDuq#>MjMZdy7y#IqPWXL`lSu`u8y~8&} zU=K}pUi|!o^qmOJzHoi(!@8L&9=MGpuM9YiO&H2xXJY0?`t}SJ=~Du((*e;O;CwdO zGji%!3x|4yrhw)GF!z3EX;=g@Az#__0{zss(e5I(j1k{QPs3ivnoOL|cC)n;;VQT- z-^V7segM*H{&cR?8OG0E1nlsRQQbr*`MtrjdN(l{xN8_-0Q7)XOq^h@? zw(rtugBGv8}pP*4Qee%yd`_x-g?< zk0P_y;LKY?O!{1Myq!Armkx+(FfSOaRfPuLvrzW~^to`7DhHqaDtoH#QTLsFlE+36 zWrd6_Xab2DF(uKPU{uQ&xudCY6820EayABsp}2XgJ=zRd5Z>0^u$a><^W>rTQlj}g zkcM{wGDtxMTe+Tl} zqDQMjZDR&GHBpT)mz&UMO{O+P9A|*`A9a3fe~pH_9z=>S+U&^ zf!e^wxbXB~;O(9}T=}3Pxf=cn0SFzSwl%S}dllXd-ozXo@VF2>Fw$Jn;PTT|yA$?` zN0`-h8lHSO5xw#4cJ2VQazTtNB1e0Skr~f&rwRc}L^QM0mdH1)@D9}0xtcD-h45 zb8a_4q8b!txmHp{O(COQ=1b#*g7d>cH?CW*S|B9?`={BxZ)5>*yK@;+4lRl(T5DHg zyM-Vj`=Y57r=Y{%p#~i!aP}dm%R_k){|sW={0ee-0fJj#f&51(>jEL7doYA*Lgc61 z2k5;*f}(0P_4XO}^GlPFE8qjnsgMPYnVud%e%{ zvTRC*5vMU~uchabKkiuokdp5zAt^$}>irBaQ+PN^@1ft>38k}{)L>Ng+{fLCW9j{( zGv`aDd4)}(@xUF=L8xQI-7j7P@XpLE_?%?QCvv68k?*he?}3<0-w%lx{f=cH+{23% ziVdIy?9k&jNQ(3fK!)=U+;w2?tkOcym{#Qh9vlo>g*aqGAtwu5XeLB7lLwVRYmf!R zjqh9p+J~RR{rCWJWtt99N(k|u7I;c|m`u$ejbZO%g@BoP@q%`_7OLnuNz$ zP*@OFhXOUsor{sPBF<@G(1`yn7Fh+!lWKn@vy7+0=dKKaDi*grJ4~5b$Z~a>Y?n={ zf#yLyj{yvvn&<&VA*)+-A(i^c#A!|m}F-!sm4A7oHrdoV{?ZP$fLyvM4>Mmni*IFD?!V6{agYY5tw)V%Tfhz zyU`q9*iJ^5&tFPWeKc~n3nh_Q7C5%ucw%1&N+w<~cIQDhW)R4M@=;I_v_}pppRZorgM#B|x*58PcOPY;`EFGQAI~ z%A>R;Y)=7EPNGu(yHJe?uFaJ0YbZ+*^&bZ8sL}dl{(j>%Bbr^U{Q9&^IUO9zDFTcI zQ+;be;g$aynL@tFuzXonggg`MG__2P#jlbPxT=GIz!?Ydg#9VpqN<+Ui^5Y)n5j1|2=m1zq3VtE|z~cnEd}&*&=5&x2NcV6g>;bpCDx5P!l4T zD{!4)ayg{DvmKBBm#C3Fr_ibF!V6*1Tl>Ou+9%0f_L<>(P)XE)f>52DI}+A7 zumpo{Gf`_|U+ajhE`OxFdu#U;^|wte7Vm{v2k;905x-GG?qQ~b(gTqy#{w!~6bdu| z2a1UW@hGw;kYQ{D|HN_XFP0yq*OqnJE4FI0^cHfQU#qT5Ygoa~%#GY(267FquPWhJ zz{8#g*h_W<^s0n+<*iAsHGHY$EiXh~JGs7&HK_2Ht#Qn{AgUbe17# zgkM~RFL-i3EW6!{M!P-Av!sA`E`u=i5G*4UVLnBF9ke+i-txx*inMDNB-JiFIJ}em3Bfht}fL`(;L_*TS zTs2AptSsjZy$hFvo!mZ?X*!e`n0urMJ`MrtW8e)U@gsuGLQpdAYVXFHKH66)eoE2% zw!El%4e?&)h=DW9^TeZSmpmmNu{n_GO&&odT&fzo4ApI?Mkj`ljYD>p47=`*?bfnHE=o$PsCjGpxp8;W^Yji$42vt|V#FkrVw<0qF{@ zUk!9f8b^V?TXu0g=iDu@kcranLa*GLoN8=83$6XIeTDM1NCtPe2Dv48TNrj7@Oby8 zcH*HzpIbvy1*Rbchh#qmmplaIzD2)n{<@^o49=5&ol&*ns_2DU=M7YvAVDMwjDt_B zc5h?s^osY9%RNO)9RN$bK5E{Rj_El~65B$9vcd}OSK%sAP)t7Y4lpXVMf1JWhC|Vq z(OQ5g>@D*8HOv(dSV^EJ8bg95*)j><(T{1-03#H-d_Bp?ijv65ar($c=tR>Vc(`dc zTH(wPSh87=ZqQsNfA+P)eXOR?5^4znDNtW3KUk_L4-SrLxRz;;W0Bq*n7$1Z@Z#Lv z3&4dvBeGI+5{tncLR4-5GEdK-W@8kd3cG?5w;mn}j!@#pMPh;ac}P41q`{9rHs7N+H+yJhY8TD4mbkU%yU{g+V<{ zu($l7wCwN|#Lp8L-SL+7nFgsP#qRR~u2!n++MiHH0W+}+=Y>8z16_TYysK`j)8 zXO<9)Smps_O49`I*a1EDif)^xCaxe}j+Y zE4%y9*9abp7g*JM4QL(+Qo!*Ilknx;88Bu(v|vt`ax_?!swxA(jSKaljcN4tih;1wVJeW;kP|D zc1UJJukD@2Ll&N^#YtmQ9zCn7v*4^T0m2pBYYgoAJQi$E@KKIgAPj~mm*N0nCdIG2hm&O z5Fp2c+|TxrRr8=DGqU_WWZs!PlHEH7CaY7^hvXcPO)Wr&G>W~9$ZZYej z5C}1~obo*tPoiF%ZDWl1^QPvj?=?FooV-Y~LA?7+66R%bDn|HeGUAYW4 z-7P$VFtqB}qvT}VN)ydGEIdwhlA~6l9r;fO5(A~`XF}Tp=mZ(qSqRdEBov#CNEMvr z5|ZX2cTbBVrlZ`X69nxmaX@ctZ6HTde!w<9h^7cm1M+{a)i=-;q3!*A>@087 zTMg=+le%?NAy}j=Eu)-@phbjM4yoykjo#8#SnB1sgsRUi+0WKD7}nLl~TYb zy;#(8hj6OH9I|h$0*=E)CRs8qK(91_vgroH?qgKcf1Ww4cL8A-J=KfkDm79GG$&}3 zc#re-H`0Z`4S6aGj*yK9KE2nZ`eF;vP`&LpsC)X>>`|OpG!kH~wbM`zqc(Yt04If` z!FYbcTIT}jx#?}I2iKriCN+JeTt$zkAry)*)*1BNsgF~d@Z2}B$oJ$nYf2Xq-fjW^ zBfCb>6vfWO=_ZtGi}ri18*JI0YEVFGQKsB02EM8}*`Cs}4n$6bgzFyaluM8ziUZZW8e#_M$xAo3!)_Uh6GIC z##--25IX9%r%!h)9AYEg1g&&hcGL+NTC%o4`lQ^kKhfIFLr!o*b*$PMVKjtgwcNUy zl->47Qvy#7l>ew?WC~j!r7%>INM+%Q^PshG*s`k&Oa(}0Cdhg zyn%%`t10nJw6=#0iZ&>DOj(*hdlUQUih5=AD7pUre(7VIRfQgs4`qQpUZBg#~HGA~RNCoJO*53T&7G>9?e8 zCto-}y0akd7W-r7CKTew>l78s&m+^FUof&JKMtkl8G&R*{n)LR)NaW2G~#0_I*OJ% zVOcesQ$L%i9}F!?4C)F7HrC2E)Y(sPmdrK{K=y~ro=r@$LDKT3Cqu5c!aCQvEK>KW zp-o&B{3%rWFwP73>CF+cHFQyj`em=R93B!=k;xGe>qj}n?9PHy&y%49pk-(^*o@JoXG?{ zK>?b*M%HQc(1%sO>{AV{tv>`KbM_SfO3p-QCSs^z=!ru4IW)-NA9Ly;g&w7}?rMtP zqRA^s)O>}NdioFj&#PD%I7a-aXNler`DH2n$KU?XR|owCWcgdD=`QUaTf@O)Wr1Vnw^DZgo^a*3#K)H>XgzPG#J@BNct*YEKIvy?HRv1a zY>aolT{pUPH{ywNLxiAReJJljql>e<7~{{yjQ({Wr=3@LM9@~FlvyU2gUjw)ZSJk= zK-Q`+yVj39+ef?|Yd_j*^{qCv$6AV(U9EO*ti2hNqWr^KEXZXIy`q91J;-g@6;+bdo2Z{QCa;lF1VG z5&6I)c1MXg>r8YNl<+-Sg*+asnqbZeKqhWO4ra!zj&y69W`Bh*!{}8X`hn?hb)&dF z*2}ZQc+1Y*9&3LQ&;@ZFKmK-Qe2CJ~rSK{O6jC)ZV~ZeOQ>W@B6X%s*Q!&q%4sTq7 zDC4&k8H07zTJZRpq1U4y6_z!gE_U#p)E; z_H=x8U0)i+V^Y=da^d{^2N-kANnE59mD4Ngm1?mPlnda)E`p=Gms78}t#f2wzcXC^I9nt(-V0_jClZaPP3IrG0m^Q(H4De?*DDH}g%(7tMRKA!0EzZo*FcW1XO+ z=!PVoh`U^c+@y5<$zV=xBmInUK64}e>k7i-=bV2f1K6xKo?rc16`)(@wx$E$uM5e{ z7Q1!&TN0#$Z28PvbH)#FX!P-0b(x4g>BzMVhyI_$@yH(j>14il37W!gFsAf@+k@_~ zu-d|tlY5lbU^X8fX5aE3#a&nTq@uMbVT^6sh@T>*2)}Pikm;@tV%POMDq`X8gxL}TkMER1e0L!l4|yBDWBRCWsOgrE2C^1Rxia$S1h)tu)nB)esXUPRvmulxNC(8zbUq^MYmTSN-k-~3In zDvZy(3k(tFn>fTSGSSD8)>Y3+8+;gs&04HcYTwxF)VDiJs^uF7<`Fym~RS@Ge5c8PhOc4F&` zafbzM<6SRd*xz&z%(XqagU*`mCE%t3$DNj>-0+aKevg;P+a6+O&p84=@58rG*5_{IUiUwN#@k5j3#4#l5s%NbG2 zxcPy~TsV0|Rp^_^X{FS6Pby-b?`QooJy0|F;}QCOU+naI>iB1Q6qpws!l;#QW%~|D zsLbxIaHDJN$J!b>b@D$|pDhER1FxJQ?GV`#E_&$5Gs8|3R6b2WiIhWaS+=oWl*ezc zS||M(547C}B*5oa0m;TuTUZJXXcVDt)P;LvtKkCH6BT}plUKbD{m#EQ2OFK%CkyyZ zYOJGxfe~7tfk57GuAg+!lze+(T^yuR1eWg}-sW?8Pgon;Zjff~fC&{4t$X3eUut&O=sgx5h!+J z3=Z?$dWy4diuVF!b(CW@p&#S7a)47SKS3s>5T3@4TuNoHLEzCG~Ho(F{&`4!Q2PEftS3aNUw`JCIH>XqrX&0Wq)V}-@-rd4py9eSmVMUu$s_&XU%+4F1~vku3dws_FK5S&f4fle`MLI z;C3mSVB!3bT3#Nlaeyr^t*I3v z3%`(875wV^G~sMBlifumkR+({Uz&pnaJgq4FkmA{EtlpssAx+9zGr=j=oGT z)xp)@BzCg+-i%IrmSH!H+!(|8i~-*3*j?n92UnD<)xQs5Awt#rOb1=`;cP5^kEJ@P z^Wqr=@i>YrdilbC=y|#{D+zXv+Z8@#Cj5;%7+qc*y87I(QzO|Yy41qB>g5OR03jyn z!0&EC5-TkS2V$>0F9iMJ2W@9bTm2ZmewIVjGqfy_Zp0n- zcZ(*h&}NpLmW&&hQ5^AO+;aML;+GH4EiEu_6K4}&gfLU5YPG^nT1@ay;c11V*IEXU zy6#7mG-InUnwK@t=Cimp0_G{`HXX~?YFnAhHnlBw30c67-+Tc<+$iLj6acO?YT*)SxK=}ck7l0OpE=b;KiM&Xg z&8C{%2LPDJ;WB8QDPEl27c2dkF_ujer&3BUFOC~%zYssa*Fvj zv`U-^B6%8_H+#b3E(f?4IZj%=<&w*2{n}@;2H?g7V9FUbhZxW?a^L&mKFofq0~|vT z0m(6$H>;9orR$74shblWCxuDCLn4ZRWk=3CqpxTft5sv{mH7mvo9+BeBYwREbM?II zZ#R>2Ew#;QhExX5Y|A}&nf1K0)az6Lg;_1$uyU3F1Z)LQNNaj;5_db5OG<~@a8p7F z%-tcsY`!$VSC-3&+AR^*_Q_7IWL?+9n)mdxIXJS zYw{_C^sO$u2%gU(wCgFwUDb3hfnBVg&#J4fE?j{7tnB`p+)_sO)y5L&{Bv;!Ts1Ax zZV8b)oKN}g3@NI|UEO0ndik8WlwZ0=X1U1sH(Mrv@5>l~B}gz}!C(XP43`(nHde$I zK#p7p5?QpjYT2Y3)&yI@R3lV9a_N`4^aTI-^c3*%B?dtD@~+}8tadj6#|fRoHKp*L zERLx6SG>N&im_7`7K5DWD_2fqK4Ddod`CaMei(lKc5L{W8{#iPh6$O7UIwI-SG_Z4 zOi1|1A~U1jo2*eh9J4yz&5h;oh{y^DC}Zc-0i;HoZkE9@E1?Pu1=ZgH0ie zR0#1y^)e#m{+W+c3&E|tXFc(9-pzGRZ= zxSLtwb2+7O19sq>2C0>(z~?+fOw;5Qa9OkwfXDI_H2b>_GW+T-O!oF_(fBe5w<2>U zmvMbW4>>D=$3u2wW$&`P>eA`_3*Em8zxF@|Pt){9rCpdRn!z(P%3@aWN2 zYsfA9;0u^s|M)rZ zU$MfhW|bG zSN%)=vwftUf6P!pfAZA)52*?HEB-ql^8byuL68Mwz}ld@j*TFc5}Z4JJ7Tl4FzE>A zk=@eFpd-k#o-CXrzvEy3IKOQBt#%l-O}SRxBeq{Ze$Fzi`IdF7>I;u?y@gDoZ0Jjl z(!Pe*v3QAugRMW$$DiN)CbMrxa+6j|Q1Y__oFgKCxrh|LIDEt|(ZBEazk>%;*Y}8^POe3}PB4e24thGP0$EjFemJ-) zxc@lzeC)oUQ>RX~mHE4%b{uvtF8B4-2@n_Czy^Erk0~_dA14hxn#tgk3~0fvZluB< zRe;wmYU&^Zy}y3(X%2DKrz}uv;$frQn&SHji%Hda>#?mHMi-UvU5nP!u8cA85~zGP zCw4$p39m&kyY2XEYePRHe*1B@M{}tAhh3@=mG;n%bh-kefwvp1x9YF(={b-R*ZSi5 z0Zv;$UL2rKO7PUq3FOdhvLE{NcD$#gvvd0W0#rQhggqq(Dh>K7_kP{#rz8`1)u(H$ zJ$qc|i@)e;_?f~arbnWKaC|w!M(60hv6h!NuWxp+2u|Q#rX%!^;|A+Oc`NY=cvCn4 zy7O=McfnEi+46H2v>Jo-{1!v});(iC-IH&o$R!r|NxXd)OfG211Tf2W!NX%w%tF6@ zw=3huJE$U>@|E(ex-HT${Z~aT4-2^^WhSCR4;_%5WWaQ%(s6G%A@V_v*)Gl-#D=lO zU{!Ae!kgDw=3eI7D2LT zYtK&$JB--?wOm{TWUbDF&D)9z_1i!0k4RIBd%VYtHG1+sq?_9k%!pZRN`N%l19ueLSzwox zXK1m%v`HhCdBAidEIy1?g?X~^^0{2xSu6M5)-B0Oc<{$t0Y+GP>m@qO@AuOjXNwmm z45=i2Hv2#(6f1a(_AI((ty=&%Y!{XXSHlA2iaDA4^BT*mXWqP$ z>N^W}%*nj}p_ZyqeMI}j_%Tn~T?e@=vNuKF{X*#o0s|*lAl15Nb4g`1Se^lQ(b;r2 z^^`d#nP82Yi-ORUTC72WBlQ%5AX~ADoF623BXg`p^j9dmLyWjh#dwYDbH=ZHK7^@Oauya* z*U#f3 z?0bucHS{oeD2#Khb+e&*eXm-swdJ?Z+nH~+=jCGZ6CK7oa&aB~rt|Gke2=*#DMU|L z4v!h*npY076;z75!V@?FjBd7~ub#>VmQ7>GnYwEb90&a{2J5Q%l@Oil*Df8i)Q^|^ z9SV3+0DdyNNJ0lNH=AOel`Kc^q$3Aq&w&j+;SIeOLijmT<@e4qHxdVGLON@OyGb3< zTKh(vwhr5+t_|zEx~Xbnjq1Xz02%B#@TB>EfaoX{UrMa*Cje6ix9_39HJJ7SbE@MB zo6>N;yx_oo_-)I&qxQQI@`GzGajfGbX(Xh=;wx`uI?Y)x7FI@%t)QTgbRW4NlS${( z%V*uw^#h?X#2!nZI`5;6?%w@ z-aS`631xaG!8{~yu530z9h1J_wyBIk*dgbQH0-F`5E9bXeyJJZ^w6n<^KI6)Pk)62h`{QTmgdNhhdEL1nv^OYAEr?M! z&xRy$MAt6zG8t~q9M_&i9QTNj{m54sqXaA;=EJa5^qJQ(MEkv6pDzzi9|l3H`ck($nq2n~zQOkOEb zgL-(pV-2(*nXbbfDLyfqMPHNT7b?8zcsX9ECo3KouNO8;F(r zkgH{p_BdL)z_76r*B&mQJ2T!EnhX^V@$ucIE!?|?pDXOW!{EYJ=>`u)=iqTcQ`dF> z^{a4;;B`!hUZFk5G{A=e(1P}!jv9 zLRG?XKK{OUu627>f~Tx%qa@~$#0^HwyD8&CDbzkr-$(D6DGaLcoyIIRmQg9gEX6l& z>gUOgJxN+pGUFHqDlATy=6ETZ)ZY@g*Q*L3B1;F(DV%b^WY9~F_Pj5TPQ z^72(D-{lLQ0sHAGafR{sKf#tVKK04$;w9L)?qnO)Wj)hczn9$MTYiBm0x~JgdxHI0 z&&S&MiR-?7qsFnKmunH~3}HDOZ{pv)GV&RAV(W|TSMcM1fPECdiMso;6DLEouL{v? z|3zg*F3Hb_Jqw*?hd#p|{w+~Has=@%A|q+#FR=$qS@nwZBl9MT$iUr^mmMow=_!L) zkC&Upgwz@dD%WL5^65#gOpfEA?W0L;O1!d3z}>k!yD;gF0{fx;=d61!6kW5oz}{C& z(>Ocn|IV~eI(v<3KT99ZD{|e4M2Qp){1-m~h&D_%XfUrV`0bep-yV1o2TY;qhV$zV67c=(r#7wQ#?UV?g= zpy=;${dJJHs;(5qF^45TPVHeKp6Vcy0_Dnatjy;>ubIO9Y zBBZjbthz;jdNWm(jFy$w#{s=1m8;$-J^8$zHzy&cM}1so!BP4SH;ecFv{G7jU1v;= zwAHuQNB5Rq6FM0A5U(A-591W!p8spdd@36tPJ2t)@V3tr(<3T0)N^(mFue$q+L8Wj z=xvp+zX^wW(E8fh3)_-aKS*3q?C`&G_`0$uo$Ea=z)!aEh#Lax ziLFoG98kXh(v@fXrJ7zU>QnAMHuaYtWO4?lQ;YMUaCBx)yRAV zLr|hUg2`8EHz5>{wr3}8Yfyd(hfJyot;KLs%turML$IP*(N+KCm%+ZbA<~)u`e${e zrr3UDGUM2nZQUz6N%zFWCRQO@G&dO=sMTkh`%0fE181K&3syEk&Em6B*zg*uHe)u% zrWyDX+;l*-D|;5qSCa>88X+NPXi z8$zR*HlztizmeLV>$S0ry_+z~;G&z#}N0(5s=nm&X-LqG+c}Oy(TVWBvKV$ zdw6#2PZoZ;q7{AIHP~ZyH0_M;xmA)nEx~5e>p)%UE*v(VBpP-n(!S(!>g{dATJPz{ zr2S_0E(rYWTK!GO2BGxKy3%hK)|X5f4iWnD5#ERP_@t-U7O|C@^B9;A)=iS1l`?y| zeSf=ye-l|qN8T!~$FyI8wkH#F-RCGop2g!BYb9s>jT~36D7$OpxVzcVQOO-L-#_&nXf z>W^ymix=}NWFJ?v?2cxk=af4^%#Xr)0=@Up>ccbIo|BEuhXR<{9?P4dmA5Y%6|5;o zvORVMoL0!?j%RHQ(I<3v0ISfJYep5%5{OAweEkZ$#Zx)vgqoWS0s4u~ve%$R7T(2U zD(vZXGr@ogw;uofTKx4VTDib15shSq2?sf~Zf(K_vI!3trpQHMHBy8W%!XF!1*|MA zcM@Z*;ULTv4R$quA^zYMtPoGmP@FlP(A`+`OyK?Bb>LaA$IY=SwOzIR-jXO66z%ac z)onlfo?;VsY*@T`Q0szy8mZph)soR^yy+Rtz)OsQTtelL@&}(M7`N@RmoFUjh^8!A z2;)pPKbXSP(s!y0RbVrTHPlr|CFtbd~YIjo5b6YapwfRGqwdb4t%V7f6 zQ3$%Rj8xcisKc0rpx)f~5&Ha>U55cJ&s;g7MYXc^-8CmM09J?B9B%z~^uiF(|JP{? z+0@cZ7Vc>Ek}~y#OG}^JIwkIUNPRb~zsKT=5QP`1U3@oFyYPwH9K4TeMrNoSVOV(1OC_+&b zvd;`dma&FNgckcUwo0;ZS*D17?=R<^>zwPl&UIhc{k!k`@w@Ne?T^!WP=oJxzMs$M z{eHb(&-cz}HFKT1^}56zd@P>aAv3G;%4ttdwpgfO&)xeh@j2-zuhuDHqs+$zl9C{D zIl+;#K+OX>xFKG4>izO?qH#fTEZaiF5mTs?^M&EYq?)AOcR{l+Us}$}Rn5sgV*hly z`tt*E!!TaMg@}`v-g0?6sAEGF$oq54UXAd0!Oyy)WigLH#PQtTdywsTgZNo+k6TH4 zFBDjrQ0S+Fh|uo~eRPhi9nhg7-iPAh69q#)Um;x1|JdJ0I=^9NW{&}JH`e~kAzi_# zB;P}rgwu7PZ<=LU&NcxifYW&H*T?LK>{bk@# zrwY?#b(&MPT+NH!vKdOP_uRNpFHS*3$?ysV`b0sN-RvADMJ_3{xaJciRMa}dcA9AbL!YqD-7OS+=I z+VCn4vL=rxQdnmp4`cj9WAUy>pLFOxJ#2M;|J$F~SDXF&(+@U(PLX6!`s zds*M*(mBu!P1k654a;zYG>zB`Nu+u26CO$}XK7B;xeV%$2hwj!2W2H9-?zB^fcE2|7)kpW&kU%a+`%OK zfGNpM#LdpueYtk2banB2{y~B#S(^#`-?UB6oIkfzJqI14iPBBb%&;i+Qmgi<43apU zgc^wPJmL4qKyi8!U4)&(`D8_FNNWd?hp{(Je0QFm_y$fCrCZx@8BS;iSGL>xxZhw2L} z)!}_Z3wsR;12Pfql4Y3z3OnROFL0dX@qE9Q`KEwV5+OldNd%Yo)G18ik}Ol&tg^+m zXn1eFL&iu1tzVP)JcObn_}!q)=Sr6>CnrXiq}FbDjVJbQCUu>NmnfR!c3^M%0j(J0 ztAy@CXG1MvSdUGKR&M?Rd5MH4&mT?%!8yp=bV;Lq5(4k}M?xy?P(s6Ho)DGDcw?$Q zd($8*;Yo~j(eSt88t=K0NIRzNPr_i&=v5R!`IC#I*In@H3t-s7DpNs73k!d%+^#J? z3Ax(?j_LlkeKKCNPa7gB4~98MELz@4TQJ3k-srQ?m#6T3^G@h*S^NfOdXrcB?W)(! zrP~duxK8)YO){xM7z+Bq<5}5X*7F-_*-xQ{DTZ+&)d#Hbnlxx5Nm`Klj!o>6{>;X_ zq{FHeFb37SR(|uRQ^Zssib9s!)8(CU)$5TS3ftaenTSfdCSpa^`RS03t==&<5z5A- zu$u}87WTBf>OkZ5Xpi_3BI?N^>33$6I*kAW{M5u0;!xKLB>N2_k1*YEbHINH?2pGC z!=KhXcM$8L?np6i%``umzO(g-{QBQ(Q@lJRjqn2wq@5v_Awp)#LY7m5x)8VKTiN(W zR5{jRYWBP#=_{wA*oBN~6t*DT4vJS8C2+5m?ywuy17VS6^qlw7Z!lsnY)Q?6#z8L* z`SE}GI1fkeSMOWu?7n>&Fq~5vu45zOWVNHkUgE~|^iTHd;tRkc!C@C8?M_*dV^x~s z=o=10jU{CHjrvQYYvrX>S?J%^?rH!l6O|aR-Vg%%T%@RFFT&P%6SkKEuB9T-?+{GL zYj#nK?&aPL&`Z}zA*(z*cJ6S-nE7>j(8}vc?HB3#2FjHfFOdXqsY|Ufa1I!QUi*N{ z;M;MTm~1=H*tKFLYGDU#f;H%E8#cqZ5w2kuRA=u7-aKmmgS_+8--uvMVoH&niz_F( zUoXa*kK6xEG4G#IO8y{<{68bNiH-M^FyenWR}4S`Gau=RkN1`Lfg1B};9YzlV%h6$ z{_RR2|MPyRK3Y7j9$Had|4@<)F5Vt#Vf?FG;+L1G3E1;QouFrwh%|W_=s&!$RDP)1 zUx0xtUy|DPH#g|Ni%R+LlG}trA;|HXUD)^tB?aEp6X58ajr$Ebh+LA#g@1m-*hO$H z-Y794A}QaoZ(^i9Ym&Oju_lz;0rJKZFul$LRvae~uU5Tdzg_##t;iOLG$uf3b2Z7i z;2bS}DW4ze2sI95UAaN}cuN5j5f*m#$C)qS3Mm0uq6k{)B}h{gaZB?4LD>#HWVhJ#~0Tc4%>(#3YkSsd5hYkTCv z*iM}hLA(yRm)_;O2B|DOMyAJ@Jz!mU49)SLIdB*(!6~Mf?oT!!3t(avP9_r`Mr4&O z)b&8}>Lzhb9~g|E2Kz*o|rSSKwkKY(K)UY~8QiI91aR z?eWjlZ|#WwR_s1%ZAIlg{>8SdVY&pYuqFS5hL*kN1z5(%Z#&@aJ9Azljp!bz@+ZI( z$pe$DX-sxp5b}4Sz&-)6v#p zgR4}PyF3nHwCIhoQehB(#38HXCL?DvOI zJ^1z_9%A-!p9P;R^O822eODWD+L!=Aa)xKqB;pqVYR(NffJHqzc{vj#NlsS8UuZX_ z6)(7Yt+>i14rJ82z+37v+d*wN$YozHavjXi9z-nT5FD-P67z_8b^KiAPYf{7b?r0< zNANS1ErNQ9H@v};xxHrUFyxDlpRd}8_^nrGX>H$@Sb6R(;P9BQc7qfeqyh43Hvne( z?YEu8244aE;@Bl7VNhc~Z-);?UxB0LaqHJR9~^hI==yB)bu9N?H}HI2FxO4XUf$ke zDu9Rn$pqr)Jn|s(`m!&i+s(k8`%EMjPD_*BU#I&;9=c{g<$7#drg<@qp-1JhggUFh zZ^_Fs{VP0D(fiw>P7{>8Jpu34Jcei-oX%g!fN5|7;$JRMXH2#6P!6QLzW{GUJ6(+r zuT{Yzr_-LMv**z^DgR|3Z*3{$2?fKu6Zq3|cimpSbW(oE!(Z(qamEd>{hd`Out5~l zf=q8H9DCq_C>60vnu@H(K}_1VtNZ}jy6%3h_bh9OJ>gE*o)^21;qOB*E?%qqB*(oK zxF*+XC9fPW#E$F&)(o2{ouLOEo=N$)5cfB%A#WPm_d(lPvcnnBza`)aZZf?Mrs`tw z2;$uLGX;DM`WwLvYd!)#PRJuZ-cXje6-zK^&^t#_McicRXXYRm`4W3lcjdRa%63gI zG!?Hah!wee0geD1xAa^6wX{R5pJBVqfJu<)Hrzz^Td@Zo}~O3NJPf zovd3g6KP`Db$E_a4mGsh89f`*inF5M;Xb^q#Ce4-jEvU1K2>i5UC)7vYSq`2XjWTn zo1w)w_}b1#%!|9ia0v@^=oOImGD>6P(nY(#)|PFe(HIrmTXH!I3blAf*N5-@4M?j! zE5*w4>Dg-~&_x%yvwdRDFw0^b@=z|vp~Q65^2Aph_nxyg47a~ zw)UWJ8#`WKx#S5%L*KzW?$uk9wd7BqUWLC9dOY0QcpB&8HffGDhlWSMS25LgCW>Ql z&zrtqVid`8?x!0%?o>}gZ($9owL&xHJyu zxsg^^2)thRhO$5yljIcWHEMfoo z8Y|`A$BdsTAFPY4ZwsOil4)`3Cl7HYa$HCh1>0;v{v3D?a!^uW=gm1nRM$Jy5TPHY zo|}%Y-YM;7Q}sL|RJkU(pKU3lza=}}_i+GUaX!lJr(qgMO1{kQHw@RKn!eqEqicYY zG*9eJbrVsOoT^OI!qMHKnMH5+A}-^Yj(I9$1V(kb!)oBN!`v;L=_)J;vdqbwq0Fze zw$*Catk{qJskt<{-yqtN_^d@*k6}pyUAqX*#w8G^==i3LUr(NClz9@YiNAdX78b9& z$;)MJgyEg;v2O9-7>O1dtub!nkahjhQRX(@az=M;d;=lP+X@6Sj#q~;q_EwvBKMR4 zSb-{|b6qOjP6{&Ab z!N6b!UifD;L4&i(dj*K<7;aVeU^M4QQ_Af}r>^8+A4f|$e>`_B6f6|RPO58n*@InN zgE^X%7*5$3R4Gdd?0%w-wu^_fX|pF4Fnw5))%mK~LzB4(;p+zSswj zJ6D)n9mw<$y|X#vC^SXP+`bPt9?*>plQ^B|t(uk6-|S404qvB=s$&xLNzyff5KA}I zlHFjSH1B^gMz0pB=Nj4H@?*Y?-bHfIsFEgA}U8-hf0}WL%_J%xv>55xd1Pm7B}? zFgAsWLsK);_dG8CFPe*Lbaj`y4e``M2YR>u^?R@pQ(!dY^PqBKu4|w zY^?U*ktBklZ5b5ElAFY$MzF|Js%>|J6qbqJpx1Dw)e|wzQMKaY#9<#|W)XbPy1;K( zI>IiCw4<;yoAgVN!`?x1KoUv@C~84OuGxW8IMgvgo1{9dEKwiLs&A}b@syXwTLJ?Q z$1h<6)I;B@QR~nW`fJqKLt74Lf7nM9OH62pz|9L9vz-#fuG3fMrY+vau&A=%L31?C zHO*~8>IPyk`X^@Uh2#-+N^z2M1vibe#T{EX1Y--I+Jg#HPQ^7q+m5ex8sCr%lW+yM zTuly~P@y$22Y#N7BY8at6_mJ@#2QygKzR~(V;ZMNWm*zX-(P1~yhGyAn=Ea&{R~>> zgSzn1qUB@i!}J~?uBc6z|Cn><0l$<+PU$)$FH5($1QDjWGQ4GRxj~}0{JG?_bJQgH z!9>>v_uJ^izmgO5NdcM^;mqkHAy#;WM8D9NF!T|RUBqsak?K6UJ!F8=R1P}Knn-AE zpTCmF{%ytl@pYr#2a@i|9Gmr;6pIwmcd+l~oIXPmHpww=-Gx1?zxebCwCeWT)*eLF z*)+aR{X}WG(e!#h@lXH^5IMwbGL-Fvxuyb^G-j#|TPTH2LWK%-lkD*3XIx0QTql^ee?wQ5zc2P#)7+La zQCv%ow*9Ww!$(x*OV4(Ud8Yj5>s@@rorwvoO6slYEqg5G?=|S&r{^i7imTMGks3zC zr4KV1C|t*t!8Fd=P%UiKe;2`PTXM~}n~S?wJDXQuNmP3v2gStc6IxC!H{QTJ%Y)iy z?gUo1V~Wh#`;J8)&BOUiV3aNIDIr;|M^{&xTPth9k%qBE$fkA(ZBbTSi>66;m3m*U z!fVGQB#)>JH;#y$kUoq}4?=HjzQfPm1*`xL_eF*Hd20SS)C|nXK6#VI&aBdIn3Bof zqNjQRT#tqy)FMd{No%4kbl5$<%inHL9$&|Yeg7XPb2SBLUVp1Ixa)0@-!ihMK}IF~ z-%_=HQr5z3j%`7XGQ6^g9BOdFnrX)Yoj5y7Rf9y)a(n^p+>5}c_N{1DJps@h6^>$m zMx~rq&iEdMhof|Xzao@`mpLvpd7#){s@I@#OKKnPs#a{F*`?!Xls8dL1jLcB4kL*5 z_|o->92`lRNe+CQ1)-(3KwXgqFi>3_wdyR`AlRaA4`RSM4eL={;Fh={oLyJ`_|tqs zjBV;4L@iA1A*#)L1F7Fe?r4jJM*8cVWF_U zX;?;cU0YLlTVThaR^H!}+O&*T55_o?G^52h+K|!K<3*8&jI@tFk36WulU_UnNG{yT zlCxyOQpS>!!3j+&3s%x}vKFTF*vUUJo~N=tRIr@+{Kj>U-`51{jO`l5#my=6cup>p zd^?i}Z!6ftJuHRJ3>v_L_JW+Gech(Wa~Izv+NC(vCJleaa;{tlv+BI2SGG zCTtTkZPlq@5XuDoSF$z}CaLJ%)v`Th1BZP4v5EKQqxao-{o zwWhDqK-Y2r8)LrPIK36gQ{y_mQ442ZB20OAq$EaU45G&DMK72@jc}ZDr(VI_Ux!6) zD)7YW*Qvq*&3R_<-DS~dQwqWCZkT~oDAzdj@sLp2Eot|VyFg(VxLlAXhX*1tJ<)M# z%QPpjCx7=Hl0LQkwLjCLrPzSXvCO#EzVsa; zri_wZTPN{YW6%M++R|oPm&CkgZQ64$>6D0KHl;)R!NV~{=>s3J8!5|qyvL4ums#jc zK2mTYC(O)G4uUh*_-TfDiHFDC4R-}aCPy0x?J#DmsyJ; znMUuVcd7JU6P>xxK5&=lNanqlsdD7hgI=^M#$5`#V+P4gO(^#8aVFpUO$<<)hr>JF zGo*S>V#8M$)6}^$q?+|uKE=7ZrOEZ!M4`_&m)(vmZSzH zpS8GdBN+kKzKwb>qoIx3^`I3|brvBMRa#o5Z9f7%kHhIP%@ATq|C-2qy>dUkB2}~y z)i9)yz9Q`)LZomZ932lb%aJ~YDr|#GNQyL(-HwtLluEiv3{}Hk|ITXUg5g)UEM#}n z-`!T_cvoet<1}%5)PmJOZKo?8T4aDm+0#r&HHF zwoqKpkK+D&>W( zkF}JN;@zJi9n5@9?())4&{XnQ@)tdy;;s3CdSAh5*!PzOexr`nIZ*%If#(RAq}GRc zB;)u@x17*zV0DR{vgu~bt1f5*J{ltjg;wxJQX01I65H>*S*QOR)cVeRDxrDKEA54_ zmE?j7yJEm?`cYdw!eQbmv{>VhCugctb?bqM|Ey16B{EFk)Nt1@2;(OV->9-j!<_1M zj`r1QZ3NWD;qI0*+iK)!_?D{=t+yfrv3u#WxmGn>(ihxecv$C{JhBX|ew_ZU`(U3| zx9(9+cC6ksmq?7=HZz}!ctyP+p-@ON81qy3Og8Fr`%5ILvqxicaIF;W{rJYz5qUwH zO4W1{>_LW|<0%g;Tuxq|m~Bhl%H)f^mVUM(AoI_}9nI2Z?Eh*z|Eul%`UZqQ|5w|A zmHR&_2=~9*&VMs)XQ%pIQOmM!NTAe39yXW$c+3|FlxEPU?SW2A>9N(v=9TJiEnmBi zBaT{MzE2lAb^Sm{C(xmkY@;~y#pkndm#3Q*ZzZwEyKS!!*Jqfrk+3j^|#BIgL}Ucz*eI`5cmru z0Ia$=`{!$>5dINl)CNDljrG<%(79sjU9Dno%M$l~8GPrM>n%}#a8|?anVxACz)y;x zwP!s<2$%8pU@k&t4opB{HQTli4mFwQUj`d;4};V?+gANEjr1CF$30#0s6!lw%{r{t z%T8CZO{~f~-3VnQc!%i3lE*C}9Qk#zf-UO8w^e;7#R+?gwtn?Z@ah$2Nv*X8OEnw+ z9$E#xOkvg(%8!`GoNqkS^NRowY6i)FK0^)UcW3oSET#Wa1_}vGu7se-!68Cjq?Cs( zRMYl(>L5WbVX7_2>OKN*C+WlwR+5DfE_7;%iLM!{su-^vKnk6ut?q5{qWYsKDyzD z7_g>v<>T+B>Gwj(^>hY{-52lICSA^{r|WW;2xO709+-J;UBOkFx{Sp>ZD8y#d;)@Jm2tr%4TIg-@x)&{*O zy5SQd#ONqdO9$~uH%o#)UY<0%E%_aFKFxpbo8Cn-xJ`>e1@SWF(q6BErjLZ@)H-rX)O4QH&S~qjEpr zbjdi}@3K$xyF|3wn*X5d3^QjdY^2Dh@Z-GVa8-!)W(mxt6HpIi>xNYBLdsZfX*Z`5 zkMS@0%MZ$CDI<{z+6x6%HK82F!yrGMS5=54w8-l2JT9X0lF`Zfk^6{8VN4(A(Wl8)jYo&SD#?u^ z8o-{k_qV{X#x3tP&gk>+Q{YZ$y&B*q3*VK-8xGdr1pPKJP-l;FOe_Q@5i(sjM)ibV z?DNXv@txH}6lDZ2VX|fjsku)F;|c}sqT1Zvpf&ZCkMw9r%SL`Pe5FBUbN@la6*$C> z_Li2I=30luS|&?|N$=@dPkEJ`|1d4ii^5PHnIx1(h3d7dF{1rNM`&J*3H$a57*}z3 z90D=+Ke113D)lG^75d@1YtIyjs3PbJb(TU)q>nx$F@(lL|8%|>AnH-24uypNMaYAW z&v<~LE0Cp)TM&D)`2=+OTTESV)n&(nXg+^MRT~6>-88LhZi-T-`O1R|-|1PN~z1`CPDWNB|lk|dhHjtb?kqO{-Is{7e)^rKwuy z-zW5l2mi}Lk3NN!Jz4i&fF#9iz(7EG?OtLEdNXq!;3`(7o;Rt8)MG#Kw^GjrPIShm zxCcUO$%&!#C1uKnWV|ejdDv@s;U{w4T?J)S0MSrP-<==Z)0p@^6vr}BEM(>e0N4)6 z?6IysLy;joaKt`&9&^>aE-1+IUm*1GMa%CDT@EDSA8qJtkra0`On9q2_+*qrP$}~F z5u8fIC!l5B{F6#ZEOGax+im|q^C_x^iA5`l`0o@SR$a1wig4IAb(t?%_cQDdTV#bv zAoHu?z61q`;Xu-hwu_9>jfqZnQf>h0=Hgyv8IDk)siB>2b_wkEm3r9SEL^0@kh(MJ z1LmNIibzC6K#RvjIsL4L9FsD_Lb?nsy{==yN|AYPcL0l$XK3Tc&MzYE_hy3u@0swZbLK9OJsZ}5)4NS7h0?HSbX!|X$#tz!R@0&B{T+nUHZZAjE2rchNCy@Jy*g6sX#=}{-D{@ z>a^9IQ_3#W4;(TaUU5i!Y0Z7yBeGc7It*T8(8x3b8rY-chTsiHLl0ol1bQABDGGW3 z7C(R-*7%>9g2B~3{C;n|Q$?Dp+aAh399W-(TT)N=gm;?z=FM%e{H62RPp*k#Wt*=)Tz3H<{?P2m5&mK49YF|T*xsB)Z?#4NSMJw8*{w4Se=+@M))gxX1>H^D@2JNBE232TDYPk@o^ zB+OiUuAOFE%O z1or1R_n%3hN><0z>aEepN<*DQW@dK$MgM7iaOs(kT|DmT|n?f zRmHLfwT&53<-HXHg?5>$B<+7EgjIrCSbOe7xQ6F2>q6Yr7BtawK@=>Ogz^`5e!Sz zHB3+-o~LXMJtGV0l^o)>02!<(ec{1Klyz zAwM2)fkk4$yXR4L_P)+!sWtNmU751kUE=K?WOZ7z<^y7-K2S$IOfk-?!*D9LO>z?M z5QSb}9&LLQ3&_Mw2t-OA*d-DoXsc<^e`e&!%D+Oc586yO{tB&r1gITY7gUN$c-L~6t|95ovnXFEwcq)|1kU`oX=^u+i{GcG z+d5qUTddkd2p~#2e7A`ZeFHx5mBs@}Vb<@Y7@(Wnm^p->qRcsYn`B~F(qs@;v4ZfV zPGwn{g3$_u&U8eeBgK`m-kqEvWRAE?ty+E2THe~ek}YDG4=+{MTd4H^61Zc9WXYV} z9Vs{4#zdml#@3x_eo!aIFzyTq-bh&!b)a)@yzBT#wqVH5;MA%&cYevPBJmapoV~A- zhiJO?-dm8+@7Q4yX>Yh9B^lbD(SU@UIT)Zah_RN=XDrQ-nJWmD1Zg#x7G8j2%P{)$ zZ$c6e_W8aDL`f=pd>5kcZ{p?p5XzaLVS`@eBXF+bRLO|%#sXJE)jb2oJK^t*z{O== z*nbHT{pIWWZf3p!T;0S-8;RE+MOekhWpsxw0dGLkIHB(a_BbjHPQQlX_>WaV6A=3ew(X*=-JZZm8x6YID}#AitS0Nuu`vIl%A!7#aC|HY<2|Rr~V$j)t8n)!YEKaOkHdaBq|FlkofgwQ8C_#1wC*#ijuK zz!)hGL~iFT+m;wC4(Eu=F!a#j^=&#~2`a~4i}PucD}g2K8(ZLBVtw?& z#$+>_(%M&saGAjd#bE|amwUuL7-yA)TL^8fPI%8Irdaf2z2^!w$rR8HSlF;ZO*b^n~b*cG9Ok`ZVN&-iHh)&lm|+Fe~PuC?!W5p(9A8b9m zF_e+7vrLvB!Vn`Hr2M<)8+DHzWDyvm3(Y3ZG}5q(CrWovcsW=~jZoLgIqd)&628Sz zUq%~;u)+AUF2AVxb$G@*WD*P=65N(}{Jx%J-a>9dM$ua_UcyX~?bxfDYo$s9H>jhf zn`YeaGDcbtb)wGKniM)EAh~sGeRpxDtFvWHlg*%dUvGB+-m}MH@KQ1Lz-)?M!yip$ z?2-m+v|8)kSlmTNE^z~c;bN(XL5-s*f+*h8*vGudqPamC`!-;&T#psXF$EoYX3f^2yEShOM(3_!6};&6D}lX4xX)E`W+o=JDRnrh#ayn)F0p40hq+} z*B(G%@FFz71Gi(wNITN?%l&!Pys@&ZPAi%RW2%&1+F&rsFJ1F&a+IB>nf$jX^HZb{ zr+y?U^upfL?%x~l2w^Yi*W$71(%~fKN0gsaT6nhA+=b`LQKh zBp|d5KtpK=0sR^Q@paKV7YM)1@9zufRkCnPw;+J=u3wRs$P2y?%d;CqQc73RiGU4^ z#S-w{h1m!bsy_B)0mG&`2Tb_jcimqAd1YYY5;_!R)|;DMaK9|O*O zo;trvU_h2JNfi2nhXGZJz;zBoeE%@i`-lIA6)!ZRj`2Fj{f8^LhKt$nst{G#Jc#o5 zV29EN{tB@8Ug>Xc(El8u;opf0QKZB`PFRKFL-?f#g!KmR1HZq7P9N+3^oAMb+2~CQ zz9OL$>1Dnp>6YbX1qYr%Q@(JoVqhTzv^!aL9(f)qV%p~Y3ov5!g{5TezzZ<|{%*wJ zkMK1v0`e*fEIIrph!PFk5g$rVO+g`GX?HDjpeGO*5ELkrWnVus14~|RHFELmPbrm| zeDPMWhu_9SuxoPU19mxXlukQDUHbJeAb&bl?o%S(LhRwVd^@!;fDr-j3Ib3KTJf?y zrmnNYH22NYQJ$`+%zjwOvkw4skK^*-FWDO8-=D?~0} z0Iva~Fk~Mtjb|x>HL1PWop2dIued^G4JaYZZ*Jl42KRNTh>j0TjeKC<)j)7QwZZTE zY3-?jS>&#zAM1^%)L1o%r3wDAf?uXd)U zzta8(JZFXA!09wjuMY8{OS*l}1a74RnC>UwE3+$rjx`FHjeLL}ngCN&euE}-K+WKI z*9}0X@%hQVNx!8zBggcPf0PIcs$^HG|E~)K9opCmdm1w9p%~ohZ@l-D;Y9OxLlr`? z11=qVd%BS*0~Cjjz64n4Jxx#SUWo>E!z4GWU&BEcxMFTGKoFweDCSEE^7+4$jRamh z0X@&tv`RbjJd%N4G+BEaIVIk>aieO9G2YdVP@j;rX#NRKm}ex;Y{T{DeU#($$Cn(z zoHAZ{-T({`d7U!)#6KS3*Xhsu4W3;1{&kw;^@%nLoYud_4KFn>k__)6wS{T9Unyjy z!1S&eF$x4hbUT2Y7;x+8i#v2Y#yUR4`7d9&3`$wiIwq7SA$Ac?$ih-4fDqo@qAw*L zfn;ML67{Y%%d*cLCJ1um_`BH$&7746i4Q!PZfP986wH0t03P)unaCzs zp6?H#?~4+`*1_^2sc3l{z>_678omesi9HB=y%+cCb#yaQDOSot_c^UVQkJBA5hR!K z-YxpZ*)1xe8)sh?U6ySGjeS)b1ZdLeUp0U%}22QFIbLu+(~T652&#CieF558Wm>%F~G$yTp1CwAf%b5E6~vQAbv+LoAVhz z=w=yHn!E%mS9AUjq80dcy`HzC4XxCH=_a~p4(<~i5UZN=PDme5eMUz+vKG%K=;CHcnTM#*`(m3#5>2Nqnw+(t091bIFEYBQ`e%myU$ z=yf83Ok@o7@a_P{^UP-9;nk?fJ85n15_%25&daIpZay1nU0iRC`hQfuzksLZjZ7?wEUFtH1-SeYNC z95WYZx`)}O$%qKmxmd>jMSoPO$3FptuEFBVlM`^ctOj?GS(4wXFs=%TkwrcOHXGtn z3&2ZDv1)N|^8MU*+lvZ&PZ!M~{p7z#B{GN<_>GOnmwo9S&*EzVE>AGqdlI((NfZb$ zNcwC$CIJDp-|A9!lT=K#`mu?OX-n+QyMfhC64gjd^3m7b^@WHN;wsy2cm~rUFx5kU z772&;f!cdDrjNv!4ABAlB&F7Cm;}{?gu~{=g|+t%n!bz%YbX!L&_l6{!Av*NVU6?9 zT*(Uy65=EWhY5@&;iZ;0^I;Q_p}u4P0vnG8^Ftg(KOjw!OepLP$!gbP0JCbWx?lDG zA2i+x7gQLz?*2M=umR@PStsPO%@rUcfS!h7UB=m(7rwt(3PBz~I67V6l+&lVW1mPz zNczQekkxK{d4GNDf#~=k;j`m+>9|L;Z)JApf%?8oz5p32}EtI;{7@aV>Jr?RMH9)Qn6@7}(5dIXVPbBdY zW6*he148i%f~bvx!YOBsb%Eu)!ZMK~NMc>wv{BauY?9YR2yv0M9#<-(E-EP|@Uut= z{Kuq%K0n-GpwGERjiu)$Rqb~`vaSbhPd2%_7O=<{lB{zo*?Vy*4hDaEIZe! z->%UM)EO$iTqyD9gD1}l^nQs5@iGYqhz1f4t(yXPN>Mat(6vfLmyMN`fU%No7XlrMAg*O)D8A3PI(&FS}-8n8Zb z;xIuW9i4f!@O>c`|7T>pO^Gp8X_U#Bjl0IHR)z^2ltgwd2D0^8b{f=+F+~C}=l;hT_F}z@`hbe2=~glke2N_?7m_=TP?Q^{v&KVL;OS^ur;E3jgy9m*x@3`9OM5lwSZAgw z9OA5!ioxh*!08n!2Rsm8Kz+PidE}G>^g;@h^}YNnnd0{~`jUce*o81pbsw#BR{=YT zc=9`a$Xv0f-VOx9U?RtaOk-l_;^s1QRvpwFu*9_4127VCj)8E5vT7tjL* zUqfzalB>;7n9JOhcFjOnWp6kT9&p5i*hKZvb;e#Y*bY5i{_aGNYvG`P`nG1{8~S12 z$`z6?YZ*I9ziN(a@P;m{r?)?#;y*$N|087mGqz)&Cboq)eIws5+(XjHT9l>}Koxmw z+Ai0Am#ArZ(-&@q=-x!kBYqaKfAb7oQulVjQitvDH+w0+5gX&6UO@FH&~A4_J7eZjK;< zsSySO#B`)cVzv};!sc3QF`pbdQDNu|O@n_Dorj9Vg()YFyJe0P>`|8|fgj0~C@80y zvLtvPP5!70<~iYvnfWfqF4sdqnLB?~qtyrFK8OGsJUlA&+ZRk0gHl}{;&$WbANI1* zObu8CqI?hil-ke^eD!Vs%-f9ma6WI4RV0_jY*2v;Eb3El2Ta21+0m%qad4+>)8Yw$ z3QQL8xlX;8M+V`fH>9lH*V7DnhZ?W(*#&71S|u~%?=bV0Hw^i1WC6;DiKjap|MbDVUXc} zVdt5+u|>8B_4q#M5sSolnJ#|@kBnDGY2alNLGNq2F+LXYzUFGpAcXpnu$bo=f zrwr$*)Vya|idp6`w}tJUauzbYjLT!(O&9_EzNu^WPGBfahR8m`Un+zXw_|-v34Mz$N^;_&GVQ#P}N=yKqz+tx#kiI6QEN`I;`s8%2hes*`G{AA2Gj&~P zLI6Dtmk<{{z?bmkUVu2tc<3SK*sHD1{3_VQS)!@@LE;gpZa=}CT$>L(Oph_+2Tn-u zA-+Oy=!C%z#6mX_OpvO07MiPZOt24%8obOBdom!At{jJz{9V~ewW=m zFRTE+eDL}KN-p>zpyYxnB+pO|t^AFLkzqI_C3cmSZL&37_$N}RT#Q~yu%?g+6^}i* zon~V&_vAjE@8efJ;IgNW%|j!q2&f|gE1>WZjx<=-6Ly!e30a z_(54navKOz5ZRNa8GT-4UVt3yEI>1bmKU?6R;+aE3TBDVR>yul0xgKl`fm8-*Pj;t zOx`g5{pw~LI6bsg>hKRC17GVNh)ymq_WiJa#R}7*a=R;u%sm$$n12R0vV*@P;KR?Y zeT?|Zq1rD7Kl7Cpc*USuwLL}Y4d^iXF^*pG56CoFR ag7M>-l{kNqo94=RTs38FrA&ph0sjY=#XAxJ literal 0 HcmV?d00001 diff --git a/docs/img/e2e-testfail.png b/docs/img/e2e-testfail.png new file mode 100644 index 0000000000000000000000000000000000000000..5ceadb196d2f4f859896a993877b7464bb81f8e1 GIT binary patch literal 135574 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

M?hT4I*-FMcfW4YlsN(f3>7N^#PS#*QlkNRx5 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

Bfdy5D9)-@^7-f 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 { - /* - // Bug:4596 Switch - */} + } x.endsWith('.log')); const names = logs .map(x => parseLog(path.join(reportsDir, x))) - .filter(x => x != null); + .filter(x => x != null && x != ''); return names; } @@ -144,7 +144,13 @@ function runWdio() { wdio.run().then( code => { - doProcess(code); + try { + doProcess(code); + } catch (e) { + console.log(e); + // any exception that isn't handled is an error + process.exit(3); + } }, error => { console.error('Launcher failed to start the test', error.stacktrace); @@ -153,4 +159,10 @@ function runWdio() { ); } -runWdio(); +try { + runWdio(); +} catch (e) { + console.log(e); + // any exception that isn't handled is an error + process.exit(2); +} diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRegularBorder.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRegularBorder.json index 818fa573d29..b6b323e4662 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRegularBorder.json +++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRegularBorder.json @@ -6,14 +6,237 @@ "Clip": null, "CornerRadius": "0,0,0,0", "FlowDirection": "LeftToRight", - "Height": 300, + "Height": 360, "HorizontalAlignment": "Stretch", "Margin": "0,0,0,0", - "RenderSize": [800, 300], + "RenderSize": [800, 360], "VerticalAlignment": "Stretch", "Visibility": "Visible", "Width": 800, + "AutomationId": "ControlStyleView", "children": [ + { + "XamlType": "Windows.UI.Xaml.Controls.ToggleSwitch", + "Background": "#33E1E1E1", + "BorderBrush": "#55FF00FF", + "BorderThickness": "1,1,1,1", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Foreground": "#FFFFFFFF", + "Height": 50, + "HorizontalAlignment": "Left", + "Margin": "0,0,0,0", + "Padding": "0,0,0,0", + "RenderSize": [51, 50], + "VerticalAlignment": "Center", + "Visibility": "Visible", + "Width": 51, + "children": [ + { + "XamlType": "Windows.UI.Xaml.Controls.Grid", + "Background": "#33E1E1E1", + "BorderBrush": "#55FF00FF", + "BorderThickness": "1,1,1,1", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Padding": "0,0,0,0", + "RenderSize": [51, 50], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "children": [ + { + "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter", + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Foreground": "#66000000", + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "HeaderContentPresenter", + "Padding": "0,0,0,0", + "RenderSize": [0, 0], + "VerticalAlignment": "Top", + "Visibility": "Collapsed" + }, + { + "XamlType": "Windows.UI.Xaml.Controls.Grid", + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "HorizontalAlignment": "Left", + "Margin": "0,0,0,0", + "Padding": "0,0,0,0", + "RenderSize": [154, 32], + "VerticalAlignment": "Top", + "Visibility": "Visible", + "children": [ + { + "XamlType": "Windows.UI.Xaml.Controls.Grid", + "Background": "#00FFFFFF", + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "HorizontalAlignment": "Stretch", + "Margin": "0,5,0,5", + "Name": "SwitchAreaGrid", + "Padding": "0,0,0,0", + "RenderSize": [52, 22], + "VerticalAlignment": "Stretch", + "Visibility": "Visible" + }, + { + "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter", + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Foreground": "#FFFFFFFF", + "HorizontalAlignment": "Left", + "Margin": "0,0,0,0", + "Name": "OffContentPresenter", + "Padding": "0,0,0,0", + "RenderSize": [0, 0], + "VerticalAlignment": "Center", + "Visibility": "Visible" + }, + { + "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter", + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Foreground": "#FFFFFFFF", + "HorizontalAlignment": "Left", + "Margin": "0,0,0,0", + "Name": "OnContentPresenter", + "Padding": "0,0,0,0", + "RenderSize": [0, 0], + "VerticalAlignment": "Center", + "Visibility": "Visible" + }, + { + "XamlType": "Windows.UI.Xaml.Shapes.Rectangle", + "Clip": null, + "FlowDirection": "LeftToRight", + "Height": 20, + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "OuterBorder", + "RenderSize": [40, 20], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 40 + }, + { + "XamlType": "Windows.UI.Xaml.Shapes.Rectangle", + "Clip": null, + "FlowDirection": "LeftToRight", + "Height": 20, + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "SwitchKnobBounds", + "RenderSize": [40, 20], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 40 + }, + { + "XamlType": "Windows.UI.Xaml.Controls.Grid", + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Height": 20, + "HorizontalAlignment": "Left", + "Margin": "0,0,0,0", + "Name": "SwitchKnob", + "Padding": "0,0,0,0", + "RenderSize": [20, 20], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 20, + "children": [ + { + "XamlType": "Windows.UI.Xaml.Shapes.Ellipse", + "Clip": null, + "FlowDirection": "LeftToRight", + "Height": 10, + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "SwitchKnobOn", + "RenderSize": [10, 10], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 10 + }, + { + "XamlType": "Windows.UI.Xaml.Shapes.Ellipse", + "Clip": null, + "FlowDirection": "LeftToRight", + "Height": 10, + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "SwitchKnobOff", + "RenderSize": [10, 10], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 10 + } + ] + }, + { + "XamlType": "Windows.UI.Xaml.Controls.Primitives.Thumb", + "Background": "#33000000", + "BorderBrush": "#00FFFFFF", + "BorderThickness": "1,1,1,1", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Foreground": "#FFFFFFFF", + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "SwitchThumb", + "Padding": "0,0,0,0", + "RenderSize": [52, 32], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "children": [ + { + "XamlType": "Windows.UI.Xaml.Shapes.Rectangle", + "Clip": null, + "FlowDirection": "LeftToRight", + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "RenderSize": [52, 32], + "VerticalAlignment": "Stretch", + "Visibility": "Visible" + } + ] + } + ] + } + ] + } + ] + }, { "XamlType": "Windows.UI.Xaml.Controls.CheckBox", "Background": "#33E1E1E1", @@ -113,6 +336,7 @@ "Margin": "0,0,0,0", "Padding": "0,0,0,0", "RenderSize": [20, 16], + "Text": "", "VerticalAlignment": "Center", "Visibility": "Visible" } @@ -157,6 +381,7 @@ "Margin": "0,0,0,0", "Padding": "10,10,10,10", "RenderSize": [800, 50], + "Text": "", "VerticalAlignment": "Stretch", "Visibility": "Visible", "Width": 800, @@ -283,56 +508,6 @@ "RenderSize": [798, 48], "VerticalAlignment": "Stretch", "Visibility": "Visible" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar", - "Background": "#00FFFFFF", - "BorderBrush": "#00FFFFFF", - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "2,2,2,2", - "FlowDirection": "LeftToRight", - "Foreground": "#00FFFFFF", - "HorizontalAlignment": "Right", - "Margin": "0,0,0,0", - "Name": "VerticalScrollBar", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar", - "Background": "#00FFFFFF", - "BorderBrush": "#00FFFFFF", - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "2,2,2,2", - "FlowDirection": "LeftToRight", - "Foreground": "#00FFFFFF", - "HorizontalAlignment": "Stretch", - "Margin": "0,0,0,0", - "Name": "HorizontalScrollBar", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Border", - "Background": "#FFE6E6E6", - "BorderBrush": null, - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "0,0,0,0", - "FlowDirection": "LeftToRight", - "HorizontalAlignment": "Stretch", - "Margin": "0,0,0,0", - "Name": "ScrollBarSeparator", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" } ] } @@ -350,6 +525,7 @@ "Name": "PlaceholderTextContentPresenter", "Padding": "10,10,10,10", "RenderSize": [798, 48], + "Text": "TextBox", "VerticalAlignment": "Stretch", "Visibility": "Visible" }, @@ -531,56 +707,6 @@ "RenderSize": [798, 48], "VerticalAlignment": "Stretch", "Visibility": "Visible" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar", - "Background": "#00FFFFFF", - "BorderBrush": "#00FFFFFF", - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "2,2,2,2", - "FlowDirection": "LeftToRight", - "Foreground": "#00FFFFFF", - "HorizontalAlignment": "Right", - "Margin": "0,0,0,0", - "Name": "VerticalScrollBar", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar", - "Background": "#00FFFFFF", - "BorderBrush": "#00FFFFFF", - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "2,2,2,2", - "FlowDirection": "LeftToRight", - "Foreground": "#00FFFFFF", - "HorizontalAlignment": "Stretch", - "Margin": "0,0,0,0", - "Name": "HorizontalScrollBar", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Border", - "Background": "#FFE6E6E6", - "BorderBrush": null, - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "0,0,0,0", - "FlowDirection": "LeftToRight", - "HorizontalAlignment": "Stretch", - "Margin": "0,0,0,0", - "Name": "ScrollBarSeparator", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" } ] } @@ -598,6 +724,7 @@ "Name": "PlaceholderTextContentPresenter", "Padding": "10,10,10,10", "RenderSize": [798, 48], + "Text": "Password", "VerticalAlignment": "Stretch", "Visibility": "Visible" }, @@ -699,6 +826,7 @@ "Name": "DateText", "Padding": "12,0,0,2", "RenderSize": [90, 21], + "Text": "select a date", "VerticalAlignment": "Center", "Visibility": "Visible" }, @@ -738,6 +866,7 @@ "Margin": "0,0,0,0", "Padding": "0,0,0,0", "RenderSize": [12, 12], + "Text": "", "VerticalAlignment": "Center", "Visibility": "Visible" } @@ -780,6 +909,7 @@ "Margin": "0,0,0,0", "Padding": "12,5,0,7", "RenderSize": [800, 50], + "Text": "", "VerticalAlignment": "Top", "Visibility": "Visible", "Width": 800, @@ -859,6 +989,7 @@ "Name": "PlaceholderTextBlock", "Padding": "0,0,0,0", "RenderSize": [756, 19], + "Text": "", "VerticalAlignment": "Stretch", "Visibility": "Visible" } @@ -878,6 +1009,7 @@ "Name": "EditableText", "Padding": "11,5,32,6", "RenderSize": [0, 0], + "Text": "", "VerticalAlignment": "Center", "Visibility": "Collapsed" }, @@ -934,6 +1066,7 @@ "Margin": "0,0,0,0", "Padding": "0,0,0,0", "RenderSize": [12, 12], + "Text": "", "VerticalAlignment": "Center", "Visibility": "Visible" } diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRoundBorder.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRoundBorder.json index 3e26498c954..a236fcc7778 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRoundBorder.json +++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRoundBorder.json @@ -6,14 +6,237 @@ "Clip": null, "CornerRadius": "0,0,0,0", "FlowDirection": "LeftToRight", - "Height": 300, + "Height": 360, "HorizontalAlignment": "Stretch", "Margin": "0,0,0,0", - "RenderSize": [800, 300], + "RenderSize": [800, 360], "VerticalAlignment": "Stretch", "Visibility": "Visible", "Width": 800, + "AutomationId": "ControlStyleView", "children": [ + { + "XamlType": "Windows.UI.Xaml.Controls.ToggleSwitch", + "Background": "#33000000", + "BorderBrush": "#5500FF00", + "BorderThickness": "10,10,10,10", + "Clip": null, + "CornerRadius": "10,10,10,10", + "FlowDirection": "LeftToRight", + "Foreground": "#FF000000", + "Height": 50, + "HorizontalAlignment": "Left", + "Margin": "0,0,0,0", + "Padding": "0,0,0,0", + "RenderSize": [51, 50], + "VerticalAlignment": "Center", + "Visibility": "Visible", + "Width": 51, + "children": [ + { + "XamlType": "Windows.UI.Xaml.Controls.Grid", + "Background": "#33000000", + "BorderBrush": "#5500FF00", + "BorderThickness": "10,10,10,10", + "Clip": null, + "CornerRadius": "10,10,10,10", + "FlowDirection": "LeftToRight", + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Padding": "0,0,0,0", + "RenderSize": [51, 50], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "children": [ + { + "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter", + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Foreground": "#66000000", + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "HeaderContentPresenter", + "Padding": "0,0,0,0", + "RenderSize": [0, 0], + "VerticalAlignment": "Top", + "Visibility": "Collapsed" + }, + { + "XamlType": "Windows.UI.Xaml.Controls.Grid", + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "HorizontalAlignment": "Left", + "Margin": "0,0,0,0", + "Padding": "0,0,0,0", + "RenderSize": [154, 32], + "VerticalAlignment": "Top", + "Visibility": "Visible", + "children": [ + { + "XamlType": "Windows.UI.Xaml.Controls.Grid", + "Background": "#00FFFFFF", + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "HorizontalAlignment": "Stretch", + "Margin": "0,5,0,5", + "Name": "SwitchAreaGrid", + "Padding": "0,0,0,0", + "RenderSize": [52, 22], + "VerticalAlignment": "Stretch", + "Visibility": "Visible" + }, + { + "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter", + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Foreground": "#66000000", + "HorizontalAlignment": "Left", + "Margin": "0,0,0,0", + "Name": "OffContentPresenter", + "Padding": "0,0,0,0", + "RenderSize": [0, 0], + "VerticalAlignment": "Center", + "Visibility": "Visible" + }, + { + "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter", + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Foreground": "#66000000", + "HorizontalAlignment": "Left", + "Margin": "0,0,0,0", + "Name": "OnContentPresenter", + "Padding": "0,0,0,0", + "RenderSize": [0, 0], + "VerticalAlignment": "Center", + "Visibility": "Visible" + }, + { + "XamlType": "Windows.UI.Xaml.Shapes.Rectangle", + "Clip": null, + "FlowDirection": "LeftToRight", + "Height": 20, + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "OuterBorder", + "RenderSize": [40, 20], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 40 + }, + { + "XamlType": "Windows.UI.Xaml.Shapes.Rectangle", + "Clip": null, + "FlowDirection": "LeftToRight", + "Height": 20, + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "SwitchKnobBounds", + "RenderSize": [40, 20], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 40 + }, + { + "XamlType": "Windows.UI.Xaml.Controls.Grid", + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Height": 20, + "HorizontalAlignment": "Left", + "Margin": "0,0,0,0", + "Name": "SwitchKnob", + "Padding": "0,0,0,0", + "RenderSize": [20, 20], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 20, + "children": [ + { + "XamlType": "Windows.UI.Xaml.Shapes.Ellipse", + "Clip": null, + "FlowDirection": "LeftToRight", + "Height": 10, + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "SwitchKnobOn", + "RenderSize": [10, 10], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 10 + }, + { + "XamlType": "Windows.UI.Xaml.Shapes.Ellipse", + "Clip": null, + "FlowDirection": "LeftToRight", + "Height": 10, + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "SwitchKnobOff", + "RenderSize": [10, 10], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 10 + } + ] + }, + { + "XamlType": "Windows.UI.Xaml.Controls.Primitives.Thumb", + "Background": "#33000000", + "BorderBrush": "#00FFFFFF", + "BorderThickness": "1,1,1,1", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Foreground": "#FF000000", + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "Name": "SwitchThumb", + "Padding": "0,0,0,0", + "RenderSize": [52, 32], + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "children": [ + { + "XamlType": "Windows.UI.Xaml.Shapes.Rectangle", + "Clip": null, + "FlowDirection": "LeftToRight", + "HorizontalAlignment": "Stretch", + "Margin": "0,0,0,0", + "RenderSize": [52, 32], + "VerticalAlignment": "Stretch", + "Visibility": "Visible" + } + ] + } + ] + } + ] + } + ] + }, { "XamlType": "Windows.UI.Xaml.Controls.CheckBox", "Background": "#33000000", @@ -113,6 +336,7 @@ "Margin": "0,0,0,0", "Padding": "0,0,0,0", "RenderSize": [20, 16], + "Text": "", "VerticalAlignment": "Center", "Visibility": "Visible" } @@ -157,6 +381,7 @@ "Margin": "0,0,0,0", "Padding": "10,10,10,10", "RenderSize": [800, 50], + "Text": "", "VerticalAlignment": "Stretch", "Visibility": "Visible", "Width": 800, @@ -283,56 +508,6 @@ "RenderSize": [780, 30], "VerticalAlignment": "Stretch", "Visibility": "Visible" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar", - "Background": "#00FFFFFF", - "BorderBrush": "#00FFFFFF", - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "2,2,2,2", - "FlowDirection": "LeftToRight", - "Foreground": "#00FFFFFF", - "HorizontalAlignment": "Right", - "Margin": "0,0,0,0", - "Name": "VerticalScrollBar", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar", - "Background": "#00FFFFFF", - "BorderBrush": "#00FFFFFF", - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "2,2,2,2", - "FlowDirection": "LeftToRight", - "Foreground": "#00FFFFFF", - "HorizontalAlignment": "Stretch", - "Margin": "0,0,0,0", - "Name": "HorizontalScrollBar", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Border", - "Background": "#FFE6E6E6", - "BorderBrush": null, - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "0,0,0,0", - "FlowDirection": "LeftToRight", - "HorizontalAlignment": "Stretch", - "Margin": "0,0,0,0", - "Name": "ScrollBarSeparator", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" } ] } @@ -350,6 +525,7 @@ "Name": "PlaceholderTextContentPresenter", "Padding": "10,10,10,10", "RenderSize": [780, 39], + "Text": "TextBox", "VerticalAlignment": "Stretch", "Visibility": "Visible" }, @@ -531,56 +707,6 @@ "RenderSize": [780, 30], "VerticalAlignment": "Stretch", "Visibility": "Visible" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar", - "Background": "#00FFFFFF", - "BorderBrush": "#00FFFFFF", - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "2,2,2,2", - "FlowDirection": "LeftToRight", - "Foreground": "#00FFFFFF", - "HorizontalAlignment": "Right", - "Margin": "0,0,0,0", - "Name": "VerticalScrollBar", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar", - "Background": "#00FFFFFF", - "BorderBrush": "#00FFFFFF", - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "2,2,2,2", - "FlowDirection": "LeftToRight", - "Foreground": "#00FFFFFF", - "HorizontalAlignment": "Stretch", - "Margin": "0,0,0,0", - "Name": "HorizontalScrollBar", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" - }, - { - "XamlType": "Windows.UI.Xaml.Controls.Border", - "Background": "#FFE6E6E6", - "BorderBrush": null, - "BorderThickness": "0,0,0,0", - "Clip": null, - "CornerRadius": "0,0,0,0", - "FlowDirection": "LeftToRight", - "HorizontalAlignment": "Stretch", - "Margin": "0,0,0,0", - "Name": "ScrollBarSeparator", - "Padding": "0,0,0,0", - "RenderSize": [0, 0], - "VerticalAlignment": "Stretch", - "Visibility": "Collapsed" } ] } @@ -598,6 +724,7 @@ "Name": "PlaceholderTextContentPresenter", "Padding": "10,10,10,10", "RenderSize": [780, 39], + "Text": "Password", "VerticalAlignment": "Stretch", "Visibility": "Visible" }, @@ -699,6 +826,7 @@ "Name": "DateText", "Padding": "12,0,0,2", "RenderSize": [90, 21], + "Text": "select a date", "VerticalAlignment": "Center", "Visibility": "Visible" }, @@ -738,6 +866,7 @@ "Margin": "0,0,0,0", "Padding": "0,0,0,0", "RenderSize": [12, 12], + "Text": "", "VerticalAlignment": "Center", "Visibility": "Visible" } @@ -780,6 +909,7 @@ "Margin": "0,0,0,0", "Padding": "12,5,0,7", "RenderSize": [800, 50], + "Text": "", "VerticalAlignment": "Top", "Visibility": "Visible", "Width": 800, @@ -859,6 +989,7 @@ "Name": "PlaceholderTextBlock", "Padding": "0,0,0,0", "RenderSize": [756, 19], + "Text": "", "VerticalAlignment": "Stretch", "Visibility": "Visible" } @@ -878,6 +1009,7 @@ "Name": "EditableText", "Padding": "11,5,32,6", "RenderSize": [0, 0], + "Text": "", "VerticalAlignment": "Center", "Visibility": "Collapsed" }, @@ -934,6 +1066,7 @@ "Margin": "0,0,0,0", "Padding": "0,0,0,0", "RenderSize": [12, 12], + "Text": "", "VerticalAlignment": "Center", "Visibility": "Visible" } diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageRTL.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageRTL.json index c00ab2049da..e6560044fe8 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageRTL.json +++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageRTL.json @@ -14,6 +14,7 @@ "VerticalAlignment": "Stretch", "Visibility": "Visible", "Width": 500, + "AutomationId": "ImageContainer", "children": [ { "XamlType": "Microsoft.ReactNative.ViewPanel", diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithBorder.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithBorder.json index 753214da826..9c87e39efe5 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithBorder.json +++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithBorder.json @@ -14,6 +14,7 @@ "VerticalAlignment": "Stretch", "Visibility": "Visible", "Width": 500, + "AutomationId": "ImageContainer", "children": [ { "XamlType": "Microsoft.ReactNative.ViewPanel", diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder-Subsequent.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder-Subsequent.json index c00ab2049da..e6560044fe8 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder-Subsequent.json +++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder-Subsequent.json @@ -14,6 +14,7 @@ "VerticalAlignment": "Stretch", "Visibility": "Visible", "Width": 500, + "AutomationId": "ImageContainer", "children": [ { "XamlType": "Microsoft.ReactNative.ViewPanel", diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder.json index 9406a02556a..9be2fa56439 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder.json +++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder.json @@ -13,6 +13,7 @@ "VerticalAlignment": "Stretch", "Visibility": "Visible", "Width": 500, + "AutomationId": "ImageContainer", "children": [ { "XamlType": "Windows.UI.Xaml.DependencyObject" diff --git a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpControlViewManager.cs b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpControlViewManager.cs index 1e12a33264b..fea206cd49f 100644 --- a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpControlViewManager.cs +++ b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpControlViewManager.cs @@ -5,11 +5,8 @@ using Microsoft.ReactNative.Managed; using System; using System.Collections.Generic; -using System.Diagnostics; -using System.IO; using System.Threading.Tasks; using Windows.ApplicationModel.DataTransfer; -using Windows.Data.Json; using Windows.Storage; using Windows.UI.ViewManagement; using Windows.UI.Xaml; @@ -126,180 +123,25 @@ private async void dispatcherTimer_Tick(object sender, object e) m_timer.Stop(); if (VisualTreeHelper.GetParent(m_textBlock) != null) { - await MatchTreeDumpFromLayoutUpdateAsync(); - } - } - private DependencyObject FindChildWithMatchingUIAID(DependencyObject element) - { - string automationId = (string)element.GetValue(Windows.UI.Xaml.Automation.AutomationProperties.AutomationIdProperty); - if (automationId == m_uiaID) - { - return element; - } - int childrenCount = VisualTreeHelper.GetChildrenCount(element); - for (int i = 0; i < childrenCount; i++) - { - var result = FindChildWithMatchingUIAID(VisualTreeHelper.GetChild(element, i)); - if (result != null) - { - return result; - } - } - - return null; - } - - private async Task MatchTreeDumpFromLayoutUpdateAsync() - { - // First find root - DependencyObject current = m_textBlock; - DependencyObject parent = VisualTreeHelper.GetParent(current); - while (parent != null) - { - current = parent; - parent = VisualTreeHelper.GetParent(current); - } - - DependencyObject dumpRoot = current; - // if UIAID is passed in from test, find the matching child as the root to dump - if (m_uiaID != null) - { - var matchingNode = FindChildWithMatchingUIAID(current); - if (matchingNode != null) + var matchSuccessful = await TreeDumpHelper.MatchTreeDumpFromLayoutUpdateAsync(m_dumpID, m_uiaID, m_textBlock, m_additionalProperties, DumpTreeMode.Json, m_dumpExpectedText); + if (!matchSuccessful) { - dumpRoot = matchingNode; - } - } - - string dumpText = VisualTreeDumper.DumpTree(dumpRoot, m_textBlock /* exclude */ , m_additionalProperties, mode); - if (dumpText != m_dumpExpectedText) - { - await MatchDump(dumpText); - } - } - - private readonly DumpTreeMode mode = DumpTreeMode.Json; - - private async Task MatchDump(string dumpText) - { - StorageFile masterFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync($@"Assets\{GetMasterFile()}"); - if (m_dumpExpectedText == null) - { - try - { - m_dumpExpectedText = await FileIO.ReadTextAsync(masterFile); - StorageFolder storageFolder = ApplicationData.Current.LocalFolder; - string copyFileName = GetMasterFile(); - var copyDumpFile = await storageFolder.CreateFileAsync(copyFileName, CreationCollisionOption.ReplaceExisting); - await FileIO.WriteTextAsync(copyDumpFile, m_dumpExpectedText); - } - catch (IOException) - { - UpdateResult(false /*matchDump*/ , "Tree dump master file not found in testapp package!"); - } - } + StorageFile outFile = await storageFolder.GetFileAsync(TreeDumpHelper.GetOutputFile(m_dumpID)); + StorageFile masterFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync($@"Assets\{TreeDumpHelper.GetMasterFile(m_dumpID)}"); - if (!DumpsAreEqual(m_dumpExpectedText, dumpText)) - { - StorageFolder storageFolder = ApplicationData.Current.LocalFolder; - string fileName = GetOutputFile(); - try - { - StorageFile outFile = await storageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); - await FileIO.WriteTextAsync(outFile, dumpText); UpdateResult(false /*matchDump*/ , $"Tree dump file does not match master at {masterFile.Path} - See output at {outFile.Path}", GetInlines(masterFile, outFile, m_textBlock)); } - catch (IOException) + else { - UpdateResult(false /*matchDump*/ , "Can't write dump output file:" + fileName); + UpdateResult(true /*matchDump*/ , ""); } - } - else - { - UpdateResult(true /*matchDump*/ , ""); - } - } - - private bool DumpsAreEqual(string dumpExpectedText, string dumpText) - { - if (mode == DumpTreeMode.Default) - { - return dumpExpectedText == dumpText; - } - else - { - JsonValue expected = JsonValue.Parse(dumpExpectedText); - JsonValue actual = JsonValue.Parse(dumpText); - return JsonComparesEqual(expected, actual); - } - } - private bool JsonComparesEqual(IJsonValue expected, IJsonValue actual) - { - if (expected.ValueType != actual.ValueType) - { - return false; - } - switch (expected.ValueType) - { - case JsonValueType.String: - if (expected.GetString() == actual.GetString()) - { - return true; - } - else { Debug.WriteLine($"Expected {expected.GetString()} got {actual.GetString()}"); return false; } - case JsonValueType.Number: - return expected.GetNumber() == actual.GetNumber(); - case JsonValueType.Boolean: - return expected.GetBoolean() == actual.GetBoolean(); - case JsonValueType.Null: - return true; - case JsonValueType.Array: - { - var ea = expected.GetArray(); - var aa = actual.GetArray(); - if (ea.Count != aa.Count) { return false; } - for (uint i = 0; i < ea.Count; i++) - { - if (!JsonComparesEqual(ea[(int)i], aa[(int)i])) - { - return false; - } - } - return true; - } - case JsonValueType.Object: - { - var eo = expected.GetObject(); - var ao = actual.GetObject(); - if (eo.Keys.Count != ao.Keys.Count) { return false; } - foreach (var key in eo.Keys) - { - if (!JsonComparesEqual(eo.GetNamedValue(key), ao.GetNamedValue(key))) - { - return false; - } - } - return true; - } - default: - throw new ArgumentException(); } } - private string GetOutputFile() - { - return "TreeDump\\" + m_dumpID + (mode == DumpTreeMode.Json ? ".json" : ".out"); - } - - private string GetMasterFile() - { - return "TreeDump\\masters\\" + m_dumpID + (mode == DumpTreeMode.Json ? ".json" : ".txt"); - } - private static IList GetInlines(StorageFile masterFile, StorageFile outFile, UIElement anchor) { Hyperlink masterLink = new Hyperlink(); diff --git a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpHelper.cs b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpHelper.cs new file mode 100644 index 00000000000..ec75dde5154 --- /dev/null +++ b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpHelper.cs @@ -0,0 +1,249 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Windows.Data.Json; +using Windows.Storage; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; + +namespace TreeDumpLibrary +{ + public static class TreeDumpHelper + { + + private static DependencyObject FindChildWithMatchingUIAID(DependencyObject element, string uiaId) + { + string automationId = (string)element.GetValue(Windows.UI.Xaml.Automation.AutomationProperties.AutomationIdProperty); + if (automationId == uiaId) + { + return element; + } + int childrenCount = VisualTreeHelper.GetChildrenCount(element); + for (int i = 0; i < childrenCount; i++) + { + var result = FindChildWithMatchingUIAID(VisualTreeHelper.GetChild(element, i), uiaId); + if (result != null) + { + return result; + } + } + + return null; + } + + internal static async Task MatchTreeDumpFromLayoutUpdateAsync(string dumpID, string uiaId, TextBlock textBlock, IList additionalProperties, DumpTreeMode mode, string dumpExpectedText) + { + // First find root + DependencyObject current = textBlock; + DependencyObject parent = VisualTreeHelper.GetParent(current); + while (parent != null) + { + current = parent; + parent = VisualTreeHelper.GetParent(current); + } + + DependencyObject dumpRoot = current; + // if UIAID is passed in from test, find the matching child as the root to dump + if (uiaId != null) + { + var matchingNode = FindChildWithMatchingUIAID(current, uiaId); + if (matchingNode != null) + { + dumpRoot = matchingNode; + } + } + + string dumpText = VisualTreeDumper.DumpTree(dumpRoot, textBlock /* exclude */, additionalProperties, mode); + if (dumpText != dumpExpectedText) + { + return await MatchDump(dumpText, dumpID); + } + return true; + } + + + internal static async Task MatchDump(string outputJson, string dumpID) + { + Debug.WriteLine($"master file = {Windows.ApplicationModel.Package.Current.InstalledLocation.Path}\\Assets\\{GetMasterFile(dumpID)}"); + StorageFolder storageFolder = ApplicationData.Current.LocalFolder; + string fileName = GetOutputFile(dumpID); + Debug.WriteLine($"output file = {storageFolder.Path + "\\" + fileName}"); + + StorageFile outFile = await storageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); + await FileIO.WriteTextAsync(outFile, outputJson); + + StorageFile masterFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync($@"Assets\{GetMasterFile(dumpID)}"); + + string masterJson = await FileIO.ReadTextAsync(masterFile); + + if (!DumpsAreEqual(masterJson, outputJson)) + { + return false; + } + else + { + return true; + } + } + + public static bool DumpsAreEqual(string dumpExpectedText, string dumpText) + { + JsonValue expected = JsonValue.Parse(dumpExpectedText); + JsonValue actual = JsonValue.Parse(dumpText); + return JsonComparesEqual(expected, actual, "root"); + } + + static readonly double epsilon = 1.0; + + private static bool JsonComparesEqual(IJsonValue expected, IJsonValue actual, string keyName) + { + const string Anything = ""; + if (expected.ValueType == JsonValueType.String && Regex.Replace(expected.GetString(), @"\p{C}", "") == Anything) + { + Debug.WriteLine($"Skipping ignored value: {actual.ValueType} {actual}"); + return true; + } + //Debug.WriteLine($"keyname: {keyName} {expected.ValueType} {actual.ValueType}"); + if (expected.ValueType != actual.ValueType) + { + Debug.WriteLine($"Expected {expected} got {actual}"); + return false; + } + switch (expected.ValueType) + { + case JsonValueType.String: + if (expected.GetString() != actual.GetString()) + { + Debug.WriteLine($"string:Expected {expected.GetString()} got {actual.GetString()}"); + return false; + } + return true; + case JsonValueType.Number: + if (Math.Abs(expected.GetNumber() - actual.GetNumber()) > epsilon) + { + Debug.WriteLine($"number: {keyName} {expected.GetNumber()} {actual.GetNumber()}"); + return false; + } + return true; + case JsonValueType.Boolean: + return expected.GetBoolean() == actual.GetBoolean(); + case JsonValueType.Null: + return true; + case JsonValueType.Array: + { + var ea = expected.GetArray(); + var aa = actual.GetArray(); + if (!JsonCompareArray(ea, aa)) + { + Debug.WriteLine("in key " + keyName); + return false; + } + return true; + } + case JsonValueType.Object: + { + if (!JsonCompareObject(expected.GetObject(), actual.GetObject())) + { + Debug.WriteLine("in key " + keyName); + return false; + } + return true; + } + default: + throw new ArgumentException(); + } + } + + private static bool JsonCompareArray(JsonArray ea, JsonArray aa) + { + var efiltered = ea.Where(x => IsNonCollapsed(x)).ToArray(); + var afiltered = aa.Where(x => IsNonCollapsed(x)).ToArray(); + + if (efiltered.Length != afiltered.Length) + { + Debug.WriteLine($"Array count expected {ea.Count} got {aa.Count}"); + return false; + } + for (int i = 0; i < efiltered.Length; i++) + { + var _e = efiltered[i]; + var _a = afiltered[i]; + if (!JsonComparesEqual(_e, _a, "array element")) + { + Debug.WriteLine($"Array element {i} expected {_e.ValueType} got {_a.ValueType}"); + return false; + } + } + return true; + } + + private const string visibilityProperty = "Visibility"; + private const string visibilityPropertyVisible = "Visible"; + + private static bool IsNonCollapsed(IJsonValue x) + { + return x.ValueType != JsonValueType.Object || + !x.GetObject().ContainsKey(visibilityProperty) || + x.GetObject().GetNamedString(visibilityProperty) == visibilityPropertyVisible; + } + + private static bool JsonCompareObject(JsonObject eo, JsonObject ao) + { + var evisible = true; + if (eo.Keys.Contains(visibilityProperty)) + { + evisible = eo[visibilityProperty].GetString() == visibilityPropertyVisible; + eo.Remove(visibilityProperty); + } + var avisible = true; + if (ao.Keys.Contains(visibilityProperty)) + { + avisible = ao[visibilityProperty].GetString() == visibilityPropertyVisible; + ao.Remove(visibilityProperty); + } + if (avisible != evisible) { return false; } + if (avisible == false) + { + // both are collapsed (or nonexistent) so don't compare children + ao.Remove("children"); + eo.Remove("children"); + } + + if (eo.Keys.Count != ao.Keys.Count) + { + Debug.WriteLine($"Expected {eo.Keys.Count} but got {ao.Keys.Count}"); + Debug.WriteLine(string.Join(", ", eo.Keys)); + Debug.WriteLine(string.Join(", ", ao.Keys)); + return false; + } + foreach (var key in eo.Keys) + { + JsonValue evalue = eo.GetNamedValue(key); + JsonValue avalue = ao.GetNamedValue(key); + if (!JsonComparesEqual(evalue, avalue, key)) + { + Debug.WriteLine($"Property {key} compared differently {evalue.ValueType} {avalue.ValueType}: expected {evalue} got {avalue}"); + return false; + } + } + return true; + } + + public static string GetOutputFile(string dumpID) + { + return "TreeDump\\" + dumpID + ".json"; + } + + public static string GetMasterFile(string dumpID) + { + return "TreeDump\\masters\\" + dumpID + ".json"; + } + } +} diff --git a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj index e8ca1d3675b..6d7628538f4 100644 --- a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj +++ b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj @@ -1,6 +1,5 @@  - + Debug @@ -112,6 +111,7 @@ + diff --git a/packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs b/packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs index 32a43aa7bd2..fd95352ebb4 100644 --- a/packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs +++ b/packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs @@ -3,10 +3,15 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Windows.Data.Json; using Windows.Foundation; using Windows.UI.Xaml; +using Windows.UI.Xaml.Automation; using Windows.UI.Xaml.Media; namespace TreeDumpLibrary @@ -51,12 +56,15 @@ public override string ToString() public bool ShouldVisitPropertiesForNode(DependencyObject node) { - return (node as UIElement) != null; + var fe = node as FrameworkElement; + string[] excludedNames = new string[] { "VerticalScrollBar", "HorizontalScrollBar", "ScrollBarSeparator" }; + if (fe != null && excludedNames.Contains(fe.Name)) { return false; } + return true; } - public bool ShouldVisitProperty(PropertyInfo propertyInfo) + public bool ShouldVisitProperty(string propertyName) { - return _filter.ShouldVisitProperty(propertyInfo.Name); + return _filter.ShouldVisitProperty(propertyName); } public void VisitProperty(string propertyName, object value, bool isLast) @@ -88,6 +96,50 @@ public bool ShouldVisitPropertyValue(string propertyName, object value) } } + private static JsonObject FindElementByAutomationId(JsonObject obj, string automationId) + { + if (obj.Keys.Contains("AutomationId") && obj["AutomationId"].GetString() == automationId) + { + return obj; + } + if (obj.Keys.Contains("children")) + { + var array = obj.GetNamedArray("children"); + foreach (var i in array) + { + var element = FindElementByAutomationId(i.GetObject(), automationId); + if (element != null) + { + return element; + } + } + } + return null; + } + + public static IAsyncOperation DoesTreeDumpMatchForRNTester(DependencyObject root) + { + string json = DumpTree(root, null, new string[] { }, DumpTreeMode.Json); + try + { + var obj = JsonValue.Parse(json).GetObject(); + var element = FindElementByAutomationId(obj, "PageHeader"); + if (element == null) + { + return Task.Run(() => false).AsAsyncOperation(); + } + var value = element.GetNamedString("Text"); + var pageName = new Regex(@"[<|>]").Replace(value, ""); + var match = TreeDumpHelper.MatchDump(json, pageName); + return match.AsAsyncOperation(); + } + catch + { + Debug.WriteLine("JSON ERROR:\n" + json); + throw; + } + } + public static string DumpTree(DependencyObject root, DependencyObject excludedNode, IList additionalProperties, DumpTreeMode mode) { var propertyFilter = new DefaultFilter(); @@ -111,20 +163,26 @@ private static void WalkThroughProperties(DependencyObject node, Visitor visitor if (visitor.ShouldVisitPropertiesForNode(node)) { var properties = (from property in node.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) - where visitor.ShouldVisitProperty(property) && + where visitor.ShouldVisitProperty(property.Name) && visitor.ShouldVisitPropertyValue(property.Name, GetObjectProperty(node, property)) orderby property.Name select property).ToArray(); + var automationId = node.GetValue(AutomationProperties.AutomationIdProperty); for (int i = 0; i < properties.Length; i++) { var property = properties[i]; object value = null; value = GetObjectProperty(node, property); - bool isLast = (i == properties.Length - 1) && !hasChildren; + bool isLast = (i == properties.Length - 1) && !hasChildren && (automationId == null); visitor.VisitProperty(property.Name, value, isLast); } + + if (automationId != null) + { + visitor.VisitProperty("AutomationId", automationId, !hasChildren); + } } } @@ -143,24 +201,36 @@ private static object GetObjectProperty(DependencyObject node, PropertyInfo prop return value; } + private static DependencyObject[] GetChildren(DependencyObject node, Visitor visitor) + { + DependencyObject[] dos = new DependencyObject[VisualTreeHelper.GetChildrenCount(node)]; + for (int i = 0; i < dos.Length; i++) + { + dos[i] = VisualTreeHelper.GetChild(node, i); + } + return dos.Where((n) => visitor.ShouldVisitPropertiesForNode(n)).ToArray(); + } + private static void WalkThroughTree(DependencyObject node, DependencyObject excludedNode, Visitor visitor, bool isLast = true) { - if (node != null) + if (node != null && visitor.ShouldVisitPropertiesForNode(node)) { // Assume that if we have a UIElement, we'll have some properties - visitor.BeginVisitNode(node, node is UIElement); + var children = GetChildren(node, visitor); + bool hasProperties = node is UIElement || (children.Length > 0); + + visitor.BeginVisitNode(node, hasProperties); - var childrenCount = VisualTreeHelper.GetChildrenCount(node); - WalkThroughProperties(node, visitor, childrenCount != 0); - if (childrenCount != 0) + WalkThroughProperties(node, visitor, children.Length != 0); + if (children.Length != 0) { visitor.BeginChildren(); - for (int i = 0; i < childrenCount; i++) + for (int i = 0; i < children.Length; i++) { - var child = VisualTreeHelper.GetChild(node, i); + var child = children[i]; if (child != excludedNode) { - bool isLastChild = (i == childrenCount - 1); + bool isLastChild = (i == children.Length - 1); WalkThroughTree(child, excludedNode, visitor, isLastChild); } } @@ -194,6 +264,7 @@ public DefaultFilter() "Clip", "FlowDirection", "Name", + "Text" /*"ActualOffset" 19h1*/ }; } @@ -251,13 +322,17 @@ public string PropertyValueToString(string propertyName, object propertyObject) { // comparing doubles is numerically unstable so just compare their integer parts Size size = (Size)propertyObject; - return $"[{(int)size.Width}, {(int)size.Height}]"; + int width = (int)size.Width; + int height = (int)size.Height; + return $"[{width}, {height}]"; } return Quote(propertyObject.ToString()); } public static string Quote(string s) { + s = s.Replace('\t', ' ').Replace("\n", @"\n"); + s = Regex.Replace(s, @"\p{Cs}", ""); // remove surrogate pairs e.g. emojis return '"' + s.Replace("\"", "\\\"") + '"'; } } From 7de1f3843a9754c7fbf744bf3e556fdca78472c1 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Thu, 14 May 2020 13:09:11 -0700 Subject: [PATCH 107/209] winui3 option for app project template (and update C++ template) (#4799) * winui3 option for app project template * only use winui3 in MSRN if we are getting --useWinUI3 * Change files --- ...05-08-17-28-25-winui3AppTemplateCPP_2.json | 8 +++++ ...05-08-17-28-25-winui3AppTemplateCPP_2.json | 8 +++++ packages/react-native-windows-init/src/Cli.ts | 8 +++++ vnext/ReactWindows-Universal.sln | 2 +- vnext/local-cli/generate-windows.js | 8 ++++- vnext/local-cli/generator-windows/index.js | 36 +++++++++++++++++++ .../templates/cpp/proj/MyApp.vcxproj | 5 +-- .../templates/cpp/proj/packages.config | 2 +- .../generator-windows/templates/cpp/src/pch.h | 14 ++++---- 9 files changed, 79 insertions(+), 12 deletions(-) create mode 100644 change/react-native-windows-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json create mode 100644 change/react-native-windows-init-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json diff --git a/change/react-native-windows-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json b/change/react-native-windows-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json new file mode 100644 index 00000000000..3a54d092f44 --- /dev/null +++ b/change/react-native-windows-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "winui3 option for app project template", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-09T00:28:25.731Z" +} diff --git a/change/react-native-windows-init-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json b/change/react-native-windows-init-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json new file mode 100644 index 00000000000..22223002272 --- /dev/null +++ b/change/react-native-windows-init-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json @@ -0,0 +1,8 @@ +{ + "type": "patch", + "comment": "winui3 option for app project template", + "packageName": "react-native-windows-init", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-09T00:28:20.187Z" +} diff --git a/packages/react-native-windows-init/src/Cli.ts b/packages/react-native-windows-init/src/Cli.ts index c6bb52dc523..33eb1b1274f 100644 --- a/packages/react-native-windows-init/src/Cli.ts +++ b/packages/react-native-windows-init/src/Cli.ts @@ -47,6 +47,13 @@ const argv = yargs.version(false).options({ 'Experimental change to start consuming a nuget containing a pre-built dll version of Microsoft.ReactNative', hidden: true, }, + useWinUI3: { + type: 'boolean', + describe: + '[Experimental] Use WinUI3', + hidden: true, + default: false, + } }).argv; const EXITCODE_UNSUPPORTED_VERION_RN = 3; @@ -354,6 +361,7 @@ You can either downgrade your version of ${chalk.green( overwrite: argv.overwrite, verbose: argv.verbose, experimentalNugetDependency: argv.experimentalNugetDependency, + useWinUI3: argv.useWinUI3, }); } catch (error) { console.error(chalk.red(error.message)); diff --git a/vnext/ReactWindows-Universal.sln b/vnext/ReactWindows-Universal.sln index 65288035f89..9bd8ab921fa 100644 --- a/vnext/ReactWindows-Universal.sln +++ b/vnext/ReactWindows-Universal.sln @@ -16,7 +16,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactCommon", "ReactCommon\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxitems", "{11C084A3-A57C-4296-A679-CAC17B603145}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "ReactWindowsCore\ReactWindowsCore.vcxproj", "{11C084A3-A57C-4296-A679-CAC17B603144}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore-UWP", "ReactWindowsCore\ReactWindowsCore.vcxproj", "{11C084A3-A57C-4296-A679-CAC17B603144}" ProjectSection(ProjectDependencies) = postProject {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} EndProjectSection diff --git a/vnext/local-cli/generate-windows.js b/vnext/local-cli/generate-windows.js index f4df862c72e..eb43c6c650d 100644 --- a/vnext/local-cli/generate-windows.js +++ b/vnext/local-cli/generate-windows.js @@ -26,7 +26,13 @@ function generateWindows (projectDir, name, ns, options) { path.join(__dirname, 'generator-windows', 'templates'), projectDir, name, - { ns, overwrite: options.overwrite, language: options.language, experimentalNugetDependency: options.experimentalNugetDependency } + { + ns, + overwrite: options.overwrite, + language: options.language, + experimentalNugetDependency: options.experimentalNugetDependency, + useWinUI3: options.useWinUI3, + } ); } diff --git a/vnext/local-cli/generator-windows/index.js b/vnext/local-cli/generator-windows/index.js index bd91a929efa..f34881758f9 100644 --- a/vnext/local-cli/generator-windows/index.js +++ b/vnext/local-cli/generator-windows/index.js @@ -81,6 +81,27 @@ function copyProjectTemplateAndReplace( const currentUser = username.sync(); // Gets the current username depending on the platform. const certificateThumbprint = generateCertificate(srcPath, destPath, newProjectName, currentUser); + + const xamlNugetPkgName = options.useWinUI3 ? 'Microsoft.WinUI' : 'Microsoft.UI.Xaml'; + const xamlNugetPkgVersion = options.useWinUI3 ? '3.0.0-alpha.200210.0' : '2.3.191129002'; + + const xamlPropsFile = `..\\packages\\${xamlNugetPkgName}.${xamlNugetPkgVersion}\\build\\native\\${xamlNugetPkgName}.props`; + const xamlPropsImport = ``; + const xamlProps30 = String.raw`${xamlPropsImport} + + + USE_WINUI3;%(PreprocessorDefinitions) + + +`; + const xamlProps2x = xamlPropsImport; + const xamlProps = options.useWinUI3 ? xamlProps30 : xamlProps2x; + + const xamlTargetsPath = `..\\packages\\${xamlNugetPkgName}.${xamlNugetPkgVersion}\\build\\native\\${xamlNugetPkgName}.targets`; + const xamlTargets = ``; + const xamlNugetErrors = ``; + const xamlNamespace = options.useWinUI3 ? 'Microsoft.UI.Xaml' : 'Windows.UI.Xaml'; + const templateVars = { '// clang-format off': '', '// clang-format on': '', @@ -92,6 +113,12 @@ function copyProjectTemplateAndReplace( '<%=packageGuid%>': packageGuid, '<%=currentUser%>': currentUser, '<%=certificateThumbprint%>': certificateThumbprint ? `${certificateThumbprint}` : '', + '<%=XamlProps%>': xamlProps, + '<%=XamlTargets%>': xamlTargets, + '<%=XamlNugetErrors%>': xamlNugetErrors, + '<%=XamlNugetPkgName%>': xamlNugetPkgName, + '<%=XamlNugetPkgVersion%>': xamlNugetPkgVersion, + '<%=XamlNamespace%>': xamlNamespace, }; [ @@ -102,6 +129,15 @@ function copyProjectTemplateAndReplace( { from: path.join(srcPath, projDir, 'MyApp.sln'), to: path.join(windowsDir, newProjectName + '.sln') }, ].forEach((mapping) => copyAndReplaceWithChangedCallback(mapping.from, destPath, mapping.to, templateVars, options.overwrite)); + if (options.useWinUI3) { + const slnFilePath = path.join(windowsDir, newProjectName + '.sln'); + const slnText = fs.readFileSync(slnFilePath).toString(); + // Target Microsoft.ReactNative.Cxx to WinUI3 + const regex = /({F7D32BD0-2749-483E-9A0D-1635EF7E3136}\..*\.\w+) = \w+\|([\w\d]+)/g; + const makeWinUI3 = '$1 = WinUI3|$2'; + fs.writeFileSync(slnFilePath, slnText.replace(regex, makeWinUI3)); + } + if (language === 'cs') { [ { from: path.join(srcPath, projDir, 'MyApp.csproj'), to: path.join(windowsDir, newProjectName, newProjectName + '.csproj') }, diff --git a/vnext/local-cli/generator-windows/templates/cpp/proj/MyApp.vcxproj b/vnext/local-cli/generator-windows/templates/cpp/proj/MyApp.vcxproj index ad4204b1b23..e1ce6a27d50 100644 --- a/vnext/local-cli/generator-windows/templates/cpp/proj/MyApp.vcxproj +++ b/vnext/local-cli/generator-windows/templates/cpp/proj/MyApp.vcxproj @@ -67,6 +67,7 @@ true false + <%=XamlProps%> @@ -162,7 +163,7 @@ - + <%=XamlTargets%> @@ -170,6 +171,6 @@ - + <%=XamlNugetErrors%> \ No newline at end of file diff --git a/vnext/local-cli/generator-windows/templates/cpp/proj/packages.config b/vnext/local-cli/generator-windows/templates/cpp/proj/packages.config index 944c02938da..aa77da1937b 100644 --- a/vnext/local-cli/generator-windows/templates/cpp/proj/packages.config +++ b/vnext/local-cli/generator-windows/templates/cpp/proj/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/vnext/local-cli/generator-windows/templates/cpp/src/pch.h b/vnext/local-cli/generator-windows/templates/cpp/src/pch.h index 4226997d4d4..60036393aa9 100644 --- a/vnext/local-cli/generator-windows/templates/cpp/src/pch.h +++ b/vnext/local-cli/generator-windows/templates/cpp/src/pch.h @@ -9,13 +9,13 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include .Controls.Primitives.h> +#include .Controls.h> +#include .Data.h> +#include .Interop.h> +#include .Markup.h> +#include .Navigation.h> +#include .h> #include From 178583fbf015ecfaecb00a7e81d53d9699b5d2ce Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Thu, 14 May 2020 14:33:45 -0700 Subject: [PATCH 108/209] Install exact version of WinAppDriver (#4905) * exact match of WinAppDriver required * Change files --- ...-windows-2020-05-14-00-25-43-rnw-dep-winappdriver.json | 8 ++++++++ vnext/Scripts/rnw-dependencies.ps1 | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 change/react-native-windows-2020-05-14-00-25-43-rnw-dep-winappdriver.json diff --git a/change/react-native-windows-2020-05-14-00-25-43-rnw-dep-winappdriver.json b/change/react-native-windows-2020-05-14-00-25-43-rnw-dep-winappdriver.json new file mode 100644 index 00000000000..08fa20d6316 --- /dev/null +++ b/change/react-native-windows-2020-05-14-00-25-43-rnw-dep-winappdriver.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "exact match of WinAppDriver required", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-14T07:25:43.437Z" +} diff --git a/vnext/Scripts/rnw-dependencies.ps1 b/vnext/Scripts/rnw-dependencies.ps1 index c274c09006f..c6006a11d5c 100644 --- a/vnext/Scripts/rnw-dependencies.ps1 +++ b/vnext/Scripts/rnw-dependencies.ps1 @@ -109,7 +109,13 @@ $requirements = @( @{ Name = 'WinAppDriver'; Valid = (Test-Path "${env:ProgramFiles(x86)}\Windows Application Driver\WinAppDriver.exe"); - Install = { choco install -y WinAppDriver }; + Install = { + # don't install from choco as we need an exact version match. appium-windows-driver checks the checksum of WAD. + # See \node_modules\appium-windows-driver\build\lib\installer.js + $ProgressPreference = 'Ignore'; + Invoke-WebRequest https://github.com/microsoft/WinAppDriver/releases/download/v1.1/WindowsApplicationDriver.msi -OutFile $env:TEMP\WindowsApplicationDriver.msi + & $env:TEMP\WindowsApplicationDriver.msi /q + }; } ); From 45f814c4785c23796edaa6c407008effaf1d5b1f Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Fri, 15 May 2020 00:04:44 +0000 Subject: [PATCH 109/209] applying package updates ***NO_CI*** --- ...05-12-21-44-51-accessibilityLabeledBy.json | 8 ---- ...05-08-17-28-25-winui3AppTemplateCPP_2.json | 8 ---- ...ndows-2020-05-13-03-45-39-smaller-pch.json | 8 ---- ...-53-42-remove-unused-lifecycle-events.json | 8 ---- ...-windows-2020-05-13-17-33-52-Move_pch.json | 8 ---- ...0-05-14-00-25-43-rnw-dep-winappdriver.json | 8 ---- ...05-08-17-28-25-winui3AppTemplateCPP_2.json | 8 ---- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- packages/react-native-win32/CHANGELOG.json | 15 +++++++ packages/react-native-win32/CHANGELOG.md | 10 ++++- packages/react-native-win32/package.json | 2 +- .../react-native-windows-init/CHANGELOG.json | 15 +++++++ .../react-native-windows-init/CHANGELOG.md | 10 ++++- .../react-native-windows-init/package.json | 2 +- vnext/CHANGELOG.json | 39 +++++++++++++++++++ vnext/CHANGELOG.md | 14 ++++++- vnext/package.json | 2 +- 19 files changed, 106 insertions(+), 65 deletions(-) delete mode 100644 change/@office-iss-react-native-win32-2020-05-12-21-44-51-accessibilityLabeledBy.json delete mode 100644 change/react-native-windows-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json delete mode 100644 change/react-native-windows-2020-05-13-03-45-39-smaller-pch.json delete mode 100644 change/react-native-windows-2020-05-13-12-53-42-remove-unused-lifecycle-events.json delete mode 100644 change/react-native-windows-2020-05-13-17-33-52-Move_pch.json delete mode 100644 change/react-native-windows-2020-05-14-00-25-43-rnw-dep-winappdriver.json delete mode 100644 change/react-native-windows-init-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json diff --git a/change/@office-iss-react-native-win32-2020-05-12-21-44-51-accessibilityLabeledBy.json b/change/@office-iss-react-native-win32-2020-05-12-21-44-51-accessibilityLabeledBy.json deleted file mode 100644 index ca92f8b3916..00000000000 --- a/change/@office-iss-react-native-win32-2020-05-12-21-44-51-accessibilityLabeledBy.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Add win32-specific accessibility props Description, DescribedBy, and LabeledBy", - "packageName": "@office-iss/react-native-win32", - "email": "ppatboyd@outlook.com", - "dependentChangeType": "patch", - "date": "2020-05-13T04:44:51.679Z" -} diff --git a/change/react-native-windows-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json b/change/react-native-windows-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json deleted file mode 100644 index 3a54d092f44..00000000000 --- a/change/react-native-windows-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "winui3 option for app project template", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-09T00:28:25.731Z" -} diff --git a/change/react-native-windows-2020-05-13-03-45-39-smaller-pch.json b/change/react-native-windows-2020-05-13-03-45-39-smaller-pch.json deleted file mode 100644 index 73f7f872090..00000000000 --- a/change/react-native-windows-2020-05-13-03-45-39-smaller-pch.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Reduce PCH Sizes", - "packageName": "react-native-windows", - "email": "ngerlem@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-13T10:45:39.135Z" -} diff --git a/change/react-native-windows-2020-05-13-12-53-42-remove-unused-lifecycle-events.json b/change/react-native-windows-2020-05-13-12-53-42-remove-unused-lifecycle-events.json deleted file mode 100644 index 11b48218652..00000000000 --- a/change/react-native-windows-2020-05-13-12-53-42-remove-unused-lifecycle-events.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Remove unused lifecycle events in ReactNativeHost", - "packageName": "react-native-windows", - "email": "kaigu@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-13T19:53:42.358Z" -} diff --git a/change/react-native-windows-2020-05-13-17-33-52-Move_pch.json b/change/react-native-windows-2020-05-13-17-33-52-Move_pch.json deleted file mode 100644 index 0621be3bc56..00000000000 --- a/change/react-native-windows-2020-05-13-17-33-52-Move_pch.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Move pch files into a Pch subfolder.", - "packageName": "react-native-windows", - "email": "vmorozov@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-14T00:33:52.732Z" -} diff --git a/change/react-native-windows-2020-05-14-00-25-43-rnw-dep-winappdriver.json b/change/react-native-windows-2020-05-14-00-25-43-rnw-dep-winappdriver.json deleted file mode 100644 index 08fa20d6316..00000000000 --- a/change/react-native-windows-2020-05-14-00-25-43-rnw-dep-winappdriver.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "exact match of WinAppDriver required", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-14T07:25:43.437Z" -} diff --git a/change/react-native-windows-init-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json b/change/react-native-windows-init-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json deleted file mode 100644 index 22223002272..00000000000 --- a/change/react-native-windows-init-2020-05-08-17-28-25-winui3AppTemplateCPP_2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "patch", - "comment": "winui3 option for app project template", - "packageName": "react-native-windows-init", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-09T00:28:20.187Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index e323ad48961..b0e0e478ff0 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.66" + "react-native-windows": "0.0.0-master.67" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 84d9aed98f0..1b8b9b1253a 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.66" + "react-native-windows": "0.0.0-master.67" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index cbbc35ea54a..7011653d84c 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -11,7 +11,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.66" + "react-native-windows": "0.0.0-master.67" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/react-native-win32/CHANGELOG.json b/packages/react-native-win32/CHANGELOG.json index c1328fdab67..73090921cb3 100644 --- a/packages/react-native-win32/CHANGELOG.json +++ b/packages/react-native-win32/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@office-iss/react-native-win32", "entries": [ + { + "date": "Fri, 15 May 2020 00:04:44 GMT", + "tag": "@office-iss/react-native-win32_v0.0.0-master.11", + "version": "0.0.0-master.11", + "comments": { + "prerelease": [ + { + "comment": "Add win32-specific accessibility props Description, DescribedBy, and LabeledBy", + "author": "ppatboyd@outlook.com", + "commit": "579a25b0079e62375e2ab94d4f8680e14d19c0c8", + "package": "@office-iss/react-native-win32" + } + ] + } + }, { "date": "Sat, 09 May 2020 00:04:42 GMT", "tag": "@office-iss/react-native-win32_v0.0.0-master.10", diff --git a/packages/react-native-win32/CHANGELOG.md b/packages/react-native-win32/CHANGELOG.md index 890deefd57e..a5f0a5f83b9 100644 --- a/packages/react-native-win32/CHANGELOG.md +++ b/packages/react-native-win32/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @office-iss/react-native-win32 -This log was last generated on Sat, 09 May 2020 00:04:42 GMT and should not be manually modified. +This log was last generated on Fri, 15 May 2020 00:04:44 GMT and should not be manually modified. +## 0.0.0-master.11 + +Fri, 15 May 2020 00:04:44 GMT + +### Changes + +- Add win32-specific accessibility props Description, DescribedBy, and LabeledBy (ppatboyd@outlook.com) + ## 0.0.0-master.10 Sat, 09 May 2020 00:04:42 GMT diff --git a/packages/react-native-win32/package.json b/packages/react-native-win32/package.json index 25955c93fb8..e1a6a2c0e97 100644 --- a/packages/react-native-win32/package.json +++ b/packages/react-native-win32/package.json @@ -1,6 +1,6 @@ { "name": "@office-iss/react-native-win32", - "version": "0.0.0-master.10", + "version": "0.0.0-master.11", "description": "Implementation of react native on top of Office's Win32 platform.", "license": "MIT", "main": "./index.win32.js", diff --git a/packages/react-native-windows-init/CHANGELOG.json b/packages/react-native-windows-init/CHANGELOG.json index 348ade66582..29540da09b6 100644 --- a/packages/react-native-windows-init/CHANGELOG.json +++ b/packages/react-native-windows-init/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "react-native-windows-init", "entries": [ + { + "date": "Fri, 15 May 2020 00:04:44 GMT", + "tag": "react-native-windows-init_v0.1.7", + "version": "0.1.7", + "comments": { + "patch": [ + { + "comment": "winui3 option for app project template", + "author": "asklar@microsoft.com", + "commit": "7de1f3843a9754c7fbf744bf3e556fdca78472c1", + "package": "react-native-windows-init" + } + ] + } + }, { "date": "Wed, 06 May 2020 00:05:03 GMT", "tag": "react-native-windows-init_v0.1.6", diff --git a/packages/react-native-windows-init/CHANGELOG.md b/packages/react-native-windows-init/CHANGELOG.md index 88e41cbbd3c..b7a8d1340e6 100644 --- a/packages/react-native-windows-init/CHANGELOG.md +++ b/packages/react-native-windows-init/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - react-native-windows-init -This log was last generated on Wed, 06 May 2020 00:05:03 GMT and should not be manually modified. +This log was last generated on Fri, 15 May 2020 00:04:44 GMT and should not be manually modified. +## 0.1.7 + +Fri, 15 May 2020 00:04:44 GMT + +### Patches + +- winui3 option for app project template (asklar@microsoft.com) + ## 0.1.6 Wed, 06 May 2020 00:05:03 GMT diff --git a/packages/react-native-windows-init/package.json b/packages/react-native-windows-init/package.json index 4d79b0c4252..0e9fe1c427e 100644 --- a/packages/react-native-windows-init/package.json +++ b/packages/react-native-windows-init/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows-init", - "version": "0.1.6", + "version": "0.1.7", "description": "CLI to add react-native-windows to an existing react-native project", "main": "index.js", "repository": "https://github.com/microsoft/react-native-windows", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index 0c2b77d662f..aefa45cb287 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,45 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Fri, 15 May 2020 00:04:44 GMT", + "tag": "react-native-windows_v0.0.0-master.67", + "version": "0.0.0-master.67", + "comments": { + "prerelease": [ + { + "comment": "winui3 option for app project template", + "author": "asklar@microsoft.com", + "commit": "7de1f3843a9754c7fbf744bf3e556fdca78472c1", + "package": "react-native-windows" + }, + { + "comment": "Reduce PCH Sizes", + "author": "ngerlem@microsoft.com", + "commit": "f6f43e1d51a67cbe27cab77684bab6cce3869c03", + "package": "react-native-windows" + }, + { + "comment": "Remove unused lifecycle events in ReactNativeHost", + "author": "kaigu@microsoft.com", + "commit": "a8cf72c8ce76c2b140c860990a9cdfd753085325", + "package": "react-native-windows" + }, + { + "comment": "Move pch files into a Pch subfolder.", + "author": "vmorozov@microsoft.com", + "commit": "204bc9e292a9889111f72e143555c3be57bf5a99", + "package": "react-native-windows" + }, + { + "comment": "exact match of WinAppDriver required", + "author": "asklar@microsoft.com", + "commit": "178583fbf015ecfaecb00a7e81d53d9699b5d2ce", + "package": "react-native-windows" + } + ] + } + }, { "date": "Thu, 14 May 2020 00:04:37 GMT", "tag": "react-native-windows_v0.0.0-master.66", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index bf33c0136ab..c4fbc42fed7 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,21 @@ # Change Log - react-native-windows -This log was last generated on Thu, 14 May 2020 00:04:37 GMT and should not be manually modified. +This log was last generated on Fri, 15 May 2020 00:04:44 GMT and should not be manually modified. +## 0.0.0-master.67 + +Fri, 15 May 2020 00:04:44 GMT + +### Changes + +- winui3 option for app project template (asklar@microsoft.com) +- Reduce PCH Sizes (ngerlem@microsoft.com) +- Remove unused lifecycle events in ReactNativeHost (kaigu@microsoft.com) +- Move pch files into a Pch subfolder. (vmorozov@microsoft.com) +- exact match of WinAppDriver required (asklar@microsoft.com) + ## 0.0.0-master.66 Thu, 14 May 2020 00:04:37 GMT diff --git a/vnext/package.json b/vnext/package.json index 615573c49b6..565fb80ff1d 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.66", + "version": "0.0.0-master.67", "license": "MIT", "repository": { "type": "git", From e0f591e8aaca01c7a52ac2825d8476920880bfed Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Thu, 14 May 2020 17:39:48 -0700 Subject: [PATCH 110/209] Some projects have target instead of bin folders (#4910) * some projects have target instead of bin folders * Change files --- change/react-native-windows-2020-05-14-13-47-03-4881.json | 8 ++++++++ vnext/local-cli/runWindows/utils/deploy.js | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 change/react-native-windows-2020-05-14-13-47-03-4881.json diff --git a/change/react-native-windows-2020-05-14-13-47-03-4881.json b/change/react-native-windows-2020-05-14-13-47-03-4881.json new file mode 100644 index 00000000000..d5100c76cab --- /dev/null +++ b/change/react-native-windows-2020-05-14-13-47-03-4881.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "some projects have target instead of bin folders", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-14T20:47:03.172Z" +} diff --git a/vnext/local-cli/runWindows/utils/deploy.js b/vnext/local-cli/runWindows/utils/deploy.js index d32b6530f05..7ae6c84dd1d 100644 --- a/vnext/local-cli/runWindows/utils/deploy.js +++ b/vnext/local-cli/runWindows/utils/deploy.js @@ -87,7 +87,9 @@ function getAppxManifestPath(options) { const configuration = getBuildConfiguration(options); const appxManifestGlob = `windows/{*/bin/${ options.arch - }/${configuration},${configuration}/*}/AppxManifest.xml`; + }/${configuration},${configuration}/*,target/${ + options.arch + }/${configuration}}/AppxManifest.xml`; const appxPath = glob.sync(path.join(options.root, appxManifestGlob))[0]; if (!appxPath) { From e15746b05bcb983f62637dcd586100afecf81b5f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 15 May 2020 03:41:06 +0000 Subject: [PATCH 111/209] Bump @types/semver from 7.1.0 to 7.2.0 (#4906) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4d224c615cd..4a4d1fca86b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2908,9 +2908,9 @@ csstype "^2.2.0" "@types/semver@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.1.0.tgz#c8c630d4c18cd326beff77404887596f96408408" - integrity sha512-pOKLaubrAEMUItGNpgwl0HMFPrSAFic8oSVIvfu1UwcgGNmNyK9gyhBHKmBnUTwwVvpZfkzUC0GaMgnL6P86uA== + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.2.0.tgz#0d72066965e910531e1db4621c15d0ca36b8d83b" + integrity sha512-TbB0A8ACUWZt3Y6bQPstW9QNbhNeebdgLX4T/ZfkrswAfUzRiXrgd9seol+X379Wa589Pu4UEx9Uok0D4RjRCQ== dependencies: "@types/node" "*" From 2d85b6a94f1a9e629c2e124f4f0951ff75829bad Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Fri, 15 May 2020 12:21:03 -0700 Subject: [PATCH 112/209] JustMyXaml.ps1 (#4914) * .\JustMyXaml.ps1 * Change files * pr feedback --- ...indows-2020-05-15-03-01-54-justMyXaml.json | 8 ++++++++ vnext/Scripts/JustMyXaml.ps1 | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 change/react-native-windows-2020-05-15-03-01-54-justMyXaml.json create mode 100644 vnext/Scripts/JustMyXaml.ps1 diff --git a/change/react-native-windows-2020-05-15-03-01-54-justMyXaml.json b/change/react-native-windows-2020-05-15-03-01-54-justMyXaml.json new file mode 100644 index 00000000000..682d8990a03 --- /dev/null +++ b/change/react-native-windows-2020-05-15-03-01-54-justMyXaml.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": ".\\JustMyXaml.ps1", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-15T10:01:54.898Z" +} diff --git a/vnext/Scripts/JustMyXaml.ps1 b/vnext/Scripts/JustMyXaml.ps1 new file mode 100644 index 00000000000..8fcd02a7357 --- /dev/null +++ b/vnext/Scripts/JustMyXaml.ps1 @@ -0,0 +1,20 @@ +# This script enables or disables VS 2019's JustMyXaml feature +[CmdletBinding()] +param([bool]$Enable) + +if (!([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544"))) { + throw "Please run this script elevated"; +} + +$instanceId = & "$(${env:ProgramFiles(x86)})\Microsoft Visual Studio\Installer\vswhere.exe" -property instanceId +$hiveFile = "$($env:LocalAppData)\Microsoft\VisualStudio\16.0_$instanceId\privateregistry.bin" +& reg.exe load HKLM\VS2019_HIVE $hiveFile | Out-Null +New-PSDrive -Name VS2019 -PSProvider Registry -Root HKLM\VS2019_HIVE -ErrorAction Stop | Out-Null +$currentValue = (Get-ItemProperty VS2019:\Software\Microsoft\VisualStudio\16.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml).EnableXamlVisualDiagnosticsJustMyXaml +if ($currentValue -eq 0) { $currentValue = $false; } else { $currentValue = $true; } +Write-Host "Current value: $currentValue" +if ($Enable) { $newValue = 1; } else { $newValue = 0; } +Set-ItemProperty VS2019:\Software\Microsoft\VisualStudio\16.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml -Value $newValue -Type DWord +Write-Host "New value: $Enable" +Remove-PSDrive -Name VS2019 +& reg.exe unload HKLM\VS2019_HIVE | Out-Null From 0ed42cac3b28889a35b4a3760047d0c3801b93bf Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 15 May 2020 12:43:04 -0700 Subject: [PATCH 113/209] Bump @microsoft/api-extractor from 7.8.0 to 7.8.1 (#4916) Bumps [@microsoft/api-extractor](https://github.com/microsoft/rushstack) from 7.8.0 to 7.8.1. - [Release notes](https://github.com/microsoft/rushstack/releases) - [Commits](https://github.com/microsoft/rushstack/compare/@microsoft/api-extractor_v7.8.0...@microsoft/api-extractor_v7.8.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4a4d1fca86b..8926c891647 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2429,14 +2429,14 @@ "@rushstack/node-core-library" "3.19.7" "@microsoft/api-extractor@^7.3.8": - version "7.8.0" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.8.0.tgz#fea68e4f21c1bf18020560fd5728b15fe44f0976" - integrity sha512-H9dI7dCw005XuGa1dPAdZLQWEUu+B4yiF2v7NZ3p70mKo2iAZcd9LwmDTZ5OFALsNiHnJk1I5JZjcsj8dtB73g== + version "7.8.1" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.8.1.tgz#29b473ef85273b6b28974f89f1ccd46329297bc3" + integrity sha512-jS1B1E7kQK8yrCM6SwwYFdtXTHb0/xLrF/kbHJoRnNQYKz2c1hwHMK35JKTTDiWTwpBMpkbzCR5Fj+6Up3yy0A== dependencies: "@microsoft/api-extractor-model" "7.8.0" "@microsoft/tsdoc" "0.12.19" "@rushstack/node-core-library" "3.19.7" - "@rushstack/ts-command-line" "4.3.14" + "@rushstack/ts-command-line" "4.4.0" colors "~1.2.1" lodash "~4.17.15" resolve "1.8.1" @@ -2691,11 +2691,25 @@ argparse "~1.0.9" colors "~1.2.1" +"@rushstack/ts-command-line@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-4.4.0.tgz#796f24681fdcbd01d463278c9e80a51ea5f73b2b" + integrity sha512-AYRICJg9Cwz+IBo1+leG0MtHx2uVScEs5P5ZNW3oocKekN6oLZvM1SNxghB7EXJzmYHnEMvCGhQx0Ll4oEkIyQ== + dependencies: + "@types/argparse" "1.0.38" + argparse "~1.0.9" + colors "~1.2.1" + "@types/argparse@1.0.33": version "1.0.33" resolved "https://registry.yarnpkg.com/@types/argparse/-/argparse-1.0.33.tgz#2728669427cdd74a99e53c9f457ca2866a37c52d" integrity sha512-VQgHxyPMTj3hIlq9SY1mctqx+Jj8kpQfoLvDlVSDNOyuYs8JYfkuY3OW/4+dO657yPmNhHpePRx0/Tje5ImNVQ== +"@types/argparse@1.0.38": + version "1.0.38" + resolved "https://registry.yarnpkg.com/@types/argparse/-/argparse-1.0.38.tgz#a81fd8606d481f873a3800c6ebae4f1d768a56a9" + integrity sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA== + "@types/babel__core@^7.1.0": version "7.1.4" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.4.tgz#5c5569cc40e5f2737dfc00692f5444e871e4a234" From a086d5bb4bdafb0f7e1ac33bb3a8deefa09de271 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 15 May 2020 12:43:39 -0700 Subject: [PATCH 114/209] Bump @types/yargs from 15.0.4 to 15.0.5 (#4907) Bumps [@types/yargs](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/yargs) from 15.0.4 to 15.0.5. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/yargs) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 8926c891647..ba11bd68764 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2958,9 +2958,9 @@ "@types/yargs-parser" "*" "@types/yargs@^15.0.0", "@types/yargs@^15.0.3": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.4.tgz#7e5d0f8ca25e9d5849f2ea443cf7c402decd8299" - integrity sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg== + version "15.0.5" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.5.tgz#947e9a6561483bdee9adffc983e91a6902af8b79" + integrity sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w== dependencies: "@types/yargs-parser" "*" From 146f22499cd48d381b113d7ec8427d4eacf1f8b0 Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Fri, 15 May 2020 13:27:27 -0700 Subject: [PATCH 115/209] Move playground-win32 to Microsoft.ReactNative (#4895) * Start converting playground win32 to MS.RN. * hook up dispatcher in playground * Change files * formatting * minor changes * Fix playground-win32 offline bundle loading * fix AttachBackHandlers * move isXamlIsland to helpers * Use proper headers for appmodel * formatting * Remove MSRN changes that will be submitted seperately * remove last MSRN change --- packages/playground/index.js | 1 + packages/playground/just-task.js | 8 + packages/playground/package.json | 1 + packages/playground/windows/.gitignore | 1 + .../playground/windows/playground-win32.sln | 76 ++--- .../playground-win32/Playground-Win32.cpp | 262 +++++++----------- .../playground-win32/Playground-win32.vcxproj | 39 ++- .../windows/playground-win32/packages.config | 1 + 8 files changed, 174 insertions(+), 215 deletions(-) create mode 100644 packages/playground/index.js diff --git a/packages/playground/index.js b/packages/playground/index.js new file mode 100644 index 00000000000..45a1db0b6b4 --- /dev/null +++ b/packages/playground/index.js @@ -0,0 +1 @@ +require('react-native-windows/RNTester'); diff --git a/packages/playground/just-task.js b/packages/playground/just-task.js index ad9f3c8a1b8..d82b4dd3b36 100644 --- a/packages/playground/just-task.js +++ b/packages/playground/just-task.js @@ -5,6 +5,7 @@ * @ts-check */ +const fs = require('fs'); const {task, series, eslintTask} = require('just-scripts'); task('eslint', () => { @@ -16,3 +17,10 @@ task('eslint:fix', () => { task('lint', series('eslint')); task('lint:fix', series('eslint:fix')); + +task('prepareBundleWin32', () => { + const file = 'windows/playground-win32/Bundle'; + if (!fs.existsSync(file)) { + fs.mkdirSync(file); + } +}); diff --git a/packages/playground/package.json b/packages/playground/package.json index 7011653d84c..8ab51da8f92 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -3,6 +3,7 @@ "version": "0.0.54", "private": true, "scripts": { + "bundle-win32":"just-scripts prepareBundleWin32 && npx react-native bundle --entry-file Samples\\rntester.tsx --bundle-output windows\\playground-win32\\Bundle\\Samples\\rntester.bundle --platform windows", "start": "react-native start", "lint:fix": "just-scripts lint:fix", "lint": "just-scripts lint", diff --git a/packages/playground/windows/.gitignore b/packages/playground/windows/.gitignore index 0925a804895..e8284b6d239 100644 --- a/packages/playground/windows/.gitignore +++ b/packages/playground/windows/.gitignore @@ -92,3 +92,4 @@ packages/ **/Generated Files/** playground/Bundle +playground-win32/Bundle diff --git a/packages/playground/windows/playground-win32.sln b/packages/playground/windows/playground-win32.sln index 705febd73f7..969d4742d16 100644 --- a/packages/playground/windows/playground-win32.sln +++ b/packages/playground/windows/playground-win32.sln @@ -7,11 +7,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Playground-Win32", "playgro EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Folly", "..\..\..\vnext\Folly\Folly.vcxproj", "{A990658C-CE31-4BCC-976F-0FC6B1AF693D}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactUWP", "..\..\..\vnext\ReactUWP\ReactUWP.vcxproj", "{2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}" - ProjectSection(ProjectDependencies) = postProject - {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactCommon", "..\..\..\vnext\ReactCommon\ReactCommon.vcxproj", "{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}" ProjectSection(ProjectDependencies) = postProject {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} @@ -22,37 +17,39 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactWindowsCore", "..\..\. {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PropertySheets", "PropertySheets", "{6F24927E-EE45-4DB2-91DA-DCC6E98B0C42}" - ProjectSection(SolutionItems) = preProject - ..\..\..\vnext\PropertySheets\ARM.props = ..\..\..\vnext\PropertySheets\ARM.props - ..\..\..\vnext\PropertySheets\Debug.props = ..\..\..\vnext\PropertySheets\Debug.props - ..\..\..\vnext\PropertySheets\React.Cpp.props = ..\..\..\vnext\PropertySheets\React.Cpp.props - ..\..\..\vnext\PropertySheets\Release.props = ..\..\..\vnext\PropertySheets\Release.props - ..\..\..\vnext\PropertySheets\Warnings.props = ..\..\..\vnext\PropertySheets\Warnings.props - ..\..\..\vnext\PropertySheets\Win32.props = ..\..\..\vnext\PropertySheets\Win32.props - ..\..\..\vnext\PropertySheets\x64.props = ..\..\..\vnext\PropertySheets\x64.props - ..\..\..\vnext\PropertySheets\x86.props = ..\..\..\vnext\PropertySheets\x86.props - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Chakra", "..\..\..\vnext\Chakra\Chakra.vcxitems", "{C38970C0-5FBF-4D69-90D8-CBAC225AE895}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative", "..\..\..\vnext\Microsoft.ReactNative\Microsoft.ReactNative.vcxproj", "{F7D32BD0-2749-483E-9A0D-1635EF7E3136}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Shared", "..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems", "{0CC28589-39E4-4288-B162-97B959F8B843}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Universal", "..\..\..\vnext\JSI\Universal\JSI.Universal.vcxproj", "{A62D504A-16B8-41D2-9F19-E2E86019E5E4}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", "..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems", "{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "..\..\..\vnext\Common\Common.vcxproj", "{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", "..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems", "{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReactNative", "ReactNative", "{5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Shared", "..\..\..\vnext\Shared\Shared.vcxitems", "{2049DBE9-8D13-42C9-AE4B-413AE38FFFD0}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso", "..\..\..\vnext\Mso\Mso.vcxitems", "{84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E}" EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 ..\..\..\vnext\ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4 - ..\..\..\vnext\Chakra\Chakra.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 - ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 - ..\..\..\vnext\Mso\Mso.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 - ..\..\..\vnext\Shared\Shared.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4 + ..\..\..\vnext\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 ..\..\..\vnext\Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{8b88ffae-4dbc-49a2-afa5-d2477d4ad189}*SharedItemsImports = 4 ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4 + ..\..\..\vnext\Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9 ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9 + ..\..\..\vnext\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 + ..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 + ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 + ..\..\..\vnext\Mso\Mso.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 + ..\..\..\vnext\Shared\Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -93,18 +90,6 @@ Global {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.Build.0 = Release|x64 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.ActiveCfg = Release|Win32 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.Build.0 = Release|Win32 - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Debug|ARM.ActiveCfg = Debug|ARM - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Debug|ARM.Build.0 = Debug|ARM - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Debug|x64.ActiveCfg = Debug|x64 - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Debug|x64.Build.0 = Debug|x64 - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Debug|x86.ActiveCfg = Debug|Win32 - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Debug|x86.Build.0 = Debug|Win32 - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Release|ARM.ActiveCfg = Release|ARM - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Release|ARM.Build.0 = Release|ARM - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Release|x64.ActiveCfg = Release|x64 - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Release|x64.Build.0 = Release|x64 - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Release|x86.ActiveCfg = Release|Win32 - {2D5D43D9-CFFC-4C40-B4CD-02EFB4E2742B}.Release|x86.Build.0 = Release|Win32 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.ActiveCfg = Debug|ARM {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.Build.0 = Debug|ARM {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.ActiveCfg = Debug|x64 @@ -129,6 +114,18 @@ Global {11C084A3-A57C-4296-A679-CAC17B603144}.Release|x64.Build.0 = Release|x64 {11C084A3-A57C-4296-A679-CAC17B603144}.Release|x86.ActiveCfg = Release|Win32 {11C084A3-A57C-4296-A679-CAC17B603144}.Release|x86.Build.0 = Release|Win32 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.ActiveCfg = Debug|ARM + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.Build.0 = Debug|ARM + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.ActiveCfg = Debug|x64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.Build.0 = Debug|x64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.ActiveCfg = Debug|Win32 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.Build.0 = Debug|Win32 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM.ActiveCfg = Release|ARM + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM.Build.0 = Release|ARM + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.ActiveCfg = Release|x64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.Build.0 = Release|x64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.ActiveCfg = Release|Win32 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.Build.0 = Release|Win32 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.ActiveCfg = Debug|ARM {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.Build.0 = Debug|ARM {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x64.ActiveCfg = Debug|x64 @@ -157,6 +154,19 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {11C084A3-A57C-4296-A679-CAC17B603144} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {C38970C0-5FBF-4D69-90D8-CBAC225AE895} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {0CC28589-39E4-4288-B162-97B959F8B843} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {A62D504A-16B8-41D2-9F19-E2E86019E5E4} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {2049DBE9-8D13-42C9-AE4B-413AE38FFFD0} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F5EAF3BA-6B6F-4E81-B5C6-49B30EC0A32E} EndGlobalSection diff --git a/packages/playground/windows/playground-win32/Playground-Win32.cpp b/packages/playground/windows/playground-win32/Playground-Win32.cpp index 04539cdf0dc..fa1dfc6f319 100644 --- a/packages/playground/windows/playground-win32/Playground-Win32.cpp +++ b/packages/playground/windows/playground-win32/Playground-Win32.cpp @@ -5,15 +5,6 @@ #include #include -#include -#include -#include -#include - -#include - -#include -#include #include #include @@ -21,72 +12,55 @@ #pragma push_macro("GetCurrentTime") #undef GetCurrentTime +#include + #include + +#include #include #include #pragma pop_macro("GetCurrentTime") -namespace { - -std::string GetAsyncLocalStorageDBPath() { - winrt::com_array localAppData; - winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, put_abi(localAppData))); - - std::filesystem::path asyncLocalStorageDBDir{localAppData.data()}; - asyncLocalStorageDBDir /= LR"(Microsoft\React Native Playground (Win32))"; - - if (!CreateDirectoryW(asyncLocalStorageDBDir.wstring().data(), nullptr)) { - if (::GetLastError() != ERROR_ALREADY_EXISTS) - winrt::throw_last_error(); - } - - auto asyncLocalStoragePath = asyncLocalStorageDBDir / L"AsyncStorage.sqlite3"; - return Microsoft::Common::Unicode::Utf16ToUtf8(asyncLocalStoragePath.wstring()); -} - -} // namespace - namespace WUX = winrt::Windows::UI::Xaml; namespace WUXC = WUX::Controls; namespace WUXH = WUX::Hosting; -struct PlaygroundNativeModuleProvider final : facebook::react::NativeModuleProvider { - virtual std::vector GetModules( - const std::shared_ptr &defaultQueueThread) override { - std::vector modules; - return modules; - } -}; +struct SimpleRedBoxHandler : winrt::implements { + SimpleRedBoxHandler() noexcept {} -class PlaygroundViewManagerProvider final : public react::uwp::ViewManagerProvider { - public: - virtual std::vector GetViewManagers( - const std::shared_ptr &instance) override { - std::vector viewManagers; + void ShowNewError( + winrt::Microsoft::ReactNative::IRedBoxErrorInfo const &info, + winrt::Microsoft::ReactNative::RedBoxErrorType type) noexcept { + OutputDebugStringA("----- Begin RedBox -----\n"); - return viewManagers; - } -}; + switch (type) { + case winrt::Microsoft::ReactNative::RedBoxErrorType::JavaScriptFatal: + OutputDebugStringA("Fatal Error: "); + break; + case winrt::Microsoft::ReactNative::RedBoxErrorType::JavaScriptSoft: + OutputDebugStringA("JavaScript Error: "); + break; + case winrt::Microsoft::ReactNative::RedBoxErrorType::Native: + OutputDebugStringA("Native Error: "); + break; + } -struct HwndReactInstanceCreator : ::react::uwp::IReactInstanceCreator { - HwndReactInstanceCreator(HWND hwnd) { - m_hwnd = hwnd; + OutputDebugString(info.Message().c_str()); + OutputDebugStringA("\n----- End RedBox -----\n"); } - void detach() { - m_hwnd = nullptr; + bool IsDevSupportEnabled() noexcept { + return true; } - std::shared_ptr<::react::uwp::IReactInstance> getInstance() override; - void markAsNeedsReload() override; - void persistUseWebDebugger(bool useWebDebugger) override; - void persistUseLiveReload(bool useLiveReload) override; - void persistUseDirectDebugger(bool useDirectDebugger) override; - void persistBreakOnNextLine(bool breakOnNextLine) override; + void UpdateError(winrt::Microsoft::ReactNative::IRedBoxErrorInfo const &info) noexcept { + // noop + } - private: - HWND m_hwnd; + void DismissRedBox() noexcept { + // noop + } }; struct WindowData { @@ -95,9 +69,12 @@ struct WindowData { std::wstring m_bundleFile; WUXH::DesktopWindowXamlSource m_desktopWindowXamlSource; - std::shared_ptr m_instance; - std::shared_ptr m_rootView; - std::shared_ptr m_instanceCreator; + + winrt::Microsoft::ReactNative::ReactRootView m_reactRootView; + winrt::Microsoft::ReactNative::ReactNativeHost m_host; + winrt::Microsoft::ReactNative::ReactInstanceSettings m_instanceSettings; + winrt::Windows::Foundation::Collections::IVector + m_packageProviders; bool m_useWebDebugger{true}; bool m_liveReloadEnabled{true}; @@ -106,8 +83,6 @@ struct WindowData { bool m_breakOnNextLine{false}; uint16_t m_debuggerPort{defaultDebuggerPort}; - react::uwp::JSIEngine m_jsEngine{react::uwp::JSIEngine::Chakra}; - WindowData(const WUXH::DesktopWindowXamlSource &desktopWindowXamlSource) : m_desktopWindowXamlSource(desktopWindowXamlSource) {} @@ -115,54 +90,69 @@ struct WindowData { return reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); } - LRESULT OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT) { - switch (id) { - case IDM_OPENJSFILE: { - DialogBox(s_instance, MAKEINTRESOURCE(IDD_OPENJSBUNDLEBOX), hwnd, &Bundle); - - if (!m_bundleFile.empty()) { - facebook::react::InitializeLogging( - [](facebook::react::RCTLogLevel logLevel, const char *message) { OutputDebugStringA(message); }); - - // Create NativeModuleProvider - std::shared_ptr moduleLoader = - std::make_shared(); - std::shared_ptr viewManagerProvider = - std::make_shared(); - - m_instance = react::uwp::CreateReactInstance(moduleLoader, viewManagerProvider); - - react::uwp::ReactInstanceSettings settings; - settings.UseWebDebugger = m_useWebDebugger; - settings.UseLiveReload = m_liveReloadEnabled; - settings.DebuggerBreakOnNextLine = m_breakOnNextLine; - settings.UseDirectDebugger = m_useDirectDebugger; - settings.DebuggerPort = m_debuggerPort; - settings.jsiEngine = m_jsEngine; + winrt::Microsoft::ReactNative::ReactNativeHost Host() noexcept { + if (!m_host) { + m_host = winrt::Microsoft::ReactNative::ReactNativeHost(); + m_host.InstanceSettings(InstanceSettings()); + m_host.PackageProviders(PackageProviders()); + } - settings.EnableDeveloperMenu = true; + return m_host; + } + winrt::Microsoft::ReactNative::ReactInstanceSettings InstanceSettings() noexcept { + if (!m_instanceSettings) { + m_instanceSettings = winrt::Microsoft::ReactNative::ReactInstanceSettings(); + } - settings.LoggingCallback = [](facebook::react::RCTLogLevel logLevel, const char *message) { - OutputDebugStringA("In LoggingCallback"); - OutputDebugStringA(message); - }; + return m_instanceSettings; + } - m_instance->Start(m_instance, settings); - m_instance->loadBundle(Microsoft::Common::Unicode::Utf16ToUtf8(m_bundleFile)); + winrt::Windows::Foundation::Collections::IVector + PackageProviders() noexcept { + if (!m_packageProviders) { + m_packageProviders = winrt::single_threaded_vector(); + } - folly::dynamic initialProps = folly::dynamic::object(); + return m_packageProviders; + } - // Retrieve ABI pointer from C++/CX pointer - auto rootElement = m_desktopWindowXamlSource.Content().as(); + LRESULT OnCommand(HWND hwnd, int id, HWND /* hwndCtl*/, UINT) { + switch (id) { + case IDM_OPENJSFILE: { + DialogBox(s_instance, MAKEINTRESOURCE(IDD_OPENJSBUNDLEBOX), hwnd, &Bundle); + if (!m_bundleFile.empty()) { PCWSTR appName = (m_bundleFile == LR"(Samples\rntester)") ? L"RNTesterApp" : L"Bootstrap"; - // Create the root view - m_rootView = react::uwp::CreateReactRootView(rootElement, appName, m_instanceCreator); + WCHAR workingDir[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, workingDir); + + auto host = Host(); + host.InstanceSettings().JavaScriptBundleFile(m_bundleFile); + host.InstanceSettings().MainComponentName(appName); + host.InstanceSettings().UseWebDebugger(m_useWebDebugger); + host.InstanceSettings().UseDirectDebugger(m_useDirectDebugger); + host.InstanceSettings().BundleRootPath( + std::wstring(L"file:").append(workingDir).append(L"\\Bundle\\").c_str()); + host.InstanceSettings().DebuggerBreakOnNextLine(m_breakOnNextLine); + host.InstanceSettings().UseFastRefresh(m_liveReloadEnabled); + host.InstanceSettings().DebuggerPort(m_debuggerPort); + host.InstanceSettings().RedBoxHandler(winrt::make()); + host.InstanceSettings().Properties().Set( + winrt::Microsoft::ReactNative::ReactDispatcherHelper::UIDispatcherProperty(), + winrt::Microsoft::ReactNative::ReactDispatcherHelper::UIThreadDispatcher()); + + // Nudge the ReactNativeHost to create the instance and wrapping context + host.ReloadInstance(); + + m_reactRootView = winrt::Microsoft::ReactNative::ReactRootView(); + m_reactRootView.ComponentName(host.InstanceSettings().MainComponentName()); + m_reactRootView.ReactNativeHost(host); - m_rootView->SetInitialProps(std::move(initialProps)); - m_rootView->SetInstanceCreator(m_instanceCreator); - m_rootView->AttachRoot(); + // Retrieve ABI pointer from C++/CX pointer + auto rootElement = m_desktopWindowXamlSource.Content().as(); + rootElement.Children().Clear(); + rootElement.Children().Append(m_reactRootView); } break; @@ -193,16 +183,10 @@ struct WindowData { SetWindowPos(hWndXamlIsland, nullptr, 0, 0, createStruct->cx, createStruct->cy, SWP_SHOWWINDOW); - try { - m_instanceCreator = std::make_shared(hwnd); - } catch (...) { - return -1; - } - return 0; } - LRESULT OnWindowPosChanged(HWND hwnd, const WINDOWPOS *windowPosition) { + LRESULT OnWindowPosChanged(HWND /* hwnd */, const WINDOWPOS *windowPosition) { auto interop = m_desktopWindowXamlSource.as(); HWND interopHwnd; winrt::check_hresult(interop->get_WindowHandle(&interopHwnd)); @@ -213,7 +197,7 @@ struct WindowData { } /// Message handler for about box. - static INT_PTR CALLBACK About(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) noexcept { + static INT_PTR CALLBACK About(HWND hwnd, UINT message, WPARAM wparam, LPARAM /* lparam */) noexcept { switch (message) { case WM_INITDIALOG: return TRUE; @@ -242,7 +226,7 @@ struct WindowData { LR"(Samples\view)", }; - static INT_PTR CALLBACK Bundle(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) noexcept { + static INT_PTR CALLBACK Bundle(HWND hwnd, UINT message, WPARAM wparam, LPARAM /*lparam*/) noexcept { switch (message) { case WM_INITDIALOG: { HWND hwndListBox = GetDlgItem(hwnd, IDC_JSBUNDLELIST); @@ -291,7 +275,7 @@ struct WindowData { SendMessageW(cmbEngines, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)TEXT("Chakra")); SendMessageW(cmbEngines, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)TEXT("Hermes")); SendMessageW(cmbEngines, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)TEXT("V8")); - SendMessageW(cmbEngines, CB_SETCURSEL, (WPARAM) static_cast(self->m_jsEngine), (LPARAM)0); + // SendMessageW(cmbEngines, CB_SETCURSEL, (WPARAM) static_cast(self->m_jsEngine), (LPARAM)0); return TRUE; } @@ -313,7 +297,7 @@ struct WindowData { auto port = std::stoi(buffer); if (port > UINT16_MAX) port = defaultDebuggerPort; - self->m_debuggerPort = port; + self->m_debuggerPort = static_cast(port); } catch (const std::out_of_range &) { self->m_debuggerPort = defaultDebuggerPort; } catch (const std::invalid_argument &) { @@ -321,9 +305,9 @@ struct WindowData { // (E.g. includes letters or symbols). } - auto cmbEngines = GetDlgItem(hwnd, IDC_JSENGINE); - int itemIndex = (int)SendMessageW(cmbEngines, (UINT)CB_GETCURSEL, (WPARAM)0, (LPARAM)0); - self->m_jsEngine = static_cast(itemIndex); + // auto cmbEngines = GetDlgItem(hwnd, IDC_JSENGINE); + // int itemIndex = (int)SendMessageW(cmbEngines, (UINT)CB_GETCURSEL, (WPARAM)0, (LPARAM)0); + // self->m_jsEngine = static_cast(itemIndex); } [[fallthrough]]; case IDCANCEL: @@ -341,50 +325,6 @@ struct WindowData { extern "C" IMAGE_DOS_HEADER __ImageBase; HINSTANCE WindowData::s_instance = reinterpret_cast(&__ImageBase); -std::shared_ptr<::react::uwp::IReactInstance> HwndReactInstanceCreator::getInstance() { - if (!m_hwnd) - return nullptr; - - return WindowData::GetFromWindow(m_hwnd)->m_instance; -} - -void HwndReactInstanceCreator::markAsNeedsReload() { - if (!m_hwnd) - return; - - auto instance = WindowData::GetFromWindow(m_hwnd)->m_instance; - if (instance) - instance->SetAsNeedsReload(); -} - -void HwndReactInstanceCreator::persistUseWebDebugger(bool useWebDebugger) { - if (!m_hwnd) - return; - - WindowData::GetFromWindow(m_hwnd)->m_useWebDebugger = useWebDebugger; -} - -void HwndReactInstanceCreator::persistUseLiveReload(bool useLiveReload) { - if (!m_hwnd) - return; - - WindowData::GetFromWindow(m_hwnd)->m_liveReloadEnabled = useLiveReload; -} - -void HwndReactInstanceCreator::persistUseDirectDebugger(bool useDirectDebugger) { - if (!m_hwnd) - return; - - WindowData::GetFromWindow(m_hwnd)->m_useDirectDebugger = useDirectDebugger; -} - -void HwndReactInstanceCreator::persistBreakOnNextLine(bool breakOnNextLine) { - if (!m_hwnd) - return; - - WindowData::GetFromWindow(m_hwnd)->m_breakOnNextLine = breakOnNextLine; -} - LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) noexcept { switch (message) { case WM_CREATE: { @@ -415,14 +355,12 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) return DefWindowProc(hwnd, message, wparam, lparam); } -_Use_decl_annotations_ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE, PSTR commandLine, int showCmd) { +_Use_decl_annotations_ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE, PSTR /* commandLine */, int showCmd) { constexpr PCWSTR appName = L"React Native Playground (Win32)"; constexpr PCWSTR windowClassName = L"MS_REACTNATIVE_PLAYGROUND_WIN32"; winrt::init_apartment(winrt::apartment_type::single_threaded); - react::windows::SetAsyncStorageDBPath(GetAsyncLocalStorageDBPath()); - WUXH::DesktopWindowXamlSource desktopXamlSource; WNDCLASSEXW wcex = {}; diff --git a/packages/playground/windows/playground-win32/Playground-win32.vcxproj b/packages/playground/windows/playground-win32/Playground-win32.vcxproj index 19af51184fe..60bb691b19c 100644 --- a/packages/playground/windows/playground-win32/Playground-win32.vcxproj +++ b/packages/playground/windows/playground-win32/Playground-win32.vcxproj @@ -1,5 +1,6 @@ + {8B88FFAE-4DBC-49A2-AFA5-D2477D4AD189} Playground @@ -10,9 +11,6 @@ false - - - Debug @@ -42,6 +40,7 @@ Application Unicode + v142 true @@ -51,7 +50,6 @@ true - @@ -68,34 +66,30 @@ - StdCall - true Use pch.h - true + $(IntDir)pch.pch Level3 + true + %(AdditionalOptions) /bigobj + 4453;28204 - shell32.lib;user32.lib;windowsapp.lib;$(ReactNativeWindowsDir)target\$(PlatformTarget)\$(Configuration)\ReactUWP\React.uwp.lib;%(AdditionalDependenices) + shell32.lib;user32.lib;windowsapp.lib;%(AdditionalDependenices) Windows true - Disabled + _DEBUG;%(PreprocessorDefinitions) + stdcpp17 - Size - true - Full + NDEBUG;%(PreprocessorDefinitions) - - true - true - @@ -116,20 +110,23 @@ - - {2d5d43d9-cffc-4c40-b4cd-02efb4e2742b} - + - + + {f7d32bd0-2749-483e-9a0d-1635ef7e3136} + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\AppxPackage\Microsoft.AppXPackage.Targets resources.pri + @@ -138,6 +135,8 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + diff --git a/packages/playground/windows/playground-win32/packages.config b/packages/playground/windows/playground-win32/packages.config index 3a066bd4eff..05122f9e4af 100644 --- a/packages/playground/windows/playground-win32/packages.config +++ b/packages/playground/windows/playground-win32/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file From ac172971e7f7ba15f90df6c5f0da163067809b76 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 15 May 2020 14:15:28 -0700 Subject: [PATCH 116/209] Bump @types/es6-collections from 0.5.31 to 0.5.32 (#4917) Bumps [@types/es6-collections](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/es6-collections) from 0.5.31 to 0.5.32. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/es6-collections) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ba11bd68764..b222031b08e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2761,9 +2761,9 @@ integrity sha512-bPYT5ECFiblzsVzyURaNhljBH2Gh1t9LowgUwciMrNAhFewLkHT2H0Mto07Y4/3KCOGZHRQll3CTtQZ0X11D/A== "@types/es6-collections@^0.5.29": - version "0.5.31" - resolved "https://registry.yarnpkg.com/@types/es6-collections/-/es6-collections-0.5.31.tgz#faad21c930cd0ea7f71f51b9e5b555796c5ab23f" - integrity sha512-djEvbdTH5Uw7V0WqdMQLG4NK3+iu/FMZy/ylyhWEFnW5xOsXEWpivo/dhP+cR43Az+ipytza7dTSnpsWCxKYAw== + version "0.5.32" + resolved "https://registry.yarnpkg.com/@types/es6-collections/-/es6-collections-0.5.32.tgz#62edb3942849951b6025d42af9da97d7b837f31b" + integrity sha512-aOOGt8ivRTqSWDzrHoNorP/o/YXgVK0oA7SP3jke3W4zZDSFAbWhYWjPG0qnGq6B/QOsx76FnmC3bUFSvleOLA== "@types/es6-promise@0.0.32": version "0.0.32" From 2dc0f3337e6d762a84c990ff40f3a76db6392599 Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Sat, 16 May 2020 00:04:28 +0000 Subject: [PATCH 117/209] applying package updates ***NO_CI*** --- ...tive-windows-2020-05-14-13-47-03-4881.json | 8 ------- ...indows-2020-05-15-03-01-54-justMyXaml.json | 8 ------- packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 4 ++-- vnext/CHANGELOG.json | 21 +++++++++++++++++++ vnext/CHANGELOG.md | 11 +++++++++- vnext/package.json | 2 +- 8 files changed, 36 insertions(+), 22 deletions(-) delete mode 100644 change/react-native-windows-2020-05-14-13-47-03-4881.json delete mode 100644 change/react-native-windows-2020-05-15-03-01-54-justMyXaml.json diff --git a/change/react-native-windows-2020-05-14-13-47-03-4881.json b/change/react-native-windows-2020-05-14-13-47-03-4881.json deleted file mode 100644 index d5100c76cab..00000000000 --- a/change/react-native-windows-2020-05-14-13-47-03-4881.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "some projects have target instead of bin folders", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-14T20:47:03.172Z" -} diff --git a/change/react-native-windows-2020-05-15-03-01-54-justMyXaml.json b/change/react-native-windows-2020-05-15-03-01-54-justMyXaml.json deleted file mode 100644 index 682d8990a03..00000000000 --- a/change/react-native-windows-2020-05-15-03-01-54-justMyXaml.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": ".\\JustMyXaml.ps1", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-15T10:01:54.898Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index b0e0e478ff0..055ddd31458 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.67" + "react-native-windows": "0.0.0-master.68" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 1b8b9b1253a..4103ed80df3 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.67" + "react-native-windows": "0.0.0-master.68" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index 8ab51da8f92..48a0e608b99 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -3,7 +3,7 @@ "version": "0.0.54", "private": true, "scripts": { - "bundle-win32":"just-scripts prepareBundleWin32 && npx react-native bundle --entry-file Samples\\rntester.tsx --bundle-output windows\\playground-win32\\Bundle\\Samples\\rntester.bundle --platform windows", + "bundle-win32": "just-scripts prepareBundleWin32 && npx react-native bundle --entry-file Samples\\rntester.tsx --bundle-output windows\\playground-win32\\Bundle\\Samples\\rntester.bundle --platform windows", "start": "react-native start", "lint:fix": "just-scripts lint:fix", "lint": "just-scripts lint", @@ -12,7 +12,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.67" + "react-native-windows": "0.0.0-master.68" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index aefa45cb287..b5d4d3c66c1 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,27 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Sat, 16 May 2020 00:04:28 GMT", + "tag": "react-native-windows_v0.0.0-master.68", + "version": "0.0.0-master.68", + "comments": { + "prerelease": [ + { + "comment": "some projects have target instead of bin folders", + "author": "asklar@microsoft.com", + "commit": "e0f591e8aaca01c7a52ac2825d8476920880bfed", + "package": "react-native-windows" + }, + { + "comment": ".\\JustMyXaml.ps1", + "author": "asklar@microsoft.com", + "commit": "2d85b6a94f1a9e629c2e124f4f0951ff75829bad", + "package": "react-native-windows" + } + ] + } + }, { "date": "Fri, 15 May 2020 00:04:44 GMT", "tag": "react-native-windows_v0.0.0-master.67", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index c4fbc42fed7..0562d0e3499 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,18 @@ # Change Log - react-native-windows -This log was last generated on Fri, 15 May 2020 00:04:44 GMT and should not be manually modified. +This log was last generated on Sat, 16 May 2020 00:04:28 GMT and should not be manually modified. +## 0.0.0-master.68 + +Sat, 16 May 2020 00:04:28 GMT + +### Changes + +- some projects have target instead of bin folders (asklar@microsoft.com) +- .\JustMyXaml.ps1 (asklar@microsoft.com) + ## 0.0.0-master.67 Fri, 15 May 2020 00:04:44 GMT diff --git a/vnext/package.json b/vnext/package.json index 565fb80ff1d..d287e7698af 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.67", + "version": "0.0.0-master.68", "license": "MIT", "repository": { "type": "git", From ce937eb0cef0812aa0b79d7017c7ae53fb566961 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Fri, 15 May 2020 17:32:46 -0700 Subject: [PATCH 118/209] Prevent hard crash on invalid jsx (button inside text e.g.) (#4921) * Prevent hard crash on invalid jsx (button inside text e.g.) * Change files --- ...-windows-2020-05-15-14-54-00-jsxCrash.json | 8 ++++++++ vnext/ReactUWP/Views/ViewViewManager.cpp | 14 ++++++++++++-- .../Modules/UIManagerModule.cpp | 19 ++++++++++++++----- 3 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 change/react-native-windows-2020-05-15-14-54-00-jsxCrash.json diff --git a/change/react-native-windows-2020-05-15-14-54-00-jsxCrash.json b/change/react-native-windows-2020-05-15-14-54-00-jsxCrash.json new file mode 100644 index 00000000000..9d5cd2732b6 --- /dev/null +++ b/change/react-native-windows-2020-05-15-14-54-00-jsxCrash.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Prevent hard crash on invalid jsx (button inside text e.g.)", + "packageName": "react-native-windows", + "email": "asklar@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-15T21:54:00.551Z" +} diff --git a/vnext/ReactUWP/Views/ViewViewManager.cpp b/vnext/ReactUWP/Views/ViewViewManager.cpp index 74b4efe12a8..75ea13efeed 100644 --- a/vnext/ReactUWP/Views/ViewViewManager.cpp +++ b/vnext/ReactUWP/Views/ViewViewManager.cpp @@ -16,7 +16,9 @@ #include #include +#include #include +#include #if defined(_DEBUG) // Currently only used for tagging controls in debug @@ -99,8 +101,16 @@ class ViewShadowNode : public ShadowNodeBase { } void AddView(ShadowNode &child, int64_t index) override { - GetViewPanel().InsertAt( - static_cast(index), static_cast(child).GetView().as()); + const auto &view = static_cast(child).GetView(); + if (view.try_as() == nullptr) { + const auto &ii = view.as(); + auto name = winrt::get_class_name(ii); + YellowBox( + std::string("ViewViewManager::AddView expected a UIElement but got a ") + + Microsoft::Common::Unicode::Utf16ToUtf8(name.c_str())); + } + + GetViewPanel().InsertAt(static_cast(index), view.as()); } void RemoveChildAt(int64_t indexToRemove) override { diff --git a/vnext/ReactWindowsCore/Modules/UIManagerModule.cpp b/vnext/ReactWindowsCore/Modules/UIManagerModule.cpp index 7d72ac8d25a..73e597bb3e0 100644 --- a/vnext/ReactWindowsCore/Modules/UIManagerModule.cpp +++ b/vnext/ReactWindowsCore/Modules/UIManagerModule.cpp @@ -14,6 +14,8 @@ using namespace std; #include "UIManagerModule.h" #include +#include +#include using namespace folly; using namespace facebook::xplat; @@ -271,11 +273,18 @@ void UIManager::setChildren(int64_t viewTag, folly::dynamic &&childrenTags) { auto &childNode = m_nodeRegistry.getNode(tag); childNode.m_parent = parent.m_tag; parent.m_children.push_back(tag); - if (!parent.m_zombie) - parent.AddView(childNode, index); - - m_nativeUIManager->AddView(parent, childNode, index); - + try { + if (!parent.m_zombie) + parent.AddView(childNode, index); + + m_nativeUIManager->AddView(parent, childNode, index); + } catch (const winrt::hresult_error &e) { + if (e.code() == E_NOINTERFACE) { + DEBUG_HRESULT_ERROR(e); + } else { + throw; + } + } ++index; } } From f5deff463294dca8cfe76ec1737a642680b3b1b3 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Fri, 15 May 2020 20:15:53 -0700 Subject: [PATCH 119/209] E2ETest - use TreeDumpLibrary from nuget (#4912) * start lifting TDL * Move to using TreeDumpLibrary nuget package --- packages/E2ETest/windows/ReactUWPTestApp.sln | 18 - .../ReactPackageProvider.cs | 0 .../ReactUWPTestApp/ReactUWPTestApp.csproj | 13 +- .../TreeDumpControlViewManager.cs | 99 ++++- .../DefaultVisualTreeLogger.cs | 44 --- .../IPropertyValueTranslator.cs | 10 - .../TreeDumpLibrary/IVisualTreeLogger.cs | 17 - .../TreeDumpLibrary/JsonVisualTreeLogger.cs | 53 --- .../windows/TreeDumpLibrary/TreeDumpHelper.cs | 249 ------------- .../TreeDumpLibrary/TreeDumpLibrary.csproj | 148 -------- .../TreeDumpLibrary/VisualTreeDumper.cs | 339 ------------------ 11 files changed, 103 insertions(+), 887 deletions(-) rename packages/E2ETest/windows/{TreeDumpLibrary => ReactUWPTestApp}/ReactPackageProvider.cs (100%) rename packages/E2ETest/windows/{TreeDumpLibrary => ReactUWPTestApp}/TreeDumpControlViewManager.cs (71%) delete mode 100644 packages/E2ETest/windows/TreeDumpLibrary/DefaultVisualTreeLogger.cs delete mode 100644 packages/E2ETest/windows/TreeDumpLibrary/IPropertyValueTranslator.cs delete mode 100644 packages/E2ETest/windows/TreeDumpLibrary/IVisualTreeLogger.cs delete mode 100644 packages/E2ETest/windows/TreeDumpLibrary/JsonVisualTreeLogger.cs delete mode 100644 packages/E2ETest/windows/TreeDumpLibrary/TreeDumpHelper.cs delete mode 100644 packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj delete mode 100644 packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs diff --git a/packages/E2ETest/windows/ReactUWPTestApp.sln b/packages/E2ETest/windows/ReactUWPTestApp.sln index d632b950855..d9a745fa941 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp.sln +++ b/packages/E2ETest/windows/ReactUWPTestApp.sln @@ -37,8 +37,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReactNative", "ReactNative" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative", "..\..\..\vnext\Microsoft.ReactNative\Microsoft.ReactNative.vcxproj", "{F7D32BD0-2749-483E-9A0D-1635EF7E3136}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TreeDumpLibrary", "TreeDumpLibrary\TreeDumpLibrary.csproj", "{C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ReactNative.Managed", "..\..\..\vnext\Microsoft.ReactNative.Managed\Microsoft.ReactNative.Managed.csproj", "{F2824844-CE15-4242-9420-308923CD76C3}" EndProject Global @@ -182,22 +180,6 @@ Global {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.Build.0 = Release|x64 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.ActiveCfg = Release|Win32 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.Build.0 = Release|Win32 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Debug|ARM.ActiveCfg = Debug|ARM - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Debug|ARM.Build.0 = Debug|ARM - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Debug|ARM64.Build.0 = Debug|ARM64 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Debug|x64.ActiveCfg = Debug|x64 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Debug|x64.Build.0 = Debug|x64 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Debug|x86.ActiveCfg = Debug|x86 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Debug|x86.Build.0 = Debug|x86 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Release|ARM.ActiveCfg = Release|ARM - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Release|ARM.Build.0 = Release|ARM - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Release|ARM64.ActiveCfg = Release|ARM64 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Release|ARM64.Build.0 = Release|ARM64 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Release|x64.ActiveCfg = Release|x64 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Release|x64.Build.0 = Release|x64 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Release|x86.ActiveCfg = Release|x86 - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C}.Release|x86.Build.0 = Release|x86 {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.ActiveCfg = Debug|ARM {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.Build.0 = Debug|ARM {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.ActiveCfg = Debug|ARM64 diff --git a/packages/E2ETest/windows/TreeDumpLibrary/ReactPackageProvider.cs b/packages/E2ETest/windows/ReactUWPTestApp/ReactPackageProvider.cs similarity index 100% rename from packages/E2ETest/windows/TreeDumpLibrary/ReactPackageProvider.cs rename to packages/E2ETest/windows/ReactUWPTestApp/ReactPackageProvider.cs diff --git a/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj b/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj index 5ffa2dda86c..1d5fdca7e4b 100644 --- a/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj +++ b/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj @@ -1,6 +1,5 @@  - + Debug @@ -22,6 +21,7 @@ ReactUWPTestApp_TemporaryKey.pfx True false + ..\packages true @@ -125,6 +125,8 @@ App.xaml + + @@ -156,6 +158,9 @@ 2.3.191129002 + + 1.0.3 + @@ -169,10 +174,6 @@ {F2824844-CE15-4242-9420-308923CD76C3} Microsoft.ReactNative.Managed - - {c0a6bd9c-3ee5-4b12-8ce4-cee95178539c} - TreeDumpLibrary - 16.0 diff --git a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpControlViewManager.cs b/packages/E2ETest/windows/ReactUWPTestApp/TreeDumpControlViewManager.cs similarity index 71% rename from packages/E2ETest/windows/TreeDumpLibrary/TreeDumpControlViewManager.cs rename to packages/E2ETest/windows/ReactUWPTestApp/TreeDumpControlViewManager.cs index fea206cd49f..fff0cb61c74 100644 --- a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpControlViewManager.cs +++ b/packages/E2ETest/windows/ReactUWPTestApp/TreeDumpControlViewManager.cs @@ -5,8 +5,13 @@ using Microsoft.ReactNative.Managed; using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Text.RegularExpressions; using System.Threading.Tasks; +using Windows.ApplicationModel.ConversationalAgent; using Windows.ApplicationModel.DataTransfer; +using Windows.Data.Json; +using Windows.Foundation; using Windows.Storage; using Windows.UI.ViewManagement; using Windows.UI.Xaml; @@ -87,6 +92,41 @@ public void UpdateProperties(FrameworkElement view, IJSValueReader propertyMapRe { "additionalProperties", ViewManagerPropertyType.Array } }; + + private static string GetOutputFile(string dumpID) + { + return "TreeDump\\" + dumpID + ".json"; + } + + private static string GetMasterFile(string dumpID) + { + return "TreeDump\\masters\\" + dumpID + ".json"; + } + + public async static Task DoesTreeDumpMatchForRNTester(DependencyObject root) + { + string json = VisualTreeDumper.DumpTree(root, null, new string[] { }, DumpTreeMode.Json); + try + { + var obj = JsonValue.Parse(json).GetObject(); + var element = VisualTreeDumper.FindElementByAutomationId(obj, "PageHeader"); + if (element == null) + { + return false; + } + var value = element.GetNamedString("Text"); + var pageName = new Regex(@"[<|>]").Replace(value, ""); + var match = await MatchDump(json, GetMasterFile(pageName), GetOutputFile(pageName)); + return match; + } + catch + { + Debug.WriteLine("JSON ERROR:\n" + json); + throw; + } + } + + public void SetDumpID(TextBlock view, string value) { m_dumpID = value; @@ -118,17 +158,70 @@ public void SetAdditionalProperties(IReadOnlyList additionalProperties) } } + public static async Task MatchDump(string outputJson, string masterFileRelativePath, string outputFileRelativePath) + { + Debug.WriteLine($"master file = {Windows.ApplicationModel.Package.Current.InstalledLocation.Path}\\Assets\\{masterFileRelativePath}"); + StorageFolder storageFolder = ApplicationData.Current.LocalFolder; + Debug.WriteLine($"output file = {storageFolder.Path + "\\" + outputFileRelativePath}"); + + StorageFile outFile = await storageFolder.CreateFileAsync(outputFileRelativePath, CreationCollisionOption.ReplaceExisting); + await FileIO.WriteTextAsync(outFile, outputJson); + + StorageFile masterFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync($@"Assets\{masterFileRelativePath}"); + + string masterJson = await FileIO.ReadTextAsync(masterFile); + + if (!TreeDumpHelper.DumpsAreEqual(masterJson, outputJson)) + { + return false; + } + else + { + return true; + } + } + + internal static async Task MatchTreeDumpFromLayoutUpdateAsync(string dumpID, string uiaId, TextBlock textBlock, IList additionalProperties, DumpTreeMode mode, string dumpExpectedText) + { + // First find root + DependencyObject current = textBlock; + DependencyObject parent = VisualTreeHelper.GetParent(current); + while (parent != null) + { + current = parent; + parent = VisualTreeHelper.GetParent(current); + } + + DependencyObject dumpRoot = current; + // if UIAID is passed in from test, find the matching child as the root to dump + if (uiaId != null) + { + var matchingNode = TreeDumpHelper.FindChildWithMatchingUIAID(current, uiaId); + if (matchingNode != null) + { + dumpRoot = matchingNode; + } + } + + string dumpText = VisualTreeDumper.DumpTree(dumpRoot, textBlock, additionalProperties, mode); + if (dumpText != dumpExpectedText) + { + return await MatchDump(dumpText, GetMasterFile(dumpID), GetOutputFile(dumpID)); + } + return true; + } + private async void dispatcherTimer_Tick(object sender, object e) { m_timer.Stop(); if (VisualTreeHelper.GetParent(m_textBlock) != null) { - var matchSuccessful = await TreeDumpHelper.MatchTreeDumpFromLayoutUpdateAsync(m_dumpID, m_uiaID, m_textBlock, m_additionalProperties, DumpTreeMode.Json, m_dumpExpectedText); + var matchSuccessful = await MatchTreeDumpFromLayoutUpdateAsync(m_dumpID, m_uiaID, m_textBlock, m_additionalProperties, DumpTreeMode.Json, m_dumpExpectedText); if (!matchSuccessful) { StorageFolder storageFolder = ApplicationData.Current.LocalFolder; - StorageFile outFile = await storageFolder.GetFileAsync(TreeDumpHelper.GetOutputFile(m_dumpID)); - StorageFile masterFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync($@"Assets\{TreeDumpHelper.GetMasterFile(m_dumpID)}"); + StorageFile outFile = await storageFolder.GetFileAsync(GetOutputFile(m_dumpID)); + StorageFile masterFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync($@"Assets\{GetMasterFile(m_dumpID)}"); UpdateResult(false /*matchDump*/ , $"Tree dump file does not match master at {masterFile.Path} - See output at {outFile.Path}", diff --git a/packages/E2ETest/windows/TreeDumpLibrary/DefaultVisualTreeLogger.cs b/packages/E2ETest/windows/TreeDumpLibrary/DefaultVisualTreeLogger.cs deleted file mode 100644 index ab558d3f0ee..00000000000 --- a/packages/E2ETest/windows/TreeDumpLibrary/DefaultVisualTreeLogger.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Text; -using Windows.UI.Xaml; - -namespace TreeDumpLibrary -{ - public sealed class DefaultVisualTreeLogger : IVisualTreeLogger - { - public void BeginNode(int indent, string nodeName, DependencyObject obj, bool hasProperties) - { - AppendLogger(indent, $"[{nodeName}]"); - } - - public void EndNode(int indent, string nodeName, DependencyObject obj, bool isLast) - { // no-op - } - - public void LogProperty(int indent, string propertyName, object propertyValue, bool isLast) - { - AppendLogger(indent, $"{propertyName}={propertyValue}"); - } - - public override string ToString() - { - return _logger.ToString(); - } - - private readonly StringBuilder _logger = new StringBuilder(); - private void AppendLogger(int indent, string s) - { - _logger.AppendLine(s.PadLeft(2 * indent + s.Length)); - } - - public void BeginArray(int indent, string propertyName) - { // no-op - } - - public void EndArray(int indent, string propertyName) - { - } - } -} diff --git a/packages/E2ETest/windows/TreeDumpLibrary/IPropertyValueTranslator.cs b/packages/E2ETest/windows/TreeDumpLibrary/IPropertyValueTranslator.cs deleted file mode 100644 index 5bcc26823f6..00000000000 --- a/packages/E2ETest/windows/TreeDumpLibrary/IPropertyValueTranslator.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace TreeDumpLibrary -{ - public interface IPropertyValueTranslator - { - string PropertyValueToString(string propertyName, object propertyObject); - } -} \ No newline at end of file diff --git a/packages/E2ETest/windows/TreeDumpLibrary/IVisualTreeLogger.cs b/packages/E2ETest/windows/TreeDumpLibrary/IVisualTreeLogger.cs deleted file mode 100644 index 4cddddc9cb2..00000000000 --- a/packages/E2ETest/windows/TreeDumpLibrary/IVisualTreeLogger.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Windows.UI.Xaml; - -namespace TreeDumpLibrary -{ - public interface IVisualTreeLogger - { - void BeginNode(int indent, string nodeName, DependencyObject obj, bool hasProperties); - void EndNode(int indent, string nodeName, DependencyObject obj, bool isLast); - void LogProperty(int indent, string propertyName, object propertyValue, bool isLast); - string ToString(); - void BeginArray(int indent, string propertyName); - void EndArray(int indent, string propertyName); - } -} diff --git a/packages/E2ETest/windows/TreeDumpLibrary/JsonVisualTreeLogger.cs b/packages/E2ETest/windows/TreeDumpLibrary/JsonVisualTreeLogger.cs deleted file mode 100644 index 7cf52ca97ab..00000000000 --- a/packages/E2ETest/windows/TreeDumpLibrary/JsonVisualTreeLogger.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Text; -using Windows.UI.Xaml; - -namespace TreeDumpLibrary -{ - public sealed class JsonVisualTreeLogger : IVisualTreeLogger - { - private readonly StringBuilder _logger = new StringBuilder(); - public void BeginArray(int indent, string propertyName) - { - AppendLogger(indent, $"\"{propertyName}\": ["); - } - - public void BeginNode(int indent, string nodeName, DependencyObject obj, bool hasProperties) - { - AppendLogger(indent, "{"); - LogProperty(indent + 2, "XamlType", JsonPropertyValueTranslator.Quote(nodeName), !hasProperties); - } - - public void EndArray(int indent, string propertyName) - { - AppendLogger(indent, "]"); - } - - public void EndNode(int indent, string nodeName, DependencyObject obj, bool isLast) - { - AppendLogger(indent, $"}}{GetDelimiter(isLast)}"); - } - - private string GetDelimiter(bool isLast) - { - return isLast ? "" : ","; - } - - public void LogProperty(int indent, string propertyName, object propertyValue, bool isLast) - { - AppendLogger(indent, $"\"{propertyName}\": {propertyValue}{GetDelimiter(isLast)}"); - } - - public override string ToString() - { - return _logger.ToString(); - } - - private void AppendLogger(int indent, string s) - { - _logger.AppendLine(s.PadLeft(2 * indent + s.Length)); - } - } -} diff --git a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpHelper.cs b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpHelper.cs deleted file mode 100644 index ec75dde5154..00000000000 --- a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpHelper.cs +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Windows.Data.Json; -using Windows.Storage; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Media; - -namespace TreeDumpLibrary -{ - public static class TreeDumpHelper - { - - private static DependencyObject FindChildWithMatchingUIAID(DependencyObject element, string uiaId) - { - string automationId = (string)element.GetValue(Windows.UI.Xaml.Automation.AutomationProperties.AutomationIdProperty); - if (automationId == uiaId) - { - return element; - } - int childrenCount = VisualTreeHelper.GetChildrenCount(element); - for (int i = 0; i < childrenCount; i++) - { - var result = FindChildWithMatchingUIAID(VisualTreeHelper.GetChild(element, i), uiaId); - if (result != null) - { - return result; - } - } - - return null; - } - - internal static async Task MatchTreeDumpFromLayoutUpdateAsync(string dumpID, string uiaId, TextBlock textBlock, IList additionalProperties, DumpTreeMode mode, string dumpExpectedText) - { - // First find root - DependencyObject current = textBlock; - DependencyObject parent = VisualTreeHelper.GetParent(current); - while (parent != null) - { - current = parent; - parent = VisualTreeHelper.GetParent(current); - } - - DependencyObject dumpRoot = current; - // if UIAID is passed in from test, find the matching child as the root to dump - if (uiaId != null) - { - var matchingNode = FindChildWithMatchingUIAID(current, uiaId); - if (matchingNode != null) - { - dumpRoot = matchingNode; - } - } - - string dumpText = VisualTreeDumper.DumpTree(dumpRoot, textBlock /* exclude */, additionalProperties, mode); - if (dumpText != dumpExpectedText) - { - return await MatchDump(dumpText, dumpID); - } - return true; - } - - - internal static async Task MatchDump(string outputJson, string dumpID) - { - Debug.WriteLine($"master file = {Windows.ApplicationModel.Package.Current.InstalledLocation.Path}\\Assets\\{GetMasterFile(dumpID)}"); - StorageFolder storageFolder = ApplicationData.Current.LocalFolder; - string fileName = GetOutputFile(dumpID); - Debug.WriteLine($"output file = {storageFolder.Path + "\\" + fileName}"); - - StorageFile outFile = await storageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); - await FileIO.WriteTextAsync(outFile, outputJson); - - StorageFile masterFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync($@"Assets\{GetMasterFile(dumpID)}"); - - string masterJson = await FileIO.ReadTextAsync(masterFile); - - if (!DumpsAreEqual(masterJson, outputJson)) - { - return false; - } - else - { - return true; - } - } - - public static bool DumpsAreEqual(string dumpExpectedText, string dumpText) - { - JsonValue expected = JsonValue.Parse(dumpExpectedText); - JsonValue actual = JsonValue.Parse(dumpText); - return JsonComparesEqual(expected, actual, "root"); - } - - static readonly double epsilon = 1.0; - - private static bool JsonComparesEqual(IJsonValue expected, IJsonValue actual, string keyName) - { - const string Anything = ""; - if (expected.ValueType == JsonValueType.String && Regex.Replace(expected.GetString(), @"\p{C}", "") == Anything) - { - Debug.WriteLine($"Skipping ignored value: {actual.ValueType} {actual}"); - return true; - } - //Debug.WriteLine($"keyname: {keyName} {expected.ValueType} {actual.ValueType}"); - if (expected.ValueType != actual.ValueType) - { - Debug.WriteLine($"Expected {expected} got {actual}"); - return false; - } - switch (expected.ValueType) - { - case JsonValueType.String: - if (expected.GetString() != actual.GetString()) - { - Debug.WriteLine($"string:Expected {expected.GetString()} got {actual.GetString()}"); - return false; - } - return true; - case JsonValueType.Number: - if (Math.Abs(expected.GetNumber() - actual.GetNumber()) > epsilon) - { - Debug.WriteLine($"number: {keyName} {expected.GetNumber()} {actual.GetNumber()}"); - return false; - } - return true; - case JsonValueType.Boolean: - return expected.GetBoolean() == actual.GetBoolean(); - case JsonValueType.Null: - return true; - case JsonValueType.Array: - { - var ea = expected.GetArray(); - var aa = actual.GetArray(); - if (!JsonCompareArray(ea, aa)) - { - Debug.WriteLine("in key " + keyName); - return false; - } - return true; - } - case JsonValueType.Object: - { - if (!JsonCompareObject(expected.GetObject(), actual.GetObject())) - { - Debug.WriteLine("in key " + keyName); - return false; - } - return true; - } - default: - throw new ArgumentException(); - } - } - - private static bool JsonCompareArray(JsonArray ea, JsonArray aa) - { - var efiltered = ea.Where(x => IsNonCollapsed(x)).ToArray(); - var afiltered = aa.Where(x => IsNonCollapsed(x)).ToArray(); - - if (efiltered.Length != afiltered.Length) - { - Debug.WriteLine($"Array count expected {ea.Count} got {aa.Count}"); - return false; - } - for (int i = 0; i < efiltered.Length; i++) - { - var _e = efiltered[i]; - var _a = afiltered[i]; - if (!JsonComparesEqual(_e, _a, "array element")) - { - Debug.WriteLine($"Array element {i} expected {_e.ValueType} got {_a.ValueType}"); - return false; - } - } - return true; - } - - private const string visibilityProperty = "Visibility"; - private const string visibilityPropertyVisible = "Visible"; - - private static bool IsNonCollapsed(IJsonValue x) - { - return x.ValueType != JsonValueType.Object || - !x.GetObject().ContainsKey(visibilityProperty) || - x.GetObject().GetNamedString(visibilityProperty) == visibilityPropertyVisible; - } - - private static bool JsonCompareObject(JsonObject eo, JsonObject ao) - { - var evisible = true; - if (eo.Keys.Contains(visibilityProperty)) - { - evisible = eo[visibilityProperty].GetString() == visibilityPropertyVisible; - eo.Remove(visibilityProperty); - } - var avisible = true; - if (ao.Keys.Contains(visibilityProperty)) - { - avisible = ao[visibilityProperty].GetString() == visibilityPropertyVisible; - ao.Remove(visibilityProperty); - } - if (avisible != evisible) { return false; } - if (avisible == false) - { - // both are collapsed (or nonexistent) so don't compare children - ao.Remove("children"); - eo.Remove("children"); - } - - if (eo.Keys.Count != ao.Keys.Count) - { - Debug.WriteLine($"Expected {eo.Keys.Count} but got {ao.Keys.Count}"); - Debug.WriteLine(string.Join(", ", eo.Keys)); - Debug.WriteLine(string.Join(", ", ao.Keys)); - return false; - } - foreach (var key in eo.Keys) - { - JsonValue evalue = eo.GetNamedValue(key); - JsonValue avalue = ao.GetNamedValue(key); - if (!JsonComparesEqual(evalue, avalue, key)) - { - Debug.WriteLine($"Property {key} compared differently {evalue.ValueType} {avalue.ValueType}: expected {evalue} got {avalue}"); - return false; - } - } - return true; - } - - public static string GetOutputFile(string dumpID) - { - return "TreeDump\\" + dumpID + ".json"; - } - - public static string GetMasterFile(string dumpID) - { - return "TreeDump\\masters\\" + dumpID + ".json"; - } - } -} diff --git a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj deleted file mode 100644 index 6d7628538f4..00000000000 --- a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - Debug - AnyCPU - {C0A6BD9C-3EE5-4B12-8CE4-CEE95178539C} - winmdobj - Properties - TreeDumpLibrary - TreeDumpLibrary - en-US - UAP - 10.0.18362.0 - 10.0.16299.0 - 16.0 - 512 - {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - false - false - - - x86 - true - bin\x86\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - false - prompt - - - x86 - bin\x86\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - false - prompt - - - ARM - true - bin\ARM\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - false - prompt - - - ARM - bin\ARM\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - false - prompt - - - x64 - true - bin\x64\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - false - prompt - - - x64 - bin\x64\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - false - prompt - - - true - bin\ARM64\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - ARM64 - false - prompt - - - bin\ARM64\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - ARM64 - false - prompt - - - PackageReference - - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ - - - - - - - - - - - - - - 6.2.10 - - - - - {f7d32bd0-2749-483e-9a0d-1635ef7e3136} - Microsoft.ReactNative - False - - - {F2824844-CE15-4242-9420-308923CD76C3} - Microsoft.ReactNative.Managed - - - - - - - 16.0 - - - - \ No newline at end of file diff --git a/packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs b/packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs deleted file mode 100644 index fd95352ebb4..00000000000 --- a/packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Windows.Data.Json; -using Windows.Foundation; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Automation; -using Windows.UI.Xaml.Media; - -namespace TreeDumpLibrary -{ - public enum DumpTreeMode - { - Default, - Json - } - - public sealed class VisualTreeDumper - { - class Visitor - { - private readonly IVisualTreeLogger _logger; - private int _indent; - private readonly DefaultFilter _filter; - private readonly IPropertyValueTranslator _translator; - public Visitor(DefaultFilter filter, IPropertyValueTranslator translator, IVisualTreeLogger logger) - { - _indent = 0; - _filter = filter; - _translator = translator; - _logger = logger; - } - public void EndVisitNode(DependencyObject obj, bool isLast) - { - _indent--; - _logger.EndNode(_indent, obj.GetType().FullName, obj, isLast); - } - - public void BeginVisitNode(DependencyObject obj, bool hasProperties) - { - _logger.BeginNode(_indent, obj.GetType().FullName, obj, hasProperties); - _indent++; - } - - public override string ToString() - { - return _logger.ToString(); - } - - public bool ShouldVisitPropertiesForNode(DependencyObject node) - { - var fe = node as FrameworkElement; - string[] excludedNames = new string[] { "VerticalScrollBar", "HorizontalScrollBar", "ScrollBarSeparator" }; - if (fe != null && excludedNames.Contains(fe.Name)) { return false; } - return true; - } - - public bool ShouldVisitProperty(string propertyName) - { - return _filter.ShouldVisitProperty(propertyName); - } - - public void VisitProperty(string propertyName, object value, bool isLast) - { - var v = _translator.PropertyValueToString(propertyName, value); - _logger.LogProperty(_indent + 1, propertyName, v, isLast); - } - - public void BeginChildren() - { - _logger.BeginArray(++_indent, "children"); - } - - public void EndChildren() - { - _logger.EndArray(_indent--, "children"); - } - - public bool ShouldVisitPropertyValue(string propertyName, object value) - { - string s = _translator.PropertyValueToString(propertyName, value); - if (propertyName == "Name") - { - string name = value as string; - return !name.StartsWith(":") && - name != ""; - } - return _filter.ShouldVisitPropertyValue(s); - } - } - - private static JsonObject FindElementByAutomationId(JsonObject obj, string automationId) - { - if (obj.Keys.Contains("AutomationId") && obj["AutomationId"].GetString() == automationId) - { - return obj; - } - if (obj.Keys.Contains("children")) - { - var array = obj.GetNamedArray("children"); - foreach (var i in array) - { - var element = FindElementByAutomationId(i.GetObject(), automationId); - if (element != null) - { - return element; - } - } - } - return null; - } - - public static IAsyncOperation DoesTreeDumpMatchForRNTester(DependencyObject root) - { - string json = DumpTree(root, null, new string[] { }, DumpTreeMode.Json); - try - { - var obj = JsonValue.Parse(json).GetObject(); - var element = FindElementByAutomationId(obj, "PageHeader"); - if (element == null) - { - return Task.Run(() => false).AsAsyncOperation(); - } - var value = element.GetNamedString("Text"); - var pageName = new Regex(@"[<|>]").Replace(value, ""); - var match = TreeDumpHelper.MatchDump(json, pageName); - return match.AsAsyncOperation(); - } - catch - { - Debug.WriteLine("JSON ERROR:\n" + json); - throw; - } - } - - public static string DumpTree(DependencyObject root, DependencyObject excludedNode, IList additionalProperties, DumpTreeMode mode) - { - var propertyFilter = new DefaultFilter(); - ((List)propertyFilter.PropertyNameAllowList).AddRange(additionalProperties); - - IPropertyValueTranslator translator = (mode == DumpTreeMode.Json ? - new JsonPropertyValueTranslator() as IPropertyValueTranslator : - new DefaultPropertyValueTranslator()); - IVisualTreeLogger logger = (mode == DumpTreeMode.Json ? - new JsonVisualTreeLogger() as IVisualTreeLogger : - new DefaultVisualTreeLogger()); - Visitor visitor = new Visitor(propertyFilter, translator, logger); - - WalkThroughTree(root, excludedNode, visitor); - - return visitor.ToString(); - } - - private static void WalkThroughProperties(DependencyObject node, Visitor visitor, bool hasChildren) - { - if (visitor.ShouldVisitPropertiesForNode(node)) - { - var properties = (from property in node.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) - where visitor.ShouldVisitProperty(property.Name) && - visitor.ShouldVisitPropertyValue(property.Name, - GetObjectProperty(node, property)) - orderby property.Name - select property).ToArray(); - var automationId = node.GetValue(AutomationProperties.AutomationIdProperty); - - for (int i = 0; i < properties.Length; i++) - { - var property = properties[i]; - object value = null; - value = GetObjectProperty(node, property); - bool isLast = (i == properties.Length - 1) && !hasChildren && (automationId == null); - visitor.VisitProperty(property.Name, value, isLast); - } - - if (automationId != null) - { - visitor.VisitProperty("AutomationId", automationId, !hasChildren); - } - } - } - - private static object GetObjectProperty(DependencyObject node, PropertyInfo property) - { - object value; - try - { - value = property.GetValue(node); - } - catch (Exception e) - { - value = "Exception when reading " + property.Name + e.ToString(); - } - - return value; - } - - private static DependencyObject[] GetChildren(DependencyObject node, Visitor visitor) - { - DependencyObject[] dos = new DependencyObject[VisualTreeHelper.GetChildrenCount(node)]; - for (int i = 0; i < dos.Length; i++) - { - dos[i] = VisualTreeHelper.GetChild(node, i); - } - return dos.Where((n) => visitor.ShouldVisitPropertiesForNode(n)).ToArray(); - } - - private static void WalkThroughTree(DependencyObject node, DependencyObject excludedNode, Visitor visitor, bool isLast = true) - { - if (node != null && visitor.ShouldVisitPropertiesForNode(node)) - { - // Assume that if we have a UIElement, we'll have some properties - var children = GetChildren(node, visitor); - bool hasProperties = node is UIElement || (children.Length > 0); - - visitor.BeginVisitNode(node, hasProperties); - - WalkThroughProperties(node, visitor, children.Length != 0); - if (children.Length != 0) - { - visitor.BeginChildren(); - for (int i = 0; i < children.Length; i++) - { - var child = children[i]; - if (child != excludedNode) - { - bool isLastChild = (i == children.Length - 1); - WalkThroughTree(child, excludedNode, visitor, isLastChild); - } - } - visitor.EndChildren(); - } - visitor.EndVisitNode(node, isLast); - } - } - } - public sealed class DefaultFilter - { - public IList PropertyNameAllowList { get; set; } - - public DefaultFilter() - { - PropertyNameAllowList = new List - { - "Foreground", - "Background", - "Padding", - "Margin", - "RenderSize", - "Visibility", - "CornerRadius", - "BorderThickness", - "Width", - "Height", - "BorderBrush", - "VerticalAlignment", - "HorizontalAlignment", - "Clip", - "FlowDirection", - "Name", - "Text" - /*"ActualOffset" 19h1*/ - }; - } - - public bool ShouldVisitPropertyValue(string propertyValue) - { - return !string.IsNullOrEmpty(propertyValue) && !propertyValue.Equals("NaN") && !propertyValue.StartsWith("Exception"); - } - - public bool ShouldVisitProperty(string propertyName) - { - return (PropertyNameAllowList.Contains(propertyName)); - } - } - public sealed class DefaultPropertyValueTranslator : IPropertyValueTranslator - { - public string PropertyValueToString(string propertyName, object propertyObject) - { - if (propertyObject == null) - { - return "[NULL]"; - } - - if (propertyObject is SolidColorBrush) - { - return (propertyObject as SolidColorBrush).Color.ToString(); - } - else if (propertyObject is Size) - { - // comparing doubles is numerically unstable so just compare their integer parts - Size size = (Size)propertyObject; - return $"{(int)size.Width},{(int)size.Height}"; - } - return propertyObject.ToString(); - } - } - - public sealed class JsonPropertyValueTranslator : IPropertyValueTranslator - { - public string PropertyValueToString(string propertyName, object propertyObject) - { - if (propertyObject == null) - { - return "null"; - } - else if (propertyObject is int || propertyObject is bool || propertyObject is double) - { - return propertyObject.ToString(); - } - else if (propertyObject is SolidColorBrush) - { - return Quote((propertyObject as SolidColorBrush).Color.ToString()); - } - else if (propertyObject is Size) - { - // comparing doubles is numerically unstable so just compare their integer parts - Size size = (Size)propertyObject; - int width = (int)size.Width; - int height = (int)size.Height; - return $"[{width}, {height}]"; - } - return Quote(propertyObject.ToString()); - } - - public static string Quote(string s) - { - s = s.Replace('\t', ' ').Replace("\n", @"\n"); - s = Regex.Replace(s, @"\p{Cs}", ""); // remove surrogate pairs e.g. emojis - return '"' + s.Replace("\"", "\\\"") + '"'; - } - } -} From 251f5205dc5cb98797b9f1c31c3d5a537321c0f1 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Fri, 15 May 2020 21:28:37 -0700 Subject: [PATCH 120/209] ReactNonAbiValue for IReactPropertyBag non-ABI values (#4911) * ReactNonAbiValue for IReactPropertyBag non-ABI values * Added comments to the new code. --- ...dows-2020-05-14-17-22-55-NonAbiValues.json | 8 + .../JSValueTest.cpp | 25 ++-- ...icrosoft.ReactNative.Cxx.UnitTests.vcxproj | 2 +- .../NativeModuleTest.cpp | 3 +- .../NoAttributeNativeModuleTest.cpp | 4 +- .../TurboModuleTest.cpp | 3 +- vnext/Microsoft.ReactNative.Cxx/BoxedValue.h | 31 ---- .../Microsoft.ReactNative.Cxx.vcxitems | 2 +- .../Microsoft.ReactNative.Cxx/NativeModules.h | 10 +- .../ReactNonAbiValue.h | 125 ++++++++++++++++ .../ReactPropertyBag.h | 61 +++++--- ...osoft.ReactNative.IntegrationTests.vcxproj | 1 + .../ReactNativeHostTests.cpp | 5 +- .../ReactNonAbiValueTests.cpp | 139 ++++++++++++++++++ .../ReactPropertyBagTests.cpp | 17 ++- .../pch.h | 4 +- vnext/Microsoft.ReactNative/IBoxedValue.idl | 13 -- .../IReactNonAbiValue.idl | 18 +++ .../Microsoft.ReactNative.vcxproj | 2 +- .../Microsoft.ReactNative.vcxproj.filters | 2 +- vnext/Mso/motifCpp/testCheck.h | 8 +- 21 files changed, 379 insertions(+), 104 deletions(-) create mode 100644 change/react-native-windows-2020-05-14-17-22-55-NonAbiValues.json delete mode 100644 vnext/Microsoft.ReactNative.Cxx/BoxedValue.h create mode 100644 vnext/Microsoft.ReactNative.Cxx/ReactNonAbiValue.h create mode 100644 vnext/Microsoft.ReactNative.IntegrationTests/ReactNonAbiValueTests.cpp delete mode 100644 vnext/Microsoft.ReactNative/IBoxedValue.idl create mode 100644 vnext/Microsoft.ReactNative/IReactNonAbiValue.idl diff --git a/change/react-native-windows-2020-05-14-17-22-55-NonAbiValues.json b/change/react-native-windows-2020-05-14-17-22-55-NonAbiValues.json new file mode 100644 index 00000000000..1a3c137c8a2 --- /dev/null +++ b/change/react-native-windows-2020-05-14-17-22-55-NonAbiValues.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "ReactNonAbiValue for IReactPropertyBag non-ABI values", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-15T00:22:54.871Z" +} diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/JSValueTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/JSValueTest.cpp index 2db87ab01f5..f80f596ffb2 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/JSValueTest.cpp +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/JSValueTest.cpp @@ -34,20 +34,19 @@ TEST_CLASS (JSValueTest) { TestCheckEqual(JSValueType::Int64, jsValue["IntValue"].Type()); TestCheckEqual(JSValueType::Double, jsValue["DoubleValue"].Type()); - JSValueObject const *objValue = nullptr; - JSValueArray const *arrayValue = nullptr; - std::string const *stringValue = nullptr; - bool const *boolValue = nullptr; - int64_t const *intValue = nullptr; - double const *doubleValue = nullptr; - TestCheck(jsValue["NullValue"].IsNull()); - TestCheck(objValue = jsValue["ObjValue"].TryGetObject()); - TestCheck(arrayValue = jsValue["ArrayValue"].TryGetArray()); - TestCheck(stringValue = jsValue["StringValue"].TryGetString()); - TestCheck(boolValue = jsValue["BoolValue"].TryGetBoolean()); - TestCheck(intValue = jsValue["IntValue"].TryGetInt64()); - TestCheck(doubleValue = jsValue["DoubleValue"].TryGetDouble()); + JSValueObject const *objValue = jsValue["ObjValue"].TryGetObject(); + JSValueArray const *arrayValue = jsValue["ArrayValue"].TryGetArray(); + std::string const *stringValue = jsValue["StringValue"].TryGetString(); + bool const *boolValue = jsValue["BoolValue"].TryGetBoolean(); + int64_t const *intValue = jsValue["IntValue"].TryGetInt64(); + double const *doubleValue = jsValue["DoubleValue"].TryGetDouble(); + TestCheck(objValue); + TestCheck(arrayValue); + TestCheck(stringValue); + TestCheck(boolValue); + TestCheck(intValue); + TestCheck(doubleValue); TestCheckEqual(1, objValue->size()); TestCheckEqual(1, jsValue["ObjValue"].PropertyCount()); diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj b/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj index 79d66fa1e3a..2a6954d74c6 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj @@ -138,13 +138,13 @@ - + diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp index 62abfec9cba..cb15f7eaa11 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp @@ -598,8 +598,7 @@ TEST_CLASS (NativeModuleTest) { m_moduleBuilder = winrt::make(m_builderMock); auto provider = React::MakeModuleProvider(); m_moduleObject = m_builderMock.CreateModule(provider, m_moduleBuilder); - auto reactModule = m_moduleObject.as(); - m_module = &React::BoxedValue::GetValueUnsafe(reactModule); + m_module = React::ReactNonAbiValue::GetPtrUnsafe(m_moduleObject); } TEST_METHOD(TestMethodCall_Add) { diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp index bb1fc56272e..dd4859ab2df 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp @@ -603,8 +603,8 @@ TEST_CLASS (NoAttributeNativeModuleTest) { m_moduleBuilder = winrt::make(m_builderMock); auto provider = React::MakeModuleProvider(); m_moduleObject = m_builderMock.CreateModule(provider, m_moduleBuilder); - auto reactModule = m_moduleObject.as(); - m_module = &React::BoxedValue::GetValueUnsafe(reactModule); + auto reactModule = m_moduleObject.as(); + m_module = React::ReactNonAbiValue::GetPtrUnsafe(m_moduleObject); } TEST_METHOD(TestMethodCall_Add) { diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp index 0933de064d8..f9f5c597724 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp @@ -1117,8 +1117,7 @@ TEST_CLASS (TurboModuleTest) { m_moduleBuilder = winrt::make(m_builderMock); auto provider = winrt::Microsoft::ReactNative::MakeTurboModuleProvider(); m_moduleObject = m_builderMock.CreateModule(provider, m_moduleBuilder); - auto reactModule = m_moduleObject.as(); - m_module = &winrt::Microsoft::ReactNative::BoxedValue::GetValueUnsafe(reactModule); + m_module = winrt::Microsoft::ReactNative::ReactNonAbiValue::GetPtrUnsafe(m_moduleObject); } TEST_METHOD(TestMethodCall_Add) { diff --git a/vnext/Microsoft.ReactNative.Cxx/BoxedValue.h b/vnext/Microsoft.ReactNative.Cxx/BoxedValue.h deleted file mode 100644 index 841391a718b..00000000000 --- a/vnext/Microsoft.ReactNative.Cxx/BoxedValue.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once -#ifndef MICROSOFT_REACTNATIVE_BOXEDVALUE -#define MICROSOFT_REACTNATIVE_BOXEDVALUE - -#include - -namespace winrt::Microsoft::ReactNative { - -template -struct BoxedValue : implements, IBoxedValue> { - template - BoxedValue(TArgs &&... args) noexcept : m_value(std::forward(args)...) {} - - int64_t GetPtr() const noexcept { - return reinterpret_cast(&m_value); - } - - static T &GetValueUnsafe(IBoxedValue const &boxedValue) noexcept { - return *reinterpret_cast(boxedValue.GetPtr()); - } - - private: - T m_value{}; -}; - -} // namespace winrt::Microsoft::ReactNative - -#endif // MICROSOFT_REACTNATIVE_BOXEDVALUE diff --git a/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems b/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems index 076e18d46d5..d4533ce3d6c 100644 --- a/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +++ b/vnext/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems @@ -17,7 +17,6 @@ - @@ -29,6 +28,7 @@ + diff --git a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h index 23532730abc..3e590f3037c 100644 --- a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h +++ b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h @@ -4,11 +4,11 @@ #pragma once #include "winrt/Microsoft.ReactNative.h" -#include "BoxedValue.h" #include "JSValueReader.h" #include "JSValueWriter.h" #include "ModuleRegistration.h" #include "ReactContext.h" +#include "ReactNonAbiValue.h" #include "ReactPromise.h" #include @@ -1109,8 +1109,8 @@ struct TurboModuleSpec { template inline ReactModuleProvider MakeModuleProvider() noexcept { return [](IReactModuleBuilder const &moduleBuilder) noexcept { - auto moduleObject = make>(); - auto module = &BoxedValue::GetValueUnsafe(moduleObject); + ReactNonAbiValue moduleObject{std::in_place}; + TModule *module = moduleObject.GetPtr(); ReactModuleBuilder builder{module, moduleBuilder}; GetReactModuleInfo(module, builder); builder.CompleteRegistration(); @@ -1122,8 +1122,8 @@ template inline ReactModuleProvider MakeTurboModuleProvider() noexcept { TModuleSpec::template ValidateModule(); return [](IReactModuleBuilder const &moduleBuilder) noexcept { - auto moduleObject = make>(); - auto module = &BoxedValue::GetValueUnsafe(moduleObject); + ReactNonAbiValue moduleObject{std::in_place}; + TModule *module = moduleObject.GetPtr(); ReactModuleBuilder builder{module, moduleBuilder}; GetReactModuleInfo(module, builder); builder.CompleteRegistration(); diff --git a/vnext/Microsoft.ReactNative.Cxx/ReactNonAbiValue.h b/vnext/Microsoft.ReactNative.Cxx/ReactNonAbiValue.h new file mode 100644 index 00000000000..380b8344784 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Cxx/ReactNonAbiValue.h @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#ifndef MICROSOFT_REACTNATIVE_REACTNONABIVALUE +#define MICROSOFT_REACTNATIVE_REACTNONABIVALUE + +#include +#include + +namespace winrt::Microsoft::ReactNative { + +namespace implementation { + +// The ReactNonAbiValue implementation that wraps up the non-ABI safe value. +// This class is created by winrt::Microsoft::ReactNative::ReactNonAbiValue constructor +// that accepts std::in_place of type std::in_place_t as the first parameter. +template +struct ReactNonAbiValue : implements, IReactNonAbiValue> { + // Create ReactNonAbiValue and construct the wrapped value. + template + ReactNonAbiValue(TArgs &&... args) noexcept : m_value{std::forward(args)...} {} + + // Get a pointer to the wrapped value. + int64_t GetPtr() const noexcept { + return reinterpret_cast(&m_value); + } + + private: + T m_value{}; // Wrapped non-ABI value. +}; + +} // namespace implementation + +// Use this class to work with non-ABI value wrappers. +// This class is a smart pointer to the implementation::ReactNonAbiValue which is +// ref-counted and allocated in the heap. The ReactNonAbiValue should be used as if +// it would be a winrt::com_ptr. It has the same behavior in regards +// to copy/move semantic. +// Use the constructor that accepts std::in_place of type std::in_place_t as the first parameter to allocate +// a new instance of implementation::ReactNonAbiValue. The std::in_place allows to disambiguate the calls to +// other constructors. +template +struct ReactNonAbiValue : Windows::Foundation::IInspectable { + // Create a new instance of implementation::ReactNonAbiValue with args and keep a ref-counted pointer to it. + template + ReactNonAbiValue(std::in_place_t, TArgs &&... args) noexcept + : IInspectable{make>(std::forward(args)...)} {} + + // Create an empty ReactNonAbiValue. + ReactNonAbiValue(std::nullptr_t = nullptr) noexcept {} + + // Create a ReactNonAbiValue with taking the onwership from the provided pointer. + ReactNonAbiValue(void *ptr, take_ownership_from_abi_t) noexcept : IInspectable(ptr, take_ownership_from_abi) {} + + // Get a pointer to the value from the object it implements IReactNonAbiValue. + // The method is unsafe because it provides no protection in case if the object has a value of different type. + // Treat this method as if you would cast to a value type from 'void*' type. + // The method returns nullptr if obj doe snot implement the IReactNonAbiValue interface. + static T *GetPtrUnsafe(IInspectable const &obj) noexcept { + if (IReactNonAbiValue temp = obj.try_as()) { + return reinterpret_cast(temp.GetPtr()); + } else { + return nullptr; + } + } + + // Get pointer to the stored value. + // Return nullptr if ReactNonAbiValue is empty. + T *GetPtr() const noexcept { + if (IReactNonAbiValue const &temp = + *static_cast(static_cast(this))) { + return reinterpret_cast(temp.GetPtr()); + } else { + return nullptr; + } + } + + // Get pointer to the stored value. + // Return nullptr if ReactNonAbiValue is empty. + T *operator->() const noexcept { + return GetPtr(); + } + + // Get a reference to the stored value. + // Crash the app if ReactNonAbiValue is empty. + T &operator*() const noexcept { + return *GetPtr(); + } + + // Get a reference to the stored value. + // Crash the app if ReactNonAbiValue is empty. + T &Value() const noexcept { + return *GetPtr(); + } + + // Call the call operator() for the stored value. + // Crash the app if ReactNonAbiValue is empty. + template + auto operator()(TArgs &&... args) const { + return (*GetPtr())(std::forward(args)...); + } +}; + +// Type traits to check if type T is a IsReactNonAbiValue. +template +struct IsReactNonAbiValue : std::false_type {}; +template +struct IsReactNonAbiValue> : std::true_type {}; + +// A shortcut for the value of the IsReactNonAbiValue type traits. +template +constexpr bool IsReactNonAbiValueV = IsReactNonAbiValue::value; + +} // namespace winrt::Microsoft::ReactNative + +namespace winrt::impl { +// C++/WinRT binding to connect ReactNonAbiValue with the IReactNonAbiValue interface. +template +struct default_interface> { + using type = Microsoft::ReactNative::IReactNonAbiValue; +}; +} // namespace winrt::impl + +#endif // MICROSOFT_REACTNATIVE_REACTNONABIVALUE diff --git a/vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h b/vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h index fcf75ff7a22..8d461e9fb12 100644 --- a/vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h +++ b/vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h @@ -23,7 +23,7 @@ // // For example, we can define a property to access an integer value: // -// const React::ReactPropertyId MyIntProperty{"MyInt"}; +// const React::ReactPropertyId MyIntProperty{L"MyInt"}; // // then we can use it to set property in settings properties during initialization: // @@ -37,14 +37,39 @@ // directly because their null value may indicated absent property value. // For other types we return std::optional. It has std::nullopt value in case if // no property value is found or if it has a wrong type. +// // To pass values through the ABI boundary the non-IInspectable types must be WinRT types // which are described here: // https://docs.microsoft.com/en-us/uwp/api/windows.foundation.propertytype?view=winrt-18362 // +// In case if we do not have a requirement to pass values across the DLL/EXE boundary, +// we can use the ReactNonAbiValue wrapper to store non-ABI safe values. +// The type ReactNonAbiValue is a smart pointer similar to winrt::com_ptr +// or winrt::Windows::Foundation::IInspactable. It is treated as IInspectable type and +// **is not** wrapped in std::optional. It can be casted to bool to check if it is null. +// +// For example, we can define a property to use in our DLL or EXE to store std::string: +// +// const React::ReactPropertyId> MyStringProperty{L"MyString"}; +// +// then we can use it to set and get property value: +// +// context.Properties().Set(MyStringProperty, "Hello"); +// assert("Hello" == context.Properties().Get(MyStringProperty); +// +// The first line above creates a new React::ReactNonAbValue value that internally. +// allocates a ref-counted wrapper React::implementation::ReactNonAbValue in the heap. +// Then this value is stored in the IReactPropertyBag and can be safely retrieved in the +// same DLL or EXE module. Using it from a different module may cause a security bug or a crash. +// +// Note that for passing the ABI-safe strings we must use the winrt::hstring: +// +// const React::ReactPropertyId MyAbiSafeStringProperty{L"MyAbiSafeString"}; +// #include #include -#include "BoxedValue.h" +#include "ReactNonAbiValue.h" namespace winrt::Microsoft::ReactNative { @@ -235,22 +260,30 @@ struct ReactPropertyBag { } private: - template - static Windows::Foundation::IInspectable ToObject(T const &value) noexcept { - if constexpr (impl::has_category_v) { - return box_value(value); - } else { - return make>(value); - } + template || std::is_same_v, int> = 0> + static Windows::Foundation::IInspectable ToObject(TValue const &value) noexcept { + // We box WinRT types and return IInspectable-inherited values as-is. + // The ReactNonAbiValue is treated as IInspectable-inherited value if TValue=='ReactNonAbiValue'. + return box_value(value); + } + + template && !std::is_same_v, int> = 0> + static Windows::Foundation::IInspectable ToObject(TValue &&value) noexcept { + // Create ReactNonAbiValue with newly allocated wrapper for U and pass TValue as an argument to the U + // constructor. For example, we can pass TValue=='const char*' to U=='std::string' where + // T=='ReactNonAbiValue'. + return T{std::in_place, std::forward(value)}; } template static Windows::Foundation::IInspectable ToObject(std::optional const &value) noexcept { - return value ? ToObject(*value) : nullptr; + return value ? ToObject(*value) : nullptr; } template static auto FromObject(Windows::Foundation::IInspectable const &obj) noexcept { + // The code mostly borrowed from the winrt::unbox_value_or implementation to return + // empty std::optional in case if obj is null or has a wrong type. if constexpr (std::is_base_of_v) { return obj.try_as(); } else if constexpr (impl::has_category_v) { @@ -273,14 +306,6 @@ struct ReactPropertyBag { } } - return std::optional{}; - } else { - if (obj) { - if (auto temp = obj.try_as()) { - return std::optional{BoxedValue::GetValueUnsafe(temp)}; - } - } - return std::optional{}; } } diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj b/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj index 6747f99b5dc..21bda3136b0 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj +++ b/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj @@ -108,6 +108,7 @@ + diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp b/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp index 81e230fcf1a..5136ffe2c31 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp +++ b/vnext/Microsoft.ReactNative.IntegrationTests/ReactNativeHostTests.cpp @@ -1,6 +1,7 @@ -#include "pch.h" -#include "NativeModules.h" +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#include "pch.h" #include using namespace React; diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/ReactNonAbiValueTests.cpp b/vnext/Microsoft.ReactNative.IntegrationTests/ReactNonAbiValueTests.cpp new file mode 100644 index 00000000000..cf8fc6471f3 --- /dev/null +++ b/vnext/Microsoft.ReactNative.IntegrationTests/ReactNonAbiValueTests.cpp @@ -0,0 +1,139 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" + +#include +#include +#include +#include + +using namespace winrt; +using namespace Microsoft::ReactNative; +using namespace Windows::Foundation; +using namespace std::string_literals; + +namespace ReactNativeIntegrationTests { + +TEST_CLASS (ReactNonAbiValueTests) { + TEST_METHOD(NonAbiValue_ctor_Default) { + ReactNonAbiValue v1; + TestCheck(!v1); + } + + TEST_METHOD(NonAbiValue_ctor_EmptyStr) { + ReactNonAbiValue v1{std::in_place}; + TestCheck(v1); + TestCheckEqual(""s, *v1); + } + + TEST_METHOD(NonAbiValue_ctor_NonEmptyStr) { + ReactNonAbiValue v1{std::in_place, "Hello"}; + TestCheck(v1); + TestCheckEqual("Hello"s, *v1); + } + + TEST_METHOD(NonAbiValue_ctor_Copy) { + ReactNonAbiValue v1{std::in_place, "Hello"}; + ReactNonAbiValue v2{v1}; + TestCheck(v1); + TestCheck(v2); + TestCheckEqual(v1.GetPtr(), v2.GetPtr()); + TestCheckEqual("Hello"s, *v1); + TestCheckEqual("Hello"s, *v2); + } + + TEST_METHOD(NonAbiValue_ctor_Move) { + ReactNonAbiValue v1{std::in_place, "Hello"}; + ReactNonAbiValue v2{std::move(v1)}; + TestCheck(!v1); + TestCheck(v2); + TestCheckEqual("Hello"s, *v2); + } + + TEST_METHOD(NonAbiValue_assignment_Copy) { + ReactNonAbiValue v1{std::in_place, "Hello"}; + ReactNonAbiValue v2; + v2 = v1; + TestCheck(v1); + TestCheck(v2); + TestCheckEqual(v1.GetPtr(), v2.GetPtr()); + TestCheckEqual("Hello"s, *v1); + TestCheckEqual("Hello"s, *v2); + } + + TEST_METHOD(NonAbiValue_assignment_Move) { + ReactNonAbiValue v1{std::in_place, "Hello"}; + ReactNonAbiValue v2; + v2 = std::move(v1); + TestCheck(!v1); + TestCheck(v2); + TestCheckEqual("Hello"s, *v2); + } + + TEST_METHOD(NonAbiValue_swap) { + using std::swap; + ReactNonAbiValue v1{std::in_place, "Hello"}; + ReactNonAbiValue v2{std::in_place, "World"}; + swap(v1, v2); + TestCheckEqual("Hello"s, *v2); + TestCheckEqual("World"s, *v1); + } + + TEST_METHOD(NonAbiValue_reset) { + ReactNonAbiValue v1{std::in_place, "Hello"}; + TestCheck(v1); + v1 = nullptr; + TestCheck(!v1); + } + + TEST_METHOD(NonAbiValue_equality) { + ReactNonAbiValue v11{std::in_place, "Hello"}; + ReactNonAbiValue v12{v11}; + ReactNonAbiValue v2{std::in_place, "World"}; + ReactNonAbiValue v3; + TestCheck(v11 == v12); + TestCheck(v12 == v11); + TestCheck(v11 != v2); + TestCheck(v11 != v3); + TestCheck(v2 != v11); + TestCheck(v3 != v11); + TestCheck(v3 == nullptr); + TestCheck(nullptr == v3); + TestCheck(v11 != nullptr); + TestCheck(nullptr != v11); + } + + TEST_METHOD(NonAbiValue_operator_arrow) { + ReactNonAbiValue v1{std::in_place, "Hello"}; + TestCheckEqual(5, v1->length()); + } + + TEST_METHOD(NonAbiValue_operator_call) { + ReactNonAbiValue> v1{std::in_place, [](int x, int y) { return x + y; }}; + TestCheckEqual(42, v1(37, 5)); + } + + TEST_METHOD(NonAbiValue_moveonly_value) { + ReactNonAbiValue> v1{std::in_place, new int{42}}; + TestCheck(v1); + TestCheck(v1->get()); + TestCheckEqual(42, *v1->get()); + std::unique_ptr ptr = std::move(*v1); + TestCheckEqual(42, *ptr); + TestCheck(v1); + TestCheck(!v1->get()); + } + + TEST_METHOD(NonAbiValue_Value) { + ReactNonAbiValue> v1{std::in_place, new int{42}}; + TestCheck(v1.Value()); + TestCheckEqual(42, *v1.Value()); + std::unique_ptr ptr{std::move(v1.Value())}; + TestCheckEqual(42, *ptr); + TestCheck(v1); + TestCheck(!v1.Value()); + } +}; + +} // namespace ReactNativeIntegrationTests diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp b/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp index f96cee63e26..d7200d84715 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp +++ b/vnext/Microsoft.ReactNative.IntegrationTests/ReactPropertyBagTests.cpp @@ -1,12 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + #include "pch.h" #include #include #include +#include using namespace winrt; using namespace Microsoft::ReactNative; using namespace Windows::Foundation; +using namespace std::string_literals; namespace ReactNativeIntegrationTests { @@ -525,21 +530,21 @@ TEST_CLASS (ReactPropertyBagTests) { } TEST_METHOD(PropertyBag_Property_Functor) { - ReactPropertyId> fooName{L"Foo"}; + ReactPropertyId>> fooName{L"Foo"}; ReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()}; TestCheck(!pb.Get(fooName)); - Mso::Functor createValue1 = []() noexcept { - return winrt::box_value(5); + Mso::Functor createValue1 = []() noexcept { + return "Hello world!"s; }; TestCheckEqual(createValue1, *pb.GetOrCreate(fooName, [&createValue1]() { return createValue1; })); TestCheckEqual(createValue1, *pb.Get(fooName)); - TestCheckEqual(5, winrt::unbox_value((*pb.Get(fooName))())); + TestCheckEqual("Hello world!"s, pb.Get(fooName)()); - Mso::Functor createValue2 = []() { return winrt::box_value(10); }; + Mso::Functor createValue2 = []() { return "Hello ReactNative!"s; }; pb.Set(fooName, createValue2); TestCheckEqual(createValue2, *pb.Get(fooName)); - TestCheckEqual(10, winrt::unbox_value((*pb.Get(fooName))())); + TestCheckEqual("Hello ReactNative!"s, pb.Get(fooName)()); TestCheck(createValue1 != *pb.Get(fooName)); pb.Remove(fooName); TestCheck(!pb.Get(fooName)); diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/pch.h b/vnext/Microsoft.ReactNative.IntegrationTests/pch.h index 19f70f55b7b..a45b8034e41 100644 --- a/vnext/Microsoft.ReactNative.IntegrationTests/pch.h +++ b/vnext/Microsoft.ReactNative.IntegrationTests/pch.h @@ -2,9 +2,9 @@ #define NOMINMAX +#include +#include #include -#include "functional/functor.h" -#include "motifCpp/testCheck.h" #undef GetCurrentTime #include diff --git a/vnext/Microsoft.ReactNative/IBoxedValue.idl b/vnext/Microsoft.ReactNative/IBoxedValue.idl deleted file mode 100644 index 36c4a15d21b..00000000000 --- a/vnext/Microsoft.ReactNative/IBoxedValue.idl +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import "NoExceptionAttribute.idl"; - -namespace Microsoft.ReactNative { - - // Helps to wrap up a simple C++ struct into an IInspectable object - [webhosthidden] - interface IBoxedValue { - Int64 GetPtr(); - } -} // namespace Microsoft.ReactNative diff --git a/vnext/Microsoft.ReactNative/IReactNonAbiValue.idl b/vnext/Microsoft.ReactNative/IReactNonAbiValue.idl new file mode 100644 index 00000000000..98d467fe9b9 --- /dev/null +++ b/vnext/Microsoft.ReactNative/IReactNonAbiValue.idl @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import "NoExceptionAttribute.idl"; + +namespace Microsoft.ReactNative { + + // IReactNonAbiValue helps to wrap up a non-ABI safe C++ values into an + // IInspectable object. We use it to handle native module lifetime. + // It also can be used to store values in the IReactPropertyBag that do not + // need to go through the EXE/DLL boundary. + [webhosthidden] + interface IReactNonAbiValue + { + // Get a pointer to the stored value. + Int64 GetPtr(); + } +} // namespace Microsoft.ReactNative diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj index 8586d47ef81..5fa4e8c16cd 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj @@ -550,7 +550,7 @@ - + diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters index 69b37cc4be2..3730f7e0db1 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters @@ -688,13 +688,13 @@ Views\cppwinrt - + diff --git a/vnext/Mso/motifCpp/testCheck.h b/vnext/Mso/motifCpp/testCheck.h index 7c18742f90a..31e1b1ea191 100644 --- a/vnext/Mso/motifCpp/testCheck.h +++ b/vnext/Mso/motifCpp/testCheck.h @@ -11,9 +11,9 @@ // It allows to write more compact code because we do not need to add comment // for every TestAssert. // -// All macros have a form with suffix "L" that accept line number as a parameter. -// It is done to enable creation of custom check macros that internally -// use the macros we provide. +// All macros have a form with suffix "At" that accepts file and line number +// as parameters. It is done to enable creation of custom check macros that +// internally use these macros. //============================================================================= #include "motifCpp/assert_motifApi.h" @@ -33,7 +33,7 @@ // It will be shown as macro usage rather than macro being expanded. //============================================================================= #define TestCheckAtInternal(file, line, expr, exprStr, ...) \ - TestAssert::IsTrueAt(file, line, expr, exprStr, TestAssert::FormatMsg("" __VA_ARGS__).c_str()) + TestAssert::IsTrueAt(file, line, !!(expr), exprStr, TestAssert::FormatMsg("" __VA_ARGS__).c_str()) #define TestCheckAt(file, line, expr, ...) TestCheckAtInternal(file, line, expr, #expr, __VA_ARGS__) #define TestCheck(expr, ...) TestCheckAtInternal(__FILE__, __LINE__, expr, #expr, __VA_ARGS__) From 06921271e82e07b7eb94d5808103367b85a76a7d Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Sat, 16 May 2020 11:04:00 -0700 Subject: [PATCH 121/209] Fixed ReactContext CallJSFunction and EmitJSEvent (#4922) * Fixed ReactContext CallJSFunction and EmitJSEvent * Change files * Added test checks for unsigned values --- ...20-05-15-21-43-34-MS_FixReactContext2.json | 8 ++ .../ReactContextTest.cpp | 98 +++++++++++++++++-- .../Microsoft.ReactNative.Cxx/JSValueWriter.h | 7 +- .../Microsoft.ReactNative.Cxx/ReactContext.h | 28 ++---- 4 files changed, 111 insertions(+), 30 deletions(-) create mode 100644 change/react-native-windows-2020-05-15-21-43-34-MS_FixReactContext2.json diff --git a/change/react-native-windows-2020-05-15-21-43-34-MS_FixReactContext2.json b/change/react-native-windows-2020-05-15-21-43-34-MS_FixReactContext2.json new file mode 100644 index 00000000000..44a07b8611e --- /dev/null +++ b/change/react-native-windows-2020-05-15-21-43-34-MS_FixReactContext2.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Fixed ReactContext CallJSFunction and EmitJSEvent", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-16T04:43:34.199Z" +} diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactContextTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactContextTest.cpp index c2d28914c93..4fec5d137c1 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactContextTest.cpp +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactContextTest.cpp @@ -20,18 +20,30 @@ struct ReactContextStub : implements { } void CallJSFunction( - hstring const & /*moduleName*/, - hstring const & /*functionName*/, - JSValueArgWriter const & /*paramsArgWriter*/) noexcept { - VerifyElseCrashSz(false, "Not implemented"); + hstring const &moduleName, + hstring const &functionName, + JSValueArgWriter const ¶msArgWriter) noexcept { + Module = moduleName; + Method = functionName; + auto writer = MakeJSValueTreeWriter(); + paramsArgWriter(writer); + Args = TakeJSValue(writer); } void EmitJSEvent( - hstring const & /*eventEmitterName*/, - hstring const & /*eventName*/, - JSValueArgWriter const & /*paramsArgWriter*/) noexcept { - VerifyElseCrashSz(false, "Not implemented"); + hstring const &eventEmitterName, + hstring const &eventName, + JSValueArgWriter const ¶msArgWriter) noexcept { + Module = eventEmitterName; + Method = eventName; + auto writer = MakeJSValueTreeWriter(); + paramsArgWriter(writer); + Args = TakeJSValue(writer); } + + std::wstring Module; + std::wstring Method; + JSValue Args; }; namespace ReactNativeTests { @@ -108,6 +120,76 @@ TEST_CLASS (ReactContextTest) { TestCheck(context11 != nullptr); TestCheck(nullptr != context11); } + + TEST_METHOD(Test_CallJSFunction) { + auto reactContextMock = winrt::make_self(); + ReactContext context{reactContextMock.as()}; + context.CallJSFunction(L"module1", L"method1"); + TestCheckEqual(L"module1", reactContextMock->Module); + TestCheckEqual(L"method1", reactContextMock->Method); + TestCheckEqual(0u, reactContextMock->Args.AsArray().size()); + + context.CallJSFunction(L"module1", L"method1", 5); + TestCheckEqual(1u, reactContextMock->Args.AsArray().size()); + TestCheckEqual(5, reactContextMock->Args[0]); + + context.CallJSFunction(L"module1", L"method1", 14, 17u); + TestCheckEqual(2u, reactContextMock->Args.AsArray().size()); + TestCheckEqual(14, reactContextMock->Args[0]); + TestCheckEqual(17u, reactContextMock->Args[1]); + + context.CallJSFunction(L"module1", L"method1", JSValueArray{12, 18u}); + TestCheckEqual(12, reactContextMock->Args[0][0]); + TestCheckEqual(18u, reactContextMock->Args[0][1]); + + context.CallJSFunction(L"module1", L"method1", JSValueObject{{"prop1", 42}, {"prop2", 77u}}); + TestCheckEqual(42, reactContextMock->Args[0]["prop1"]); + TestCheckEqual(77u, reactContextMock->Args[0]["prop2"]); + + context.CallJSFunction(L"module1", L"method1", [](IJSValueWriter const &writer) { + writer.WriteArrayBegin(); + WriteValue(writer, 10u); + WriteValue(writer, 19); + writer.WriteArrayEnd(); + }); + TestCheckEqual(10u, reactContextMock->Args[0]); + TestCheckEqual(19, reactContextMock->Args[1]); + } + + TEST_METHOD(Test_EmitJSEvent) { + auto reactContextMock = winrt::make_self(); + ReactContext context{reactContextMock.as()}; + context.EmitJSEvent(L"module1", L"event1"); + TestCheckEqual(L"module1", reactContextMock->Module); + TestCheckEqual(L"event1", reactContextMock->Method); + TestCheckEqual(0u, reactContextMock->Args.AsArray().size()); + + context.EmitJSEvent(L"module1", L"event1", 5); + TestCheckEqual(1u, reactContextMock->Args.AsArray().size()); + TestCheckEqual(5, reactContextMock->Args[0]); + + context.EmitJSEvent(L"module1", L"event1", 14, 17u); + TestCheckEqual(2u, reactContextMock->Args.AsArray().size()); + TestCheckEqual(14, reactContextMock->Args[0]); + TestCheckEqual(17u, reactContextMock->Args[1]); + + context.EmitJSEvent(L"module1", L"event1", JSValueArray{12, 18u}); + TestCheckEqual(12, reactContextMock->Args[0][0]); + TestCheckEqual(18u, reactContextMock->Args[0][1]); + + context.EmitJSEvent(L"module1", L"event1", JSValueObject{{"prop1", 42}, {"prop2", 77u}}); + TestCheckEqual(42, reactContextMock->Args[0]["prop1"]); + TestCheckEqual(77u, reactContextMock->Args[0]["prop2"]); + + context.EmitJSEvent(L"module1", L"event1", [](IJSValueWriter const &writer) { + writer.WriteArrayBegin(); + WriteValue(writer, 10u); + WriteValue(writer, 19); + writer.WriteArrayEnd(); + }); + TestCheckEqual(10u, reactContextMock->Args[0]); + TestCheckEqual(19, reactContextMock->Args[1]); + } }; } // namespace ReactNativeTests diff --git a/vnext/Microsoft.ReactNative.Cxx/JSValueWriter.h b/vnext/Microsoft.ReactNative.Cxx/JSValueWriter.h index 80b6cb68748..71f8401eaee 100644 --- a/vnext/Microsoft.ReactNative.Cxx/JSValueWriter.h +++ b/vnext/Microsoft.ReactNative.Cxx/JSValueWriter.h @@ -257,9 +257,14 @@ inline void WriteArgs(IJSValueWriter const &writer, TArgs const &... args) noexc writer.WriteArrayEnd(); } +template , int> = 0> +inline JSValueArgWriter MakeJSValueArgWriter(T &&argWriter) noexcept { + return std::forward(argWriter); +} + template inline JSValueArgWriter MakeJSValueArgWriter(TArgs &&... args) noexcept { - return [args...](IJSValueWriter const &writer) noexcept { + return [&args...](IJSValueWriter const &writer) noexcept { WriteArgs(writer, args...); }; } diff --git a/vnext/Microsoft.ReactNative.Cxx/ReactContext.h b/vnext/Microsoft.ReactNative.Cxx/ReactContext.h index 3dc09ee14ad..b80b03e8ad0 100644 --- a/vnext/Microsoft.ReactNative.Cxx/ReactContext.h +++ b/vnext/Microsoft.ReactNative.Cxx/ReactContext.h @@ -32,42 +32,28 @@ struct ReactContext { return ReactPropertyBag{m_handle.Properties()}; } + // Call methodName JS function of module with moduleName. + // args are either function arguments or a single lambda with 'IJSValueWriter const&' argument. template void CallJSFunction(std::wstring_view moduleName, std::wstring_view methodName, TArgs &&... args) const noexcept { m_handle.CallJSFunction(moduleName, methodName, MakeJSValueArgWriter(std::forward(args)...)); } - void CallJSFunction( - std::wstring_view moduleName, - std::wstring_view methodName, - JSValueArgWriter const ¶msArgWriter) const noexcept { - m_handle.CallJSFunction(moduleName, methodName, paramsArgWriter); - } - + // Simplifies calls to CallJSFunction to emit events (method named 'emit'). + // Call eventName JS event of module with eventEmitterName. + // args are either function arguments or a single lambda with 'IJSValueWriter const&' argument. template void EmitJSEvent(std::wstring_view eventEmitterName, std::wstring_view eventName, TArgs &&... args) const noexcept { m_handle.EmitJSEvent(eventEmitterName, eventName, MakeJSValueArgWriter(std::forward(args)...)); } - void EmitJSEvent( - std::wstring_view eventEmitterName, - std::wstring_view eventName, - JSValueArgWriter const ¶msArgWriter) const noexcept { - m_handle.EmitJSEvent(eventEmitterName, eventName, paramsArgWriter); - } - + // Dispatch eventName event to the view. + // args are either function arguments or a single lambda with 'IJSValueWriter const&' argument. template void DispatchEvent(xaml::FrameworkElement const &view, std::wstring_view eventName, TArgs &&... args) const noexcept { m_handle.DispatchEvent(view, eventName, MakeJSValueArgWriter(std::forward(args)...)); } - void DispatchEvent( - xaml::FrameworkElement const &view, - std::wstring_view eventName, - JSValueArgWriter const ¶msArgWriter) const noexcept { - m_handle.DispatchEvent(view, eventName, paramsArgWriter); - } - friend bool operator==(ReactContext const &left, ReactContext const &right) noexcept { return left.m_handle == right.m_handle; } From d5173362962f380c76290d6c117228204efcd68f Mon Sep 17 00:00:00 2001 From: React-Native-Windows Bot <53619745+rnbot@users.noreply.github.com> Date: Sun, 17 May 2020 00:04:22 +0000 Subject: [PATCH 122/209] applying package updates ***NO_CI*** --- ...dows-2020-05-14-17-22-55-NonAbiValues.json | 8 ------ ...-windows-2020-05-15-14-54-00-jsxCrash.json | 8 ------ ...20-05-15-21-43-34-MS_FixReactContext2.json | 8 ------ packages/E2ETest/package.json | 2 +- .../package.json | 2 +- packages/playground/package.json | 2 +- vnext/CHANGELOG.json | 27 +++++++++++++++++++ vnext/CHANGELOG.md | 12 ++++++++- vnext/package.json | 2 +- 9 files changed, 42 insertions(+), 29 deletions(-) delete mode 100644 change/react-native-windows-2020-05-14-17-22-55-NonAbiValues.json delete mode 100644 change/react-native-windows-2020-05-15-14-54-00-jsxCrash.json delete mode 100644 change/react-native-windows-2020-05-15-21-43-34-MS_FixReactContext2.json diff --git a/change/react-native-windows-2020-05-14-17-22-55-NonAbiValues.json b/change/react-native-windows-2020-05-14-17-22-55-NonAbiValues.json deleted file mode 100644 index 1a3c137c8a2..00000000000 --- a/change/react-native-windows-2020-05-14-17-22-55-NonAbiValues.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "ReactNonAbiValue for IReactPropertyBag non-ABI values", - "packageName": "react-native-windows", - "email": "vmorozov@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-15T00:22:54.871Z" -} diff --git a/change/react-native-windows-2020-05-15-14-54-00-jsxCrash.json b/change/react-native-windows-2020-05-15-14-54-00-jsxCrash.json deleted file mode 100644 index 9d5cd2732b6..00000000000 --- a/change/react-native-windows-2020-05-15-14-54-00-jsxCrash.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Prevent hard crash on invalid jsx (button inside text e.g.)", - "packageName": "react-native-windows", - "email": "asklar@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-15T21:54:00.551Z" -} diff --git a/change/react-native-windows-2020-05-15-21-43-34-MS_FixReactContext2.json b/change/react-native-windows-2020-05-15-21-43-34-MS_FixReactContext2.json deleted file mode 100644 index 44a07b8611e..00000000000 --- a/change/react-native-windows-2020-05-15-21-43-34-MS_FixReactContext2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "prerelease", - "comment": "Fixed ReactContext CallJSFunction and EmitJSEvent", - "packageName": "react-native-windows", - "email": "vmorozov@microsoft.com", - "dependentChangeType": "patch", - "date": "2020-05-16T04:43:34.199Z" -} diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json index 055ddd31458..9c8b0d0a31f 100644 --- a/packages/E2ETest/package.json +++ b/packages/E2ETest/package.json @@ -25,7 +25,7 @@ "prompt-sync": "^4.2.0", "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.68" + "react-native-windows": "0.0.0-master.69" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json index 4103ed80df3..07c6c771d97 100644 --- a/packages/microsoft-reactnative-sampleapps/package.json +++ b/packages/microsoft-reactnative-sampleapps/package.json @@ -16,7 +16,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.68" + "react-native-windows": "0.0.0-master.69" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/packages/playground/package.json b/packages/playground/package.json index 48a0e608b99..815b80d355f 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -12,7 +12,7 @@ "dependencies": { "react": "16.11.0", "react-native": "0.62.2", - "react-native-windows": "0.0.0-master.68" + "react-native-windows": "0.0.0-master.69" }, "devDependencies": { "@babel/core": "^7.8.4", diff --git a/vnext/CHANGELOG.json b/vnext/CHANGELOG.json index b5d4d3c66c1..aad661f29b8 100644 --- a/vnext/CHANGELOG.json +++ b/vnext/CHANGELOG.json @@ -1,6 +1,33 @@ { "name": "react-native-windows", "entries": [ + { + "date": "Sun, 17 May 2020 00:04:22 GMT", + "tag": "react-native-windows_v0.0.0-master.69", + "version": "0.0.0-master.69", + "comments": { + "prerelease": [ + { + "comment": "ReactNonAbiValue for IReactPropertyBag non-ABI values", + "author": "vmorozov@microsoft.com", + "commit": "251f5205dc5cb98797b9f1c31c3d5a537321c0f1", + "package": "react-native-windows" + }, + { + "comment": "Prevent hard crash on invalid jsx (button inside text e.g.)", + "author": "asklar@microsoft.com", + "commit": "ce937eb0cef0812aa0b79d7017c7ae53fb566961", + "package": "react-native-windows" + }, + { + "comment": "Fixed ReactContext CallJSFunction and EmitJSEvent", + "author": "vmorozov@microsoft.com", + "commit": "06921271e82e07b7eb94d5808103367b85a76a7d", + "package": "react-native-windows" + } + ] + } + }, { "date": "Sat, 16 May 2020 00:04:28 GMT", "tag": "react-native-windows_v0.0.0-master.68", diff --git a/vnext/CHANGELOG.md b/vnext/CHANGELOG.md index 0562d0e3499..06981257fb8 100644 --- a/vnext/CHANGELOG.md +++ b/vnext/CHANGELOG.md @@ -1,9 +1,19 @@ # Change Log - react-native-windows -This log was last generated on Sat, 16 May 2020 00:04:28 GMT and should not be manually modified. +This log was last generated on Sun, 17 May 2020 00:04:22 GMT and should not be manually modified. +## 0.0.0-master.69 + +Sun, 17 May 2020 00:04:22 GMT + +### Changes + +- ReactNonAbiValue for IReactPropertyBag non-ABI values (vmorozov@microsoft.com) +- Prevent hard crash on invalid jsx (button inside text e.g.) (asklar@microsoft.com) +- Fixed ReactContext CallJSFunction and EmitJSEvent (vmorozov@microsoft.com) + ## 0.0.0-master.68 Sat, 16 May 2020 00:04:28 GMT diff --git a/vnext/package.json b/vnext/package.json index d287e7698af..633744a1aa2 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -1,6 +1,6 @@ { "name": "react-native-windows", - "version": "0.0.0-master.68", + "version": "0.0.0-master.69", "license": "MIT", "repository": { "type": "git", From efa28f0447467b4269114c037ba90036340a870d Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Sun, 17 May 2020 20:39:57 -0700 Subject: [PATCH 123/209] Ensure Override Prompts Create Integral Issue Numbers (#4931) After reported issues I recently moved `override-tools` to use `inquirer` instead of `prompts` for asking for override details. During validation I missed that we now assign an issue number to be text instead of a parsed integer. This propagates to the manifest when adding a new issue number, leading to an assumed invalid manifest. Make sure we treat the issue number as integral when returning it. Additionally make sure to specify radix while parsing in all places. Validated integral issues are added to the manifest instead of strings. --- packages/override-tools/src/OverridePrompt.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/override-tools/src/OverridePrompt.ts b/packages/override-tools/src/OverridePrompt.ts index 4f304526413..4e404b931e6 100644 --- a/packages/override-tools/src/OverridePrompt.ts +++ b/packages/override-tools/src/OverridePrompt.ts @@ -82,7 +82,7 @@ async function promptDerivedDetails(): Promise

{ message: 'Github Issue Number:', }, ]); - issue = issueResponse.issue; + issue = Number.parseInt(issueResponse.issue, 10); } const baseFileResponse = await inquirer.prompt([ @@ -110,11 +110,12 @@ async function promptPatchDetails(overrideFile: string): Promise
{ ]); const baseFile = overrideFile.replace(WIN_PLATFORM_EXT, '.js'); - return {type: 'patch', baseFile, issue: response.issue}; + return {type: 'patch', baseFile, issue: Number.parseInt(response.issue, 10)}; } function validateIssueNumber(answer: string): boolean | string { return ( - Number.isInteger(Number.parseInt(answer)) || 'Github issue must be a number' + Number.isInteger(Number.parseInt(answer, 10)) || + 'Github issue must be a number' ); } From c9d9d5c9fa59e28fe0c33c203feb2e5716c5fb6a Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Mon, 18 May 2020 08:06:44 -0700 Subject: [PATCH 124/209] Add support for 0..n args in native module callbacks (#4929) * Support 0..n args in native module callbacks * Change files --- ...0-05-17-09-26-39-MS_CallbackMultiArgs.json | 8 + .../NativeModuleTest.cpp | 139 +++++++ .../NoAttributeNativeModuleTest.cpp | 139 +++++++ .../ReactModuleBuilderMock.h | 110 ++---- .../TurboModuleTest.cpp | 357 ++++++++++++++---- .../Microsoft.ReactNative.Cxx/NativeModules.h | 2 + ...osoft.ReactNative.IntegrationTests.vcxproj | 1 - .../NativeModuleTest.cs | 259 ++++++++++--- .../NoAttributeNativeModuleTest.cs | 350 ++++++++++++++--- .../ReactModuleBuilderMock.cs | 52 ++- .../JSValueGenerator.cs | 12 +- .../ReactMethodInfo.cs | 25 +- 12 files changed, 1162 insertions(+), 292 deletions(-) create mode 100644 change/react-native-windows-2020-05-17-09-26-39-MS_CallbackMultiArgs.json diff --git a/change/react-native-windows-2020-05-17-09-26-39-MS_CallbackMultiArgs.json b/change/react-native-windows-2020-05-17-09-26-39-MS_CallbackMultiArgs.json new file mode 100644 index 00000000000..3a160551071 --- /dev/null +++ b/change/react-native-windows-2020-05-17-09-26-39-MS_CallbackMultiArgs.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Support 0..n args in native module callbacks", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-05-17T16:26:39.781Z" +} diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp index cb15f7eaa11..8ab06a582a4 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp @@ -152,6 +152,21 @@ struct SimpleNativeModule { resolve("Static Hello_2"); } + REACT_METHOD(CallbackZeroArgs) + void CallbackZeroArgs(std::function const &resolve) noexcept { + resolve(); + } + + REACT_METHOD(CallbackTwoArgs) + void CallbackTwoArgs(std::function const &resolve) noexcept { + resolve(1, 2); + } + + REACT_METHOD(CallbackThreeArgs) + void CallbackThreeArgs(std::function const &resolve) noexcept { + resolve(1, 2, "Hello"); + } + REACT_METHOD(DivideCallbacks) void DivideCallbacks( int x, @@ -312,6 +327,44 @@ struct SimpleNativeModule { reject("Goodbye"); } + REACT_METHOD(TwoCallbacksZeroArgs1) + void TwoCallbacksZeroArgs1(std::function const &resolve, std::function const & /*reject*/) noexcept { + resolve(); + } + + REACT_METHOD(TwoCallbacksZeroArgs2) + void TwoCallbacksZeroArgs2(std::function const & /*resolve*/, std::function const &reject) noexcept { + reject(); + } + + REACT_METHOD(TwoCallbacksTwoArgs1) + void TwoCallbacksTwoArgs1( + std::function const &resolve, + std::function const & /*reject*/) noexcept { + resolve(1, 2); + } + + REACT_METHOD(TwoCallbacksTwoArgs2) + void TwoCallbacksTwoArgs2( + std::function const & /*resolve*/, + std::function const &reject) noexcept { + reject(1, 2); + } + + REACT_METHOD(TwoCallbacksThreeArgs1) + void TwoCallbacksThreeArgs1( + std::function const &resolve, + std::function const & /*reject*/) noexcept { + resolve(1, 2, "Hello"); + } + + REACT_METHOD(TwoCallbacksThreeArgs2) + void TwoCallbacksThreeArgs2( + std::function const & /*resolve*/, + std::function const &reject) noexcept { + reject(1, 2, "Hello"); + } + REACT_METHOD(DividePromise) void DividePromise(int x, int y, React::ReactPromise const &result) noexcept { if (y != 0) { @@ -746,6 +799,30 @@ TEST_CLASS (NativeModuleTest) { TestCheck(m_builderMock.IsResolveCallbackCalled()); } + TEST_METHOD(TestMethodCall_CallbackZeroArgs) { + m_builderMock.Call1(L"CallbackZeroArgs", std::function([]() noexcept {})); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_CallbackTwoArgs) { + m_builderMock.Call1(L"CallbackTwoArgs", std::function([](int p1, int p2) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_CallbackThreeArgs) { + m_builderMock.Call1( + L"CallbackThreeArgs", + std::function([](int p1, int p2, std::string const &p3) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + TestCheckEqual("Hello", p3); + })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + TEST_METHOD(TestMethodCall_DivideCallbacks) { m_builderMock.Call2( L"DivideCallbacks", @@ -990,6 +1067,68 @@ TEST_CLASS (NativeModuleTest) { TestCheck(m_builderMock.IsRejectCallbackCalled()); } + TEST_METHOD(TestMethodCall_TwoCallbacksZeroArgs1) { + m_builderMock.Call2(L"TwoCallbacksZeroArgs1", std::function([]() noexcept {}), std::function([ + ]() noexcept { TestCheckFail(); })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksZeroArgs2) { + m_builderMock.Call2( + L"TwoCallbacksZeroArgs2", + std::function([]() noexcept { TestCheckFail(); }), + std::function([]() noexcept {})); + TestCheck(m_builderMock.IsRejectCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksTwoArgs1) { + m_builderMock.Call2( + L"TwoCallbacksTwoArgs1", + std::function([](int p1, int p2) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + }), + std::function([](int /*p1*/, int /*p2*/) noexcept { TestCheckFail(); })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksTwoArgs2) { + m_builderMock.Call2( + L"TwoCallbacksTwoArgs2", + std::function([](int /*p1*/, int /*p2*/) noexcept { TestCheckFail(); }), + std::function([](int p1, int p2) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + })); + TestCheck(m_builderMock.IsRejectCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksThreeArgs1) { + m_builderMock.Call2( + L"TwoCallbacksThreeArgs1", + std::function([](int p1, int p2, std::string const &p3) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + TestCheckEqual("Hello", p3); + }), + std::function( + [](int /*p1*/, int /*p2*/, std::string const & /*p3*/) noexcept { TestCheckFail(); })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksThreeArgs2) { + m_builderMock.Call2( + L"TwoCallbacksThreeArgs2", + std::function( + [](int /*p1*/, int /*p2*/, std::string const & /*p3*/) noexcept { TestCheckFail(); }), + std::function([](int p1, int p2, std::string const &p3) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + TestCheckEqual("Hello", p3); + })); + TestCheck(m_builderMock.IsRejectCallbackCalled()); + } + TEST_METHOD(TestMethodCall_DividePromise) { m_builderMock.Call2( L"DividePromise", diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp index dd4859ab2df..1496c3f355d 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp @@ -135,6 +135,18 @@ struct SimpleNativeModule2 { resolve("Static Hello_2"); } + void CallbackZeroArgs(std::function const &resolve) noexcept { + resolve(); + } + + void CallbackTwoArgs(std::function const &resolve) noexcept { + resolve(1, 2); + } + + void CallbackThreeArgs(std::function const &resolve) noexcept { + resolve(1, 2, "Hello"); + } + void DivideCallbacks( int x, int y, @@ -281,6 +293,38 @@ struct SimpleNativeModule2 { reject("Goodbye"); } + void TwoCallbacksZeroArgs1(std::function const &resolve, std::function const & /*reject*/) noexcept { + resolve(); + } + + void TwoCallbacksZeroArgs2(std::function const & /*resolve*/, std::function const &reject) noexcept { + reject(); + } + + void TwoCallbacksTwoArgs1( + std::function const &resolve, + std::function const & /*reject*/) noexcept { + resolve(1, 2); + } + + void TwoCallbacksTwoArgs2( + std::function const & /*resolve*/, + std::function const &reject) noexcept { + reject(1, 2); + } + + void TwoCallbacksThreeArgs1( + std::function const &resolve, + std::function const & /*reject*/) noexcept { + resolve(1, 2, "Hello"); + } + + void TwoCallbacksThreeArgs2( + std::function const & /*resolve*/, + std::function const &reject) noexcept { + reject(1, 2, "Hello"); + } + void DividePromise(int x, int y, React::ReactPromise const &result) noexcept { if (y != 0) { result.Resolve(x / y); @@ -535,6 +579,9 @@ void GetReactModuleInfo(SimpleNativeModule2 *, React::ReactModuleBuilder([]() noexcept {})); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_CallbackTwoArgs) { + m_builderMock.Call1(L"CallbackTwoArgs", std::function([](int p1, int p2) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_CallbackThreeArgs) { + m_builderMock.Call1( + L"CallbackThreeArgs", + std::function([](int p1, int p2, std::string const &p3) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + TestCheckEqual("Hello", p3); + })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + TEST_METHOD(TestMethodCall_DivideCallbacks) { m_builderMock.Call2( L"DivideCallbacks", @@ -997,6 +1074,68 @@ TEST_CLASS (NoAttributeNativeModuleTest) { TestCheck(m_builderMock.IsRejectCallbackCalled()); } + TEST_METHOD(TestMethodCall_TwoCallbacksZeroArgs1) { + m_builderMock.Call2(L"TwoCallbacksZeroArgs1", std::function([]() noexcept {}), std::function([ + ]() noexcept { TestCheckFail(); })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksZeroArgs2) { + m_builderMock.Call2( + L"TwoCallbacksZeroArgs2", + std::function([]() noexcept { TestCheckFail(); }), + std::function([]() noexcept {})); + TestCheck(m_builderMock.IsRejectCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksTwoArgs1) { + m_builderMock.Call2( + L"TwoCallbacksTwoArgs1", + std::function([](int p1, int p2) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + }), + std::function([](int /*p1*/, int /*p2*/) noexcept { TestCheckFail(); })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksTwoArgs2) { + m_builderMock.Call2( + L"TwoCallbacksTwoArgs2", + std::function([](int /*p1*/, int /*p2*/) noexcept { TestCheckFail(); }), + std::function([](int p1, int p2) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + })); + TestCheck(m_builderMock.IsRejectCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksThreeArgs1) { + m_builderMock.Call2( + L"TwoCallbacksThreeArgs1", + std::function([](int p1, int p2, std::string const &p3) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + TestCheckEqual("Hello", p3); + }), + std::function( + [](int /*p1*/, int /*p2*/, std::string const & /*p3*/) noexcept { TestCheckFail(); })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksThreeArgs2) { + m_builderMock.Call2( + L"TwoCallbacksThreeArgs2", + std::function( + [](int /*p1*/, int /*p2*/, std::string const & /*p3*/) noexcept { TestCheckFail(); }), + std::function([](int p1, int p2, std::string const &p3) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + TestCheckEqual("Hello", p3); + })); + TestCheck(m_builderMock.IsRejectCallbackCalled()); + } + TEST_METHOD(TestMethodCall_DividePromise) { m_builderMock.Call2( L"DividePromise", diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h index 28da1d8c0fd..8fc22495bba 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h @@ -9,6 +9,7 @@ #include #include "CppWinRTIncludes.h" #include "JSValue.h" +#include "NativeModules.h" #undef GetCurrentTime @@ -22,26 +23,15 @@ struct ReactModuleBuilderMock { template void Call0(std::wstring const &methodName, TArgs &&... args) noexcept; - template + template Mso::Future - Call1(std::wstring const &methodName, std::function &&resolve, TArgs &&... args) noexcept; + Call1(std::wstring const &methodName, std::function &&resolve, TArgs &&... args) noexcept; - template - Mso::Future - Call1(std::wstring const &methodName, std::function const &resolve, TArgs &&... args) noexcept; - - template + template Mso::Future Call2( std::wstring const &methodName, - std::function const &resolve, - std::function const &reject, - TArgs &&... args) noexcept; - - template - Mso::Future Call2( - std::wstring const &methodName, - std::function const &resolve, - std::function const &reject, + std::function const &resolve, + std::function const &reject, TArgs &&... args) noexcept; template @@ -95,15 +85,16 @@ struct ReactModuleBuilderMock { static IJSValueReader ArgReader(TArgs &&... args) noexcept; static IJSValueReader CreateArgReader(std::function const &argWriter) noexcept; - template + template MethodResultCallback ResolveCallback( - std::function const &resolve, + std::function const &resolve, + std::index_sequence, Mso::Promise const &promise) noexcept; - MethodResultCallback ResolveCallback( - std::function const &resolve, + template + MethodResultCallback RejectCallback( + std::function const &reject, + std::index_sequence, Mso::Promise const &promise) noexcept; - template - MethodResultCallback RejectCallback(std::function const &reject, Mso::Promise const &promise) noexcept; private: IReactContext m_reactContext{nullptr}; @@ -167,60 +158,35 @@ inline void ReactModuleBuilderMock::Call0(std::wstring const &methodName, TArgs } } -template -inline Mso::Future ReactModuleBuilderMock::Call1( - std::wstring const &methodName, - std::function &&resolve, - TArgs &&... args) noexcept { - Mso::Promise promise; - if (auto method = GetMethod1(methodName)) { - method(ArgReader(std::forward(args)...), ArgWriter(), ResolveCallback(resolve, promise), nullptr); - } - return promise.AsFuture(); -} - -template +template inline Mso::Future ReactModuleBuilderMock::Call1( std::wstring const &methodName, - std::function const &resolve, + std::function &&resolve, TArgs &&... args) noexcept { Mso::Promise promise; if (auto method = GetMethod1(methodName)) { - method(ArgReader(std::forward(args)...), ArgWriter(), ResolveCallback(resolve, promise), nullptr); - } - return promise.AsFuture(); -} - -template -inline Mso::Future ReactModuleBuilderMock::Call2( - std::wstring const &methodName, - std::function const &resolve, - std::function const &reject, - TArgs &&... args) noexcept { - Mso::Promise promise; - if (auto method = GetMethod2(methodName)) { method( ArgReader(std::forward(args)...), ArgWriter(), - ResolveCallback(resolve, promise), - RejectCallback(reject, promise)); + ResolveCallback(resolve, std::make_index_sequence{}, promise), + nullptr); } return promise.AsFuture(); } -template +template inline Mso::Future ReactModuleBuilderMock::Call2( std::wstring const &methodName, - std::function const &resolve, - std::function const &reject, + std::function const &resolve, + std::function const &reject, TArgs &&... args) noexcept { Mso::Promise promise; if (auto method = GetMethod2(methodName)) { method( ArgReader(std::forward(args)...), ArgWriter(), - ResolveCallback(resolve, promise), - RejectCallback(reject, promise)); + ResolveCallback(resolve, std::make_index_sequence{}, promise), + RejectCallback(reject, std::make_index_sequence{}, promise)); } return promise.AsFuture(); } @@ -242,37 +208,29 @@ inline /*static*/ IJSValueReader ReactModuleBuilderMock::ArgReader(TArgs &&... a }); } -template +template inline MethodResultCallback ReactModuleBuilderMock::ResolveCallback( - std::function const &resolve, + std::function const &resolve, + std::index_sequence, Mso::Promise const &promise) noexcept { return [ this, resolve, promise ](IJSValueWriter const &writer) noexcept { - std::remove_const_t> arg; - ReadArgs(MakeJSValueTreeReader(TakeJSValue(writer)), arg); - resolve(arg); - m_isResolveCallbackCalled = true; - promise.TrySetValue(true); - }; -} - -inline MethodResultCallback ReactModuleBuilderMock::ResolveCallback( - std::function const &resolve, - Mso::Promise const &promise) noexcept { - return [ this, resolve, promise ](IJSValueWriter const & /*writer*/) noexcept { - resolve(); + std::tuple...> args; + ReadArgs(MakeJSValueTreeReader(TakeJSValue(writer)), std::get(args)...); + resolve(std::get(args)...); m_isResolveCallbackCalled = true; promise.TrySetValue(true); }; } -template +template inline MethodResultCallback ReactModuleBuilderMock::RejectCallback( - std::function const &reject, + std::function const &reject, + std::index_sequence, Mso::Promise const &promise) noexcept { return [ this, reject, promise ](IJSValueWriter const &writer) noexcept { - std::remove_const_t> arg; - ReadArgs(MakeJSValueTreeReader(TakeJSValue(writer)), arg); - reject(arg); + std::tuple...> args; + ReadArgs(MakeJSValueTreeReader(TakeJSValue(writer)), std::get(args)...); + reject(std::get(args)...); m_isRejectCallbackCalled = true; promise.TrySetValue(false); }; diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp index f9f5c597724..f7f380912dd 100644 --- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp +++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp @@ -151,6 +151,21 @@ struct MyTurboModule { resolve("Static Hello_2"); } + REACT_METHOD(CallbackZeroArgs) + void CallbackZeroArgs(std::function const &resolve) noexcept { + resolve(); + } + + REACT_METHOD(CallbackTwoArgs) + void CallbackTwoArgs(std::function const &resolve) noexcept { + resolve(1, 2); + } + + REACT_METHOD(CallbackThreeArgs) + void CallbackThreeArgs(std::function const &resolve) noexcept { + resolve(1, 2, "Hello"); + } + REACT_METHOD(DivideCallbacks) void DivideCallbacks( int x, @@ -311,6 +326,44 @@ struct MyTurboModule { reject("Goodbye"); } + REACT_METHOD(TwoCallbacksZeroArgs1) + void TwoCallbacksZeroArgs1(std::function const &resolve, std::function const & /*reject*/) noexcept { + resolve(); + } + + REACT_METHOD(TwoCallbacksZeroArgs2) + void TwoCallbacksZeroArgs2(std::function const & /*resolve*/, std::function const &reject) noexcept { + reject(); + } + + REACT_METHOD(TwoCallbacksTwoArgs1) + void TwoCallbacksTwoArgs1( + std::function const &resolve, + std::function const & /*reject*/) noexcept { + resolve(1, 2); + } + + REACT_METHOD(TwoCallbacksTwoArgs2) + void TwoCallbacksTwoArgs2( + std::function const & /*resolve*/, + std::function const &reject) noexcept { + reject(1, 2); + } + + REACT_METHOD(TwoCallbacksThreeArgs1) + void TwoCallbacksThreeArgs1( + std::function const &resolve, + std::function const & /*reject*/) noexcept { + resolve(1, 2, "Hello"); + } + + REACT_METHOD(TwoCallbacksThreeArgs2) + void TwoCallbacksThreeArgs2( + std::function const & /*resolve*/, + std::function const &reject) noexcept { + reject(1, 2, "Hello"); + } + REACT_METHOD(DividePromise) void DividePromise(int x, int y, React::ReactPromise const &result) noexcept { if (y != 0) { @@ -618,42 +671,55 @@ struct MyTurboModuleSpec : winrt::Microsoft::ReactNative::TurboModuleSpec { Method) noexcept>{21, L"StaticNegateDispatchQueueCallback"}, Method) noexcept>{22, L"StaticNegateFutureCallback"}, Method) noexcept>{23, L"StaticSayHelloCallback"}, - Method, Callback) noexcept>{24, L"DivideCallbacks"}, - Method, Callback) noexcept>{25, L"NegateCallbacks"}, - Method, Callback) noexcept>{26, L"NegateAsyncCallbacks"}, - Method, Callback) noexcept>{27, L"NegateDispatchQueueCallbacks"}, - Method, Callback) noexcept>{28, L"NegateFutureCallbacks"}, - Method, Callback) noexcept>{29, L"ResolveSayHelloCallbacks"}, - Method, Callback) noexcept>{30, L"RejectSayHelloCallbacks"}, - Method, Callback) noexcept>{31, L"StaticDivideCallbacks"}, - Method, Callback) noexcept>{32, L"StaticNegateCallbacks"}, - Method, Callback) noexcept>{33, L"StaticNegateAsyncCallbacks"}, - Method, Callback) noexcept>{34, L"StaticNegateDispatchQueueCallbacks"}, - Method, Callback) noexcept>{35, L"StaticNegateFutureCallbacks"}, - Method, Callback) noexcept>{36, L"StaticResolveSayHelloCallbacks"}, - Method, Callback) noexcept>{37, L"StaticRejectSayHelloCallbacks"}, - Method) noexcept>{38, L"DividePromise"}, - Method) noexcept>{39, L"NegatePromise"}, - Method) noexcept>{40, L"NegateAsyncPromise"}, - Method) noexcept>{41, L"NegateDispatchQueuePromise"}, - Method) noexcept>{42, L"NegateFuturePromise"}, - Method) noexcept>{43, L"voidPromise"}, - Method) noexcept>{44, L"ResolveSayHelloPromise"}, - Method) noexcept>{45, L"RejectSayHelloPromise"}, - Method) noexcept>{46, L"StaticDividePromise"}, - Method) noexcept>{47, L"StaticNegatePromise"}, - Method) noexcept>{48, L"StaticNegateAsyncPromise"}, - Method) noexcept>{49, L"StaticNegateDispatchQueuePromise"}, - Method) noexcept>{50, L"StaticNegateFuturePromise"}, - Method) noexcept>{51, L"staticVoidPromise"}, - Method) noexcept>{52, L"StaticResolveSayHelloPromise"}, - Method) noexcept>{53, L"StaticRejectSayHelloPromise"}, - SyncMethod{54, L"AddSync"}, - SyncMethod{55, L"NegateSync"}, - SyncMethod{56, L"SayHelloSync"}, - SyncMethod{57, L"StaticAddSync"}, - SyncMethod{58, L"StaticNegateSync"}, - SyncMethod{59, L"StaticSayHelloSync"}, + Method) noexcept>{24, L"CallbackZeroArgs"}, + Method) noexcept>{25, L"CallbackTwoArgs"}, + Method) noexcept>{26, L"CallbackThreeArgs"}, + Method, Callback) noexcept>{27, L"DivideCallbacks"}, + Method, Callback) noexcept>{28, L"NegateCallbacks"}, + Method, Callback) noexcept>{29, L"NegateAsyncCallbacks"}, + Method, Callback) noexcept>{30, L"NegateDispatchQueueCallbacks"}, + Method, Callback) noexcept>{31, L"NegateFutureCallbacks"}, + Method, Callback) noexcept>{32, L"ResolveSayHelloCallbacks"}, + Method, Callback) noexcept>{33, L"RejectSayHelloCallbacks"}, + Method, Callback) noexcept>{34, L"StaticDivideCallbacks"}, + Method, Callback) noexcept>{35, L"StaticNegateCallbacks"}, + Method, Callback) noexcept>{36, L"StaticNegateAsyncCallbacks"}, + Method, Callback) noexcept>{37, L"StaticNegateDispatchQueueCallbacks"}, + Method, Callback) noexcept>{38, L"StaticNegateFutureCallbacks"}, + Method, Callback) noexcept>{39, L"StaticResolveSayHelloCallbacks"}, + Method, Callback) noexcept>{40, L"StaticRejectSayHelloCallbacks"}, + Method, Callback<>) noexcept>{41, L"TwoCallbacksZeroArgs1"}, + Method, Callback<>) noexcept>{42, L"TwoCallbacksZeroArgs2"}, + Method, Callback) noexcept>{43, L"TwoCallbacksTwoArgs1"}, + Method, Callback) noexcept>{44, L"TwoCallbacksTwoArgs2"}, + Method, Callback) noexcept>{ + 45, + L"TwoCallbacksThreeArgs1"}, + Method, Callback) noexcept>{ + 46, + L"TwoCallbacksThreeArgs2"}, + Method) noexcept>{47, L"DividePromise"}, + Method) noexcept>{48, L"NegatePromise"}, + Method) noexcept>{49, L"NegateAsyncPromise"}, + Method) noexcept>{50, L"NegateDispatchQueuePromise"}, + Method) noexcept>{51, L"NegateFuturePromise"}, + Method) noexcept>{52, L"voidPromise"}, + Method) noexcept>{53, L"ResolveSayHelloPromise"}, + Method) noexcept>{54, L"RejectSayHelloPromise"}, + Method) noexcept>{55, L"StaticDividePromise"}, + Method) noexcept>{56, L"StaticNegatePromise"}, + Method) noexcept>{57, L"StaticNegateAsyncPromise"}, + Method) noexcept>{58, L"StaticNegateDispatchQueuePromise"}, + Method) noexcept>{59, L"StaticNegateFuturePromise"}, + Method) noexcept>{60, L"staticVoidPromise"}, + Method) noexcept>{61, L"StaticResolveSayHelloPromise"}, + Method) noexcept>{62, L"StaticRejectSayHelloPromise"}, + SyncMethod{63, L"AddSync"}, + SyncMethod{64, L"NegateSync"}, + SyncMethod{65, L"SayHelloSync"}, + SyncMethod{66, L"StaticAddSync"}, + SyncMethod{67, L"StaticNegateSync"}, + SyncMethod{68, L"StaticSayHelloSync"}, }; template @@ -866,241 +932,304 @@ struct MyTurboModuleSpec : winrt::Microsoft::ReactNative::TurboModuleSpec { " REACT_METHOD(StaticSayHelloCallback) static winrt::fire_and_forget StaticSayHelloCallback(ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( 24, + "CallbackZeroArgs", + " REACT_METHOD(CallbackZeroArgs) void CallbackZeroArgs(ReactCallback<>) noexcept {/*implementation*/}\n" + " REACT_METHOD(CallbackZeroArgs) winrt::fire_and_forget CallbackZeroArgs(ReactCallback<>) noexcept {/*implementation*/}\n" + " REACT_METHOD(CallbackZeroArgs) static void CallbackZeroArgs(ReactCallback<>) noexcept {/*implementation*/}\n" + " REACT_METHOD(CallbackZeroArgs) static winrt::fire_and_forget CallbackZeroArgs(ReactCallback<>) noexcept {/*implementation*/}\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 25, + "CallbackTwoArgs", + " REACT_METHOD(CallbackTwoArgs) void CallbackTwoArgs(ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(CallbackTwoArgs) winrt::fire_and_forget CallbackTwoArgs(ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(CallbackTwoArgs) static void CallbackTwoArgs(ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(CallbackTwoArgs) static winrt::fire_and_forget CallbackTwoArgs(ReactCallback) noexcept {/*implementation*/}\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 26, + "CallbackThreeArgs", + " REACT_METHOD(CallbackThreeArgs) void CallbackThreeArgs(ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(CallbackThreeArgs) winrt::fire_and_forget CallbackThreeArgs(ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(CallbackThreeArgs) static void CallbackThreeArgs(ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(CallbackThreeArgs) static winrt::fire_and_forget CallbackThreeArgs(ReactCallback) noexcept {/*implementation*/}\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 27, "DivideCallbacks", " REACT_METHOD(DivideCallbacks) void DivideCallbacks(int, int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(DivideCallbacks) winrt::fire_and_forget DivideCallbacks(int, int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(DivideCallbacks) static void DivideCallbacks(int, int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(DivideCallbacks) static winrt::fire_and_forget DivideCallbacks(int, int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 25, + 28, "NegateCallbacks", " REACT_METHOD(NegateCallbacks) void NegateCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateCallbacks) winrt::fire_and_forget NegateCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateCallbacks) static void NegateCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateCallbacks) static winrt::fire_and_forget NegateCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 26, + 29, "NegateAsyncCallbacks", " REACT_METHOD(NegateAsyncCallbacks) void NegateAsyncCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateAsyncCallbacks) winrt::fire_and_forget NegateAsyncCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateAsyncCallbacks) static void NegateAsyncCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateAsyncCallbacks) static winrt::fire_and_forget NegateAsyncCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 27, + 30, "NegateDispatchQueueCallbacks", " REACT_METHOD(NegateDispatchQueueCallbacks) void NegateDispatchQueueCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateDispatchQueueCallbacks) winrt::fire_and_forget NegateDispatchQueueCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateDispatchQueueCallbacks) static void NegateDispatchQueueCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateDispatchQueueCallbacks) static winrt::fire_and_forget NegateDispatchQueueCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 28, + 31, "NegateFutureCallbacks", " REACT_METHOD(NegateFutureCallbacks) void NegateFutureCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateFutureCallbacks) winrt::fire_and_forget NegateFutureCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateFutureCallbacks) static void NegateFutureCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateFutureCallbacks) static winrt::fire_and_forget NegateFutureCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 29, + 32, "ResolveSayHelloCallbacks", " REACT_METHOD(ResolveSayHelloCallbacks) void ResolveSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(ResolveSayHelloCallbacks) winrt::fire_and_forget ResolveSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(ResolveSayHelloCallbacks) static void ResolveSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(ResolveSayHelloCallbacks) static winrt::fire_and_forget ResolveSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 30, + 33, "RejectSayHelloCallbacks", " REACT_METHOD(RejectSayHelloCallbacks) void RejectSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(RejectSayHelloCallbacks) winrt::fire_and_forget RejectSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(RejectSayHelloCallbacks) static void RejectSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(RejectSayHelloCallbacks) static winrt::fire_and_forget RejectSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 31, + 34, "StaticDivideCallbacks", " REACT_METHOD(StaticDivideCallbacks) void StaticDivideCallbacks(int, int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticDivideCallbacks) winrt::fire_and_forget StaticDivideCallbacks(int, int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticDivideCallbacks) static void StaticDivideCallbacks(int, int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticDivideCallbacks) static winrt::fire_and_forget StaticDivideCallbacks(int, int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 32, + 35, "StaticNegateCallbacks", " REACT_METHOD(StaticNegateCallbacks) void StaticNegateCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateCallbacks) winrt::fire_and_forget StaticNegateCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateCallbacks) static void StaticNegateCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateCallbacks) static winrt::fire_and_forget StaticNegateCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 33, + 36, "StaticNegateAsyncCallbacks", " REACT_METHOD(StaticNegateAsyncCallbacks) void StaticNegateAsyncCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateAsyncCallbacks) winrt::fire_and_forget StaticNegateAsyncCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateAsyncCallbacks) static void StaticNegateAsyncCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateAsyncCallbacks) static winrt::fire_and_forget StaticNegateAsyncCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 34, + 37, "StaticNegateDispatchQueueCallbacks", " REACT_METHOD(StaticNegateDispatchQueueCallbacks) void StaticNegateDispatchQueueCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateDispatchQueueCallbacks) winrt::fire_and_forget StaticNegateDispatchQueueCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateDispatchQueueCallbacks) static void StaticNegateDispatchQueueCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateDispatchQueueCallbacks) static winrt::fire_and_forget StaticNegateDispatchQueueCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 35, + 38, "StaticNegateFutureCallbacks", " REACT_METHOD(StaticNegateFutureCallbacks) void StaticNegateFutureCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateFutureCallbacks) winrt::fire_and_forget StaticNegateFutureCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateFutureCallbacks) static void StaticNegateFutureCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateFutureCallbacks) static winrt::fire_and_forget StaticNegateFutureCallbacks(int, ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 36, + 39, "StaticResolveSayHelloCallbacks", " REACT_METHOD(StaticResolveSayHelloCallbacks) void StaticResolveSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticResolveSayHelloCallbacks) winrt::fire_and_forget StaticResolveSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticResolveSayHelloCallbacks) static void StaticResolveSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticResolveSayHelloCallbacks) static winrt::fire_and_forget StaticResolveSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 37, + 40, "StaticRejectSayHelloCallbacks", " REACT_METHOD(StaticRejectSayHelloCallbacks) void StaticRejectSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticRejectSayHelloCallbacks) winrt::fire_and_forget StaticRejectSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticRejectSayHelloCallbacks) static void StaticRejectSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticRejectSayHelloCallbacks) static winrt::fire_and_forget StaticRejectSayHelloCallbacks(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 38, + 41, + "TwoCallbacksZeroArgs1", + " REACT_METHOD(TwoCallbacksZeroArgs1) void TwoCallbacksZeroArgs1(ReactCallback<>, ReactCallback<>) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksZeroArgs1) winrt::fire_and_forget TwoCallbacksZeroArgs1(ReactCallback<>, ReactCallback<>) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksZeroArgs1) static void TwoCallbacksZeroArgs1(ReactCallback<>, ReactCallback<>) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksZeroArgs1) static winrt::fire_and_forget TwoCallbacksZeroArgs1(ReactCallback<>, ReactCallback<>) noexcept {/*implementation*/}\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 42, + "TwoCallbacksZeroArgs2", + " REACT_METHOD(TwoCallbacksZeroArgs2) void TwoCallbacksZeroArgs2(ReactCallback<>, ReactCallback<>) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksZeroArgs2) winrt::fire_and_forget TwoCallbacksZeroArgs2(ReactCallback<>, ReactCallback<>) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksZeroArgs2) static void TwoCallbacksZeroArgs2(ReactCallback<>, ReactCallback<>) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksZeroArgs2) static winrt::fire_and_forget TwoCallbacksZeroArgs2(ReactCallback<>, ReactCallback<>) noexcept {/*implementation*/}\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 43, + "TwoCallbacksTwoArgs1", + " REACT_METHOD(TwoCallbacksTwoArgs1) void TwoCallbacksTwoArgs1(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksTwoArgs1) winrt::fire_and_forget TwoCallbacksTwoArgs1(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksTwoArgs1) static void TwoCallbacksTwoArgs1(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksTwoArgs1) static winrt::fire_and_forget TwoCallbacksTwoArgs1(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 44, + "TwoCallbacksTwoArgs2", + " REACT_METHOD(TwoCallbacksTwoArgs2) void TwoCallbacksTwoArgs2(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksTwoArgs2) winrt::fire_and_forget TwoCallbacksTwoArgs2(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksTwoArgs2) static void TwoCallbacksTwoArgs2(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksTwoArgs2) static winrt::fire_and_forget TwoCallbacksTwoArgs2(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 45, + "TwoCallbacksThreeArgs1", + " REACT_METHOD(TwoCallbacksThreeArgs1) void TwoCallbacksThreeArgs1(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksThreeArgs1) winrt::fire_and_forget TwoCallbacksThreeArgs1(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksThreeArgs1) static void TwoCallbacksThreeArgs1(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksThreeArgs1) static winrt::fire_and_forget TwoCallbacksThreeArgs1(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 46, + "TwoCallbacksThreeArgs2", + " REACT_METHOD(TwoCallbacksThreeArgs2) void TwoCallbacksThreeArgs2(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksThreeArgs2) winrt::fire_and_forget TwoCallbacksThreeArgs2(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksThreeArgs2) static void TwoCallbacksThreeArgs2(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n" + " REACT_METHOD(TwoCallbacksThreeArgs2) static winrt::fire_and_forget TwoCallbacksThreeArgs2(ReactCallback, ReactCallback) noexcept {/*implementation*/}\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 47, "DividePromise", " REACT_METHOD(DividePromise) void DividePromise(int, int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(DividePromise) winrt::fire_and_forget DividePromise(int, int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(DividePromise) static void DividePromise(int, int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(DividePromise) static winrt::fire_and_forget DividePromise(int, int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 39, + 48, "NegatePromise", " REACT_METHOD(NegatePromise) void NegatePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegatePromise) winrt::fire_and_forget NegatePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegatePromise) static void NegatePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegatePromise) static winrt::fire_and_forget NegatePromise(int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 40, + 49, "NegateAsyncPromise", " REACT_METHOD(NegateAsyncPromise) void NegateAsyncPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateAsyncPromise) winrt::fire_and_forget NegateAsyncPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateAsyncPromise) static void NegateAsyncPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateAsyncPromise) static winrt::fire_and_forget NegateAsyncPromise(int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 41, + 50, "NegateDispatchQueuePromise", " REACT_METHOD(NegateDispatchQueuePromise) void NegateDispatchQueuePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateDispatchQueuePromise) winrt::fire_and_forget NegateDispatchQueuePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateDispatchQueuePromise) static void NegateDispatchQueuePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateDispatchQueuePromise) static winrt::fire_and_forget NegateDispatchQueuePromise(int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 42, + 51, "NegateFuturePromise", " REACT_METHOD(NegateFuturePromise) void NegateFuturePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateFuturePromise) winrt::fire_and_forget NegateFuturePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateFuturePromise) static void NegateFuturePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateFuturePromise) static winrt::fire_and_forget NegateFuturePromise(int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 43, + 52, "voidPromise", " REACT_METHOD(voidPromise) void voidPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(voidPromise) winrt::fire_and_forget voidPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(voidPromise) static void voidPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(voidPromise) static winrt::fire_and_forget voidPromise(int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 44, + 53, "ResolveSayHelloPromise", " REACT_METHOD(ResolveSayHelloPromise) void ResolveSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(ResolveSayHelloPromise) winrt::fire_and_forget ResolveSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(ResolveSayHelloPromise) static void ResolveSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(ResolveSayHelloPromise) static winrt::fire_and_forget ResolveSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 45, + 54, "RejectSayHelloPromise", " REACT_METHOD(RejectSayHelloPromise) void RejectSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(RejectSayHelloPromise) winrt::fire_and_forget RejectSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(RejectSayHelloPromise) static void RejectSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(RejectSayHelloPromise) static winrt::fire_and_forget RejectSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 46, + 55, "StaticDividePromise", " REACT_METHOD(StaticDividePromise) void StaticDividePromise(int, int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticDividePromise) winrt::fire_and_forget StaticDividePromise(int, int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticDividePromise) static void StaticDividePromise(int, int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticDividePromise) static winrt::fire_and_forget StaticDividePromise(int, int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 47, + 56, "StaticNegatePromise", " REACT_METHOD(StaticNegatePromise) void StaticNegatePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegatePromise) winrt::fire_and_forget StaticNegatePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegatePromise) static void StaticNegatePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegatePromise) static winrt::fire_and_forget StaticNegatePromise(int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 48, + 57, "StaticNegateAsyncPromise", " REACT_METHOD(StaticNegateAsyncPromise) void StaticNegateAsyncPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateAsyncPromise) winrt::fire_and_forget StaticNegateAsyncPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateAsyncPromise) static void StaticNegateAsyncPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateAsyncPromise) static winrt::fire_and_forget StaticNegateAsyncPromise(int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 49, + 58, "StaticNegateDispatchQueuePromise", " REACT_METHOD(StaticNegateDispatchQueuePromise) void StaticNegateDispatchQueuePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateDispatchQueuePromise) winrt::fire_and_forget StaticNegateDispatchQueuePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateDispatchQueuePromise) static void StaticNegateDispatchQueuePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateDispatchQueuePromise) static winrt::fire_and_forget StaticNegateDispatchQueuePromise(int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 50, + 59, "StaticNegateFuturePromise", " REACT_METHOD(StaticNegateFuturePromise) void StaticNegateFuturePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateFuturePromise) winrt::fire_and_forget StaticNegateFuturePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateFuturePromise) static void StaticNegateFuturePromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateFuturePromise) static winrt::fire_and_forget StaticNegateFuturePromise(int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 51, + 60, "staticVoidPromise", " REACT_METHOD(staticVoidPromise) void staticVoidPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(staticVoidPromise) winrt::fire_and_forget staticVoidPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(staticVoidPromise) static void staticVoidPromise(int, ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(staticVoidPromise) static winrt::fire_and_forget staticVoidPromise(int, ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 52, + 61, "StaticResolveSayHelloPromise", " REACT_METHOD(StaticResolveSayHelloPromise) void StaticResolveSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticResolveSayHelloPromise) winrt::fire_and_forget StaticResolveSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticResolveSayHelloPromise) static void StaticResolveSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticResolveSayHelloPromise) static winrt::fire_and_forget StaticResolveSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 53, + 62, "StaticRejectSayHelloPromise", " REACT_METHOD(StaticRejectSayHelloPromise) void StaticRejectSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticRejectSayHelloPromise) winrt::fire_and_forget StaticRejectSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticRejectSayHelloPromise) static void StaticRejectSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticRejectSayHelloPromise) static winrt::fire_and_forget StaticRejectSayHelloPromise(ReactPromise) noexcept {/*implementation*/}\n"); REACT_SHOW_SYNC_METHOD_SPEC_ERRORS( - 54, + 63, "AddSync", " REACT_METHOD(AddSync) int AddSync(int, int) noexcept {/*implementation*/}\n" " REACT_METHOD(AddSync) static int AddSync(int, int) noexcept {/*implementation*/}\n"); REACT_SHOW_SYNC_METHOD_SPEC_ERRORS( - 55, + 64, "NegateSync", " REACT_METHOD(NegateSync) int NegateSync(int) noexcept {/*implementation*/}\n" " REACT_METHOD(NegateSync) static int NegateSync(int) noexcept {/*implementation*/}\n"); REACT_SHOW_SYNC_METHOD_SPEC_ERRORS( - 56, + 65, "SayHelloSync", " REACT_METHOD(SayHelloSync) std::string SayHelloSync() noexcept {/*implementation*/}\n" " REACT_METHOD(SayHelloSync) static std::string SayHelloSync() noexcept {/*implementation*/}\n"); REACT_SHOW_SYNC_METHOD_SPEC_ERRORS( - 57, + 66, "StaticAddSync", " REACT_METHOD(StaticAddSync) int StaticAddSync(int, int) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticAddSync) static int StaticAddSync(int, int) noexcept {/*implementation*/}\n"); REACT_SHOW_SYNC_METHOD_SPEC_ERRORS( - 58, + 67, "StaticNegateSync", " REACT_METHOD(StaticNegateSync) int StaticNegateSync(int) noexcept {/*implementation*/}\n" " REACT_METHOD(StaticNegateSync) static int StaticNegateSync(int) noexcept {/*implementation*/}\n"); REACT_SHOW_SYNC_METHOD_SPEC_ERRORS( - 59, + 68, "StaticSayHelloSync", " REACT_METHOD(StaticSayHelloSync) std::string StaticSayHelloSync() noexcept {/*implementation*/}\n" " REACT_METHOD(StaticSayHelloSync) static std::string StaticSayHelloSync() noexcept {/*implementation*/}\n"); @@ -1265,6 +1394,30 @@ TEST_CLASS (TurboModuleTest) { TestCheck(m_builderMock.IsResolveCallbackCalled()); } + TEST_METHOD(TestMethodCall_CallbackZeroArgs) { + m_builderMock.Call1(L"CallbackZeroArgs", std::function([]() noexcept {})); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_CallbackTwoArgs) { + m_builderMock.Call1(L"CallbackTwoArgs", std::function([](int p1, int p2) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_CallbackThreeArgs) { + m_builderMock.Call1( + L"CallbackThreeArgs", + std::function([](int p1, int p2, std::string const &p3) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + TestCheckEqual("Hello", p3); + })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + TEST_METHOD(TestMethodCall_DivideCallbacks) { m_builderMock.Call2( L"DivideCallbacks", @@ -1509,6 +1662,68 @@ TEST_CLASS (TurboModuleTest) { TestCheck(m_builderMock.IsRejectCallbackCalled()); } + TEST_METHOD(TestMethodCall_TwoCallbacksZeroArgs1) { + m_builderMock.Call2(L"TwoCallbacksZeroArgs1", std::function([]() noexcept {}), std::function([ + ]() noexcept { TestCheckFail(); })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksZeroArgs2) { + m_builderMock.Call2( + L"TwoCallbacksZeroArgs2", + std::function([]() noexcept { TestCheckFail(); }), + std::function([]() noexcept {})); + TestCheck(m_builderMock.IsRejectCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksTwoArgs1) { + m_builderMock.Call2( + L"TwoCallbacksTwoArgs1", + std::function([](int p1, int p2) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + }), + std::function([](int /*p1*/, int /*p2*/) noexcept { TestCheckFail(); })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksTwoArgs2) { + m_builderMock.Call2( + L"TwoCallbacksTwoArgs2", + std::function([](int /*p1*/, int /*p2*/) noexcept { TestCheckFail(); }), + std::function([](int p1, int p2) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + })); + TestCheck(m_builderMock.IsRejectCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksThreeArgs1) { + m_builderMock.Call2( + L"TwoCallbacksThreeArgs1", + std::function([](int p1, int p2, std::string const &p3) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + TestCheckEqual("Hello", p3); + }), + std::function( + [](int /*p1*/, int /*p2*/, std::string const & /*p3*/) noexcept { TestCheckFail(); })); + TestCheck(m_builderMock.IsResolveCallbackCalled()); + } + + TEST_METHOD(TestMethodCall_TwoCallbacksThreeArgs2) { + m_builderMock.Call2( + L"TwoCallbacksThreeArgs2", + std::function( + [](int /*p1*/, int /*p2*/, std::string const & /*p3*/) noexcept { TestCheckFail(); }), + std::function([](int p1, int p2, std::string const &p3) noexcept { + TestCheckEqual(1, p1); + TestCheckEqual(2, p2); + TestCheckEqual("Hello", p3); + })); + TestCheck(m_builderMock.IsRejectCallbackCalled()); + } + TEST_METHOD(TestMethodCall_DividePromise) { m_builderMock.Call2( L"DividePromise", diff --git a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h index 3e590f3037c..6d76e18f4ca 100644 --- a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h +++ b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h @@ -205,6 +205,7 @@ struct GetCallbackSignatureImpl> { template struct CallbackCreator; +// Callback signature without noexcept template

7A|`YzB^O&H9Utboj8WNNygwF_l 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