UNPKG

80.7 kBJavaScriptView Raw
1var _satellite = (function () {
2'use strict';
3
4if (!window.atob) { console.warn('Adobe Launch is unsupported in IE 9 and below.'); return; }
5
6/***************************************************************************************
7 * (c) 2017 Adobe. All rights reserved.
8 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License. You may obtain a copy
10 * of the License at http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software distributed under
13 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
14 * OF ANY KIND, either express or implied. See the License for the specific language
15 * governing permissions and limitations under the License.
16 ****************************************************************************************/
17
18/**
19 * Log levels.
20 * @readonly
21 * @enum {string}
22 * @private
23 */
24var levels = {
25 LOG: 'log',
26 INFO: 'info',
27 WARN: 'warn',
28 ERROR: 'error'
29};
30
31/**
32 * Rocket unicode surrogate pair.
33 * @type {string}
34 */
35var ROCKET = '\uD83D\uDE80';
36
37/**
38 * The user's internet explorer version. If they're not running internet explorer, then it should
39 * be NaN.
40 * @type {Number}
41 */
42var ieVersion = parseInt((/msie (\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1]);
43
44/**
45 * Prefix to use on all messages. The rocket unicode doesn't work on IE 10.
46 * @type {string}
47 */
48var launchPrefix = ieVersion === 10 ? '[Launch]' : ROCKET;
49
50/**
51 * Whether logged messages should be output to the console.
52 * @type {boolean}
53 */
54var outputEnabled = false;
55
56/**
57 * Processes a log message.
58 * @param {string} level The level of message to log.
59 * @param {...*} arg Any argument to be logged.
60 * @private
61 */
62var process = function(level) {
63 if (outputEnabled && window.console) {
64 var logArguments = Array.prototype.slice.call(arguments, 1);
65 logArguments.unshift(launchPrefix);
66 window.console[level].apply(window.console, logArguments);
67 }
68};
69
70/**
71 * Outputs a message to the web console.
72 * @param {...*} arg Any argument to be logged.
73 */
74var log = process.bind(null, levels.LOG);
75
76/**
77 * Outputs informational message to the web console. In some browsers a small "i" icon is
78 * displayed next to these items in the web console's log.
79 * @param {...*} arg Any argument to be logged.
80 */
81var info = process.bind(null, levels.INFO);
82
83/**
84 * Outputs a warning message to the web console.
85 * @param {...*} arg Any argument to be logged.
86 */
87var warn = process.bind(null, levels.WARN);
88
89/**
90 * Outputs an error message to the web console.
91 * @param {...*} arg Any argument to be logged.
92 */
93var error = process.bind(null, levels.ERROR);
94
95var logger = {
96 log: log,
97 info: info,
98 warn: warn,
99 error: error,
100 /**
101 * Whether logged messages should be output to the console.
102 * @type {boolean}
103 */
104 get outputEnabled() {
105 return outputEnabled;
106 },
107 set outputEnabled(value) {
108 outputEnabled = value;
109 },
110 /**
111 * Creates a logging utility that only exposes logging functionality and prefixes all messages
112 * with an identifier.
113 */
114 createPrefixedLogger: function(identifier) {
115 var loggerSpecificPrefix = '[' + identifier + ']';
116
117 return {
118 log: log.bind(null, loggerSpecificPrefix),
119 info: info.bind(null, loggerSpecificPrefix),
120 warn: warn.bind(null, loggerSpecificPrefix),
121 error: error.bind(null, loggerSpecificPrefix)
122 };
123 }
124};
125
126/***************************************************************************************
127 * (c) 2017 Adobe. All rights reserved.
128 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
129 * you may not use this file except in compliance with the License. You may obtain a copy
130 * of the License at http://www.apache.org/licenses/LICENSE-2.0
131 *
132 * Unless required by applicable law or agreed to in writing, software distributed under
133 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
134 * OF ANY KIND, either express or implied. See the License for the specific language
135 * governing permissions and limitations under the License.
136 ****************************************************************************************/
137
138
139
140/**
141 * Replacing any variable tokens (%myDataElement%, %this.foo%, etc.) with their associated values.
142 * A new string, object, or array will be created; the thing being processed will never be
143 * modified.
144 * @param {*} thing Thing potentially containing variable tokens. Objects and arrays will be
145 * deeply processed.
146 * @param {HTMLElement} [element] Associated HTML element. Used for special tokens
147 * (%this.something%).
148 * @param {Object} [event] Associated event. Used for special tokens (%event.something%,
149 * %target.something%)
150 * @returns {*} A processed value.
151 */
152var createReplaceTokens = function(isVar, getVar, undefinedVarsReturnEmpty) {
153 var replaceTokensInString;
154 var replaceTokensInObject;
155 var replaceTokensInArray;
156 var replaceTokens;
157 var variablesBeingRetrieved = [];
158
159 var getVarValue = function(token, variableName, syntheticEvent) {
160 if (!isVar(variableName)) {
161 return token;
162 }
163
164 variablesBeingRetrieved.push(variableName);
165 var val = getVar(variableName, syntheticEvent);
166 variablesBeingRetrieved.pop();
167 return val == null && undefinedVarsReturnEmpty ? '' : val;
168 };
169
170 /**
171 * Perform variable substitutions to a string where tokens are specified in the form %foo%.
172 * If the only content of the string is a single data element token, then the raw data element
173 * value will be returned instead.
174 *
175 * @param str {string} The string potentially containing data element tokens.
176 * @param element {HTMLElement} The element to use for tokens in the form of %this.property%.
177 * @param event {Object} The event object to use for tokens in the form of %target.property%.
178 * @returns {*}
179 */
180 replaceTokensInString = function(str, syntheticEvent) {
181 // Is the string a single data element token and nothing else?
182 var result = /^%([^%]+)%$/.exec(str);
183
184 if (result) {
185 return getVarValue(str, result[1], syntheticEvent);
186 } else {
187 return str.replace(/%(.+?)%/g, function(token, variableName) {
188 return getVarValue(token, variableName, syntheticEvent);
189 });
190 }
191 };
192
193 replaceTokensInObject = function(obj, syntheticEvent) {
194 var ret = {};
195 var keys = Object.keys(obj);
196 for (var i = 0; i < keys.length; i++) {
197 var key = keys[i];
198 var value = obj[key];
199 ret[key] = replaceTokens(value, syntheticEvent);
200 }
201 return ret;
202 };
203
204 replaceTokensInArray = function(arr, syntheticEvent) {
205 var ret = [];
206 for (var i = 0, len = arr.length; i < len; i++) {
207 ret.push(replaceTokens(arr[i], syntheticEvent));
208 }
209 return ret;
210 };
211
212 replaceTokens = function(thing, syntheticEvent) {
213 if (typeof thing === 'string') {
214 return replaceTokensInString(thing, syntheticEvent);
215 } else if (Array.isArray(thing)) {
216 return replaceTokensInArray(thing, syntheticEvent);
217 } else if (typeof thing === 'object' && thing !== null) {
218 return replaceTokensInObject(thing, syntheticEvent);
219 }
220
221 return thing;
222 };
223
224 return function(thing, syntheticEvent) {
225 // It's possible for a data element to reference another data element. Because of this,
226 // we need to prevent circular dependencies from causing an infinite loop.
227 if (variablesBeingRetrieved.length > 10) {
228 logger.error('Data element circular reference detected: ' +
229 variablesBeingRetrieved.join(' -> '));
230 return thing;
231 }
232
233 return replaceTokens(thing, syntheticEvent);
234 };
235};
236
237/***************************************************************************************
238 * (c) 2017 Adobe. All rights reserved.
239 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
240 * you may not use this file except in compliance with the License. You may obtain a copy
241 * of the License at http://www.apache.org/licenses/LICENSE-2.0
242 *
243 * Unless required by applicable law or agreed to in writing, software distributed under
244 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
245 * OF ANY KIND, either express or implied. See the License for the specific language
246 * governing permissions and limitations under the License.
247 ****************************************************************************************/
248
249var createSetCustomVar = function(customVars) {
250 return function() {
251 if (typeof arguments[0] === 'string') {
252 customVars[arguments[0]] = arguments[1];
253 } else if (arguments[0]) { // assume an object literal
254 var mapping = arguments[0];
255 for (var key in mapping) {
256 customVars[key] = mapping[key];
257 }
258 }
259 };
260};
261
262/***************************************************************************************
263 * (c) 2017 Adobe. All rights reserved.
264 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
265 * you may not use this file except in compliance with the License. You may obtain a copy
266 * of the License at http://www.apache.org/licenses/LICENSE-2.0
267 *
268 * Unless required by applicable law or agreed to in writing, software distributed under
269 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
270 * OF ANY KIND, either express or implied. See the License for the specific language
271 * governing permissions and limitations under the License.
272 ****************************************************************************************/
273
274/**
275 * "Cleans" text by trimming the string and removing spaces and newlines.
276 * @param {string} str The string to clean.
277 * @returns {string}
278 */
279var cleanText = function(str) {
280 return typeof str === 'string' ? str.replace(/\s+/g, ' ').trim() : str;
281};
282
283var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
284
285
286
287
288
289function createCommonjsModule(fn, module) {
290 return module = { exports: {} }, fn(module, module.exports), module.exports;
291}
292
293var js_cookie = createCommonjsModule(function (module, exports) {
294/*!
295 * JavaScript Cookie v2.1.4
296 * https://github.com/js-cookie/js-cookie
297 *
298 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
299 * Released under the MIT license
300 */
301(function (factory) {
302 var registeredInModuleLoader = false;
303 if (typeof undefined === 'function' && undefined.amd) {
304 undefined(factory);
305 registeredInModuleLoader = true;
306 }
307 {
308 module.exports = factory();
309 registeredInModuleLoader = true;
310 }
311 if (!registeredInModuleLoader) {
312 var OldCookies = window.Cookies;
313 var api = window.Cookies = factory();
314 api.noConflict = function () {
315 window.Cookies = OldCookies;
316 return api;
317 };
318 }
319}(function () {
320 function extend () {
321 var i = 0;
322 var result = {};
323 for (; i < arguments.length; i++) {
324 var attributes = arguments[ i ];
325 for (var key in attributes) {
326 result[key] = attributes[key];
327 }
328 }
329 return result;
330 }
331
332 function init (converter) {
333 function api (key, value, attributes) {
334 var result;
335 if (typeof document === 'undefined') {
336 return;
337 }
338
339 // Write
340
341 if (arguments.length > 1) {
342 attributes = extend({
343 path: '/'
344 }, api.defaults, attributes);
345
346 if (typeof attributes.expires === 'number') {
347 var expires = new Date();
348 expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
349 attributes.expires = expires;
350 }
351
352 // We're using "expires" because "max-age" is not supported by IE
353 attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
354
355 try {
356 result = JSON.stringify(value);
357 if (/^[\{\[]/.test(result)) {
358 value = result;
359 }
360 } catch (e) {}
361
362 if (!converter.write) {
363 value = encodeURIComponent(String(value))
364 .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
365 } else {
366 value = converter.write(value, key);
367 }
368
369 key = encodeURIComponent(String(key));
370 key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
371 key = key.replace(/[\(\)]/g, escape);
372
373 var stringifiedAttributes = '';
374
375 for (var attributeName in attributes) {
376 if (!attributes[attributeName]) {
377 continue;
378 }
379 stringifiedAttributes += '; ' + attributeName;
380 if (attributes[attributeName] === true) {
381 continue;
382 }
383 stringifiedAttributes += '=' + attributes[attributeName];
384 }
385 return (document.cookie = key + '=' + value + stringifiedAttributes);
386 }
387
388 // Read
389
390 if (!key) {
391 result = {};
392 }
393
394 // To prevent the for loop in the first place assign an empty array
395 // in case there are no cookies at all. Also prevents odd result when
396 // calling "get()"
397 var cookies = document.cookie ? document.cookie.split('; ') : [];
398 var rdecode = /(%[0-9A-Z]{2})+/g;
399 var i = 0;
400
401 for (; i < cookies.length; i++) {
402 var parts = cookies[i].split('=');
403 var cookie = parts.slice(1).join('=');
404
405 if (cookie.charAt(0) === '"') {
406 cookie = cookie.slice(1, -1);
407 }
408
409 try {
410 var name = parts[0].replace(rdecode, decodeURIComponent);
411 cookie = converter.read ?
412 converter.read(cookie, name) : converter(cookie, name) ||
413 cookie.replace(rdecode, decodeURIComponent);
414
415 if (this.json) {
416 try {
417 cookie = JSON.parse(cookie);
418 } catch (e) {}
419 }
420
421 if (key === name) {
422 result = cookie;
423 break;
424 }
425
426 if (!key) {
427 result[name] = cookie;
428 }
429 } catch (e) {}
430 }
431
432 return result;
433 }
434
435 api.set = api;
436 api.get = function (key) {
437 return api.call(api, key);
438 };
439 api.getJSON = function () {
440 return api.apply({
441 json: true
442 }, [].slice.call(arguments));
443 };
444 api.defaults = {};
445
446 api.remove = function (key, attributes) {
447 api(key, '', extend(attributes, {
448 expires: -1
449 }));
450 };
451
452 api.withConverter = init;
453
454 return api;
455 }
456
457 return init(function () {});
458}));
459});
460
461'use strict';
462
463
464
465// js-cookie has other methods that we haven't exposed here. By limiting the exposed API,
466// we have a little more flexibility to change the underlying implementation later. If clear
467// use cases come up for needing the other methods js-cookie exposes, we can re-evaluate whether
468// we want to expose them here.
469var reactorCookie = {
470 get: js_cookie.get,
471 set: js_cookie.set,
472 remove: js_cookie.remove
473};
474
475'use strict';
476
477var reactorWindow = window;
478
479/***************************************************************************************
480 * (c) 2017 Adobe. All rights reserved.
481 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
482 * you may not use this file except in compliance with the License. You may obtain a copy
483 * of the License at http://www.apache.org/licenses/LICENSE-2.0
484 *
485 * Unless required by applicable law or agreed to in writing, software distributed under
486 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
487 * OF ANY KIND, either express or implied. See the License for the specific language
488 * governing permissions and limitations under the License.
489 ****************************************************************************************/
490
491
492var NAMESPACE = 'com.adobe.reactor.';
493
494var getNamespacedStorage = function(storageType, additionalNamespace) {
495 var finalNamespace = NAMESPACE + (additionalNamespace || '');
496
497 // When storage is disabled on Safari, the mere act of referencing window.localStorage
498 // or window.sessionStorage throws an error. For this reason, we wrap in a try-catch.
499 return {
500 /**
501 * Reads a value from storage.
502 * @param {string} name The name of the item to be read.
503 * @returns {string}
504 */
505 getItem: function(name) {
506 try {
507 return reactorWindow[storageType].getItem(finalNamespace + name);
508 } catch (e) {
509 return null;
510 }
511 },
512 /**
513 * Saves a value to storage.
514 * @param {string} name The name of the item to be saved.
515 * @param {string} value The value of the item to be saved.
516 * @returns {boolean} Whether the item was successfully saved to storage.
517 */
518 setItem: function(name, value) {
519 try {
520 reactorWindow[storageType].setItem(finalNamespace + name, value);
521 return true;
522 } catch (e) {
523 return false;
524 }
525 }
526 };
527};
528
529/***************************************************************************************
530 * (c) 2017 Adobe. All rights reserved.
531 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
532 * you may not use this file except in compliance with the License. You may obtain a copy
533 * of the License at http://www.apache.org/licenses/LICENSE-2.0
534 *
535 * Unless required by applicable law or agreed to in writing, software distributed under
536 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
537 * OF ANY KIND, either express or implied. See the License for the specific language
538 * governing permissions and limitations under the License.
539 ****************************************************************************************/
540
541
542
543
544var COOKIE_PREFIX = '_sdsat_';
545
546var DATA_ELEMENTS_NAMESPACE = 'dataElements.';
547var MIGRATED_KEY = 'dataElementCookiesMigrated';
548
549var reactorLocalStorage = getNamespacedStorage('localStorage');
550var dataElementSessionStorage = getNamespacedStorage('sessionStorage', DATA_ELEMENTS_NAMESPACE);
551var dataElementLocalStorage = getNamespacedStorage('localStorage', DATA_ELEMENTS_NAMESPACE);
552
553var storageDurations = {
554 PAGEVIEW: 'pageview',
555 SESSION: 'session',
556 VISITOR: 'visitor'
557};
558
559var pageviewCache = {};
560
561var serialize = function(value) {
562 var serialized;
563
564 try {
565 // On some browsers, with some objects, errors will be thrown during serialization. For example,
566 // in Chrome with the window object, it will throw "TypeError: Converting circular structure
567 // to JSON"
568 serialized = JSON.stringify(value);
569 } catch (e) {}
570
571 return serialized;
572};
573
574var setValue = function(key, storageDuration, value) {
575 var serializedValue;
576
577 switch (storageDuration) {
578 case storageDurations.PAGEVIEW:
579 pageviewCache[key] = value;
580 return;
581 case storageDurations.SESSION:
582 serializedValue = serialize(value);
583 if (serializedValue) {
584 dataElementSessionStorage.setItem(key, serializedValue);
585 }
586 return;
587 case storageDurations.VISITOR:
588 serializedValue = serialize(value);
589 if (serializedValue) {
590 dataElementLocalStorage.setItem(key, serializedValue);
591 }
592 return;
593 }
594};
595
596var getValue = function(key, storageDuration) {
597 var value;
598
599 // It should consistently return the same value if no stored item was found. We chose null,
600 // though undefined could be a reasonable value as well.
601 switch (storageDuration) {
602 case storageDurations.PAGEVIEW:
603 return pageviewCache.hasOwnProperty(key) ? pageviewCache[key] : null;
604 case storageDurations.SESSION:
605 value = dataElementSessionStorage.getItem(key);
606 return value === null ? value : JSON.parse(value);
607 case storageDurations.VISITOR:
608 value = dataElementLocalStorage.getItem(key);
609 return value === null ? value : JSON.parse(value);
610 }
611};
612
613// Remove when migration period has ended. We intentionally leave cookies as they are so that if
614// DTM is running on the same domain it can still use the persisted values. Our migration strategy
615// is essentially copying data from cookies and then diverging the storage mechanism between
616// DTM and Launch (DTM uses cookies and Launch uses session and local storage).
617var migrateDataElement = function(dataElementName, storageDuration) {
618 var storedValue = reactorCookie.get(COOKIE_PREFIX + dataElementName);
619
620 if (storedValue !== undefined) {
621 setValue(dataElementName, storageDuration, storedValue);
622 }
623};
624
625var migrateCookieData = function(dataElements) {
626 if (!reactorLocalStorage.getItem(MIGRATED_KEY)) {
627 Object.keys(dataElements).forEach(function(dataElementName) {
628 migrateDataElement(dataElementName, dataElements[dataElementName].storageDuration);
629 });
630
631 reactorLocalStorage.setItem(MIGRATED_KEY, true);
632 }
633};
634
635var dataElementSafe = {
636 setValue: setValue,
637 getValue: getValue,
638 migrateCookieData: migrateCookieData
639};
640
641/***************************************************************************************
642 * (c) 2017 Adobe. All rights reserved.
643 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
644 * you may not use this file except in compliance with the License. You may obtain a copy
645 * of the License at http://www.apache.org/licenses/LICENSE-2.0
646 *
647 * Unless required by applicable law or agreed to in writing, software distributed under
648 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
649 * OF ANY KIND, either express or implied. See the License for the specific language
650 * governing permissions and limitations under the License.
651 ****************************************************************************************/
652
653
654
655
656
657var getErrorMessage = function(dataDef, dataElementName, errorMessage, errorStack) {
658 return 'Failed to execute data element module ' + dataDef.modulePath + ' for data element ' +
659 dataElementName + '. ' + errorMessage + (errorStack ? '\n' + errorStack : '');
660};
661
662var isDataElementValuePresent = function(value) {
663 return value !== undefined && value !== null;
664};
665
666var createGetDataElementValue = function(
667 moduleProvider,
668 getDataElementDefinition,
669 replaceTokens,
670 undefinedVarsReturnEmpty
671) {
672 return function(name) {
673 var dataDef = getDataElementDefinition(name);
674
675 if (!dataDef) {
676 return undefinedVarsReturnEmpty ? '' : null;
677 }
678
679 var storageDuration = dataDef.storageDuration;
680 var moduleExports;
681
682 try {
683 moduleExports = moduleProvider.getModuleExports(dataDef.modulePath);
684 } catch (e) {
685 logger.error(getErrorMessage(dataDef, name, e.message, e.stack));
686 return;
687 }
688
689 if (typeof moduleExports !== 'function') {
690 logger.error(getErrorMessage(dataDef, name, 'Module did not export a function.'));
691 return;
692 }
693
694 var value;
695
696 try {
697 value = moduleExports(replaceTokens(dataDef.settings));
698 } catch (e) {
699 logger.error(getErrorMessage(dataDef, name, e.message, e.stack));
700 return;
701 }
702
703 if (storageDuration) {
704 if (isDataElementValuePresent(value)) {
705 dataElementSafe.setValue(name, storageDuration, value);
706 } else {
707 value = dataElementSafe.getValue(name, storageDuration);
708 }
709 }
710
711 if (!isDataElementValuePresent(value)) {
712 value = dataDef.defaultValue || '';
713 }
714
715 if (typeof value === 'string') {
716 if (dataDef.cleanText) {
717 value = cleanText(value);
718 }
719
720 if (dataDef.forceLowerCase) {
721 value = value.toLowerCase();
722 }
723 }
724
725 return value;
726 };
727};
728
729/***************************************************************************************
730 * (c) 2017 Adobe. All rights reserved.
731 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
732 * you may not use this file except in compliance with the License. You may obtain a copy
733 * of the License at http://www.apache.org/licenses/LICENSE-2.0
734 *
735 * Unless required by applicable law or agreed to in writing, software distributed under
736 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
737 * OF ANY KIND, either express or implied. See the License for the specific language
738 * governing permissions and limitations under the License.
739 ****************************************************************************************/
740
741var extractModuleExports = function(script, require, turbine) {
742 var module = {
743 exports: {}
744 };
745
746 script.call(module.exports, module, module.exports, require, turbine);
747
748 return module.exports;
749};
750
751/***************************************************************************************
752 * (c) 2017 Adobe. All rights reserved.
753 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
754 * you may not use this file except in compliance with the License. You may obtain a copy
755 * of the License at http://www.apache.org/licenses/LICENSE-2.0
756 *
757 * Unless required by applicable law or agreed to in writing, software distributed under
758 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
759 * OF ANY KIND, either express or implied. See the License for the specific language
760 * governing permissions and limitations under the License.
761 ****************************************************************************************/
762
763
764
765
766var createModuleProvider = function() {
767 var moduleByReferencePath = {};
768
769 var getModule = function(referencePath) {
770 var module = moduleByReferencePath[referencePath];
771
772 if (!module) {
773 throw new Error('Module ' + referencePath + ' not found.');
774 }
775
776 return module;
777 };
778
779 var registerModule = function(referencePath, moduleDefinition, extensionName, require, turbine) {
780 var module = {
781 definition: moduleDefinition,
782 extensionName: extensionName,
783 require: require,
784 turbine: turbine
785 };
786 module.require = require;
787 moduleByReferencePath[referencePath] = module;
788 };
789
790 var hydrateCache = function() {
791 Object.keys(moduleByReferencePath).forEach(function(referencePath) {
792 try {
793 getModuleExports(referencePath);
794 } catch (e) {
795 var errorMessage = 'Error initializing module ' + referencePath + '. ' +
796 e.message + (e.stack ? '\n' + e.stack : '');
797 logger.error(errorMessage);
798 }
799 });
800 };
801
802 var getModuleExports = function(referencePath) {
803 var module = getModule(referencePath);
804
805 // Using hasOwnProperty instead of a falsey check because the module could export undefined
806 // in which case we don't want to execute the module each time the exports is requested.
807 if (!module.hasOwnProperty('exports')) {
808 module.exports = extractModuleExports(module.definition.script, module.require,
809 module.turbine);
810 }
811
812 return module.exports;
813 };
814
815 var getModuleDefinition = function(referencePath) {
816 return getModule(referencePath).definition;
817 };
818
819 var getModuleExtensionName = function(referencePath) {
820 return getModule(referencePath).extensionName;
821 };
822
823 return {
824 registerModule: registerModule,
825 hydrateCache: hydrateCache,
826 getModuleExports: getModuleExports,
827 getModuleDefinition: getModuleDefinition,
828 getModuleExtensionName: getModuleExtensionName
829 };
830};
831
832/***************************************************************************************
833 * (c) 2017 Adobe. All rights reserved.
834 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
835 * you may not use this file except in compliance with the License. You may obtain a copy
836 * of the License at http://www.apache.org/licenses/LICENSE-2.0
837 *
838 * Unless required by applicable law or agreed to in writing, software distributed under
839 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
840 * OF ANY KIND, either express or implied. See the License for the specific language
841 * governing permissions and limitations under the License.
842 ****************************************************************************************/
843
844/**
845 * Determines if the provided name is a valid variable, where the variable
846 * can be a data element, element, event, target, or custom var.
847 * @param variableName
848 * @returns {boolean}
849 */
850var createIsVar = function(customVars, getDataElementDefinition) {
851 return function(variableName) {
852 var nameBeforeDot = variableName.split('.')[0];
853
854 return Boolean(
855 getDataElementDefinition(variableName) ||
856 nameBeforeDot === 'this' ||
857 nameBeforeDot === 'event' ||
858 nameBeforeDot === 'target' ||
859 customVars.hasOwnProperty(nameBeforeDot)
860 );
861 };
862};
863
864/***************************************************************************************
865 * (c) 2017 Adobe. All rights reserved.
866 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
867 * you may not use this file except in compliance with the License. You may obtain a copy
868 * of the License at http://www.apache.org/licenses/LICENSE-2.0
869 *
870 * Unless required by applicable law or agreed to in writing, software distributed under
871 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
872 * OF ANY KIND, either express or implied. See the License for the specific language
873 * governing permissions and limitations under the License.
874 ****************************************************************************************/
875
876
877
878var specialPropertyAccessors = {
879 text: function(obj) {
880 return obj.textContent;
881 },
882 cleanText: function(obj) {
883 return cleanText(obj.textContent);
884 }
885};
886
887/**
888 * This returns the value of a property at a given path. For example, a <code>path<code> of
889 * <code>foo.bar</code> will return the value of <code>obj.foo.bar</code>.
890 *
891 * In addition, if <code>path</code> is <code>foo.bar.getAttribute(unicorn)</code> and
892 * <code>obj.foo.bar</code> has a method named <code>getAttribute</code>, the method will be
893 * called with a value of <code>"unicorn"</code> and the value will be returned.
894 *
895 * Also, if <code>path</code> is <code>foo.bar.@text</code> or other supported properties
896 * beginning with <code>@</code>, a special accessor will be used.
897 *
898 * @param host
899 * @param path
900 * @param supportSpecial
901 * @returns {*}
902 */
903var getObjectProperty = function(host, propChain, supportSpecial) {
904 var value = host;
905 var attrMatch;
906 for (var i = 0, len = propChain.length; i < len; i++) {
907 if (value == null) {
908 return undefined;
909 }
910 var prop = propChain[i];
911 if (supportSpecial && prop.charAt(0) === '@') {
912 var specialProp = prop.slice(1);
913 value = specialPropertyAccessors[specialProp](value);
914 continue;
915 }
916 if (value.getAttribute &&
917 (attrMatch = prop.match(/^getAttribute\((.+)\)$/))) {
918 var attr = attrMatch[1];
919 value = value.getAttribute(attr);
920 continue;
921 }
922 value = value[prop];
923 }
924 return value;
925};
926
927/**
928 * Returns the value of a variable.
929 * @param {string} variable
930 * @param {Object} [syntheticEvent] A synthetic event. Only required when using %event... %this...
931 * or %target...
932 * @returns {*}
933 */
934var createGetVar = function(customVars, getDataElementDefinition, getDataElementValue) {
935 return function(variable, syntheticEvent) {
936 var value;
937
938 if (getDataElementDefinition(variable)) {
939 // Accessing nested properties of a data element using dot-notation is unsupported because
940 // users can currently create data elements with periods in the name.
941 value = getDataElementValue(variable);
942 } else {
943 var propChain = variable.split('.');
944 var variableHostName = propChain.shift();
945
946 if (variableHostName === 'this') {
947 if (syntheticEvent) {
948 // I don't know why this is the only one that supports special properties, but that's the
949 // way it was in Satellite.
950 value = getObjectProperty(syntheticEvent.element, propChain, true);
951 }
952 } else if (variableHostName === 'event') {
953 if (syntheticEvent) {
954 value = getObjectProperty(syntheticEvent, propChain);
955 }
956 } else if (variableHostName === 'target') {
957 if (syntheticEvent) {
958 value = getObjectProperty(syntheticEvent.target, propChain);
959 }
960 } else {
961 value = getObjectProperty(customVars[variableHostName], propChain);
962 }
963 }
964
965 return value;
966 };
967};
968
969/***************************************************************************************
970 * (c) 2017 Adobe. All rights reserved.
971 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
972 * you may not use this file except in compliance with the License. You may obtain a copy
973 * of the License at http://www.apache.org/licenses/LICENSE-2.0
974 *
975 * Unless required by applicable law or agreed to in writing, software distributed under
976 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
977 * OF ANY KIND, either express or implied. See the License for the specific language
978 * governing permissions and limitations under the License.
979 ****************************************************************************************/
980
981/**
982 * Creates a function that, when called with an extension name and module name, will return the
983 * exports of the respective shared module.
984 *
985 * @param {Object} extensions
986 * @param {Object} moduleProvider
987 * @returns {Function}
988 */
989var createGetSharedModuleExports = function(extensions, moduleProvider) {
990 return function(extensionName, moduleName) {
991 var extension = extensions[extensionName];
992
993 if (extension) {
994 var modules = extension.modules;
995 if (modules) {
996 var referencePaths = Object.keys(modules);
997 for (var i = 0; i < referencePaths.length; i++) {
998 var referencePath = referencePaths[i];
999 var module = modules[referencePath];
1000 if (module.shared && module.name === moduleName) {
1001 return moduleProvider.getModuleExports(referencePath);
1002 }
1003 }
1004 }
1005 }
1006 };
1007};
1008
1009/***************************************************************************************
1010 * (c) 2017 Adobe. All rights reserved.
1011 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
1012 * you may not use this file except in compliance with the License. You may obtain a copy
1013 * of the License at http://www.apache.org/licenses/LICENSE-2.0
1014 *
1015 * Unless required by applicable law or agreed to in writing, software distributed under
1016 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
1017 * OF ANY KIND, either express or implied. See the License for the specific language
1018 * governing permissions and limitations under the License.
1019 ****************************************************************************************/
1020
1021/**
1022 * Creates a function that, when called, will return a configuration object with data element
1023 * tokens replaced.
1024 *
1025 * @param {Object} settings
1026 * @returns {Function}
1027 */
1028var createGetExtensionSettings = function(replaceTokens, settings) {
1029 return function() {
1030 return settings ? replaceTokens(settings) : {};
1031 };
1032};
1033
1034/***************************************************************************************
1035 * (c) 2017 Adobe. All rights reserved.
1036 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
1037 * you may not use this file except in compliance with the License. You may obtain a copy
1038 * of the License at http://www.apache.org/licenses/LICENSE-2.0
1039 *
1040 * Unless required by applicable law or agreed to in writing, software distributed under
1041 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
1042 * OF ANY KIND, either express or implied. See the License for the specific language
1043 * governing permissions and limitations under the License.
1044 ****************************************************************************************/
1045
1046/**
1047 * Creates a function that, when called, will return the full hosted lib file URL.
1048 *
1049 * @param {string} hostedLibFilesBaseUrl
1050 * @returns {Function}
1051 */
1052
1053var createGetHostedLibFileUrl = function(hostedLibFilesBaseUrl, minified) {
1054 return function(file) {
1055 if (minified) {
1056 var fileParts = file.split('.');
1057 fileParts.splice(fileParts.length - 1 || 1, 0, 'min');
1058 file = fileParts.join('.');
1059 }
1060
1061 return hostedLibFilesBaseUrl + file;
1062 };
1063};
1064
1065/***************************************************************************************
1066 * (c) 2017 Adobe. All rights reserved.
1067 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
1068 * you may not use this file except in compliance with the License. You may obtain a copy
1069 * of the License at http://www.apache.org/licenses/LICENSE-2.0
1070 *
1071 * Unless required by applicable law or agreed to in writing, software distributed under
1072 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
1073 * OF ANY KIND, either express or implied. See the License for the specific language
1074 * governing permissions and limitations under the License.
1075 ****************************************************************************************/
1076
1077var JS_EXTENSION = '.js';
1078
1079/**
1080 * @private
1081 * Returns the directory of a path. A limited version of path.dirname in nodejs.
1082 *
1083 * To keep it simple, it makes the following assumptions:
1084 * path has a least one slash
1085 * path does not end with a slash
1086 * path does not have empty segments (e.g., /src/lib//foo.bar)
1087 *
1088 * @param {string} path
1089 * @returns {string}
1090 */
1091var dirname = function(path) {
1092 return path.substr(0, path.lastIndexOf('/'));
1093};
1094
1095/**
1096 * Determines if a string ends with a certain string.
1097 * @param {string} str The string to test.
1098 * @param {string} suffix The suffix to look for at the end of str.
1099 * @returns {boolean} Whether str ends in suffix.
1100 */
1101var endsWith = function(str, suffix) {
1102 return str.indexOf(suffix, str.length - suffix.length) !== -1;
1103};
1104
1105/**
1106 * Given a starting path and a path relative to the starting path, returns the final path. A
1107 * limited version of path.resolve in nodejs.
1108 *
1109 * To keep it simple, it makes the following assumptions:
1110 * fromPath has at least one slash
1111 * fromPath does not end with a slash.
1112 * fromPath does not have empty segments (e.g., /src/lib//foo.bar)
1113 * relativePath starts with ./ or ../
1114 *
1115 * @param {string} fromPath
1116 * @param {string} relativePath
1117 * @returns {string}
1118 */
1119var resolveRelativePath = function(fromPath, relativePath) {
1120 // Handle the case where the relative path does not end in the .js extension. We auto-append it.
1121 if (!endsWith(relativePath, JS_EXTENSION)) {
1122 relativePath = relativePath + JS_EXTENSION;
1123 }
1124
1125 var relativePathSegments = relativePath.split('/');
1126 var resolvedPathSegments = dirname(fromPath).split('/');
1127
1128 relativePathSegments.forEach(function(relativePathSegment) {
1129 if (!relativePathSegment || relativePathSegment === '.') {
1130 return;
1131 } else if (relativePathSegment === '..') {
1132 if (resolvedPathSegments.length) {
1133 resolvedPathSegments.pop();
1134 }
1135 } else {
1136 resolvedPathSegments.push(relativePathSegment);
1137 }
1138 });
1139
1140 return resolvedPathSegments.join('/');
1141};
1142
1143'use strict';
1144
1145var reactorDocument = document;
1146
1147var promise = createCommonjsModule(function (module) {
1148(function (root) {
1149
1150 // Store setTimeout reference so promise-polyfill will be unaffected by
1151 // other code modifying setTimeout (like sinon.useFakeTimers())
1152 var setTimeoutFunc = setTimeout;
1153
1154 function noop() {}
1155
1156 // Polyfill for Function.prototype.bind
1157 function bind(fn, thisArg) {
1158 return function () {
1159 fn.apply(thisArg, arguments);
1160 };
1161 }
1162
1163 function Promise(fn) {
1164 if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
1165 if (typeof fn !== 'function') throw new TypeError('not a function');
1166 this._state = 0;
1167 this._handled = false;
1168 this._value = undefined;
1169 this._deferreds = [];
1170
1171 doResolve(fn, this);
1172 }
1173
1174 function handle(self, deferred) {
1175 while (self._state === 3) {
1176 self = self._value;
1177 }
1178 if (self._state === 0) {
1179 self._deferreds.push(deferred);
1180 return;
1181 }
1182 self._handled = true;
1183 Promise._immediateFn(function () {
1184 var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
1185 if (cb === null) {
1186 (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
1187 return;
1188 }
1189 var ret;
1190 try {
1191 ret = cb(self._value);
1192 } catch (e) {
1193 reject(deferred.promise, e);
1194 return;
1195 }
1196 resolve(deferred.promise, ret);
1197 });
1198 }
1199
1200 function resolve(self, newValue) {
1201 try {
1202 // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
1203 if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.');
1204 if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
1205 var then = newValue.then;
1206 if (newValue instanceof Promise) {
1207 self._state = 3;
1208 self._value = newValue;
1209 finale(self);
1210 return;
1211 } else if (typeof then === 'function') {
1212 doResolve(bind(then, newValue), self);
1213 return;
1214 }
1215 }
1216 self._state = 1;
1217 self._value = newValue;
1218 finale(self);
1219 } catch (e) {
1220 reject(self, e);
1221 }
1222 }
1223
1224 function reject(self, newValue) {
1225 self._state = 2;
1226 self._value = newValue;
1227 finale(self);
1228 }
1229
1230 function finale(self) {
1231 if (self._state === 2 && self._deferreds.length === 0) {
1232 Promise._immediateFn(function() {
1233 if (!self._handled) {
1234 Promise._unhandledRejectionFn(self._value);
1235 }
1236 });
1237 }
1238
1239 for (var i = 0, len = self._deferreds.length; i < len; i++) {
1240 handle(self, self._deferreds[i]);
1241 }
1242 self._deferreds = null;
1243 }
1244
1245 function Handler(onFulfilled, onRejected, promise) {
1246 this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
1247 this.onRejected = typeof onRejected === 'function' ? onRejected : null;
1248 this.promise = promise;
1249 }
1250
1251 /**
1252 * Take a potentially misbehaving resolver function and make sure
1253 * onFulfilled and onRejected are only called once.
1254 *
1255 * Makes no guarantees about asynchrony.
1256 */
1257 function doResolve(fn, self) {
1258 var done = false;
1259 try {
1260 fn(function (value) {
1261 if (done) return;
1262 done = true;
1263 resolve(self, value);
1264 }, function (reason) {
1265 if (done) return;
1266 done = true;
1267 reject(self, reason);
1268 });
1269 } catch (ex) {
1270 if (done) return;
1271 done = true;
1272 reject(self, ex);
1273 }
1274 }
1275
1276 Promise.prototype['catch'] = function (onRejected) {
1277 return this.then(null, onRejected);
1278 };
1279
1280 Promise.prototype.then = function (onFulfilled, onRejected) {
1281 var prom = new (this.constructor)(noop);
1282
1283 handle(this, new Handler(onFulfilled, onRejected, prom));
1284 return prom;
1285 };
1286
1287 Promise.all = function (arr) {
1288 var args = Array.prototype.slice.call(arr);
1289
1290 return new Promise(function (resolve, reject) {
1291 if (args.length === 0) return resolve([]);
1292 var remaining = args.length;
1293
1294 function res(i, val) {
1295 try {
1296 if (val && (typeof val === 'object' || typeof val === 'function')) {
1297 var then = val.then;
1298 if (typeof then === 'function') {
1299 then.call(val, function (val) {
1300 res(i, val);
1301 }, reject);
1302 return;
1303 }
1304 }
1305 args[i] = val;
1306 if (--remaining === 0) {
1307 resolve(args);
1308 }
1309 } catch (ex) {
1310 reject(ex);
1311 }
1312 }
1313
1314 for (var i = 0; i < args.length; i++) {
1315 res(i, args[i]);
1316 }
1317 });
1318 };
1319
1320 Promise.resolve = function (value) {
1321 if (value && typeof value === 'object' && value.constructor === Promise) {
1322 return value;
1323 }
1324
1325 return new Promise(function (resolve) {
1326 resolve(value);
1327 });
1328 };
1329
1330 Promise.reject = function (value) {
1331 return new Promise(function (resolve, reject) {
1332 reject(value);
1333 });
1334 };
1335
1336 Promise.race = function (values) {
1337 return new Promise(function (resolve, reject) {
1338 for (var i = 0, len = values.length; i < len; i++) {
1339 values[i].then(resolve, reject);
1340 }
1341 });
1342 };
1343
1344 // Use polyfill for setImmediate for performance gains
1345 Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) ||
1346 function (fn) {
1347 setTimeoutFunc(fn, 0);
1348 };
1349
1350 Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
1351 if (typeof console !== 'undefined' && console) {
1352 console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
1353 }
1354 };
1355
1356 /**
1357 * Set the immediate function to execute callbacks
1358 * @param fn {function} Function to execute
1359 * @deprecated
1360 */
1361 Promise._setImmediateFn = function _setImmediateFn(fn) {
1362 Promise._immediateFn = fn;
1363 };
1364
1365 /**
1366 * Change the function to execute on unhandled rejection
1367 * @param {function} fn Function to execute on unhandled rejection
1368 * @deprecated
1369 */
1370 Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
1371 Promise._unhandledRejectionFn = fn;
1372 };
1373
1374 if ('object' !== 'undefined' && module.exports) {
1375 module.exports = Promise;
1376 } else if (!root.Promise) {
1377 root.Promise = Promise;
1378 }
1379
1380})(commonjsGlobal);
1381});
1382
1383/***************************************************************************************
1384 * (c) 2017 Adobe. All rights reserved.
1385 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
1386 * you may not use this file except in compliance with the License. You may obtain a copy
1387 * of the License at http://www.apache.org/licenses/LICENSE-2.0
1388 *
1389 * Unless required by applicable law or agreed to in writing, software distributed under
1390 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
1391 * OF ANY KIND, either express or implied. See the License for the specific language
1392 * governing permissions and limitations under the License.
1393 ****************************************************************************************/
1394'use strict';
1395
1396var reactorPromise = window.Promise || promise;
1397
1398/***************************************************************************************
1399 * (c) 2017 Adobe. All rights reserved.
1400 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
1401 * you may not use this file except in compliance with the License. You may obtain a copy
1402 * of the License at http://www.apache.org/licenses/LICENSE-2.0
1403 *
1404 * Unless required by applicable law or agreed to in writing, software distributed under
1405 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
1406 * OF ANY KIND, either express or implied. See the License for the specific language
1407 * governing permissions and limitations under the License.
1408 ****************************************************************************************/
1409'use strict';
1410
1411
1412
1413var getPromise = function(url, script) {
1414 return new reactorPromise(function(resolve, reject) {
1415 if ('onload' in script) {
1416 script.onload = function() {
1417 resolve(script);
1418 };
1419
1420 script.onerror = function() {
1421 reject(new Error('Failed to load script ' + url));
1422 };
1423 } else if ('readyState' in script) {
1424 script.onreadystatechange = function() {
1425 var rs = script.readyState;
1426 if (rs === 'loaded' || rs === 'complete') {
1427 script.onreadystatechange = null;
1428 resolve(script);
1429 }
1430 };
1431 }
1432 });
1433};
1434
1435var reactorLoadScript = function(url) {
1436 var script = document.createElement('script');
1437 script.src = url;
1438 script.async = true;
1439
1440 var promise = getPromise(url, script);
1441
1442 document.getElementsByTagName('head')[0].appendChild(script);
1443 return promise;
1444};
1445
1446/*
1447object-assign
1448(c) Sindre Sorhus
1449@license MIT
1450*/
1451
1452'use strict';
1453/* eslint-disable no-unused-vars */
1454var getOwnPropertySymbols = Object.getOwnPropertySymbols;
1455var hasOwnProperty = Object.prototype.hasOwnProperty;
1456var propIsEnumerable = Object.prototype.propertyIsEnumerable;
1457
1458function toObject(val) {
1459 if (val === null || val === undefined) {
1460 throw new TypeError('Object.assign cannot be called with null or undefined');
1461 }
1462
1463 return Object(val);
1464}
1465
1466function shouldUseNative() {
1467 try {
1468 if (!Object.assign) {
1469 return false;
1470 }
1471
1472 // Detect buggy property enumeration order in older V8 versions.
1473
1474 // https://bugs.chromium.org/p/v8/issues/detail?id=4118
1475 var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
1476 test1[5] = 'de';
1477 if (Object.getOwnPropertyNames(test1)[0] === '5') {
1478 return false;
1479 }
1480
1481 // https://bugs.chromium.org/p/v8/issues/detail?id=3056
1482 var test2 = {};
1483 for (var i = 0; i < 10; i++) {
1484 test2['_' + String.fromCharCode(i)] = i;
1485 }
1486 var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
1487 return test2[n];
1488 });
1489 if (order2.join('') !== '0123456789') {
1490 return false;
1491 }
1492
1493 // https://bugs.chromium.org/p/v8/issues/detail?id=3056
1494 var test3 = {};
1495 'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
1496 test3[letter] = letter;
1497 });
1498 if (Object.keys(Object.assign({}, test3)).join('') !==
1499 'abcdefghijklmnopqrst') {
1500 return false;
1501 }
1502
1503 return true;
1504 } catch (err) {
1505 // We don't expect any of the above to throw, but better to be safe.
1506 return false;
1507 }
1508}
1509
1510var objectAssign = shouldUseNative() ? Object.assign : function (target, source) {
1511 var from;
1512 var to = toObject(target);
1513 var symbols;
1514
1515 for (var s = 1; s < arguments.length; s++) {
1516 from = Object(arguments[s]);
1517
1518 for (var key in from) {
1519 if (hasOwnProperty.call(from, key)) {
1520 to[key] = from[key];
1521 }
1522 }
1523
1524 if (getOwnPropertySymbols) {
1525 symbols = getOwnPropertySymbols(from);
1526 for (var i = 0; i < symbols.length; i++) {
1527 if (propIsEnumerable.call(from, symbols[i])) {
1528 to[symbols[i]] = from[symbols[i]];
1529 }
1530 }
1531 }
1532 }
1533
1534 return to;
1535};
1536
1537'use strict';
1538
1539var reactorObjectAssign = objectAssign;
1540
1541// Copyright Joyent, Inc. and other Node contributors.
1542//
1543// Permission is hereby granted, free of charge, to any person obtaining a
1544// copy of this software and associated documentation files (the
1545// "Software"), to deal in the Software without restriction, including
1546// without limitation the rights to use, copy, modify, merge, publish,
1547// distribute, sublicense, and/or sell copies of the Software, and to permit
1548// persons to whom the Software is furnished to do so, subject to the
1549// following conditions:
1550//
1551// The above copyright notice and this permission notice shall be included
1552// in all copies or substantial portions of the Software.
1553//
1554// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1555// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1556// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
1557// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
1558// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1559// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
1560// USE OR OTHER DEALINGS IN THE SOFTWARE.
1561
1562'use strict';
1563
1564// If obj.hasOwnProperty has been overridden, then calling
1565// obj.hasOwnProperty(prop) will break.
1566// See: https://github.com/joyent/node/issues/1707
1567function hasOwnProperty$1(obj, prop) {
1568 return Object.prototype.hasOwnProperty.call(obj, prop);
1569}
1570
1571var decode = function(qs, sep, eq, options) {
1572 sep = sep || '&';
1573 eq = eq || '=';
1574 var obj = {};
1575
1576 if (typeof qs !== 'string' || qs.length === 0) {
1577 return obj;
1578 }
1579
1580 var regexp = /\+/g;
1581 qs = qs.split(sep);
1582
1583 var maxKeys = 1000;
1584 if (options && typeof options.maxKeys === 'number') {
1585 maxKeys = options.maxKeys;
1586 }
1587
1588 var len = qs.length;
1589 // maxKeys <= 0 means that we should not limit keys count
1590 if (maxKeys > 0 && len > maxKeys) {
1591 len = maxKeys;
1592 }
1593
1594 for (var i = 0; i < len; ++i) {
1595 var x = qs[i].replace(regexp, '%20'),
1596 idx = x.indexOf(eq),
1597 kstr, vstr, k, v;
1598
1599 if (idx >= 0) {
1600 kstr = x.substr(0, idx);
1601 vstr = x.substr(idx + 1);
1602 } else {
1603 kstr = x;
1604 vstr = '';
1605 }
1606
1607 k = decodeURIComponent(kstr);
1608 v = decodeURIComponent(vstr);
1609
1610 if (!hasOwnProperty$1(obj, k)) {
1611 obj[k] = v;
1612 } else if (Array.isArray(obj[k])) {
1613 obj[k].push(v);
1614 } else {
1615 obj[k] = [obj[k], v];
1616 }
1617 }
1618
1619 return obj;
1620};
1621
1622// Copyright Joyent, Inc. and other Node contributors.
1623//
1624// Permission is hereby granted, free of charge, to any person obtaining a
1625// copy of this software and associated documentation files (the
1626// "Software"), to deal in the Software without restriction, including
1627// without limitation the rights to use, copy, modify, merge, publish,
1628// distribute, sublicense, and/or sell copies of the Software, and to permit
1629// persons to whom the Software is furnished to do so, subject to the
1630// following conditions:
1631//
1632// The above copyright notice and this permission notice shall be included
1633// in all copies or substantial portions of the Software.
1634//
1635// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1636// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1637// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
1638// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
1639// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1640// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
1641// USE OR OTHER DEALINGS IN THE SOFTWARE.
1642
1643'use strict';
1644
1645var stringifyPrimitive = function(v) {
1646 switch (typeof v) {
1647 case 'string':
1648 return v;
1649
1650 case 'boolean':
1651 return v ? 'true' : 'false';
1652
1653 case 'number':
1654 return isFinite(v) ? v : '';
1655
1656 default:
1657 return '';
1658 }
1659};
1660
1661var encode = function(obj, sep, eq, name) {
1662 sep = sep || '&';
1663 eq = eq || '=';
1664 if (obj === null) {
1665 obj = undefined;
1666 }
1667
1668 if (typeof obj === 'object') {
1669 return Object.keys(obj).map(function(k) {
1670 var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
1671 if (Array.isArray(obj[k])) {
1672 return obj[k].map(function(v) {
1673 return ks + encodeURIComponent(stringifyPrimitive(v));
1674 }).join(sep);
1675 } else {
1676 return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
1677 }
1678 }).join(sep);
1679
1680 }
1681
1682 if (!name) return '';
1683 return encodeURIComponent(stringifyPrimitive(name)) + eq +
1684 encodeURIComponent(stringifyPrimitive(obj));
1685};
1686
1687var querystring = createCommonjsModule(function (module, exports) {
1688'use strict';
1689
1690exports.decode = exports.parse = decode;
1691exports.encode = exports.stringify = encode;
1692});
1693
1694/***************************************************************************************
1695 * (c) 2017 Adobe. All rights reserved.
1696 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
1697 * you may not use this file except in compliance with the License. You may obtain a copy
1698 * of the License at http://www.apache.org/licenses/LICENSE-2.0
1699 *
1700 * Unless required by applicable law or agreed to in writing, software distributed under
1701 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
1702 * OF ANY KIND, either express or implied. See the License for the specific language
1703 * governing permissions and limitations under the License.
1704 ****************************************************************************************/
1705'use strict';
1706
1707
1708
1709// We proxy the underlying querystring module so we can limit the API we expose.
1710// This allows us to more easily make changes to the underlying implementation later without
1711// having to worry about breaking extensions. If extensions demand additional functionality, we
1712// can make adjustments as needed.
1713var reactorQueryString = {
1714 parse: function(string) {
1715 //
1716 if (typeof string === 'string') {
1717 // Remove leading ?, #, & for some leniency so you can pass in location.search or
1718 // location.hash directly.
1719 string = string.trim().replace(/^[?#&]/, '');
1720 }
1721 return querystring.parse(string);
1722 },
1723 stringify: function(object) {
1724 return querystring.stringify(object);
1725 }
1726};
1727
1728/***************************************************************************************
1729 * (c) 2017 Adobe. All rights reserved.
1730 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
1731 * you may not use this file except in compliance with the License. You may obtain a copy
1732 * of the License at http://www.apache.org/licenses/LICENSE-2.0
1733 *
1734 * Unless required by applicable law or agreed to in writing, software distributed under
1735 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
1736 * OF ANY KIND, either express or implied. See the License for the specific language
1737 * governing permissions and limitations under the License.
1738 ****************************************************************************************/
1739
1740var CORE_MODULE_PREFIX = '@adobe/reactor-';
1741
1742var modules = {
1743 'cookie': reactorCookie,
1744 'document': reactorDocument,
1745 'load-script': reactorLoadScript,
1746 'object-assign': reactorObjectAssign,
1747 'promise': reactorPromise,
1748 'query-string': reactorQueryString,
1749 'window': reactorWindow
1750};
1751
1752/**
1753 * Creates a function which can be passed as a "require" function to extension modules.
1754 *
1755 * @param {Function} getModuleExportsByRelativePath
1756 * @returns {Function}
1757 */
1758var createPublicRequire = function(getModuleExportsByRelativePath) {
1759 return function(key) {
1760 if (key.indexOf(CORE_MODULE_PREFIX) === 0) {
1761 var keyWithoutScope = key.substr(CORE_MODULE_PREFIX.length);
1762 var module = modules[keyWithoutScope];
1763
1764 if (module) {
1765 return module;
1766 }
1767 }
1768
1769 if (key.indexOf('./') === 0 || key.indexOf('../') === 0) {
1770 return getModuleExportsByRelativePath(key);
1771 }
1772
1773 throw new Error('Cannot resolve module "' + key + '".');
1774 };
1775};
1776
1777/***************************************************************************************
1778 * (c) 2017 Adobe. All rights reserved.
1779 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
1780 * you may not use this file except in compliance with the License. You may obtain a copy
1781 * of the License at http://www.apache.org/licenses/LICENSE-2.0
1782 *
1783 * Unless required by applicable law or agreed to in writing, software distributed under
1784 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
1785 * OF ANY KIND, either express or implied. See the License for the specific language
1786 * governing permissions and limitations under the License.
1787 ****************************************************************************************/
1788
1789
1790
1791
1792
1793
1794
1795
1796var hydrateModuleProvider = function(container, moduleProvider, replaceTokens, getDataElementValue) {
1797 var extensions = container.extensions;
1798 var buildInfo = container.buildInfo;
1799 var propertySettings = container.property.settings;
1800
1801 if (extensions) {
1802 var getSharedModuleExports = createGetSharedModuleExports(extensions, moduleProvider);
1803
1804 Object.keys(extensions).forEach(function(extensionName) {
1805 var extension = extensions[extensionName];
1806 var getExtensionSettings = createGetExtensionSettings(replaceTokens, extension.settings);
1807
1808 if (extension.modules) {
1809 var prefixedLogger = logger.createPrefixedLogger(extension.displayName);
1810 var getHostedLibFileUrl = createGetHostedLibFileUrl(
1811 extension.hostedLibFilesBaseUrl,
1812 buildInfo.minified
1813 );
1814 var turbine = {
1815 buildInfo: buildInfo,
1816 getDataElementValue: getDataElementValue,
1817 getExtensionSettings: getExtensionSettings,
1818 getHostedLibFileUrl: getHostedLibFileUrl,
1819 getSharedModule: getSharedModuleExports,
1820 logger: prefixedLogger,
1821 propertySettings: propertySettings,
1822 replaceTokens: replaceTokens
1823 };
1824
1825 Object.keys(extension.modules).forEach(function(referencePath) {
1826 var module = extension.modules[referencePath];
1827 var getModuleExportsByRelativePath = function(relativePath) {
1828 var resolvedReferencePath = resolveRelativePath(referencePath, relativePath);
1829 return moduleProvider.getModuleExports(resolvedReferencePath);
1830 };
1831 var publicRequire = createPublicRequire(getModuleExportsByRelativePath);
1832
1833 moduleProvider.registerModule(
1834 referencePath,
1835 module,
1836 extensionName,
1837 publicRequire,
1838 turbine
1839 );
1840 });
1841 }
1842 });
1843
1844 // We want to extract the module exports immediately to allow the modules
1845 // to run some logic immediately.
1846 // We need to do the extraction here in order for the moduleProvider to
1847 // have all the modules previously registered. (eg. when moduleA needs moduleB, both modules
1848 // must exist inside moduleProvider).
1849 moduleProvider.hydrateCache();
1850 }
1851 return moduleProvider;
1852};
1853
1854/***************************************************************************************
1855 * (c) 2017 Adobe. All rights reserved.
1856 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
1857 * you may not use this file except in compliance with the License. You may obtain a copy
1858 * of the License at http://www.apache.org/licenses/LICENSE-2.0
1859 *
1860 * Unless required by applicable law or agreed to in writing, software distributed under
1861 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
1862 * OF ANY KIND, either express or implied. See the License for the specific language
1863 * governing permissions and limitations under the License.
1864 ****************************************************************************************/
1865
1866
1867
1868
1869var hydrateSatelliteObject = function(_satellite, container, setDebugOutputEnabled, getVar, setCustomVar) {
1870 var prefixedLogger = logger.createPrefixedLogger('Custom Script');
1871
1872 // Will get replaced by the directCall event delegate from the Core extension. Exists here in
1873 // case there are no direct call rules (and therefore the directCall event delegate won't get
1874 // included) and our customers are still calling the method. In this case, we don't want an error
1875 // to be thrown. This method existed before Reactor.
1876 _satellite.track = function() {};
1877
1878 // Will get replaced by the Marketing Cloud ID extension if installed. Exists here in case
1879 // the extension is not installed and our customers are still calling the method. In this case,
1880 // we don't want an error to be thrown. This method existed before Reactor.
1881 _satellite.getVisitorId = function() { return null; };
1882
1883 // container.property also has property settings, but it shouldn't concern the user.
1884 // By limiting our API exposure to necessities, we provide more flexibility in the future.
1885 _satellite.property = {
1886 name: container.property.name
1887 };
1888
1889 _satellite.buildInfo = container.buildInfo;
1890
1891 _satellite.logger = prefixedLogger;
1892
1893 /**
1894 * Log a message. We keep this due to legacy baggage.
1895 * @param {string} message The message to log.
1896 * @param {number} [level] A number that represents the level of logging.
1897 * 3=info, 4=warn, 5=error, anything else=log
1898 */
1899 _satellite.notify = function(message, level) {
1900 logger.warn('_satellite.notify is deprecated. Please use the `_satellite.logger` API.');
1901
1902 switch (level) {
1903 case 3:
1904 prefixedLogger.info(message);
1905 break;
1906 case 4:
1907 prefixedLogger.warn(message);
1908 break;
1909 case 5:
1910 prefixedLogger.error(message);
1911 break;
1912 default:
1913 prefixedLogger.log(message);
1914 }
1915 };
1916
1917 _satellite.getVar = getVar;
1918 _satellite.setVar = setCustomVar;
1919
1920 /**
1921 * Writes a cookie.
1922 * @param {string} name The name of the cookie to save.
1923 * @param {string} value The value of the cookie to save.
1924 * @param {number} [days] The number of days to store the cookie. If not specified, the cookie
1925 * will be stored for the session only.
1926 */
1927 _satellite.setCookie = function(name, value, days) {
1928 var optionsStr = '';
1929 var options = {};
1930
1931 if (days) {
1932 optionsStr = ', { expires: ' + days + ' }';
1933 options.expires = days;
1934 }
1935
1936 var msg = '_satellite.setCookie is deprecated. Please use ' +
1937 '_satellite.cookie.set("' + name + '", "' + value + '"' + optionsStr + ').';
1938
1939 logger.warn(msg);
1940 reactorCookie.set(name, value, options);
1941 };
1942
1943 /**
1944 * Reads a cookie value.
1945 * @param {string} name The name of the cookie to read.
1946 * @returns {string}
1947 */
1948 _satellite.readCookie = function(name) {
1949 logger.warn('_satellite.readCookie is deprecated. ' +
1950 'Please use _satellite.cookie.get("' + name + '").');
1951 return reactorCookie.get(name);
1952 };
1953
1954 /**
1955 * Removes a cookie value.
1956 * @param name
1957 */
1958 _satellite.removeCookie = function(name) {
1959 logger.warn('_satellite.removeCookie is deprecated. ' +
1960 'Please use _satellite.cookie.remove("' + name + '").');
1961 reactorCookie.remove(name);
1962 };
1963
1964 _satellite.cookie = reactorCookie;
1965
1966 // Will get replaced by the pageBottom event delegate from the Core extension. Exists here in
1967 // case the customers are not using core (and therefore the pageBottom event delegate won't get
1968 // included) and they are still calling the method. In this case, we don't want an error
1969 // to be thrown. This method existed before Reactor.
1970 _satellite.pageBottom = function() {};
1971
1972 _satellite.setDebug = setDebugOutputEnabled;
1973
1974 var warningLogged = false;
1975
1976 Object.defineProperty(_satellite, '_container', {
1977 get: function() {
1978 if (!warningLogged) {
1979 logger.warn('_satellite._container may change at any time and should only ' +
1980 'be used for debugging.');
1981 warningLogged = true;
1982 }
1983
1984 return container;
1985 }
1986 });
1987};
1988
1989/***************************************************************************************
1990 * (c) 2017 Adobe. All rights reserved.
1991 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
1992 * you may not use this file except in compliance with the License. You may obtain a copy
1993 * of the License at http://www.apache.org/licenses/LICENSE-2.0
1994 *
1995 * Unless required by applicable law or agreed to in writing, software distributed under
1996 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
1997 * OF ANY KIND, either express or implied. See the License for the specific language
1998 * governing permissions and limitations under the License.
1999 ****************************************************************************************/
2000
2001
2002
2003
2004/**
2005 * Normalizes a synthetic event so that it exists and has at least meta.
2006 * @param {Object} syntheticEventMeta
2007 * @param {Object} [syntheticEvent]
2008 * @returns {Object}
2009 */
2010var normalizeSyntheticEvent = function(syntheticEventMeta, syntheticEvent) {
2011 syntheticEvent = syntheticEvent || {};
2012 reactorObjectAssign(syntheticEvent, syntheticEventMeta);
2013
2014 // Remove after some arbitrary time period when we think users have had sufficient chance
2015 // to move away from event.type
2016 if (!syntheticEvent.hasOwnProperty('type')) {
2017 Object.defineProperty(syntheticEvent, 'type', {
2018 get: function() {
2019 logger.warn('Accessing event.type in Adobe Launch has been deprecated and will be ' +
2020 'removed soon. Please use event.$type instead.');
2021 return syntheticEvent.$type;
2022 }
2023 });
2024 }
2025
2026 return syntheticEvent;
2027};
2028
2029/***************************************************************************************
2030 * (c) 2017 Adobe. All rights reserved.
2031 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
2032 * you may not use this file except in compliance with the License. You may obtain a copy
2033 * of the License at http://www.apache.org/licenses/LICENSE-2.0
2034 *
2035 * Unless required by applicable law or agreed to in writing, software distributed under
2036 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
2037 * OF ANY KIND, either express or implied. See the License for the specific language
2038 * governing permissions and limitations under the License.
2039 ****************************************************************************************/
2040
2041/**
2042 * Rules can be ordered by users at the event type level. For example, assume both Rule A and Rule B
2043 * use the Library Loaded and Window Loaded event types. Rule A can be ordered to come before Rule B
2044 * on Library Loaded but after Rule B on Window Loaded.
2045 *
2046 * Order values are integers and act more as a priority. In other words, multiple rules can have the
2047 * same order value. If they have the same order value, their order of execution should be
2048 * considered nondetermistic.
2049 *
2050 * @param {Array} rules
2051 * @returns {Array} An ordered array of rule-event pair objects.
2052 */
2053var buildRuleExecutionOrder = function(rules) {
2054 var ruleEventPairs = [];
2055
2056 rules.forEach(function(rule) {
2057 if (rule.events) {
2058 rule.events.forEach(function(event) {
2059 ruleEventPairs.push({
2060 rule: rule,
2061 event: event
2062 });
2063 });
2064 }
2065 });
2066
2067 return ruleEventPairs.sort(function(ruleEventPairA, ruleEventPairB) {
2068 return ruleEventPairA.event.ruleOrder - ruleEventPairB.event.ruleOrder;
2069 });
2070};
2071
2072/***************************************************************************************
2073 * (c) 2017 Adobe. All rights reserved.
2074 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
2075 * you may not use this file except in compliance with the License. You may obtain a copy
2076 * of the License at http://www.apache.org/licenses/LICENSE-2.0
2077 *
2078 * Unless required by applicable law or agreed to in writing, software distributed under
2079 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
2080 * OF ANY KIND, either express or implied. See the License for the specific language
2081 * governing permissions and limitations under the License.
2082 ****************************************************************************************/
2083
2084
2085var warningLogged = false;
2086
2087var createNotifyMonitors = function(_satellite) {
2088 return function(type, event) {
2089 var monitors = _satellite._monitors;
2090
2091 if (monitors) {
2092 if (!warningLogged) {
2093 logger.warn('The _satellite._monitors API may change at any time and should only ' +
2094 'be used for debugging.');
2095 warningLogged = true;
2096 }
2097
2098 monitors.forEach(function(monitor) {
2099 if (monitor[type]) {
2100 monitor[type](event);
2101 }
2102 });
2103 }
2104 };
2105};
2106
2107/***************************************************************************************
2108 * (c) 2017 Adobe. All rights reserved.
2109 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
2110 * you may not use this file except in compliance with the License. You may obtain a copy
2111 * of the License at http://www.apache.org/licenses/LICENSE-2.0
2112 *
2113 * Unless required by applicable law or agreed to in writing, software distributed under
2114 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
2115 * OF ANY KIND, either express or implied. See the License for the specific language
2116 * governing permissions and limitations under the License.
2117 ****************************************************************************************/
2118
2119
2120
2121
2122
2123
2124var MODULE_NOT_FUNCTION_ERROR = 'Module did not export a function.';
2125
2126var initRules = function(
2127 _satellite,
2128 rules,
2129 moduleProvider,
2130 replaceTokens,
2131 getShouldExecuteActions
2132) {
2133 var notifyMonitors = createNotifyMonitors(_satellite);
2134
2135 var getModuleDisplayNameByRuleComponent = function(ruleComponent) {
2136 var moduleDefinition = moduleProvider.getModuleDefinition(ruleComponent.modulePath);
2137 return (moduleDefinition && moduleDefinition.displayName) || ruleComponent.modulePath;
2138 };
2139
2140 var getErrorMessage = function(ruleComponent, rule, errorMessage, errorStack) {
2141 var moduleDisplayName = getModuleDisplayNameByRuleComponent(ruleComponent);
2142 return 'Failed to execute ' + moduleDisplayName + ' for ' + rule.name + ' rule. ' +
2143 errorMessage + (errorStack ? '\n' + errorStack : '');
2144 };
2145
2146 var runActions = function(rule, syntheticEvent) {
2147 if (getShouldExecuteActions() && rule.actions) {
2148 rule.actions.forEach(function(action) {
2149 action.settings = action.settings || {};
2150
2151 var moduleExports;
2152
2153 try {
2154 moduleExports = moduleProvider.getModuleExports(action.modulePath);
2155 } catch (e) {
2156 logger.error(getErrorMessage(action, rule, e.message, e.stack));
2157 return;
2158 }
2159
2160 if (typeof moduleExports !== 'function') {
2161 logger.error(getErrorMessage(action, rule, MODULE_NOT_FUNCTION_ERROR));
2162 return;
2163 }
2164
2165 var settings = replaceTokens(action.settings, syntheticEvent);
2166
2167 try {
2168 moduleExports(settings, syntheticEvent);
2169 } catch (e) {
2170 logger.error(getErrorMessage(action, rule, e.message, e.stack));
2171 return;
2172 }
2173 });
2174 }
2175
2176 logger.log('Rule "' + rule.name + '" fired.');
2177 notifyMonitors('ruleCompleted', {
2178 rule: rule
2179 });
2180 };
2181
2182 var checkConditions = function(rule, syntheticEvent) {
2183 if (rule.conditions) {
2184 for (var i = 0; i < rule.conditions.length; i++) {
2185 var condition = rule.conditions[i];
2186 condition.settings = condition.settings || {};
2187
2188 var moduleExports;
2189
2190 try {
2191 moduleExports = moduleProvider.getModuleExports(condition.modulePath);
2192 } catch (e) {
2193 logger.error(getErrorMessage(condition, rule, e.message, e.stack));
2194 return;
2195 }
2196
2197 if (typeof moduleExports !== 'function') {
2198 logger.error(getErrorMessage(condition, rule, MODULE_NOT_FUNCTION_ERROR));
2199 return;
2200 }
2201
2202 var settings = replaceTokens(condition.settings, syntheticEvent);
2203
2204 var result;
2205
2206 try {
2207 result = moduleExports(settings, syntheticEvent);
2208 } catch (e) {
2209 logger.error(getErrorMessage(condition, rule, e.message, e.stack));
2210 notifyMonitors('ruleConditionFailed', {
2211 rule: rule,
2212 condition: condition
2213 });
2214 // We return because we want to assume the condition would have failed and therefore
2215 // we don't want to run the following conditions or the rule's actions.
2216 return;
2217 }
2218
2219 if ((!result && !condition.negate) || (result && condition.negate)) {
2220 var conditionDisplayName = getModuleDisplayNameByRuleComponent(condition);
2221 logger.log('Condition ' + conditionDisplayName + ' for rule ' + rule.name + ' not met.');
2222 notifyMonitors('ruleConditionFailed', {
2223 rule: rule,
2224 condition: condition
2225 });
2226 return;
2227 }
2228 }
2229 }
2230
2231 runActions(rule, syntheticEvent);
2232 };
2233
2234 var initEventModule = function(ruleEventPair) {
2235 var rule = ruleEventPair.rule;
2236 var event = ruleEventPair.event;
2237 event.settings = event.settings || {};
2238
2239 var moduleExports;
2240 var moduleName;
2241 var extensionName;
2242
2243 try {
2244 moduleExports = moduleProvider.getModuleExports(event.modulePath);
2245 moduleName = moduleProvider.getModuleDefinition(event.modulePath).name;
2246 extensionName = moduleProvider.getModuleExtensionName(event.modulePath);
2247 } catch (e) {
2248 logger.error(getErrorMessage(event, rule, e.message, e.stack));
2249 return;
2250 }
2251
2252 if (typeof moduleExports !== 'function') {
2253 logger.error(getErrorMessage(event, rule, MODULE_NOT_FUNCTION_ERROR));
2254 return;
2255 }
2256
2257 var settings = replaceTokens(event.settings);
2258
2259 var syntheticEventMeta = {
2260 $type: extensionName + '.' + moduleName,
2261 $rule: {
2262 id: rule.id,
2263 name: rule.name
2264 }
2265 };
2266
2267 /**
2268 * This is the callback that executes a particular rule when an event has occurred.
2269 * @callback ruleTrigger
2270 * @param {Object} [syntheticEvent] An object that contains detail regarding the event
2271 * that occurred.
2272 */
2273 var trigger = function(syntheticEvent) {
2274 notifyMonitors('ruleTriggered', {
2275 rule: rule
2276 });
2277 checkConditions(rule, normalizeSyntheticEvent(syntheticEventMeta, syntheticEvent));
2278 };
2279
2280 try {
2281 moduleExports(settings, trigger);
2282 } catch (e) {
2283 logger.error(getErrorMessage(event, rule, e.message, e.stack));
2284 return;
2285 }
2286 };
2287
2288 buildRuleExecutionOrder(rules).forEach(initEventModule);
2289};
2290
2291/***************************************************************************************
2292 * (c) 2017 Adobe. All rights reserved.
2293 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
2294 * you may not use this file except in compliance with the License. You may obtain a copy
2295 * of the License at http://www.apache.org/licenses/LICENSE-2.0
2296 *
2297 * Unless required by applicable law or agreed to in writing, software distributed under
2298 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
2299 * OF ANY KIND, either express or implied. See the License for the specific language
2300 * governing permissions and limitations under the License.
2301 ****************************************************************************************/
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315var HIDE_ACTIVITY_LOCAL_STORAGE_NAME = 'hideActivity';
2316var DEBUG_LOCAL_STORAGE_NAME = 'debug';
2317
2318
2319var _satellite = window._satellite;
2320
2321if (_satellite && !window.__satelliteLoaded) {
2322 // If a consumer loads the library multiple times, make sure only the first time is effective.
2323 window.__satelliteLoaded = true;
2324
2325 var container = _satellite.container;
2326
2327 // Remove container in public scope ASAP so it can't be manipulated by extension or user code.
2328 delete _satellite.container;
2329
2330 var undefinedVarsReturnEmpty = container.property.settings.undefinedVarsReturnEmpty;
2331
2332 var dataElements = container.dataElements || {};
2333
2334 // Remove when migration period has ended.
2335 dataElementSafe.migrateCookieData(dataElements);
2336
2337 var getDataElementDefinition = function(name) {
2338 return dataElements[name];
2339 };
2340
2341 var moduleProvider = createModuleProvider();
2342
2343 var replaceTokens;
2344
2345 // We support data elements referencing other data elements. In order to be able to retrieve a
2346 // data element value, we need to be able to replace data element tokens inside its settings
2347 // object (which is what replaceTokens is for). In order to be able to replace data element
2348 // tokens inside a settings object, we need to be able to retrieve data element
2349 // values (which is what getDataElementValue is for). This proxy replaceTokens function solves the
2350 // chicken-or-the-egg problem by allowing us to provide a replaceTokens function to
2351 // getDataElementValue that will stand in place of the real replaceTokens function until it
2352 // can be created. This also means that createDataElementValue should not call the proxy
2353 // replaceTokens function until after the real replaceTokens has been created.
2354 var proxyReplaceTokens = function() {
2355 return replaceTokens.apply(null, arguments);
2356 };
2357
2358 var getDataElementValue = createGetDataElementValue(
2359 moduleProvider,
2360 getDataElementDefinition,
2361 proxyReplaceTokens,
2362 undefinedVarsReturnEmpty
2363 );
2364
2365 var customVars = {};
2366 var setCustomVar = createSetCustomVar(
2367 customVars
2368 );
2369
2370 var isVar = createIsVar(
2371 customVars,
2372 getDataElementDefinition
2373 );
2374
2375 var getVar = createGetVar(
2376 customVars,
2377 getDataElementDefinition,
2378 getDataElementValue
2379 );
2380
2381 replaceTokens = createReplaceTokens(
2382 isVar,
2383 getVar,
2384 undefinedVarsReturnEmpty
2385 );
2386
2387 var localStorage = getNamespacedStorage('localStorage');
2388
2389 var getDebugOutputEnabled = function() {
2390 return localStorage.getItem(DEBUG_LOCAL_STORAGE_NAME) === 'true';
2391 };
2392
2393 var setDebugOutputEnabled = function(value) {
2394 localStorage.setItem(DEBUG_LOCAL_STORAGE_NAME, value);
2395 logger.outputEnabled = value;
2396 };
2397
2398 var getShouldExecuteActions = function() {
2399 return localStorage.getItem(HIDE_ACTIVITY_LOCAL_STORAGE_NAME) !== 'true';
2400 };
2401
2402 logger.outputEnabled = getDebugOutputEnabled();
2403
2404 // Important to hydrate satellite object before we hydrate the module provider or init rules.
2405 // When we hydrate module provider, we also execute extension code which may be
2406 // accessing _satellite.
2407 hydrateSatelliteObject(
2408 _satellite,
2409 container,
2410 setDebugOutputEnabled,
2411 getVar,
2412 setCustomVar
2413 );
2414
2415 hydrateModuleProvider(
2416 container,
2417 moduleProvider,
2418 replaceTokens,
2419 getDataElementValue
2420 );
2421
2422 initRules(
2423 _satellite,
2424 container.rules || [],
2425 moduleProvider,
2426 replaceTokens,
2427 getShouldExecuteActions
2428 );
2429}
2430
2431// Rollup's iife option always sets a global with whatever is exported, so we'll set the
2432// _satellite global with the same object it already is (we've only modified it).
2433var src = _satellite;
2434
2435return src;
2436
2437}());