AdguardTeam / AdguardTeam/Scriptlets

Add new scriptlets — 'edit-object-on-getter' and 'edit-object-on-setter'

オープン
#568 コメント 1 件 リアクション 0 件 担当者 1 名 @maximtop が担当を希望しています GitHub で見る
enhancement Feature request Priority: P4 Version: Scriptlets v2.5
主要言語
JavaScript
スター
195
フォーク
33
PR マージ指標
30日以内にマージされた PR はありません

説明

uBlock Origin recently added four new scriptlets that AdGuard has no equivalent for — ([commit 99e6228](https://github.com/gorhill/uBlock/commit/99e622831b5fdd746996334d2108a45f65aeb1e6)):

- **`edit-object-on-getter.js`** — prune properties from an object on **read** access
- **`trusted-edit-object-on-getter.js`** — edit (set new values) properties of an object on **read** access
- **`edit-object-on-setter.js`** — prune properties from an object on **write** access
- **`trusted-edit-object-on-setter.js`** — edit (set new values) properties of an object on **write** access

## How they work

```
Scriptlet intercepts property descriptor:
propChain (e.g. "window.__data")

getter trap OR setter trap

JSONPath query applied (prune / edit)

Modified object returned to / stored for page scripts
```

The core mechanism uses `trapProperty` that walks the property chain, replaces the descriptor with `{ get, set }` traps, and on access applies JSONPath edits.

## Gap analysis

| AdGuard scriptlet | What it does | Why it's not equivalent |
|---|---|---|
| `set-constant` / `trusted-set-constant` | Replaces **entire** property value | No selective editing — can't say "remove `trackingId` but keep `userName`" |
| `json-prune` / `json-prune-fetch-response` / `json-prune-xhr-response` | Intercepts `JSON.parse` / `fetch` / `XHR` | Only works on network/parse boundaries, not arbitrary property access |
| `trusted-json-set` | Intercepts method calls via `Proxy` | Intercepts function calls, not property descriptor access |
| `abort-on-property-read/write` | Throws `ReferenceError` on access | Only aborts — doesn't modify values |
| `trusted-prune-inbound-object` | `Proxy` on native methods, prunes arguments | Prunes function arguments, not property descriptor returns |

**None of these can do**: "When `window.__CONFIG` is read, return it with `trackingPreferences` removed."

## Real-world use case

```javascript
// Site sets:
window.__INITIAL_STATE__ = {
user: { name: "Alice", id: "123", trackingId: "abc-def", adPreferences: {...} },
config: { theme: "dark", analyticsEnabled: true }
};

// Desired: when any script reads window.__INITIAL_STATE__,
// `trackingId` and `adPreferences` are pruned, `analyticsEnabled` set to false

// example.com##+js(edit-object-on-getter, window.__INITIAL_STATE__, $.user.trackingId $.user.adPreferences $.config.analyticsEnabled)
// Not possible with any existing AdGuard scriptlet
```

## Proposed implementation

### 1. New helper
A shared helper that defines getter/setter traps on a property chain and applies a configurable edit callback. Can reuse:
- `getPropertyInChain()` — chain walking (`get-property-in-chain.ts`)
- `setPropertyAccess()` — safe `Object.defineProperty` wrapper (`object-utils.ts`)
- `interceptChainProp()` — intermediate chain trap (`chain-prop-utils.ts`)
- `getDescriptorAddon()` — infinite-loop prevention (`get-descriptor-addon.ts`)
- `jsonPruner()` / `jsonPath()` — JSON mutation (`prune-utils.ts`, `json-path-utils.ts`)

### 2. Four new scriptlet files

| File | Uses |
|---|---|
| `src/scriptlets/edit-object-on-getter.js` | `jsonPruner` for prune-only |
| `src/scriptlets/edit-object-on-setter.js` | `jsonPruner` for prune-only |
| `src/scriptlets/trusted-edit-object-on-getter.js` | `jsonPath` for full edit |
| `src/scriptlets/trusted-edit-object-on-setter.js` | `jsonPath` for full edit |

Each accepts: `propChain` (dot-separated path) + variadic JSONPath expressions.

### 3. Test files (4), compatibility table updates, auto-generated wiki docs

## Design decisions

1. **JSONPath syntax**: Use AdGuard's existing JSONPath syntax from `json-path-utils.ts`. uBO compatibility aliases may be needed for cross-blocker filter lists.
2. **Non-trusted scope**: Follow uBO's security boundary — only pruning, no value injection.
3. **Chain trapping**: Follow `set-constant` pattern — trap intermediate null/undefined props so the trap activates when the chain materializes.
4. **Stack matching**: Consider adding optional `stack` parameter for targeting specific call sites (uBO doesn't include it, but AdGuard's `set-constant` does).

## Related

- uBO commit: https://github.com/gorhill/uBlock/commit/99e622831b5fdd746996334d2108a45f65aeb1e6
- uBO issue: https://github.com/uBlockOrigin/uBlock-issues/issues/4019

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。