agentpage 0.0.51 → 0.0.53
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.d.mts.map +1 -1
- package/dist/index.mjs +257 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/tool-registry.ts","../src/core/types.ts","../src/core/agent-loop/types.ts","../src/web/ref-store.ts","../src/web/tools/page-info-tool.ts","../src/web/ui/panel.ts","../src/web/tools/dom-tool.ts","../src/web/tools/navigate-tool.ts","../src/web/tools/wait-tool.ts","../src/web/tools/evaluate-tool.ts","../src/web/messaging.ts","../src/web/index.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/tool-registry.ts","../src/core/types.ts","../src/core/agent-loop/types.ts","../src/web/ref-store.ts","../src/web/tools/page-info-tool.ts","../src/web/ui/panel.ts","../src/web/tools/dom-tool.ts","../src/web/tools/navigate-tool.ts","../src/web/tools/wait-tool.ts","../src/web/tools/evaluate-tool.ts","../src/web/messaging.ts","../src/web/index.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -111,6 +111,75 @@ function _djb2(str) {
|
|
|
111
111
|
return (hash >>> 0).toString(36);
|
|
112
112
|
}
|
|
113
113
|
/**
|
|
114
|
+
* 从快照文本中查找指定 selector 附近的可点击元素。
|
|
115
|
+
*
|
|
116
|
+
* 当点击某个元素无效果时,框架需要推荐具体的替代目标而非泛泛的建议。
|
|
117
|
+
* 此函数在快照中定位目标 selector 所在行,然后在上下 windowSize 行内
|
|
118
|
+
* 扫描带有点击信号的元素,返回按距离排序的推荐列表。
|
|
119
|
+
*
|
|
120
|
+
* 点击信号判定:
|
|
121
|
+
* - listeners 属性含 clk / pdn / mdn
|
|
122
|
+
* - 有 onclick 属性
|
|
123
|
+
* - 标签为 [a] 或 [button]
|
|
124
|
+
* - role="button" 或 role="link"
|
|
125
|
+
*
|
|
126
|
+
* 返回:描述字符串数组(`#hashID ([tag] "text" listeners="...")`),最多 5 个。
|
|
127
|
+
*
|
|
128
|
+
* 用途:
|
|
129
|
+
* - `INEFFECTIVE_CLICK_BLOCKED` 拦截消息中附带推荐
|
|
130
|
+
* - "Snapshot unchanged" 提示中附带推荐
|
|
131
|
+
* - 交替循环检测提示中附带推荐
|
|
132
|
+
*/
|
|
133
|
+
function findNearbyClickTargets(snapshot, selector, excludeSelectors, windowSize = 15) {
|
|
134
|
+
if (!snapshot || !selector) return [];
|
|
135
|
+
const lines = snapshot.split("\n");
|
|
136
|
+
const selectorRef = selector.startsWith("#") ? selector : `#${selector}`;
|
|
137
|
+
let targetLineIdx = -1;
|
|
138
|
+
for (let i = 0; i < lines.length; i++) if (lines[i].includes(selectorRef)) {
|
|
139
|
+
targetLineIdx = i;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
if (targetLineIdx === -1) return [];
|
|
143
|
+
const start = Math.max(0, targetLineIdx - windowSize);
|
|
144
|
+
const end = Math.min(lines.length - 1, targetLineIdx + windowSize);
|
|
145
|
+
const CLICK_SIGNAL_RE = /(?:listeners="[^"]*\b(?:clk|pdn|mdn)\b[^"]*")|(?:\bonclick\b)|(?:\[a\])|(?:\[button\])|(?:role="(?:button|link)")/i;
|
|
146
|
+
const HASH_RE = /#([a-z0-9]{4,})\b/gi;
|
|
147
|
+
const TAG_RE = /\[([a-z0-9-]+)\]/i;
|
|
148
|
+
const TEXT_RE = /"([^"]{1,40})"/;
|
|
149
|
+
const candidates = [];
|
|
150
|
+
for (let i = start; i <= end; i++) {
|
|
151
|
+
if (i === targetLineIdx) continue;
|
|
152
|
+
const line = lines[i];
|
|
153
|
+
if (!CLICK_SIGNAL_RE.test(line)) continue;
|
|
154
|
+
HASH_RE.lastIndex = 0;
|
|
155
|
+
let match;
|
|
156
|
+
while ((match = HASH_RE.exec(line)) !== null) {
|
|
157
|
+
const ref = `#${match[1]}`;
|
|
158
|
+
if (ref === selectorRef) continue;
|
|
159
|
+
if (excludeSelectors?.has(ref)) continue;
|
|
160
|
+
const tag = TAG_RE.exec(line)?.[1] ?? "?";
|
|
161
|
+
const text = TEXT_RE.exec(line)?.[1] ?? "";
|
|
162
|
+
const listeners = line.match(/listeners="([^"]*)"/)?.[1] ?? "";
|
|
163
|
+
const brief = text ? `[${tag}] "${text}" listeners="${listeners}"` : `[${tag}] listeners="${listeners}"`;
|
|
164
|
+
candidates.push({
|
|
165
|
+
ref,
|
|
166
|
+
distance: Math.abs(i - targetLineIdx),
|
|
167
|
+
brief
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
candidates.sort((a, b) => a.distance - b.distance);
|
|
172
|
+
const seen = /* @__PURE__ */ new Set();
|
|
173
|
+
const result = [];
|
|
174
|
+
for (const c of candidates) {
|
|
175
|
+
if (seen.has(c.ref)) continue;
|
|
176
|
+
seen.add(c.ref);
|
|
177
|
+
result.push(`${c.ref} (${c.brief})`);
|
|
178
|
+
if (result.length >= 5) break;
|
|
179
|
+
}
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
114
183
|
* 构建任务数组。
|
|
115
184
|
*
|
|
116
185
|
* 作用:把一轮工具调用规整成稳定字符串数组,
|
|
@@ -738,6 +807,49 @@ function detectIdleLoop(toolCalls, consecutiveReadOnlyRounds) {
|
|
|
738
807
|
}
|
|
739
808
|
return 0;
|
|
740
809
|
}
|
|
810
|
+
/**
|
|
811
|
+
* 重复无效点击拦截。
|
|
812
|
+
*
|
|
813
|
+
* 场景:模型反复点击同一个 selector 但页面快照从未变化。
|
|
814
|
+
* 框架在每轮结束时通过快照指纹对比发现点击无效后,将 selector 加入
|
|
815
|
+
* `ineffectiveClickSelectors` 集合。下一轮模型再次点击相同 selector 时,
|
|
816
|
+
* 直接拦截并返回错误提示,引导模型换目标。
|
|
817
|
+
*
|
|
818
|
+
* 使用方式:
|
|
819
|
+
* - 在工具执行前调用此函数
|
|
820
|
+
* - 仅对 `dom.click` 动作生效
|
|
821
|
+
* - 返回 null 表示放行,返回 ToolCallResult 表示拦截
|
|
822
|
+
*
|
|
823
|
+
* 集合的维护由 index.ts 负责:
|
|
824
|
+
* - 轮次结束且快照未变:将本轮 click 的 selector 加入集合
|
|
825
|
+
* - 快照变化:仅移除本轮点击的 selector,保留其他无效记录
|
|
826
|
+
*
|
|
827
|
+
* 增强:当拦截时,自动从快照中查找附近可点击元素并作为具体推荐注入响应,
|
|
828
|
+
* 让模型有明确的替代目标而非盲猜。
|
|
829
|
+
*/
|
|
830
|
+
function checkIneffectiveClickRepeat(toolName, toolInput, ineffectiveClickSelectors, latestSnapshot) {
|
|
831
|
+
if (toolName !== "dom") return null;
|
|
832
|
+
if (getToolAction(toolInput) !== "click") return null;
|
|
833
|
+
const selector = toolInput && typeof toolInput === "object" ? toolInput.selector : void 0;
|
|
834
|
+
if (typeof selector !== "string" || !selector) return null;
|
|
835
|
+
if (!ineffectiveClickSelectors.has(selector)) return null;
|
|
836
|
+
const nearby = latestSnapshot ? findNearbyClickTargets(latestSnapshot, selector, ineffectiveClickSelectors) : [];
|
|
837
|
+
const lines = [`Click on ${selector} was BLOCKED — this target was already clicked in a previous round with NO visible effect on the page.`, "You MUST try a DIFFERENT element."];
|
|
838
|
+
if (nearby.length > 0) {
|
|
839
|
+
lines.push("", "Nearby clickable alternatives (try these first, sorted by proximity):");
|
|
840
|
+
for (const item of nearby) lines.push(` → ${item}`);
|
|
841
|
+
lines.push("");
|
|
842
|
+
}
|
|
843
|
+
lines.push("Other suggestions:", "1) Look INSIDE the clicked container for an <a>, <button>, or child with clk/pdn/mdn listener", "2) Try a parent or sibling element with stronger click signal", "3) Use evaluate to inspect or trigger navigation programmatically", "4) Try a completely different approach (search, sidebar, direct URL navigation)");
|
|
844
|
+
return {
|
|
845
|
+
content: lines.join("\n"),
|
|
846
|
+
details: {
|
|
847
|
+
error: true,
|
|
848
|
+
code: "INEFFECTIVE_CLICK_BLOCKED",
|
|
849
|
+
selector
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
}
|
|
741
853
|
|
|
742
854
|
//#endregion
|
|
743
855
|
//#region src/core/agent-loop/index.ts
|
|
@@ -841,6 +953,8 @@ async function executeAgentLoop(params) {
|
|
|
841
953
|
};
|
|
842
954
|
let recoveryCount = 0;
|
|
843
955
|
let redundantInterceptCount = 0;
|
|
956
|
+
const ineffectiveClickSelectors = /* @__PURE__ */ new Set();
|
|
957
|
+
const recentRoundClickTargets = [];
|
|
844
958
|
let pendingNotFoundRetry;
|
|
845
959
|
let snapshotReadCount = 0;
|
|
846
960
|
let snapshotSizeTotal = 0;
|
|
@@ -1025,6 +1139,7 @@ async function executeAgentLoop(params) {
|
|
|
1025
1139
|
let roundHasConfirmedProgress = false;
|
|
1026
1140
|
const executedTaskCalls = [];
|
|
1027
1141
|
const roundMissingTasks = [];
|
|
1142
|
+
const roundClickSelectors = [];
|
|
1028
1143
|
for (const tc of response.toolCalls) {
|
|
1029
1144
|
if (tc.name === "dom" && getToolAction(tc.input) === "scroll") {
|
|
1030
1145
|
const ref = extractHashSelectorRef(tc.input);
|
|
@@ -1037,6 +1152,15 @@ async function executeAgentLoop(params) {
|
|
|
1037
1152
|
callbacks?.onToolResult?.(tc.name, redundant);
|
|
1038
1153
|
continue;
|
|
1039
1154
|
}
|
|
1155
|
+
const ineffective = checkIneffectiveClickRepeat(tc.name, tc.input, ineffectiveClickSelectors, pageContext.latestSnapshot);
|
|
1156
|
+
if (ineffective) {
|
|
1157
|
+
appendToolTrace(round, tc.name, tc.input, ineffective);
|
|
1158
|
+
redundantInterceptCount += 1;
|
|
1159
|
+
callbacks?.onToolCall?.(tc.name, tc.input);
|
|
1160
|
+
callbacks?.onToolResult?.(tc.name, ineffective);
|
|
1161
|
+
roundHasError = true;
|
|
1162
|
+
continue;
|
|
1163
|
+
}
|
|
1040
1164
|
callbacks?.onToolCall?.(tc.name, tc.input);
|
|
1041
1165
|
let result = await registry.dispatch(tc.name, tc.input);
|
|
1042
1166
|
const debounced = applySnapshotDebounce(tc.name, tc.input, result, consecutiveSnapshotCalls);
|
|
@@ -1050,6 +1174,10 @@ async function executeAgentLoop(params) {
|
|
|
1050
1174
|
name: tc.name,
|
|
1051
1175
|
input: tc.input
|
|
1052
1176
|
});
|
|
1177
|
+
if (tc.name === "dom" && getToolAction(tc.input) === "click" && !hasToolError(result)) {
|
|
1178
|
+
const sel = tc.input && typeof tc.input === "object" ? tc.input.selector : void 0;
|
|
1179
|
+
if (typeof sel === "string" && sel) roundClickSelectors.push(sel);
|
|
1180
|
+
}
|
|
1053
1181
|
const missingTask = collectMissingTask(tc.name, tc.input, result);
|
|
1054
1182
|
if (missingTask) roundMissingTasks.push(missingTask);
|
|
1055
1183
|
if (result.details && typeof result.details === "object") roundHasError = roundHasError || Boolean(result.details.error);
|
|
@@ -1101,14 +1229,70 @@ async function executeAgentLoop(params) {
|
|
|
1101
1229
|
if (roundHasPotentialDomMutation) {
|
|
1102
1230
|
const roundEndFingerprint = computeSnapshotFingerprint(pageContext.latestSnapshot || "");
|
|
1103
1231
|
if (roundEndFingerprint === roundStartFingerprint && roundStartFingerprint !== "") {
|
|
1232
|
+
const nearbyHintLines = [];
|
|
1233
|
+
for (const sel of roundClickSelectors) {
|
|
1234
|
+
const nearby = findNearbyClickTargets(pageContext.latestSnapshot || "", sel, ineffectiveClickSelectors);
|
|
1235
|
+
if (nearby.length > 0) {
|
|
1236
|
+
nearbyHintLines.push(`Nearby clickable alternatives for ${sel}:`);
|
|
1237
|
+
for (const item of nearby) nearbyHintLines.push(` → ${item}`);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1104
1240
|
const unchangedHint = [
|
|
1105
1241
|
"Snapshot unchanged after action:",
|
|
1106
1242
|
"- The page snapshot is IDENTICAL before and after your action(s) this round.",
|
|
1107
1243
|
"- Your click/action had NO visible effect on the page. Do NOT repeat it.",
|
|
1108
|
-
|
|
1244
|
+
...nearbyHintLines.length > 0 ? [
|
|
1245
|
+
"",
|
|
1246
|
+
"Try these nearby elements instead (sorted by proximity):",
|
|
1247
|
+
...nearbyHintLines,
|
|
1248
|
+
""
|
|
1249
|
+
] : [],
|
|
1250
|
+
"- If no suggestion above fits, look INSIDE the target for <a>/<button>/child with clk listener, or try a parent/sibling with stronger signal, or use a completely different approach."
|
|
1109
1251
|
].join("\n");
|
|
1110
1252
|
protocolViolationHint = protocolViolationHint ? protocolViolationHint + "\n\n" + unchangedHint : unchangedHint;
|
|
1111
|
-
|
|
1253
|
+
for (const sel of roundClickSelectors) ineffectiveClickSelectors.add(sel);
|
|
1254
|
+
} else if (roundEndFingerprint !== roundStartFingerprint) {
|
|
1255
|
+
consecutiveNoProtocolRounds = 0;
|
|
1256
|
+
for (const sel of roundClickSelectors) ineffectiveClickSelectors.delete(sel);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
if (roundClickSelectors.length > 0) {
|
|
1260
|
+
recentRoundClickTargets.push([...roundClickSelectors]);
|
|
1261
|
+
while (recentRoundClickTargets.length > 6) recentRoundClickTargets.shift();
|
|
1262
|
+
}
|
|
1263
|
+
if (recentRoundClickTargets.length >= 4) {
|
|
1264
|
+
const recentWindow = recentRoundClickTargets.slice(-4);
|
|
1265
|
+
const allTargets = recentWindow.flat();
|
|
1266
|
+
const uniqueTargets = new Set(allTargets);
|
|
1267
|
+
if (uniqueTargets.size <= 2 && allTargets.length >= 4) {
|
|
1268
|
+
const cycleNearbyLines = [];
|
|
1269
|
+
for (const sel of uniqueTargets) {
|
|
1270
|
+
const nearby = findNearbyClickTargets(pageContext.latestSnapshot || "", sel, new Set([...ineffectiveClickSelectors, ...uniqueTargets]));
|
|
1271
|
+
if (nearby.length > 0) {
|
|
1272
|
+
cycleNearbyLines.push(`Alternatives near ${sel}:`);
|
|
1273
|
+
for (const item of nearby) cycleNearbyLines.push(` → ${item}`);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
const cycleHint = [
|
|
1277
|
+
"Click target cycling detected:",
|
|
1278
|
+
`- You have been alternating between the same ${uniqueTargets.size} target(s) for ${recentWindow.length}+ rounds: ${[...uniqueTargets].join(", ")}`,
|
|
1279
|
+
"- NONE of these clicks achieved navigation or meaningful page change.",
|
|
1280
|
+
...cycleNearbyLines.length > 0 ? [
|
|
1281
|
+
"",
|
|
1282
|
+
"Try these nearby clickable alternatives instead:",
|
|
1283
|
+
...cycleNearbyLines,
|
|
1284
|
+
""
|
|
1285
|
+
] : [],
|
|
1286
|
+
"You MUST abandon ALL these targets. If no suggestion above fits, try:",
|
|
1287
|
+
" 1) Look INSIDE the clicked container for <a>, <button>, or child with clk/pdn/mdn listener",
|
|
1288
|
+
" 2) Navigate via URL: use navigate.goto to go to the target page directly",
|
|
1289
|
+
" 3) Use evaluate to inspect the page and find the real navigation link",
|
|
1290
|
+
" 4) Use a search/filter/sidebar navigation approach instead"
|
|
1291
|
+
].join("\n");
|
|
1292
|
+
protocolViolationHint = protocolViolationHint ? protocolViolationHint + "\n\n" + cycleHint : cycleHint;
|
|
1293
|
+
for (const sel of uniqueTargets) ineffectiveClickSelectors.add(sel);
|
|
1294
|
+
recentRoundClickTargets.length = 0;
|
|
1295
|
+
}
|
|
1112
1296
|
}
|
|
1113
1297
|
if (consecutiveNoProtocolRounds >= 5) {
|
|
1114
1298
|
finalReply = response.text?.trim() || "任务已完成。";
|
|
@@ -2479,6 +2663,35 @@ const FILL_RELEVANT_EVENTS = new Set([
|
|
|
2479
2663
|
"mousedown",
|
|
2480
2664
|
"pointerdown"
|
|
2481
2665
|
]);
|
|
2666
|
+
/** 仅含焦点类事件的集合——只绑定这些事件的元素不应作为 click 目标 */
|
|
2667
|
+
const FOCUS_ONLY_EVENTS = new Set([
|
|
2668
|
+
"blur",
|
|
2669
|
+
"focus",
|
|
2670
|
+
"focusin",
|
|
2671
|
+
"focusout"
|
|
2672
|
+
]);
|
|
2673
|
+
/** 点击信号事件集合 */
|
|
2674
|
+
const CLICK_SIGNAL_EVENTS = new Set([
|
|
2675
|
+
"click",
|
|
2676
|
+
"mousedown",
|
|
2677
|
+
"pointerdown",
|
|
2678
|
+
"mouseup",
|
|
2679
|
+
"pointerup"
|
|
2680
|
+
]);
|
|
2681
|
+
/** 原生可被点击的 ARIA role */
|
|
2682
|
+
const CLICKABLE_ROLES = new Set([
|
|
2683
|
+
"button",
|
|
2684
|
+
"link",
|
|
2685
|
+
"tab",
|
|
2686
|
+
"menuitem",
|
|
2687
|
+
"menuitemcheckbox",
|
|
2688
|
+
"menuitemradio",
|
|
2689
|
+
"option",
|
|
2690
|
+
"checkbox",
|
|
2691
|
+
"radio",
|
|
2692
|
+
"switch",
|
|
2693
|
+
"treeitem"
|
|
2694
|
+
]);
|
|
2482
2695
|
let activeRefStore;
|
|
2483
2696
|
function setActiveRefStore(store) {
|
|
2484
2697
|
activeRefStore = store;
|
|
@@ -3050,6 +3263,44 @@ function executePress(el, key) {
|
|
|
3050
3263
|
...modState
|
|
3051
3264
|
}));
|
|
3052
3265
|
}
|
|
3266
|
+
/**
|
|
3267
|
+
* 点击信号校验:检查目标元素是否具备可点击信号。
|
|
3268
|
+
*
|
|
3269
|
+
* 判定逻辑(仅在有正向证据时拦截):
|
|
3270
|
+
* - 原生可点击元素(a/button/summary/input[submit|button|reset])→ 放行
|
|
3271
|
+
* - 有 CLICKABLE_ROLES 中的 ARIA role → 放行
|
|
3272
|
+
* - 有 onclick 属性 → 放行
|
|
3273
|
+
* - 有 click/mousedown/pointerdown 等事件监听 → 放行
|
|
3274
|
+
* - 无任何事件监听 → 放行(可能有事件委托)
|
|
3275
|
+
* - 有事件监听但全部为 focus/blur 类 → 拦截
|
|
3276
|
+
*/
|
|
3277
|
+
function validateClickSignal(el, selector, action) {
|
|
3278
|
+
if (el instanceof HTMLAnchorElement || el instanceof HTMLButtonElement || el instanceof HTMLSummaryElement || el instanceof HTMLOptionElement || el instanceof HTMLInputElement && [
|
|
3279
|
+
"submit",
|
|
3280
|
+
"button",
|
|
3281
|
+
"reset"
|
|
3282
|
+
].includes(el.type)) return null;
|
|
3283
|
+
const role = el.getAttribute("role");
|
|
3284
|
+
if (role && CLICKABLE_ROLES.has(role)) return null;
|
|
3285
|
+
if (el.hasAttribute("onclick")) return null;
|
|
3286
|
+
const trackedEvents = getTrackedElementEvents(el);
|
|
3287
|
+
if (trackedEvents.length === 0) return null;
|
|
3288
|
+
if (trackedEvents.some((e) => CLICK_SIGNAL_EVENTS.has(e))) return null;
|
|
3289
|
+
if (trackedEvents.every((e) => FOCUS_ONLY_EVENTS.has(e))) return {
|
|
3290
|
+
content: [
|
|
3291
|
+
`Element ${describeElement(el)} has NO click handler (listeners: ${trackedEvents.join(",")}).`,
|
|
3292
|
+
`This element only has focus/blur listeners — it is NOT a valid click target.`,
|
|
3293
|
+
`Look for a nearby <a>, <button>, or sibling/parent with clk/pdn/mdn listener instead.`
|
|
3294
|
+
].join(" "),
|
|
3295
|
+
details: {
|
|
3296
|
+
error: true,
|
|
3297
|
+
code: "NO_CLICK_SIGNAL",
|
|
3298
|
+
action,
|
|
3299
|
+
selector
|
|
3300
|
+
}
|
|
3301
|
+
};
|
|
3302
|
+
return null;
|
|
3303
|
+
}
|
|
3053
3304
|
function describeElement(el) {
|
|
3054
3305
|
const tag = el.tagName.toLowerCase();
|
|
3055
3306
|
const id = el.id ? `#${el.id}` : "";
|
|
@@ -3242,6 +3493,10 @@ function createDomTool() {
|
|
|
3242
3493
|
case "click": {
|
|
3243
3494
|
const target = resolvePointerActionTarget(resolveFormItemControlTarget(retarget(el, force ? "none" : "button-link")));
|
|
3244
3495
|
const clickCount = typeof params.clickCount === "number" ? params.clickCount : 1;
|
|
3496
|
+
if (!force) {
|
|
3497
|
+
const noSignal = validateClickSignal(target, selector, action);
|
|
3498
|
+
if (noSignal) return noSignal;
|
|
3499
|
+
}
|
|
3245
3500
|
if (target instanceof HTMLOptionElement) {
|
|
3246
3501
|
const parent = target.parentElement;
|
|
3247
3502
|
if (parent instanceof HTMLSelectElement) {
|