Skip to content

fix(adblocker): inject scriptlets of a frame in one scope - #3687

Merged
chrmod merged 7 commits into
mainfrom
scriptlets-shared-scope
Oct 7, 2026
Merged

chrmod merged 7 commits into
mainfrom
scriptlets-shared-scope

Conversation

@chrmod

@chrmod chrmod commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Scriptlets of a world are injected once, in one scope, so safeSelf() and its cache exist once per frame instead of once per scriptlet (refs #3672). The Symbol.for marker on window from ghostery/scriptlets#63 is gone.

Every path runs the package's run() with the frame's calls: serialized as code for registered scripts (Firefox contentScripts, Chrome userScripts), and as a function with JSON arguments for chrome.scripting.executeScript. A filter that matched the frame directly is registered even when it also carries a >> domain.

Requires ghostery/scriptlets#64 (merged); the lockfile resolves @ghostery/scriptlets to its merge commit.

@smalluban smalluban left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's draft, but I have only one ask to separate fix with e2e - it can just help others before we merge this PR.

Comment thread tests/e2e/wdio.conf.js
Comment thread package.json Outdated
Comment thread src/background/adblocker/cosmetics.js Outdated
Comment thread src/background/adblocker/cosmetics.js Outdated
Comment on lines +131 to +132
const registered =
useRegistry && (!filter.hasSubframeConstraint() || filter.match(hostname, domain));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be discussed. But intended to address a possible regression with 217e02b

Suggested change
const registered =
useRegistry && (!filter.hasSubframeConstraint() || filter.match(hostname, domain));
// filter.match() reads a negation-only list (`a.com>>,~b.com`) as "every hostname but b.com",
// so only a positive hostname or entity entry counts as a direct match.
const { domains } = filter;
const matchesDirectly =
domains !== undefined &&
(domains.hostnames !== undefined || domains.entities !== undefined) &&
filter.match(hostname, domain);
const registered = useRegistry && (!filter.hasSubframeConstraint() || matchesDirectly);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, as discussed, let's keep it out. (If it is a real problem, we should address it in a follow-up.)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out this diff is only a workaround for an adblocker bug: ghostery/adblocker#5850

That means, the original line is good. The real fix is in the adblocker, not here.

@chrmod
chrmod force-pushed the scriptlets-shared-scope branch from 522d08b to 2fd9284 Compare October 6, 2026 14:27
@chrmod
chrmod requested a review from smalluban October 6, 2026 15:05
@chrmod
chrmod force-pushed the scriptlets-shared-scope branch from 7fcc090 to 3e8dd80 Compare October 6, 2026 15:09

@smalluban smalluban left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM now.

@chrmod
chrmod merged commit 6c287bb into main Oct 7, 2026
7 checks passed
@chrmod
chrmod deleted the scriptlets-shared-scope branch October 7, 2026 08:47
@smalluban smalluban mentioned this pull request Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants