frida 16.7.13 → 16.7.15

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.
Files changed (172) hide show
  1. package/README.md +1 -10
  2. package/build/BSDmakefile +6 -0
  3. package/build/Makefile +10 -0
  4. package/build/src/frida.d.ts +364 -0
  5. package/build/src/frida.js +962 -0
  6. package/build/src/frida_binding.d.ts +938 -0
  7. package/meson.build +34 -67
  8. package/package.json +30 -20
  9. package/scripts/fetch-abi-bits.py +15 -65
  10. package/scripts/install.js +5 -4
  11. package/src/addon.def +3 -0
  12. package/src/addon.symbols +2 -1
  13. package/src/addon.version +4 -0
  14. package/src/frida_bindgen/__init__.py +0 -0
  15. package/src/frida_bindgen/__main__.py +4 -0
  16. package/src/frida_bindgen/__pycache__/__init__.cpython-312.pyc +0 -0
  17. package/src/frida_bindgen/__pycache__/__main__.cpython-312.pyc +0 -0
  18. package/src/frida_bindgen/__pycache__/cli.cpython-312.pyc +0 -0
  19. package/src/frida_bindgen/__pycache__/codegen.cpython-312.pyc +0 -0
  20. package/src/frida_bindgen/__pycache__/customization.cpython-312.pyc +0 -0
  21. package/src/frida_bindgen/__pycache__/loader.cpython-312.pyc +0 -0
  22. package/src/frida_bindgen/__pycache__/model.cpython-312.pyc +0 -0
  23. package/src/frida_bindgen/assets/codegen_helpers.c +1970 -0
  24. package/src/frida_bindgen/assets/codegen_helpers.ts +100 -0
  25. package/src/frida_bindgen/assets/codegen_prototypes.h +78 -0
  26. package/src/frida_bindgen/assets/codegen_types.h +57 -0
  27. package/src/frida_bindgen/assets/customization_facade.exports +13 -0
  28. package/src/frida_bindgen/assets/customization_facade.ts +157 -0
  29. package/src/frida_bindgen/assets/customization_helpers.imports +2 -0
  30. package/src/frida_bindgen/assets/customization_helpers.ts +396 -0
  31. package/src/frida_bindgen/cli.py +96 -0
  32. package/src/frida_bindgen/codegen.py +2233 -0
  33. package/src/frida_bindgen/customization.py +924 -0
  34. package/src/frida_bindgen/loader.py +60 -0
  35. package/src/frida_bindgen/model.py +1357 -0
  36. package/src/meson.build +92 -27
  37. package/{lib/build.py → src/tsc.py} +12 -12
  38. package/src/win_delay_load_hook.c +56 -0
  39. package/subprojects/frida-core.wrap +1 -1
  40. package/test/data/index.ts +2 -2
  41. package/test/device.ts +1 -2
  42. package/test/device_manager.ts +1 -2
  43. package/test/labrat.ts +2 -2
  44. package/test/script.ts +12 -12
  45. package/test/session.ts +3 -3
  46. package/tsconfig.json +6 -11
  47. package/dist/application.d.ts +0 -81
  48. package/dist/application.js +0 -2
  49. package/dist/authentication.d.ts +0 -3
  50. package/dist/authentication.js +0 -2
  51. package/dist/bus.d.ts +0 -16
  52. package/dist/bus.js +0 -23
  53. package/dist/cancellable.d.ts +0 -15
  54. package/dist/cancellable.js +0 -41
  55. package/dist/child.d.ts +0 -16
  56. package/dist/child.js +0 -9
  57. package/dist/crash.d.ts +0 -10
  58. package/dist/crash.js +0 -2
  59. package/dist/device.d.ts +0 -156
  60. package/dist/device.js +0 -188
  61. package/dist/device_manager.d.ts +0 -25
  62. package/dist/device_manager.js +0 -42
  63. package/dist/endpoint_parameters.d.ts +0 -26
  64. package/dist/endpoint_parameters.js +0 -24
  65. package/dist/icon.d.ts +0 -14
  66. package/dist/icon.js +0 -2
  67. package/dist/index.d.ts +0 -161
  68. package/dist/index.js +0 -170
  69. package/dist/iostream.d.ts +0 -13
  70. package/dist/iostream.js +0 -73
  71. package/dist/native.d.ts +0 -1
  72. package/dist/native.js +0 -11
  73. package/dist/portal_membership.d.ts +0 -6
  74. package/dist/portal_membership.js +0 -12
  75. package/dist/portal_service.d.ts +0 -48
  76. package/dist/portal_service.js +0 -52
  77. package/dist/process.d.ts +0 -47
  78. package/dist/process.js +0 -2
  79. package/dist/relay.d.ts +0 -22
  80. package/dist/relay.js +0 -32
  81. package/dist/script.d.ts +0 -70
  82. package/dist/script.js +0 -266
  83. package/dist/service.d.ts +0 -16
  84. package/dist/service.js +0 -26
  85. package/dist/session.d.ts +0 -45
  86. package/dist/session.js +0 -73
  87. package/dist/signals.d.ts +0 -20
  88. package/dist/signals.js +0 -40
  89. package/dist/socket_address.d.ts +0 -25
  90. package/dist/socket_address.js +0 -2
  91. package/dist/spawn.d.ts +0 -4
  92. package/dist/spawn.js +0 -2
  93. package/dist/system_parameters.d.ts +0 -84
  94. package/dist/system_parameters.js +0 -2
  95. package/lib/application.ts +0 -98
  96. package/lib/authentication.ts +0 -3
  97. package/lib/bus.ts +0 -30
  98. package/lib/cancellable.ts +0 -48
  99. package/lib/child.ts +0 -15
  100. package/lib/crash.ts +0 -11
  101. package/lib/device.ts +0 -331
  102. package/lib/device_manager.ts +0 -69
  103. package/lib/endpoint_parameters.ts +0 -56
  104. package/lib/icon.ts +0 -15
  105. package/lib/index.ts +0 -316
  106. package/lib/iostream.ts +0 -78
  107. package/lib/meson.build +0 -53
  108. package/lib/native.ts +0 -9
  109. package/lib/portal_membership.ts +0 -10
  110. package/lib/portal_service.ts +0 -105
  111. package/lib/process.ts +0 -57
  112. package/lib/relay.ts +0 -44
  113. package/lib/script.ts +0 -361
  114. package/lib/service.ts +0 -34
  115. package/lib/session.ts +0 -113
  116. package/lib/signals.ts +0 -45
  117. package/lib/socket_address.ts +0 -35
  118. package/lib/spawn.ts +0 -4
  119. package/lib/system_parameters.ts +0 -103
  120. package/meson.options +0 -11
  121. package/src/addon.cc +0 -78
  122. package/src/application.cc +0 -148
  123. package/src/application.h +0 -31
  124. package/src/authentication.cc +0 -174
  125. package/src/authentication.h +0 -24
  126. package/src/bus.cc +0 -167
  127. package/src/bus.h +0 -33
  128. package/src/cancellable.cc +0 -117
  129. package/src/cancellable.h +0 -31
  130. package/src/child.cc +0 -150
  131. package/src/child.h +0 -32
  132. package/src/crash.cc +0 -122
  133. package/src/crash.h +0 -30
  134. package/src/device.cc +0 -1350
  135. package/src/device.h +0 -56
  136. package/src/device_manager.cc +0 -362
  137. package/src/device_manager.h +0 -35
  138. package/src/endpoint_parameters.cc +0 -171
  139. package/src/endpoint_parameters.h +0 -28
  140. package/src/glib_context.cc +0 -62
  141. package/src/glib_context.h +0 -29
  142. package/src/glib_object.cc +0 -25
  143. package/src/glib_object.h +0 -37
  144. package/src/iostream.cc +0 -243
  145. package/src/iostream.h +0 -30
  146. package/src/operation.h +0 -94
  147. package/src/portal_membership.cc +0 -100
  148. package/src/portal_membership.h +0 -26
  149. package/src/portal_service.cc +0 -401
  150. package/src/portal_service.h +0 -40
  151. package/src/process.cc +0 -135
  152. package/src/process.h +0 -30
  153. package/src/relay.cc +0 -139
  154. package/src/relay.h +0 -31
  155. package/src/runtime.cc +0 -568
  156. package/src/runtime.h +0 -69
  157. package/src/script.cc +0 -301
  158. package/src/script.h +0 -36
  159. package/src/service.cc +0 -224
  160. package/src/service.h +0 -36
  161. package/src/session.cc +0 -860
  162. package/src/session.h +0 -42
  163. package/src/signals.cc +0 -334
  164. package/src/signals.h +0 -47
  165. package/src/spawn.cc +0 -95
  166. package/src/spawn.h +0 -27
  167. package/src/usage_monitor.h +0 -117
  168. package/src/uv_context.cc +0 -118
  169. package/src/uv_context.h +0 -40
  170. package/src/win_delay_load_hook.cc +0 -63
  171. package/subprojects/nan.wrap +0 -9
  172. package/subprojects/packagefiles/nan.patch +0 -13
