• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

prebid / Prebid.js / 21696548993

05 Feb 2026 02:34AM UTC coverage: 96.234% (+33.1%) from 63.163%
21696548993

Pull #14383

github

c914e8
web-flow
Merge branch 'master' into master
Pull Request #14383: Optidigital Bid Adapter: Adding ortb2 device, keywords, addtlConsent, gpid

41808 of 51387 branches covered (81.36%)

55 of 55 new or added lines in 2 files covered. (100.0%)

48 existing lines in 2 files now uncovered.

209780 of 217990 relevant lines covered (96.23%)

71.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.92
/src/adloader.js
1
import { LOAD_EXTERNAL_SCRIPT } from './activities/activities.js';
2
import { activityParams } from './activities/activityParams.js';
3
import { isActivityAllowed } from './activities/rules.js';
4

5
import { insertElement, logError, logWarn, setScriptAttributes } from './utils.js';
6

7
const _requestCache = new WeakMap();
8✔
8

9
/**
10
 * Loads external javascript. Can only be used if external JS is approved by Prebid. See https://github.com/prebid/prebid-js-external-js-template#policy
11
 * Each unique URL will be loaded at most 1 time.
12
 * @param {string} url the url to load
13
 * @param {string} moduleType moduleType of the module requesting this resource
14
 * @param {string} moduleCode bidderCode or module code of the module requesting this resource
15
 * @param {function} [callback] callback function to be called after the script is loaded
16
 * @param {Document} [doc] the context document, in which the script will be loaded, defaults to loaded document
17
 * @param {object} attributes an object of attributes to be added to the script with setAttribute by [key] and [value]; Only the attributes passed in the first request of a url will be added.
18
 */
19
export function loadExternalScript(url, moduleType, moduleCode, callback, doc, attributes) {
20
  if (!isActivityAllowed(LOAD_EXTERNAL_SCRIPT, activityParams(moduleType, moduleCode))) {
11✔
21
    return;
1✔
22
  }
23

24
  if (!moduleCode || !url) {
10✔
25
    logError('cannot load external script without url and moduleCode');
1✔
26
    return;
1✔
27
  }
28

29
  if (!doc) {
9✔
30
    doc = document; // provide a "valid" key for the WeakMap
3✔
31
  }
32
  // only load each asset once
33
  const storedCachedObject = getCacheObject(doc, url);
9✔
34
  if (storedCachedObject) {
9✔
35
    if (callback && typeof callback === 'function') {
4✔
36
      if (storedCachedObject.loaded) {
3!
37
        // invokeCallbacks immediately
38
        callback();
×
39
      } else {
40
        // queue the callback
41
        storedCachedObject.callbacks.push(callback);
3✔
42
      }
43
    }
44
    return storedCachedObject.tag;
4✔
45
  }
46
  const cachedDocObj = _requestCache.get(doc) || {};
5✔
47
  const cacheObject = {
5✔
48
    loaded: false,
49
    tag: null,
50
    callbacks: []
51
  };
52
  cachedDocObj[url] = cacheObject;
5✔
53
  _requestCache.set(doc, cachedDocObj);
5✔
54

55
  if (callback && typeof callback === 'function') {
5✔
56
    cacheObject.callbacks.push(callback);
3✔
57
  }
58

59
  logWarn(`module ${moduleCode} is loading external JavaScript`);
5✔
60
  return requestResource(url, function () {
5✔
UNCOV
61
    cacheObject.loaded = true;
×
UNCOV
62
    try {
×
63
      for (let i = 0; i < cacheObject.callbacks.length; i++) {
×
64
        cacheObject.callbacks[i]();
×
65
      }
66
    } catch (e) {
UNCOV
67
      logError('Error executing callback', 'adloader.js:loadExternalScript', e);
×
68
    }
69
  }, doc, attributes);
70

71
  function requestResource(tagSrc, callback, doc, attributes) {
72
    if (!doc) {
5!
UNCOV
73
      doc = document;
×
74
    }
75
    var jptScript = doc.createElement('script');
5✔
76
    jptScript.type = 'text/javascript';
5✔
77
    jptScript.async = true;
5✔
78

79
    const cacheObject = getCacheObject(doc, url);
5✔
80
    if (cacheObject) {
5✔
81
      cacheObject.tag = jptScript;
5✔
82
    }
83

84
    if (jptScript.readyState) {
5!
UNCOV
85
      jptScript.onreadystatechange = function () {
×
UNCOV
86
        if (jptScript.readyState === 'loaded' || jptScript.readyState === 'complete') {
×
UNCOV
87
          jptScript.onreadystatechange = null;
×
UNCOV
88
          callback();
×
89
        }
90
      };
91
    } else {
92
      jptScript.onload = function () {
5✔
UNCOV
93
        callback();
×
94
      };
95
    }
96

97
    jptScript.src = tagSrc;
5✔
98

99
    if (attributes) {
5✔
100
      setScriptAttributes(jptScript, attributes);
1✔
101
    }
102

103
    // add the new script tag to the page
104
    insertElement(jptScript, doc);
5✔
105

106
    return jptScript;
5✔
107
  }
108
  function getCacheObject(doc, url) {
109
    const cachedDocObj = _requestCache.get(doc);
14✔
110
    if (cachedDocObj && cachedDocObj[url]) {
14✔
111
      return cachedDocObj[url];
9✔
112
    }
113
    return null; // return new cache object?
5✔
114
  }
115
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc