Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(react-jsx-runtime): implements custom JSX pragma #27472

Conversation

bsunderhus
Copy link
Contributor

@bsunderhus bsunderhus commented Apr 6, 2023

New Behavior

  1. Implements custom JSX pragma at @fluentui/react-jsx-runtime
  2. releases @fluentui/react-jsx-runtime
  3. creates getSlotsNext as a compatible version of getSlots with the newest custom JSX pragma
  4. updates resolveShorthand and getSlots accordingly to ensure previous behaviour
  5. creates tests for custom pragma
  6. creates tests for getSlotsNext
  7. updates tests for resolveShorthand

Related Issue(s)

@bsunderhus bsunderhus self-assigned this Apr 6, 2023
@github-actions github-actions bot added this to the April Project Cycle Q2 2023 milestone Apr 6, 2023
@bsunderhus bsunderhus force-pushed the react-jsx-runtime/feat--implements-custom-jsx-pragma branch from eb275e8 to 132e7bf Compare April 6, 2023 12:57
@fabricteam
Copy link
Collaborator

fabricteam commented Apr 6, 2023

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-accordion
Accordion (including children components)
88.882 kB
26.551 kB
88.959 kB
26.571 kB
77 B
20 B
react-alert
Alert
96.647 kB
23.133 kB
96.725 kB
23.155 kB
78 B
22 B
react-avatar
Avatar
60.312 kB
15.579 kB
60.39 kB
15.605 kB
78 B
26 B
react-avatar
AvatarGroup
18.178 kB
6.683 kB
18.137 kB
6.67 kB
-41 B
-13 B
react-avatar
AvatarGroupItem
76.573 kB
20.086 kB
76.651 kB
20.11 kB
78 B
24 B
react-badge
Badge
25.985 kB
7.6 kB
26.063 kB
7.621 kB
78 B
21 B
react-badge
CounterBadge
26.968 kB
7.907 kB
27.046 kB
7.93 kB
78 B
23 B
react-badge
PresenceBadge
34.458 kB
8.693 kB
34.535 kB
8.716 kB
77 B
23 B
react-button
Button
39.749 kB
9.959 kB
39.827 kB
9.987 kB
78 B
28 B
react-button
CompoundButton
46.921 kB
11.428 kB
46.999 kB
11.456 kB
78 B
28 B
react-button
MenuButton
44.437 kB
11.306 kB
44.514 kB
11.332 kB
77 B
26 B
react-button
SplitButton
52.931 kB
12.872 kB
53.009 kB
12.898 kB
78 B
26 B
react-button
ToggleButton
58.121 kB
11.878 kB
58.199 kB
11.907 kB
78 B
29 B
react-card
Card - All
83.489 kB
23.894 kB
83.566 kB
23.927 kB
77 B
33 B
react-card
Card
78.308 kB
22.431 kB
78.385 kB
22.46 kB
77 B
29 B
react-card
CardFooter
9.035 kB
3.799 kB
9.11 kB
3.824 kB
75 B
25 B
react-card
CardHeader
10.959 kB
4.503 kB
11.036 kB
4.528 kB
77 B
25 B
react-card
CardPreview
9.84 kB
4.153 kB
9.915 kB
4.173 kB
75 B
20 B
react-checkbox
Checkbox
37.02 kB
11.255 kB
37.097 kB
11.277 kB
77 B
22 B
react-combobox
Combobox (including child components)
89.788 kB
28.51 kB
89.865 kB
28.545 kB
77 B
35 B
react-combobox
Dropdown (including child components)
88.472 kB
28.238 kB
88.549 kB
28.267 kB
77 B
29 B
react-components
react-components: Button, FluentProvider & webLightTheme
67.994 kB
18.395 kB
68.075 kB
18.416 kB
81 B
21 B
react-components
react-components: Accordion, Button, FluentProvider, Image, Menu, Popover
207.529 kB
57.549 kB
207.606 kB
57.581 kB
77 B
32 B
react-components
react-components: FluentProvider & webLightTheme
38.819 kB
12.351 kB
38.778 kB
12.337 kB
-41 B
-14 B
react-datepicker-compat
DatePicker Compat
251.274 kB
67.327 kB
251.351 kB
67.358 kB
77 B
31 B
react-dialog
Dialog (including children components)
93.242 kB
27.369 kB
93.319 kB
27.389 kB
77 B
20 B
react-divider
Divider
19.863 kB
6.697 kB
19.94 kB
6.725 kB
77 B
28 B
react-field
Field
21.494 kB
7.41 kB
21.571 kB
7.437 kB
77 B
27 B
react-image
Image
14.011 kB
4.993 kB
13.97 kB
4.978 kB
-41 B
-15 B
react-infobutton
InfoButton
130.594 kB
39.431 kB
130.671 kB
39.464 kB
77 B
33 B
react-infobutton
InfoLabel
133.891 kB
40.483 kB
133.97 kB
40.505 kB
79 B
22 B
react-input
Input
26.707 kB
8.113 kB
26.784 kB
8.141 kB
77 B
28 B
react-label
Label
12.57 kB
4.586 kB
12.645 kB
4.609 kB
75 B
23 B
react-link
Link
12.301 kB
5.07 kB
12.26 kB
5.053 kB
-41 B
-17 B
react-menu
Menu (including children components)
131.055 kB
39.651 kB
131.132 kB
39.675 kB
77 B
24 B
react-menu
Menu (including selectable components)
134.191 kB
40.186 kB
134.268 kB
40.211 kB
77 B
25 B
react-persona
Persona
67.338 kB
17.524 kB
67.416 kB
17.552 kB
78 B
28 B
react-popover
Popover
117.597 kB
35.827 kB
117.556 kB
35.812 kB
-41 B
-15 B
react-progress
ProgressBar
16.322 kB
5.822 kB
16.397 kB
5.846 kB
75 B
24 B
react-provider
FluentProvider
20.766 kB
7.119 kB
20.725 kB
7.104 kB
-41 B
-15 B
react-radio
Radio
35.557 kB
11.152 kB
35.635 kB
11.179 kB
78 B
27 B
react-radio
RadioGroup
18.935 kB
6.94 kB
18.894 kB
6.926 kB
-41 B
-14 B
react-select
Select
27.915 kB
9.189 kB
27.992 kB
9.215 kB
77 B
26 B
react-slider
Slider
36.845 kB
11.474 kB
36.922 kB
11.506 kB
77 B
32 B
react-spinbutton
SpinButton
36.615 kB
10.757 kB
36.693 kB
10.784 kB
78 B
27 B
react-spinner
Spinner
23.425 kB
7.195 kB
23.503 kB
7.217 kB
78 B
22 B
react-switch
Switch
32.438 kB
9.706 kB
32.515 kB
9.726 kB
77 B
20 B
react-table
DataGrid
150.906 kB
41.068 kB
150.983 kB
41.093 kB
77 B
25 B
react-table
Table (Primitives only)
47.119 kB
12.703 kB
47.196 kB
12.732 kB
77 B
29 B
react-table
Table as DataGrid
139.048 kB
35.735 kB
139.125 kB
35.768 kB
77 B
33 B
react-table
Table (Selection only)
86.877 kB
21.757 kB
86.954 kB
21.779 kB
77 B
22 B
react-table
Table (Sort only)
86.207 kB
21.565 kB
86.284 kB
21.589 kB
77 B
24 B
react-text
Text - Default
15.018 kB
5.327 kB
14.977 kB
5.308 kB
-41 B
-19 B
react-text
Text - Wrappers
15.572 kB
5.23 kB
15.531 kB
5.215 kB
-41 B
-15 B
react-textarea
Textarea
30.108 kB
9.478 kB
30.185 kB
9.502 kB
77 B
24 B
react-tooltip
Tooltip
49.388 kB
16.815 kB
49.465 kB
16.844 kB
77 B
29 B
Unchanged fixtures
Package & Exports Size (minified/GZIP)
global-context
createContext
533 B
341 B
global-context
createContextSelector
560 B
352 B
react-overflow
hooks only
11.214 kB
4.271 kB
react-portal
Portal
11.649 kB
4.263 kB
react-portal-compat
PortalCompatProvider
6.446 kB
2.185 kB
react-positioning
usePositioning
24.008 kB
8.798 kB
react-utilities
SSRProvider
180 B
159 B
🤖 This report was generated against faa429a450e970352796776268983c5081d7e72a

