Skip to content

userId: a filtered refreshUserIds must not release the auction early - #15

Open
MO-Thibault wants to merge 1255 commits into
masterfrom
mo/userid-refresh-preserves-pending-init
Open

userId: a filtered refreshUserIds must not release the auction early#15
MO-Thibault wants to merge 1255 commits into
masterfrom
mo/userid-refresh-preserves-pending-init

Conversation

@MO-Thibault

Copy link
Copy Markdown

Type of change

  • Bugfix

Description

refreshUserIds({submoduleNames}) can release the auction before submodules it did not name have finished initializing.

cancelAndTry rejects the previous cancel deferred, so the old done — a race that includes cancel.promise — settles immediately. The replacement chain then does done.catch(() => null) against that already-settled race rather than the inner promise still holding the pending work:

if (refresh && initialized) {
  done = cancelAndTry(
    done
      .catch(() => null)     // <- the cancelled race, not the work in flight
      .then(timeConsent)
      .then(checkRefs(() => { /* initSubmodules for the named submodules only */ }))
  );
}

What it waits on instead is initSubmodules for the named submodules. For something like pubProvidedId that is a synchronous storage read, so it resolves almost immediately, getUserIdsAsync resolves with it, and startAuctionHook proceeds:

PbPromise.race([ getIds().catch(() => null), mkDelay(auctionDelay) ])
  .then(() => { addIdData(reqBidsConfigObj); fn.call(this, reqBidsConfigObj); });

This contradicts getUserIdsAsync's own docstring:

@returns a promise that resolves to the same value as getUserIds(), but only once all ID submodules have completed initialization.

and startAuctionHook is its main internal consumer, so the auction stops honouring auctionDelay for every submodule the refresh did not name.

retryOnCancel's INIT_CANCELED handler is not the problem — it retries correctly. The leak is one level down, in the refresh branch.

How it shows up

Publisher running userSync.auctionDelay = 300 with liveIntentId and pubProvidedId. A page-load refreshUserIds({submoduleNames: ['pubProvidedId']}) released the first auction roughly 300ms early, before liveIntentId's network call returned, so its EIDs were absent from that auction's bid requests.

Instrumented browser, LiveIntent's endpoints delayed so its arrival straddled the two auction times:

kept LiveIntent on auction 1
with the refresh 0 of 9
without it 8 of 9

The auction opened ~294ms earlier in 6 of 6 timed pairs, against the configured 300, with refreshUserIds firing 15-25ms before auctionInit every run.

Confirmed independently in production: a control arm carrying one inert EID purely to trigger the refresh, and nothing else, dropped first-auction LiveIntent presence from 77.1% to 49.7% (n=384 and n=350, z ~8), converging with the untouched arm from the second auction on.

Any publisher combining a non-zero auctionDelay with a filtered refreshUserIds is silently losing their slowest ID module on the first auction, which is typically their most valuable.

The change

Track pending submodule callbacks per submodule name rather than as one blob, and have getUserIdsAsync await the ones still outstanding.

A refresh supersedes the entries for the modules it names. An unfiltered refreshUserIds() therefore clears them all and keeps its current behaviour of unblocking a stuck init, which should still resolve promises returned by refreshUserIds and ... getUserIdsAsync both depend on. A filtered refresh leaves the untouched modules' entries in place, which is the fix.

refreshUserIds' own return value is unchanged. Nothing waits longer than before except getUserIdsAsync, and the auction is still bounded by mkDelay(auctionDelay), so a genuinely stuck submodule cannot hang it.

An earlier attempt chained the refresh off the uncancelled inner promise instead. It broke the two tests above, because an unfiltered forced refresh is meant to escape a stuck init. Per-module tracking is what reconciles the two.

Test

New: should not release the auction when a filtered refresh cancels a pending submodule.

Verified in both directions with gulp test --file test/spec/modules/userId_spec.js:

  • with the fix: 130 passed
  • source fix reverted, test kept: 129 passed, 1 failed, and the failure is the new test

ESLint clean on both files.

patmmccann and others added 30 commits June 22, 2026 15:17
* add build on Windows

* translate import paths

* refactor workflow

* stray param

* fix define testing strategy job

* force bash
* Build: replace fancy-log with gulplog

* Build: replace fancy-log with gulplog

* Add comment about gulplog availability

---------

Co-authored-by: Patrick McCann <pmccann@cafemedia.com>
* New adapter: billow_rtb25

* delete options

* add public interface

* Change the adapter type to a ts file

* update Adapter billow_rtb25: Add support for the sharedId field

* update Adapter billow_rtb25: Add support for the sharedId field

* update Adapter billow_rtb25: fix

* fix

---------

Co-authored-by: zepeng.yin <zp.yin@foxmail.com>
* ConnectAd: adapter, documentation and test updates

Co-authored-by: Cursor <cursoragent@cursor.com>

* ConnectAd: use CDN URL for outstream renderer

Co-authored-by: Cursor <cursoragent@cursor.com>

* ConnectAd: restore EIDs mapping and stabilize audio spec in no-feature runs

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix missing semicolon on line 35 in connectadBidAdapter_spec.js

* Add missing tests for code coverage: viewability, outstream renderer, floorprice fallback, endpointUrl override, and video/native media type detection

* Add ConnectAd adapter tests to restore PR code coverage.

Cover viewability, outstream renderer, media type fallbacks, native asset
alignment, and getUserSyncs edge cases that Barecheck reported as uncovered.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix ConnectAd spec for lint and feature-disabled CI.

Remove unnecessary Function.prototype.call usage flagged by ESLint and
skip video viewability coverage when the VIDEO feature is disabled.

Co-authored-by: Cursor <cursoragent@cursor.com>

* ConnectAd Adapter: address requested review changes

* ConnectAd Adapter: address follow-up review feedback

Remove dead bidRequest.data string parsing incompatible with ortbConverter
object identity, refactor outstream tests with sinon sandbox cleanup, and
drop obsolete string-parse specs.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Robert Ray Martinez III <rrmartinez1552@gmail.com>
* Yieldmo Bid Adapter: revert badv support (keep bcat)

Reverts the badv portions of prebid#14989 because a large publisher's long badv
lists are materially hurting monetization (FS-12411). bcat is left fully
intact (ortb2 + params merge on banner and video).

badv is restored to its exact pre-prebid#14989 behavior:
- banner GET no longer sends badv
- video OpenRTB sends badv: bidRequests[0].params.badv || [] (no ortb2/merge)
- params.badv array validation moves back into validateVideoParams (video-only)

