prebid.js 6.7.0 → 6.8.0
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.
- package/integrationExamples/gpt/x-domain/creative.html +53 -26
- package/modules/adagioBidAdapter.js +0 -8
- package/modules/adagioBidAdapter.md +1 -1
- package/modules/appnexusBidAdapter.js +11 -0
- package/modules/brandmetricsRtdProvider.js +168 -0
- package/modules/brandmetricsRtdProvider.md +40 -0
- package/modules/criteoBidAdapter.js +9 -0
- package/modules/currency.js +26 -1
- package/modules/displayioBidAdapter.js +157 -0
- package/modules/displayioBidAdapter.md +148 -0
- package/modules/e_volutionBidAdapter.js +158 -0
- package/modules/gumgumBidAdapter.js +52 -38
- package/modules/interactiveOffersBidAdapter.js +9 -6
- package/modules/sovrnBidAdapter.js +93 -18
- package/modules/sovrnBidAdapter.md +80 -2
- package/modules/undertoneBidAdapter.js +17 -1
- package/modules/yahoosspBidAdapter.js +2 -0
- package/package.json +1 -1
- package/src/adRendering.js +38 -0
- package/src/auction.js +44 -9
- package/src/prebid.js +3 -19
- package/src/secureCreatives.js +111 -42
- package/src/utils.js +13 -3
- package/test/helpers/syncPromise.js +71 -0
- package/test/spec/auctionmanager_spec.js +148 -16
- package/test/spec/modules/adagioBidAdapter_spec.js +0 -10
- package/test/spec/modules/appnexusBidAdapter_spec.js +27 -0
- package/test/spec/modules/brandmetricsRtdProvider_spec.js +191 -0
- package/test/spec/modules/criteoBidAdapter_spec.js +21 -0
- package/test/spec/modules/currency_spec.js +21 -6
- package/test/spec/modules/displayioBidAdapter_spec.js +239 -0
- package/test/spec/modules/e_volutionBidAdapter_spec.js +242 -0
- package/test/spec/modules/gumgumBidAdapter_spec.js +46 -0
- package/test/spec/modules/sovrnBidAdapter_spec.js +413 -333
- package/test/spec/modules/undertoneBidAdapter_spec.js +55 -2
- package/test/spec/modules/yahoosspBidAdapter_spec.js +10 -0
- package/test/spec/unit/pbjs_api_spec.js +17 -1
- package/test/spec/unit/secureCreatives_spec.js +85 -0
|
@@ -10,9 +10,9 @@ Maintainer: jrosendahl@sovrn.com
|
|
|
10
10
|
|
|
11
11
|
Sovrn's adapter integration to the Prebid library. Posts plain-text JSON to the /rtb/bid endpoint.
|
|
12
12
|
|
|
13
|
-
# Test Parameters
|
|
13
|
+
# Banner Test Parameters
|
|
14
14
|
|
|
15
|
-
```
|
|
15
|
+
```js
|
|
16
16
|
var adUnits = [
|
|
17
17
|
{
|
|
18
18
|
code: 'test-leaderboard',
|
|
@@ -45,3 +45,81 @@ var adUnits = [
|
|
|
45
45
|
}
|
|
46
46
|
]
|
|
47
47
|
```
|
|
48
|
+
|
|
49
|
+
# Video Test Parameters
|
|
50
|
+
### Instream
|
|
51
|
+
```js
|
|
52
|
+
var videoAdUnit = {
|
|
53
|
+
code: 'video1',
|
|
54
|
+
sizes: [640, 480],
|
|
55
|
+
mediaTypes: {
|
|
56
|
+
video: {
|
|
57
|
+
context: 'instream',
|
|
58
|
+
playerSize: [640, 480],
|
|
59
|
+
mimes: ['video/mp4'],
|
|
60
|
+
protocols: [1, 2, 3, 4, 5, 6, 7, 8],
|
|
61
|
+
playbackmethod: [2],
|
|
62
|
+
skip: 1,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
bids: [
|
|
66
|
+
{
|
|
67
|
+
bidder: 'sovrn',
|
|
68
|
+
// Prebid Server Bidder Params https://docs.prebid.org/dev-docs/pbs-bidders.html#sovrn
|
|
69
|
+
params: {
|
|
70
|
+
tagid: '315045',
|
|
71
|
+
bidfloor: '0.04',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
### Outstream
|
|
78
|
+
```js
|
|
79
|
+
var adUnits = [
|
|
80
|
+
{
|
|
81
|
+
code: videoId,
|
|
82
|
+
mediaTypes: {
|
|
83
|
+
video: {
|
|
84
|
+
context: 'outstream',
|
|
85
|
+
playerSize: [640, 360],
|
|
86
|
+
mimes: ['video/mp4'],
|
|
87
|
+
protocols: [1, 2, 3, 4, 5, 6, 7, 8],
|
|
88
|
+
playbackmethod: [2],
|
|
89
|
+
skip: 1,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
bids: [
|
|
93
|
+
{
|
|
94
|
+
bidder: 'sovrn',
|
|
95
|
+
// Prebid Server Bidder Params https://docs.prebid.org/dev-docs/pbs-bidders.html#sovrn
|
|
96
|
+
params: {
|
|
97
|
+
tagid: '315045',
|
|
98
|
+
bidfloor: '0.04',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
renderer: {
|
|
103
|
+
url: 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js',
|
|
104
|
+
render: function (bid) {
|
|
105
|
+
adResponse = {
|
|
106
|
+
ad: {
|
|
107
|
+
video: {
|
|
108
|
+
content: bid.vastXml,
|
|
109
|
+
player_height: bid.height,
|
|
110
|
+
player_width: bid.width,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
// push to render queue because ANOutstreamVideo may not be loaded yet.
|
|
115
|
+
bid.renderer.push(() => {
|
|
116
|
+
ANOutstreamVideo.renderAd({
|
|
117
|
+
targetId: bid.adUnitCode,
|
|
118
|
+
adResponse: adResponse,
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
]
|
|
125
|
+
```
|
|
@@ -12,6 +12,20 @@ const FRAME_USER_SYNC = 'https://cdn.undertone.com/js/usersync.html';
|
|
|
12
12
|
const PIXEL_USER_SYNC_1 = 'https://usr.undertone.com/userPixel/syncOne?id=1&of=2';
|
|
13
13
|
const PIXEL_USER_SYNC_2 = 'https://usr.undertone.com/userPixel/syncOne?id=2&of=2';
|
|
14
14
|
|
|
15
|
+
function getBidFloor(bidRequest, mediaType) {
|
|
16
|
+
if (typeof bidRequest.getFloor !== 'function') {
|
|
17
|
+
return 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const floor = bidRequest.getFloor({
|
|
21
|
+
currency: 'USD',
|
|
22
|
+
mediaType: mediaType,
|
|
23
|
+
size: '*'
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return (floor && floor.currency === 'USD' && floor.floor) || 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
15
29
|
function getCanonicalUrl() {
|
|
16
30
|
try {
|
|
17
31
|
let doc = window.top.document;
|
|
@@ -134,6 +148,9 @@ export const spec = {
|
|
|
134
148
|
params: bidReq.params
|
|
135
149
|
};
|
|
136
150
|
const videoMediaType = deepAccess(bidReq, 'mediaTypes.video');
|
|
151
|
+
const mediaType = videoMediaType ? VIDEO : BANNER;
|
|
152
|
+
bid.mediaType = mediaType;
|
|
153
|
+
bid.bidfloor = getBidFloor(bidReq, mediaType);
|
|
137
154
|
if (videoMediaType) {
|
|
138
155
|
bid.video = {
|
|
139
156
|
playerSize: deepAccess(bidReq, 'mediaTypes.video.playerSize') || null,
|
|
@@ -142,7 +159,6 @@ export const spec = {
|
|
|
142
159
|
maxDuration: deepAccess(bidReq, 'params.video.maxDuration') || null,
|
|
143
160
|
skippable: deepAccess(bidReq, 'params.video.skippable') || null
|
|
144
161
|
};
|
|
145
|
-
bid.mediaType = 'video';
|
|
146
162
|
}
|
|
147
163
|
payload['x-ut-hb-params'].push(bid);
|
|
148
164
|
});
|
|
@@ -6,6 +6,7 @@ import { Renderer } from '../src/Renderer.js';
|
|
|
6
6
|
|
|
7
7
|
const INTEGRATION_METHOD = 'prebid.js';
|
|
8
8
|
const BIDDER_CODE = 'yahoossp';
|
|
9
|
+
const GVLID = 25;
|
|
9
10
|
const ADAPTER_VERSION = '1.0.2';
|
|
10
11
|
const PREBID_VERSION = '$prebid.version$';
|
|
11
12
|
const DEFAULT_BID_TTL = 300;
|
|
@@ -515,6 +516,7 @@ function createRenderer(bidderRequest, bidResponse) {
|
|
|
515
516
|
|
|
516
517
|
export const spec = {
|
|
517
518
|
code: BIDDER_CODE,
|
|
519
|
+
gvlid: GVLID,
|
|
518
520
|
aliases: [],
|
|
519
521
|
supportedMediaTypes: [BANNER, VIDEO],
|
|
520
522
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {logError} from './utils.js';
|
|
2
|
+
import events from './events.js';
|
|
3
|
+
import CONSTANTS from './constants.json';
|
|
4
|
+
|
|
5
|
+
const {AD_RENDER_FAILED, AD_RENDER_SUCCEEDED} = CONSTANTS.EVENTS;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Emit the AD_RENDER_FAILED event.
|
|
9
|
+
*
|
|
10
|
+
* @param reason one of the values in CONSTANTS.AD_RENDER_FAILED_REASON
|
|
11
|
+
* @param message failure description
|
|
12
|
+
* @param bid? bid response object that failed to render
|
|
13
|
+
* @param id? adId that failed to render
|
|
14
|
+
*/
|
|
15
|
+
export function emitAdRenderFail({ reason, message, bid, id }) {
|
|
16
|
+
const data = { reason, message };
|
|
17
|
+
if (bid) data.bid = bid;
|
|
18
|
+
if (id) data.adId = id;
|
|
19
|
+
|
|
20
|
+
logError(message);
|
|
21
|
+
events.emit(AD_RENDER_FAILED, data);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Emit the AD_RENDER_SUCCEEDED event.
|
|
26
|
+
*
|
|
27
|
+
* @param doc document object that was used to `.write` the ad. Should be `null` if unavailable (e.g. for documents in
|
|
28
|
+
* a cross-origin frame).
|
|
29
|
+
* @param bid bid response object for the ad that was rendered
|
|
30
|
+
* @param id adId that was rendered.
|
|
31
|
+
*/
|
|
32
|
+
export function emitAdRenderSucceeded({ doc, bid, id }) {
|
|
33
|
+
const data = { doc };
|
|
34
|
+
if (bid) data.bid = bid;
|
|
35
|
+
if (id) data.adId = id;
|
|
36
|
+
|
|
37
|
+
events.emit(AD_RENDER_SUCCEEDED, data);
|
|
38
|
+
}
|
package/src/auction.js
CHANGED
|
@@ -250,10 +250,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a
|
|
|
250
250
|
|
|
251
251
|
let callbacks = auctionCallbacks(auctionDone, this);
|
|
252
252
|
adapterManager.callBids(_adUnits, bidRequests, function(...args) {
|
|
253
|
-
addBidResponse.apply(
|
|
254
|
-
dispatch: callbacks.addBidResponse,
|
|
255
|
-
bidderRequest: this
|
|
256
|
-
}, args)
|
|
253
|
+
callbacks.addBidResponse.apply(this, args);
|
|
257
254
|
}, callbacks.adapterDone, {
|
|
258
255
|
request(source, origin) {
|
|
259
256
|
increment(outstandingRequests, origin);
|
|
@@ -344,6 +341,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a
|
|
|
344
341
|
addWinningBid,
|
|
345
342
|
setBidTargeting,
|
|
346
343
|
getWinningBids: () => _winningBids,
|
|
344
|
+
getAuctionStart: () => _auctionStart,
|
|
347
345
|
getTimeout: () => _timeout,
|
|
348
346
|
getAuctionId: () => _auctionId,
|
|
349
347
|
getAuctionStatus: () => _auctionStatus,
|
|
@@ -355,8 +353,12 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a
|
|
|
355
353
|
}
|
|
356
354
|
}
|
|
357
355
|
|
|
358
|
-
|
|
359
|
-
|
|
356
|
+
/**
|
|
357
|
+
* addBidResponse may return a Promise; if it does, the auction will attempt to
|
|
358
|
+
* wait for it to complete (successfully or not) before closing.
|
|
359
|
+
*/
|
|
360
|
+
export const addBidResponse = hook('sync', function(adUnitCode, bid) {
|
|
361
|
+
return this.dispatch.call(this.bidderRequest, adUnitCode, bid);
|
|
360
362
|
}, 'addBidResponse');
|
|
361
363
|
|
|
362
364
|
export const addBidderRequests = hook('sync', function(bidderRequests) {
|
|
@@ -374,6 +376,32 @@ export function auctionCallbacks(auctionDone, auctionInstance) {
|
|
|
374
376
|
let allAdapterCalledDone = false;
|
|
375
377
|
let bidderRequestsDone = new Set();
|
|
376
378
|
let bidResponseMap = {};
|
|
379
|
+
const ready = {};
|
|
380
|
+
|
|
381
|
+
function waitFor(bidderRequest, result) {
|
|
382
|
+
const id = bidderRequest.bidderRequestId;
|
|
383
|
+
if (ready[id] == null) {
|
|
384
|
+
ready[id] = Promise.resolve();
|
|
385
|
+
}
|
|
386
|
+
ready[id] = ready[id].then(() => Promise.resolve(result).catch(() => {}))
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function guard(bidderRequest, fn) {
|
|
390
|
+
let timeout = bidderRequest.timeout;
|
|
391
|
+
if (timeout == null || timeout > auctionInstance.getTimeout()) {
|
|
392
|
+
timeout = auctionInstance.getTimeout();
|
|
393
|
+
}
|
|
394
|
+
const timeRemaining = auctionInstance.getAuctionStart() + timeout - Date.now();
|
|
395
|
+
const wait = ready[bidderRequest.bidderRequestId];
|
|
396
|
+
if (wait != null && timeRemaining > 0) {
|
|
397
|
+
Promise.race([
|
|
398
|
+
new Promise((resolve) => setTimeout(resolve, timeRemaining)),
|
|
399
|
+
wait
|
|
400
|
+
]).then(fn);
|
|
401
|
+
} else {
|
|
402
|
+
fn();
|
|
403
|
+
}
|
|
404
|
+
}
|
|
377
405
|
|
|
378
406
|
function afterBidAdded() {
|
|
379
407
|
outstandingBidsAdded--;
|
|
@@ -382,7 +410,7 @@ export function auctionCallbacks(auctionDone, auctionInstance) {
|
|
|
382
410
|
}
|
|
383
411
|
}
|
|
384
412
|
|
|
385
|
-
function
|
|
413
|
+
function handleBidResponse(adUnitCode, bid) {
|
|
386
414
|
let bidderRequest = this;
|
|
387
415
|
|
|
388
416
|
bidResponseMap[bid.requestId] = true;
|
|
@@ -429,8 +457,15 @@ export function auctionCallbacks(auctionDone, auctionInstance) {
|
|
|
429
457
|
}
|
|
430
458
|
|
|
431
459
|
return {
|
|
432
|
-
addBidResponse
|
|
433
|
-
|
|
460
|
+
addBidResponse: function (...args) {
|
|
461
|
+
waitFor(this, addBidResponse.apply({
|
|
462
|
+
dispatch: handleBidResponse,
|
|
463
|
+
bidderRequest: this
|
|
464
|
+
}, args));
|
|
465
|
+
},
|
|
466
|
+
adapterDone: function () {
|
|
467
|
+
guard(this, adapterDone.bind(this))
|
|
468
|
+
}
|
|
434
469
|
}
|
|
435
470
|
}
|
|
436
471
|
|
package/src/prebid.js
CHANGED
|
@@ -19,6 +19,7 @@ import { adunitCounter } from './adUnits.js';
|
|
|
19
19
|
import { executeRenderer, isRendererRequired } from './Renderer.js';
|
|
20
20
|
import { createBid } from './bidfactory.js';
|
|
21
21
|
import { storageCallbacks } from './storageManager.js';
|
|
22
|
+
import { emitAdRenderSucceeded, emitAdRenderFail } from './adRendering.js';
|
|
22
23
|
|
|
23
24
|
const $$PREBID_GLOBAL$$ = getGlobal();
|
|
24
25
|
const CONSTANTS = require('./constants.json');
|
|
@@ -27,7 +28,7 @@ const events = require('./events.js');
|
|
|
27
28
|
const { triggerUserSyncs } = userSync;
|
|
28
29
|
|
|
29
30
|
/* private variables */
|
|
30
|
-
const { ADD_AD_UNITS, BID_WON, REQUEST_BIDS, SET_TARGETING,
|
|
31
|
+
const { ADD_AD_UNITS, BID_WON, REQUEST_BIDS, SET_TARGETING, STALE_RENDER } = CONSTANTS.EVENTS;
|
|
31
32
|
const { PREVENT_WRITING_ON_MAIN_DOCUMENT, NO_AD, EXCEPTION, CANNOT_FIND_AD, MISSING_DOC_OR_ADID } = CONSTANTS.AD_RENDER_FAILED_REASON;
|
|
32
33
|
|
|
33
34
|
const eventValidators = {
|
|
@@ -146,7 +147,7 @@ function validateNativeMediaType(adUnit) {
|
|
|
146
147
|
function validateAdUnitPos(adUnit, mediaType) {
|
|
147
148
|
let pos = deepAccess(adUnit, `mediaTypes.${mediaType}.pos`);
|
|
148
149
|
|
|
149
|
-
if (!pos ||
|
|
150
|
+
if (!isNumber(pos) || isNaN(pos) || !isFinite(pos)) {
|
|
150
151
|
let warning = `Value of property 'pos' on ad unit ${adUnit.code} should be of type: Number`;
|
|
151
152
|
|
|
152
153
|
logWarn(warning);
|
|
@@ -385,23 +386,6 @@ $$PREBID_GLOBAL$$.setTargetingForAst = function (adUnitCodes) {
|
|
|
385
386
|
events.emit(SET_TARGETING, targeting.getAllTargeting());
|
|
386
387
|
};
|
|
387
388
|
|
|
388
|
-
function emitAdRenderFail({ reason, message, bid, id }) {
|
|
389
|
-
const data = { reason, message };
|
|
390
|
-
if (bid) data.bid = bid;
|
|
391
|
-
if (id) data.adId = id;
|
|
392
|
-
|
|
393
|
-
logError(message);
|
|
394
|
-
events.emit(AD_RENDER_FAILED, data);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function emitAdRenderSucceeded({ doc, bid, id }) {
|
|
398
|
-
const data = { doc };
|
|
399
|
-
if (bid) data.bid = bid;
|
|
400
|
-
if (id) data.adId = id;
|
|
401
|
-
|
|
402
|
-
events.emit(AD_RENDER_SUCCEEDED, data);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
389
|
/**
|
|
406
390
|
* This function will check for presence of given node in given parent. If not present - will inject it.
|
|
407
391
|
* @param {Node} node node, whose existance is in question
|
package/src/secureCreatives.js
CHANGED
|
@@ -4,18 +4,25 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import events from './events.js';
|
|
7
|
-
import {
|
|
7
|
+
import {fireNativeTrackers, getAllAssetsMessage, getAssetMessage} from './native.js';
|
|
8
8
|
import constants from './constants.json';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import {deepAccess, isApnGetTagDefined, isGptPubadsDefined, logError, logWarn, replaceAuctionPrice} from './utils.js';
|
|
10
|
+
import {auctionManager} from './auctionManager.js';
|
|
11
11
|
import find from 'core-js-pure/features/array/find.js';
|
|
12
|
-
import { isRendererRequired
|
|
12
|
+
import {executeRenderer, isRendererRequired} from './Renderer.js';
|
|
13
13
|
import includes from 'core-js-pure/features/array/includes.js';
|
|
14
|
-
import {
|
|
14
|
+
import {config} from './config.js';
|
|
15
|
+
import {emitAdRenderFail, emitAdRenderSucceeded} from './adRendering.js';
|
|
15
16
|
|
|
16
17
|
const BID_WON = constants.EVENTS.BID_WON;
|
|
17
18
|
const STALE_RENDER = constants.EVENTS.STALE_RENDER;
|
|
18
19
|
|
|
20
|
+
const HANDLER_MAP = {
|
|
21
|
+
'Prebid Request': handleRenderRequest,
|
|
22
|
+
'Prebid Native': handleNativeRequest,
|
|
23
|
+
'Prebid Event': handleEventRequest,
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
export function listenMessagesFromCreative() {
|
|
20
27
|
window.addEventListener('message', receiveMessage, false);
|
|
21
28
|
}
|
|
@@ -29,52 +36,114 @@ export function receiveMessage(ev) {
|
|
|
29
36
|
return;
|
|
30
37
|
}
|
|
31
38
|
|
|
32
|
-
if (data && data.adId) {
|
|
39
|
+
if (data && data.adId && data.message) {
|
|
33
40
|
const adObject = find(auctionManager.getBidsReceived(), function (bid) {
|
|
34
41
|
return bid.adId === data.adId;
|
|
35
42
|
});
|
|
43
|
+
if (HANDLER_MAP.hasOwnProperty(data.message)) {
|
|
44
|
+
HANDLER_MAP[data.message](ev, data, adObject);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
36
48
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
function handleRenderRequest(ev, data, adObject) {
|
|
50
|
+
if (adObject == null) {
|
|
51
|
+
emitAdRenderFail({
|
|
52
|
+
reason: constants.AD_RENDER_FAILED_REASON.CANNOT_FIND_AD,
|
|
53
|
+
message: `Cannot find ad '${data.adId}' for cross-origin render request`,
|
|
54
|
+
id: data.adId
|
|
55
|
+
});
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (adObject.status === constants.BID_STATUS.RENDERED) {
|
|
59
|
+
logWarn(`Ad id ${adObject.adId} has been rendered before`);
|
|
60
|
+
events.emit(STALE_RENDER, adObject);
|
|
61
|
+
if (deepAccess(config.getConfig('auctionOptions'), 'suppressStaleRender')) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
45
65
|
|
|
46
|
-
|
|
66
|
+
try {
|
|
67
|
+
_sendAdToCreative(adObject, ev);
|
|
68
|
+
} catch (e) {
|
|
69
|
+
emitAdRenderFail({
|
|
70
|
+
reason: constants.AD_RENDER_FAILED_REASON.EXCEPTION,
|
|
71
|
+
message: e.message,
|
|
72
|
+
id: data.adId,
|
|
73
|
+
bid: adObject
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
47
77
|
|
|
48
|
-
|
|
49
|
-
|
|
78
|
+
// save winning bids
|
|
79
|
+
auctionManager.addWinningBid(adObject);
|
|
50
80
|
|
|
51
|
-
|
|
52
|
-
|
|
81
|
+
events.emit(BID_WON, adObject);
|
|
82
|
+
}
|
|
53
83
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
84
|
+
function handleNativeRequest(ev, data, adObject) {
|
|
85
|
+
// handle this script from native template in an ad server
|
|
86
|
+
// window.parent.postMessage(JSON.stringify({
|
|
87
|
+
// message: 'Prebid Native',
|
|
88
|
+
// adId: '%%PATTERN:hb_adid%%'
|
|
89
|
+
// }), '*');
|
|
90
|
+
if (adObject == null) {
|
|
91
|
+
logError(`Cannot find ad '${data.adId}' for x-origin event request`);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
switch (data.action) {
|
|
95
|
+
case 'assetRequest':
|
|
96
|
+
reply(getAssetMessage(data, adObject));
|
|
97
|
+
break;
|
|
98
|
+
case 'allAssetRequest':
|
|
99
|
+
reply(getAllAssetsMessage(data, adObject));
|
|
100
|
+
break;
|
|
101
|
+
case 'resizeNativeHeight':
|
|
102
|
+
adObject.height = data.height;
|
|
103
|
+
adObject.width = data.width;
|
|
104
|
+
resizeRemoteCreative(adObject);
|
|
105
|
+
break;
|
|
106
|
+
default:
|
|
107
|
+
const trackerType = fireNativeTrackers(data, adObject);
|
|
108
|
+
if (trackerType === 'click') {
|
|
109
|
+
return;
|
|
76
110
|
}
|
|
77
|
-
|
|
111
|
+
auctionManager.addWinningBid(adObject);
|
|
112
|
+
events.emit(BID_WON, adObject);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function reply(message) {
|
|
116
|
+
ev.source.postMessage(JSON.stringify(message), ev.origin);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function handleEventRequest(ev, data, adObject) {
|
|
121
|
+
if (adObject == null) {
|
|
122
|
+
logError(`Cannot find ad '${data.adId}' for x-origin event request`);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (adObject.status !== constants.BID_STATUS.RENDERED) {
|
|
126
|
+
logWarn(`Received x-origin event request without corresponding render request for ad '${data.adId}'`);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
switch (data.event) {
|
|
130
|
+
case constants.EVENTS.AD_RENDER_FAILED:
|
|
131
|
+
emitAdRenderFail({
|
|
132
|
+
bid: adObject,
|
|
133
|
+
id: data.adId,
|
|
134
|
+
reason: data.info.reason,
|
|
135
|
+
message: data.info.message
|
|
136
|
+
});
|
|
137
|
+
break;
|
|
138
|
+
case constants.EVENTS.AD_RENDER_SUCCEEDED:
|
|
139
|
+
emitAdRenderSucceeded({
|
|
140
|
+
doc: null,
|
|
141
|
+
bid: adObject,
|
|
142
|
+
id: data.adId
|
|
143
|
+
});
|
|
144
|
+
break;
|
|
145
|
+
default:
|
|
146
|
+
logError(`Received x-origin event request for unsupported event: '${data.event}' (adId: '${data.adId}')`)
|
|
78
147
|
}
|
|
79
148
|
}
|
|
80
149
|
|
package/src/utils.js
CHANGED
|
@@ -22,7 +22,17 @@ let consoleLogExists = Boolean(consoleExists && window.console.log);
|
|
|
22
22
|
let consoleInfoExists = Boolean(consoleExists && window.console.info);
|
|
23
23
|
let consoleWarnExists = Boolean(consoleExists && window.console.warn);
|
|
24
24
|
let consoleErrorExists = Boolean(consoleExists && window.console.error);
|
|
25
|
-
|
|
25
|
+
|
|
26
|
+
const emitEvent = (function () {
|
|
27
|
+
// lazy load events to avoid circular import
|
|
28
|
+
let ev;
|
|
29
|
+
return function() {
|
|
30
|
+
if (ev == null) {
|
|
31
|
+
ev = require('./events.js');
|
|
32
|
+
}
|
|
33
|
+
return ev.emit.apply(ev, arguments);
|
|
34
|
+
}
|
|
35
|
+
})();
|
|
26
36
|
|
|
27
37
|
// this allows stubbing of utility functions that are used internally by other utility functions
|
|
28
38
|
export const internal = {
|
|
@@ -265,14 +275,14 @@ export function logWarn() {
|
|
|
265
275
|
if (debugTurnedOn() && consoleWarnExists) {
|
|
266
276
|
console.warn.apply(console, decorateLog(arguments, 'WARNING:'));
|
|
267
277
|
}
|
|
268
|
-
|
|
278
|
+
emitEvent(CONSTANTS.EVENTS.AUCTION_DEBUG, {type: 'WARNING', arguments: arguments});
|
|
269
279
|
}
|
|
270
280
|
|
|
271
281
|
export function logError() {
|
|
272
282
|
if (debugTurnedOn() && consoleErrorExists) {
|
|
273
283
|
console.error.apply(console, decorateLog(arguments, 'ERROR:'));
|
|
274
284
|
}
|
|
275
|
-
|
|
285
|
+
emitEvent(CONSTANTS.EVENTS.AUCTION_DEBUG, {type: 'ERROR', arguments: arguments});
|
|
276
286
|
}
|
|
277
287
|
|
|
278
288
|
function decorateLog(args, prefix) {
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const orig = {};
|
|
2
|
+
['resolve', 'reject', 'all', 'race', 'allSettled'].forEach((k) => orig[k] = Promise[k].bind(Promise))
|
|
3
|
+
|
|
4
|
+
// Callbacks attached through Promise.resolve(value).then(...) will usually
|
|
5
|
+
// not execute immediately even if `value` is immediately available. This
|
|
6
|
+
// breaks tests that were written before promises even though they are semantically still valid.
|
|
7
|
+
// They can be made to work by making promises quasi-synchronous.
|
|
8
|
+
|
|
9
|
+
export function SyncPromise(value, fail = false) {
|
|
10
|
+
if (value instanceof SyncPromise) {
|
|
11
|
+
return value;
|
|
12
|
+
} else if (typeof value === 'object' && typeof value.then === 'function') {
|
|
13
|
+
return orig.resolve(value);
|
|
14
|
+
} else {
|
|
15
|
+
Object.assign(this, {
|
|
16
|
+
then: function (cb, err) {
|
|
17
|
+
const handler = fail ? err : cb;
|
|
18
|
+
if (handler != null) {
|
|
19
|
+
return new SyncPromise(handler(value));
|
|
20
|
+
} else {
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
catch: function (cb) {
|
|
25
|
+
if (fail) {
|
|
26
|
+
return new SyncPromise(cb(value))
|
|
27
|
+
} else {
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
finally: function (cb) {
|
|
32
|
+
cb();
|
|
33
|
+
return this;
|
|
34
|
+
},
|
|
35
|
+
__value: fail ? {status: 'rejected', reason: value} : {status: 'fulfilled', value}
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Object.assign(SyncPromise, {
|
|
41
|
+
resolve: (val) => new SyncPromise(val),
|
|
42
|
+
reject: (val) => new SyncPromise(val, true),
|
|
43
|
+
race: (promises) => promises.find((p) => p instanceof SyncPromise) || orig.race(promises),
|
|
44
|
+
allSettled: (promises) => {
|
|
45
|
+
if (promises.every((p) => p instanceof SyncPromise)) {
|
|
46
|
+
return new SyncPromise(promises.map((p) => p.__value))
|
|
47
|
+
} else {
|
|
48
|
+
return orig.allSettled(promises);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
all: (promises) => {
|
|
52
|
+
if (promises.every((p) => p instanceof SyncPromise)) {
|
|
53
|
+
return SyncPromise.allSettled(promises).then((result) => {
|
|
54
|
+
const err = result.find((r) => r.status === 'rejected');
|
|
55
|
+
if (err != null) {
|
|
56
|
+
return new SyncPromise(err.reason, true);
|
|
57
|
+
} else {
|
|
58
|
+
return new SyncPromise(result.map((r) => r.value))
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
} else {
|
|
62
|
+
return orig.all(promises);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
export function synchronizePromise(sandbox) {
|
|
68
|
+
Object.keys(orig).forEach((k) => {
|
|
69
|
+
sandbox.stub(window.Promise, k).callsFake(SyncPromise[k]);
|
|
70
|
+
})
|
|
71
|
+
}
|