@fabricteam
Copy link
Collaborator

fabricteam commented Apr 6, 2023

Perf Analysis (@fluentui/react-components)

No significant results to display.

All results

Scenario Render type Master Ticks PR Ticks Iterations Status
Avatar mount 676 692 5000
Button mount 390 371 5000
Field mount 1236 1234 5000
FluentProvider mount 910 902 5000
FluentProviderWithTheme mount 123 119 10
FluentProviderWithTheme virtual-rerender 110 107 10
FluentProviderWithTheme virtual-rerender-with-unmount 109 113 10
InfoButton mount 18 22 5000
MakeStyles mount 1133 1131 50000
Persona mount 1968 1929 5000
SpinButton mount 1562 1573 5000

@fabricteam
Copy link
Collaborator

fabricteam commented Apr 6, 2023

Perf Analysis (@fluentui/react-northstar)

Perf tests with no regressions
Scenario Current PR Ticks Baseline Ticks Ratio
FormMinimalPerf.default 291 264 1.1:1
RefMinimalPerf.default 146 134 1.09:1
AccordionMinimalPerf.default 103 96 1.07:1
FlexMinimalPerf.default 210 196 1.07:1
TreeWith60ListItems.default 115 108 1.06:1
SegmentMinimalPerf.default 261 248 1.05:1
AttachmentSlotsPerf.default 856 827 1.04:1
AvatarMinimalPerf.default 137 132 1.04:1
DividerMinimalPerf.default 267 256 1.04:1
LabelMinimalPerf.default 288 278 1.04:1
GridMinimalPerf.default 243 236 1.03:1
ImageMinimalPerf.default 275 266 1.03:1
PortalMinimalPerf.default 121 117 1.03:1
ReactionMinimalPerf.default 273 264 1.03:1
StatusMinimalPerf.default 517 502 1.03:1
AttachmentMinimalPerf.default 99 97 1.02:1
ButtonOverridesMissPerf.default 838 823 1.02:1
CardMinimalPerf.default 384 377 1.02:1
CarouselMinimalPerf.default 344 338 1.02:1
ChatMinimalPerf.default 536 526 1.02:1
ChatWithPopoverPerf.default 250 245 1.02:1
DialogMinimalPerf.default 587 576 1.02:1
HeaderSlotsPerf.default 567 558 1.02:1
MenuMinimalPerf.default 616 604 1.02:1
TextMinimalPerf.default 251 245 1.02:1
AnimationMinimalPerf.default 373 371 1.01:1
DropdownMinimalPerf.default 1820 1803 1.01:1
EmbedMinimalPerf.default 2413 2393 1.01:1
ListMinimalPerf.default 386 381 1.01:1
MenuButtonMinimalPerf.default 1255 1240 1.01:1
PopupMinimalPerf.default 455 451 1.01:1
RadioGroupMinimalPerf.default 331 328 1.01:1
TextAreaMinimalPerf.default 351 349 1.01:1
VideoMinimalPerf.default 535 532 1.01:1
AlertMinimalPerf.default 191 191 1:1
BoxMinimalPerf.default 247 247 1:1
ButtonMinimalPerf.default 109 109 1:1
CheckboxMinimalPerf.default 1559 1553 1:1
InputMinimalPerf.default 720 721 1:1
ItemLayoutMinimalPerf.default 897 893 1:1
LayoutMinimalPerf.default 262 262 1:1
ListNestedPerf.default 403 403 1:1
RosterPerf.default 1818 1823 1:1
ProviderMergeThemesPerf.default 976 975 1:1
ProviderMinimalPerf.default 277 276 1:1
SkeletonMinimalPerf.default 256 256 1:1
TableManyItemsPerf.default 1420 1416 1:1
ToolbarMinimalPerf.default 665 662 1:1
TreeMinimalPerf.default 587 587 1:1
ButtonSlotsPerf.default 407 412 0.99:1
DropdownManyItemsPerf.default 485 490 0.99:1
ListCommonPerf.default 483 488 0.99:1
LoaderMinimalPerf.default 239 241 0.99:1
SplitButtonMinimalPerf.default 2980 3001 0.99:1
TableMinimalPerf.default 299 301 0.99:1
CustomToolbarPrototype.default 1872 1887 0.99:1
ChatDuplicateMessagesPerf.default 192 196 0.98:1
IconMinimalPerf.default 453 461 0.98:1
HeaderMinimalPerf.default 261 268 0.97:1
TooltipMinimalPerf.default 1574 1622 0.97:1
ListWith60ListItems.default 459 477 0.96:1
SliderMinimalPerf.default 898 932 0.96:1
DatepickerMinimalPerf.default 4592 4855 0.95:1

