Skip to content

Commit 81db081

Browse files
committed
fix(flexbox): Prevent unserializable styles passed to flexbox worker
1 parent f55f7f5 commit 81db081

File tree

3 files changed

+63
-8
lines changed

3 files changed

+63
-8
lines changed

.changeset/cyan-wolves-sneeze.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@plextv/react-lightning-plugin-flexbox": patch
3+
---
4+
5+
(flexbox) Prevent unserializable values being passed to worker"

packages/plugin-flexbox/src/YogaManagerWorker.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { LightningElementStyle } from '@plextv/react-lightning';
22
import { EventEmitter } from 'tseep';
33
import { NodeOperations } from './types/NodeOperations';
44
import { SimpleDataView } from './util/SimpleDataView';
5+
import { toSerializableValue } from './util/toSerializableValue';
56
import Worker from './worker?worker&inline';
67
import type { YogaManager, YogaManagerEvents } from './YogaManager';
78

@@ -64,8 +65,6 @@ function wrapWorker<T>(worker: Worker): Workerized<T> {
6465
let _sizeRequestPromise: Promise<void> | null = null;
6566

6667
function flushSendStyles() {
67-
const needsRender = _needsRender;
68-
6968
if (Object.keys(_stylesToSend).length === 0) {
7069
return;
7170
}
@@ -76,7 +75,7 @@ function wrapWorker<T>(worker: Worker): Workerized<T> {
7675

7776
worker.postMessage({
7877
method: 'applyStyles',
79-
args: [_stylesToSend, !needsRender],
78+
args: [_stylesToSend, !_needsRender],
8079
});
8180

8281
_needsRender = false;
@@ -92,14 +91,23 @@ function wrapWorker<T>(worker: Worker): Workerized<T> {
9291
skipRender = false,
9392
) {
9493
if (style) {
95-
if (!_stylesToSend[elementId]) {
94+
let styleToSend = _stylesToSend[elementId];
95+
96+
if (!styleToSend) {
9697
_numStylesToSend++;
98+
styleToSend = {};
99+
_stylesToSend[elementId] = styleToSend;
97100
}
98101

99-
_stylesToSend[elementId] = {
100-
..._stylesToSend[elementId],
101-
...style,
102-
};
102+
// Add style props if they're serializable
103+
for (const [key, value] of Object.entries(style)) {
104+
const serializedValue = toSerializableValue(key, value);
105+
106+
if (serializedValue != null) {
107+
// @ts-expect-error
108+
styleToSend[key] = serializedValue;
109+
}
110+
}
103111
} else {
104112
delete _stylesToSend[elementId];
105113
_numStylesToSend--;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
function isPrimitiveValue(
2+
valueType:
3+
| 'string'
4+
| 'number'
5+
| 'bigint'
6+
| 'boolean'
7+
| 'symbol'
8+
| 'undefined'
9+
| 'object'
10+
| 'function',
11+
): boolean {
12+
return (
13+
valueType === 'string' ||
14+
valueType === 'number' ||
15+
valueType === 'boolean' ||
16+
valueType === 'bigint'
17+
);
18+
}
19+
20+
// biome-ignore lint/suspicious/noExplicitAny: Any value can be passed in
21+
export function toSerializableValue<T>(key: string, value: any): T | null {
22+
const valueType = typeof value;
23+
24+
if (isPrimitiveValue(valueType)) {
25+
return value as T;
26+
} else if (valueType === 'object') {
27+
// Only transforms can be objects
28+
if (key === 'transform') {
29+
return value as T;
30+
} else if ('current' in value && isPrimitiveValue(typeof value.current)) {
31+
// ...unless it's a reanimated animation. Unfortunately, there's no real
32+
// good way to serialize animations. There's also no real good way to
33+
// keep this logic in the reanimated plugin, so we'll just have to do it
34+
// here.
35+
return value.current as T;
36+
}
37+
38+
return null;
39+
}
40+
41+
return null;
42+
}

0 commit comments

Comments
 (0)