From cd2c3d266970ddb0861d6f21f4bb2306bb21b689 Mon Sep 17 00:00:00 2001 From: Jason Gore Date: Mon, 27 Aug 2018 08:56:16 -0700 Subject: [PATCH 1/7] Remove Object.assign usage in Foundation to fix IE11 issues. --- packages/foundation/src/createComponent.tsx | 58 ++++++++++++++------- packages/foundation/tslint.json | 3 +- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/packages/foundation/src/createComponent.tsx b/packages/foundation/src/createComponent.tsx index d518d395ef578..16e533f365f19 100644 --- a/packages/foundation/src/createComponent.tsx +++ b/packages/foundation/src/createComponent.tsx @@ -74,7 +74,6 @@ export interface IStylingProviders | undefined)[]) => TProcessedStyleSet; getCustomizations: (scope: string, context: TContext) => IStyleableComponent; // TODO: remove any if possible - // tslint:disable-next-line:no-any CustomizableContextTypes: any; } @@ -145,19 +144,18 @@ export function createComponent< // merging user props and processed props together. This ensures all props are passed properly to view, // including children and styles. const propStyles = processedProps.styles || userProps.styles; - const themedProps: TProcessedProps = Object.assign({}, rest, userProps, processedProps); - const viewProps: IViewComponentProps = Object.assign( - {}, - processedProps, - userProps, - { + const themedProps: TProcessedProps = { ...rest, ...(userProps as any), ...(processedProps as any) }; + const viewProps: IViewComponentProps = { + ...(processedProps as any), + ...(userProps as any), + ...{ classNames: providers.mergeStyleSets( _evaluateStyle(themedProps, options.styles), _evaluateStyle(themedProps, contextStyles), _evaluateStyle(themedProps, propStyles) ) } - ); + }; // TODO: consider rendering view as JSX component with display name in debug mode to aid in debugging return options.view(viewProps); @@ -169,7 +167,7 @@ export function createComponent< result.contextTypes = providers.CustomizableContextTypes; result.displayName = options.displayName; - Object.assign(result, options.statics); + _assignStatics(result, options.statics); // Later versions of TypeSript should allow us to merge objects in a type safe way and avoid this cast. return result as React.StatelessComponent & TStatics; @@ -201,14 +199,17 @@ export function createStatelessComponent< const content = (processedProps: TProcessedProps) => { const { styles: propStyles } = processedProps; - const themedProps: TProcessedProps = Object.assign({}, rest, processedProps); - const viewProps: IViewComponentProps = Object.assign({}, processedProps, { - classNames: providers.mergeStyleSets( - _evaluateStyle(themedProps, options.styles), - _evaluateStyle(themedProps, contextStyles), - _evaluateStyle(themedProps, propStyles) - ) - }); + const themedProps: TProcessedProps = { ...rest, ...(processedProps as any) }; + const viewProps: IViewComponentProps = { + ...(processedProps as any), + ...{ + classNames: providers.mergeStyleSets( + _evaluateStyle(themedProps, options.styles), + _evaluateStyle(themedProps, contextStyles), + _evaluateStyle(themedProps, propStyles) + ) + } + }; // TODO: consider rendering view as JSX component with display name in debug mode to aid in debugging return options.view(viewProps); @@ -219,12 +220,33 @@ export function createStatelessComponent< result.contextTypes = providers.CustomizableContextTypes; result.displayName = options.displayName; - Object.assign(result, options.statics); + + _assignStatics(result, options.statics); // Later versions of TypeSript should allow us to merge objects in a type safe way and avoid this cast. return result as React.StatelessComponent & TStatics; } +/** + * Basic Object.assign helper for applying source object to target. + * @param target Target object to merge into. + * @param source Source object that will be mixed into target. + * @returns Resulting merged target. + */ +function _assignStatics(target: any, source: any): any { + target = target || {}; + + if (source) { + for (const propName in source) { + if (source.hasOwnProperty(propName)) { + target[propName] = source[propName]; + } + } + } + + return target; +} + /** * Evaluate styles based on type to return consistent TStyleSet. */ diff --git a/packages/foundation/tslint.json b/packages/foundation/tslint.json index b057578463d41..c481d5d9d3187 100644 --- a/packages/foundation/tslint.json +++ b/packages/foundation/tslint.json @@ -3,6 +3,7 @@ "office-ui-fabric-react-tslint" ], "rules": { - "deprecation": false + "deprecation": false, + "no-any": false } } \ No newline at end of file From 411979593a467fd8b2b23d2e9b70ddf2fb352adc Mon Sep 17 00:00:00 2001 From: Jason Gore Date: Mon, 27 Aug 2018 08:57:00 -0700 Subject: [PATCH 2/7] Change file. --- .../jg-remove-object-assign_2018-08-27-15-56.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@uifabric/foundation/jg-remove-object-assign_2018-08-27-15-56.json diff --git a/common/changes/@uifabric/foundation/jg-remove-object-assign_2018-08-27-15-56.json b/common/changes/@uifabric/foundation/jg-remove-object-assign_2018-08-27-15-56.json new file mode 100644 index 0000000000000..262df1d7581da --- /dev/null +++ b/common/changes/@uifabric/foundation/jg-remove-object-assign_2018-08-27-15-56.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "@uifabric/foundation", + "comment": "Remove Object.assign usage to fix IE11 issues.", + "type": "patch" + } + ], + "packageName": "@uifabric/foundation", + "email": "jagore@microsoft.com" +} \ No newline at end of file From e5b854b5bba4311cf8c2d7d0c0424806b931d4ea Mon Sep 17 00:00:00 2001 From: Jason Gore Date: Mon, 27 Aug 2018 09:00:56 -0700 Subject: [PATCH 3/7] Tweak naming consistency. --- packages/foundation/src/createComponent.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/foundation/src/createComponent.tsx b/packages/foundation/src/createComponent.tsx index 16e533f365f19..c1fa62da26562 100644 --- a/packages/foundation/src/createComponent.tsx +++ b/packages/foundation/src/createComponent.tsx @@ -228,18 +228,18 @@ export function createStatelessComponent< } /** - * Basic Object.assign helper for applying source object to target. + * Basic Object.assign helper for applying statics to target. * @param target Target object to merge into. - * @param source Source object that will be mixed into target. + * @param statics Statics object that will be mixed into target. * @returns Resulting merged target. */ -function _assignStatics(target: any, source: any): any { +function _assignStatics(target: any, statics: any): any { target = target || {}; - if (source) { - for (const propName in source) { - if (source.hasOwnProperty(propName)) { - target[propName] = source[propName]; + if (statics) { + for (const propName in statics) { + if (statics.hasOwnProperty(propName)) { + target[propName] = statics[propName]; } } } From 091e5ff5bb80e3f9d71da543d7361c9758beff4e Mon Sep 17 00:00:00 2001 From: Jason Gore Date: Mon, 27 Aug 2018 09:14:48 -0700 Subject: [PATCH 4/7] Merge props consistently. --- packages/foundation/src/createComponent.tsx | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/foundation/src/createComponent.tsx b/packages/foundation/src/createComponent.tsx index c1fa62da26562..817ee94589794 100644 --- a/packages/foundation/src/createComponent.tsx +++ b/packages/foundation/src/createComponent.tsx @@ -144,15 +144,14 @@ export function createComponent< // merging user props and processed props together. This ensures all props are passed properly to view, // including children and styles. const propStyles = processedProps.styles || userProps.styles; - const themedProps: TProcessedProps = { ...rest, ...(userProps as any), ...(processedProps as any) }; + const mergedProps: TProcessedProps = { ...rest, ...(processedProps as any), ...(userProps as any) }; const viewProps: IViewComponentProps = { - ...(processedProps as any), - ...(userProps as any), + ...(mergedProps as any), ...{ classNames: providers.mergeStyleSets( - _evaluateStyle(themedProps, options.styles), - _evaluateStyle(themedProps, contextStyles), - _evaluateStyle(themedProps, propStyles) + _evaluateStyle(mergedProps, options.styles), + _evaluateStyle(mergedProps, contextStyles), + _evaluateStyle(mergedProps, propStyles) ) } }; @@ -199,14 +198,14 @@ export function createStatelessComponent< const content = (processedProps: TProcessedProps) => { const { styles: propStyles } = processedProps; - const themedProps: TProcessedProps = { ...rest, ...(processedProps as any) }; + const mergedProps: TProcessedProps = { ...rest, ...(processedProps as any) }; const viewProps: IViewComponentProps = { - ...(processedProps as any), + ...(mergedProps as any), ...{ classNames: providers.mergeStyleSets( - _evaluateStyle(themedProps, options.styles), - _evaluateStyle(themedProps, contextStyles), - _evaluateStyle(themedProps, propStyles) + _evaluateStyle(mergedProps, options.styles), + _evaluateStyle(mergedProps, contextStyles), + _evaluateStyle(mergedProps, propStyles) ) } }; From 5261be8bc1edb1830db3c8646056c8d738af6334 Mon Sep 17 00:00:00 2001 From: Jason Gore Date: Mon, 27 Aug 2018 09:55:35 -0700 Subject: [PATCH 5/7] Revert customizations mixin to view props. --- packages/foundation/src/createComponent.tsx | 25 ++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/foundation/src/createComponent.tsx b/packages/foundation/src/createComponent.tsx index 817ee94589794..6bfe59813fc93 100644 --- a/packages/foundation/src/createComponent.tsx +++ b/packages/foundation/src/createComponent.tsx @@ -143,15 +143,18 @@ export function createComponent< // The approach here is to allow state components to provide only the props they care about, automatically // merging user props and processed props together. This ensures all props are passed properly to view, // including children and styles. + // TODO: Should 'rest' props from customizations pass onto view? They are not currently. + // (items like theme seem like they shouldn't) const propStyles = processedProps.styles || userProps.styles; - const mergedProps: TProcessedProps = { ...rest, ...(processedProps as any), ...(userProps as any) }; + const styleProps: TProcessedProps = { ...rest, ...(processedProps as any), ...(userProps as any) }; const viewProps: IViewComponentProps = { - ...(mergedProps as any), + ...(processedProps as any), + ...(userProps as any), ...{ classNames: providers.mergeStyleSets( - _evaluateStyle(mergedProps, options.styles), - _evaluateStyle(mergedProps, contextStyles), - _evaluateStyle(mergedProps, propStyles) + _evaluateStyle(styleProps, options.styles), + _evaluateStyle(styleProps, contextStyles), + _evaluateStyle(styleProps, propStyles) ) } }; @@ -197,15 +200,17 @@ export function createStatelessComponent< const { styles: contextStyles, ...rest } = settings; const content = (processedProps: TProcessedProps) => { + // TODO: Should 'rest' props from customizations pass onto view? They are not currently. + // (items like theme seem like they shouldn't) const { styles: propStyles } = processedProps; - const mergedProps: TProcessedProps = { ...rest, ...(processedProps as any) }; + const styleProps: TProcessedProps = { ...rest, ...(processedProps as any) }; const viewProps: IViewComponentProps = { - ...(mergedProps as any), + ...(processedProps as any), ...{ classNames: providers.mergeStyleSets( - _evaluateStyle(mergedProps, options.styles), - _evaluateStyle(mergedProps, contextStyles), - _evaluateStyle(mergedProps, propStyles) + _evaluateStyle(styleProps, options.styles), + _evaluateStyle(styleProps, contextStyles), + _evaluateStyle(styleProps, propStyles) ) } }; From d66cb8f296fa63bec43d50288db76dc09901da4c Mon Sep 17 00:00:00 2001 From: Jason Gore Date: Mon, 27 Aug 2018 19:36:39 -0700 Subject: [PATCH 6/7] Use tslib's __assign for statics. --- packages/foundation/src/createComponent.tsx | 25 +++------------------ 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/packages/foundation/src/createComponent.tsx b/packages/foundation/src/createComponent.tsx index 6bfe59813fc93..459738d575afe 100644 --- a/packages/foundation/src/createComponent.tsx +++ b/packages/foundation/src/createComponent.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { __assign } from 'tslib'; /** * Props contract for themed components. @@ -169,7 +170,7 @@ export function createComponent< result.contextTypes = providers.CustomizableContextTypes; result.displayName = options.displayName; - _assignStatics(result, options.statics); + __assign(result, options.statics); // Later versions of TypeSript should allow us to merge objects in a type safe way and avoid this cast. return result as React.StatelessComponent & TStatics; @@ -225,32 +226,12 @@ export function createStatelessComponent< result.contextTypes = providers.CustomizableContextTypes; result.displayName = options.displayName; - _assignStatics(result, options.statics); + __assign(result, options.statics); // Later versions of TypeSript should allow us to merge objects in a type safe way and avoid this cast. return result as React.StatelessComponent & TStatics; } -/** - * Basic Object.assign helper for applying statics to target. - * @param target Target object to merge into. - * @param statics Statics object that will be mixed into target. - * @returns Resulting merged target. - */ -function _assignStatics(target: any, statics: any): any { - target = target || {}; - - if (statics) { - for (const propName in statics) { - if (statics.hasOwnProperty(propName)) { - target[propName] = statics[propName]; - } - } - } - - return target; -} - /** * Evaluate styles based on type to return consistent TStyleSet. */ From 8344baf6a2691db3a92a339d09fe331d0cd8bf2f Mon Sep 17 00:00:00 2001 From: Jason Gore Date: Tue, 28 Aug 2018 11:47:04 -0700 Subject: [PATCH 7/7] Consolidate __assign usage. --- packages/foundation/src/createComponent.tsx | 6 +++--- packages/foundation/src/utilities.ts | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 packages/foundation/src/utilities.ts diff --git a/packages/foundation/src/createComponent.tsx b/packages/foundation/src/createComponent.tsx index 459738d575afe..1f2a5fc079d6a 100644 --- a/packages/foundation/src/createComponent.tsx +++ b/packages/foundation/src/createComponent.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { __assign } from 'tslib'; +import { assign } from './utilities'; /** * Props contract for themed components. @@ -170,7 +170,7 @@ export function createComponent< result.contextTypes = providers.CustomizableContextTypes; result.displayName = options.displayName; - __assign(result, options.statics); + assign(result, options.statics); // Later versions of TypeSript should allow us to merge objects in a type safe way and avoid this cast. return result as React.StatelessComponent & TStatics; @@ -226,7 +226,7 @@ export function createStatelessComponent< result.contextTypes = providers.CustomizableContextTypes; result.displayName = options.displayName; - __assign(result, options.statics); + assign(result, options.statics); // Later versions of TypeSript should allow us to merge objects in a type safe way and avoid this cast. return result as React.StatelessComponent & TStatics; diff --git a/packages/foundation/src/utilities.ts b/packages/foundation/src/utilities.ts new file mode 100644 index 0000000000000..3146eabfcb330 --- /dev/null +++ b/packages/foundation/src/utilities.ts @@ -0,0 +1,2 @@ +import { __assign } from 'tslib'; +export const assign = __assign;