@codesandbox-ci
Copy link

codesandbox-ci bot commented Apr 6, 2023

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 62cce49:

Sandbox Source
@fluentui/react 8 starter Configuration
@fluentui/react-components 9 starter Configuration

@size-auditor
Copy link

size-auditor bot commented Apr 6, 2023

Asset size changes

Size Auditor did not detect a change in bundle size for any component!

Baseline commit: faa429a450e970352796776268983c5081d7e72a (build)

@fabricteam
Copy link
Collaborator

fabricteam commented Apr 6, 2023

🕵 fluentuiv9 No visual regressions between this PR and main

@fabricteam
Copy link
Collaborator

fabricteam commented Apr 6, 2023

🕵 FluentUI-v0 No visual regressions between this PR and main

@fabricteam
Copy link
Collaborator

fabricteam commented Apr 6, 2023

Perf Analysis (@fluentui/react)

No significant results to display.

All results

Scenario Render type Master Ticks PR Ticks Iterations Status
BaseButton mount 802 799 5000
Breadcrumb mount 2219 2170 1000
Checkbox mount 2138 2114 5000
CheckboxBase mount 1858 1864 5000
ChoiceGroup mount 3673 3725 5000
ComboBox mount 865 870 1000
CommandBar mount 7892 7908 1000
ContextualMenu mount 14885 15211 1000
DefaultButton mount 983 973 5000
DetailsRow mount 2891 2904 5000
DetailsRowFast mount 2896 2866 5000
DetailsRowNoStyles mount 2612 2682 5000
Dialog mount 3395 3389 1000
DocumentCardTitle mount 312 313 1000
Dropdown mount 2520 2522 5000
FocusTrapZone mount 1512 1523 5000
FocusZone mount 1428 1418 5000
GroupedList mount 49329 57266 2
GroupedList virtual-rerender 23874 23847 2
GroupedList virtual-rerender-with-unmount 73706 72688 2
GroupedListV2 mount 309 309 2
GroupedListV2 virtual-rerender 291 304 2
GroupedListV2 virtual-rerender-with-unmount 315 319 2
IconButton mount 1414 1409 5000
Label mount 455 449 5000
Layer mount 3585 3628 5000
Link mount 522 520 5000
MenuButton mount 1206 1225 5000
MessageBar mount 27254 27308 5000
Nav mount 2526 2523 1000
OverflowSet mount 1001 988 5000
Panel mount 2208 2239 1000
Persona mount 969 969 1000
Pivot mount 1163 1164 1000
PrimaryButton mount 1106 1095 5000
Rating mount 5736 5745 5000
SearchBox mount 1153 1148 5000
Shimmer mount 2333 2310 5000
Slider mount 1710 1706 5000
SpinButton mount 3720 3752 5000
Spinner mount 528 520 5000
SplitButton mount 2398 2402 5000
Stack mount 539 535 5000
StackWithIntrinsicChildren mount 1113 1127 5000
StackWithTextChildren mount 3223 3212 5000
SwatchColorPicker mount 8073 8084 5000
TagPicker mount 1987 1962 5000
Text mount 503 497 5000
TextField mount 1200 1194 5000
ThemeProvider mount 1108 1127 5000
ThemeProvider virtual-rerender 768 772 5000
ThemeProvider virtual-rerender-with-unmount 1715 1725 5000
Toggle mount 796 815 5000
buttonNative mount 279 280 5000

