Skip to content

Instantly share code, notes, and snippets.

@Kudo
Created February 27, 2025 12:48
Show Gist options
  • Save Kudo/acf48613b1c5b3f85e524d3e26078094 to your computer and use it in GitHub Desktop.
Save Kudo/acf48613b1c5b3f85e524d3e26078094 to your computer and use it in GitHub Desktop.
Expo DOM components for Android 9 support
module.exports = function (api) {
api.cache(true);
return {
presets: [
'babel-preset-expo',
],
plugins: [
['@babel/plugin-transform-class-properties', { loose: true }],
['@babel/plugin-transform-private-methods', { loose: true }],
['@babel/plugin-transform-private-property-in-object', { loose: true }],
'@babel/plugin-transform-optional-chaining',
'@babel/plugin-transform-nullish-coalescing-operator',
'babel-plugin-transform-globalthis',
],
};
};
// The other version supports per platform transforms. That would have slower bundling time.
module.exports = function (api) {
let platform
api.caller((caller) => {
platform = caller.platform;
});
// Cache must be disabled
api.cache(false);
if (platform === 'web') {
return {
presets: [
'babel-preset-expo',
[
'@babel/preset-env',
{
'targets': {
'chrome': '66',
},
},
],
],
plugins: [
['@babel/plugin-transform-class-properties', { loose: true }],
['@babel/plugin-transform-private-methods', { loose: true }],
['@babel/plugin-transform-private-property-in-object', { loose: true }],
'babel-plugin-transform-globalthis',
],
};
}
return {
presets: ['babel-preset-expo'],
};
};
diff --git a/node_modules/expo/src/dom/dom-entry.tsx b/node_modules/expo/src/dom/dom-entry.tsx
index 43a920a..88c3762 100644
--- a/node_modules/expo/src/dom/dom-entry.tsx
+++ b/node_modules/expo/src/dom/dom-entry.tsx
@@ -57,12 +57,16 @@ export function registerDOMComponent(AppModule: any) {
function DOMComponentRoot(props) {
// Props listeners
const [marshalledProps, setProps] = React.useState(() => {
- if (typeof window.$$EXPO_INITIAL_PROPS === 'undefined') {
+ let initialProps = undefined;
+ try {
+ initialProps = JSON.parse(window.ReactNativeWebView.injectedObjectJson()).initialProps;
+ } catch {}
+ if (typeof initialProps === 'undefined') {
throw new Error(
'Initial props are not defined. This is a bug in the DOM Component runtime.'
);
}
- return window.$$EXPO_INITIAL_PROPS;
+ return initialProps;
});
React.useEffect(() => {
@@ -79,11 +83,10 @@ export function registerDOMComponent(AppModule: any) {
const proxyActions = React.useMemo(() => {
if (!marshalledProps.names) return {};
// Create a named map { [name: string]: ProxyFunction }
- return Object.fromEntries(
- marshalledProps.names.map((key) => {
- return [key, ACTIONS[key]];
- })
- );
+ return marshalledProps.names.reduce((acc, key) => {
+ acc[key] = ACTIONS[key];
+ return acc;
+ }, {});
}, [marshalledProps.names]);
return <AppModule {...props} {...(marshalledProps.props || {})} {...proxyActions} />;
diff --git a/node_modules/expo/src/dom/injection.ts b/node_modules/expo/src/dom/injection.ts
index 66f6f35..eaf0a8b 100644
--- a/node_modules/expo/src/dom/injection.ts
+++ b/node_modules/expo/src/dom/injection.ts
@@ -17,10 +17,12 @@ export const getInjectEventScript = <T extends BridgeMessage<any>>(detail: T) =>
export function getInjectBodySizeObserverScript() {
return `;(function observeDocumentBodySize() {
- window.addEventListener('DOMContentLoaded', () => {
+ if (window.ReactNativeWebView == null) { return; }
+
+ function registerObserver() {
new ResizeObserver(entries => {
const { width, height } = entries[0].contentRect;
- window.ReactNativeWebView?.postMessage(JSON.stringify({
+ window.ReactNativeWebView.postMessage(JSON.stringify({
type: '${MATCH_CONTENTS_EVENT}',
data: {
width,
@@ -29,13 +31,21 @@ export function getInjectBodySizeObserverScript() {
}));
})
.observe(document.body);
- window.ReactNativeWebView?.postMessage(JSON.stringify({
+ window.ReactNativeWebView.postMessage(JSON.stringify({
type: '${MATCH_CONTENTS_EVENT}',
data: {
width: document.body.clientWidth,
height: document.body.clientHeight,
},
}));
+ }
+
+ if (document.readyState === 'complete') {
+ registerObserver();
+ return;
+ }
+ window.addEventListener('DOMContentLoaded', () => {
+ registerObserver();
});
})();
true;`;
diff --git a/node_modules/expo/src/dom/webview-wrapper.tsx b/node_modules/expo/src/dom/webview-wrapper.tsx
index 3ee2761..5858ec6 100644
--- a/node_modules/expo/src/dom/webview-wrapper.tsx
+++ b/node_modules/expo/src/dom/webview-wrapper.tsx
@@ -117,11 +117,13 @@ const RawWebView = React.forwardRef<object, Props>(({ dom, filePath, ...marshalP
...dom,
containerStyle: [containerStyle, debugZeroHeightStyle, dom?.containerStyle],
onLayout: __DEV__ ? debugOnLayout : dom?.onLayout,
- injectedJavaScriptBeforeContentLoaded: [
- // On first mount, inject `$$EXPO_INITIAL_PROPS` with the initial props.
- `window.$$EXPO_INITIAL_PROPS = ${JSON.stringify(smartActions)};true;`,
+ injectedJavaScriptObject: {
+ initialProps: smartActions,
+ },
+ injectedJavaScriptForMainFrameOnly: true,
+ injectedJavaScript: [
dom?.matchContents ? getInjectBodySizeObserverScript() : null,
- dom?.injectedJavaScriptBeforeContentLoaded,
+ dom?.injectedJavaScript,
'true;',
]
.filter(Boolean)
diff --git a/node_modules/metro/src/lib/getPreludeCode.js b/node_modules/metro/src/lib/getPreludeCode.js
index 2a3612f..6f1e8ea 100644
--- a/node_modules/metro/src/lib/getPreludeCode.js
+++ b/node_modules/metro/src/lib/getPreludeCode.js
@@ -7,10 +7,10 @@ function getPreludeCode({
requireCycleIgnorePatterns,
}) {
const vars = [
- "__BUNDLE_START_TIME__=globalThis.nativePerformanceNow?nativePerformanceNow():Date.now()",
+ "__BUNDLE_START_TIME__=this.nativePerformanceNow?nativePerformanceNow():Date.now()",
`__DEV__=${String(isDev)}`,
...formatExtraVars(extraVars),
- "process=globalThis.process||{}",
+ "process=this.process||{}",
`__METRO_GLOBAL_PREFIX__='${globalPrefix}'`,
];
if (isDev) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment