@oh-my-pi/pi-coding-agent 16.1.8 → 16.1.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/CHANGELOG.md +40 -0
- package/dist/cli.js +4775 -3942
- package/dist/types/cli/flag-tables.d.ts +17 -0
- package/dist/types/cli-commands.d.ts +4 -2
- package/dist/types/config/settings-schema.d.ts +10 -0
- package/dist/types/edit/streaming.d.ts +5 -5
- package/dist/types/modes/controllers/command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +0 -1
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/types.d.ts +1 -1
- package/dist/types/sdk.d.ts +1 -0
- package/dist/types/session/agent-session.d.ts +13 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/tools/browser/aria/aria-snapshot.d.ts +39 -0
- package/dist/types/tools/browser/cmux/cmux-tab.d.ts +3 -0
- package/dist/types/tools/browser/launch.d.ts +5 -0
- package/dist/types/tools/browser.d.ts +1 -0
- package/dist/types/tools/find.d.ts +1 -2
- package/dist/types/tools/write.d.ts +1 -2
- package/package.json +12 -12
- package/scripts/generate-aria-snapshot.ts +134 -0
- package/src/cli/args.ts +0 -1
- package/src/cli/flag-tables.ts +42 -0
- package/src/cli/profile-bootstrap.ts +1 -11
- package/src/cli-commands.ts +48 -3
- package/src/config/model-registry.ts +6 -7
- package/src/config/settings-schema.ts +12 -0
- package/src/edit/streaming.ts +5 -5
- package/src/internal-urls/docs-index.generated.txt +1 -1
- package/src/lsp/client.ts +39 -25
- package/src/modes/controllers/command-controller.ts +18 -3
- package/src/modes/controllers/event-controller.ts +20 -0
- package/src/modes/controllers/mcp-command-controller.ts +40 -12
- package/src/modes/controllers/selector-controller.ts +3 -5
- package/src/modes/interactive-mode.ts +1 -1
- package/src/modes/types.ts +1 -1
- package/src/prompts/system/project-prompt.md +2 -0
- package/src/prompts/system/system-prompt.md +0 -1
- package/src/prompts/tools/browser.md +2 -0
- package/src/sdk.ts +8 -1
- package/src/session/agent-session.ts +36 -1
- package/src/slash-commands/builtin-registry.ts +24 -66
- package/src/system-prompt.ts +15 -3
- package/src/tools/bash.ts +3 -3
- package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
- package/src/tools/browser/aria/aria-snapshot.ts +103 -0
- package/src/tools/browser/cmux/cmux-tab.ts +36 -1
- package/src/tools/browser/launch.ts +107 -31
- package/src/tools/browser/tab-worker.ts +89 -17
- package/src/tools/browser.ts +5 -0
- package/src/tools/find.ts +1 -2
- package/src/tools/index.ts +1 -1
- package/src/tools/puppeteer/00_stealth_tampering.txt +16 -35
- package/src/tools/puppeteer/01_stealth_activity.txt +79 -19
- package/src/tools/puppeteer/02_stealth_hairline.txt +57 -11
- package/src/tools/puppeteer/03_stealth_botd.txt +10 -14
- package/src/tools/puppeteer/04_stealth_iframe.txt +156 -63
- package/src/tools/puppeteer/05_stealth_webgl.txt +222 -64
- package/src/tools/puppeteer/06_stealth_screen.txt +255 -67
- package/src/tools/puppeteer/07_stealth_fonts.txt +17 -15
- package/src/tools/puppeteer/08_stealth_audio.txt +32 -20
- package/src/tools/puppeteer/09_stealth_locale.txt +45 -40
- package/src/tools/puppeteer/10_stealth_plugins.txt +12 -8
- package/src/tools/puppeteer/11_stealth_hardware.txt +57 -6
- package/src/tools/puppeteer/12_stealth_codecs.txt +20 -18
- package/src/tools/puppeteer/13_stealth_worker.txt +206 -45
- package/src/tools/write.ts +1 -2
- package/src/utils/git.ts +3 -2
|
@@ -22,6 +22,12 @@ import { resizeImage } from "../../utils/image-resize";
|
|
|
22
22
|
import { resolveToCwd } from "../path-utils";
|
|
23
23
|
import { formatScreenshot } from "../render-utils";
|
|
24
24
|
import { ToolAbortError, ToolError, throwIfAborted } from "../tool-errors";
|
|
25
|
+
import {
|
|
26
|
+
type AriaSnapshotOptions,
|
|
27
|
+
captureAriaSnapshot,
|
|
28
|
+
parseAriaRefSelector,
|
|
29
|
+
resolveAriaRefHandle,
|
|
30
|
+
} from "./aria/aria-snapshot";
|
|
25
31
|
import {
|
|
26
32
|
applyStealthPatches,
|
|
27
33
|
applyViewport,
|
|
@@ -106,6 +112,7 @@ interface TabApi {
|
|
|
106
112
|
opts?: { waitUntil?: "load" | "domcontentloaded" | "networkidle0" | "networkidle2" },
|
|
107
113
|
): Promise<void>;
|
|
108
114
|
observe(opts?: { includeAll?: boolean; viewportOnly?: boolean }): Promise<Observation>;
|
|
115
|
+
ariaSnapshot(selector?: string, opts?: AriaSnapshotOptions): Promise<string>;
|
|
109
116
|
screenshot(opts?: ScreenshotOptions): Promise<ScreenshotResult>;
|
|
110
117
|
extract(format?: ReadableFormat): Promise<string>;
|
|
111
118
|
click(selector: string): Promise<void>;
|
|
@@ -128,6 +135,7 @@ interface TabApi {
|
|
|
128
135
|
opts?: { timeout?: number },
|
|
129
136
|
): Promise<HTTPResponse>;
|
|
130
137
|
id(n: number): Promise<ElementHandle>;
|
|
138
|
+
ref(id: string): Promise<ElementHandle>;
|
|
131
139
|
}
|
|
132
140
|
|
|
133
141
|
function normalizeSelector(selector: string): string {
|
|
@@ -792,6 +800,28 @@ export class WorkerCore {
|
|
|
792
800
|
);
|
|
793
801
|
}),
|
|
794
802
|
observe: opts => op("tab.observe()", quickOpMs, sig => this.#collectObservation({ ...opts, signal: sig })),
|
|
803
|
+
ariaSnapshot: (selector, opts) =>
|
|
804
|
+
op(
|
|
805
|
+
selector ? `tab.ariaSnapshot(${JSON.stringify(selector)})` : "tab.ariaSnapshot()",
|
|
806
|
+
quickOpMs,
|
|
807
|
+
async sig => {
|
|
808
|
+
let root: ElementHandle | null = null;
|
|
809
|
+
if (selector) {
|
|
810
|
+
root = (await untilAborted(sig, () =>
|
|
811
|
+
page.$(normalizeSelector(selector)),
|
|
812
|
+
)) as ElementHandle | null;
|
|
813
|
+
if (!root)
|
|
814
|
+
throw new ToolError(
|
|
815
|
+
`tab.ariaSnapshot: selector ${JSON.stringify(selector)} matched no element`,
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
try {
|
|
819
|
+
return await untilAborted(sig, () => captureAriaSnapshot(page, root, opts));
|
|
820
|
+
} finally {
|
|
821
|
+
await root?.dispose().catch(() => undefined);
|
|
822
|
+
}
|
|
823
|
+
},
|
|
824
|
+
),
|
|
795
825
|
screenshot: opts =>
|
|
796
826
|
op(describeScreenshot(opts), quickOpMs, sig =>
|
|
797
827
|
this.#captureScreenshot(session, displays, screenshots, sig, opts),
|
|
@@ -815,25 +845,50 @@ export class WorkerCore {
|
|
|
815
845
|
}),
|
|
816
846
|
click: selector =>
|
|
817
847
|
op(`tab.click(${JSON.stringify(selector)})`, INF, async sig => {
|
|
848
|
+
if (parseAriaRefSelector(selector) !== null) {
|
|
849
|
+
const handle = await this.#resolveAriaRef(selector);
|
|
850
|
+
try {
|
|
851
|
+
await untilAborted(sig, () => handle.click());
|
|
852
|
+
} finally {
|
|
853
|
+
await handle.dispose().catch(() => undefined);
|
|
854
|
+
}
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
818
857
|
const resolved = normalizeSelector(selector);
|
|
819
858
|
if (resolved.startsWith("text/")) await clickQueryHandlerText(page, resolved, timeoutMs, sig);
|
|
820
859
|
else await untilAborted(sig, () => page.locator(resolved).setTimeout(timeoutMs).click());
|
|
821
860
|
}),
|
|
822
861
|
type: (selector, text) =>
|
|
823
862
|
op(`tab.type(${JSON.stringify(selector)})`, INF, async sig => {
|
|
824
|
-
const handle =
|
|
825
|
-
page.locator(normalizeSelector(selector)).setTimeout(timeoutMs).waitHandle(),
|
|
826
|
-
)) as ElementHandle;
|
|
863
|
+
const handle = await this.#resolveActionHandle(selector, timeoutMs, sig);
|
|
827
864
|
try {
|
|
828
865
|
await untilAborted(sig, () => handle.type(text, { delay: 0 }));
|
|
829
866
|
} finally {
|
|
830
|
-
await handle.dispose();
|
|
867
|
+
await handle.dispose().catch(() => undefined);
|
|
831
868
|
}
|
|
832
869
|
}),
|
|
833
870
|
fill: (selector, value) =>
|
|
834
|
-
op(`tab.fill(${JSON.stringify(selector)})`, INF, sig =>
|
|
835
|
-
|
|
836
|
-
|
|
871
|
+
op(`tab.fill(${JSON.stringify(selector)})`, INF, async sig => {
|
|
872
|
+
if (parseAriaRefSelector(selector) !== null) {
|
|
873
|
+
const handle = await this.#resolveAriaRef(selector);
|
|
874
|
+
try {
|
|
875
|
+
await untilAborted(sig, () =>
|
|
876
|
+
handle.evaluate(el => {
|
|
877
|
+
const node = el as unknown as { value?: string; focus?: () => void };
|
|
878
|
+
node.focus?.();
|
|
879
|
+
if ("value" in node) node.value = "";
|
|
880
|
+
}),
|
|
881
|
+
);
|
|
882
|
+
await untilAborted(sig, () => handle.type(value, { delay: 0 }));
|
|
883
|
+
} finally {
|
|
884
|
+
await handle.dispose().catch(() => undefined);
|
|
885
|
+
}
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
await untilAborted(sig, () =>
|
|
889
|
+
page.locator(normalizeSelector(selector)).setTimeout(timeoutMs).fill(value),
|
|
890
|
+
);
|
|
891
|
+
}),
|
|
837
892
|
press: (key, opts) =>
|
|
838
893
|
op(`tab.press(${JSON.stringify(key)})`, INF, async sig => {
|
|
839
894
|
const selector = opts?.selector;
|
|
@@ -844,13 +899,8 @@ export class WorkerCore {
|
|
|
844
899
|
op("tab.scroll()", INF, sig => untilAborted(sig, () => page.mouse.wheel({ deltaX, deltaY }))),
|
|
845
900
|
drag: (from, to) => op("tab.drag()", INF, sig => this.#drag(from, to, sig)),
|
|
846
901
|
waitFor: selector =>
|
|
847
|
-
op(
|
|
848
|
-
|
|
849
|
-
INF,
|
|
850
|
-
async sig =>
|
|
851
|
-
(await untilAborted(sig, () =>
|
|
852
|
-
page.locator(normalizeSelector(selector)).setTimeout(timeoutMs).waitHandle(),
|
|
853
|
-
)) as ElementHandle,
|
|
902
|
+
op(`tab.waitFor(${JSON.stringify(selector)})`, INF, sig =>
|
|
903
|
+
this.#resolveActionHandle(selector, timeoutMs, sig),
|
|
854
904
|
),
|
|
855
905
|
evaluate: (fn, ...args) =>
|
|
856
906
|
op("tab.evaluate()", INF, sig =>
|
|
@@ -862,9 +912,7 @@ export class WorkerCore {
|
|
|
862
912
|
) as never,
|
|
863
913
|
scrollIntoView: selector =>
|
|
864
914
|
op(`tab.scrollIntoView(${JSON.stringify(selector)})`, INF, async sig => {
|
|
865
|
-
const handle =
|
|
866
|
-
page.locator(normalizeSelector(selector)).setTimeout(timeoutMs).waitHandle(),
|
|
867
|
-
)) as ElementHandle;
|
|
915
|
+
const handle = await this.#resolveActionHandle(selector, timeoutMs, sig);
|
|
868
916
|
try {
|
|
869
917
|
await untilAborted(sig, () =>
|
|
870
918
|
handle.evaluate(el => {
|
|
@@ -889,6 +937,7 @@ export class WorkerCore {
|
|
|
889
937
|
waitForResponse: (pattern, opts) =>
|
|
890
938
|
op("tab.waitForResponse()", INF, sig => this.#waitForResponse(pattern, opts?.timeout ?? timeoutMs, sig)),
|
|
891
939
|
id: id => this.#resolveCachedHandle(id),
|
|
940
|
+
ref: id => this.#resolveAriaRef(id),
|
|
892
941
|
};
|
|
893
942
|
}
|
|
894
943
|
|
|
@@ -1188,6 +1237,29 @@ export class WorkerCore {
|
|
|
1188
1237
|
}
|
|
1189
1238
|
return handle;
|
|
1190
1239
|
}
|
|
1240
|
+
|
|
1241
|
+
async #resolveAriaRef(id: string): Promise<ElementHandle> {
|
|
1242
|
+
const ref = parseAriaRefSelector(id) ?? id.trim();
|
|
1243
|
+
const handle = await resolveAriaRefHandle(this.#requirePage(), ref);
|
|
1244
|
+
if (!handle) {
|
|
1245
|
+
throw new ToolError(
|
|
1246
|
+
`Unknown ARIA ref ${JSON.stringify(ref)}. Run tab.ariaSnapshot() to refresh refs (they renumber each snapshot).`,
|
|
1247
|
+
);
|
|
1248
|
+
}
|
|
1249
|
+
return handle;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
/**
|
|
1253
|
+
* Resolve a selector to an ElementHandle for handle-based actions. An
|
|
1254
|
+
* `aria-ref=eN` selector resolves against the latest ariaSnapshot's refs
|
|
1255
|
+
* (main world); anything else goes through the normal locator wait.
|
|
1256
|
+
*/
|
|
1257
|
+
async #resolveActionHandle(selector: string, timeoutMs: number, sig: AbortSignal): Promise<ElementHandle> {
|
|
1258
|
+
if (parseAriaRefSelector(selector) !== null) return this.#resolveAriaRef(selector);
|
|
1259
|
+
return (await untilAborted(sig, () =>
|
|
1260
|
+
this.#requirePage().locator(normalizeSelector(selector)).setTimeout(timeoutMs).waitHandle(),
|
|
1261
|
+
)) as ElementHandle;
|
|
1262
|
+
}
|
|
1191
1263
|
#clearElementCache(): void {
|
|
1192
1264
|
if (this.#elementCache.size === 0) {
|
|
1193
1265
|
this.#elementCounter = 0;
|
package/src/tools/browser.ts
CHANGED
|
@@ -16,6 +16,11 @@ import { ToolAbortError, ToolError, throwIfAborted } from "./tool-errors";
|
|
|
16
16
|
import { toolResult } from "./tool-result";
|
|
17
17
|
import { clampTimeout } from "./tool-timeouts";
|
|
18
18
|
|
|
19
|
+
export {
|
|
20
|
+
type AriaSnapshotOptions,
|
|
21
|
+
buildAriaSnapshotScript,
|
|
22
|
+
parseAriaRefSelector,
|
|
23
|
+
} from "./browser/aria/aria-snapshot";
|
|
19
24
|
export { cmuxSnapshotToObservation, mapWaitUntil, resolveCmuxKind, serializeEval } from "./browser/cmux/rpc";
|
|
20
25
|
export { CmuxSocketClient } from "./browser/cmux/socket-client";
|
|
21
26
|
export { extractReadableFromHtml, type ReadableFormat, type ReadableResult } from "./browser/readable";
|
package/src/tools/find.ts
CHANGED
|
@@ -101,8 +101,7 @@ interface FindTarget {
|
|
|
101
101
|
export class FindTool implements AgentTool<typeof findSchema, FindToolDetails> {
|
|
102
102
|
readonly name = "find";
|
|
103
103
|
readonly approval = "read" as const;
|
|
104
|
-
readonly
|
|
105
|
-
readonly loadMode = "discoverable";
|
|
104
|
+
readonly loadMode = "essential";
|
|
106
105
|
readonly label = "Find";
|
|
107
106
|
readonly description: string;
|
|
108
107
|
readonly parameters = findSchema;
|
package/src/tools/index.ts
CHANGED
|
@@ -375,7 +375,7 @@ export type ToolFactory = (session: ToolSession) => Tool | null | Promise<Tool |
|
|
|
375
375
|
export type BuiltinToolLoadMode = "essential" | "discoverable";
|
|
376
376
|
|
|
377
377
|
/** Default essential tool names when tools.essentialOverride is empty. */
|
|
378
|
-
export const DEFAULT_ESSENTIAL_TOOL_NAMES: readonly string[] = ["read", "bash", "edit"] as const;
|
|
378
|
+
export const DEFAULT_ESSENTIAL_TOOL_NAMES: readonly string[] = ["read", "bash", "edit", "write", "find"] as const;
|
|
379
379
|
|
|
380
380
|
/**
|
|
381
381
|
* Resolve the active essential built-in tool names from settings.
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
"function " + (name || "") + "() { [native code] }";
|
|
4
|
-
|
|
5
|
-
// Patch toString for common fingerprinted functions
|
|
1
|
+
// Register native-looking source for common fingerprinted functions without
|
|
2
|
+
// adding own toString properties.
|
|
6
3
|
const patchedFns = [
|
|
7
4
|
[window.alert, "alert"],
|
|
8
5
|
[window.prompt, "prompt"],
|
|
@@ -20,44 +17,28 @@ const patchedFns = [
|
|
|
20
17
|
];
|
|
21
18
|
|
|
22
19
|
for (const [fn, name] of patchedFns) {
|
|
23
|
-
|
|
24
|
-
const nativeStr = makeNativeString(name);
|
|
25
|
-
Object_defineProperty(fn, "toString", {
|
|
26
|
-
value: function toString() { return nativeStr; },
|
|
27
|
-
writable: false,
|
|
28
|
-
configurable: true,
|
|
29
|
-
enumerable: false,
|
|
30
|
-
});
|
|
31
|
-
}
|
|
20
|
+
patchToString(fn, name);
|
|
32
21
|
}
|
|
33
22
|
|
|
34
|
-
// Patch Object.getOwnPropertyDescriptor to return native-looking
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
// Patch Object.getOwnPropertyDescriptor to return native-looking accessor
|
|
24
|
+
// source through the shared Function.prototype.toString registry.
|
|
25
|
+
const patchedGetOwnPropertyDescriptor = function getOwnPropertyDescriptor(obj, prop) {
|
|
26
|
+
const descriptor = Reflect_apply(Object_getOwnPropertyDescriptor, this, [obj, prop]);
|
|
37
27
|
if (!descriptor) return descriptor;
|
|
38
28
|
|
|
39
|
-
// Make patched descriptors look native
|
|
40
29
|
if (descriptor.get && typeof descriptor.get === "function") {
|
|
41
|
-
|
|
42
|
-
Object_defineProperty(descriptor.get, "toString", {
|
|
43
|
-
value: function toString() { return getStr; },
|
|
44
|
-
writable: false,
|
|
45
|
-
configurable: true,
|
|
46
|
-
enumerable: false,
|
|
47
|
-
});
|
|
30
|
+
patchToString(descriptor.get, "get " + String(prop));
|
|
48
31
|
}
|
|
49
32
|
if (descriptor.set && typeof descriptor.set === "function") {
|
|
50
|
-
|
|
51
|
-
Object_defineProperty(descriptor.set, "toString", {
|
|
52
|
-
value: function toString() { return setStr; },
|
|
53
|
-
writable: false,
|
|
54
|
-
configurable: true,
|
|
55
|
-
enumerable: false,
|
|
56
|
-
});
|
|
33
|
+
patchToString(descriptor.set, "set " + String(prop));
|
|
57
34
|
}
|
|
58
35
|
|
|
59
36
|
return descriptor;
|
|
60
37
|
};
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
38
|
+
patchToString(patchedGetOwnPropertyDescriptor, "getOwnPropertyDescriptor");
|
|
39
|
+
Object_defineProperty(Object, "getOwnPropertyDescriptor", {
|
|
40
|
+
value: patchedGetOwnPropertyDescriptor,
|
|
41
|
+
writable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
enumerable: false,
|
|
44
|
+
});
|
|
@@ -1,20 +1,80 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
{
|
|
2
|
+
const visibilityDescriptors = Object_getOwnPropertyDescriptors({
|
|
3
|
+
get hidden() {
|
|
4
|
+
return false;
|
|
5
|
+
},
|
|
6
|
+
get visibilityState() {
|
|
7
|
+
return "visible";
|
|
8
|
+
},
|
|
9
|
+
get webkitHidden() {
|
|
10
|
+
return false;
|
|
11
|
+
},
|
|
12
|
+
get webkitVisibilityState() {
|
|
13
|
+
return "visible";
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
for (const key of Object_keys(visibilityDescriptors)) {
|
|
17
|
+
const descriptor = visibilityDescriptors[key];
|
|
18
|
+
if (descriptor && typeof descriptor.get === "function") {
|
|
19
|
+
patchToString(descriptor.get, "get " + key);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const focusDescriptor = Object_getOwnPropertyDescriptor(
|
|
23
|
+
{
|
|
24
|
+
hasFocus() {
|
|
25
|
+
return document.visibilityState === "visible";
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
"hasFocus",
|
|
29
|
+
);
|
|
30
|
+
if (focusDescriptor && typeof focusDescriptor.value === "function") {
|
|
31
|
+
patchToString(focusDescriptor.value, "hasFocus");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const clearOwnSlot = (name) => {
|
|
35
|
+
const ownDescriptor = Object_getOwnPropertyDescriptor(document, name);
|
|
36
|
+
if (!ownDescriptor) return true;
|
|
37
|
+
if (ownDescriptor.configurable !== true) return false;
|
|
38
|
+
return Reflect_deleteProperty(document, name);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const inheritedSlot = (name, expectedKind) => {
|
|
42
|
+
let proto = Object_getPrototypeOf(document);
|
|
43
|
+
while (proto) {
|
|
44
|
+
const descriptor = Object_getOwnPropertyDescriptor(proto, name);
|
|
45
|
+
if (descriptor && typeof descriptor[expectedKind] === "function") {
|
|
46
|
+
return [proto, descriptor];
|
|
47
|
+
}
|
|
48
|
+
proto = Object_getPrototypeOf(proto);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const defineAccessor = (name) => {
|
|
53
|
+
if (!clearOwnSlot(name)) return;
|
|
54
|
+
const slot = inheritedSlot(name, "get");
|
|
55
|
+
if (!slot || slot[1].configurable !== true) return;
|
|
56
|
+
|
|
57
|
+
Object_defineProperty(slot[0], name, {
|
|
58
|
+
get: visibilityDescriptors[name].get,
|
|
59
|
+
enumerable: slot[1].enumerable,
|
|
60
|
+
configurable: true,
|
|
7
61
|
});
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
defineAccessor("hidden");
|
|
65
|
+
defineAccessor("visibilityState");
|
|
66
|
+
defineAccessor("webkitHidden");
|
|
67
|
+
defineAccessor("webkitVisibilityState");
|
|
68
|
+
|
|
69
|
+
if (clearOwnSlot("hasFocus")) {
|
|
70
|
+
const slot = inheritedSlot("hasFocus", "value");
|
|
71
|
+
if (slot && slot[1].configurable === true) {
|
|
72
|
+
Object_defineProperty(slot[0], "hasFocus", {
|
|
73
|
+
value: focusDescriptor.value,
|
|
74
|
+
writable: slot[1].writable === true,
|
|
75
|
+
enumerable: slot[1].enumerable,
|
|
76
|
+
configurable: true,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -1,11 +1,57 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
{
|
|
2
|
+
const htmlElementOffsetHeightDescriptor =
|
|
3
|
+
typeof HTMLElement === "undefined"
|
|
4
|
+
? undefined
|
|
5
|
+
: Object_getOwnPropertyDescriptor(HTMLElement.prototype, "offsetHeight");
|
|
6
|
+
const htmlDivElementOffsetHeightDescriptor =
|
|
7
|
+
typeof HTMLDivElement === "undefined"
|
|
8
|
+
? undefined
|
|
9
|
+
: Object_getOwnPropertyDescriptor(HTMLDivElement.prototype, "offsetHeight");
|
|
10
|
+
const offsetHeightDescriptor =
|
|
11
|
+
htmlDivElementOffsetHeightDescriptor || htmlElementOffsetHeightDescriptor;
|
|
12
|
+
const offsetHeightPrototype = htmlDivElementOffsetHeightDescriptor
|
|
13
|
+
? HTMLDivElement.prototype
|
|
14
|
+
: htmlElementOffsetHeightDescriptor
|
|
15
|
+
? HTMLElement.prototype
|
|
16
|
+
: undefined;
|
|
17
|
+
const elementIdDescriptor =
|
|
18
|
+
typeof Element === "undefined"
|
|
19
|
+
? undefined
|
|
20
|
+
: Object_getOwnPropertyDescriptor(Element.prototype, "id");
|
|
21
|
+
|
|
22
|
+
if (
|
|
23
|
+
typeof HTMLDivElement !== "undefined" &&
|
|
24
|
+
offsetHeightPrototype &&
|
|
25
|
+
offsetHeightDescriptor &&
|
|
26
|
+
typeof offsetHeightDescriptor.get === "function" &&
|
|
27
|
+
offsetHeightDescriptor.configurable &&
|
|
28
|
+
elementIdDescriptor &&
|
|
29
|
+
typeof elementIdDescriptor.get === "function"
|
|
30
|
+
) {
|
|
31
|
+
const offsetHeightGetter = new Window_Proxy(offsetHeightDescriptor.get, {
|
|
32
|
+
apply(target, thisArg, args) {
|
|
33
|
+
const height = Reflect_apply(target, thisArg, args);
|
|
34
|
+
|
|
35
|
+
if (
|
|
36
|
+
height === 0 &&
|
|
37
|
+
Object_getPrototypeOf(thisArg) === HTMLDivElement.prototype &&
|
|
38
|
+
Reflect_apply(elementIdDescriptor.get, thisArg, []) === "modernizr"
|
|
39
|
+
) {
|
|
40
|
+
return 1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return height;
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
patchToString(offsetHeightGetter, "get offsetHeight");
|
|
48
|
+
|
|
49
|
+
Object_defineProperty(
|
|
50
|
+
offsetHeightPrototype,
|
|
51
|
+
"offsetHeight",
|
|
52
|
+
Object_assign({}, offsetHeightDescriptor, {
|
|
53
|
+
get: offsetHeightGetter,
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
const makeNativeString = (name) => "function " + (name || "") + "() { [native code] }";
|
|
2
|
-
const patchToString = (fn, name) => {
|
|
3
|
-
if (typeof fn !== "function") return;
|
|
4
|
-
Object_defineProperty(fn, "toString", {
|
|
5
|
-
value: function toString() {
|
|
6
|
-
return makeNativeString(name);
|
|
7
|
-
},
|
|
8
|
-
writable: false,
|
|
9
|
-
configurable: true,
|
|
10
|
-
enumerable: false,
|
|
11
|
-
});
|
|
12
|
-
};
|
|
13
1
|
|
|
14
2
|
// Ensure navigator.webdriver behaves like real Chrome
|
|
15
3
|
if (navigator.webdriver !== false && navigator.webdriver !== undefined) {
|
|
@@ -356,13 +344,19 @@ if (window.chrome && !("runtime" in window.chrome) && isSecureOrigin) {
|
|
|
356
344
|
// Suppress Permission.query for automation-controlled
|
|
357
345
|
if (navigator.permissions?.query) {
|
|
358
346
|
if (isSecureOrigin && "Notification" in window) {
|
|
347
|
+
const notificationPermissionGetter = Object_getOwnPropertyDescriptor({
|
|
348
|
+
get permission() {
|
|
349
|
+
return "default";
|
|
350
|
+
},
|
|
351
|
+
}, "permission").get;
|
|
352
|
+
patchToString(notificationPermissionGetter, "get permission");
|
|
359
353
|
Object_defineProperty(Notification, "permission", {
|
|
360
|
-
get:
|
|
354
|
+
get: notificationPermissionGetter,
|
|
361
355
|
configurable: true,
|
|
362
356
|
});
|
|
363
357
|
} else if (!isSecureOrigin) {
|
|
364
358
|
const originalQuery = navigator.permissions.query;
|
|
365
|
-
|
|
359
|
+
const patchedPermissionsQuery = function query(parameters) {
|
|
366
360
|
if (parameters?.name === "notifications") {
|
|
367
361
|
const status = { state: "denied", onchange: null };
|
|
368
362
|
if (typeof PermissionStatus !== "undefined") {
|
|
@@ -372,6 +366,8 @@ if (navigator.permissions?.query) {
|
|
|
372
366
|
}
|
|
373
367
|
return originalQuery.call(this, parameters);
|
|
374
368
|
};
|
|
369
|
+
patchToString(patchedPermissionsQuery, "query");
|
|
370
|
+
navigator.permissions.query = patchedPermissionsQuery;
|
|
375
371
|
}
|
|
376
372
|
}
|
|
377
373
|
|