Skip to content

Commit

Permalink
Add stylex metadata to new plugins field
Browse files Browse the repository at this point in the history
And display it separately in DevTools, as read-only (for now)
  • Loading branch information
Brian Vaughn committed Dec 7, 2021
1 parent 578853e commit ac638f1
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

describe('Stylex plugin utils', () => {
let getStyleXValues;
let getStyleXData;
let styleElements;

function defineStyles(style) {
Expand All @@ -22,7 +22,7 @@ describe('Stylex plugin utils', () => {
}

beforeEach(() => {
getStyleXValues = require('../utils').getStyleXValues;
getStyleXData = require('../utils').getStyleXData;

styleElements = [];
});
Expand All @@ -47,16 +47,25 @@ describe('Stylex plugin utils', () => {
`);

expect(
getStyleXValues({
getStyleXData({
// The source/module styles are defined in
Example__style: 'Example__style',

// Map of CSS style to StyleX class name, booleans, or nested structures
display: 'foo',
flexDirection: 'baz',
alignItems: 'bar',
}),
).toMatchInlineSnapshot(`
Object {
"alignItems": "center",
"display": "flex",
"flexDirection": "center",
"resolvedStyles": Object {
"alignItems": "center",
"display": "flex",
"flexDirection": "center",
},
"sources": Array [
"Example__style",
],
}
`);
});
Expand All @@ -75,15 +84,25 @@ describe('Stylex plugin utils', () => {
`);

expect(
getStyleXValues([
{display: 'foo'},
{flexDirection: 'baz', alignItems: 'bar'},
getStyleXData([
{Example1__style: 'Example1__style', display: 'foo'},
{
Example2__style: 'Example2__style',
flexDirection: 'baz',
alignItems: 'bar',
},
]),
).toMatchInlineSnapshot(`
Object {
"alignItems": "center",
"display": "flex",
"flexDirection": "center",
"resolvedStyles": Object {
"alignItems": "center",
"display": "flex",
"flexDirection": "center",
},
"sources": Array [
"Example1__style",
"Example2__style",
],
}
`);
});
Expand All @@ -102,19 +121,29 @@ describe('Stylex plugin utils', () => {
`);

expect(
getStyleXValues([
getStyleXData([
false,
{display: 'foo'},
{Example1__style: 'Example1__style', display: 'foo'},
false,
false,
{flexDirection: 'baz', alignItems: 'bar'},
{
Example2__style: 'Example2__style',
flexDirection: 'baz',
alignItems: 'bar',
},
false,
]),
).toMatchInlineSnapshot(`
Object {
"alignItems": "center",
"display": "flex",
"flexDirection": "center",
"resolvedStyles": Object {
"alignItems": "center",
"display": "flex",
"flexDirection": "center",
},
"sources": Array [
"Example1__style",
"Example2__style",
],
}
`);
});
Expand All @@ -133,7 +162,11 @@ describe('Stylex plugin utils', () => {
`);

expect(
getStyleXValues({
getStyleXData({
// The source/module styles are defined in
Example__style: 'Example__style',

// Map of CSS style to StyleX class name, booleans, or nested structures
color: 'foo',
':hover': {
color: 'bar',
Expand All @@ -142,11 +175,16 @@ describe('Stylex plugin utils', () => {
}),
).toMatchInlineSnapshot(`
Object {
":hover": Object {
"color": "blue",
"textDecoration": "none",
"resolvedStyles": Object {
":hover": Object {
"color": "blue",
"textDecoration": "none",
},
"color": "black",
},
"color": "black",
"sources": Array [
"Example__style",
],
}
`);
});
Expand All @@ -165,17 +203,28 @@ describe('Stylex plugin utils', () => {
`);

expect(
getStyleXValues([
{display: 'foo'},
getStyleXData([
{Example1__style: 'Example1__style', display: 'foo'},
false,
[false, {flexDirection: 'baz'}, {alignItems: 'bar'}],
[
false,
{Example2__style: 'Example2__style', flexDirection: 'baz'},
{Example3__style: 'Example3__style', alignItems: 'bar'},
],
false,
]),
).toMatchInlineSnapshot(`
Object {
"alignItems": "center",
"display": "flex",
"flexDirection": "center",
"resolvedStyles": Object {
"alignItems": "center",
"display": "flex",
"flexDirection": "center",
},
"sources": Array [
"Example1__style",
"Example2__style",
"Example3__style",
],
}
`);
});
Expand Down
50 changes: 41 additions & 9 deletions packages/react-devtools-shared/src/backend/StyleX/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,66 @@
* @flow
*/

export type StyleXData = {|
sources: Array<string>,
resolvedStyles: Object,
|};

const cachedStyleNameToValueMap: Map<string, string> = new Map();

export function getStyleXValues(data: any, mappedStyles: Object = {}) {
export function getStyleXData(data: any): StyleXData {
const sources = new Set();
const resolvedStyles = {};

crawlData(data, sources, resolvedStyles);

return {
sources: Array.from(sources).sort(),
resolvedStyles,
};
}

export function crawlData(
data: any,
sources: Set<string>,
resolvedStyles: Object,
): void {
if (Array.isArray(data)) {
data.forEach(entry => {
if (Array.isArray(entry)) {
getStyleXValues(entry, mappedStyles);
crawlData(entry, sources, resolvedStyles);
} else {
crawlObjectProperties(entry, mappedStyles);
crawlObjectProperties(entry, sources, resolvedStyles);
}
});
} else {
crawlObjectProperties(data, mappedStyles);
crawlObjectProperties(data, sources, resolvedStyles);
}

return Object.fromEntries<string, any>(Object.entries(mappedStyles).sort());
resolvedStyles = Object.fromEntries<string, any>(
Object.entries(resolvedStyles).sort(),
);
}

function crawlObjectProperties(entry: Object, mappedStyles: Object) {
function crawlObjectProperties(
entry: Object,
sources: Set<string>,
resolvedStyles: Object,
): void {
const keys = Object.keys(entry);
keys.forEach(key => {
const value = entry[key];
if (typeof value === 'string') {
mappedStyles[key] = getPropertyValueForStyleName(value);
if (key === value) {
// Special case; this key is the name of the style's source/file/module.
sources.add(key);
} else {
resolvedStyles[key] = getPropertyValueForStyleName(value);
}
} else {
const nestedStyle = {};
mappedStyles[key] = nestedStyle;
getStyleXValues([value], nestedStyle);
resolvedStyles[key] = nestedStyle;
crawlData([value], sources, nestedStyle);
}
});
}
Expand Down
2 changes: 2 additions & 0 deletions packages/react-devtools-shared/src/backend/legacy/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,8 @@ export function attach(
rootType: null,
rendererPackageName: null,
rendererVersion: null,

plugins: [],
};
}

Expand Down
19 changes: 12 additions & 7 deletions packages/react-devtools-shared/src/backend/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ import {
import is from 'shared/objectIs';
import isArray from 'shared/isArray';
import hasOwnProperty from 'shared/hasOwnProperty';
import {getStyleXValues} from './StyleX/utils';
import {getStyleXData} from './StyleX/utils';

import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
import type {
Expand All @@ -102,6 +102,7 @@ import type {
NativeType,
PathFrame,
PathMatch,
Plugin,
ProfilingDataBackend,
ProfilingDataForRootBackend,
ReactRenderer,
Expand Down Expand Up @@ -3238,12 +3239,14 @@ export function attach(
targetErrorBoundaryID = getNearestErrorBoundaryID(fiber);
}

const modifiedProps = {
...memoizedProps,
};
const plugins: Array<Plugin> = [];

if (enableStyleXFeatures) {
if (modifiedProps.hasOwnProperty('xstyle')) {
modifiedProps.xstyle = getStyleXValues(modifiedProps.xstyle);
if (memoizedProps.hasOwnProperty('xstyle')) {
plugins.push({
type: 'stylex',
data: getStyleXData(memoizedProps.xstyle),
});
}
}

Expand Down Expand Up @@ -3292,7 +3295,7 @@ export function attach(
// TODO Review sanitization approach for the below inspectable values.
context,
hooks,
props: modifiedProps,
props: memoizedProps,
state: showState ? memoizedState : null,
errors: Array.from(errors.entries()),
warnings: Array.from(warnings.entries()),
Expand All @@ -3306,6 +3309,8 @@ export function attach(
rootType,
rendererPackageName: renderer.rendererPackageName,
rendererVersion: renderer.version,

plugins,
};
}

Expand Down
11 changes: 11 additions & 0 deletions packages/react-devtools-shared/src/backend/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,14 @@ export type OwnersList = {|
owners: Array<SerializedElement> | null,
|};

// For now, let's only support a hard-coded set of plugins.
type PluginType = 'stylex';

export type Plugin = {
type: PluginType,
data: any,
};

export type InspectedElement = {|
id: number,

Expand Down Expand Up @@ -265,6 +273,9 @@ export type InspectedElement = {|
// Meta information about the renderer that created this element.
rendererPackageName: string | null,
rendererVersion: string | null,

// Array of UI plugins/visualizations for the inspected element.
plugins: Array<Plugin>,
|};

export const InspectElementErrorType = 'error';
Expand Down
2 changes: 2 additions & 0 deletions packages/react-devtools-shared/src/backendAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ export function convertInspectedElementBackendToFrontend(
owners,
context,
hooks,
plugins,
props,
rendererPackageName,
rendererVersion,
Expand All @@ -233,6 +234,7 @@ export function convertInspectedElementBackendToFrontend(
hasLegacyContext,
id,
key,
plugins,
rendererPackageName,
rendererVersion,
rootType,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.Source {
color: var(--color-dim);
margin-left: 1rem;
overflow: auto;
text-overflow: ellipsis;
}
Loading

0 comments on commit ac638f1

Please sign in to comment.