@qontinui/ui-bridge-native 0.6.8 → 0.6.10
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/control/action-executor.d.ts +15 -0
- package/dist/control/action-executor.d.ts.map +1 -1
- package/dist/control/index.js +36 -1
- package/dist/control/index.js.map +1 -1
- package/dist/control/index.mjs +36 -1
- package/dist/control/index.mjs.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +1 -1
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +153 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +152 -27
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.js +94 -26
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +94 -26
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/useUIElement.d.ts +10 -0
- package/dist/react/useUIElement.d.ts.map +1 -1
- package/dist/server/bind-retry.d.ts +64 -0
- package/dist/server/bind-retry.d.ts.map +1 -0
- package/dist/server/handlers.d.ts.map +1 -1
- package/dist/server/http-server.d.ts.map +1 -1
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +103 -22
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +102 -23
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/types.d.ts +14 -0
- package/dist/server/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ function inferActions(type) {
|
|
|
28
28
|
case "pressable":
|
|
29
29
|
return [...baseActions, "click", "press", "longPress", "doubleTap"];
|
|
30
30
|
case "input":
|
|
31
|
-
return [...baseActions, "click", "press", "type", "clear"];
|
|
31
|
+
return [...baseActions, "click", "press", "type", "setValue", "clear"];
|
|
32
32
|
case "text":
|
|
33
33
|
return [...baseActions, "click", "press", "longPress"];
|
|
34
34
|
case "view":
|
|
@@ -987,9 +987,10 @@ var DefaultNativeActionExecutor = class {
|
|
|
987
987
|
requestId: request.requestId,
|
|
988
988
|
durationMs: successTime - startTime
|
|
989
989
|
});
|
|
990
|
+
const fresh = this.registry.getElement(registered.id) ?? registered;
|
|
990
991
|
return {
|
|
991
992
|
success: true,
|
|
992
|
-
elementState:
|
|
993
|
+
elementState: fresh.getState(),
|
|
993
994
|
result,
|
|
994
995
|
durationMs: successTime - startTime,
|
|
995
996
|
timestamp: successTime,
|
|
@@ -1042,6 +1043,8 @@ var DefaultNativeActionExecutor = class {
|
|
|
1042
1043
|
return this.performDoubleTap(props);
|
|
1043
1044
|
case "type":
|
|
1044
1045
|
return this.performType(element, props, params);
|
|
1046
|
+
case "setValue":
|
|
1047
|
+
return this.performSetValue(element, props, params);
|
|
1045
1048
|
case "clear":
|
|
1046
1049
|
return this.performClear(element, props);
|
|
1047
1050
|
case "focus":
|
|
@@ -1134,6 +1137,38 @@ var DefaultNativeActionExecutor = class {
|
|
|
1134
1137
|
this.registry.updateElementState(element.id, { value: params.text });
|
|
1135
1138
|
}
|
|
1136
1139
|
}
|
|
1140
|
+
/**
|
|
1141
|
+
* Perform setValue action.
|
|
1142
|
+
*
|
|
1143
|
+
* Web/runner UI Bridge parity: `setValue` replaces the input's value
|
|
1144
|
+
* atomically in a single call (no per-character keystroke simulation),
|
|
1145
|
+
* mirroring the web bridge's `setValue` semantics. On native there is no
|
|
1146
|
+
* DOM value to assign, so we drive the controlled-input handler
|
|
1147
|
+
* (`onChangeText`, falling back to `onChange`) with the full string. The
|
|
1148
|
+
* registry's `state.value` is then synced so a subsequent GET on the
|
|
1149
|
+
* element reflects the new value.
|
|
1150
|
+
*
|
|
1151
|
+
* Unlike `type`, this does not append to existing content and ignores
|
|
1152
|
+
* `delay` — it is the deterministic "set the field to exactly this" action.
|
|
1153
|
+
*/
|
|
1154
|
+
async performSetValue(element, props, params) {
|
|
1155
|
+
const next = typeof params?.text === "string" ? params.text : typeof params?.value === "string" ? params.value : void 0;
|
|
1156
|
+
if (typeof next !== "string") {
|
|
1157
|
+
throw new Error('setValue action requires a string "text" (or "value") parameter');
|
|
1158
|
+
}
|
|
1159
|
+
if (typeof props.onChangeText === "function") {
|
|
1160
|
+
props.onChangeText(next);
|
|
1161
|
+
} else if (typeof props.onChange === "function") {
|
|
1162
|
+
props.onChange({
|
|
1163
|
+
nativeEvent: { text: next }
|
|
1164
|
+
});
|
|
1165
|
+
} else {
|
|
1166
|
+
throw new Error("No text change handler found on element");
|
|
1167
|
+
}
|
|
1168
|
+
if (element) {
|
|
1169
|
+
this.registry.updateElementState(element.id, { value: next });
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1137
1172
|
/**
|
|
1138
1173
|
* Perform clear action
|
|
1139
1174
|
*/
|
|
@@ -2126,6 +2161,13 @@ function matchElementsByText(registry, text, opts) {
|
|
|
2126
2161
|
scored.sort((a, b) => a.rank - b.rank);
|
|
2127
2162
|
return scored.map((s) => s.element);
|
|
2128
2163
|
}
|
|
2164
|
+
function resolveElementState(element) {
|
|
2165
|
+
const state = element.getState();
|
|
2166
|
+
if (element.type === "input" && state.value === void 0 && typeof element.props?.value === "string") {
|
|
2167
|
+
return { ...state, value: element.props.value };
|
|
2168
|
+
}
|
|
2169
|
+
return state;
|
|
2170
|
+
}
|
|
2129
2171
|
async function executeWorkflowStep(step, registry, executor) {
|
|
2130
2172
|
const startTime = Date.now();
|
|
2131
2173
|
try {
|
|
@@ -2362,7 +2404,7 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2362
2404
|
type: element.type,
|
|
2363
2405
|
label: element.label,
|
|
2364
2406
|
identifier: element.getIdentifier(),
|
|
2365
|
-
state: element
|
|
2407
|
+
state: resolveElementState(element),
|
|
2366
2408
|
actions: element.actions,
|
|
2367
2409
|
customActions: element.customActions ? Object.keys(element.customActions) : void 0,
|
|
2368
2410
|
registeredHandlers: handlers.length > 0 ? handlers : void 0,
|
|
@@ -2376,18 +2418,19 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2376
2418
|
if (!element) {
|
|
2377
2419
|
return error2(`Element not found: ${id}`, "ELEMENT_NOT_FOUND");
|
|
2378
2420
|
}
|
|
2379
|
-
return success2({ state: element
|
|
2421
|
+
return success2({ state: resolveElementState(element) });
|
|
2380
2422
|
},
|
|
2381
2423
|
executeAction: async (ctx) => {
|
|
2382
|
-
const
|
|
2383
|
-
const
|
|
2384
|
-
|
|
2424
|
+
const rawBody = ctx.body ?? {};
|
|
2425
|
+
const envelope = rawBody.request && typeof rawBody.request === "object" ? rawBody.request : rawBody;
|
|
2426
|
+
const id = ctx.params.id ?? rawBody.id ?? "";
|
|
2427
|
+
if (!envelope?.action) {
|
|
2385
2428
|
return error2("Action is required", "INVALID_REQUEST");
|
|
2386
2429
|
}
|
|
2387
2430
|
const response = await executor.executeAction(id, {
|
|
2388
|
-
action:
|
|
2389
|
-
params:
|
|
2390
|
-
waitOptions:
|
|
2431
|
+
action: envelope.action,
|
|
2432
|
+
params: envelope.params,
|
|
2433
|
+
waitOptions: envelope.waitOptions
|
|
2391
2434
|
});
|
|
2392
2435
|
if (!response.success) {
|
|
2393
2436
|
return error2(response.error || "Action failed", "ACTION_FAILED");
|
|
@@ -2899,7 +2942,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2899
2942
|
return success2({
|
|
2900
2943
|
entries: [],
|
|
2901
2944
|
count: 0,
|
|
2902
|
-
bufferSize: 0
|
|
2945
|
+
bufferSize: 0,
|
|
2946
|
+
installed: false
|
|
2903
2947
|
});
|
|
2904
2948
|
}
|
|
2905
2949
|
const entries = buf.entries({
|
|
@@ -2909,7 +2953,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2909
2953
|
return success2({
|
|
2910
2954
|
entries,
|
|
2911
2955
|
count: entries.length,
|
|
2912
|
-
bufferSize: buf.size()
|
|
2956
|
+
bufferSize: buf.size(),
|
|
2957
|
+
installed: buf.isInstalled()
|
|
2913
2958
|
});
|
|
2914
2959
|
},
|
|
2915
2960
|
getNetworkRequests: async (ctx) => {
|
|
@@ -2920,7 +2965,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2920
2965
|
return success2({
|
|
2921
2966
|
entries: [],
|
|
2922
2967
|
count: 0,
|
|
2923
|
-
bufferSize: 0
|
|
2968
|
+
bufferSize: 0,
|
|
2969
|
+
installed: false
|
|
2924
2970
|
});
|
|
2925
2971
|
}
|
|
2926
2972
|
const entries = buf.entries({
|
|
@@ -2930,7 +2976,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2930
2976
|
return success2({
|
|
2931
2977
|
entries,
|
|
2932
2978
|
count: entries.length,
|
|
2933
|
-
bufferSize: buf.size()
|
|
2979
|
+
bufferSize: buf.size(),
|
|
2980
|
+
installed: buf.isInstalled()
|
|
2934
2981
|
});
|
|
2935
2982
|
},
|
|
2936
2983
|
// Test hooks — modal stack manipulation
|
|
@@ -3022,7 +3069,7 @@ function createServerHandlers(registry, executor, config) {
|
|
|
3022
3069
|
};
|
|
3023
3070
|
if (config?.appInfo) {
|
|
3024
3071
|
response.uiBridge = {
|
|
3025
|
-
version: "0.
|
|
3072
|
+
version: "0.6.10",
|
|
3026
3073
|
...config.appInfo,
|
|
3027
3074
|
capabilities: ["elements", "components", "actions", "design"],
|
|
3028
3075
|
elementCount: stats.elements,
|
|
@@ -3349,7 +3396,10 @@ var WS_ROUTES = [
|
|
|
3349
3396
|
// same handler at both paths to keep agents portable across platforms.
|
|
3350
3397
|
{ pattern: "ai/find", handler: "find", httpMethods: ["POST"] },
|
|
3351
3398
|
{ pattern: "control/snapshot", handler: "getSnapshot", httpMethods: ["GET"] },
|
|
3352
|
-
|
|
3399
|
+
// Discovery alias — web/runner parity with `POST /control/discover` (a
|
|
3400
|
+
// legacy alias for snapshot/find). Mounted on HTTP (GET+POST) so mobile
|
|
3401
|
+
// doesn't 404 where web returns 200; delegates to the snapshot handler.
|
|
3402
|
+
{ pattern: "control/discover", handler: "getSnapshot", httpMethods: ["GET", "POST"] },
|
|
3353
3403
|
// Page health — accepts both GET and POST so the canonical skill invocation
|
|
3354
3404
|
// (`POST .../control/page-health` with an empty body) and ad-hoc curls both
|
|
3355
3405
|
// work without a body-shape gotcha.
|
|
@@ -3443,19 +3493,26 @@ var WS_ROUTES = [
|
|
|
3443
3493
|
httpMethods: ["POST"],
|
|
3444
3494
|
requiresTestHooks: true
|
|
3445
3495
|
},
|
|
3446
|
-
// Observability — last-N console errors + network requests.
|
|
3447
|
-
//
|
|
3496
|
+
// Observability — last-N console errors + network requests.
|
|
3497
|
+
//
|
|
3498
|
+
// Always mounted (not testHooks-gated) so they return a schema-valid 200
|
|
3499
|
+
// on every build instead of a 404 that agents can't distinguish from a
|
|
3500
|
+
// missing route. The INVASIVE part — monkey-patching `console.error` /
|
|
3501
|
+
// `fetch` / `XMLHttpRequest` — stays gated behind `testHooks` (see
|
|
3502
|
+
// NativeUIBridgeServer.start → buffer.install()). When the patches aren't
|
|
3503
|
+
// installed the handlers report `installed: false` + empty entries, so
|
|
3504
|
+
// production builds expose the contract without observing real users'
|
|
3505
|
+
// console/network traffic. Set `features.testHooks` (typically on
|
|
3506
|
+
// `__DEV__`) to populate the buffers with live data.
|
|
3448
3507
|
{
|
|
3449
3508
|
pattern: "control/console-errors",
|
|
3450
3509
|
handler: "getConsoleErrors",
|
|
3451
|
-
httpMethods: ["GET"]
|
|
3452
|
-
requiresTestHooks: true
|
|
3510
|
+
httpMethods: ["GET"]
|
|
3453
3511
|
},
|
|
3454
3512
|
{
|
|
3455
3513
|
pattern: "sdk/network-requests",
|
|
3456
3514
|
handler: "getNetworkRequests",
|
|
3457
|
-
httpMethods: ["GET"]
|
|
3458
|
-
requiresTestHooks: true
|
|
3515
|
+
httpMethods: ["GET"]
|
|
3459
3516
|
}
|
|
3460
3517
|
];
|
|
3461
3518
|
var HANDLER_DESCRIPTIONS = {
|
|
@@ -3502,8 +3559,8 @@ var HANDLER_DESCRIPTIONS = {
|
|
|
3502
3559
|
typeInto: "App-agnostic: type into the input matching a label: body { label, text, clear?, visibleOnly? }. (selector form is web-only)",
|
|
3503
3560
|
readValue: "STUB \u2014 selector-based; NOT_SUPPORTED on native (no DOM). Use /control/element/:id/state to read a value.",
|
|
3504
3561
|
findByText: "App-agnostic: list elements matching free-text (no press): body { text, visibleOnly? }",
|
|
3505
|
-
getConsoleErrors: "
|
|
3506
|
-
getNetworkRequests: "
|
|
3562
|
+
getConsoleErrors: "Last-N console.error/console.warn entries; ?since=<ms>&limit=<n>. `installed:false` when capture is off (no testHooks) \u2014 entries empty but schema-valid.",
|
|
3563
|
+
getNetworkRequests: "Last-N fetch/XHR entries with status + duration; ?since=<ms>&limit=<n>. `installed:false` when capture is off (no testHooks) \u2014 entries empty but schema-valid.",
|
|
3507
3564
|
pushModal: "TEST HOOK \u2014 push a modal onto the snapshot.modalStack via the registry ModalDetector",
|
|
3508
3565
|
dismissModal: "TEST HOOK \u2014 dismiss a modal by id from the snapshot.modalStack via the registry ModalDetector",
|
|
3509
3566
|
keepAwake: "TEST HOOK \u2014 keep the device screen awake via the injected keepAwakeProvider: body { enabled: boolean, durationMs?: number }"
|
|
@@ -5674,7 +5731,8 @@ function useUIElement(options) {
|
|
|
5674
5731
|
parentPath,
|
|
5675
5732
|
style,
|
|
5676
5733
|
stateStyles: stateStylesProp,
|
|
5677
|
-
handlers: handlersProp
|
|
5734
|
+
handlers: handlersProp,
|
|
5735
|
+
value: valueProp
|
|
5678
5736
|
} = options;
|
|
5679
5737
|
const treePath = parentPath ? `${parentPath}/${id}` : id;
|
|
5680
5738
|
const bridgeProps = react.useMemo(
|
|
@@ -5700,9 +5758,12 @@ function useUIElement(options) {
|
|
|
5700
5758
|
});
|
|
5701
5759
|
registeredRef.current = true;
|
|
5702
5760
|
registeredIdRef.current = id;
|
|
5761
|
+
if (typeof valueProp === "string") {
|
|
5762
|
+
bridge.registry.updateElementState(id, { value: valueProp });
|
|
5763
|
+
}
|
|
5703
5764
|
setRegistered(true);
|
|
5704
5765
|
scheduleDeadButtonWarning(bridge, id, type);
|
|
5705
|
-
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp]);
|
|
5766
|
+
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp, valueProp]);
|
|
5706
5767
|
const unregister = react.useCallback(() => {
|
|
5707
5768
|
if (!bridge || !registeredRef.current) return;
|
|
5708
5769
|
bridge.registry.unregisterElement(registeredIdRef.current ?? id);
|
|
@@ -5832,6 +5893,13 @@ function useUIElement(options) {
|
|
|
5832
5893
|
}
|
|
5833
5894
|
};
|
|
5834
5895
|
}, [bridge, registered, id, handlersProp]);
|
|
5896
|
+
react.useEffect(() => {
|
|
5897
|
+
if (!bridge || !registered) return;
|
|
5898
|
+
if (typeof valueProp !== "string") return;
|
|
5899
|
+
const current = bridge.registry.getElement(id)?.getState().value;
|
|
5900
|
+
if (current === valueProp) return;
|
|
5901
|
+
bridge.registry.updateElementState(id, { value: valueProp });
|
|
5902
|
+
}, [bridge, registered, id, valueProp]);
|
|
5835
5903
|
react.useCallback(
|
|
5836
5904
|
(props) => {
|
|
5837
5905
|
propsRef.current = { ...propsRef.current, ...props };
|
|
@@ -6223,6 +6291,11 @@ var UI_BRIDGE_NATIVE_ROUTES = {
|
|
|
6223
6291
|
path: "/ui-bridge/control/snapshot",
|
|
6224
6292
|
description: "Get full bridge snapshot"
|
|
6225
6293
|
},
|
|
6294
|
+
DISCOVER: {
|
|
6295
|
+
method: "GET",
|
|
6296
|
+
path: "/ui-bridge/control/discover",
|
|
6297
|
+
description: "Discover elements (alias for snapshot; web/runner parity)"
|
|
6298
|
+
},
|
|
6226
6299
|
PAGE_HEALTH: {
|
|
6227
6300
|
method: "POST",
|
|
6228
6301
|
path: "/ui-bridge/control/page-health",
|
|
@@ -6350,6 +6423,18 @@ var UI_BRIDGE_NATIVE_ROUTES = {
|
|
|
6350
6423
|
path: "/ui-bridge/control/modal/dismiss/:id",
|
|
6351
6424
|
description: "Dismiss a modal by id (testHooks)"
|
|
6352
6425
|
},
|
|
6426
|
+
// Observability — last-N ring buffers (always mounted; `installed:false`
|
|
6427
|
+
// when the console/network patches are off, i.e. no testHooks).
|
|
6428
|
+
CONSOLE_ERRORS: {
|
|
6429
|
+
method: "GET",
|
|
6430
|
+
path: "/ui-bridge/control/console-errors",
|
|
6431
|
+
description: "Last-N captured console.error/console.warn entries"
|
|
6432
|
+
},
|
|
6433
|
+
NETWORK_REQUESTS: {
|
|
6434
|
+
method: "GET",
|
|
6435
|
+
path: "/ui-bridge/sdk/network-requests",
|
|
6436
|
+
description: "Last-N captured fetch/XHR requests with status + duration"
|
|
6437
|
+
},
|
|
6353
6438
|
// Health
|
|
6354
6439
|
HEALTH: {
|
|
6355
6440
|
method: "GET",
|
|
@@ -6556,6 +6641,46 @@ function decodeTextPayload(payload) {
|
|
|
6556
6641
|
return new TextDecoder().decode(payload);
|
|
6557
6642
|
}
|
|
6558
6643
|
|
|
6644
|
+
// src/server/bind-retry.ts
|
|
6645
|
+
function isAddrInUseError(err) {
|
|
6646
|
+
const message = err instanceof Error ? err.message : typeof err === "string" ? err : String(err);
|
|
6647
|
+
const code = err?.code;
|
|
6648
|
+
return message.includes("EADDRINUSE") || message.toLowerCase().includes("address already in use") || code === "EADDRINUSE";
|
|
6649
|
+
}
|
|
6650
|
+
var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
6651
|
+
async function bindWithRetry(attempt, options = {}) {
|
|
6652
|
+
const {
|
|
6653
|
+
minTotalMs = 3e4,
|
|
6654
|
+
initialDelayMs = 500,
|
|
6655
|
+
maxDelayMs = 5e3,
|
|
6656
|
+
backoffFactor = 2,
|
|
6657
|
+
logger = console,
|
|
6658
|
+
sleep: sleep2 = defaultSleep,
|
|
6659
|
+
now = Date.now
|
|
6660
|
+
} = options;
|
|
6661
|
+
const startedAt = now();
|
|
6662
|
+
let delay = initialDelayMs;
|
|
6663
|
+
let attemptIndex = 0;
|
|
6664
|
+
for (; ; ) {
|
|
6665
|
+
try {
|
|
6666
|
+
await attempt(attemptIndex);
|
|
6667
|
+
return;
|
|
6668
|
+
} catch (err) {
|
|
6669
|
+
const elapsed = now() - startedAt;
|
|
6670
|
+
const budgetExhausted = elapsed + delay >= minTotalMs;
|
|
6671
|
+
if (!isAddrInUseError(err) || budgetExhausted) {
|
|
6672
|
+
throw err;
|
|
6673
|
+
}
|
|
6674
|
+
logger.warn(
|
|
6675
|
+
`[ui-bridge-native] bind failed with EADDRINUSE (attempt ${attemptIndex + 1}); retrying in ${delay}ms (elapsed ${elapsed}ms / budget ${minTotalMs === Infinity ? "\u221E" : minTotalMs}ms)`
|
|
6676
|
+
);
|
|
6677
|
+
await sleep2(delay);
|
|
6678
|
+
delay = Math.min(delay * backoffFactor, maxDelayMs);
|
|
6679
|
+
attemptIndex += 1;
|
|
6680
|
+
}
|
|
6681
|
+
}
|
|
6682
|
+
}
|
|
6683
|
+
|
|
6559
6684
|
// src/server/ws-connection.ts
|
|
6560
6685
|
var WebSocketConnection = class {
|
|
6561
6686
|
constructor(id, socket, onMessage, onClose) {
|
|
@@ -7137,6 +7262,7 @@ exports.UI_BRIDGE_NATIVE_ROUTES = UI_BRIDGE_NATIVE_ROUTES;
|
|
|
7137
7262
|
exports.UndoTracker = UndoTracker;
|
|
7138
7263
|
exports.WebSocketConnection = WebSocketConnection;
|
|
7139
7264
|
exports.WebSocketEventBridge = WebSocketEventBridge;
|
|
7265
|
+
exports.bindWithRetry = bindWithRetry;
|
|
7140
7266
|
exports.buildTreePath = buildTreePath;
|
|
7141
7267
|
exports.buildUpgradeResponse = buildUpgradeResponse;
|
|
7142
7268
|
exports.captureNativeResponsiveSnapshot = captureNativeResponsiveSnapshot;
|
|
@@ -7152,6 +7278,7 @@ exports.findAllByPattern = findAllByPattern;
|
|
|
7152
7278
|
exports.findElementByIdentifier = findElementByIdentifier;
|
|
7153
7279
|
exports.getGlobalRegistry = getGlobalRegistry;
|
|
7154
7280
|
exports.getNativeElementDesignData = getNativeElementDesignData;
|
|
7281
|
+
exports.isAddrInUseError = isAddrInUseError;
|
|
7155
7282
|
exports.mapNativeStyleToExtended = mapNativeStyleToExtended;
|
|
7156
7283
|
exports.matchesIdentifier = matchesIdentifier;
|
|
7157
7284
|
exports.parseTreePath = parseTreePath;
|