Skip to content

Commit 8e4c822

Browse files
fix(native): share the :root variable registries across a dual-package split (#410)
* fix(native): share the :root variable registries across a dual-package split Re-cut onto main (a5002c5). The test reads the registries through jest.requireActual, because main's jest runs no dynamic import. * refactor(native): state the registry constraints in one line each --------- Co-authored-by: dan <dan@danstepanov.com>
1 parent eda2b28 commit 8e4c822

2 files changed

Lines changed: 70 additions & 13 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { rootVariables, universalVariables } from "../../native-internal/root";
2+
3+
test("the module's exports are the registries published on globalThis", () => {
4+
const registries = globalThis.__react_native_css_root_variable_registries;
5+
6+
expect(registries).toBeDefined();
7+
expect(rootVariables).toBe(registries?.root);
8+
expect(universalVariables).toBe(registries?.universal);
9+
});
10+
11+
test("a second copy of the module shares the registries and does not re-seed", () => {
12+
// resetModules evaluates the module again against the same globalThis, as a second build in one bundle does
13+
const firstCopy = jest.requireActual<
14+
typeof import("../../native-internal/root")
15+
>("../../native-internal/root");
16+
17+
expect(firstCopy.rootVariables("__rn-css-rem").get()).toBe(14);
18+
firstCopy.rootVariables("__rn-css-rem").set([[16]]);
19+
20+
jest.resetModules();
21+
const secondCopy = jest.requireActual<
22+
typeof import("../../native-internal/root")
23+
>("../../native-internal/root");
24+
25+
// The module body really re-ran, so the assertions below are about two copies
26+
expect(secondCopy).not.toBe(firstCopy);
27+
28+
expect(secondCopy.rootVariables).toBe(firstCopy.rootVariables);
29+
expect(secondCopy.rootVariables("__rn-css-rem").get()).toBe(16);
30+
});

‎src/native-internal/root.ts‎

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,43 @@ const rootVariableFamily = () => {
2929
});
3030
};
3131

32-
export const rootVariables = rootVariableFamily();
33-
export const universalVariables = rootVariableFamily();
34-
35-
rootVariables("__rn-css-rem").set([[14]]);
36-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
37-
rootVariables("__rn-css-color").set([
38-
[
39-
Platform.OS === "ios"
40-
? PlatformColor("label", "labelColor")
41-
: PlatformColor("?attr/textColorPrimary", "SystemBaseHighColor"),
42-
],
43-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
44-
] as any);
32+
interface RootVariableRegistries {
33+
root: ReturnType<typeof rootVariableFamily>;
34+
universal: ReturnType<typeof rootVariableFamily>;
35+
}
36+
37+
declare global {
38+
var __react_native_css_root_variable_registries:
39+
| RootVariableRegistries
40+
| undefined;
41+
}
42+
43+
// Seeded with the registries, so a copy that loads after the stylesheet inject keeps the project's rem
44+
function createRootVariableRegistries(): RootVariableRegistries {
45+
const registries: RootVariableRegistries = {
46+
root: rootVariableFamily(),
47+
universal: rootVariableFamily(),
48+
};
49+
50+
registries.root("__rn-css-rem").set([[14]]);
51+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
52+
registries.root("__rn-css-color").set([
53+
[
54+
Platform.OS === "ios"
55+
? PlatformColor("label", "labelColor")
56+
: PlatformColor("?attr/textColorPrimary", "SystemBaseHighColor"),
57+
],
58+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
59+
] as any);
60+
61+
return registries;
62+
}
63+
64+
// The exports map gives import and require different builds, and Metro resolves each per requesting module
65+
globalThis.__react_native_css_root_variable_registries ??=
66+
createRootVariableRegistries();
67+
68+
export const rootVariables =
69+
globalThis.__react_native_css_root_variable_registries.root;
70+
export const universalVariables =
71+
globalThis.__react_native_css_root_variable_registries.universal;

0 commit comments

Comments
 (0)