prebid.js 9.53.2 → 9.53.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/dist/33acrossAnalyticsAdapter.js +1 -1
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/33acrossIdSystem.js +1 -1
  4. package/dist/BTBidAdapter.js +1 -1
  5. package/dist/adagioAnalyticsAdapter.js +1 -1
  6. package/dist/adagioBidAdapter.js +1 -1
  7. package/dist/adagioRtdProvider.js +1 -1
  8. package/dist/adagioUtils.js +1 -1
  9. package/dist/addefendBidAdapter.js +1 -1
  10. package/dist/adgenerationBidAdapter.js +1 -1
  11. package/dist/adlooxRtdProvider.js +1 -1
  12. package/dist/adqueryBidAdapter.js +1 -1
  13. package/dist/adrelevantisBidAdapter.js +1 -1
  14. package/dist/adstirBidAdapter.js +1 -1
  15. package/dist/adtrgtmeBidAdapter.js +1 -1
  16. package/dist/adxcgAnalyticsAdapter.js +1 -1
  17. package/dist/adxcgBidAdapter.js +1 -1
  18. package/dist/adyoulikeBidAdapter.js +1 -1
  19. package/dist/agmaAnalyticsAdapter.js +1 -1
  20. package/dist/ajaBidAdapter.js +1 -1
  21. package/dist/amxBidAdapter.js +1 -1
  22. package/dist/amxIdSystem.js +1 -1
  23. package/dist/aniviewBidAdapter.js +1 -1
  24. package/dist/appierAnalyticsAdapter.js +1 -1
  25. package/dist/appnexusBidAdapter.js +1 -1
  26. package/dist/asoBidAdapter.js +1 -1
  27. package/dist/axonixBidAdapter.js +1 -1
  28. package/dist/beopBidAdapter.js +1 -1
  29. package/dist/bidderTimeoutUtils.js +1 -0
  30. package/dist/bidglassBidAdapter.js +1 -1
  31. package/dist/big-richmediaBidAdapter.js +1 -1
  32. package/dist/bitmediaBidAdapter.js +1 -1
  33. package/dist/bridBidAdapter.js +1 -1
  34. package/dist/bridgeuppBidAdapter.js +1 -1
  35. package/dist/bridgewellBidAdapter.js +1 -1
  36. package/dist/brightMountainMediaBidAdapter.js +1 -1
  37. package/dist/carodaBidAdapter.js +1 -1
  38. package/dist/chtnwBidAdapter.js +1 -1
  39. package/dist/chunk-core.js +1 -1
  40. package/dist/concertBidAdapter.js +1 -1
  41. package/dist/connectadBidAdapter.js +1 -1
  42. package/dist/consumableBidAdapter.js +1 -1
  43. package/dist/contxtfulBidAdapter.js +1 -1
  44. package/dist/conversantAnalyticsAdapter.js +1 -1
  45. package/dist/conversantBidAdapter.js +1 -1
  46. package/dist/craftBidAdapter.js +1 -1
  47. package/dist/criteoBidAdapter.js +1 -1
  48. package/dist/cwireBidAdapter.js +1 -1
  49. package/dist/dailymotionBidAdapter.js +1 -1
  50. package/dist/debugging-standalone.js +1 -1
  51. package/dist/dependencies.json +10 -1
  52. package/dist/dspxBidAdapter.js +1 -1
  53. package/dist/dxkultureBidAdapter.js +1 -1
  54. package/dist/eplanningBidAdapter.js +1 -1
  55. package/dist/equativBidAdapter.js +1 -1
  56. package/dist/eskimiBidAdapter.js +1 -1
  57. package/dist/euidIdSystem.js +1 -1
  58. package/dist/exadsBidAdapter.js +1 -1
  59. package/dist/excoBidAdapter.js +1 -1
  60. package/dist/feedadBidAdapter.js +1 -1
  61. package/dist/finativeBidAdapter.js +1 -1
  62. package/dist/freewheel-sspBidAdapter.js +1 -1
  63. package/dist/fwsspBidAdapter.js +1 -1
  64. package/dist/gmosspBidAdapter.js +1 -1
  65. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  66. package/dist/greenbidsBidAdapter.js +1 -1
  67. package/dist/greenbidsRtdProvider.js +1 -1
  68. package/dist/gridBidAdapter.js +1 -1
  69. package/dist/gumgumBidAdapter.js +1 -1
  70. package/dist/h12mediaBidAdapter.js +1 -1
  71. package/dist/hypelabBidAdapter.js +1 -1
  72. package/dist/id5AnalyticsAdapter.js +1 -1
  73. package/dist/id5IdSystem.js +1 -1
  74. package/dist/imdsBidAdapter.js +1 -1
  75. package/dist/improvedigitalBidAdapter.js +1 -1
  76. package/dist/inmobiBidAdapter.js +1 -1
  77. package/dist/insticatorBidAdapter.js +1 -1
  78. package/dist/intentIqAnalyticsAdapter.js +1 -1
  79. package/dist/ixBidAdapter.js +1 -1
  80. package/dist/jixieBidAdapter.js +1 -1
  81. package/dist/justpremiumBidAdapter.js +1 -1
  82. package/dist/kargoBidAdapter.js +1 -1
  83. package/dist/kimberliteBidAdapter.js +1 -1
  84. package/dist/konduitAnalyticsAdapter.js +1 -1
  85. package/dist/kueezBidAdapter.js +1 -1
  86. package/dist/lassoBidAdapter.js +1 -1
  87. package/dist/lifestreetBidAdapter.js +1 -1
  88. package/dist/liveIntentId.js +1 -1
  89. package/dist/logicadBidAdapter.js +1 -1
  90. package/dist/loglyliftBidAdapter.js +1 -1
  91. package/dist/luceadBidAdapter.js +1 -1
  92. package/dist/mabidderBidAdapter.js +1 -1
  93. package/dist/madsenseBidAdapter.js +1 -1
  94. package/dist/magniteAnalyticsAdapter.js +1 -1
  95. package/dist/malltvAnalyticsAdapter.js +1 -1
  96. package/dist/marsmediaBidAdapter.js +1 -1
  97. package/dist/mediafuseBidAdapter.js +1 -1
  98. package/dist/medianetBidAdapter.js +1 -1
  99. package/dist/medianetUtils.js +1 -1
  100. package/dist/mediasquareBidAdapter.js +1 -1
  101. package/dist/mgidBidAdapter.js +1 -1
  102. package/dist/missenaBidAdapter.js +1 -1
  103. package/dist/mobilefuseBidAdapter.js +1 -1
  104. package/dist/nextMillenniumBidAdapter.js +1 -1
  105. package/dist/nexx360Utils.js +1 -1
  106. package/dist/nobidAnalyticsAdapter.js +1 -1
  107. package/dist/nobidBidAdapter.js +1 -1
  108. package/dist/nodalsAiRtdProvider.js +1 -1
  109. package/dist/not-for-prod/prebid.js +178 -175
  110. package/dist/objectGuard.js +1 -1
  111. package/dist/oguryBidAdapter.js +1 -1
  112. package/dist/onetagBidAdapter.js +1 -1
  113. package/dist/ooloAnalyticsAdapter.js +1 -1
  114. package/dist/openxBidAdapter.js +1 -1
  115. package/dist/optableRtdProvider.js +1 -1
  116. package/dist/optidigitalBidAdapter.js +1 -1
  117. package/dist/orbidderBidAdapter.js +1 -1
  118. package/dist/outbrainBidAdapter.js +1 -1
  119. package/dist/pixfutureBidAdapter.js +1 -1
  120. package/dist/publinkIdSystem.js +1 -1
  121. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  122. package/dist/pubmaticBidAdapter.js +1 -1
  123. package/dist/pubmaticIdSystem.js +1 -1
  124. package/dist/pubmaticRtdProvider.js +1 -1
  125. package/dist/pubmaticUtils.js +1 -0
  126. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  127. package/dist/pubxaiAnalyticsAdapter.js +1 -1
  128. package/dist/pxyzBidAdapter.js +1 -1
  129. package/dist/quantcastBidAdapter.js +1 -1
  130. package/dist/readpeakBidAdapter.js +1 -1
  131. package/dist/relaidoBidAdapter.js +1 -1
  132. package/dist/retailspotBidAdapter.js +1 -1
  133. package/dist/rhythmoneBidAdapter.js +1 -1
  134. package/dist/riseUtils.js +1 -1
  135. package/dist/rtdModule.js +1 -1
  136. package/dist/rubiconBidAdapter.js +1 -1
  137. package/dist/seedingAllianceBidAdapter.js +1 -1
  138. package/dist/seedtagBidAdapter.js +1 -1
  139. package/dist/sevioBidAdapter.js +1 -0
  140. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  141. package/dist/sharethroughBidAdapter.js +1 -1
  142. package/dist/showheroes-bsBidAdapter.js +1 -1
  143. package/dist/smaatoBidAdapter.js +1 -1
  144. package/dist/smartadserverBidAdapter.js +1 -1
  145. package/dist/smartxBidAdapter.js +1 -1
  146. package/dist/smilewantedBidAdapter.js +1 -1
  147. package/dist/snigelBidAdapter.js +1 -1
  148. package/dist/sonobiBidAdapter.js +1 -1
  149. package/dist/sovrnBidAdapter.js +1 -1
  150. package/dist/sparteoBidAdapter.js +1 -1
  151. package/dist/sspBCBidAdapter.js +1 -1
  152. package/dist/stvBidAdapter.js +1 -1
  153. package/dist/sublimeBidAdapter.js +1 -1
  154. package/dist/taboolaBidAdapter.js +1 -1
  155. package/dist/tappxBidAdapter.js +1 -1
  156. package/dist/targetVideoBidAdapter.js +1 -1
  157. package/dist/teadsBidAdapter.js +1 -1
  158. package/dist/terceptAnalyticsAdapter.js +1 -1
  159. package/dist/themoneytizerBidAdapter.js +1 -1
  160. package/dist/timeoutRtdProvider.js +1 -1
  161. package/dist/trionBidAdapter.js +1 -1
  162. package/dist/tripleliftBidAdapter.js +1 -1
  163. package/dist/ttdBidAdapter.js +1 -1
  164. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  165. package/dist/uid2IdSystem.js +1 -1
  166. package/dist/underdogmediaBidAdapter.js +1 -1
  167. package/dist/undertoneBidAdapter.js +1 -1
  168. package/dist/unrulyBidAdapter.js +1 -1
  169. package/dist/userId.js +1 -1
  170. package/dist/vidazooUtils.js +1 -1
  171. package/dist/videobyteBidAdapter.js +1 -1
  172. package/dist/visxBidAdapter.js +1 -1
  173. package/dist/vuukleBidAdapter.js +1 -1
  174. package/dist/widespaceBidAdapter.js +1 -1
  175. package/dist/winrBidAdapter.js +1 -1
  176. package/dist/yahooAdsBidAdapter.js +1 -1
  177. package/dist/yandexBidAdapter.js +1 -1
  178. package/dist/yieldmoBidAdapter.js +1 -1
  179. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  180. package/integrationExamples/gpt/pubmaticRtdProvider_Example.html +161 -0
  181. package/libraries/bidderTimeoutUtils/bidderTimeoutUtils.js +119 -0
  182. package/libraries/objectGuard/objectGuard.js +170 -48
  183. package/libraries/objectGuard/ortbGuard.js +33 -43
  184. package/libraries/pubmaticUtils/plugins/dynamicTimeout.js +209 -0
  185. package/libraries/pubmaticUtils/plugins/floorProvider.js +168 -0
  186. package/libraries/pubmaticUtils/plugins/pluginManager.js +106 -0
  187. package/libraries/pubmaticUtils/plugins/unifiedPricingRule.js +375 -0
  188. package/libraries/pubmaticUtils/pubmaticUtils.js +76 -0
  189. package/modules/adagioAnalyticsAdapter.js +6 -1
  190. package/modules/adagioBidAdapter.js +12 -5
  191. package/modules/adagioRtdProvider.js +41 -35
  192. package/modules/fwsspBidAdapter.js +134 -69
  193. package/modules/fwsspBidAdapter.md +121 -26
  194. package/modules/optableRtdProvider.js +33 -12
  195. package/modules/pubmaticAnalyticsAdapter.js +315 -587
  196. package/modules/pubmaticBidAdapter.js +71 -8
  197. package/modules/pubmaticIdSystem.js +4 -4
  198. package/modules/pubmaticRtdProvider.js +105 -613
  199. package/modules/rtdModule/index.js +23 -6
  200. package/modules/sevioBidAdapter.js +413 -0
  201. package/modules/sevioBidAdapter.md +29 -0
  202. package/modules/sparteoBidAdapter.js +122 -10
  203. package/modules/timeoutRtdProvider.js +2 -105
  204. package/modules/ttdBidAdapter.js +0 -5
  205. package/modules/userId/eids.js +1 -1
  206. package/modules/userId/index.js +32 -1
  207. package/package.json +1 -1
  208. package/src/auction.js +3 -0
  209. package/test/spec/activities/objectGuard_spec.js +189 -32
  210. package/test/spec/activities/ortbGuard_spec.js +10 -15
  211. package/test/spec/libraries/bidderTimeoutUtils/bidderTimeoutUtils_spec.js +213 -0
  212. package/test/spec/libraries/pubmaticUtils/plugins/dynamicTimeout_spec.js +746 -0
  213. package/test/spec/libraries/pubmaticUtils/plugins/floorProvider_spec.js +184 -0
  214. package/test/spec/libraries/pubmaticUtils/plugins/pluginManager_spec.js +489 -0
  215. package/test/spec/libraries/pubmaticUtils/plugins/unifiedPricingRule_spec.js +359 -0
  216. package/test/spec/libraries/pubmaticUtils/pubmaticUtils_spec.js +236 -0
  217. package/test/spec/modules/adagioAnalyticsAdapter_spec.js +94 -24
  218. package/test/spec/modules/adagioRtdProvider_spec.js +17 -17
  219. package/test/spec/modules/fwsspBidAdapter_spec.js +513 -78
  220. package/test/spec/modules/optableRtdProvider_spec.js +55 -5
  221. package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +634 -916
  222. package/test/spec/modules/pubmaticBidAdapter_spec.js +260 -1
  223. package/test/spec/modules/pubmaticRtdProvider_spec.js +252 -1505
  224. package/test/spec/modules/realTimeDataModule_spec.js +58 -8
  225. package/test/spec/modules/sevioBidAdapter_spec.js +513 -0
  226. package/test/spec/modules/sparteoBidAdapter_spec.js +528 -43
  227. package/test/spec/modules/timeoutRtdProvider_spec.js +1 -201
  228. package/test/spec/modules/ttdBidAdapter_spec.js +0 -33
  229. package/test/spec/modules/userId_spec.js +115 -1
