peachsim 0.1.1406 → 0.1.1465
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -4
- package/README.md +22 -2
- package/cli/app-fonts.ts +50 -44
- package/cli/bin.ts +5 -4
- package/cli/bridge-diagnostics.ts +5 -0
- package/cli/bridge-flow-runner.ts +21 -13
- package/cli/cloud-client.ts +4 -3
- package/cli/commands/control.ts +155 -123
- package/cli/commands/daemon-mac-app.ts +3 -3
- package/cli/commands/daemon.ts +2 -2
- package/cli/commands/do-chain.ts +9 -2
- package/cli/commands/electron.ts +4 -1
- package/cli/commands/inspect/core.ts +1 -1
- package/cli/commands/inspect/settle.ts +19 -7
- package/cli/commands/inspect/settling.ts +92 -56
- package/cli/commands/inspect/wait-idle.ts +21 -9
- package/cli/commands/inspect/wait-ready.ts +22 -8
- package/cli/commands/inspect.ts +101 -134
- package/cli/commands/setup.ts +26 -16
- package/cli/commands/upgrade.ts +53 -9
- package/cli/desktop-companion.ts +1 -1
- package/cli/drivers/playwright-sim-host.ts +32 -13
- package/cli/drivers/playwright.ts +3 -3
- package/cli/main.ts +14 -5
- package/cli/outbound-endpoints.ts +1 -9
- package/detox/index.ts +6 -1
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +3 -3
- package/dist-lib/bridge-contract.mjs +3 -3
- package/dist-lib/bundle-channel.cjs +322 -274
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/config.mjs +1 -1
- package/dist-lib/detox/index.cjs +512 -122
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +69 -33
- package/dist-lib/expo-swift-metadata.cjs +1 -1
- package/dist-lib/expo-swift-metadata.mjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +3650 -3528
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +327 -123
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +10 -5
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +49 -47
- package/dist-lib/native-app-identity-project.cjs +1 -1
- package/dist-lib/native-app-identity-project.mjs +1 -1
- package/dist-lib/native-app-identity.cjs +1 -1
- package/dist-lib/native-app-identity.mjs +1 -1
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +23 -17
- package/dist-lib/sdk.cjs +99 -61
- package/dist-lib/sdk.mjs +97 -61
- package/dist-lib/skills.cjs +3347 -3051
- package/dist-lib/swift-compile.cjs +26 -12
- package/dist-lib/swift-compile.mjs +26 -12
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +2 -2
- package/dist-lib/swift-submit.mjs +2 -2
- package/dist-lib/swift-toolchain.cjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +66 -31
- package/dist-lib/vite.cjs +1 -1
- package/dist-lib/worklet-executable.cjs +5 -1
- package/dist-lib/worklet-executable.mjs +5 -1
- package/kotlin/AppSources/android/view/Window.kt +2 -0
- package/kotlin/AppSources/dev/peach/app/PeachApp.kt +1 -1
- package/kotlin/ComposeSources/PeachComposeHost.kt +35 -9
- package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +2 -2
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +9 -6
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +4 -4
- package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +2 -2
- package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +22 -8
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +0 -3
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +10 -9
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +6 -5
- package/kotlin/fixtures/import-drawing/Drawing.d.kt.ts +7 -0
- package/kotlin/fixtures/import-drawing/Drawing.kt +101 -0
- package/kotlin/fixtures/import-drawing/ImportDrawing.native.tsx +18 -0
- package/kotlin/fixtures/import-drawing/README.md +34 -0
- package/kotlin/fixtures/import-drawing/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-drawing/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-drawing/package.json +23 -0
- package/kotlin/fixtures/import-drawing/tsconfig.json +20 -0
- package/kotlin/fixtures/import-drawing/vite.config.ts +20 -0
- package/kotlin/fixtures/import-scroll/ImportNested.native.tsx +10 -0
- package/kotlin/fixtures/import-scroll/Nested.d.kt.ts +4 -0
- package/kotlin/fixtures/import-scroll/README.md +15 -0
- package/kotlin/fixtures/import-scroll/app/nested+spa.tsx +1 -0
- package/kotlin/fixtures/import-values/ImportValues.native.tsx +26 -0
- package/kotlin/fixtures/import-values/README.md +6 -1
- package/kotlin/fixtures/import-values/Values.d.kt.ts +4 -0
- package/kotlin/fixtures/import-values/Values.kt +18 -0
- package/kotlin/tools/expo-types.main.kts +17 -5
- package/package.json +2 -1
- package/scripts/dev-server-scanner.ts +33 -23
- package/src/assetCatalogContract.ts +7 -0
- package/src/bridge-contract.ts +21 -3
- package/src/connect.ts +18 -5
- package/src/desktop-host-delivery.ts +33 -3
- package/src/expo-swift-host.ts +6 -3
- package/src/host/bridge-host.ts +2 -0
- package/src/host/fetch-proxy-transport.ts +8 -0
- package/src/kotlin-host.ts +11 -5
- package/src/native-firebase-config.ts +95 -54
- package/src/process-output.ts +16 -0
- package/src/sdk.ts +6 -1
- package/src/sim-client.ts +6 -1
- package/src/swift-compile.ts +36 -15
- package/src/swift-distribution.lock.json +8 -8
- package/src/swift-standin-emit.ts +10 -1
- package/src/swift-standins.ts +21 -7
- package/src/swift-submit.ts +6 -1
- package/src/worklet-executable.ts +7 -2
- /package/kotlin/fixtures/{kotlin-app-variants → import-scroll}/Nested.kt +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { acquireChromiumAdmission } from '../../../../scripts/lib/chromium-admission'
|
|
1
2
|
// the detached browser host, as CJS source.
|
|
2
3
|
//
|
|
3
4
|
// it resolves playwright from the absolute path the driver hands it, launches
|
|
@@ -117,6 +118,7 @@ const automateWebViewFrames = ${automateWebViewFrames.toString()};
|
|
|
117
118
|
const webViewAutomationHelpers = ${webViewAutomationHelpersSource()};
|
|
118
119
|
const readBrowserCompositeCaptureRequest = ${readBrowserCompositeCaptureRequest.toString()};
|
|
119
120
|
const resolveBrowserCompositeCdpClip = ${resolveBrowserCompositeCdpClip.toString()};
|
|
121
|
+
const acquireChromiumAdmission = ${acquireChromiumAdmission.toString()};
|
|
120
122
|
// chrome tree reaper — playwright's browser.close() and even SIGKILLing the
|
|
121
123
|
// root chrome process do NOT reliably take down the helper tree (gpu, renderer,
|
|
122
124
|
// network/storage utilities). they reparent to launchd/init and survive, each
|
|
@@ -224,6 +226,17 @@ const cleanupProfile = () => {
|
|
|
224
226
|
let connected = false;
|
|
225
227
|
let shuttingDown = false;
|
|
226
228
|
let desktopHost = null;
|
|
229
|
+
// the host runs the tenant's workers in its realms, where the browser cannot see them; it
|
|
230
|
+
// evaluates there over node ipc and answers each realm's value, null where one throws
|
|
231
|
+
const hostEvaluations = new Map();
|
|
232
|
+
let hostEvaluation = 0;
|
|
233
|
+
const hostRealms = {
|
|
234
|
+
evaluate: (fn, args) => new Promise((resolve) => {
|
|
235
|
+
const id = ++hostEvaluation;
|
|
236
|
+
hostEvaluations.set(id, resolve);
|
|
237
|
+
desktopHost.send({ t: 'evaluate', id, expression: '(' + fn + ')(' + JSON.stringify(args) + ')' });
|
|
238
|
+
}).then((values) => values.find((value) => value !== null) ?? null),
|
|
239
|
+
};
|
|
227
240
|
const stopDesktopHost = async () => {
|
|
228
241
|
if (!desktopHost || desktopHost.exitCode !== null || desktopHost.signalCode !== null) return;
|
|
229
242
|
const exited = new Promise((resolve) => desktopHost.once('exit', resolve));
|
|
@@ -233,28 +246,25 @@ const cleanupProfile = () => {
|
|
|
233
246
|
// the host's ready line follows its CDP auto-attach registration, so every
|
|
234
247
|
// page this browser opens afterwards is composited by it
|
|
235
248
|
const startDesktopHost = async () => {
|
|
236
|
-
const port = await new Promise((resolve, reject) => {
|
|
237
|
-
const server = require('net').createServer();
|
|
238
|
-
server.once('error', reject);
|
|
239
|
-
server.listen(0, '127.0.0.1', () => {
|
|
240
|
-
const { port } = server.address();
|
|
241
|
-
server.close(() => resolve(port));
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
249
|
desktopHost = spawn(
|
|
245
250
|
hostCommand[0],
|
|
246
|
-
[...hostCommand.slice(1), '--port',
|
|
247
|
-
{ stdio: ['ignore', 'ignore', 'pipe'] },
|
|
251
|
+
[...hostCommand.slice(1), '--port', '0', '--browser', 'http://127.0.0.1:' + cdpPort, '--headless'],
|
|
252
|
+
{ stdio: ['ignore', 'ignore', 'pipe', 'ipc'] },
|
|
248
253
|
);
|
|
254
|
+
desktopHost.on('message', (m) => {
|
|
255
|
+
hostEvaluations.get(m.id)?.(m.values);
|
|
256
|
+
hostEvaluations.delete(m.id);
|
|
257
|
+
});
|
|
249
258
|
let log = '';
|
|
250
|
-
await new Promise((resolve, reject) => {
|
|
259
|
+
const hostUrl = await new Promise((resolve, reject) => {
|
|
251
260
|
const timer = setTimeout(() => reject(new Error('[playwright-driver] desktop host did not start within 30s: ' + log)), 30000);
|
|
252
261
|
desktopHost.once('error', (error) => { clearTimeout(timer); reject(error); });
|
|
253
262
|
desktopHost.once('exit', (code) => { clearTimeout(timer); reject(new Error('[playwright-driver] desktop host exited during startup (' + code + '): ' + log)); });
|
|
254
263
|
desktopHost.stderr.on('data', (data) => {
|
|
255
264
|
process.stderr.write(data);
|
|
256
265
|
if (log.length < 65536) log += String(data);
|
|
257
|
-
|
|
266
|
+
const ready = /peach host on (http:\\/\\/127\\.0\\.0\\.1:\\d+\\/)/.exec(log);
|
|
267
|
+
if (ready) { clearTimeout(timer); resolve(ready[1]); }
|
|
258
268
|
});
|
|
259
269
|
});
|
|
260
270
|
desktopHost.removeAllListeners('exit');
|
|
@@ -262,7 +272,7 @@ const cleanupProfile = () => {
|
|
|
262
272
|
process.stderr.write('[playwright-driver] desktop host exited (' + code + ')\\n');
|
|
263
273
|
void shutdown(3);
|
|
264
274
|
});
|
|
265
|
-
process.stderr.write('[playwright-driver] desktop host attached on ' +
|
|
275
|
+
process.stderr.write('[playwright-driver] desktop host attached on ' + hostUrl + '\\n');
|
|
266
276
|
};
|
|
267
277
|
const clearConnectTimer = () => {
|
|
268
278
|
if (connectTimer) {
|
|
@@ -496,6 +506,14 @@ const cleanupProfile = () => {
|
|
|
496
506
|
// an orphaned helper back to us, which is the leak we just fixed.
|
|
497
507
|
return await pw.chromium.launchPersistentContext(profileDir, opts);
|
|
498
508
|
};
|
|
509
|
+
// the host-wide chromium slot is held for this host's life; its exit frees it
|
|
510
|
+
await acquireChromiumAdmission({
|
|
511
|
+
fs: require('fs'),
|
|
512
|
+
os: require('os'),
|
|
513
|
+
path: require('path'),
|
|
514
|
+
childProcess: require('child_process'),
|
|
515
|
+
label: 'peach sim host ' + profileDir,
|
|
516
|
+
});
|
|
499
517
|
let launchErr = null;
|
|
500
518
|
let launchedChannel = null;
|
|
501
519
|
for (const channel of channelsToTry) {
|
|
@@ -569,6 +587,7 @@ const cleanupProfile = () => {
|
|
|
569
587
|
bootstrapSource: '(' + ${JSON.stringify(WEBVIEW_HOST_BOOTSTRAP_SOURCE)} + ')(' + JSON.stringify(webViewTimingName) + ');',
|
|
570
588
|
},
|
|
571
589
|
webViewAutomationHelpers,
|
|
590
|
+
hostCommand ? () => [hostRealms] : (page) => page.workers(),
|
|
572
591
|
);
|
|
573
592
|
await context.exposeBinding('__sootsimHostClose', async () => {
|
|
574
593
|
await shutdown(0);
|
|
@@ -157,14 +157,14 @@ async function launch(opts: DriverLaunchOptions): Promise<DriverLaunchResult> {
|
|
|
157
157
|
if (headless && desktopHostPlatform()) {
|
|
158
158
|
try {
|
|
159
159
|
hostCommand = headlessHostCommand()
|
|
160
|
-
if (!hostCommand) {
|
|
160
|
+
if (!hostCommand && desktopHostPlatform() === 'linux-x64') {
|
|
161
161
|
// a missing or older host upgrades to the channel's current release; one published
|
|
162
|
-
// before the headless host existed leaves this run on the browser engine alone
|
|
162
|
+
// before the compatible headless host existed leaves this run on the browser engine alone
|
|
163
163
|
await desktopHostDelivery().install()
|
|
164
164
|
hostCommand = headlessHostCommand()
|
|
165
165
|
if (!hostCommand)
|
|
166
166
|
console.error(
|
|
167
|
-
' native host release has no headless host yet; rendering in the browser',
|
|
167
|
+
' native host release has no compatible headless host yet; rendering in the browser',
|
|
168
168
|
)
|
|
169
169
|
}
|
|
170
170
|
} catch (error) {
|
package/cli/main.ts
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
// single lazy-imported command a run dispatches to. `./bin` imports this only
|
|
3
3
|
// when none of its hidden entry points claimed the process.
|
|
4
4
|
|
|
5
|
+
import { Console } from 'node:console'
|
|
5
6
|
import { automaticPeachUpdatesEnabled } from '../src/automatic-update-policy'
|
|
7
|
+
import { exitWithFlushedOutput } from '../src/process-output'
|
|
6
8
|
import { rnxPublicBrand } from '../src/public-brand'
|
|
7
9
|
import { levenshtein } from './levenshtein'
|
|
8
10
|
import { COMMANDS, parseArgs, TOP_LEVEL_RUNTIME_COMMANDS } from './parse-args'
|
|
@@ -10,6 +12,9 @@ import { PeachExit } from './run-rnx'
|
|
|
10
12
|
import { rnxSelfInvocation } from './self-invocation'
|
|
11
13
|
import { IS_STANDALONE } from './standalone'
|
|
12
14
|
|
|
15
|
+
// bun's console has its own sink; use the streams our exit boundary drains.
|
|
16
|
+
Object.assign(console, new Console(process.stdout, process.stderr))
|
|
17
|
+
|
|
13
18
|
// `./help` is loaded lazily (only on help paths) — it statically pulls the full
|
|
14
19
|
// CLI registry renderers and engine settings, which would otherwise add ~400ms
|
|
15
20
|
// of eager chunk load to every command, including hot-path reads like
|
|
@@ -54,7 +59,7 @@ async function handleTopLevelError(err: unknown): Promise<never> {
|
|
|
54
59
|
msg.startsWith('could not resolve a native bundle for ')
|
|
55
60
|
if (isKnownCliFailure && !process.env.SOOTSIM_VERBOSE) {
|
|
56
61
|
process.stderr.write(` ${msg}\n`)
|
|
57
|
-
|
|
62
|
+
await exitWithFlushedOutput(1)
|
|
58
63
|
}
|
|
59
64
|
// an unexpected crash is ours to fix: it goes to the issue queue on its own
|
|
60
65
|
if (!isKnownCliFailure) await reportCliCrash(err)
|
|
@@ -62,7 +67,7 @@ async function handleTopLevelError(err: unknown): Promise<never> {
|
|
|
62
67
|
// the message always goes first.
|
|
63
68
|
process.stderr.write(` ${msg}\n`)
|
|
64
69
|
if (err instanceof Error && err.stack) process.stderr.write(`${err.stack}\n`)
|
|
65
|
-
|
|
70
|
+
return exitWithFlushedOutput(1)
|
|
66
71
|
}
|
|
67
72
|
function printUnknownCommand(attempted: string) {
|
|
68
73
|
const closest = [...COMMANDS]
|
|
@@ -106,7 +111,7 @@ if (redact) {
|
|
|
106
111
|
process.stderr.write(
|
|
107
112
|
` --redact applies to ${[...REDACTABLE_COMMANDS].join(', ')}; this command can print output it cannot mask\n`,
|
|
108
113
|
)
|
|
109
|
-
|
|
114
|
+
await exitWithFlushedOutput(1)
|
|
110
115
|
}
|
|
111
116
|
}
|
|
112
117
|
|
|
@@ -133,7 +138,7 @@ if (isCliUpdateWorker) {
|
|
|
133
138
|
await refreshCliUpdateCache()
|
|
134
139
|
} catch {}
|
|
135
140
|
}
|
|
136
|
-
|
|
141
|
+
await exitWithFlushedOutput(0)
|
|
137
142
|
}
|
|
138
143
|
|
|
139
144
|
if (
|
|
@@ -263,7 +268,7 @@ async function exitWithFlush(code: number): Promise<never> {
|
|
|
263
268
|
await flushCliTelemetry(code)
|
|
264
269
|
await scheduleAutomaticCliUpdate(code)
|
|
265
270
|
await scheduleAutomaticCleanup()
|
|
266
|
-
|
|
271
|
+
return exitWithFlushedOutput(code)
|
|
267
272
|
}
|
|
268
273
|
|
|
269
274
|
// --version
|
|
@@ -371,6 +376,10 @@ if (
|
|
|
371
376
|
const { runReset } = await import('./commands/reset')
|
|
372
377
|
await exitWithFlush(await runReset(commandArgsWithSim, { port }))
|
|
373
378
|
}
|
|
379
|
+
if (command === 'maestro' && parsed.commandArgs[0] === 'compare') {
|
|
380
|
+
const { runMaestroCompare } = await import('./commands/maestro-compare')
|
|
381
|
+
await exitWithFlush(await runMaestroCompare(parsed.commandArgs.slice(1), { port }))
|
|
382
|
+
}
|
|
374
383
|
// for grouping verbs, try to resolve per-verb help from the first
|
|
375
384
|
// positional arg. e.g. `peach do tap --help` shows tap's help page,
|
|
376
385
|
// not the generic `do` grouping page. bare `peach do --help` falls
|
|
@@ -626,14 +626,6 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
626
626
|
category: 'local_development',
|
|
627
627
|
count: 1,
|
|
628
628
|
},
|
|
629
|
-
'packages/peachsim/cli/commands/control.ts :: fetch :: imageUrl': {
|
|
630
|
-
category: 'local_development',
|
|
631
|
-
count: 1,
|
|
632
|
-
},
|
|
633
|
-
'packages/peachsim/cli/commands/control.ts :: fetch :: spec.url': {
|
|
634
|
-
category: 'local_development',
|
|
635
|
-
count: 1,
|
|
636
|
-
},
|
|
637
629
|
'packages/peachsim/cli/commands/control.ts :: websocket :: `ws://127.0.0.1:${port}`': {
|
|
638
630
|
category: 'local_development',
|
|
639
631
|
count: 1,
|
|
@@ -750,7 +742,7 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
750
742
|
category: 'local_development',
|
|
751
743
|
count: 1,
|
|
752
744
|
},
|
|
753
|
-
'packages/peach-engine/src/expo-
|
|
745
|
+
'packages/peach-engine/src/expo-swift-compilation.ts :: fetch :: address': {
|
|
754
746
|
category: 'local_development',
|
|
755
747
|
count: 1,
|
|
756
748
|
},
|
package/detox/index.ts
CHANGED
|
@@ -1960,6 +1960,7 @@ export const device = {
|
|
|
1960
1960
|
WEBVIEW_HOST_BOOTSTRAP_SOURCE,
|
|
1961
1961
|
),
|
|
1962
1962
|
webViewAutomationHelpers,
|
|
1963
|
+
(page) => page.workers(),
|
|
1963
1964
|
)
|
|
1964
1965
|
await _context.exposeBinding('__sootsimHostCapture', async (source, value) => {
|
|
1965
1966
|
const request = readBrowserCompositeCaptureRequest(value)
|
|
@@ -2333,6 +2334,7 @@ export const device = {
|
|
|
2333
2334
|
lockstepCapture?: {
|
|
2334
2335
|
begin: (fps: number) => Promise<{
|
|
2335
2336
|
readonly initialFrame: FrameReceipt
|
|
2337
|
+
flushFrame: () => Promise<FrameReceipt>
|
|
2336
2338
|
stepFrame: () => Promise<FrameReceipt>
|
|
2337
2339
|
framesForOffset: (offsetMs: number) => number
|
|
2338
2340
|
stepToOffset: (
|
|
@@ -2540,6 +2542,9 @@ export const device = {
|
|
|
2540
2542
|
let previousBitmap: ImageBitmap | null = null
|
|
2541
2543
|
// android can publish mount layout at p=0 before a clock step.
|
|
2542
2544
|
if (input.platform === 'android') {
|
|
2545
|
+
// time zero needs the same producer publication fence as stepped
|
|
2546
|
+
// frames; intermediate tree paints are not a transition onset.
|
|
2547
|
+
const receipt = await controller.flushFrame()
|
|
2543
2548
|
const candidateBitmap = await captureBitmap()
|
|
2544
2549
|
const bounds = boundsFor(candidateBitmap)
|
|
2545
2550
|
const measurement = measureChange({
|
|
@@ -2551,7 +2556,7 @@ export const device = {
|
|
|
2551
2556
|
width: bounds.width,
|
|
2552
2557
|
})
|
|
2553
2558
|
if (measurement.passedMinimum) {
|
|
2554
|
-
visibleStart =
|
|
2559
|
+
visibleStart = receipt
|
|
2555
2560
|
detectedMeasurement = measurement
|
|
2556
2561
|
keptFrames.set(visibleStart.frameIndex, candidateBitmap)
|
|
2557
2562
|
} else {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/beta.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/beta.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -108,10 +108,10 @@ var SEMANTIC_READY_NODE_STABLE_MS = 750;
|
|
|
108
108
|
var SEMANTIC_READY_POLL_MS = 150;
|
|
109
109
|
var HEADLESS_TENANT_FETCH_HUNG_MARKER = "headless tenant fetch hung";
|
|
110
110
|
function readyProbeHasContent(probe) {
|
|
111
|
-
return (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0 || probe.nodes >= SEMANTIC_READY_CONTENT_NODE_FLOOR;
|
|
111
|
+
return probe.paintedAppContent === true || (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0 || probe.nodes >= SEMANTIC_READY_CONTENT_NODE_FLOOR;
|
|
112
112
|
}
|
|
113
113
|
function readyProbeHasTargetContent(probe) {
|
|
114
|
-
return (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0;
|
|
114
|
+
return probe.paintedAppContent === true || (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0;
|
|
115
115
|
}
|
|
116
116
|
function readyProbeIsReady(probe) {
|
|
117
117
|
return (probe.flag === true ? readyProbeHasContent(probe) : readyProbeHasTargetContent(probe)) && probe.externalReady !== false && !probe.externalError && !probe.loadingText;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
|
|
3
3
|
// src/bridge-contract.ts
|
|
4
4
|
var REFUSED_PERFORM_STEP_TYPES = [
|
|
@@ -73,10 +73,10 @@ var SEMANTIC_READY_NODE_STABLE_MS = 750;
|
|
|
73
73
|
var SEMANTIC_READY_POLL_MS = 150;
|
|
74
74
|
var HEADLESS_TENANT_FETCH_HUNG_MARKER = "headless tenant fetch hung";
|
|
75
75
|
function readyProbeHasContent(probe) {
|
|
76
|
-
return (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0 || probe.nodes >= SEMANTIC_READY_CONTENT_NODE_FLOOR;
|
|
76
|
+
return probe.paintedAppContent === true || (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0 || probe.nodes >= SEMANTIC_READY_CONTENT_NODE_FLOOR;
|
|
77
77
|
}
|
|
78
78
|
function readyProbeHasTargetContent(probe) {
|
|
79
|
-
return (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0;
|
|
79
|
+
return probe.paintedAppContent === true || (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0;
|
|
80
80
|
}
|
|
81
81
|
function readyProbeIsReady(probe) {
|
|
82
82
|
return (probe.flag === true ? readyProbeHasContent(probe) : readyProbeHasTargetContent(probe)) && probe.externalReady !== false && !probe.externalError && !probe.loadingText;
|