Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .yarn/patches/cypress-npm-15.4.0-c92384506d.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
diff --git a/types/cypress-expect.d.ts b/types/cypress-expect.d.ts
index bea4c7f566d362f988b534ac4ef2791f4052ed6f..bd0cbe5c6c7cae7a1b47aad53e6df50bae231fa7 100644
--- a/types/cypress-expect.d.ts
+++ b/types/cypress-expect.d.ts
@@ -1,3 +1,3 @@
// Cypress adds chai expect and assert to global
-declare var expect: Chai.ExpectStatic
-declare var assert: Chai.AssertStatic
+// declare var expect: Chai.ExpectStatic
+// declare var assert: Chai.AssertStatic
24 changes: 12 additions & 12 deletions apps/common-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"@shopify/flash-list": "2.1.0",
"d3-shape": "3.2.0",
"fuse.js": "patch:fuse.js@npm%3A7.1.0#~/.yarn/patches/fuse.js-npm-7.1.0-5dcae892a6.patch",
"react": "19.1.1",
"react-dom": "19.1.1",
"react": "19.2.3",
"react-dom": "19.2.3",
"react-native-gesture-handler": "2.28.0",
"react-native-mmkv": "4.0.0",
"react-native-nitro-modules": "0.31.9",
Expand All @@ -42,20 +42,20 @@
"react-native-safe-area-context": "5.6.1",
"react-native-screens": "4.19.0-nightly-20251125-46052f31e",
"react-native-svg": "15.14.0",
"react-native-worklets": "0.7.2",
"react-native-worklets": "0.8.0-nightly-20260211-96ab3f00d",
"react-strict-dom": "0.0.54"
},
"devDependencies": {
"@babel/core": "7.28.4",
"@babel/preset-env": "7.28.3",
"@babel/runtime": "7.28.4",
"@react-native-community/cli": "20.0.0",
"@react-native-community/cli-platform-android": "20.0.0",
"@react-native-community/cli-platform-ios": "20.0.0",
"@react-native/babel-preset": "0.82.0",
"@react-native/eslint-config": "0.82.0",
"@react-native/metro-config": "0.82.0",
"@react-native/typescript-config": "0.82.0",
"@react-native-community/cli": "20.1.0",
"@react-native-community/cli-platform-android": "20.1.0",
"@react-native-community/cli-platform-ios": "20.1.0",
"@react-native/babel-preset": "0.84.0",
"@react-native/eslint-config": "0.84.0",
"@react-native/metro-config": "0.84.0",
"@react-native/typescript-config": "0.84.0",
"@tsconfig/react-native": "3.0.0",
"@types/d3-shape": "3.1.7",
"@types/jest": "30.0.0",
Expand All @@ -65,8 +65,8 @@
"jest": "30.2.0",
"madge": "8.0.0",
"prettier": "3.6.2",
"react-native": "0.82.0",
"react-test-renderer": "19.1.1",
"react-native": "0.84.0",
"react-test-renderer": "19.2.3",
"typescript": "5.8.3",
"typescript-eslint": "8.46.0"
}
Expand Down
50 changes: 40 additions & 10 deletions apps/common-app/scripts/dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,71 @@ const path = require('path');
/**
* @param {Object<string, string>} dependencies
* @param {Set<string>} exclude
* @param {string} appDir
*/
function resolveDependencies(dependencies = {}, exclude) {
function resolveDependencies(dependencies = {}, exclude, appDir) {
return Object.fromEntries(
Object.keys(dependencies)
.filter((name) => !exclude.has(name))
.map((name) => [
name,
{ root: path.resolve(__dirname, `../../../node_modules/${name}`) },
{
root: getRootPath(name, appDir),
},
])
);
}

/**
* @param {string} moduleName
* @param {string} appDir
*/
function getRootPath(moduleName, appDir) {
try {
return path.dirname(
require.resolve(`${moduleName}/package.json`, {
paths: [appDir, __dirname],
})
);
} catch {
// If a package defines an `exports` field, `require.resolve` can fail.
// Fortunately, none of the packages we care about cause this issue.
}
}

/**
* This function will return the dependencies from the common-app package that
* aren't listed in the current app's package.json
*
* @param {string} currentAppDir - The current app directory (e.g. __dirname)
* @param {string[]} exclude - The dependencies to exclude from the common-app
* @param {string} appDir - The directory of the app that wants to obtain the
* dependencies. Used in resolution priority.
* @param {string[]} [exclude=[]] - The dependencies to exclude from the
* common-app. Default is `[]`
*/
function getDependencies(currentAppDir = '.', exclude = []) {
function getDependencies(appDir, exclude = []) {
const commonAppDir = path.resolve(__dirname, '..');
const commonAppPkg = require(path.resolve(commonAppDir, 'package.json'));

const currentAppPkg = require(path.resolve(currentAppDir, 'package.json'));
const appPkg = require(path.resolve(appDir, 'package.json'));

const excludedDependencies = new Set([
...Object.keys(currentAppPkg.devDependencies),
...Object.keys(currentAppPkg.dependencies),
...Object.keys(appPkg.devDependencies),
...Object.keys(appPkg.dependencies),
...exclude,
]);

return {
// Get all common-app dependencies that aren't already in the current app
...resolveDependencies(commonAppPkg.devDependencies, excludedDependencies),
...resolveDependencies(commonAppPkg.dependencies, excludedDependencies),
...resolveDependencies(
commonAppPkg.devDependencies,
excludedDependencies,
appDir
),
...resolveDependencies(
commonAppPkg.dependencies,
excludedDependencies,
appDir
),
};
}

Expand Down
239 changes: 239 additions & 0 deletions apps/common-app/src/apps/reanimated/examples/FetchExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
import React from 'react';
import { StyleSheet, View, Button, Text } from 'react-native';
import {
createWorkletRuntime,
scheduleOnRuntime,
type WorkletRuntime,
createSynchronizable,
} from 'react-native-worklets';
import axios from 'axios';

export default function App() {
let elephantRuntime: WorkletRuntime;

let giraffeRuntime: WorkletRuntime;

let monkeyRuntime: WorkletRuntime;

const shouldStop = createSynchronizable(false);

function testXHR(
readystateHandler: boolean,
progressHandler: boolean,
arraybuffer: boolean,
chunked: boolean
) {
'worklet';
const xhr = new globalThis.XMLHttpRequest();

const state = {
readystateHandler,
progressHandler,
arraybuffer,
chunked,
downloading: false,
contentLength: 1,
responseLength: 0,
progressTotal: 1,
progressLoaded: 0,
cancelled: false,
};

const onreadystatechange = () => {
if (xhr.readyState === xhr.HEADERS_RECEIVED) {
const contentLength = parseInt(
xhr.getResponseHeader('Content-Length')!,
10
);
state.contentLength = contentLength;
state.responseLength = 0;
} else if (xhr.readyState === xhr.LOADING && xhr.response) {
state.responseLength = (xhr.response as Record<string, unknown>)
.length as number;
}
};
const onprogress = (event: ProgressEvent) => {
state.progressTotal = event.total;
state.progressLoaded = event.loaded;
};
const onerror = (event: ProgressEvent) => {
state.downloading = false;
throw new Error(
`XHR error: ${event.type} - ${xhr.status} - ${xhr.responseText} - ${event.toString()}`
);
};

if (state.readystateHandler) {
xhr.onreadystatechange = onreadystatechange;
}
if (state.progressHandler) {
xhr.onprogress = onprogress;
}
if (state.arraybuffer) {
xhr.responseType = 'arraybuffer';
}
xhr.onerror = onerror;
xhr.onload = () => {
state.downloading = false;
if (state.cancelled) {
state.cancelled = false;
return;
}
if (xhr.status === 200) {
let responseType = `Response is a string, ${(xhr.response as Record<string, unknown>).length as number} characters long.`;
if (xhr.response instanceof ArrayBuffer) {
responseType = `Response is an ArrayBuffer, ${xhr.response.byteLength} bytes long.`;
}
console.log('Download complete!', responseType);
} else if (xhr.status !== 0) {
console.error(
`Server returned HTTP status of ${xhr.status}: ${xhr.responseText}`
);
} else {
console.error(xhr.responseText);
}
};
if (state.chunked) {
xhr.open(
'GET',
'https://filesamples.com/samples/ebook/azw3/Around%20the%20World%20in%2028%20Languages.azw3'
);
} else {
xhr.open(
'GET',
'https://filesamples.com/samples/document/txt/sample3.txt'
);
// Avoid gzip so we can actually show progress
xhr.setRequestHeader('Accept-Encoding', '');
}
xhr.send();

state.downloading = true;
}

function testFetch(
runtime: WorkletRuntime,
runtimes: {
elephant: WorkletRuntime;
giraffe: WorkletRuntime;
monkey: WorkletRuntime;
},
count: number
) {
'worklet';
if (count > 8) {
return;
}

axios({
method: 'get',
url: `https://jsonplaceholder.typicode.com/todos/${count}`,
})
.then((response) => {
console.log(`Received ${count} response on ${runtime.name}`);
console.log(response.data);
})
.catch((error) => {
shouldStop.setBlocking(true);
console.error('Axios error:', error);
});
if (count > 8) {
return;
}

const nextRuntime =
runtime.name === runtimes.elephant.name
? runtimes.giraffe
: runtime.name === runtimes.giraffe.name
? runtimes.monkey
: runtimes.elephant;

setTimeout(() => {
if (!shouldStop.getDirty()) {
scheduleOnRuntime(
nextRuntime,
testFetch,
nextRuntime,
runtimes,
count + 1
);
}
}, 100);
}

function initializeRuntimes() {
if (!elephantRuntime) {
elephantRuntime = createWorkletRuntime({
name: 'elephant',
});
giraffeRuntime = createWorkletRuntime({
name: 'giraffe',
});
monkeyRuntime = createWorkletRuntime({
name: 'monkey',
});
}
}

function testWebSocket() {
'worklet';
const socket = new WebSocket('ws://localhost:8080');

socket.addEventListener('open', () => {});
}
return (
<View style={styles.container}>
<Text>Check console output</Text>
<Button
title="Test fetch chain"
onPress={() => {
initializeRuntimes();
shouldStop.setBlocking(false);
scheduleOnRuntime(
elephantRuntime,
testFetch,
elephantRuntime,
{
elephant: elephantRuntime,
giraffe: giraffeRuntime,
monkey: monkeyRuntime,
},
1
);
}}
/>
<Button
title="Test XHR"
onPress={() => {
initializeRuntimes();
scheduleOnRuntime(
elephantRuntime,
testXHR,
false,
false,
false,
false
);
scheduleOnRuntime(giraffeRuntime, testXHR, true, false, false, false);
scheduleOnRuntime(monkeyRuntime, testXHR, true, true, false, false);
scheduleOnRuntime(elephantRuntime, testXHR, true, true, true, false);
scheduleOnRuntime(giraffeRuntime, testXHR, true, true, true, true);
}}
/>
<Button
title="Test WebSocket (not implemented)"
onPress={() => {
scheduleOnRuntime(elephantRuntime, testWebSocket);
}}
/>
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
Loading
Loading