Docs and unit tests updated to match; getBlocklist retained for bcat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Yieldmo Bid Adapter: document video-only params.badv

Restore badv to the docs after the FS-12411 revert, but scoped to its
actual reverted behavior: video-only, params source only (no ortb2, no
banner). Documentation only; no code change.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Prebid Server Adapter: align sync browser restrictions

* Prebid Server Adapter: align sync browser restrictions

### Motivation
- PBS cookie syncs were being attempted in browsers where regular user syncs are blocked, causing inconsistent behavior and potential failures.
- The change centralizes the browser/cookie eligibility logic so both client-side user syncs and PBS syncs share the same restrictions (avoid Chrome on iOS, Safari, and Firefox and require cookies enabled).

### Description
- Exported `browserSupportsUserSyncCookies()` from `src/userSync.ts` and switched the user-sync getter to call it so the eligibility check is reusable.
- Added an early-return in `queueSync` inside `modules/prebidServerBidAdapter/index.ts` to skip PBS cookie syncs when `browserSupportsUserSyncCookies()` is false.
- Updated `src/userSync.ts` to use the new exported helper for `browserSupportsCookies` so logic is not duplicated.
- Added unit tests in `test/spec/modules/prebidServerBidAdapter_spec.js` to verify PBS syncs are skipped for Safari, Firefox, and Chrome on iOS while the auction request still proceeds.

### Testing
- Ran lint for the changed files with `npx eslint modules/prebidServerBidAdapter/index.ts src/userSync.ts test/spec/modules/prebidServerBidAdapter_spec.js --cache --cache-strategy content` which completed successfully.
- Executed the adapter test target with `npx gulp test --nolint --file test/spec/modules/prebidServerBidAdapter_spec.js` and the spec chunk completed successfully (tests passed).
- Confirmed the modified spec asserts that PBS sync requests are not made on Safari, Firefox, and Chrome on iOS (unit tests passed).

* Prevent user syncs on browsers with restricted cookies (Safari/Firefox/Chrome iOS)

### Motivation
- Prevent initiating user syncs when the browser environment is known to block third-party cookies or when cookies are disabled to avoid futile sync attempts and privacy/regulatory issues.
- Centralize the browser/cookie capability check so both the PBS adapter and the user sync subsystem use the same logic.

### Description
- Added `browserSupportsUserSyncCookies()` in `src/userSync.ts` which returns `!isSafariBrowser() && !isFirefoxBrowser() && !isChromeIOSBrowser() && storage.cookiesAreEnabled()`.
- Updated `userSync` to use the new `browserSupportsUserSyncCookies()` via the `browserSupportsCookies` getter to keep cookie-capability checks consistent.
- Imported and used `browserSupportsUserSyncCookies()` in `modules/prebidServerBidAdapter/index.ts` to early-return from `queueSync()` when user sync cookies are not supported.
- Extended and updated unit tests in `test/spec/modules/prebidServerBidAdapter_spec.js` to stub browser detectors and assert that PBS syncs are not requested for Safari, Firefox, and Chrome on iOS.

### Testing
- Ran unit tests for the s2s/PBS adapter spec (`test/spec/modules/prebidServerBidAdapter_spec.js`) including new browser-restriction cases, and they passed.
- Ran the repository unit test suite after changes and all tests succeeded.

* better test fix

---------

Co-authored-by: Demetrio Girardi <dgirardi@prebid.org>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
* New Adapter: m152

* fix adapter according to new example

---------

Co-authored-by: 152media <info@152media.com>
…prebid#15148) on

* new version

* fixes

* naming fixes

* test fix

* copilot cr fixes

* linter fix

* fix url documentation
)

* Uniquest Adapters: send im_uid from intimatemerger EID

* Uniquest Adapters: fix im_uid EID lookup to use userIdAsEids

Read EIDs from bidRequest.userIdAsEids (the canonical path populated by
the Prebid userId module) with ortb2.user.ext.eids as a fallback for
manually configured cases. Previously, only the ortb2 path was checked,
causing im_uid to be silently omitted when the intimatemerger submodule
was configured via the userId module.

Extracted shared getImuid() helper into uniquestUtils to deduplicate
the logic across both adapters. Added tests covering the userIdAsEids
path.

* Uniquest Adapters: fix im_uid lost when userIdAsEids is empty array
…ebid#15187)

* Implemented setting device.connectiontype Bid Request property

ADBRO-4534

* Avoided override existing Device Connection Type

ADBRO-4534
* Lint: catch redundant validated conditionals

* Core: prevent redundant conditionals

### Motivation
- Reduce noisy/incorrect conditionals flagged by CodeQL by adding a lint rule to detect redundant checks that follow an exiting guard.
- Replace always-true/always-false fallbacks with simpler, clearer expressions to avoid confusion and potential bugs.

### Description
- Enable ESLint's `no-constant-binary-expression` rule and add a custom rule `prebid/no-redundant-validated-condition` in `eslint.config.js` to catch redundant conditionals.
- Add a new custom rule implementation at `plugins/eslint/noRedundantValidatedCondition.js` and register it in `plugins/eslint/index.js`.
- Fix a set of reported redundant conditionals and simplify expressions across modules and tests, including `modules/reconciliationRtdProvider.js`, `modules/abtshieldIdSystem.js`, `modules/jwplayerRtdProvider.js`, `modules/magniteAnalyticsAdapter.js`, `modules/rubiconBidAdapter.js`, `modules/sonobiBidAdapter.js`, `modules/topicsFpdModule.js`, `modules/pubxaiRtdProvider.js`, `modules/optidigitalBidAdapter.js`, `modules/nextMillenniumBidAdapter.js`, and test specs `test/spec/modules/consentManagementUsp_spec.js` and `test/spec/unit/secureCreatives_spec.js`.
- Small cleanups: removed an unused `cookieless` variable and simplified several conditional fallbacks to the straightforward form (see modified files list in the diff).

### Testing
- Ran targeted ESLint on the changed files with `npx eslint --cache --cache-strategy content <files>` and the lint pass for the modified files completed successfully.
- Ran unit test chunks for impacted specs with `npx gulp test --nolint --file test/spec/modules/consentManagementUsp_spec.js` and `npx gulp test --nolint --file test/spec/unit/secureCreatives_spec.js`, and both test runs completed with all tests passing.
- Verified repository changes compile during the test bundles (webpack compiled successfully during the test runs).

* Add ESLint rule to catch redundant validated conditionals and apply lint-driven cleanups

