From 2c769e948a68b291342a33d46e5667a764ebf1d8 Mon Sep 17 00:00:00 2001 From: Andrew Slagle <42588549+spotxslagle@users.noreply.github.com> Date: Sat, 23 Jul 2022 09:57:19 -0600 Subject: [PATCH] Prebid Core : add setScriptAttributes to adloader in Utils (#8624) * Allow SpotX module to load script without appendChild * Fix SpotX spec to no longer use appendChild * Restore spotx files * Formatting fixes * Unit test for setScriptAttributes * Unit test and formatting fix * Formatting fix * Comment that attributes are added once only --- src/adloader.js | 14 ++++++++++---- src/utils.js | 13 +++++++++++++ test/spec/adloader_spec.js | 23 +++++++++++++++++++++++ test/spec/utils_spec.js | 16 ++++++++++++++++ 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/adloader.js b/src/adloader.js index 28acec136f6..1e7995a9dc6 100644 --- a/src/adloader.js +++ b/src/adloader.js @@ -1,5 +1,5 @@ import {includes} from './polyfill.js'; -import { logError, logWarn, insertElement } from './utils.js'; +import { logError, logWarn, insertElement, setScriptAttributes } from './utils.js'; const _requestCache = new WeakMap(); // The below list contains modules or vendors whom Prebid allows to load external JS. @@ -9,6 +9,7 @@ const _approvedLoadExternalJSList = [ 'criteo', 'outstream', 'adagio', + 'spotx', 'browsi', 'brandmetrics', 'justtag', @@ -27,8 +28,9 @@ const _approvedLoadExternalJSList = [ * @param {string} moduleCode bidderCode or module code of the module requesting this resource * @param {function} [callback] callback function to be called after the script is loaded * @param {Document} [doc] the context document, in which the script will be loaded, defaults to loaded document + * @param {object} 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. */ -export function loadExternalScript(url, moduleCode, callback, doc) { +export function loadExternalScript(url, moduleCode, callback, doc, attributes) { if (!moduleCode || !url) { logError('cannot load external script without url and moduleCode'); return; @@ -77,9 +79,9 @@ export function loadExternalScript(url, moduleCode, callback, doc) { } catch (e) { logError('Error executing callback', 'adloader.js:loadExternalScript', e); } - }, doc); + }, doc, attributes); - function requestResource(tagSrc, callback, doc) { + function requestResource(tagSrc, callback, doc, attributes) { if (!doc) { doc = document; } @@ -107,6 +109,10 @@ export function loadExternalScript(url, moduleCode, callback, doc) { jptScript.src = tagSrc; + if (attributes) { + setScriptAttributes(jptScript, attributes); + } + // add the new script tag to the page insertElement(jptScript, doc); diff --git a/src/utils.js b/src/utils.js index b53475af912..9434a163133 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1368,3 +1368,16 @@ export function safeJSONParse(data) { return JSON.parse(data); } catch (e) {} } + +/** + * Sets dataset attributes on a script + * @param {Script} script + * @param {object} attributes + */ +export function setScriptAttributes(script, attributes) { + for (let key in attributes) { + if (attributes.hasOwnProperty(key)) { + script.setAttribute(key, attributes[key]); + } + } +} diff --git a/test/spec/adloader_spec.js b/test/spec/adloader_spec.js index 0c50e66c63c..b775ec76e9b 100644 --- a/test/spec/adloader_spec.js +++ b/test/spec/adloader_spec.js @@ -69,4 +69,27 @@ describe('adLoader', function () { expect(utilsinsertElementStub.callCount).to.equal(2); }); }); + + it('attaches passed attributes to a script', function () { + const doc = { + createElement: function () { + return { + setAttribute: function (key, value) { + this[key] = value; + } + } + }, + getElementsByTagName: function() { + return { + firstChild: { + insertBefore: function() {} + } + } + } + }, + attrs = {'z': 'A', 'y': 2}; + let script = adLoader.loadExternalScript('someUrl', 'criteo', undefined, doc, attrs); + expect(script.z).to.equal('A'); + expect(script.y).to.equal(2); + }); }); diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 50a95b079c9..500f479355d 100644 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -1243,4 +1243,20 @@ describe('Utils', function () { }); }); }); + + describe('setScriptAttributes', () => { + it('correctly adds attributes from an object', () => { + const script = document.createElement('script'), + attrs = { + 'data-first_prop': '1', + 'data-second_prop': 'b', + 'id': 'newId' + }; + script.id = 'oldId'; + utils.setScriptAttributes(script, attrs); + expect(script.dataset['first_prop']).to.equal('1'); + expect(script.dataset.second_prop).to.equal('b'); + expect(script.id).to.equal('newId'); + }); + }); });