@@ -2,6 +2,7 @@ import { submodule } from '../src/hook.js';
2
2
  import * as ajax from '../src/ajax.js';
3
3
  import { logInfo, deepAccess, logError } from '../src/utils.js';
4
4
  import { getGlobal } from '../src/prebidGlobal.js';
5
+ import { bidderTimeoutFunctions } from '../libraries/bidderTimeoutUtils/bidderTimeoutUtils.js';
5
6
 
6
7
  /**
7
8
  * @typedef {import('../modules/rtdModule/index.js').RtdSubmodule} RtdSubmodule
@@ -11,113 +12,9 @@ const SUBMODULE_NAME = 'timeout';
11
12
 
12
13
  // this allows the stubbing of functions during testing
13
14
  export const timeoutRtdFunctions = {
14
- getDeviceType,
15
- getConnectionSpeed,
16
- checkVideo,
17
- calculateTimeoutModifier,
18
15
  handleTimeoutIncrement
19
16
  };
20
17
 
21
- const entries = Object.entries || function(obj) {
22
- const ownProps = Object.keys(obj);
23
- let i = ownProps.length;
24
- let resArray = new Array(i);
25
- while (i--) { resArray[i] = [ownProps[i], obj[ownProps[i]]]; }
26
- return resArray;
27
- };
28
-
29
- function getDeviceType() {
30
- const userAgent = window.navigator.userAgent.toLowerCase();
31
- if ((/ipad|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i.test(userAgent))) {
32
- return 5; // tablet
33
- }
34
- if ((/iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i.test(userAgent))) {
35
- return 4; // mobile
36
- }
37
- return 2; // personal computer
38
- }
39
-
40
- function checkVideo(adUnits) {
41
- return adUnits.some((adUnit) => {
42
- return adUnit.mediaTypes && adUnit.mediaTypes.video;
43
- });
44
- }
45
-
46
- function getConnectionSpeed() {
47
- const connection = window.navigator.connection || window.navigator.mozConnection || window.navigator.webkitConnection || {}
48
- const connectionType = connection.type || connection.effectiveType;
49
-
50
- switch (connectionType) {
51
- case 'slow-2g':
52
- case '2g':
53
- return 'slow';
54
-
55
- case '3g':
56
- return 'medium';
57
-
58
- case 'bluetooth':
59
- case 'cellular':
60
- case 'ethernet':
61
- case 'wifi':
62
- case 'wimax':
63
- case '4g':
64
- return 'fast';
65
- }
66
-
67
- return 'unknown';
68
- }
69
- /**
70
- * Calculate the time to be added to the timeout
71
- * @param {Array} adUnits
72
- * @param {Object} rules
73
- * @return {number}
74
- */
75
- function calculateTimeoutModifier(adUnits, rules) {
76
- logInfo('Timeout rules', rules);
77
- let timeoutModifier = 0;
78
- let toAdd = 0;
79
-
80
- if (rules.includesVideo) {
81
- const hasVideo = timeoutRtdFunctions.checkVideo(adUnits);
82
- toAdd = rules.includesVideo[hasVideo] || 0;
83
- logInfo(`Adding ${toAdd} to timeout for includesVideo ${hasVideo}`)
84
- timeoutModifier += toAdd;
85
- }
86
-
87
- if (rules.numAdUnits) {
88
- const numAdUnits = adUnits.length;
89
- if (rules.numAdUnits[numAdUnits]) {
90
- timeoutModifier += rules.numAdUnits[numAdUnits];
91
- } else {
92
- for (const [rangeStr, timeoutVal] of entries(rules.numAdUnits)) {
93
- const [lowerBound, upperBound] = rangeStr.split('-');
94
- if (parseInt(lowerBound) <= numAdUnits && numAdUnits <= parseInt(upperBound)) {
95
- logInfo(`Adding ${timeoutVal} to timeout for numAdUnits ${numAdUnits}`)
96
- timeoutModifier += timeoutVal;
97
- break;
98
- }
99
- }
100
- }
101
- }
102
-
103
- if (rules.deviceType) {
104
- const deviceType = timeoutRtdFunctions.getDeviceType();
105
- toAdd = rules.deviceType[deviceType] || 0;
106
- logInfo(`Adding ${toAdd} to timeout for deviceType ${deviceType}`)
107
- timeoutModifier += toAdd;
108
- }
109
-
110
- if (rules.connectionSpeed) {
111
- const connectionSpeed = timeoutRtdFunctions.getConnectionSpeed();
112
- toAdd = rules.connectionSpeed[connectionSpeed] || 0;
113
- logInfo(`Adding ${toAdd} to timeout for connectionSpeed ${connectionSpeed}`)
114
- timeoutModifier += toAdd;
115
- }
116
-
117
- logInfo('timeout Modifier calculated', timeoutModifier);
118
- return timeoutModifier;
119
- }
120
-
121
18
  /**
122
19
  *
123
20
  * @param {Object} reqBidsConfigObj
@@ -161,7 +58,7 @@ function getBidRequestData(reqBidsConfigObj, callback, config, userConsent) {
161
58
  */
