@mearl/native-host 2.7.0 → 2.7.1
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/index.js +160 -6
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -2091,8 +2091,8 @@ function resolvePageDragInput(data) {
|
|
|
2091
2091
|
if (!data || typeof data !== "object") {
|
|
2092
2092
|
throw new Error("page_drag: payload is required");
|
|
2093
2093
|
}
|
|
2094
|
-
if (data.dragMode !== void 0 && !["auto", "mouse", "touch"].includes(data.dragMode)) {
|
|
2095
|
-
throw new Error('page_drag: "dragMode" must be one of auto, mouse, touch');
|
|
2094
|
+
if (data.dragMode !== void 0 && !["auto", "dom", "mouse", "touch"].includes(data.dragMode)) {
|
|
2095
|
+
throw new Error('page_drag: "dragMode" must be one of auto, dom, mouse, touch');
|
|
2096
2096
|
}
|
|
2097
2097
|
const durationMs = data.durationMs ?? PAGE_DRAG_DEFAULT_DURATION_MS;
|
|
2098
2098
|
if (!Number.isFinite(durationMs) || durationMs < 0 || durationMs > PAGE_DRAG_MAX_DURATION_MS) {
|
|
@@ -2105,6 +2105,16 @@ function resolvePageDragInput(data) {
|
|
|
2105
2105
|
durationMs: Math.round(durationMs)
|
|
2106
2106
|
};
|
|
2107
2107
|
}
|
|
2108
|
+
function resolvePageDragDispatchPolicy(dragMode, visibilityState, touchEmulationEnabled) {
|
|
2109
|
+
const requestedMode = dragMode ?? "auto";
|
|
2110
|
+
const pointerType = requestedMode === "mouse" || requestedMode === "touch" ? requestedMode : touchEmulationEnabled ? "touch" : "mouse";
|
|
2111
|
+
if (requestedMode === "dom")
|
|
2112
|
+
return { dispatchMode: "dom", pointerType };
|
|
2113
|
+
if (requestedMode === "auto" && visibilityState === "hidden") {
|
|
2114
|
+
return { dispatchMode: "dom", pointerType, fallbackReason: "page-hidden" };
|
|
2115
|
+
}
|
|
2116
|
+
return { dispatchMode: "trusted-input", pointerType };
|
|
2117
|
+
}
|
|
2108
2118
|
function buildPageDragPath(from, to, durationMs) {
|
|
2109
2119
|
const steps = Math.max(PAGE_DRAG_MIN_STEPS, Math.min(PAGE_DRAG_MAX_STEPS, Math.ceil(durationMs / PAGE_DRAG_STEP_INTERVAL_MS)));
|
|
2110
2120
|
const points = Array.from({ length: steps }, (_, index) => {
|
|
@@ -2116,6 +2126,116 @@ function buildPageDragPath(from, to, durationMs) {
|
|
|
2116
2126
|
});
|
|
2117
2127
|
return { points, intervalMs: durationMs / steps };
|
|
2118
2128
|
}
|
|
2129
|
+
function dragBetweenPointsInPage(from, points, pointerType) {
|
|
2130
|
+
const target = document.elementFromPoint(from.x, from.y);
|
|
2131
|
+
if (!target) {
|
|
2132
|
+
return {
|
|
2133
|
+
dragged: false,
|
|
2134
|
+
steps: 0,
|
|
2135
|
+
error: `No element found at drag start point (${from.x}, ${from.y})`
|
|
2136
|
+
};
|
|
2137
|
+
}
|
|
2138
|
+
if (points.length === 0) {
|
|
2139
|
+
return { dragged: false, steps: 0, error: "Drag path must contain at least one point" };
|
|
2140
|
+
}
|
|
2141
|
+
const view = target.ownerDocument.defaultView ?? window;
|
|
2142
|
+
const realm = view;
|
|
2143
|
+
const pointerId = 1;
|
|
2144
|
+
const pointerInit = (point, buttons, pressure) => ({
|
|
2145
|
+
bubbles: true,
|
|
2146
|
+
cancelable: true,
|
|
2147
|
+
composed: true,
|
|
2148
|
+
view,
|
|
2149
|
+
clientX: point.x,
|
|
2150
|
+
clientY: point.y,
|
|
2151
|
+
screenX: point.x,
|
|
2152
|
+
screenY: point.y,
|
|
2153
|
+
button: 0,
|
|
2154
|
+
buttons,
|
|
2155
|
+
pointerId,
|
|
2156
|
+
pointerType,
|
|
2157
|
+
isPrimary: true,
|
|
2158
|
+
pressure,
|
|
2159
|
+
width: 1,
|
|
2160
|
+
height: 1
|
|
2161
|
+
});
|
|
2162
|
+
const dispatchPointer = (type, point, buttons, pressure) => {
|
|
2163
|
+
if (typeof realm.PointerEvent !== "function")
|
|
2164
|
+
return false;
|
|
2165
|
+
target.dispatchEvent(new realm.PointerEvent(type, pointerInit(point, buttons, pressure)));
|
|
2166
|
+
return true;
|
|
2167
|
+
};
|
|
2168
|
+
const dispatchMouse = (type, point, buttons) => {
|
|
2169
|
+
if (typeof realm.MouseEvent !== "function")
|
|
2170
|
+
return false;
|
|
2171
|
+
target.dispatchEvent(new realm.MouseEvent(type, {
|
|
2172
|
+
bubbles: true,
|
|
2173
|
+
cancelable: true,
|
|
2174
|
+
composed: true,
|
|
2175
|
+
view,
|
|
2176
|
+
clientX: point.x,
|
|
2177
|
+
clientY: point.y,
|
|
2178
|
+
screenX: point.x,
|
|
2179
|
+
screenY: point.y,
|
|
2180
|
+
button: 0,
|
|
2181
|
+
buttons
|
|
2182
|
+
}));
|
|
2183
|
+
return true;
|
|
2184
|
+
};
|
|
2185
|
+
const createTouch = (point) => {
|
|
2186
|
+
const init = {
|
|
2187
|
+
identifier: pointerId,
|
|
2188
|
+
target,
|
|
2189
|
+
clientX: point.x,
|
|
2190
|
+
clientY: point.y,
|
|
2191
|
+
screenX: point.x,
|
|
2192
|
+
screenY: point.y,
|
|
2193
|
+
pageX: point.x + view.scrollX,
|
|
2194
|
+
pageY: point.y + view.scrollY,
|
|
2195
|
+
radiusX: 1,
|
|
2196
|
+
radiusY: 1,
|
|
2197
|
+
rotationAngle: 0,
|
|
2198
|
+
force: 0.5
|
|
2199
|
+
};
|
|
2200
|
+
return typeof realm.Touch === "function" ? new realm.Touch(init) : init;
|
|
2201
|
+
};
|
|
2202
|
+
const dispatchTouch = (type, point) => {
|
|
2203
|
+
if (typeof realm.TouchEvent !== "function")
|
|
2204
|
+
return false;
|
|
2205
|
+
const touch = createTouch(point);
|
|
2206
|
+
const activeTouches = type === "touchend" ? [] : [touch];
|
|
2207
|
+
target.dispatchEvent(new realm.TouchEvent(type, {
|
|
2208
|
+
bubbles: true,
|
|
2209
|
+
cancelable: true,
|
|
2210
|
+
composed: true,
|
|
2211
|
+
touches: activeTouches,
|
|
2212
|
+
targetTouches: activeTouches,
|
|
2213
|
+
changedTouches: [touch]
|
|
2214
|
+
}));
|
|
2215
|
+
return true;
|
|
2216
|
+
};
|
|
2217
|
+
let dispatched = dispatchPointer("pointerdown", from, 1, 0.5);
|
|
2218
|
+
dispatched = pointerType === "touch" ? dispatchTouch("touchstart", from) || dispatched : dispatchMouse("mousedown", from, 1) || dispatched;
|
|
2219
|
+
for (const point of points) {
|
|
2220
|
+
dispatched = dispatchPointer("pointermove", point, 1, 0.5) || dispatched;
|
|
2221
|
+
dispatched = pointerType === "touch" ? dispatchTouch("touchmove", point) || dispatched : dispatchMouse("mousemove", point, 1) || dispatched;
|
|
2222
|
+
}
|
|
2223
|
+
const end = points[points.length - 1];
|
|
2224
|
+
dispatched = pointerType === "touch" ? dispatchTouch("touchend", end) || dispatched : dispatchMouse("mouseup", end, 0) || dispatched;
|
|
2225
|
+
dispatched = dispatchPointer("pointerup", end, 0, 0) || dispatched;
|
|
2226
|
+
return dispatched ? { dragged: true, steps: points.length } : { dragged: false, steps: 0, error: "This page does not support synthetic drag events" };
|
|
2227
|
+
}
|
|
2228
|
+
var DRAG_BETWEEN_POINTS_IN_PAGE_SOURCE = dragBetweenPointsInPage.toString();
|
|
2229
|
+
function buildPageDragDomExpression(from, points, pointerType) {
|
|
2230
|
+
return `(${DRAG_BETWEEN_POINTS_IN_PAGE_SOURCE})(${JSON.stringify(from)}, ${JSON.stringify(points)}, ${JSON.stringify(pointerType)})`;
|
|
2231
|
+
}
|
|
2232
|
+
function unwrapPageDragDomResult(result) {
|
|
2233
|
+
if (!result)
|
|
2234
|
+
throw new Error("page_drag: DOM simulation returned no result");
|
|
2235
|
+
if (!result.dragged)
|
|
2236
|
+
throw new Error(`page_drag: ${result.error}`);
|
|
2237
|
+
return result;
|
|
2238
|
+
}
|
|
2119
2239
|
function getDragCoordsFromNode() {
|
|
2120
2240
|
const el = this.nodeType === Node.TEXT_NODE ? this.parentElement : this;
|
|
2121
2241
|
if (!el || typeof el.getBoundingClientRect !== "function")
|
|
@@ -8489,18 +8609,52 @@ async function resolveDragEndpoint(session, endpoint) {
|
|
|
8489
8609
|
}
|
|
8490
8610
|
async function cdpPageDrag(session, data) {
|
|
8491
8611
|
const input = resolvePageDragInput(data);
|
|
8612
|
+
const visibilityResult = input.dragMode === "auto" ? await session.client.sendCommand("Runtime.evaluate", {
|
|
8613
|
+
expression: "document.visibilityState",
|
|
8614
|
+
returnByValue: true
|
|
8615
|
+
}) : void 0;
|
|
8616
|
+
const touchEmulationEnabled = input.dragMode === "auto" || input.dragMode === "dom" ? await prefersTouchInput(session) : input.dragMode === "touch";
|
|
8617
|
+
const policy = resolvePageDragDispatchPolicy(
|
|
8618
|
+
input.dragMode,
|
|
8619
|
+
visibilityResult?.result?.value,
|
|
8620
|
+
touchEmulationEnabled
|
|
8621
|
+
);
|
|
8492
8622
|
await scrollDragSourceIntoView(session, input.from);
|
|
8493
8623
|
const from = await resolveDragEndpoint(session, input.from);
|
|
8494
8624
|
const to = await resolveDragEndpoint(session, input.to);
|
|
8495
8625
|
if (Math.hypot(to.point.x - from.point.x, to.point.y - from.point.y) < 1) {
|
|
8496
8626
|
throw new Error("page_drag: resolved endpoints must be at least 1 viewport pixel apart");
|
|
8497
8627
|
}
|
|
8498
|
-
|
|
8628
|
+
if (policy.dispatchMode === "dom") {
|
|
8629
|
+
const path15 = buildPageDragPath(from.point, to.point, input.durationMs);
|
|
8630
|
+
const result = await session.client.sendCommand("Runtime.evaluate", {
|
|
8631
|
+
expression: buildPageDragDomExpression(from.point, path15.points, policy.pointerType),
|
|
8632
|
+
returnByValue: true
|
|
8633
|
+
});
|
|
8634
|
+
if (result.exceptionDetails) {
|
|
8635
|
+
throw new Error(
|
|
8636
|
+
result.exceptionDetails.exception?.description ?? result.exceptionDetails.text ?? "page_drag: DOM simulation failed"
|
|
8637
|
+
);
|
|
8638
|
+
}
|
|
8639
|
+
const { steps: steps2 } = unwrapPageDragDomResult(
|
|
8640
|
+
result.result?.value
|
|
8641
|
+
);
|
|
8642
|
+
return {
|
|
8643
|
+
dragged: true,
|
|
8644
|
+
from,
|
|
8645
|
+
to,
|
|
8646
|
+
dispatchMode: "dom",
|
|
8647
|
+
pointerType: policy.pointerType,
|
|
8648
|
+
durationMs: input.durationMs,
|
|
8649
|
+
steps: steps2,
|
|
8650
|
+
...policy.fallbackReason ? { fallbackReason: policy.fallbackReason } : {}
|
|
8651
|
+
};
|
|
8652
|
+
}
|
|
8499
8653
|
const { steps } = await dispatchCdpDrag(
|
|
8500
8654
|
session,
|
|
8501
8655
|
from.point,
|
|
8502
8656
|
to.point,
|
|
8503
|
-
pointerType,
|
|
8657
|
+
policy.pointerType,
|
|
8504
8658
|
input.durationMs
|
|
8505
8659
|
);
|
|
8506
8660
|
return {
|
|
@@ -8508,7 +8662,7 @@ async function cdpPageDrag(session, data) {
|
|
|
8508
8662
|
from,
|
|
8509
8663
|
to,
|
|
8510
8664
|
dispatchMode: "trusted-input",
|
|
8511
|
-
pointerType,
|
|
8665
|
+
pointerType: policy.pointerType,
|
|
8512
8666
|
durationMs: input.durationMs,
|
|
8513
8667
|
steps
|
|
8514
8668
|
};
|
|
@@ -10634,7 +10788,7 @@ import os2 from "node:os";
|
|
|
10634
10788
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
10635
10789
|
|
|
10636
10790
|
// src/version.ts
|
|
10637
|
-
var NATIVE_HOST_VERSION = true ? "2.7.
|
|
10791
|
+
var NATIVE_HOST_VERSION = true ? "2.7.1" : "unknown";
|
|
10638
10792
|
|
|
10639
10793
|
// src/analytics.ts
|
|
10640
10794
|
var MEASUREMENT_ID = "G-W84LJDZ6PH";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mearl/native-host",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "Native Messaging Host for Mearl — bridges Chrome Extension and local socket server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/install.js",
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"@types/ws": "^8.18.1",
|
|
38
38
|
"esbuild": "^0.25.2",
|
|
39
39
|
"typescript": "^5.8.3",
|
|
40
|
-
"@mearl/browser-core": "2.7.
|
|
41
|
-
"@mearl/daemon-core": "2.7.
|
|
42
|
-
"@mearl/setup": "2.7.
|
|
40
|
+
"@mearl/browser-core": "2.7.1",
|
|
41
|
+
"@mearl/daemon-core": "2.7.1",
|
|
42
|
+
"@mearl/setup": "2.7.1"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "rm -rf dist/ && node build.mjs",
|