### Motivation

- Introduce a new ESLint rule to detect redundant conditionals where an identifier is already known to be truthy.
- Apply related lint-driven cleanups and small bug fixes across multiple modules to improve code clarity and correctness.

### Description

- Add new rule implementation in `plugins/eslint/noRedundantValidatedCondition.js` and register it in `plugins/eslint/index.js` as `no-redundant-validated-condition`.
- Enable new rules in `eslint.config.js` by adding `prebid/no-redundant-validated-condition` and `no-constant-binary-expression`.
- Make localized code changes to satisfy the new lint rule and modernize code, including replacing redundant expressions, removing unnecessary parentheses, adopting optional chaining, and simplifying conditionals in modules such as `abtshieldIdSystem.js`, `jwplayerRtdProvider.js`, `magniteAnalyticsAdapter.js`, `nextMillenniumBidAdapter.js`, `optidigitalBidAdapter.js`, `pubxaiRtdProvider.js`, `reconciliationRtdProvider.js`, `rubiconBidAdapter.js`, `sonobiBidAdapter.js`, and `topicsFpdModule.js`.
- Fix behavior and small bugs such as returning `null` when no `endpoint` is present in `pubxaiRtdProvider.getUrl`, ensuring `platform` is always an object in `getSua`, and updating test messaging behavior to post an object rather than a JSON string.

### Testing

- Ran the automated unit/spec test suite that covers modified tests under `test/spec/*`, including updated `consentManagementUsp_spec.js` and `secureCreatives_spec.js`, and all tests passed.
- Linting was executed against the repository to validate the new rule and code adjustments and completed without errors.

