@validate.qa/runner 1.0.100 → 1.0.102
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/README.md +3 -0
- package/dist/{chunk-MBKGTELT.mjs → chunk-3JM6XTSZ.mjs} +1862 -530
- package/dist/{chunk-2XD63NU5.mjs → chunk-4WLP3RWN.mjs} +941 -86
- package/dist/{chunk-MHFP3QXU.mjs → chunk-5DFBEL72.mjs} +1 -1
- package/dist/{chunk-II7QW7MZ.mjs → chunk-BXLEPT4M.mjs} +31 -18
- package/dist/{chunk-MAO6ADAO.mjs → chunk-CBVHPYVJ.mjs} +62 -2
- package/dist/{chunk-5P4ANVDY.mjs → chunk-DN3O6EYT.mjs} +43073 -23357
- package/dist/{chunk-GIIIVO2W.mjs → chunk-E2RRAE27.mjs} +155 -11
- package/dist/chunk-E2VEMBQQ.mjs +291 -0
- package/dist/{chunk-HMUC3DKS.mjs → chunk-HJ6FKHMM.mjs} +2281 -2
- package/dist/{chunk-WDXLAZ2J.mjs → chunk-PWFWMVZU.mjs} +3 -2
- package/dist/{chunk-6NIT2CCH.mjs → chunk-ZZYBRIBT.mjs} +18 -12
- package/dist/cli.js +139723 -114754
- package/dist/cli.mjs +536 -247
- package/dist/credential-mcp-server.js +1761 -358
- package/dist/credential-mcp-server.mjs +3 -3
- package/dist/discovery-mcp-server.js +1874 -379
- package/dist/discovery-mcp-server.mjs +4 -4
- package/dist/dist-52M5RDZ6.mjs +17 -0
- package/dist/inbox-mcp-server.js +1902 -505
- package/dist/inbox-mcp-server.mjs +3 -3
- package/dist/route-seed-worker.js +3976 -356
- package/dist/route-seed-worker.mjs +14 -7
- package/dist/run-write-guard-preload.js +2908 -572
- package/dist/run-write-guard-preload.mjs +5 -285
- package/dist/run-write-guard.js +2908 -572
- package/dist/run-write-guard.mjs +3 -3
- package/dist/spec-driver.js +1 -1
- package/dist/spec-driver.mjs +1 -1
- package/package.json +4 -3
- package/dist/dist-DFNLMH6L.mjs +0 -16
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
require_route_manifest
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PWFWMVZU.mjs";
|
|
4
4
|
import {
|
|
5
5
|
require_survey_network_guard
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-E2RRAE27.mjs";
|
|
7
7
|
import {
|
|
8
8
|
dist_exports,
|
|
9
9
|
init_dist
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-3JM6XTSZ.mjs";
|
|
11
11
|
import {
|
|
12
12
|
__commonJS,
|
|
13
13
|
__toCommonJS
|
|
@@ -20,6 +20,7 @@ var require_exploration_parser = __commonJS({
|
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
exports.extractCodeLines = extractCodeLines;
|
|
22
22
|
exports.extractProvenLocator = extractProvenLocator;
|
|
23
|
+
exports.maskTypedValues = maskTypedValues;
|
|
23
24
|
exports.sanitizePromptCodeLine = sanitizePromptCodeLine;
|
|
24
25
|
exports.extractPageUrl = extractPageUrl;
|
|
25
26
|
exports.extractPageTitle = extractPageTitle;
|
|
@@ -31,9 +32,10 @@ var require_exploration_parser = __commonJS({
|
|
|
31
32
|
exports.normalizeRouteForFocusScope = normalizeRouteForFocusScope;
|
|
32
33
|
exports.routeIsWithinFocusAreas = routeIsWithinFocusAreas;
|
|
33
34
|
exports.detectRouteFromResponse = detectRouteFromResponse;
|
|
35
|
+
var shared_1 = (init_dist(), __toCommonJS(dist_exports));
|
|
34
36
|
function extractCodeLines(toolResultContent) {
|
|
35
37
|
const isPlaywrightLine = (l) => l.startsWith("await page.") || l.startsWith("await expect(");
|
|
36
|
-
const codeSection = toolResultContent.match(/###\s*Ran Playwright code\s*\n([\s\S]*?)(?=\n###|\n$|$)/);
|
|
38
|
+
const codeSection = toolResultContent.match(/###\s*Ran Playwright code\s*\n(?![^\S\n]*\n)([\s\S]*?)(?=\n###|\n$|$)/);
|
|
37
39
|
if (codeSection) {
|
|
38
40
|
return codeSection[1].split("\n").map((l) => l.trim()).filter(isPlaywrightLine).map((l) => l.replace(/;$/, ""));
|
|
39
41
|
}
|
|
@@ -77,7 +79,7 @@ var require_exploration_parser = __commonJS({
|
|
|
77
79
|
cut = idx;
|
|
78
80
|
}
|
|
79
81
|
let locator = cut > start ? codeLine.slice(start, cut) : codeLine.slice(start);
|
|
80
|
-
locator = locator.trim().replace(
|
|
82
|
+
locator = locator.trim().replace(/(?<!;);+\s*$/, "").trim();
|
|
81
83
|
if (!locator.includes("("))
|
|
82
84
|
return null;
|
|
83
85
|
if (!/^(getBy\w+|locator)\(/.test(locator))
|
|
@@ -157,13 +159,16 @@ var require_exploration_parser = __commonJS({
|
|
|
157
159
|
return false;
|
|
158
160
|
return RECORD_TITLE_WITH_COMPANY.test(name);
|
|
159
161
|
}
|
|
162
|
+
var TYPED_VALUE_CALL_RE = /\.(fill|type|pressSequentially|insertText)\(\s*(['"])(?:\\.|(?!\2)[^\\])*\2(\s*,\s*\{[^{}]*\})?\s*\)/g;
|
|
163
|
+
function maskTypedValues(codeLine, mask) {
|
|
164
|
+
return codeLine.replace(TYPED_VALUE_CALL_RE, (_all, method, _quote, options) => `.${method}(${mask}${options ?? ""})`);
|
|
165
|
+
}
|
|
160
166
|
function sanitizePromptCodeLine(codeLine) {
|
|
161
167
|
let sanitized = codeLine;
|
|
162
168
|
sanitized = sanitized.replace(/getByRole\('(textbox|searchbox|combobox|spinbutton)',\s*\{\s*name:\s*['"]([^'"]*)['"]\s*\}\)/g, (match, role, name, _offset, line) => looksDynamicFieldLabel(name, line) ? `getByRole('${role}')` : match);
|
|
163
169
|
sanitized = sanitized.replace(/getByLabel\(\s*(['"])([^'"]*)\1\s*\)(?=\)?\.(?:fill|type|toHaveValue|inputValue|press)\()/g, (match, _quote, label, _offset, line) => looksDynamicFieldLabel(label, line) ? "getByRole('textbox')" : match);
|
|
164
170
|
sanitized = sanitized.replace(/getByLabel\(\s*(['"])([^'"]*)\1\s*\)(?=\)?\.selectOption\()/g, (match, _quote, label, _offset, line) => looksDynamicFieldLabel(label, line) ? "getByRole('combobox')" : match);
|
|
165
|
-
sanitized = sanitized
|
|
166
|
-
sanitized = sanitized.replace(/\.type\(\s*(['"]).*?\1\s*\)/g, ".type('<test-value>')");
|
|
171
|
+
sanitized = maskTypedValues(sanitized, "'<test-value>'");
|
|
167
172
|
sanitized = sanitized.replace(/\.toHaveValue\(\s*(['"]).*?\1\s*\)/g, ".toHaveValue(/./)");
|
|
168
173
|
sanitized = sanitized.replace(/getByRole\('heading',\s*\{\s*name:\s*'([^']*)'\s*\}\)/g, (match, name) => looksDynamicRecordTitle(name) ? "getByRole('heading')" : match);
|
|
169
174
|
sanitized = sanitized.replace(/getByRole\('heading',\s*\{\s*name:\s*"([^"]*)"\s*\}\)/g, (match, name) => looksDynamicRecordTitle(name) ? "getByRole('heading')" : match);
|
|
@@ -187,7 +192,7 @@ var require_exploration_parser = __commonJS({
|
|
|
187
192
|
return match ? match[1].trim() : null;
|
|
188
193
|
}
|
|
189
194
|
function extractSnapshotSection(content) {
|
|
190
|
-
const match = content.match(/###\s*Snapshot\s*\n([\s\S]*?)(?=\n###|$)/);
|
|
195
|
+
const match = content.match(/###\s*Snapshot\s*\n(?![^\S\n]*\n)([\s\S]*?)(?=\n###|$)/);
|
|
191
196
|
if (!match)
|
|
192
197
|
return null;
|
|
193
198
|
if (/^\s*- \[Snapshot\]\([^)\n]*\)\s*$/.test(match[1]))
|
|
@@ -255,7 +260,7 @@ var require_exploration_parser = __commonJS({
|
|
|
255
260
|
return hints;
|
|
256
261
|
}
|
|
257
262
|
function extractFirstAlert(snapshotYaml) {
|
|
258
|
-
const match = snapshotYaml.match(
|
|
263
|
+
const match = snapshotYaml.match(/^[^\S\n\r\u2028\u2029]*-\s+(?:alert|status)\s+"([^"]+)"/m);
|
|
259
264
|
return match ? match[1] : null;
|
|
260
265
|
}
|
|
261
266
|
function buildInteractionLogEntry(toolName, toolArgs, codeLines, pageUrl, pageTitle, snapshotSection) {
|
|
@@ -296,6 +301,12 @@ var require_exploration_parser = __commonJS({
|
|
|
296
301
|
return /^\d{10,}$/.test(value);
|
|
297
302
|
return false;
|
|
298
303
|
}
|
|
304
|
+
function hashRouterPathWithoutTrailingSlash(hash) {
|
|
305
|
+
const q = hash.indexOf("?");
|
|
306
|
+
const path = q < 0 ? hash : hash.slice(0, q);
|
|
307
|
+
const stripped = (0, shared_1.stripTrailingSlashes)(path);
|
|
308
|
+
return stripped === "#" || stripped === "" ? hash : stripped + (q < 0 ? "" : hash.slice(q));
|
|
309
|
+
}
|
|
299
310
|
function normalizeRoute(url) {
|
|
300
311
|
let route = url.pathname;
|
|
301
312
|
const encodeQueryPart = (part) => part.replace(/[%&=#+?]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`);
|
|
@@ -314,7 +325,7 @@ var require_exploration_parser = __commonJS({
|
|
|
314
325
|
}
|
|
315
326
|
}
|
|
316
327
|
if (url.hash && url.hash !== "#" && url.hash !== "#/") {
|
|
317
|
-
route += url.hash;
|
|
328
|
+
route += url.hash.startsWith("#/") ? hashRouterPathWithoutTrailingSlash(url.hash) : url.hash;
|
|
318
329
|
}
|
|
319
330
|
return route;
|
|
320
331
|
}
|
|
@@ -324,7 +335,7 @@ var require_exploration_parser = __commonJS({
|
|
|
324
335
|
const decoded = raw.replace(/&/g, "&").replace(/&#(\d+);/g, (_m, code) => String.fromCharCode(Number(code)));
|
|
325
336
|
try {
|
|
326
337
|
const url = new URL(decoded, "http://canonical.invalid");
|
|
327
|
-
url.pathname = url.pathname
|
|
338
|
+
url.pathname = (0, shared_1.stripTrailingSlashes)(url.pathname) || "/";
|
|
328
339
|
return normalizeRoute(url);
|
|
329
340
|
} catch {
|
|
330
341
|
return decoded;
|
|
@@ -356,9 +367,9 @@ var require_exploration_parser = __commonJS({
|
|
|
356
367
|
const text = String(route ?? "").trim();
|
|
357
368
|
const at = text.indexOf("#/");
|
|
358
369
|
if (at < 0)
|
|
359
|
-
return text.startsWith("#") ? text.split("?")[0].toLowerCase()
|
|
370
|
+
return text.startsWith("#") ? (0, shared_1.stripTrailingSlashes)(text.split("?")[0].toLowerCase()) : null;
|
|
360
371
|
const hashPath = text.slice(at).split("?")[0].toLowerCase();
|
|
361
|
-
return hashPath.length > 2 ?
|
|
372
|
+
return hashPath.length > 2 ? (0, shared_1.stripTrailingSlashes)(hashPath) || "#/" : hashPath;
|
|
362
373
|
}
|
|
363
374
|
function routeIsWithinFocusAreas(route, focusAreas, otherRoutes) {
|
|
364
375
|
if (!focusAreas || focusAreas.length === 0)
|
|
@@ -839,6 +850,7 @@ var require_survey_repo_route_frontier = __commonJS({
|
|
|
839
850
|
exports.buildRepoRouteCandidates = buildRepoRouteCandidates;
|
|
840
851
|
exports.routeIdsHiddenFromChecklist = routeIdsHiddenFromChecklist;
|
|
841
852
|
exports.parseRepoRouteCoverage = parseRepoRouteCoverage;
|
|
853
|
+
var shared_1 = (init_dist(), __toCommonJS(dist_exports));
|
|
842
854
|
var route_manifest_js_1 = require_route_manifest();
|
|
843
855
|
var survey_scope_js_1 = require_survey_scope();
|
|
844
856
|
var repo_route_safety_js_1 = require_repo_route_safety();
|
|
@@ -900,7 +912,7 @@ var require_survey_repo_route_frontier = __commonJS({
|
|
|
900
912
|
return route;
|
|
901
913
|
try {
|
|
902
914
|
const base = new URL(baseUrl);
|
|
903
|
-
return `${base.pathname
|
|
915
|
+
return `${(0, shared_1.stripTrailingSlashes)(base.pathname) || "/"}${route}`;
|
|
904
916
|
} catch {
|
|
905
917
|
return `/${route}`;
|
|
906
918
|
}
|
|
@@ -1131,7 +1143,7 @@ var require_survey_repo_route_frontier = __commonJS({
|
|
|
1131
1143
|
try {
|
|
1132
1144
|
const base = new URL(input.baseUrl);
|
|
1133
1145
|
origin = base.origin;
|
|
1134
|
-
basePathname = base.pathname
|
|
1146
|
+
basePathname = (0, shared_1.stripTrailingSlashes)(base.pathname) || "/";
|
|
1135
1147
|
} catch {
|
|
1136
1148
|
origin = null;
|
|
1137
1149
|
}
|
|
@@ -1164,7 +1176,7 @@ var require_survey_repo_route_frontier = __commonJS({
|
|
|
1164
1176
|
return null;
|
|
1165
1177
|
if (parsed.origin !== this.appOrigin)
|
|
1166
1178
|
return null;
|
|
1167
|
-
const pathname = parsed.pathname
|
|
1179
|
+
const pathname = (0, shared_1.stripTrailingSlashes)(parsed.pathname) || "/";
|
|
1168
1180
|
const key = manifestRouteKey(`${parsed.pathname}${parsed.search}${parsed.hash}`);
|
|
1169
1181
|
if (!key)
|
|
1170
1182
|
return null;
|
|
@@ -1629,6 +1641,7 @@ var require_repo_feature_verification = __commonJS({
|
|
|
1629
1641
|
exports.parseBrowserVerificationRequirement = parseBrowserVerificationRequirement;
|
|
1630
1642
|
exports.parseBrowserVerificationResult = parseBrowserVerificationResult;
|
|
1631
1643
|
exports.renderBrowserVerificationForPrompt = renderBrowserVerificationForPrompt;
|
|
1644
|
+
var shared_1 = (init_dist(), __toCommonJS(dist_exports));
|
|
1632
1645
|
var survey_repo_route_frontier_js_1 = require_survey_repo_route_frontier();
|
|
1633
1646
|
var ABSOLUTE_URL = /^[a-z][a-z0-9+.-]*:\/\//i;
|
|
1634
1647
|
function originOf(url) {
|
|
@@ -1685,7 +1698,7 @@ var require_repo_feature_verification = __commonJS({
|
|
|
1685
1698
|
before = before.split("?")[0];
|
|
1686
1699
|
if (!before.startsWith("/"))
|
|
1687
1700
|
return null;
|
|
1688
|
-
return
|
|
1701
|
+
return (0, shared_1.stripTrailingSlashes)(before);
|
|
1689
1702
|
}
|
|
1690
1703
|
function sameHashMount(route, entry) {
|
|
1691
1704
|
const entryMount = hashMount(entry);
|
|
@@ -1741,7 +1754,7 @@ var require_repo_feature_verification = __commonJS({
|
|
|
1741
1754
|
function compileEntryPattern(pattern) {
|
|
1742
1755
|
const trimmed = String(pattern ?? "").trim();
|
|
1743
1756
|
const hashAt = trimmed.indexOf("#/");
|
|
1744
|
-
const raw = (hashAt >= 0 || trimmed.startsWith("#") ? trimmed.slice(Math.max(hashAt, 0)).split("?")[0] : trimmed.split(/[?#]/)[0])
|
|
1757
|
+
const raw = (0, shared_1.stripTrailingSlashes)(hashAt >= 0 || trimmed.startsWith("#") ? trimmed.slice(Math.max(hashAt, 0)).split("?")[0] : trimmed.split(/[?#]/)[0]);
|
|
1745
1758
|
if (!isEntrySpelling(raw) || raw.length > 500)
|
|
1746
1759
|
return null;
|
|
1747
1760
|
let out = "";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
dist_exports,
|
|
3
3
|
init_dist
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3JM6XTSZ.mjs";
|
|
5
5
|
import {
|
|
6
6
|
__commonJS,
|
|
7
7
|
__esm,
|
|
@@ -67455,23 +67455,41 @@ var require_harness_init_script = __commonJS({
|
|
|
67455
67455
|
exports.isHarnessInitConsoleLine = isHarnessInitConsoleLine;
|
|
67456
67456
|
exports.stripHarnessConsoleEntries = stripHarnessConsoleEntries;
|
|
67457
67457
|
var node_crypto_1 = __require("crypto");
|
|
67458
|
+
var shared_1 = (init_dist(), __toCommonJS(dist_exports));
|
|
67458
67459
|
exports.HARNESS_INIT_SOURCE_URL = `vqa-harness-init-${(0, node_crypto_1.randomBytes)(4).toString("hex")}.js`;
|
|
67460
|
+
var TRANSITION_LOOP_LIMIT = 8;
|
|
67461
|
+
var TRANSITION_LOOP_WINDOW_MS = 1e3;
|
|
67459
67462
|
function withHarnessSourceUrl(content) {
|
|
67460
67463
|
return `${content}
|
|
67461
67464
|
//# sourceURL=${exports.HARNESS_INIT_SOURCE_URL}`;
|
|
67462
67465
|
}
|
|
67463
67466
|
function buildAnimationDisablingSource(opts) {
|
|
67467
|
+
const finishTransitions = opts.finishTransitions ?? (0, shared_1.parseBoolFlag)(process.env.HARNESS_FINISH_CSS_TRANSITIONS);
|
|
67468
|
+
const css = finishTransitions ? "*, *::before, *::after { animation-duration: 0s !important; animation-delay: 0s !important; }" : "*, *::before, *::after { transition-duration: 0s !important; animation-duration: 0s !important; transition-delay: 0s !important; animation-delay: 0s !important; }";
|
|
67464
67469
|
return withHarnessSourceUrl(`(() => {
|
|
67465
67470
|
// Layer 1: CSS transitions and animations - instant, not removed
|
|
67466
67471
|
// (duration 0s preserves final state; 'none' would prevent keyframes from completing)
|
|
67472
|
+
// The rule goes in a constructed stylesheet on document.adoptedStyleSheets, which adds no node to the DOM:
|
|
67473
|
+
// a <style> element changed what the test sees (locator('style') and 'head > *' counts, document.styleSheets,
|
|
67474
|
+
// an iframe's empty head), so a spec stock Playwright passes failed. The <style> is the fallback for a
|
|
67475
|
+
// browser with no constructable stylesheets.
|
|
67476
|
+
let adopted = false;
|
|
67467
67477
|
try {
|
|
67478
|
+
if (typeof CSSStyleSheet === 'function' && typeof Document === 'function' && 'adoptedStyleSheets' in Document.prototype) {
|
|
67479
|
+
const sheet = new CSSStyleSheet();
|
|
67480
|
+
sheet.replaceSync(${JSON.stringify(css)});
|
|
67481
|
+
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
|
|
67482
|
+
adopted = true;
|
|
67483
|
+
}
|
|
67484
|
+
} catch (e) {}
|
|
67485
|
+
if (!adopted) try {
|
|
67468
67486
|
let applied = false;
|
|
67469
67487
|
const apply = () => {
|
|
67470
67488
|
if (applied) return true;
|
|
67471
67489
|
const root = document.head || document.documentElement;
|
|
67472
67490
|
if (!root) return false;
|
|
67473
67491
|
const style = document.createElement('style');
|
|
67474
|
-
style.textContent =
|
|
67492
|
+
style.textContent = ${JSON.stringify(css)};
|
|
67475
67493
|
root.appendChild(style);
|
|
67476
67494
|
applied = true;
|
|
67477
67495
|
return true;
|
|
@@ -67493,6 +67511,48 @@ ${opts.hideWebdriver ? `
|
|
|
67493
67511
|
try {
|
|
67494
67512
|
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
|
|
67495
67513
|
} catch (e) {}
|
|
67514
|
+
` : ""}
|
|
67515
|
+
${finishTransitions ? `
|
|
67516
|
+
// Layer 1b: CSS transitions run, and are finished as they start, so transitionend fires.
|
|
67517
|
+
// - finish() is deferred to a task: called inside the transitionrun dispatch (or a microtask of it) after a
|
|
67518
|
+
// real input event, Chromium finishes the transition but never fires its transitionstart/transitionend.
|
|
67519
|
+
// - setTimeout and performance.now are the ones present when this script runs, before the page's own
|
|
67520
|
+
// scripts: fake timers the page installs later cannot hold a finish back.
|
|
67521
|
+
// - The subtree is walked only for a pseudo-element's transition (its animations hang off the element).
|
|
67522
|
+
// - An element whose same transition restarts more than ${TRANSITION_LOOP_LIMIT} times within ${TRANSITION_LOOP_WINDOW_MS} ms (an app that starts it again on
|
|
67523
|
+
// each transitionend: carousel, pulse) is left to run at its own pace from then on, instead of cycling at
|
|
67524
|
+
// frame rate for the rest of the run.
|
|
67525
|
+
try {
|
|
67526
|
+
const st = setTimeout;
|
|
67527
|
+
const perf = typeof performance === 'object' && performance && typeof performance.now === 'function' ? performance : null;
|
|
67528
|
+
const now = perf ? perf.now.bind(perf) : Date.now;
|
|
67529
|
+
const seen = new WeakMap();
|
|
67530
|
+
const looping = (el, key) => {
|
|
67531
|
+
let byKey = seen.get(el);
|
|
67532
|
+
if (!byKey) { byKey = new Map(); seen.set(el, byKey); }
|
|
67533
|
+
const t = now();
|
|
67534
|
+
let s = byKey.get(key);
|
|
67535
|
+
if (s && s.loop) return true;
|
|
67536
|
+
if (!s || t - s.since > ${TRANSITION_LOOP_WINDOW_MS}) { s = { n: 0, since: t, loop: false }; byKey.set(key, s); }
|
|
67537
|
+
s.n += 1;
|
|
67538
|
+
if (s.n > ${TRANSITION_LOOP_LIMIT}) s.loop = true;
|
|
67539
|
+
return s.loop;
|
|
67540
|
+
};
|
|
67541
|
+
window.addEventListener('transitionrun', (ev) => {
|
|
67542
|
+
try {
|
|
67543
|
+
const el = ev && ev.target;
|
|
67544
|
+
if (!el || typeof el.getAnimations !== 'function' || typeof CSSTransition !== 'function') return;
|
|
67545
|
+
const pseudo = ev.pseudoElement || '';
|
|
67546
|
+
if (looping(el, ev.propertyName + '|' + pseudo)) return;
|
|
67547
|
+
for (const a of (pseudo ? el.getAnimations({ subtree: true }) : el.getAnimations())) {
|
|
67548
|
+
if (a instanceof CSSTransition && a.transitionProperty === ev.propertyName && a.effect
|
|
67549
|
+
&& a.effect.target === el && (a.effect.pseudoElement || '') === pseudo) {
|
|
67550
|
+
st(() => { try { a.finish(); } catch (e) {} }, 0);
|
|
67551
|
+
}
|
|
67552
|
+
}
|
|
67553
|
+
} catch (e) {}
|
|
67554
|
+
}, true);
|
|
67555
|
+
} catch (e) {}
|
|
67496
67556
|
` : ""}
|
|
67497
67557
|
// Layer 2: Web Animations API - make instant instead of no-op
|
|
67498
67558
|
// (preserves animation completion callbacks that app code may depend on)
|