@react-native-harness/platform-android 1.4.1 → 1.6.0
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/dist/adb.d.ts +2 -4
- package/dist/adb.d.ts.map +1 -1
- package/dist/adb.js +2 -3
- package/dist/app-session.d.ts +3 -12
- package/dist/app-session.d.ts.map +1 -1
- package/dist/app-session.js +23 -33
- package/dist/config.d.ts +10 -10
- package/dist/instance.d.ts.map +1 -1
- package/dist/instance.js +2 -4
- package/package.json +4 -4
- package/src/adb.ts +5 -6
- package/src/app-session.ts +14 -31
- package/src/instance.ts +2 -4
package/dist/adb.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AndroidAppLaunchOptions } from '@react-native-harness/platforms';
|
|
2
|
-
import { type
|
|
2
|
+
import { type OwnedProcess } from '@react-native-harness/tools';
|
|
3
3
|
import type { ChildProcessByStdio } from 'node:child_process';
|
|
4
4
|
import type { Readable } from 'node:stream';
|
|
5
5
|
import { type EmulatorBootMode } from './emulator-startup.js';
|
|
@@ -44,9 +44,7 @@ export declare const getAppPid: (adbId: string, bundleId: string) => Promise<num
|
|
|
44
44
|
export declare const getAppUid: (adbId: string, bundleId: string) => Promise<number>;
|
|
45
45
|
export declare const setHideErrorDialogs: (adbId: string, hide: boolean) => Promise<void>;
|
|
46
46
|
export declare const getLogcatTimestamp: (adbId: string) => Promise<string>;
|
|
47
|
-
export declare const startLogcat: (adbId: string, args: readonly string[]
|
|
48
|
-
signal?: AbortSignal;
|
|
49
|
-
}) => Subprocess;
|
|
47
|
+
export declare const startLogcat: (adbId: string, args: readonly string[]) => OwnedProcess;
|
|
50
48
|
export declare const DROPBOX_CRASH_TAGS: readonly ["data_app_crash", "data_app_native_crash"];
|
|
51
49
|
export declare const getDropboxPrint: (adbId: string, tags?: readonly string[]) => Promise<string>;
|
|
52
50
|
export declare const getActivityExitInfo: (adbId: string, bundleId: string) => Promise<string>;
|
package/dist/adb.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adb.d.ts","sourceRoot":"","sources":["../src/adb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,
|
|
1
|
+
{"version":3,"file":"adb.d.ts","sourceRoot":"","sources":["../src/adb.ts"],"names":[],"mappings":"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"}
|
package/dist/adb.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { delay, logger, spawn, SubprocessError, waitForAbort, } from '@react-native-harness/tools';
|
|
1
|
+
import { delay, logger, spawn, spawnOwnedProcess, SubprocessError, waitForAbort, } from '@react-native-harness/tools';
|
|
2
2
|
import { spawn as nodeSpawn } from 'node:child_process';
|
|
3
3
|
import { access, rm } from 'node:fs/promises';
|
|
4
4
|
import { getAvdConfigPath, getAvdDirectory, readAvdConfig, } from './avd-config.js';
|
|
@@ -505,10 +505,9 @@ export const getLogcatTimestamp = async (adbId) => {
|
|
|
505
505
|
]);
|
|
506
506
|
return stdout.trim().replace(/^'+|'+$/g, '');
|
|
507
507
|
};
|
|
508
|
-
export const startLogcat = (adbId, args
|
|
508
|
+
export const startLogcat = (adbId, args) => spawnOwnedProcess(getAdbBinaryPath(), ['-s', adbId, ...args], {
|
|
509
509
|
stdout: 'pipe',
|
|
510
510
|
stderr: 'pipe',
|
|
511
|
-
signal: options?.signal,
|
|
512
511
|
});
|
|
513
512
|
export const DROPBOX_CRASH_TAGS = [
|
|
514
513
|
'data_app_crash',
|
package/dist/app-session.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AppSession, type CrashArtifactWriter } from '@react-native-harness/platforms';
|
|
2
|
-
import { type
|
|
2
|
+
import { type OwnedProcess } from '@react-native-harness/tools';
|
|
3
3
|
type CreateAndroidAppSessionOptions = {
|
|
4
4
|
appUid: number;
|
|
5
5
|
bundleId: string;
|
|
@@ -7,20 +7,11 @@ type CreateAndroidAppSessionOptions = {
|
|
|
7
7
|
stopApp: () => Promise<void>;
|
|
8
8
|
getAppPid: () => Promise<number | null>;
|
|
9
9
|
getLogcatTimestamp: () => Promise<string>;
|
|
10
|
-
startLogcat: (args: readonly string[]
|
|
11
|
-
signal: AbortSignal;
|
|
12
|
-
}) => Subprocess;
|
|
10
|
+
startLogcat: (args: readonly string[]) => OwnedProcess;
|
|
13
11
|
getDropboxOutput?: () => Promise<string>;
|
|
14
12
|
getExitInfo?: () => Promise<string>;
|
|
15
13
|
crashArtifactWriter?: CrashArtifactWriter;
|
|
16
|
-
/**
|
|
17
|
-
* Session-lifetime abort signal (see HarnessPlatformInitOptions.signal).
|
|
18
|
-
* Combined with the app session's own logcatAbortController so that
|
|
19
|
-
* aborting the session stops the logcat stream even if dispose() hasn't
|
|
20
|
-
* been called yet (e.g. SIGTERM during teardown of other resources).
|
|
21
|
-
*/
|
|
22
|
-
signal?: AbortSignal;
|
|
23
14
|
};
|
|
24
|
-
export declare const createAndroidAppSession: ({ appUid, bundleId, startApp, stopApp, getAppPid, getLogcatTimestamp, startLogcat, getDropboxOutput, getExitInfo, crashArtifactWriter,
|
|
15
|
+
export declare const createAndroidAppSession: ({ appUid, bundleId, startApp, stopApp, getAppPid, getLogcatTimestamp, startLogcat, getDropboxOutput, getExitInfo, crashArtifactWriter, }: CreateAndroidAppSessionOptions) => Promise<AppSession>;
|
|
25
16
|
export {};
|
|
26
17
|
//# sourceMappingURL=app-session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-session.d.ts","sourceRoot":"","sources":["../src/app-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,UAAU,EAEf,KAAK,mBAAmB,EACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAGL,KAAK,
|
|
1
|
+
{"version":3,"file":"app-session.d.ts","sourceRoot":"","sources":["../src/app-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,UAAU,EAEf,KAAK,mBAAmB,EACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,6BAA6B,CAAC;AA0DrC,KAAK,8BAA8B,GAAG;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxC,kBAAkB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,WAAW,EAAE,CACX,IAAI,EAAE,SAAS,MAAM,EAAE,KACpB,YAAY,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC3C,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAU,0IAW3C,8BAA8B,KAAG,OAAO,CAAC,UAAU,CA2MrD,CAAC"}
|
package/dist/app-session.js
CHANGED
|
@@ -31,7 +31,7 @@ const isCrashSignal = (line, bundleId) => {
|
|
|
31
31
|
/fatal|crash|signal 11|signal 6|backtrace/i.test(line)));
|
|
32
32
|
};
|
|
33
33
|
const isExitedState = (state) => state.status === 'exited';
|
|
34
|
-
export const createAndroidAppSession = async ({ appUid, bundleId, startApp, stopApp, getAppPid, getLogcatTimestamp, startLogcat, getDropboxOutput, getExitInfo, crashArtifactWriter,
|
|
34
|
+
export const createAndroidAppSession = async ({ appUid, bundleId, startApp, stopApp, getAppPid, getLogcatTimestamp, startLogcat, getDropboxOutput, getExitInfo, crashArtifactWriter, }) => {
|
|
35
35
|
const emitter = createAppSessionEmitter();
|
|
36
36
|
const logBuffer = createBoundedLogBuffer();
|
|
37
37
|
let state = { status: 'running' };
|
|
@@ -105,20 +105,8 @@ export const createAndroidAppSession = async ({ appUid, bundleId, startApp, stop
|
|
|
105
105
|
};
|
|
106
106
|
const logcatTimestamp = await getLogcatTimestamp();
|
|
107
107
|
const sessionStartedAt = Date.now();
|
|
108
|
-
const
|
|
109
|
-
const
|
|
110
|
-
? AbortSignal.any([signal, logcatAbortController.signal])
|
|
111
|
-
: logcatAbortController.signal;
|
|
112
|
-
const logcatProcess = startLogcat(getLogcatArgs(appUid, logcatTimestamp), {
|
|
113
|
-
signal: logcatSignal,
|
|
114
|
-
});
|
|
115
|
-
// Aborting is nano-spawn's own cancellation path, so the resulting
|
|
116
|
-
// SubprocessError is settled the same way regardless of which of the
|
|
117
|
-
// merged stdout/stderr iterators observes it first. Without this, killing
|
|
118
|
-
// the underlying process directly can make both iterators reject at once,
|
|
119
|
-
// and nano-spawn's internal `Promise.race` only reports one of them,
|
|
120
|
-
// leaving the other an unhandled rejection.
|
|
121
|
-
logcatProcess.catch(() => undefined);
|
|
108
|
+
const ownedLogcatProcess = startLogcat(getLogcatArgs(appUid, logcatTimestamp));
|
|
109
|
+
const logcatProcess = ownedLogcatProcess.subprocess;
|
|
122
110
|
const crashReporter = createAndroidCrashReporter({
|
|
123
111
|
bundleId,
|
|
124
112
|
crashArtifactWriter,
|
|
@@ -161,7 +149,7 @@ export const createAndroidAppSession = async ({ appUid, bundleId, startApp, stop
|
|
|
161
149
|
disposed = true;
|
|
162
150
|
stopPolling = true;
|
|
163
151
|
emitter.clear();
|
|
164
|
-
|
|
152
|
+
await ownedLogcatProcess.dispose();
|
|
165
153
|
await Promise.allSettled([logTask]);
|
|
166
154
|
throw error;
|
|
167
155
|
}
|
|
@@ -187,24 +175,26 @@ export const createAndroidAppSession = async ({ appUid, bundleId, startApp, stop
|
|
|
187
175
|
await waitForNextPoll();
|
|
188
176
|
}
|
|
189
177
|
})();
|
|
178
|
+
let disposePromise;
|
|
179
|
+
const dispose = () => (disposePromise ??= (async () => {
|
|
180
|
+
if (disposed) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
disposed = true;
|
|
184
|
+
stopPolling = true;
|
|
185
|
+
state = { status: 'disposed', occurredAt: Date.now() };
|
|
186
|
+
if (exitNotification) {
|
|
187
|
+
clearTimeout(exitNotification);
|
|
188
|
+
exitNotification = null;
|
|
189
|
+
}
|
|
190
|
+
cancelPendingPollDelay();
|
|
191
|
+
emitter.clear();
|
|
192
|
+
await ownedLogcatProcess.dispose();
|
|
193
|
+
await stopApp();
|
|
194
|
+
await Promise.allSettled([logTask, pollTask]);
|
|
195
|
+
})());
|
|
190
196
|
return {
|
|
191
|
-
dispose
|
|
192
|
-
if (disposed) {
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
disposed = true;
|
|
196
|
-
stopPolling = true;
|
|
197
|
-
state = { status: 'disposed', occurredAt: Date.now() };
|
|
198
|
-
if (exitNotification) {
|
|
199
|
-
clearTimeout(exitNotification);
|
|
200
|
-
exitNotification = null;
|
|
201
|
-
}
|
|
202
|
-
cancelPendingPollDelay();
|
|
203
|
-
emitter.clear();
|
|
204
|
-
logcatAbortController.abort();
|
|
205
|
-
await stopApp();
|
|
206
|
-
await Promise.allSettled([logTask, pollTask]);
|
|
207
|
-
},
|
|
197
|
+
dispose,
|
|
208
198
|
getState: async () => state,
|
|
209
199
|
getLogs: () => logBuffer.getLogs(),
|
|
210
200
|
getCrashDetails: crashReporter.getCrashDetails,
|
package/dist/config.d.ts
CHANGED
|
@@ -68,8 +68,8 @@ export declare const AndroidEmulatorSchema: z.ZodObject<{
|
|
|
68
68
|
} | undefined;
|
|
69
69
|
}>>;
|
|
70
70
|
}, "strip", z.ZodTypeAny, {
|
|
71
|
-
type: "emulator";
|
|
72
71
|
name: string;
|
|
72
|
+
type: "emulator";
|
|
73
73
|
avd?: {
|
|
74
74
|
apiLevel: number;
|
|
75
75
|
profile: string;
|
|
@@ -80,8 +80,8 @@ export declare const AndroidEmulatorSchema: z.ZodObject<{
|
|
|
80
80
|
} | undefined;
|
|
81
81
|
} | undefined;
|
|
82
82
|
}, {
|
|
83
|
-
type: "emulator";
|
|
84
83
|
name: string;
|
|
84
|
+
type: "emulator";
|
|
85
85
|
avd?: {
|
|
86
86
|
apiLevel: number;
|
|
87
87
|
profile: string;
|
|
@@ -138,8 +138,8 @@ export declare const AndroidDeviceSchema: z.ZodDiscriminatedUnion<"type", [z.Zod
|
|
|
138
138
|
} | undefined;
|
|
139
139
|
}>>;
|
|
140
140
|
}, "strip", z.ZodTypeAny, {
|
|
141
|
-
type: "emulator";
|
|
142
141
|
name: string;
|
|
142
|
+
type: "emulator";
|
|
143
143
|
avd?: {
|
|
144
144
|
apiLevel: number;
|
|
145
145
|
profile: string;
|
|
@@ -150,8 +150,8 @@ export declare const AndroidDeviceSchema: z.ZodDiscriminatedUnion<"type", [z.Zod
|
|
|
150
150
|
} | undefined;
|
|
151
151
|
} | undefined;
|
|
152
152
|
}, {
|
|
153
|
-
type: "emulator";
|
|
154
153
|
name: string;
|
|
154
|
+
type: "emulator";
|
|
155
155
|
avd?: {
|
|
156
156
|
apiLevel: number;
|
|
157
157
|
profile: string;
|
|
@@ -209,8 +209,8 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
209
209
|
} | undefined;
|
|
210
210
|
}>>;
|
|
211
211
|
}, "strip", z.ZodTypeAny, {
|
|
212
|
-
type: "emulator";
|
|
213
212
|
name: string;
|
|
213
|
+
type: "emulator";
|
|
214
214
|
avd?: {
|
|
215
215
|
apiLevel: number;
|
|
216
216
|
profile: string;
|
|
@@ -221,8 +221,8 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
221
221
|
} | undefined;
|
|
222
222
|
} | undefined;
|
|
223
223
|
}, {
|
|
224
|
-
type: "emulator";
|
|
225
224
|
name: string;
|
|
225
|
+
type: "emulator";
|
|
226
226
|
avd?: {
|
|
227
227
|
apiLevel: number;
|
|
228
228
|
profile: string;
|
|
@@ -255,10 +255,11 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
255
255
|
extras?: Record<string, string | number | boolean> | undefined;
|
|
256
256
|
}>>;
|
|
257
257
|
}, "strip", z.ZodTypeAny, {
|
|
258
|
+
bundleId: string;
|
|
258
259
|
name: string;
|
|
259
260
|
device: {
|
|
260
|
-
type: "emulator";
|
|
261
261
|
name: string;
|
|
262
|
+
type: "emulator";
|
|
262
263
|
avd?: {
|
|
263
264
|
apiLevel: number;
|
|
264
265
|
profile: string;
|
|
@@ -273,16 +274,16 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
273
274
|
manufacturer: string;
|
|
274
275
|
model: string;
|
|
275
276
|
};
|
|
276
|
-
bundleId: string;
|
|
277
277
|
activityName: string;
|
|
278
278
|
appLaunchOptions?: {
|
|
279
279
|
extras?: Record<string, string | number | boolean> | undefined;
|
|
280
280
|
} | undefined;
|
|
281
281
|
}, {
|
|
282
|
+
bundleId: string;
|
|
282
283
|
name: string;
|
|
283
284
|
device: {
|
|
284
|
-
type: "emulator";
|
|
285
285
|
name: string;
|
|
286
|
+
type: "emulator";
|
|
286
287
|
avd?: {
|
|
287
288
|
apiLevel: number;
|
|
288
289
|
profile: string;
|
|
@@ -297,7 +298,6 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
297
298
|
manufacturer: string;
|
|
298
299
|
model: string;
|
|
299
300
|
};
|
|
300
|
-
bundleId: string;
|
|
301
301
|
activityName?: string | undefined;
|
|
302
302
|
appLaunchOptions?: {
|
|
303
303
|
extras?: Record<string, string | number | boolean> | undefined;
|
package/dist/instance.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../src/instance.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,0BAA0B,EAC/B,qBAAqB,EACtB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE5E,OAAO,EACL,qBAAqB,EAGtB,MAAM,aAAa,CAAC;AAyKrB,eAAO,MAAM,kCAAkC,GAC7C,QAAQ,qBAAqB,EAC7B,eAAe,aAAa,EAC5B,MAAM,0BAA0B,KAC/B,OAAO,CAAC,qBAAqB,
|
|
1
|
+
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../src/instance.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,0BAA0B,EAC/B,qBAAqB,EACtB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE5E,OAAO,EACL,qBAAqB,EAGtB,MAAM,aAAa,CAAC;AAyKrB,eAAO,MAAM,kCAAkC,GAC7C,QAAQ,qBAAqB,EAC7B,eAAe,aAAa,EAC5B,MAAM,0BAA0B,KAC/B,OAAO,CAAC,qBAAqB,CAmI/B,CAAC;AAEF,eAAO,MAAM,wCAAwC,GACnD,QAAQ,qBAAqB,EAC7B,eAAe,aAAa,EAC5B,OAAO,0BAA0B,KAChC,OAAO,CAAC,qBAAqB,CA8D/B,CAAC"}
|
package/dist/instance.js
CHANGED
|
@@ -172,11 +172,10 @@ export const getAndroidEmulatorPlatformInstance = async (config, harnessConfig,
|
|
|
172
172
|
stopApp: () => adb.stopApp(adbId, config.bundleId),
|
|
173
173
|
getAppPid: () => adb.getAppPid(adbId, config.bundleId),
|
|
174
174
|
getLogcatTimestamp: () => adb.getLogcatTimestamp(adbId),
|
|
175
|
-
startLogcat: (args
|
|
175
|
+
startLogcat: (args) => adb.startLogcat(adbId, args),
|
|
176
176
|
getDropboxOutput: () => adb.getDropboxPrint(adbId),
|
|
177
177
|
getExitInfo: () => adb.getActivityExitInfo(adbId, config.bundleId),
|
|
178
178
|
crashArtifactWriter: init.crashArtifactWriter,
|
|
179
|
-
signal: init.signal,
|
|
180
179
|
});
|
|
181
180
|
},
|
|
182
181
|
dispose: async () => {
|
|
@@ -218,11 +217,10 @@ export const getAndroidPhysicalDevicePlatformInstance = async (config, harnessCo
|
|
|
218
217
|
stopApp: () => adb.stopApp(adbId, config.bundleId),
|
|
219
218
|
getAppPid: () => adb.getAppPid(adbId, config.bundleId),
|
|
220
219
|
getLogcatTimestamp: () => adb.getLogcatTimestamp(adbId),
|
|
221
|
-
startLogcat: (args
|
|
220
|
+
startLogcat: (args) => adb.startLogcat(adbId, args),
|
|
222
221
|
getDropboxOutput: () => adb.getDropboxPrint(adbId),
|
|
223
222
|
getExitInfo: () => adb.getActivityExitInfo(adbId, config.bundleId),
|
|
224
223
|
crashArtifactWriter: init?.crashArtifactWriter,
|
|
225
|
-
signal: init?.signal,
|
|
226
224
|
});
|
|
227
225
|
},
|
|
228
226
|
dispose: async () => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-native-harness/platform-android",
|
|
3
3
|
"description": "Android platform for React Native Harness",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.6.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"vite": "^7.2.2",
|
|
20
20
|
"zod": "^3.25.67",
|
|
21
21
|
"tslib": "^2.3.0",
|
|
22
|
-
"@react-native-harness/
|
|
23
|
-
"@react-native-harness/platforms": "1.
|
|
24
|
-
"@react-native-harness/
|
|
22
|
+
"@react-native-harness/tools": "1.6.0",
|
|
23
|
+
"@react-native-harness/platforms": "1.6.0",
|
|
24
|
+
"@react-native-harness/config": "1.6.0"
|
|
25
25
|
},
|
|
26
26
|
"license": "MIT"
|
|
27
27
|
}
|
package/src/adb.ts
CHANGED
|
@@ -3,9 +3,10 @@ import {
|
|
|
3
3
|
delay,
|
|
4
4
|
logger,
|
|
5
5
|
spawn,
|
|
6
|
+
spawnOwnedProcess,
|
|
6
7
|
SubprocessError,
|
|
7
8
|
waitForAbort,
|
|
8
|
-
type
|
|
9
|
+
type OwnedProcess,
|
|
9
10
|
} from '@react-native-harness/tools';
|
|
10
11
|
import { spawn as nodeSpawn } from 'node:child_process';
|
|
11
12
|
import type { ChildProcessByStdio } from 'node:child_process';
|
|
@@ -789,13 +790,11 @@ export const getLogcatTimestamp = async (adbId: string): Promise<string> => {
|
|
|
789
790
|
|
|
790
791
|
export const startLogcat = (
|
|
791
792
|
adbId: string,
|
|
792
|
-
args: readonly string[]
|
|
793
|
-
|
|
794
|
-
)
|
|
795
|
-
spawn(getAdbBinaryPath(), ['-s', adbId, ...args], {
|
|
793
|
+
args: readonly string[]
|
|
794
|
+
): OwnedProcess =>
|
|
795
|
+
spawnOwnedProcess(getAdbBinaryPath(), ['-s', adbId, ...args], {
|
|
796
796
|
stdout: 'pipe',
|
|
797
797
|
stderr: 'pipe',
|
|
798
|
-
signal: options?.signal,
|
|
799
798
|
});
|
|
800
799
|
|
|
801
800
|
export const DROPBOX_CRASH_TAGS = [
|
package/src/app-session.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
escapeRegExp,
|
|
10
10
|
logger,
|
|
11
|
-
type
|
|
11
|
+
type OwnedProcess,
|
|
12
12
|
} from '@react-native-harness/tools';
|
|
13
13
|
import { createAndroidCrashReporter } from './crash-reporter.js';
|
|
14
14
|
|
|
@@ -75,19 +75,11 @@ type CreateAndroidAppSessionOptions = {
|
|
|
75
75
|
getAppPid: () => Promise<number | null>;
|
|
76
76
|
getLogcatTimestamp: () => Promise<string>;
|
|
77
77
|
startLogcat: (
|
|
78
|
-
args: readonly string[]
|
|
79
|
-
|
|
80
|
-
) => Subprocess;
|
|
78
|
+
args: readonly string[]
|
|
79
|
+
) => OwnedProcess;
|
|
81
80
|
getDropboxOutput?: () => Promise<string>;
|
|
82
81
|
getExitInfo?: () => Promise<string>;
|
|
83
82
|
crashArtifactWriter?: CrashArtifactWriter;
|
|
84
|
-
/**
|
|
85
|
-
* Session-lifetime abort signal (see HarnessPlatformInitOptions.signal).
|
|
86
|
-
* Combined with the app session's own logcatAbortController so that
|
|
87
|
-
* aborting the session stops the logcat stream even if dispose() hasn't
|
|
88
|
-
* been called yet (e.g. SIGTERM during teardown of other resources).
|
|
89
|
-
*/
|
|
90
|
-
signal?: AbortSignal;
|
|
91
83
|
};
|
|
92
84
|
|
|
93
85
|
export const createAndroidAppSession = async ({
|
|
@@ -101,7 +93,6 @@ export const createAndroidAppSession = async ({
|
|
|
101
93
|
getDropboxOutput,
|
|
102
94
|
getExitInfo,
|
|
103
95
|
crashArtifactWriter,
|
|
104
|
-
signal,
|
|
105
96
|
}: CreateAndroidAppSessionOptions): Promise<AppSession> => {
|
|
106
97
|
const emitter = createAppSessionEmitter();
|
|
107
98
|
const logBuffer = createBoundedLogBuffer();
|
|
@@ -196,20 +187,8 @@ export const createAndroidAppSession = async ({
|
|
|
196
187
|
|
|
197
188
|
const logcatTimestamp = await getLogcatTimestamp();
|
|
198
189
|
const sessionStartedAt = Date.now();
|
|
199
|
-
const
|
|
200
|
-
const
|
|
201
|
-
? AbortSignal.any([signal, logcatAbortController.signal])
|
|
202
|
-
: logcatAbortController.signal;
|
|
203
|
-
const logcatProcess = startLogcat(getLogcatArgs(appUid, logcatTimestamp), {
|
|
204
|
-
signal: logcatSignal,
|
|
205
|
-
});
|
|
206
|
-
// Aborting is nano-spawn's own cancellation path, so the resulting
|
|
207
|
-
// SubprocessError is settled the same way regardless of which of the
|
|
208
|
-
// merged stdout/stderr iterators observes it first. Without this, killing
|
|
209
|
-
// the underlying process directly can make both iterators reject at once,
|
|
210
|
-
// and nano-spawn's internal `Promise.race` only reports one of them,
|
|
211
|
-
// leaving the other an unhandled rejection.
|
|
212
|
-
logcatProcess.catch(() => undefined);
|
|
190
|
+
const ownedLogcatProcess = startLogcat(getLogcatArgs(appUid, logcatTimestamp));
|
|
191
|
+
const logcatProcess = ownedLogcatProcess.subprocess;
|
|
213
192
|
const crashReporter = createAndroidCrashReporter({
|
|
214
193
|
bundleId,
|
|
215
194
|
crashArtifactWriter,
|
|
@@ -255,7 +234,7 @@ export const createAndroidAppSession = async ({
|
|
|
255
234
|
disposed = true;
|
|
256
235
|
stopPolling = true;
|
|
257
236
|
emitter.clear();
|
|
258
|
-
|
|
237
|
+
await ownedLogcatProcess.dispose();
|
|
259
238
|
await Promise.allSettled([logTask]);
|
|
260
239
|
throw error;
|
|
261
240
|
}
|
|
@@ -285,8 +264,9 @@ export const createAndroidAppSession = async ({
|
|
|
285
264
|
}
|
|
286
265
|
})();
|
|
287
266
|
|
|
288
|
-
|
|
289
|
-
|
|
267
|
+
let disposePromise: Promise<void> | undefined;
|
|
268
|
+
const dispose = () =>
|
|
269
|
+
(disposePromise ??= (async () => {
|
|
290
270
|
if (disposed) {
|
|
291
271
|
return;
|
|
292
272
|
}
|
|
@@ -303,10 +283,13 @@ export const createAndroidAppSession = async ({
|
|
|
303
283
|
cancelPendingPollDelay();
|
|
304
284
|
|
|
305
285
|
emitter.clear();
|
|
306
|
-
|
|
286
|
+
await ownedLogcatProcess.dispose();
|
|
307
287
|
await stopApp();
|
|
308
288
|
await Promise.allSettled([logTask, pollTask]);
|
|
309
|
-
}
|
|
289
|
+
})());
|
|
290
|
+
|
|
291
|
+
return {
|
|
292
|
+
dispose,
|
|
310
293
|
getState: async () => state,
|
|
311
294
|
getLogs: () => logBuffer.getLogs(),
|
|
312
295
|
getCrashDetails: crashReporter.getCrashDetails,
|
package/src/instance.ts
CHANGED
|
@@ -297,11 +297,10 @@ export const getAndroidEmulatorPlatformInstance = async (
|
|
|
297
297
|
stopApp: () => adb.stopApp(adbId, config.bundleId),
|
|
298
298
|
getAppPid: () => adb.getAppPid(adbId, config.bundleId),
|
|
299
299
|
getLogcatTimestamp: () => adb.getLogcatTimestamp(adbId),
|
|
300
|
-
startLogcat: (args
|
|
300
|
+
startLogcat: (args) => adb.startLogcat(adbId, args),
|
|
301
301
|
getDropboxOutput: () => adb.getDropboxPrint(adbId),
|
|
302
302
|
getExitInfo: () => adb.getActivityExitInfo(adbId, config.bundleId),
|
|
303
303
|
crashArtifactWriter: init.crashArtifactWriter,
|
|
304
|
-
signal: init.signal,
|
|
305
304
|
});
|
|
306
305
|
},
|
|
307
306
|
dispose: async () => {
|
|
@@ -371,11 +370,10 @@ export const getAndroidPhysicalDevicePlatformInstance = async (
|
|
|
371
370
|
stopApp: () => adb.stopApp(adbId, config.bundleId),
|
|
372
371
|
getAppPid: () => adb.getAppPid(adbId, config.bundleId),
|
|
373
372
|
getLogcatTimestamp: () => adb.getLogcatTimestamp(adbId),
|
|
374
|
-
startLogcat: (args
|
|
373
|
+
startLogcat: (args) => adb.startLogcat(adbId, args),
|
|
375
374
|
getDropboxOutput: () => adb.getDropboxPrint(adbId),
|
|
376
375
|
getExitInfo: () => adb.getActivityExitInfo(adbId, config.bundleId),
|
|
377
376
|
crashArtifactWriter: init?.crashArtifactWriter,
|
|
378
|
-
signal: init?.signal,
|
|
379
377
|
});
|
|
380
378
|
},
|
|
381
379
|
dispose: async () => {
|