AdguardTeam / AdguardTeam/Scriptlets

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

Aberta
#568 1 comentário 0 reações 1 responsável Reivindicada por @maximtop Ver no GitHub
enhancement Feature request Priority: P4 Version: Scriptlets v2.5
Linguagem predominante
JavaScript
Estrelas
195
Forks
33
Métricas de merge de PRs
Nenhum PR com merge em 30d

Descrição

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

Guia de contribuição

Nenhum guia de contribuição indexado para este repositório

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.