Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
1b5f090
RPRS-3986: previousAuctionInfo data
michachen Jul 9, 2025
16a7167
RPRS-3986: previousAuctionInfo data
michachen Jul 9, 2025
0013fc8
Prebid 10.1.0 release
prebidjs-release Jul 9, 2025
820c6b0
Increment version to 10.2.0-pre
prebidjs-release Jul 9, 2025
31d1044
Core: remove circleci from merges and pulls (#13551)
patmmccann Jul 9, 2025
b213bda
Colossus Bid Adapter: use shared utils (#13511)
patmmccann Jul 9, 2025
73926f3
supports cids outside of ext (#13553)
karimMourra Jul 9, 2025
e257303
removes redundant content.value (#13552)
karimMourra Jul 9, 2025
397a20a
ortbConverter: accept null responses (#13558)
dgirardi Jul 9, 2025
c9c8eb8
storageControl: improve metadata generation (#13557)
dgirardi Jul 10, 2025
a7fa059
userId: alias requests' `.userIdAsEids` to `ortb2.user.ext.eids` (#13…
dgirardi Jul 10, 2025
481af2c
feat(): debug mode query parameter support (#13547)
pb-pete Jul 10, 2025
c20fee1
invibesBidAdapter: optimize keyword parsing (#13460)
patmmccann Jul 10, 2025
7203d19
Linting: remove exception (#13518)
patmmccann Jul 10, 2025
03addf7
Build system: fix linter GH action (#13561)
dgirardi Jul 10, 2025
c1e56e9
Build system: fix CI to run on the correct commit on PRs (#13563)
dgirardi Jul 10, 2025
3d22c15
Build system: update coveralls report (#13564)
dgirardi Jul 11, 2025
cb88b60
OptimizeRx Bid Adapter: initial release (#13443)
suruvu Jul 11, 2025
b0a5ebb
Test suite: enable no-redeclare rule for tests (#13568)
patmmccann Jul 11, 2025
4796fbf
Test suite: enable import/no-duplicates and precision check in lintin…
patmmccann Jul 11, 2025
585c8ef
Merge remote-tracking branch 'refs/remotes/upstream/master' into RPRS…
michachen Jul 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
113 changes: 7 additions & 106 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,111 +1,12 @@
# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#

aliases:
- &environment
docker:
# specify the version you desire here
- image: cimg/node:20.14.0
resource_class: medium
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/mongo:3.4.4
working_directory: ~/Prebid.js

- &restore_dep_cache
keys:
- v1-dependencies-{{ checksum "package.json" }}

- &restore_babel_cache
keys:
- v1-babel-cache-{{ checksum "package.json" }}

- &save_dep_cache
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}

- &save_babel_cache
paths:
- .cache
key: v1-babel-cache-{{ checksum "package.json" }}

- &install
name: Install gulp cli
command: sudo npm install -g gulp-cli

- &run_unit_test
name: BrowserStack testing
command: gulp test --browserstack --nolintfix --nolint

- &run_endtoend_test
name: BrowserStack End to end testing
command: gulp e2e-test

- &unit_test_steps
- checkout
- restore_cache: *restore_dep_cache
- restore_cache: *restore_babel_cache
- run: npm ci
- save_cache: *save_dep_cache
- save_cache: *save_babel_cache
- run: *install
- run: *run_unit_test

- &endtoend_test_steps
- checkout
- restore_cache: *restore_dep_cache
- restore_cache: *restore_babel_cache
- run: npm install
- save_cache: *save_dep_cache
- save_cache: *save_babel_cache
- run: *install
- run: *run_endtoend_test

version: 2
version: 2.1
jobs:
build:
<<: *environment
steps: *unit_test_steps
serial-group: "browserstack"

lint:
<<: *environment
noop:
docker:
- image: cimg/base:stable
steps:
- checkout
- restore_cache: *restore_dep_cache
- run: npm ci
- save_cache: *save_dep_cache
- restore_cache:
keys:
- eslint-cache-{{ checksum "package-lock.json" }}-{{ checksum "eslint.config.js" }}-{{ checksum ".gitignore" }}
- run:
name: 'Run ESLint'
command: echo 'linting ...' && npx eslint --cache --cache-strategy content
- save_cache:
key: eslint-cache-{{ checksum "package-lock.json" }}-{{ checksum "eslint.config.js" }}-{{ checksum ".gitignore" }}
paths:
- .eslintcache

e2etest:
<<: *environment
steps: *endtoend_test_steps
serial-group: "browserstack"

- run: echo "CircleCI build skipped - using GitHub Actions. This job can be removed once 9.x is no longer supported."
workflows:
version: 2
commit:
default:
jobs:
- lint
- build:
requires:
- lint
- e2etest:
requires:
- build

experimental:
pipelines: true
- noop
38 changes: 35 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,41 @@ jobs:
name: "Check out source and install dependencies"
timeout-minutes: 2
runs-on: ubuntu-latest
outputs:
ref: ${{ steps.info.outputs.ref }}
commit: ${{ steps.info.outputs.commit }}
branch: ${{ steps.info.outputs.branch }}
fork: ${{ steps.info.outputs.fork }}
base-branch: ${{ steps.info.outputs.base-branch }}
base-commit: ${{ steps.info.outputs.base-commit }}
steps:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Checkout code
- name: Checkout code (PR)
id: checkout-pr
if: ${{ github.event_name == 'pull_request_target' }}
uses: actions/checkout@v4
with:
ref: refs/pull/${{ github.event.pull_request.number }}/head

- name: Checkout code (push)
id: checkout-push
if: ${{ github.event_name == 'push' }}
uses: actions/checkout@v4

- name: Commit info
id: info
run: |
echo ref="${{ steps.checkout-pr.outputs.ref || steps.checkout-push.outputs.ref }}" >> $GITHUB_OUTPUT
echo commit="${{ steps.checkout-pr.outputs.commit || steps.checkout-push.outputs.commit }}" >> $GITHUB_OUTPUT
echo branch="${{ github.head_ref || github.ref }}" >> $GITHUB_OUTPUT
echo fork="${{ (github.event.pull_request && github.event.pull_request.head.repo.owner.login != github.repository_owner) && github.event.pull_request.head.repo.owner.login || null }}" >> $GITHUB_OUTPUT
echo base-branch="${{ github.event.pull_request.base.ref || github.ref }}" >> $GITHUB_OUTPUT
echo base-commit="${{ github.event.pull_request.base.sha || github.event.before }}" >> $GITHUB_OUTPUT

- name: Install dependencies
run: npm ci

Expand All @@ -51,7 +77,8 @@ jobs:
key: source-${{ github.run_id }}
fail-on-cache-miss: true
- name: lint
run: npx eslint
run: |
npx eslint

test-no-features:
name: "Unit tests (all features disabled)"
Expand Down Expand Up @@ -106,7 +133,7 @@ jobs:

coveralls:
name: Update coveralls
needs: test
needs: [checkout, test]
runs-on: ubuntu-latest
steps:
- name: Restore working directory
Expand All @@ -117,3 +144,8 @@ jobs:
fail-on-cache-miss: true
- name: Coveralls
uses: coverallsapp/github-action@v2
with:
git-branch: ${{ needs.checkout.outputs.fork && format('{0}:{1}', needs.checkout.outputs.fork, needs.checkout.outputs.branch) || needs.checkout.outputs.branch }}
git-commit: ${{ needs.checkout.outputs.commit }}
compare-ref: ${{ needs.checkout.outputs.base-branch }}
compare-sha: ${{ needs.checkout.outputs.base-commit }}
2 changes: 1 addition & 1 deletion PR_REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ General gulp commands include separate commands for serving the codebase on a bu
- Checkout the branch (these instructions are available on the GitHub PR page as well).
- Verify PR is a single change type. Example, refactor OR bugfix. If more than 1 type, ask submitter to break out requests.
- Verify code under review has at least 80% unit test coverage. If legacy code doesn't have enough unit test coverage, require that additional unit tests to be included in the PR.
- Verify tests are green in circle-ci + local build by running `gulp serve` | `gulp test`
- Verify tests are green in Github Actions + local build by running `gulp serve` | `gulp test`
- Verify no code quality violations are present from linting (should be reported in terminal)
- Make sure the code is not setting cookies or localstorage directly -- it must use the `StorageManager`.
- Review for obvious errors or bad coding practice / use best judgement here.
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
[![Build Status](https://circleci.com/gh/prebid/Prebid.js.svg?style=svg)](https://circleci.com/gh/prebid/Prebid.js)
[![Percentage of issues still open](http://isitmaintained.com/badge/open/prebid/Prebid.js.svg)](https://isitmaintained.com/project/prebid/Prebid.js "Percentage of issues still open")
[![Coverage Status](https://coveralls.io/repos/github/prebid/Prebid.js/badge.svg?branch=master)](https://coveralls.io/github/prebid/Prebid.js?branch=master)

Expand Down
2 changes: 1 addition & 1 deletion RELEASE_SCHEDULE.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Announcements regarding releases will be made to the #prebid-js channel in prebi

### 2. Make sure all browserstack tests are passing

On PR merge to master, CircleCI will run unit tests on browserstack. Checking the last CircleCI build [here](https://circleci.com/gh/prebid/Prebid.js) for master branch will show you detailed results.**
On PR merge to master, Github Actions will run unit tests on browserstack. Checking the last build for master branch will show you detailed results.**

In case of failure do following,
- Try to fix the failing tests.
Expand Down
7 changes: 1 addition & 6 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ module.exports = [
'no-empty': 'off',
'no-void': 'off',
'array-callback-return': 'off',
'import-x/no-named-default': 'off',
'prefer-const': 'off',
'no-prototype-builtins': 'off',
'object-shorthand': 'off',
Expand Down Expand Up @@ -237,12 +236,8 @@ module.exports = [
'no-unused-vars': 'off',
'import/extensions': 'off',
'camelcase': 'off',
'import-x/no-duplicates': 'off',
'no-loss-of-precision': 'off',
'no-redeclare': 'off',
'no-global-assign': 'off',
'default-case-last': 'off',
'@stylistic/no-trailing-spaces': 'error',
'default-case-last': 'off'
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion integrationExamples/gpt/x-domain/creative.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// creative will be rendered, e.g. GAM delivering a SafeFrame

// this code is autogenerated, also available in 'build/creative/creative.js'
<script>(()=>{"use strict";const e="Prebid Event",n=(()=>{const e={frameBorder:0,scrolling:"no",marginHeight:0,marginWidth:0,topMargin:0,leftMargin:0,allowTransparency:"true"};return(n,t)=>{const r=n.createElement("iframe");return Object.entries(Object.assign({},t,e)).forEach((e=>{let[n,t]=e;return r.setAttribute(n,t)})),r}})();function t(e){return!!e.frames.__pb_locator__}window.pbRender=function(r){let o=r.parent;try{for(;o!==r.top&&!t(o);)o=o.parent;t(o)||(o=r.parent)}catch(e){}return function(t){let{adId:s,pubUrl:i,clickUrl:a}=t;const c=new URL(i,window.location).origin;function d(e,n,t){const r=new MessageChannel;r.port1.onmessage=u(t),o.postMessage(JSON.stringify(Object.assign({message:e,adId:s},n)),c,[r.port2])}function l(n){d(e,{event:"adRenderFailed",info:{reason:n?.reason||"exception",message:n?.message}}),n?.stack&&console.error(n)}function u(e){return function(){try{return e.apply(this,arguments)}catch(e){l(e)}}}d("Prebid Request",{options:{clickUrl:a}},(function(t){let o;try{o=JSON.parse(t.data)}catch(e){return}if("Prebid Response"===o.message&&o.adId===s){const t=n(r.document,{width:0,height:0,style:"display: none",srcdoc:`<script>${o.renderer}<\/script>`});t.onload=u((function(){const s=t.contentWindow;s.Promise.resolve(s.render(o,{sendMessage:d,mkFrame:n},r)).then((()=>d(e,{event:"adRenderSucceeded"})),l)})),r.document.body.appendChild(t)}}))}}(window)})();</script>
<script>(()=>{"use strict";const e="Prebid Event",n=(()=>{const e={frameBorder:0,scrolling:"no",marginHeight:0,marginWidth:0,topMargin:0,leftMargin:0,allowTransparency:"true"};return(n,t)=>{const r=n.createElement("iframe");return Object.entries(Object.assign({},t,e)).forEach((e=>{let[n,t]=e;return r.setAttribute(n,t)})),r}})();function t(e){return!!e.frames.__pb_locator__}window.pbRender=function(r){let o=r.parent;try{for(;o!==r.top&&!t(o);)o=o.parent;t(o)||(o=r.parent)}catch(e){}return function(t){let{adId:s,pubUrl:i,clickUrl:a}=t;const c=new URL(i,window.location).origin;function d(e,n,t){const r=new MessageChannel;r.port1.onmessage=u(t),o.postMessage(JSON.stringify(Object.assign({message:e,adId:s},n)),c,[r.port2])}function l(n){d(e,{event:"adRenderFailed",info:{reason:n?.reason||"exception",message:n?.message}}),n?.stack&&console.error(n)}function u(e){return function(){try{return e.apply(this,arguments)}catch(e){l(e)}}}d("Prebid Request",{options:{clickUrl:a}},(function(t){let o;try{o=JSON.parse(t.data)}catch(e){return}if("Prebid Response"===o.message&&o.adId===s){const t=n(r.document,{width:0,height:0,style:"display: none"});t.onload=u((function(){const s=t.contentWindow;s.Promise.resolve(s.render(o,{sendMessage:d,mkFrame:n},r)).then((()=>d(e,{event:"adRenderSucceeded"})),l)})),t.srcdoc=`<script>${o.renderer}<\/script>`,r.document.body.appendChild(t)}}))}}(window)})();</script>

<script>
pbRender({
Expand Down
26 changes: 13 additions & 13 deletions libraries/advangUtils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ export function isVideoBid(bid) {
}

export function getBannerBidFloor(bid) {
let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'banner', size: '*' }) : {};
const floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'banner', size: '*' }) : {};
return floorInfo?.floor || getBannerBidParam(bid, 'bidfloor');
}

export function getVideoBidFloor(bid) {
let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'video', size: '*' }) : {};
const floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'video', size: '*' }) : {};
return floorInfo.floor || getVideoBidParam(bid, 'bidfloor');
}

Expand Down Expand Up @@ -60,7 +60,7 @@ export function findAndFillParam(o, key, value) {
}

export function getOsVersion() {
let clientStrings = [
const clientStrings = [
{ s: 'Android', r: /Android/ },
{ s: 'iOS', r: /(iPhone|iPad|iPod)/ },
{ s: 'Mac OS X', r: /Mac OS X/ },
Expand All @@ -76,7 +76,7 @@ export function getOsVersion() {
{ s: 'UNIX', r: /UNIX/ },
{ s: 'Search Bot', r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ }
];
let cs = clientStrings.find(cs => cs.r.test(navigator.userAgent));
const cs = clientStrings.find(cs => cs.r.test(navigator.userAgent));
return cs ? cs.s : 'unknown';
}

Expand All @@ -86,7 +86,7 @@ export function getFirstSize(sizes) {

export function parseSizes(sizes) {
return parseSizesInput(sizes).map(size => {
let [ width, height ] = size.split('x');
const [ width, height ] = size.split('x');
return {
w: parseInt(width, 10) || undefined,
h: parseInt(height, 10) || undefined
Expand Down Expand Up @@ -127,11 +127,11 @@ export function getVideoTargetingParams(bid, VIDEO_TARGETING) {
}

export function createRequestData(bid, bidderRequest, isVideo, getBidParam, getSizes, getBidFloor, BIDDER_CODE, ADAPTER_VERSION) {
let topLocation = getTopWindowLocation(bidderRequest);
let topReferrer = getTopWindowReferrer(bidderRequest);
let paramSize = getBidParam(bid, 'size');
const topLocation = getTopWindowLocation(bidderRequest);
const topReferrer = getTopWindowReferrer(bidderRequest);
const paramSize = getBidParam(bid, 'size');
let sizes = [];
let coppa = config.getConfig('coppa');
const coppa = config.getConfig('coppa');

if (typeof paramSize !== 'undefined' && paramSize != '') {
sizes = parseSizes(paramSize);
Expand All @@ -140,7 +140,7 @@ export function createRequestData(bid, bidderRequest, isVideo, getBidParam, getS
}

const firstSize = getFirstSize(sizes);
let floor = getBidFloor(bid) || (isVideo ? 0.5 : 0.1);
const floor = getBidFloor(bid) || (isVideo ? 0.5 : 0.1);
const o = {
'device': {
'langauge': (global.navigator.language).split('-')[0],
Expand Down Expand Up @@ -182,8 +182,8 @@ export function createRequestData(bid, bidderRequest, isVideo, getBidParam, getS
return global.screen.width;
});

let placement = getBidParam(bid, 'placement');
let impType = isVideo ? {
const placement = getBidParam(bid, 'placement');
const impType = isVideo ? {
'video': Object.assign({
'id': generateUUID(),
'pos': 0,
Expand Down Expand Up @@ -218,7 +218,7 @@ export function createRequestData(bid, bidderRequest, isVideo, getBidParam, getS
}

if (bidderRequest && bidderRequest.gdprConsent) {
let { gdprApplies, consentString } = bidderRequest.gdprConsent;
const { gdprApplies, consentString } = bidderRequest.gdprConsent;
o.regs.ext = {'gdpr': gdprApplies ? 1 : 0};
o.user.ext = {'consent': consentString};
}
Expand Down
12 changes: 6 additions & 6 deletions libraries/appnexusUtils/anKeywords.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function transformBidderParamKeywords(keywords, paramName = 'keywords') {

_each(keywords, (v, k) => {
if (isArray(v)) {
let values = [];
const values = [];
_each(v, (val) => {
val = getValueString(paramName + '.' + k, val);
if (val || val === '') {
Expand Down Expand Up @@ -86,9 +86,9 @@ function convertKeywordsToANMap(kwarray) {
kwarray.forEach(kw => {
// if = exists, then split
if (kw.indexOf('=') !== -1) {
let kwPair = kw.split('=');
let key = kwPair[0];
let val = kwPair[1];
const kwPair = kw.split('=');
const key = kwPair[0];
const val = kwPair[1];

// then check for existing key in result > if so add value to the array > if not, add new key and create value array
if (result.hasOwnProperty(key)) {
Expand Down Expand Up @@ -131,9 +131,9 @@ export function getANKeywordParam(ortb2, ...anKeywordsMaps) {
}

export function getANMapFromOrtbSegments(ortb2) {
let ortbSegData = {};
const ortbSegData = {};
ORTB_SEG_PATHS.forEach(path => {
let ortbSegsArrObj = deepAccess(ortb2, path) || [];
const ortbSegsArrObj = deepAccess(ortb2, path) || [];
ortbSegsArrObj.forEach(segObj => {
// only read segment data from known sources
const segtax = ORTB_SEGTAX_KEY_MAP[segObj?.ext?.segtax];
Expand Down
4 changes: 2 additions & 2 deletions libraries/appnexusUtils/anUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ export const appnexusAliases = [
* Creates an array of n length and fills each item with the given value
*/
export function fill(value, length) {
let newArray = [];
const newArray = [];

for (let i = 0; i < length; i++) {
let valueToPush = isPlainObject(value) ? deepClone(value) : value;
const valueToPush = isPlainObject(value) ? deepClone(value) : value;
newArray.push(valueToPush);
}

Expand Down
6 changes: 3 additions & 3 deletions libraries/asteriobidUtils/asteriobidUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ const utmTags = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_co

export function collectUtmTagData(storage, getParameterByName, logError, analyticsName) {
let newUtm = false;
let pmUtmTags = {};
const pmUtmTags = {};
try {
utmTags.forEach(function (utmKey) {
let utmValue = getParameterByName(utmKey);
const utmValue = getParameterByName(utmKey);
if (utmValue !== '') {
newUtm = true;
}
pmUtmTags[utmKey] = utmValue;
});
if (newUtm === false) {
utmTags.forEach(function (utmKey) {
let itemValue = storage.getDataFromLocalStorage(`pm_${utmKey}`);
const itemValue = storage.getDataFromLocalStorage(`pm_${utmKey}`);
if (itemValue && itemValue.length !== 0) {
pmUtmTags[utmKey] = itemValue;
}
Expand Down
Loading
Loading