@@ -0,0 +1,100 @@
1
+ type SignalTransformer<
2
+ Source extends SignalHandler,
3
+ Target extends SignalHandler
4
+ > = (...args: Parameters<Source>) => Parameters<Target>;
5
+
6
+ type SignalInterceptor<H extends SignalHandler> = (...args: Parameters<H>) => boolean;
7
+
8
+ interface SignalWrapperOptionsNoTransform<H extends SignalHandler> {
9
+ transform?: undefined;
10
+ intercept?: SignalInterceptor<H>;
11
+ }
12
+
13
+ interface SignalWrapperOptionsTransform<
14
+ Source extends SignalHandler,
15
+ Target extends SignalHandler
16
+ > {
17
+ transform: SignalTransformer<Source, Target>;
18
+ intercept?: SignalInterceptor<Target>;
19
+ }
20
+
21
+ type SignalWrapperOptions<
22
+ Source extends SignalHandler,
23
+ Target extends SignalHandler
24
+ > =
25
+ | SignalWrapperOptionsNoTransform<Source & Target>
26
+ | SignalWrapperOptionsTransform<Source, Target>;
27
+
28
+ class SignalWrapper<
29
+ SourceHandler extends SignalHandler,
30
+ TargetHandler extends SignalHandler
31
+ > {
32
+ #source: Signal<SourceHandler>;
33
+ #transform?: SignalTransformer<SourceHandler, TargetHandler>;
34
+ #intercept?: SignalInterceptor<any>;
35
+
36
+ #handlers = new Set<TargetHandler>();
37
+
38
+ constructor(
39
+ source: Signal<SourceHandler>,
40
+ options?: SignalWrapperOptions<SourceHandler, TargetHandler>
41
+ ) {
42
+ this.#source = source;
43
+
44
+ if (options === undefined || options.transform === undefined) {
45
+ this.#intercept = options?.intercept;
46
+ } else {
47
+ this.#transform = options.transform;
48
+ this.#intercept = options.intercept;
49
+ }
50
+ }
51
+
52
+ connect(handler: TargetHandler): void {
53
+ this.#handlers.add(handler);
54
+ if (this.#handlers.size === 1) {
55
+ this.#source.connect(this.#wrappedHandler);
56
+ }
57
+ }
58
+
59
+ disconnect(handler: TargetHandler): void {
60
+ this.#handlers.delete(handler);
61
+ if (this.#handlers.size === 0) {
62
+ this.#source.disconnect(this.#wrappedHandler);
63
+ }
64
+ }
65
+
66
+ #wrappedHandler = ((...sourceArgs: Parameters<SourceHandler>) => {
67
+ let targetArgs: Parameters<TargetHandler>;
68
+ const transform = this.#transform;
69
+ if (transform === undefined) {
70
+ targetArgs = sourceArgs as unknown as Parameters<TargetHandler>;
71
+ } else {
72
+ targetArgs = transform(...sourceArgs);
73
+ }
74
+
75
+ const intercept = this.#intercept;
76
+ if (intercept !== undefined) {
77
+ if (!intercept(...targetArgs)) {
78
+ return;
79
+ }
80
+ }
81
+
82
+ for (const handler of this.#handlers) {
83
+ handler(...targetArgs);
84
+ }
85
+ }) as SourceHandler;
86
+ }
87
+
88
+ function inspectWrapper(object: any, name: string, properties: string[], depth: number, options: util.InspectOptionsStylized): string {
89
+ if (depth < 0) {
90
+ return options.stylize(`[${name}]`, "special");
91
+ }
92
+
93
+ const summary = Object.fromEntries(properties.map(name => [name, object[name]]));
94
+
95
+ const nextOptions = Object.assign({}, options, {
96
+ depth: (options.depth === null) ? null : depth - 1
97
+ });
98
+
99
+ return name + " " + inspect(summary, nextOptions);
100
+ }
@@ -0,0 +1,78 @@
1
+ G_GNUC_UNUSED static gboolean fdn_is_null (napi_env env, napi_value value);
2
+ static gboolean fdn_is_undefined_or_null (napi_env env, napi_value value);
3
+ static gboolean fdn_is_function (napi_env env, napi_value value);
4
+
5
+ static gboolean fdn_boolean_from_value (napi_env env, napi_value value, gboolean * b);
6
+ static napi_value fdn_boolean_to_value (napi_env env, gboolean b);
7
+ static gboolean fdn_size_from_value (napi_env env, napi_value value, gsize * s);
8
+ static napi_value fdn_size_to_value (napi_env env, gsize s);
9
+ static napi_value fdn_ssize_to_value (napi_env env, gssize s);
10
+ static gboolean fdn_int_from_value (napi_env env, napi_value value, gint * i);
11
+ static napi_value fdn_int_to_value (napi_env env, gint i);
12
+ static gboolean fdn_uint_from_value (napi_env env, napi_value value, guint * u);
13
+ static napi_value fdn_uint_to_value (napi_env env, guint u);
14
+ static gboolean fdn_uint16_from_value (napi_env env, napi_value value, guint16 * u);
15
+ static napi_value fdn_uint16_to_value (napi_env env, guint16 u);
16
+ static napi_value fdn_uint32_to_value (napi_env env, guint32 u);
17
+ static gboolean fdn_int64_from_value (napi_env env, napi_value value, gint64 * i);
18
+ static napi_value fdn_int64_to_value (napi_env env, gint64 i);
19
+ static napi_value fdn_uint64_to_value (napi_env env, guint64 u);
20
+ static gboolean fdn_ulong_from_value (napi_env env, napi_value value, gulong * u);
21
+ static gboolean fdn_double_from_value (napi_env env, napi_value value, gdouble * d);
22
+ static napi_value fdn_double_to_value (napi_env env, gdouble d);
23
+ static gboolean fdn_enum_from_value (napi_env env, GType enum_type, napi_value value, gint * e);
24
+ static napi_value fdn_enum_to_value (napi_env env, GType enum_type, gint e);
25
+ static gboolean fdn_utf8_from_value (napi_env env, napi_value value, gchar ** str);
26
+ static napi_value fdn_utf8_to_value (napi_env env, const gchar * str);
27
+ static gboolean fdn_strv_from_value (napi_env env, napi_value value, gchar *** strv);
28
+ static napi_value fdn_strv_to_value (napi_env env, gchar ** strv);
29
+ static napi_value fdn_buffer_to_value (napi_env env, const guint8 * data, gsize size);
30
+ static gboolean fdn_bytes_from_value (napi_env env, napi_value value, GBytes ** bytes);
31
+ static napi_value fdn_bytes_to_value (napi_env env, GBytes * bytes);
32
+ static gboolean fdn_vardict_from_value (napi_env env, napi_value value, GHashTable ** vardict);
33
+ static napi_value fdn_vardict_to_value (napi_env env, GHashTable * vardict);
34
+ static gboolean fdn_variant_from_value (napi_env env, napi_value value, GVariant ** variant);
35
+ static napi_value fdn_variant_to_value (napi_env env, GVariant * variant);
36
+ static gboolean fdn_gvalue_from_value (napi_env env, GType type, napi_value js_value, GValue * value);
37
+ static napi_value fdn_gvalue_to_value (napi_env env, GValue * value);
38
+ static gboolean fdn_error_from_value (napi_env env, napi_value value, GError ** error);
39
+ static napi_value fdn_error_to_value (napi_env env, GError * error);
40
+ static gboolean fdn_file_from_value (napi_env env, napi_value value, GFile ** file);
41
+ static napi_value fdn_file_to_value (napi_env env, GFile * file);
42
+ static gboolean fdn_tls_certificate_from_value (napi_env env, napi_value value, GTlsCertificate ** certificate);
43
+ static napi_value fdn_tls_certificate_to_value (napi_env env, GTlsCertificate * certificate);
44
+ static gboolean fdn_options_from_value (napi_env env, GType object_type, napi_value value, gpointer * options);
45
+
46
+ static napi_value fdn_object_subclass_to_value (napi_env env, GObject * object);
47
+ static napi_value fdn_object_new (napi_env env, GObject * handle, napi_ref constructor);
48
+ static gboolean fdn_object_wrap (napi_env env, napi_value wrapper, GObject * handle, napi_finalize finalizer);
49
+ static gboolean fdn_object_unwrap (napi_env env, napi_value wrapper, GType expected_type, GObject ** handle);
50
+ static void fdn_object_finalize (napi_env env, void * finalize_data, void * finalize_hint);
51
+ static napi_value fdn_object_get_signal (napi_env env, napi_callback_info info, const gchar * name, const gchar * js_storage_name, FdnSignalBehavior behavior);
52
+
53
+ static napi_value fdn_signal_new (napi_env env, GObject * handle, const gchar * name, FdnSignalBehavior behavior);
54
+ static void fdn_signal_register (napi_env env, napi_value exports);
55
+ static napi_value fdn_signal_construct (napi_env env, napi_callback_info info);
56
+ static void fdn_signal_finalize (napi_env env, void * finalize_data, void * finalize_hint);
57
+ static napi_value fdn_signal_connect (napi_env env, napi_callback_info info);
58
+ static napi_value fdn_signal_disconnect (napi_env env, napi_callback_info info);
59
+ static void fdn_signal_disconnect_closure (FdnSignal * self, FdnSignalClosure * closure);
60
+ static gboolean fdn_signal_parse_arguments (napi_env env, napi_callback_info info, FdnSignal ** self, napi_value * js_self, napi_value * handler);
61
+ static FdnSignalClosure * fdn_signal_closure_new (napi_env env, FdnSignal * sig, napi_value js_sig, napi_value handler);
62
+ static void fdn_signal_closure_finalize (gpointer data, GClosure * closure);
63
+ static void fdn_signal_closure_marshal (GClosure * closure, GValue * return_gvalue, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data);
64
+ static void fdn_signal_closure_deliver (napi_env env, napi_value js_cb, void * context, void * data);
65
+
66
+ static void fdn_keep_alive_until (napi_env env, napi_value js_object, GObject * handle, FdnIsDestroyedFunc is_destroyed, const gchar * destroy_signal_name);
67
+ static void fdn_keep_alive_on_finalize (napi_env env, void * finalize_data, void * finalize_hint);
68
+ static void fdn_keep_alive_on_destroy_signal (GObject * handle, gpointer user_data);
69
+ static void fdn_keep_alive_on_destroy_signal_handler_detached (gpointer data, GClosure * closure);
70
+ static void fdn_keep_alive_schedule_cleanup (FdnKeepAliveContext * context);
71
+ static void fdn_keep_alive_on_tsfn_invoke (napi_env env, napi_value js_cb, void * context, void * data);
72
+
73
+ static void fdn_inherit_val_val (napi_env env, napi_value sub_ctor, napi_value super_ctor, napi_value object_ctor, napi_value set_proto);
74
+ G_GNUC_UNUSED static void fdn_inherit_val_ref (napi_env env, napi_value sub_ctor, napi_ref super_ctor, napi_value object_ctor, napi_value set_proto);
75
+ static void fdn_inherit_ref_val (napi_env env, napi_ref sub_ctor, napi_value super_ctor, napi_value object_ctor, napi_value set_proto);
76
+ static void fdn_inherit_ref_ref (napi_env env, napi_ref sub_ctor, napi_ref super_ctor, napi_value object_ctor, napi_value set_proto);
77
+
78
+ static gchar * fdn_camel_case_to_kebab_case (const gchar * name);
@@ -0,0 +1,57 @@
1
+ typedef enum {
2
+ FDN_SIGNAL_ALLOW_EXIT,
3
+ FDN_SIGNAL_KEEP_ALIVE
4
+ } FdnSignalBehavior;
5
+
6
+ typedef struct {
7
+ GObject * handle;
8
+ guint id;
9
+ FdnSignalBehavior behavior;
10
+ GSList * closures;
11
+ } FdnSignal;
12
+
13
+ typedef enum {
14
+ FDN_SIGNAL_CLOSURE_OPEN,
15
+ FDN_SIGNAL_CLOSURE_CLOSED,
16
+ } FdnSignalClosureState;
17
+
18
+ typedef struct {
19
+ GClosure closure;
20
+ FdnSignal * sig;
21
+ napi_ref js_sig;
22
+ FdnSignalClosureState state;
23
+ napi_threadsafe_function tsfn;
24
+ napi_ref handler;
25
+ gulong handler_id;
26
+ } FdnSignalClosure;
27
+
28
+ typedef enum {
29
+ FDN_SIGNAL_CLOSURE_MESSAGE_DESTROY,
30
+ FDN_SIGNAL_CLOSURE_MESSAGE_MARSHAL,
31
+ } FdnSignalClosureMessageType;
32
+
33
+ typedef struct {
34
+ napi_ref js_sig;
35
+ napi_threadsafe_function tsfn;
36
+ napi_ref handler;
37
+ } FdnSignalClosureMessageDestroy;
38
+
39
+ typedef struct {
40
+ GArray * args;
41
+ } FdnSignalClosureMessageMarshal;
42
+
43
+ typedef struct {
44
+ FdnSignalClosureMessageType type;
45
+ union {
46
+ FdnSignalClosureMessageDestroy destroy;
47
+ FdnSignalClosureMessageMarshal marshal;
48
+ } payload;
49
+ } FdnSignalClosureMessage;
50
+
51
+ typedef struct {
52
+ guint ref_count;
53
+ GObject * handle;
54
+ gulong signal_handler_id;
55
+ } FdnKeepAliveContext;
56
+
57
+ typedef gboolean (* FdnIsDestroyedFunc) (GObject * handle);
@@ -0,0 +1,13 @@
1
+ querySystemParameters
2
+ spawn
3
+ resume
4
+ kill
5
+ attach
6
+ injectLibraryFile
7
+ injectLibraryBlob
8
+ enumerateDevices
9
+ getDeviceManager
10
+ getLocalDevice
11
+ getRemoteDevice
12
+ getUsbDevice
13
+ getDevice
@@ -0,0 +1,157 @@
1
+ let sharedDeviceManager: DeviceManager | null = null;
2
+
3
+ export async function querySystemParameters(cancellable?: Cancellable | null): Promise<SystemParameters> {
4
+ const device = await getLocalDevice(cancellable);
5
+ return await device.querySystemParameters(cancellable);
6
+ }
7
+
8
+ export async function spawn(program: string | string[], options?: SpawnOptions, cancellable?: Cancellable | null): Promise<number> {
9
+ const device = await getLocalDevice(cancellable);
10
+ return await device.spawn(program, options, cancellable);
11
+ }
12
+
13
+ export async function resume(target: TargetProcess, cancellable?: Cancellable | null): Promise<void> {
14
+ const device = await getLocalDevice(cancellable);
15
+ await device.resume(target, cancellable);
16
+ }
17
+
18
+ export async function kill(target: TargetProcess, cancellable?: Cancellable | null): Promise<void> {
19
+ const device = await getLocalDevice(cancellable);
20
+ await device.kill(target, cancellable);
21
+ }
22
+
23
+ export async function attach(target: TargetProcess, options?: SessionOptions, cancellable?: Cancellable | null): Promise<Session> {
24
+ const device = await getLocalDevice(cancellable);
25
+ return await device.attach(target, options, cancellable);
26
+ }
27
+
28
+ export async function injectLibraryFile(target: TargetProcess, path: string, entrypoint: string, data: string,
29
+ cancellable?: Cancellable | null): Promise<number> {
30
+ const device = await getLocalDevice(cancellable);
31
+ return await device.injectLibraryFile(target, path, entrypoint, data, cancellable);
32
+ }
33
+
34
+ export async function injectLibraryBlob(target: TargetProcess, blob: Buffer, entrypoint: string, data: string,
35
+ cancellable?: Cancellable | null): Promise<number> {
36
+ const device = await getLocalDevice(cancellable);
37
+ return await device.injectLibraryBlob(target, blob, entrypoint, data, cancellable);
38
+ }
39
+
40
+ export async function enumerateDevices(cancellable?: Cancellable | null): Promise<Device[]> {
41
+ const deviceManager = getDeviceManager();
42
+ return await deviceManager.enumerateDevices(cancellable);
43
+ };
44
+
45
+ export function getDeviceManager(): DeviceManager {
46
+ if (sharedDeviceManager === null) {
47
+ sharedDeviceManager = new DeviceManager();
48
+ }
49
+ return sharedDeviceManager;
50
+ }
51
+
52
+ export function getLocalDevice(cancellable?: Cancellable | null): Promise<Device> {
53
+ return getMatchingDevice(device => device.type === DeviceType.Local, {}, cancellable);
54
+ }
55
+
56
+ export function getRemoteDevice(cancellable?: Cancellable | null): Promise<Device> {
57
+ return getMatchingDevice(device => device.type === DeviceType.Remote, {}, cancellable);
58
+ }
59
+
60
+ export function getUsbDevice(options?: GetDeviceOptions, cancellable?: Cancellable | null): Promise<Device> {
61
+ return getMatchingDevice(device => device.type === DeviceType.Usb, options, cancellable);
62
+ }
63
+
64
+ export function getDevice(id: string, options?: GetDeviceOptions, cancellable?: Cancellable | null): Promise<Device> {
65
+ return getMatchingDevice(device => device.id === id, options, cancellable);
66
+ }
67
+
68
+ export interface GetDeviceOptions {
69
+ timeout?: number | null;
70
+ }
71
+
72
+ async function getMatchingDevice(predicate: DevicePredicate, options: GetDeviceOptions = {}, cancellable: Cancellable | null = null): Promise<Device> {
73
+ const device = await findMatchingDevice(predicate, cancellable);
74
+ if (device !== null) {
75
+ return device;
76
+ }
77
+
78
+ const { timeout = 0 } = options;
79
+ if (timeout === 0) {
80
+ throw new Error("Device not found");
81
+ }
82
+
83
+ const getDeviceEventually = new Promise((resolve: (device: Device) => void, reject: (error: Error) => void) => {
84
+ const deviceManager = getDeviceManager();
85
+
86
+ deviceManager.added.connect(onDeviceAdded);
87
+
88
+ const timer = (timeout !== null) ? setTimeout(onTimeout, timeout) : null;
89
+
90
+ if (cancellable !== null) {
91
+ cancellable.cancelled.connect(onCancel);
92
+ if (cancellable.isCancelled) {
93
+ onCancel();
94
+ return;
95
+ }
96
+ }
97
+
98
+ findMatchingDevice(predicate, cancellable)
99
+ .then(device => {
100
+ if (device !== null) {
101
+ onSuccess(device);
102
+ }
103
+ })
104
+ .catch(onError);
105
+
106
+ function onDeviceAdded(device: Device): void {
107
+ if (predicate(device)) {
108
+ onSuccess(device);
109
+ }
110
+ }
111
+
112
+ function onSuccess(device: Device): void {
113
+ stopMonitoring();
114
+ resolve(device);
115
+ }
116
+
117
+ function onError(error: Error): void {
118
+ stopMonitoring();
119
+ reject(error);
120
+ }
121
+
122
+ function onTimeout(): void {
123
+ onError(new Error("Timed out while waiting for device to appear"));
124
+ }
125
+
126
+ function onCancel(): void {
127
+ onError(new Error("Operation was cancelled"));
128
+ }
129
+
130
+ function stopMonitoring(): void {
131
+ cancellable?.cancelled.disconnect(onCancel);
132
+
133
+ if (timer !== null) {
134
+ clearTimeout(timer);
135
+ }
136
+
137
+ deviceManager.added.disconnect(onDeviceAdded);
138
+ }
139
+ });
140
+
141
+ return await getDeviceEventually;
142
+ }
143
+
144
+ async function findMatchingDevice(predicate: DevicePredicate, cancellable?: Cancellable | null): Promise<Device | null> {
145
+ const deviceManager = getDeviceManager();
146
+
147
+ const devices = await deviceManager.enumerateDevices(cancellable);
148
+
149
+ const matching = devices.filter(predicate);
150
+ if (matching.length === 0) {
151
+ return null;
152
+ }
153
+
154
+ return matching[0];
155
+ }
156
+
157
+ type DevicePredicate = (device: Device) => boolean;
@@ -0,0 +1,2 @@
1
+ import { Minimatch } from "minimatch";
2
+ import { Duplex } from "stream";