* ESLint Plugin: handle fact invalidation (prebid#15194)

* Fix redundant condition invalidation in blocks (prebid#15204)
* Core: update browserslist target

* Update supported browsers information in README

* Update browser support information in README

Clarify browser support details for Prebid.js.
…n interpretResponse (prebid#15216)

* Add meta category and attribute fields to interpretResponse and tests

* Improve Add tests for meta fields in interpretResponse

* chore: update onetag adapter version to 1.1.8

---------

Co-authored-by: Diego Tomba <d.tomba@onetag.com>
* TTD Bid Adapter: configurable endpointCompression support

Add opt-in GZIP compression of the outgoing bid request via a
ttd.gzipEnabled bidder config, mirroring the Criteo adapter. Defaults
to disabled; accepts a boolean or string and falls back to the default
on invalid values. Core bidderFactory already honors
options.endpointCompression.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* TTD Bid Adapter: honor alias bidder configs for gzip

Read gzipEnabled against the active bidderRequest.bidderCode (e.g. the
`thetradedesk` alias) with a fallback to the canonical `ttd` code, so
the opt-in works for alias traffic. Addresses PR review feedback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e attribute in meta.attr (prebid#15231)

* bidResponseFilter: fix attr enforcement incorrectly expecting a single attribute in meta.attr

* treat empty array as uknown

* better tests

* lint

* flip default for attr.blockUnknown
* Core: catch implicit operand conversions

* Core: catch implicit operand conversions

### Motivation
- A code scan flagged implicit operand conversion patterns (negation used directly in relational comparisons and function/undefined identifiers interpolated into template literals) that can lead to incorrect behavior due to JS coercion.
- Prevent regressions by adding a static lint rule to catch these patterns at authoring time.
- Fix the three existing occurrences discovered by the scan so tests remain green.

### Description
- Add a new ESLint rule `prebid/no-implicit-operand-conversion` in `plugins/eslint/index.js` that reports negated operands used in relational `BinaryExpression`s and identifiers that reference functions or `undefined` when used inside `TemplateLiteral` expressions.
- Enable the new rule in `eslint.config.js` for the source folders using `prebid/no-implicit-operand-conversion: 'error'`.
- Apply three code fixes: replace the undefined template interpolation with an explicit URL generator call in `test/spec/modules/imuIdSystem_spec.js` (`callImuidApi(getApiUrl(5126))`), change `if (!config?.params?.groupId?.length > 0)` to `if (!(config?.params?.groupId?.length > 0))` in `modules/qortexRtdProvider.js`, and change `!et.methods.length > 0` to `et.methods.length <= 0` in `modules/onetagBidAdapter.js`.

### Testing
- Ran `npx eslint modules/qortexRtdProvider.js modules/onetagBidAdapter.js test/spec/modules/imuIdSystem_spec.js --cache --cache-strategy content` and ESLint reported no remaining violations in the touched files.
- Verified the rule behavior with a quick `node - <<'NODE' ... NODE` ESLint snippet check to assert the new rule flags the targeted patterns as expected.
- Ran unit tests for the affected specs with `npx gulp test --nolint --file` and the runs completed successfully: `imuIdSystem_spec.js` (21 tests), `qortexRtdProvider_spec.js` (20 tests), and `onetagBidAdapter_spec.js` (63 tests).

* Core: stop flagging template string conversions (prebid#15198)

* remove duplication

---------

Co-authored-by: Demetrio Girardi <dgirardi@prebid.org>
…#15178)

* Apply suggested fix to plugins/eslint/noExtraFunctionArgs.js from Copilot Autofix

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

* Apply suggested fix to plugins/eslint/noExtraFunctionArgs.js from Copilot Autofix

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

* Remove unused ESLint rule for extra function args

Removed 'prebid/no-extra-function-args' rule from ESLint configuration.

* Fix lint failures from extra test arguments (prebid#15188)

* Core: handle lexical arguments in lint rule (prebid#15200)

* run plugin tests on gulp test

---------

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Demetrio Girardi <dgirardi@prebid.org>
getPreparedBidForAuction dereferenced adUnit.renderer/adUnit.safeRenderer
without optional chaining, while index.getAdUnit(bid) can legitimately
return undefined (e.g. the originating auction has expired out of the
auctionManager TTL collection, or the bid carries an adUnitId matching no
held ad unit). This threw an unhandled
"TypeError: undefined is not an object (evaluating 'i.renderer')" while
accepting the bid, before any rendering, so no adRenderFailed event fired.

Add optional chaining, consistent with the adjacent adUnit?.ortb2Imp /
adUnit?.element / adUnit?.ttlBuffer guards, plus a regression test.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bid#15235)

* Mediago Bid Adapter :  add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago Bid Adapter : add param publisherid

* Mediago/Discovery Bid Adapter:remove request.{}.userID

* Mediago Bid Adapter:remove request.{}.userID

* Mediago Bid Adapter:remove request.{}.userID

* Mediago Bid Adapter:remove request.{}.userID

* Mediago Bid Adapter:udpate banenr.format param key,match ortb

* Mediago Bid Adapter:udpate banenr.format param key,match ortb

* Mediago Bid Adapter:udpate banenr.format param key,match ortb

* Mediago Bid Adapter:udpate banenr.format param key,match ortb

* Mediago Bid Adapter : Compatible parameter gbid data types
* Test Lint: enforce unused variable checks

* Test Lint: clean initial unused variables

* Test Lint: mark unused test bindings

* Test Lint: remove unused test bindings

* Test Lint: preserve PubMatic floor stubs

* Tests: fix chunk3 strict-mode specs (prebid#15169)

* Fix chunk 2 adapter specs (prebid#15170)

* Fix chunk 6 test failures (prebid#15168)

* Weborama RTD Provider: fix onData test callback assertions (prebid#15166)

* Fix AdPlayerPro provider spec setup (prebid#15167)

* Fix chunk 5 adapter tests (prebid#15171)

* Fix chunk 4 module tests (prebid#15172)

* Fix chunk 7 adapter and user ID specs (prebid#15173)

* Fix chunk 1 test failures (prebid#15174)

* Revert "Fix chunk 1 test failures (prebid#15174)" (prebid#15175)

This reverts commit 9ee9e03.

* Fix chunk 1 test failures (prebid#15176)

* Core: fix chunk 8 unit specs (prebid#15180)

* PubMatic Adapter: fix missing playerSize warning test (prebid#15181)

* Test: remove lint suppressions (prebid#15182)

* Tests: restore removed spec actions (prebid#15183)

* Test Lint: fix chunk 8 test stubs (prebid#15184)

* Test Lint: preserve UID2 timer debug context (prebid#15186)

* test: restore removed spec assertions (prebid#15192)

* Adspirit Adapter: restore dimension assertions (prebid#15193)

* Core: restore API spec initialization (prebid#15195) to

* Tests: address remaining review comments (prebid#15196)

* Adspirit Bid Adapter: fix viewport dimensions (prebid#15197)

* Tests: add UID2 optout eid coverage (prebid#15201)

* Revert "Adspirit Bid Adapter: fix viewport dimensions (prebid#15197)" (prebid#15202) c 

This reverts commit 12f3a5a.

* Tests: address review feedback (prebid#15203)

* Tests: address PR 15161 review comments (prebid#15205)

* Adspirit Bid Adapter: fix dimension tests (prebid#15206)

* Reconciliation RTD Provider: restore spec coverage (prebid#15207)

* Admatic Adapter: reuse floor fixtures in tests (prebid#15208)

* Tests: address relevatehealth and rivr review comments (prebid#15209)

* Reconciliation RTD Provider: cover broken frame chain (prebid#15210)

* Adlane RTD Provider: address review comments (prebid#15211)

* Tests: address adapter review comments (prebid#15212)

* Tests: address remaining adapter review comments (prebid#15213)

* Tests: clean stale review comments (prebid#15214)

* Tests: address IntentIQ and Finative review comments (prebid#15217)

* Test gzip CompressionStream constructor probe (prebid#15218)

* Nobid Bid Adapter: restore review test coverage (prebid#15219)

* Tests: address dxtech review comment (prebid#15220)

* Tests: fix dxkulture banner validation case (prebid#15222)

* Nobid Adapter: restore video request fixture (prebid#15223)

* Adspirit Bid Adapter: restore spec CRLF endings (prebid#15224)

* Admatic Adapter: reuse floor test fixtures (prebid#15225)

* Remove deepFreeze utility and associated tests

Removed deepFreeze function and related tests for bid requests.
* medianetAnalyticsAdapter.js Updates

- Disable analytics on consent change signals from prebid
- getPriceGranularity bug fix

* review changes for getPriceByGranularity

* review changes for getPriceByGranularity

* Add fetchAnalyticsConfig tests for logging configuration handling

---------

Co-authored-by: shubham.si <shubham.si@media.net>
Co-authored-by: pratik.ta <143182729+Pratik3307@users.noreply.github.com>
Co-authored-by: Pratik3307 <pratik.ta@media.net>
patmmccann and others added 7 commits August 26, 2026 04:11
…pe declarations (prebid#15428)

* Add bidder parameter type declarations

* Fix bidder parameter declaration coverage

* Complete bidder alias and coordinate types

* AppNexus Bid Adapter: prefer underscore parameter names
* new adapters

* fix linter

* fix comments

---------

Co-authored-by: mderevyanko <mderevyanko24@gmail.com>
* RTB House Bid Adapter: migrate to ortbConverter

* RTB House Bid Adapter: keep site as the only ORTB client section

* RTB House Bid Adapter: fix missing comma in native test params example
…dance (prebid#15542)

* Build system: cache the precompilation babel pass

`gulp precompile` re-transpiled the whole source tree on every cold invocation.
`gulp.lastRun` is per-process state, so the existing `since:` filters made
`watch` / `serve-*` incremental and did nothing for a fresh CLI run. Babel was
~16s of a ~20s precompile.

Cache it on disk, per file, keyed on the file's contents and on the build
configuration - so that repeat runs are cheap without anyone needing to know a
cache exists: no new flags, no hygiene rules, and no obligations on steps added
later.

- gulp.cache.js: `cachedPipeline` splits the source stream into hits and
  misses, runs the transform on misses only, and merges the hits back in before
  `dest`. The source glob still decides which files exist, so a stale entry in
  the cache is never enumerated - pruning it is disk housekeeping, not
  correctness.
- `precompilationKey` is both what `babelPrecomp` memoizes on and the name of
  its cache directory, so the two cannot drift apart. It hashes the resolved
  options, since `disableFeatures`, `distUrlBase` and `polyfills` all default
  from `argv`.
- `dist/src` is now built whole from empty on every cold run, which makes
  orphaned output structurally impossible. Previously a deleted module kept its
  `dist/src/public` entry point - which ships - a deleted spec kept running via
  `require.context`, and a stale `.d.ts` stayed in the public type summary. The
  wipe is skipped when this process has already precompiled, so `watch` and
  `serve-*` behave exactly as before.
- tsconfig.json: move the `tsc --incremental` buildinfo out of `outDir`, where
  the wipe would delete it and `ts-dev` would silently do a full compile.
- generateTypeSummary: sort the globbed declarations, so the summaries no
  longer vary with directory order now that the tree is rebuilt each run.

Cold `gulp precompile` is unchanged at ~21s; warm is ~5.6s. Warm output is
byte-identical to cold, and identical to master's except for the two type
summaries that are now sorted (same imports, stable order).

gulp lint: passes.
gulp test-build-logic: 39 passing, including 7 new specs for `cachedPipeline`.
gulp test-only-nobuild: 24386 passing.
gulp test-all-features-disabled-nobuild: 23820 passing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Build system: keep caches out of `clean`, key webpack caches by configuration

`clean` deleted `.cache` along with `build` and `dist`, so every task starting with
it - `test`, `test-coverage`, all four `serve*`, `serve-e2e*`, `e2e-test` - discarded
the precompilation, webpack and babel-loader caches before anything could use them.
`clean` now leaves them alone, and a new `clean-cache` removes them deliberately,
which is what a change to the build system itself calls for.

Caches surviving `clean` then exposed a pre-existing bug. `dist/src` holds one
feature variant at a time, at the same paths, and `gulp.dest` carries each source
file's mtime over - so two variants are indistinguishable to webpack, and it served
modules compiled from whichever variant it saw first. `gulp test` was already
exposed, building both variants in one invocation with a single `clean`.

Every cache is now keyed on the build configuration. `precompilationKey` moves into
gulp.cache.js, which owns how the build is keyed; precompilation stamps the tree it
produces with that key; webpack.common.js versions the bundle caches on it, plus
`--ES5`, which decides the loader rules it adds; and karma versions
`.cache/webpack-test` on the stamp rather than on argv, since
`test-all-features-disabled` and `serve-and-test` set the variant directly where
argv cannot see it. An unstamped tree disables the karma cache rather than risk
reusing the wrong entries.

Verified for both webpack passes, each against a control confirming the two variants
do produce different output: building variant B with the cache warmed by variant A
now yields byte-identical output to building B cold, where before it yielded A's.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Build system: let `gulp lint` take a file subset

`gulp lint` could only lint the whole repo, so linting a few changed files meant
calling eslint directly - and a bare `npx eslint` without `--cache` *deletes*
.eslintcache, making the next full run pay for a rebuild. `gulp lint --files a,b`
lints a subset with the cache flags already applied; comma separated, the same shape
as `--modules`.

Calling eslint directly stays perfectly fine, and CI deliberately keeps doing so: it
starts from a fresh checkout with no cache to lose, and it keeps eslint.config.js
authoritative rather than letting lint configuration accumulate in this task.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Build system: emit declarations into the cache, and always incrementally

`tsc` emitted declarations into `dist/src` while its buildinfo lived under `.cache`,
so the two disagreed the moment `precompile` emptied `dist/src`: with a warm
buildinfo tsc skipped emitting declarations it believed it had already written, and
the tree ended up with 118 of 379.

It escaped because only `ts-dev` was incremental, so the partial emit happened on the
dev path alone - and the dev series omits `ts-strict` and `check-declarations`
entirely. Had `check-declarations` run it would have caught this: the missing set
includes the core entry it resolves, and it errors outright when that is absent. What
it would *not* have caught is a partial set elsewhere - removing 132 module
declarations by hand leaves it passing - so it guards the entry point, not the
completeness of the type surface.

`outDir` now sits beside the buildinfo under `.cache/ts`, so tsc's outputs and its
incremental state survive the wipe together, and `precompile` copies the declarations
into `dist/src` afterwards. Same shape as the babel cache: build into the cache,
materialise into the tree.

The copy is driven by the sources, not by the cache: tsc never deletes an output whose
input is gone, so copying wholesale would restore orphan declarations that
`check-declarations` type-checks and `generateTypeSummary` imports, keeping deleted
modules in the published type surface. What gets skipped is logged, because the test -
does `<name>.ts` exist on disk - would also skip a `.ts` generated during the build,
and that case is a missing declaration rather than housekeeping.

`ts` and `ts-dev` collapse into one always-incremental task; with the buildinfo
coherent there is nothing for a non-incremental variant to protect against. The gain
is a pre-warmed local build - CI starts from a fresh checkout and restores no `.cache`,
so it is unaffected.

Measured: 379 declarations with a cold buildinfo, a warm buildinfo over a wiped tree,
and on the dev path; `tsc` 2.3s cold and ~0.5s warm; a warm prod `precompile` 3.3s,
down from 4.5s.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Documentation: rewrite the agent command guidance

The command instructions were spread across three sections that contradicted each
other, and several were wrong. Verified against the build rather than transcribed:

- "Use `gulp serve-and-test --file <spec>` or `gulp test --file` so Babel processes
  only the specified files" was false on both counts. Both tasks begin with `clean`
  and a whole-tree precompile; `--file` is read only by the karma config, where it
  selects which specs to load. And `serve-and-test` runs karma with
  `singleRun: false`, so it never exits - an agent told to use it for a check hangs.
- `gulp test --file <spec>` was recommended per changed spec. It is the slowest way to
  run one spec (`clean`, a repo-wide auto-fixing lint, two precompiles, the spec
  twice) and it cannot validate anything: with `--file`, karma loads only that spec,
  so nothing about specs leaking global state is exercised - which is what CI checks.
- `gulp review-start` was removed in prebid#13501.
- `submodules.json` does not exist; it is `modules/.submodules.json`, and only
  submodules of `userId`, `rtdModule`, `fpdModule` and `videoModule` register there.
- The three core type-reference paths are TypeScript now, so every documented path
  404s: `src/adapterManager.ts`, `src/adapters/bidderFactory.ts`, `src/userSync.ts`.
- `TEST_CHUNKS` was described as something to switch on; it is on by default, its
  three siblings were undocumented, and all four are ignored when `--file` is given.
- "Do not submit pr's with changes to creative.html or creative.js" named nothing that
  exists - no `creative.js` has been tracked since prebid#955. Generalised to the actual
  rule: do not hand-edit tracked generated files, because `gulp build-release`
  regenerates and commits them. Each one says so in its opening lines, so the rule
  leans on that notice rather than on a list that will rot.

The three sections are replaced by one table of what to run per goal, plus a list of
the traps. Two of those are newly documented: `--coverage=false` silently *enables*
coverage (yargs yields the string "false", which is truthy), and `--disable VIDEO`
also switches `GREEDY` back on, because the list replaces the default rather than
adding to it.

Coverage had a threshold stated in three places and no method stated anywhere, and
both documented report paths were wrong. The table now carries a measured procedure,
and distinguishes "is my change covered" - one spec, one lcov file - from "does this
file meet 80%", which needs the chunks merged, because a file is exercised by specs in
different chunks and any single chunk understates it.

Durations are gone throughout. They were wrong in the direction that matters - the
file told agents to budget fifteen minutes and poll - and any number written today
goes stale; the caching work this week moved one of them fourfold. Relative cost and
the reason for it are stated instead.

Where facts have an owner elsewhere they are linked, not restated: the release and
SemVer labels now point at PR_REVIEW.md, which is how `bugfix` came to be missing
here. Commands go the other way - this file says it is authoritative for them, because
CONTRIBUTING.md and PR_REVIEW.md still carry stale ones.

This PR deliberately breaks the rule against changing root `.md` files, which is the
only way to fix that file. The rule now states its own exception, so a reviewer can
tell drift from repair.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Build system: test the precompilation cache key and declaration copy

Both of these fail quietly when they break, which is the argument for covering them:
a key that stops distinguishing two builds lets webpack serve one variant's modules
to the other, and a declaration copy that stops skipping orphans puts deleted modules
back into the published type surface. Neither shows up as a failing build.

`precompilationKey` is checked against every input the output depends on - the feature
set and its ordering, dev vs production, the chunk URL base, and `LiveConnectMode`,
which plugins/pbjsGlobals.js substitutes into the emitted code. The stamp is checked
for the round trip and for reading as null on an unstamped tree, which is what makes
karma turn its filesystem cache off rather than key on nothing.

`copyDeclarations` is checked for copying a declaration whose source is present,
skipping one whose source is gone, and leaving the orphan in the cache rather than
deleting it. It needed exporting to be reachable from a test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Build system: make karma's webpack cache work, for single-spec runs

`.cache/webpack-test` was configured but never written. Nothing closes the compiler
in a single run - karma-webpack registers `compiler.close()`, which is what flushes
the cache, only on its watch branch, and that branch needs `watch: true` in the
webpack options, which karma-webpack's own defaults set to false. So the only path to
disk is webpack's idle timer, whose initial store defaults to 5s, and a `--file` run
finishes in about two seconds and then exits through `karmaRunner`'s `process.exit()`.
The cache was therefore populated only by long multi-chunk runs and never by the fast
loop it would help. Zeroing the idle timeouts fixes that: a single spec compiles in
~170ms warm against ~715ms cold.

Restricted to `--file` runs, because a store rewrites the cache for the compilation
that just ran. The full suite is eight compilations that between them grow it to
~800MB while saving under 10% (76s to 69s), and the two patterns evict each other -
measured before this restriction, a single spec after a full suite compiled in 240ms
rather than 170ms, and a full suite after a single spec pushed 33MB to 345MB. Gated,
the cache stays at 33MB and a full suite leaves it untouched.

The flag has to be passed explicitly: for a full run `karmaRunner` hands each chunk of
the suite to `karmaConfMaker` through the same `file` argument that carries a single
spec, so the config cannot tell the two apart - both arrive as arrays.

Watch mode keeps webpack's default timeouts: that process lives long enough for them
to fire on their own, and storing after every rebuild would put the cache write into
the save loop.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Build system: fix three cache defects found in review

**`gulp test` was broken.** It precompiles two feature variants back to back in one
process, and `cleanPrecompiled` wiped `dist/src` for each of them. The second wipe
emptied the tree while `copyVerbatim`, `generateMetadataModules`,
`generatePublicModules` and `generateCreativeRenderers` were all holding
`gulp.lastRun(...)` timestamps from the first pass, so they saw unchanged inputs and
skipped, and nothing put the `.json` files, metadata modules or public modules back.
It failed on the first casualty - `generateGlobalDef` writing into a directory that no
longer existed. The wipe now happens once per process: it exists to sweep orphans out
of a tree left by an *earlier* run, and a variant switch does not need it, because
everything configuration-dependent is rebuilt regardless while everything else is
already correct on disk.

**The cache key missed Babel's external inputs.** `plugins/pbjsGlobals.js` substitutes
`package.json`'s version into the output, and `plugins/callerContext.js` and
`plugins/gvlPurposes.js` read `metadata/modules/*.json` - so a change to either altered
what was emitted while leaving every source file's own content hash untouched, and a
release build on a warm cache would have emitted the previous version number. Both are
now digested into the key, whole rather than field by field: keying on the fields in use
today would invalidate less often but would quietly stop covering a plugin that starts
reading something else, and that failure is silent. `build-release` and
`prepare-release` also begin with `clean-cache`, so the paths that publish never depend
on the key being complete.

**`--polyfills` produced a partial report.** `plugins/polyfills.js` accumulates across
every file it visits and writes a summary of the lot, which is not the pure per-file
transform `cachedPipeline` requires: only misses reach Babel, so the summary covered
just those, or was absent entirely when every file hit. That build now bypasses the
cache. Only `build-metadata.yml` passes the flag, so the exposure was CI-only.

Tests: `externalInputsDigest` is exercised through injected paths against a scratch
tree, so nothing touches `package.json` or `metadata/`, plus one check that the real
digest is carried in the real key.

Verified: `gulp test` exits 0 with both passes intact (23,820 and 24,386 tests);
`gulp build --polyfills` twice yields an identical 1,371-file summary; a warm
`precompile` is still ~3s; `gulp test-build-logic` 56 passing; lint clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* nice try

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@MO-Thibault
MO-Thibault force-pushed the mo/userid-refresh-preserves-pending-init branch from 768d538 to 3d99ab3 Compare August 28, 2026 22:02
@github-actions

Copy link
Copy Markdown

Tread carefully! This PR adds 3 linter errors (possibly disabled through directives):

  • libraries/pubmaticUtils/plugins/floorProvider.js (+1 error)
  • modules/showheroes-bsBidAdapter.js (+1 error)
  • src/creativeRenderers.js (+1 error)

refreshUserIds({submoduleNames}) replaces the pending init chain with one
scoped to the named submodules. cancelAndTry rejects the previous cancel
deferred first, so the old `done` (a race that includes cancel.promise)
settles immediately and the new chain's `done.catch(() => null)` sails past
it without waiting for the work still in flight.

The new chain then waits only on initSubmodules for the named submodules,
which for something like pubProvidedId is a synchronous storage read. So
getUserIdsAsync resolves while unnamed submodules are still fetching, and
startAuctionHook releases the auction against auctionDelay that has not
elapsed.

That contradicts getUserIdsAsync's documented contract, which promises to
resolve 'only once all ID submodules have completed initialization', and
startAuctionHook is its main internal consumer.

Observed on a publisher running userSync.auctionDelay = 300 with liveIntentId
and pubProvidedId. A pubProvidedId-only refresh during page load released the
first auction about 300ms early, before liveIntentId's network call returned,
dropping its EIDs from that auction entirely. Measured in an instrumented
browser: LiveIntent present on the first auction in 0 of 9 runs with the
refresh against 8 of 9 without it.

Track pending callbacks per submodule rather than as one blob, and have
getUserIdsAsync await the ones still outstanding. A refresh supersedes the
entries for the modules it names, so an unfiltered refreshUserIds() clears
them all and keeps its existing behaviour of unblocking a stuck init.

refreshUserIds' own return value is unchanged.
@MO-Thibault
MO-Thibault force-pushed the mo/userid-refresh-preserves-pending-init branch from 3d99ab3 to 3fa5e1b Compare August 28, 2026 22:21
@github-actions

Copy link
Copy Markdown

Tread carefully! This PR adds 3 linter errors (possibly disabled through directives):

  • libraries/pubmaticUtils/plugins/floorProvider.js (+1 error)
  • modules/showheroes-bsBidAdapter.js (+1 error)
  • src/creativeRenderers.js (+1 error)

@github-actions

Copy link
Copy Markdown

Tread carefully! This PR adds 3 linter errors (possibly disabled through directives):

  • libraries/pubmaticUtils/plugins/floorProvider.js (+1 error)
  • modules/showheroes-bsBidAdapter.js (+1 error)
  • src/creativeRenderers.js (+1 error)

anna-y-perion and others added 8 commits August 31, 2026 10:33
* updating request url subdomain

* fixing test

---------

Co-authored-by: Anna Yablonsky <annay+perion@perion.com>
…aliases (prebid#15555)

The prismassp and scoremedia white-label aliases declared Nexx360's own
GVL ID (965) instead of their own registered GVL IDs (1185 for Prisma
Media, 1090 for Score Media Group), verified against the live IAB GVL
(https://vendor-list.consensu.org/v3/vendor-list.json). This causes
Prebid's TCF consent/activity-control checks to evaluate GDPR consent
for the wrong vendor for these two aliases.

Adds a regression test asserting spec.aliases carries the correct
gvlid for both aliases, verified to fail against the unmodified code
and pass with the fix.
…tor/window (prebid#15548)

buildRequests populated payload.device.ua/height/width/language directly
from navigator.userAgent, window.screen.height/width, and
navigator.language.

Prebid core's FPD enrichment (src/fpd/enrichment.ts) already populates
bidderRequest.ortb2.device.{ua,w,h,language} on every bid request from
the same sources, so this was duplicating information core already
provides rather than reading it - the pattern the Module Rules (2.3)
and several other adapters (consumable, engerio, targetVideo, yieldmo,
etc.) already follow via bidderRequest.ortb2.device.

Reads from bidderRequest.ortb2.device instead. No change to the shape
or semantics of payload.device sent to the endpoint.

Related to prebid#11001, which asks
that core-provided device info be used instead of adapters accessing
navigator/window directly; this migrates one adapter as a scoped first
step rather than attempting the full sweep across all affected adapters
in one PR.
…data block merge collapse (prebid#15319)

* Stackup RTD Module: disclose sessionStorage cache keys

* Stackup RTD Provider: fix merge collapse of same-name ortb2 data blocks

Distinguish site.content.data and user.data blocks by name + segtax +
dimension instead of name alone. StackUP emits multiple blocks under a
single provider name (e.g. several segtax:501 user dimensions all named
data.stackup-ai.com); keying on name alone caused siblings to overwrite
each other, leaving only the last block.

* Stackup RTD Provider: accept segtax allowlist (4, 501, 502, 600)

Replace the strict segtax === 502 check with an allowlist of the
taxonomies StackUP emits: 4 (IAB Audience), 501 (legacy audience),
502 (content), 600 (publisher FPD). Validation now skips blocks with an
unrecognised segtax instead of rejecting the whole payload, and such
blocks are filtered out before merge so only allowlisted taxonomies
reach ortb2. Broaden the segtax type to a StackupSegtax union and update
tests and docs to cover the 600/4 blocks and the drop-unknown behavior.

* pass through data with segtax 7 and mirror into legacy fields if permitted

* accept all segtax categories from the backend

* stackupRtdProvider: implement review findings

* stackupRtdProvider: guard site.cattax across cat/sectioncat, validate segtax positivity

---------

Co-authored-by: Nicolas Kogler <nicolas@stackup-ai.com>
* Update tests for sspBC adapter

Update tests for sspBC adapter:
- change userSync test (due to tcf param appended in v4.6)
- add tests for onBidWon and onTimeout

* [sspbc-adapter] 5.3 updates: content-type for notifications

* [sspbc-adapter] pass CTA to native bid

* [sspbc-5.3] keep pbsize for detected adunits

* [maintenance] - remove old test for sspBc bid adaptor

* [sspbc-5.3] increment adaptor ver

* [sspbc-adapter] maintenance update to sspBCBidAdapter

* remove yarn.lock

* Delete package-lock.json

* remove package-lock.jsonfrom pull request

* [sspbc-adapter] send pageViewId in request

* [sspbc-adapter] update pageViewId test

* [sspbc-adapter] add viewabiility tracker to native ads

* [sspbc-adapter] add support for bid.admNative property

* [sspbc-adapter] ensure that placement id length is always 3 (improves matching response to request)

* [sspbc-adapter] read publisher id and custom ad label, then send them to banner creative

* [sspbc-adapter] adlabel and pubid are set as empty strings, if not present in bid response

* [sspbc-adapter] jstracker data fix

* [sspbc-adapter] jstracker data fix

* [sspbc-adapter] send tagid in notifications

* [sspbc-adapter] add gvlid to spec; prepare getUserSyncs for iframe + image sync

* update remote repo

* cleanup of grupawp/prebid master branch

* update sspBC adapter to v 5.9

* update tests for sspBC bid adapter

* [sspbc-adapter] add support for topicsFPD module

* [sspbc-adapter] change topic segment ids to int

* sspbc adapter -> update to v6

* [gopl-adapter] new adapter for Gopl (former sspBC)

* [WIP] Go.pl bid adapter

* [gopl-adapter] publisherID, video cache, events

* [gopl-adapter] update description

* [gopl-adapter] handle burl

* [gopl-adapter] - cosmetic fixes

* [gopl-adapter] revert unrelated metadata/dependency drift

`gulp update-metadata` was run as part of the sspBC->gopl rename, which
regenerated metadata for every module (not just gopl/sspBC) and picked up
pre-existing staleness in master (playstream, wurfl entries). Restore all
of that to master's state, keeping only the gopl/sspBC-related metadata
changes. Also drop an unrelated `gulp-cli` dependency addition and its
package-lock.json fallout - gulp itself is already a devDependency.

* [gopl-adapter] - CR fixes

* [gopl-adapter] - CR fixes

* Gopl Adapter: add tests to cover previously untested branches

Covers native ads sent via admNative, burl propagation, local-storage
stac handling, top-level window access failures, OneCode detection
override with cpm-derived notification fields, the sync-iframe
postMessage handshake, and the onBidderError/onBidViewable/
onAdRenderSucceeded/onSetTargeting callbacks, none of which had any
test coverage. Exports `storage` so tests can stub it, matching the
pattern used by other adapters.

* [gopl-adapter-dev] send bidid identifier in adapter-generated notifications

* [gopl-adapter-dev] - unit tests

* Gopl Adapter: restore sspBCBidAdapter.js as a backward-compat shim, add typed params

- modules/sspBCBidAdapter.js re-exports spec/storage from goplBidAdapter.js so
  publishers building with --modules=sspBCBidAdapter still get a working bundle
  now that sspBC is registered as an alias of gopl.
- modules/goplBidAdapter.d.ts types the bidder params (id, siteId) for both
  gopl and sspBC.
- metadata/overrides.mjs maps sspBCBidAdapter -> sspBC so `gulp update-metadata`
  can attribute the alias component to the right module file; regenerated
  metadata/modules/{goplBidAdapter,sspBCBidAdapter}.json via the real tool
  instead of hand-editing them.

* Gopl Adapter: address review feedback (alias GVL ID, native shape, FPD passthrough)

- Revert hand-regenerated metadata/modules/{goplBidAdapter,sspBCBidAdapter}.json;
  these are build output and shouldn't be part of the PR diff (per review).
- Preserve GVL ID 690 on the sspBC alias by declaring it as
  { code: 'sspBC', gvlid: GVLID } instead of a plain string, so TCF consent
  checks correctly associate it with vendor 690.
- applyClientHints() now appends to ortbRequest.user.data instead of replacing
  it, so FPD already merged in by the shared ortbConverter (e.g. Topics
  segments) isn't dropped.
- Recognize and normalize native adm payloads wrapped as
  `{ native: { assets: [...] } }` (in addition to the root-level shape this
  backend sends), using the shared safeJSONParse utility instead of a local
  try/catch.
- Document the bc_stac local storage usage in goplBidAdapter.md.
- Add/adjust tests for all of the above.

* Gopl Adapter: stop accessing navigator directly, trim comments

- Replace navigator.connection with getConnectionInfo() from
  libraries/connectionInfo/connectionUtils.js.
- Drop navigator.userAgentData entirely; use device.sua, already populated
  on the request by core FPD enrichment, instead.
- Add a test covering the "adm can't be parsed as native despite admNative
  being present" warning branch.
- Trim comments added in prior commits per feedback.

---------

Co-authored-by: wojciech-bialy-wpm <67895844+wojciech-bialy-wpm@users.noreply.github.com>
Co-authored-by: Wojciech Biały <wb@WojciechBialy.local>
Co-authored-by: Wojciech Biały <wojciech.bialy@grupawp.pl>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Tread carefully! This PR adds 4 linter errors (possibly disabled through directives):

  • libraries/pubmaticUtils/plugins/floorProvider.js (+1 error)
  • modules/showheroes-bsBidAdapter.js (+1 error)
  • modules/sspBCBidAdapter.js (+1 error)
  • src/creativeRenderers.js (+1 error)

A module whose refreshed getId resolves synchronously, returns no callback,
or throws was excluded from cbModules, so trackCallbacks never replaced or
removed its earlier pendingByModule entry. getUserIdsAsync then waited on a
callback the refresh had already replaced, which also undid the escape from
a stuck initialization that an unfiltered forced refresh has always given.

Clear the entries for every module the refresh names before tracking the
callbacks it does return. Reported by Codex review.
@github-actions

Copy link
Copy Markdown

Tread carefully! This PR adds 4 linter errors (possibly disabled through directives):

  • libraries/pubmaticUtils/plugins/floorProvider.js (+1 error)
  • modules/showheroes-bsBidAdapter.js (+1 error)
  • modules/sspBCBidAdapter.js (+1 error)
  • src/creativeRenderers.js (+1 error)

Two follow-ups from review, both the same flaw as the first: pendingByModule
did not participate in cancellation.

A batch promise settles only once every module in it has called back, so an
entry pointing at the batch kept the others hostage: superseding A could not
release B. processSubmoduleCallbacks now reports per-module completion and
each module gets its own deferred.

A superseded entry is resolved rather than dropped, so a caller that already
captured it is released instead of waiting on work the refresh replaced, and
getUserIdsAsync rechecks the pending set after each wait instead of trusting
the snapshot it took.

Reported by Codex review.
@github-actions

Copy link
Copy Markdown

Tread carefully! This PR adds 4 linter errors (possibly disabled through directives):

  • libraries/pubmaticUtils/plugins/floorProvider.js (+1 error)
  • modules/showheroes-bsBidAdapter.js (+1 error)
  • modules/sspBCBidAdapter.js (+1 error)
  • src/creativeRenderers.js (+1 error)

…at discovery

Two more from review. A stale callback settled by module name, so a
callback from a superseded generation could resolve the entry a later
refresh had just created; entries are now bound to the generation that
created them. And entries were only registered when callbacks started
running, which with auctionDelay = 0 is after AUCTION_END plus syncDelay,
leaving a window where a refresh saw nothing pending; they are now
registered as soon as the callbacks are discovered.

Also stop a cancelled refresh inheriting getUserIdsAsync's wait for other
submodules: retryOnCancel now retries the init chain rather than routing
through getUserIdsAsync, which is a contract only its own callers want.
@github-actions

Copy link
Copy Markdown

Tread carefully! This PR adds 4 linter errors (possibly disabled through directives):

  • libraries/pubmaticUtils/plugins/floorProvider.js (+1 error)
  • modules/showheroes-bsBidAdapter.js (+1 error)
  • modules/sspBCBidAdapter.js (+1 error)
  • src/creativeRenderers.js (+1 error)

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.