162
59
  function handleTimeoutIncrement(reqBidsConfigObj, rules) {
163
60
  const adUnits = reqBidsConfigObj.adUnits || getGlobal().adUnits;
164
- const timeoutModifier = timeoutRtdFunctions.calculateTimeoutModifier(adUnits, rules);
61
+ const timeoutModifier = bidderTimeoutFunctions.calculateTimeoutModifier(adUnits, rules);
165
62
  const bidderTimeout = reqBidsConfigObj.timeout || getGlobal().getConfig('bidderTimeout');
166
63
  reqBidsConfigObj.timeout = bidderTimeout + timeoutModifier;
167
64
  }
@@ -110,11 +110,6 @@ function getUser(bidderRequest, firstPartyData) {
110
110
  var eids = utils.deepAccess(bidderRequest, 'bids.0.userIdAsEids')
111
111
  if (eids && eids.length) {
112
112
  utils.deepSetValue(user, 'ext.eids', eids);
113
-
114
- const tdid = eids.find(eid => eid.source == 'adserver.org')?.uids?.[0]?.id;
115
- if (tdid) {
116
- user.buyeruid = tdid
117
- }
118
113
  }
119
114
 
120
115
  utils.mergeDeep(user, firstPartyData.user)
@@ -72,7 +72,7 @@ export function createEidsArray(bidRequestUserId, eidConfigs = EID_CONFIG) {
72
72
  eids = deepClone(values);
73
73
  } else if (typeof eidConf === 'function') {
74
74
  try {
75
- eids = eidConf(values);
75
+ eids = deepClone(eidConf(values));
76
76
  if (!Array.isArray(eids)) {
77
77
  eids = [eids];
78
78
  }
@@ -141,7 +141,7 @@ import {
141
141
  isPlainObject,
142
142
  logError,
143
143
  logInfo,
144
- logWarn
144
+ logWarn, mergeDeep
145
145
  } from '../../src/utils.js';
146
146
  import {getPPID as coreGetPPID} from '../../src/adserver.js';
147
147
  import {defer, PbPromise, delay} from '../../src/utils/promise.js';
@@ -154,6 +154,7 @@ import {ACTIVITY_ENRICH_EIDS} from '../../src/activities/activities.js';
154
154
  import {activityParams} from '../../src/activities/activityParams.js';
155
155
  import {USERSYNC_DEFAULT_CONFIG} from '../../src/userSync.js';
156
156
  import {startAuction} from '../../src/prebid.js';
157
+ import {beforeInitAuction} from '../../src/auction.js';
157
158
 
158
159
  const MODULE_NAME = 'User ID';
159
160
  const COOKIE = STORAGE_TYPE_COOKIES;
@@ -737,6 +738,35 @@ function aliasEidsHook(next, bidderRequests) {
737
738
  next(bidderRequests);
738
739
  }
739
740
 
741
+ export function adUnitEidsHook(next, auction) {
742
+ // for backwards-compat, add `userIdAsEids` to ad units' bid objects
743
+ // before auction events are fired
744
+ // these are computed similarly to bid requests' `ortb2`, but unlike them,
745
+ // they are not subject to the same activity checks (since they are not intended for bid adapters)
746
+
747
+ const eidsByBidder = {};
748
+ const globalEids = auction.getFPD()?.global?.user?.ext?.eids ?? [];
749
+ function getEids(bidderCode) {
750
+ if (bidderCode == null) return globalEids;
751
+ if (!eidsByBidder.hasOwnProperty(bidderCode)) {
752
+ eidsByBidder[bidderCode] = mergeDeep(
753
+ {eids: []},
754
+ {eids: globalEids},
755
+ {eids: auction.getFPD()?.bidder?.[bidderCode]?.user?.ext?.eids ?? []}
756
+ ).eids;
757
+ }
758
+ return eidsByBidder[bidderCode];
759
+ }
760
+ auction.getAdUnits()
761
+ .flatMap(au => au.bids)
762
+ .forEach(bid => {
763
+ const eids = getEids(bid.bidder);
764
+ if (eids.length > 0) {
765
+ bid.userIdAsEids = eids;
766
+ }
767
+ });
768
+ next(auction);
769
+ }
740
770
  /**
741
771
  * Is startAuctionHook added
742
772
  * @returns {boolean}
@@ -1262,6 +1292,7 @@ export function init(config, {mkDelay = delay} = {}) {
1262
1292
  }
1263
1293
  });
1264
1294
  adapterManager.makeBidRequests.after(aliasEidsHook);
1295
+ beforeInitAuction.before(adUnitEidsHook);
1265
1296
 
1266
1297
  // exposing getUserIds function in global-name-space so that userIds stored in Prebid can be used by external codes.
1267
1298
  (getGlobal()).getUserIds = getUserIds;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prebid.js",
3
- "version": "9.53.2",
3
+ "version": "9.53.4",
4
4
  "description": "Header Bidding Management Library",
5
5
  "main": "src/prebid.public.js",
6
6
  "exports": {
package/src/auction.js CHANGED
@@ -124,6 +124,8 @@ export function resetAuctionState() {
124
124
  [outstandingRequests, sourceInfo].forEach((ob) => Object.keys(ob).forEach((k) => { delete ob[k] }));
125
125
  }
126
126
 
127
+ export const beforeInitAuction = hook('sync', (auction) => {})
128
+
127
129
  /**
128
130
  * Creates new auction instance
129
131
  *
@@ -293,6 +295,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a
293
295
  let call = {
294
296
  bidRequests,
295
297
  run: () => {
298
+ beforeInitAuction(this);
296
299
  startAuctionTimer();
297
300
 
298
301
  _auctionStatus = AUCTION_IN_PROGRESS;
@@ -1,4 +1,5 @@
1
1
  import {objectGuard, writeProtectRule} from '../../../libraries/objectGuard/objectGuard.js';
2
+ import {redactRule} from '../../../src/activities/redactor.js';
2
3
 
3
4
  describe('objectGuard', () => {
4
5
  describe('read rule', () => {
@@ -12,8 +13,20 @@ describe('objectGuard', () => {
12
13
  get(val) { return `repl${val}` },
13
14
  }
14
15
  })
16
+
17
+ it('should reject conflicting rules', () => {
18
+ const crule = {...rule, paths: ['outer']};
19
+ expect(() => objectGuard([rule, crule])).to.throw();
20
+ expect(() => objectGuard([crule, rule])).to.throw();
21
+ });
22
+
23
+ it('should preserve object identity', () => {
24
+ const guard = objectGuard([rule])({outer: {inner: {foo: 'bar'}}});
25
+ expect(guard.outer).to.equal(guard.outer);
26
+ expect(guard.outer.inner).to.equal(guard.outer.inner);
27
+ })
15
28
  it('can prevent top level read access', () => {
16
- const {obj} = objectGuard([rule])({'foo': 1, 'other': 2});
29
+ const obj = objectGuard([rule])({'foo': 1, 'other': 2});
17
30
  expect(obj).to.eql({
18
31
  foo: 'repl1',
19
32
  other: 2
@@ -21,20 +34,27 @@ describe('objectGuard', () => {
21
34
  });
22
35
 
23
36
  it('does not choke if a guarded property is missing', () => {
24
- const {obj} = objectGuard([rule])({});
37
+ const obj = objectGuard([rule])({});
25
38
  expect(obj.foo).to.not.exist;
26
39
  });
27
40
 
41
+ it('allows concurrent reads', () => {
42
+ const obj = {'foo': 'bar'};
43
+ const guarded = objectGuard([rule])(obj);
44
+ obj.foo = 'baz';
45
+ expect(guarded.foo).to.eql('replbaz');
46
+ })
47
+
28
48
  it('does not prevent access if applies returns false', () => {
29
49
  applies = false;
30
- const {obj} = objectGuard([rule])({foo: 1});
50
+ const obj = objectGuard([rule])({foo: 1});
31
51
  expect(obj).to.eql({
32
52
  foo: 1
33
53
  });
34
54
  })
35
55
 
36
56
  it('can prevent nested property access', () => {
37
- const {obj} = objectGuard([rule])({
57
+ const obj = objectGuard([rule])({
38
58
  other: 0,
39
59
  outer: {
40
60
  foo: 1,
@@ -60,6 +80,11 @@ describe('objectGuard', () => {
60
80
  })
61
81
  });
62
82
 
83
+ it('prevents nested property access when a parent property is protected', () => {
84
+ const guard = objectGuard([rule])({foo: {inner: 'value'}});
85
+ expect(guard.inner?.value).to.not.exist;
86
+ })
87
+
63
88
  it('does not call applies more than once', () => {
64
89
  JSON.stringify(objectGuard([rule])({
65
90
  foo: 0,
@@ -68,7 +93,7 @@ describe('objectGuard', () => {
68
93
  foo: 1
69
94
  }
70
95
  }
71
- }).obj);
96
+ }));
72
97
  expect(rule.applies.callCount).to.equal(1);
73
98
  })
74
99
  });
@@ -84,35 +109,72 @@ describe('objectGuard', () => {
84
109
  });
85
110
  });
86
111
 
87
- it('should undo top-level writes', () => {
112
+ it('should reject conflicting rules', () => {
113
+ const crule = {...rule, paths: ['outer']};
114
+ expect(() => objectGuard([rule, crule])).to.throw();
115
+ expect(() => objectGuard([crule, rule])).to.throw();
116
+ });
117
+
118
+ it('should preserve object identity', () => {
119
+ const guard = objectGuard([rule])({outer: {inner: {foo: 'bar'}}});
120
+ expect(guard.outer).to.equal(guard.outer);
121
+ expect(guard.outer.inner).to.equal(guard.outer.inner);
122
+ })
123
+
124
+ it('does not mess up array reads', () => {
125
+ const guard = objectGuard([rule])({foo: [{bar: 'baz'}]});
126
+ expect(guard.foo).to.eql([{bar: 'baz'}]);
127
+ })
128
+
129
+ it('prevents array modification', () => {
130
+ const obj = {foo: ['value']};
131
+ const guard = objectGuard([rule])(obj);
132
+ guard.foo.pop();
133
+ guard.foo.push('test');
134
+ expect(obj.foo).to.eql(['value']);
135
+ })
136
+
137
+ it('allows array modification when not applicable', () => {
138
+ applies = false;
139
+ const obj = {foo: ['value']};
140
+ const guard = objectGuard([rule])(obj);
141
+ guard.foo.pop();
142
+ guard.foo.push('test');
143
+ expect(obj.foo).to.eql(['test']);
144
+ })
145
+
146
+ it('should prevent top-level writes', () => {
88
147
  const obj = {bar: {nested: 'val'}, other: 'val'};
89
148
  const guard = objectGuard([rule])(obj);
90
- guard.obj.foo = 'denied';
91
- guard.obj.bar.nested = 'denied';
92
- guard.obj.bar.other = 'denied';
93
- guard.obj.other = 'allowed';
94
- guard.verify();
95
- expect(obj).to.eql({bar: {nested: 'val'}, other: 'allowed'});
149
+ guard.foo = 'denied';
150
+ guard.bar.nested = 'denied';
151
+ guard.bar.other = 'denied';
152
+ guard.other = 'allowed';
153
+ expect(guard).to.eql({bar: {nested: 'val'}, other: 'allowed'});
96
154
  });
97
155
 
98
- it('should undo top-level deletes', () => {
156
+ it('should not prevent no-op writes', () => {
157
+ const guard = objectGuard([rule])({foo: {some: 'value'}});
158
+ guard.foo = {some: 'value'};
159
+ sinon.assert.notCalled(rule.applies);
160
+ })
161
+
162
+ it('should prevent top-level deletes', () => {
99
163
  const obj = {foo: {nested: 'val'}, bar: 'val'};
100
164
  const guard = objectGuard([rule])(obj);
101
- delete guard.obj.foo.nested;
102
- delete guard.obj.bar;
103
- guard.verify();
104
- expect(obj).to.eql({foo: {nested: 'val'}, bar: 'val'});
165
+ delete guard.foo.nested;
166
+ delete guard.bar;
167
+ expect(guard).to.eql({foo: {nested: 'val'}, bar: 'val'});
105
168
  })
106
169
 
107
- it('should undo nested writes', () => {
170
+ it('should prevent nested writes', () => {
108
171
  const obj = {outer: {inner: {bar: {nested: 'val'}, other: 'val'}}};
109
172
  const guard = objectGuard([rule])(obj);
110
- guard.obj.outer.inner.bar.other = 'denied';
111
- guard.obj.outer.inner.bar.nested = 'denied';
112
- guard.obj.outer.inner.foo = 'denied';
113
- guard.obj.outer.inner.other = 'allowed';
114
- guard.verify();
115
- expect(obj).to.eql({
173
+ guard.outer.inner.bar.other = 'denied';
174
+ guard.outer.inner.bar.nested = 'denied';
175
+ guard.outer.inner.foo = 'denied';
176
+ guard.outer.inner.other = 'allowed';
177
+ expect(guard).to.eql({
116
178
  outer: {
117
179
  inner: {
118
180
  bar: {
@@ -124,21 +186,116 @@ describe('objectGuard', () => {
124
186
  })
125
187
  });
126
188
 
127
- it('should undo nested deletes', () => {
189
+ it('should prevent writes if upper levels are protected', () => {
190
+ const obj = {foo: {inner: {}}};
191
+ const guard = objectGuard([rule])(obj);
192
+ guard.foo.inner.prop = 'value';
193
+ expect(obj).to.eql({foo: {inner: {}}});
194
+ })
195
+
196
+ it('should prevent deletes if a higher level property is protected', () => {
197
+ const obj = {foo: {inner: {prop: 'value'}}};
198
+ const guard = objectGuard([rule])(obj);
199
+ delete guard.foo.inner.prop;
200
+ expect(obj).to.eql({foo: {inner: {prop: 'value'}}});
201
+ })
202
+
203
+ it('should clean up top-level writes that would result in inner properties changing', () => {
204
+ const guard = objectGuard([rule])({outer: {inner: {bar: 'baz'}}});
205
+ guard.outer = {inner: {bar: 'baz', foo: 'baz', prop: 'allowed'}};
206
+ expect(guard).to.eql({outer: {inner: {bar: 'baz', prop: 'allowed'}}});
207
+ })
208
+
209
+ it('should not prevent writes that are not protected', () => {
210
+ const obj = {};
211
+ const guard = objectGuard([rule])(obj);
212
+ guard.outer = {
213
+ test: 'value'
214
+ }
215
+ expect(obj.outer.test).to.eql('value');
216
+ })
217
+
218
+ it('should not choke on type mismatch: overwrite object with scalar', () => {
219
+ const obj = {outer: {inner: {}}};
220
+ const guard = objectGuard([rule])(obj);
221
+ guard.outer = null;
222
+ expect(obj).to.eql({outer: {inner: {}}});
223
+ });
224
+
225
+ it('should not choke on type mismatch: overwrite scalar with object', () => {
226
+ const obj = {outer: null};
227
+ const guard = objectGuard([rule])(obj);
228
+ guard.outer = {inner: {bar: 'denied', other: 'allowed'}};
229
+ expect(obj).to.eql({outer: {inner: {other: 'allowed'}}});
230
+ })
231
+
232
+ it('should prevent nested deletes', () => {
128
233
  const obj = {outer: {inner: {foo: {nested: 'val'}, bar: 'val'}}};
129
234
  const guard = objectGuard([rule])(obj);
130
- delete guard.obj.outer.inner.foo.nested;
131
- delete guard.obj.outer.inner.bar;
132
- guard.verify();
133
- expect(obj).to.eql({outer: {inner: {foo: {nested: 'val'}, bar: 'val'}}})
235
+ delete guard.outer.inner.foo.nested;
236
+ delete guard.outer.inner.bar;
237
+ expect(guard).to.eql({outer: {inner: {foo: {nested: 'val'}, bar: 'val'}}})
134
238
  });
135
239
 
240
+ it('should prevent higher level deletes that would result in inner properties changing', () => {
241
+ const guard = objectGuard([rule])({outer: {inner: {bar: 'baz'}}});
242
+ delete guard.outer.inner;
243
+ expect(guard).to.eql({outer: {inner: {bar: 'baz'}}});
244
+ })
245
+
136
246
  it('should work on null properties', () => {
137
247
  const obj = {foo: null};
138
248
  const guard = objectGuard([rule])(obj);
139
- guard.obj.foo = 'denied';
140
- guard.verify();
141
- expect(obj).to.eql({foo: null});
249
+ guard.foo = 'denied';
250
+ expect(guard).to.eql({foo: null});
142
251
  });
143
252
  });
253
+ describe('multiple rules on the same path', () => {
254
+ it('should each be checked for redacts', () => {
255
+ const obj = objectGuard([
256
+ redactRule({
257
+ paths: ['foo'],
258
+ applies: () => true,
259
+ get(val) {
260
+ return '1' + val;
261
+ }
262
+ }),
263
+ redactRule({
264
+ paths: ['foo'],
265
+ applies: () => true,
266
+ get(val) {
267
+ return '2' + val;
268
+ }
269
+ })
270
+ ])({foo: 'bar'});
271
+ expect(obj.foo).to.eql('21bar');
272
+ });
273
+
274
+ describe('when a property has both redact and write protect rules', () => {
275
+ let rules;
276
+ beforeEach(() => {
277
+ rules = [
278
+ redactRule({
279
+ paths: ['foo'],
280
+ applies: () => true,
281
+ }),
282
+ writeProtectRule({
283
+ paths: ['foo'],
284
+ applies: () => true,
285
+ })
286
+ ];
287
+ })
288
+ Object.entries({
289
+ 'simple value': 'val',
290
+ 'object value': {inner: 'val'}
291
+ }).forEach(([t, val]) => {
292
+ it(`can apply them both (on ${t})`, () => {
293
+ const obj = objectGuard(rules)({foo: val});
294
+ expect(obj.foo).to.not.exist;
295
+ obj.foo = {other: 'val'};
296
+ expect(obj.foo).to.not.exist;
297
+ })
298
+ })
299
+ })
300
+ })
144
301
  });
@@ -45,7 +45,7 @@ describe('ortb2Guard', () => {
45
45
 
46
46
  function testPropertiesAreProtected(properties, allowed) {
47
47
  properties.forEach(prop => {
48
- it(`should ${allowed ? 'keep' : 'undo'} additions to ${prop}`, () => {
48
+ it(`should ${allowed ? 'keep' : 'prevent'} additions to ${prop}`, () => {
49
49
  const orig = [{n: 'orig'}];
50
50
  const ortb2 = {};
51
51
  deepSetValue(ortb2, prop, deepClone(orig));
@@ -53,8 +53,7 @@ describe('ortb2Guard', () => {
53
53
  const mod = {};
54
54
  const insert = [{n: 'new'}];
55
55
  deepSetValue(mod, prop, insert);
56
- mergeDeep(guard.obj, mod);
57
- guard.verify();
56
+ mergeDeep(guard, mod);
58
57
  const actual = deepAccess(ortb2, prop);
59
58
  if (allowed) {
60
59
  expect(actual).to.eql(orig.concat(insert))
@@ -63,13 +62,12 @@ describe('ortb2Guard', () => {
63
62
  }
64
63
  });
65
64
 
66
- it(`should ${allowed ? 'keep' : 'undo'} modifications to ${prop}`, () => {
65
+ it(`should ${allowed ? 'keep' : 'prevent'} modifications to ${prop}`, () => {
67
66
  const orig = [{n: 'orig'}];
68
67
  const ortb2 = {};
69
68
  deepSetValue(ortb2, prop, orig);
70
69
  const guard = ortb2Guard(ortb2, activityParams(MOD_TYPE, MOD_NAME));
71
- deepSetValue(guard.obj, `${prop}.0.n`, 'new');
72
- guard.verify();
70
+ deepSetValue(guard, `${prop}.0.n`, 'new');
73
71
  const actual = deepAccess(ortb2, prop);
74
72
  if (allowed) {
75
73
  expect(actual).to.eql([{n: 'new'}]);
@@ -102,19 +100,18 @@ describe('ortb2FragmentsGuard', () => {
102
100
  guardFragments = ortb2FragmentsGuardFactory(testGuard);
103
101
  });
104
102
 
105
- it('should undo changes to global FPD', () => {
103
+ it('should prevent changes to global FPD', () => {
106
104
  const fragments = {
107
105
  global: {
108
106
  foo: {inner: 'val'}
109
107
  }
110
108
  }
111
109
  const guard = guardFragments(fragments);
112
- guard.obj.global.foo = 'other';
113
- guard.verify();
110
+ guard.global.foo = 'other';
114
111
  expect(fragments.global.foo).to.eql({inner: 'val'});
115
112
  });
116
113
 
117
- it('should undo changes to bidder FPD', () => {
114
+ it('should prevent changes to bidder FPD', () => {
118
115
  const fragments = {
119
116
  bidder: {
120
117
  A: {
@@ -123,18 +120,16 @@ describe('ortb2FragmentsGuard', () => {
123
120
  }
124
121
  };
125
122
  const guard = guardFragments(fragments);
126
- guard.obj.bidder.A.foo = 'denied';
127
- guard.verify();
123
+ guard.bidder.A.foo = 'denied';
128
124
  expect(fragments.bidder.A).to.eql({foo: 'val'});
129
125
  });
130
126
 
131
- it('should undo changes to bidder FPD that was not initially there', () => {
127
+ it('should prevent changes to bidder FPD that was not initially there', () => {
132
128
  const fragments = {
133
129
  bidder: {}
134
130
  };
135
131
  const guard = guardFragments(fragments);
136
- guard.obj.bidder.A = {foo: 'denied', other: 'allowed'};
137
- guard.verify();
132
+ guard.bidder.A = {foo: 'denied', other: 'allowed'};
138
133
  expect(fragments.bidder.A).to.eql({other: 'allowed'});
139
134
  });
140
135
  })