@bsunderhus bsunderhus marked this pull request as ready for review April 6, 2023 16:44
@bsunderhus bsunderhus requested review from a team as code owners April 6, 2023 16:44
@Hotell Hotell self-requested a review April 11, 2023 12:16
bsunderhus and others added 3 commits April 12, 2023 09:04
@bsunderhus bsunderhus force-pushed the react-jsx-runtime/feat--implements-custom-jsx-pragma branch 2 times, most recently from 722dac4 to b61aa75 Compare April 12, 2023 09:18
& restructure jsx to simplify
@bsunderhus bsunderhus force-pushed the react-jsx-runtime/feat--implements-custom-jsx-pragma branch from b61aa75 to 1bfca4a Compare April 12, 2023 09:54
@bsunderhus bsunderhus merged commit 97af91a into microsoft:master Apr 12, 2023
marcosmoura added a commit to marcosmoura/fluentui that referenced this pull request Apr 13, 2023
…t/drawer-light-dismiss-prop

* marcosmoura/feat/drawer-component: (51 commits)
  fix: upgrade react-dialog
  Doc: Add/Remove TreeItem and useFlatTree stories (microsoft#27515)
  applying package updates
  Fix accessibility labels for tree stories (microsoft#27443)
  fix: BasePickerListBelow aria-describedby with values (microsoft#27525)
  chore: Remove deprecated InputField, etc. shim components (microsoft#27492)
  [Feature]: allow aria-description attribute on v9 (microsoft#27478)
  feat(react-jsx-runtime): implements custom JSX pragma (microsoft#27472)
  chore: update generator to include "test-ssr" script (microsoft#27463)
  applying package updates
  fix: add "style" to exports field (microsoft#27274)
  applying package updates
  feat(react-datepicker-compat): Make package public (microsoft#27524)
  fix: react-combobox defines fallbackPositions for popup on small screens (microsoft#27521)
  fix: use tabster to focus on trigger, instead of manually invoking .focus (microsoft#27512)
  add cxe-red to react-shared-context ownership (microsoft#27296)
  docs: add props tables for all exported Popover controls (microsoft#27503)
  fix: Update FormFieldShim to work with Field context changes (microsoft#27436)
  Fix wrong state narration for multiple selected legends (microsoft#27429)
  add codeowners to theme designer v9 (microsoft#27311)
  ...
Comment on lines +8 to +45
export function createElement<P extends {}>(
type: React.ElementType<P>,
props?: P | null,
...children: React.ReactNode[]
): React.ReactElement<P> | null {
if (!isSlotComponent(props)) {
return React.createElement(type, props, ...children);
}

const result = normalizeRenderFunction(props, children);
return React.createElement(
React.Fragment,
{},
result.renderFunction(type, { ...result.props, children: result.children }),
) as React.ReactElement<P>;
}

function normalizeRenderFunction<Props extends UnknownSlotProps>(
propsWithMetadata: WithMetadata<Props>,
overrideChildren?: React.ReactNode[],
): {
props: Props;
children: React.ReactNode;
renderFunction: SlotRenderFunction<Props>;
} {
const { [SLOT_RENDER_FUNCTION_SYMBOL]: renderFunction, children: externalChildren, ...props } = propsWithMetadata;

const children: React.ReactNode =
Array.isArray(overrideChildren) && overrideChildren.length > 0
? React.createElement(React.Fragment, {}, ...overrideChildren)
: externalChildren;

return {
children,
renderFunction,
props: props as UnknownSlotProps as Props,
};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like these functions could be simplified quite a bit, to reduce the number of Fragments and object spreads, and to be easier to understand:

export function createElement<P extends {}>(
  type: React.ElementType<P>,
  props?: P | null,
  ...children: React.ReactNode[]
): React.ReactElement<P> | null {
  if (!isSlotComponent(props)) {
    return React.createElement(type, props, children);
  }

  const { [SLOT_RENDER_FUNCTION_SYMBOL]: renderFunction, ...renderProps } = props;

  if (Array.isArray(children) && children.length > 0) {
    renderProps.children = children;
  }

  return React.createElement(React.Fragment, {}, renderFunction(type, renderProps));
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renderProps.children cannot be an array! it has to be converted to a fragment. otherwise we'll be requiring for the render function to properly provide keys for each children element.

in this simplification, renderProps.children might end up being an array.

Our tests are even catching this problem:

image

Nonetheless I can see clear simplifications with this method. I'll see to follow up on this with another PR

@bsunderhus bsunderhus deleted the react-jsx-runtime/feat--implements-custom-jsx-pragma branch April 14, 2023 08:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature]: Implements RFC: slot children render function support decision
4 participants