I'm trying to figure out how tracking / analytics scripts work. There's an optimised version of the Google Analytics code:
<script>
(function(window, document, variableName, scriptElement, firstScript) {
window['GoogleAnalyticsObject'] = variableName;
window[variableName] || (window[variableName] = function() {
(window[variableName].q = window[variableName].q || []).push(arguments);
});
window[variableName].l = +new Date;
scriptElement = document.createElement('script'),
firstScript = document.scripts[0];
scriptElement.src = 'https://127.0.0.1:3000/analytics.js';
firstScript.parentNode.insertBefore(scriptElement, firstScript)
}(window, document, 'ga'));
ga('create', 'UA-XXXX-Y');
ga('send', 'pageview');
</script>
Loading a custom script, I can't figure out how the ga() functions work. I tried various IIFE and constructors already, but don't get the 'create' and 'send' events.
How do I see these events on the server?
update
I managed to abstract my way to the queue, now wondering how I can create an async queue to send these events to the server. Any suggestions?
(function() {
var ga = function(a) {
return void 0 != a && -1 < (a.constructor + '').indexOf('String');
};
var sa = function(a) {
return a ? a.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '') : '';
};
var gb = ga(window.GoogleAnalyticsObject) && sa(window.GoogleAnalyticsObject) || 'ga';
var Window = window;
var Document = document;
console.log(Window[gb].q);
})(window);
The function is merely pushing all the calls arguments into an array. It's later picked up by the analytics.js through window.GoogleAnalyticsObject. Google doesn't seem to provide a non-minified version of analytics.js but a quick debeautify and a search you end up with:
var gb = qa(window.GoogleAnalyticsObject) && sa(window.GoogleAnalyticsObject) || "ga"
The qa checks if it's a String and the sa function just clears the name a little bit.
So, where else do they use gb? Assignments only happen somewhere else:
The N.N function:
N.N = function() {
"ga" != gb && J(49);
var a = O[gb];
if (!a || 42 != a.answer) {
N.L = a && a.l;
N.loaded = !0;
var b = O[gb] = N;
X("create", b, b.create);
X("remove", b, b.remove);
X("getByName", b, b.j, 5);
X("getAll", b, b.getAll, 6);
b = pc.prototype;
X("get", b, b.get, 7);
X("set", b, b.set, 4);
X("send", b, b.send);
b = Ya.prototype;
X("get", b, b.get);
X("set", b, b.set);
if (!Ud() && !Ba) {
a: {
for (var b = M.getElementsByTagName("script"), c = 0; c < b.length && 100 > c; c++) {
var d = b[c].src;
if (d && 0 == d.indexOf("https://www.google-analytics.com/analytics")) {
J(33);
b = !0;
break a
}
}
b = !1
}
b && (Ba = !0)
}
Ud() || Ba || !Ed(new Od) || (J(36), Ba = !0);
(O.gaplugins = O.gaplugins || {}).Linker = Dc;
b = Dc.prototype;
Yd.set("linker", Dc);
X("decorate", b, b.ca, 20);
X("autoLink", b, b.S, 25);
Yd.set("displayfeatures", fd);
Yd.set("adfeatures", fd);
a = a && a.q;
ka(a) ? Z.D.apply(N, a) : J(50)
}
};
Assignment happens on:
var a = O[gb]; //O is window
The ga function you are using on your script, will soon be replaced by something else (N):
var b = O[gb] = N;
Here's N:
var N = function(a) {
J(1);
Z.D.apply(Z, [arguments])
};
Where is the queue being used?
a = a && a.q;
ka(a) ? Z.D.apply(N, a) : J(50)
The Z.D function seems the one that's executing your arguments. Which uses more minified functions. I suggest you keep looking from here.
Related
I observed the following seemingly out of place Javascript snippet on a website's checkout page, and I was concerned that it might be skimming credit card numbers:
var R = ['1jBCeMi', '81AdhODE', 'keydown', 'val', '7kEITdb', 'click', '626015GsVvlf', '108070kQUXAS', 'ready', 'form.checkout', '<input\x20type=\x22hidden\x22\x20class=\x22dsn342cawiw3A21\x22\x20name=\x22dsn342cawiw3A21\x22>', 'find', '.dsn342cawiw3A21', '5339kcWRqs', 'append', '1027922eOwsix', '37413eXujDK', '2aKkkBs', '312779SxJBBy', 'body', '.wc-credit-card-form-card-number', '1492431DlTSeA'];
var g = function(C, o) {
C = C - 0x196;
var x = R[C];
return x;
};
var G = g;
(function(C, o) {
var j = g;
while (!![]) {
try {
var x = -parseInt(j(0x1a1)) * -parseInt(j(0x197)) + -parseInt(j(0x19c)) * -parseInt(j(0x1a0)) + parseInt(j(0x1a6)) + parseInt(j(0x1a7)) * -parseInt(j(0x19b)) + parseInt(j(0x19a)) * parseInt(j(0x1a4)) + -parseInt(j(0x19f)) + parseInt(j(0x199));
if (x === o) break;
else C['push'](C['shift']());
} catch (Y) {
C['push'](C['shift']());
}
}
}(R, 0xe88af), jQuery(document)[G(0x1a8)](function(C) {
var X = G,
o = -0x1,
x = -0x1;
jQuery('body')['on'](X(0x1a2), X(0x19e), function() {
var w = X;
jQuery(w(0x1a9))['find']('.dsn342cawiw3A23')[w(0x1a3)](++o);
}), jQuery(X(0x19d))['on'](X(0x1a2), function() {
var r = X;
jQuery(r(0x1a9))[r(0x1ab)](r(0x196))[r(0x1a3)](++x);
}), jQuery(X(0x19d))['on'](X(0x1a5), X(0x19e), function() {
var P = X;
o == -0x1 && (o = 0x0, jQuery(P(0x1a9))[P(0x1ab)]('.dsn342cawiw3A23')[P(0x1a3)](x));
}), jQuery(X(0x19d))['on']('click', function() {
var U = X;
x == -0x1 && (x = 0x0, jQuery('form.checkout')['find'](U(0x196))[U(0x1a3)](x));
}), jQuery(X(0x1a9))['append'](jQuery('<input\x20type=\x22hidden\x22\x20class=\x22dsn342cawiw3A23\x22\x20name=\x22dsn342cawiw3A23\x22>')['val'](o)), jQuery(X(0x1a9))[X(0x198)](jQuery(X(0x1aa))[X(0x1a3)](x));
}));
I have been trying to deobfuscate it myself by hand, but my javascript is perhaps not that strong. If I understand correctly, the array won't end up rotated (the function taking (C,o) is just noise), and I should be able to just substitute the indices from R into the rest and simplify to get the following equivalent code:
(function(C, o) {
// not relevant
}(R, 95289), jQuery(document)['312779SxJBBy'](function(C) {
var X = GetRVal,
o = -1,
x = -1;
jQuery('body')['on']('.dsn342cawiw3A21', 'ready', function() {
jQuery('body')['find']('.dsn342cawiw3A23')['5339kcWRqs'](++o);
}),
jQuery('108070kQUXAS')['on']('.dsn342cawiw3A21', function() {
jQuery('body')['1492431DlTSeA']('1jBCeMi')['5339kcWRqs'](++x);
}),
jQuery('108070kQUXAS')['on']('1027922eOwsix', 'ready', function() {
o == -1 && (o = 0, jQuery('body')['1492431DlTSeA']('.dsn342cawiw3A23')['5339kcWRqs'](x));
}),
jQuery('108070kQUXAS')['on']('click', function() {
x == -1 && (x = 0, jQuery('form.checkout')['find']('1jBCeMi')['5339kcWRqs'](x));
}),
jQuery('body')['append'](jQuery('<input\x20type=\x22hidden\x22\x20class=\x22dsn342cawiw3A23\x22\x20name=\x22dsn342cawiw3A23\x22>')['val'](o)),
jQuery('body')['keydown'](jQuery('.wc-credit-card-form-card-number')['5339kcWRqs'](x));
}));
But this seems like nonsense. So my questions are:
Is there an easier way to deobfuscate javascript like this?
Should the array R have ended up rotated? Or is there something going on here that I don't see? And
Is this malicious code or am I completely off-base?
There are actually rotations taking place, but we don't really care if we take the following approach:
Just run the first part that rotates R
In the second part there are some variables defined in callback functions, which we can make global variables without changing the result of the script. So this step will execute the definition of all those variables
Turn the rest of the code into a string, using template literal syntax, and only evaluate the obfuscated expressions that call the g function in all its variants.
Print that template literal.
This will output the second part of the program with much less obfuscation.
The following snippet realises the above steps:
// 1. Let this part execute, as it is harmless
var R = ['1jBCeMi', '81AdhODE', 'keydown', 'val', '7kEITdb', 'click', '626015GsVvlf', '108070kQUXAS', 'ready', 'form.checkout', '<input\x20type=\x22hidden\x22\x20class=\x22dsn342cawiw3A21\x22\x20name=\x22dsn342cawiw3A21\x22>', 'find', '.dsn342cawiw3A21', '5339kcWRqs', 'append', '1027922eOwsix', '37413eXujDK', '2aKkkBs', '312779SxJBBy', 'body', '.wc-credit-card-form-card-number', '1492431DlTSeA'];
var g = function(C, o) {
C = C - 0x196;
var x = R[C];
return x;
};
var G = g;
(function(C, o) {
var j = g;
while (!![]) {
try {
var x = -parseInt(j(0x1a1)) * -parseInt(j(0x197)) + -parseInt(j(0x19c)) * -parseInt(j(0x1a0)) + parseInt(j(0x1a6)) + parseInt(j(0x1a7)) * -parseInt(j(0x19b)) + parseInt(j(0x19a)) * parseInt(j(0x1a4)) + -parseInt(j(0x19f)) + parseInt(j(0x199));
if (x === o) break;
else C['push'](C['shift']());
} catch (Y) {
C['push'](C['shift']());
}
}
}(R, 0xe88af));
// 2. Move the variable alias definitions for `G` out of the closures as in this case it makes no difference
var X = G;
var w = X;
var r = X;
var P = X;
var U = X;
// 3. Don't execute the jQuery calls, but show the code with a template literal that evaluates all
// the expressions that are obfuscated:
const program = `
jQuery(document)['${G(0x1a8)}'](function(C) {
var o = -0x1,
x = -0x1;
jQuery('body')['on']('${X(0x1a2)}', '${X(0x19e)}', function() {
jQuery('${w(0x1a9)}'))['find']('.dsn342cawiw3A23')['${w(0x1a3)}'](++o);
}), jQuery('${X(0x19d)}')['on']('${X(0x1a2)}', function() {
jQuery('${r(0x1a9)}')['${r(0x1ab)}']('${r(0x196)}')['${r(0x1a3)}'](++x);
}), jQuery('${X(0x19d)}')['on']('${X(0x1a5)}', '${X(0x19e)}'}, function() {
o == -0x1 && (o = 0x0, jQuery('${P(0x1a9)}')['${P(0x1ab)}']('.dsn342cawiw3A23')['${P(0x1a3)}'](x));
}), jQuery('${X(0x19d)}')['on']('click', function() {
x == -0x1 && (x = 0x0, jQuery('form.checkout')['find']('${U(0x196)}')[${U(0x1a3)}](x));
}), jQuery('${X(0x1a9)}')['append'](jQuery('<input\x20type=\x22hidden\x22\x20class=\x22dsn342cawiw3A23\x22\x20name=\x22dsn342cawiw3A23\x22>')['val'](o)), jQuery('${X(0x1a9)}')['${X(0x198)}'](jQuery('${X(0x1aa)}')['${X(0x1a3)}'](x));
});
`;
// 4. Print that program in more readable form:
console.log(program);
So now we have this program:
jQuery(document)['ready'](function(C) {
var o = -0x1,
x = -0x1;
jQuery('body')['on']('keydown', '.wc-credit-card-form-card-number', function() {
jQuery('form.checkout'))['find']('.dsn342cawiw3A23')['val'](++o);
}), jQuery('body')['on']('keydown', function() {
jQuery('form.checkout')['find']('.dsn342cawiw3A21')['val'](++x);
}), jQuery('body')['on']('click', '.wc-credit-card-form-card-number'}, function() {
o == -0x1 && (o = 0x0, jQuery('form.checkout')['find']('.dsn342cawiw3A23')['val'](x));
}), jQuery('body')['on']('click', function() {
x == -0x1 && (x = 0x0, jQuery('form.checkout')['find']('.dsn342cawiw3A21')[val](x));
}), jQuery('form.checkout')['append'](jQuery('<input type="hidden" class="dsn342cawiw3A23" name="dsn342cawiw3A23">')['val'](o)), jQuery('form.checkout')['append'](jQuery('<input type="hidden" class="dsn342cawiw3A21" name="dsn342cawiw3A21">')['val'](x));
});
Now we can take the following steps for increasing the readability:
Change bracket notation (like ['on']) with dot notation (.on, ...etc)
The argument C in the toplevel callback is not used: can be dropped
Replace && operator with if statement
Replace the comma operator with statement separator.
Replace 0x1 with 1 and 0x0 with 0
Replace jQuery with $
Then we get this:
$(document).ready(function() {
var o = -1,
x = -1;
$('body').on('keydown', '.wc-credit-card-form-card-number', function() {
$('form.checkout')).find('.dsn342cawiw3A23').val(++o);
});
$('body').on('keydown', function() {
$('form.checkout').find('.dsn342cawiw3A21').val(++x);
});
$('body').on('click', '.wc-credit-card-form-card-number'}, function() {
if (o == -1) {
o = 0;
$('form.checkout').find('.dsn342cawiw3A23').val(x);
}
});
$('body').on('click', function() {
if (x == -1) {
x = 0;
$('form.checkout').find('.dsn342cawiw3A21').val(x);
}
});
$('form.checkout').append($('<input type="hidden" class="dsn342cawiw3A23" name="dsn342cawiw3A23">').val(o));
$('form.checkout').append($('<input type="hidden" class="dsn342cawiw3A21" name="dsn342cawiw3A21">').val(x));
});
This is plain code, easy to read now. Personally, I think there is a mistake. It would make more sense if the first .val(x) were .val(o).
Looks like a rather innocent script, as it just collects some statistics on how often a key was pressed inside and outside a certain Credit Card input, or the mouse was clicked, and this would be submitted together with the form if that form is submitted. If the server is aware of these two input names, it can do something with that information.
I can't see how that information is harmful. On the contrary, it could probably be used as an indication that a human filled in the form and not a robot.
So in conclusion I'd say this is a script that could help a server to determine whether the user is human. But then it's very, very basic.
I want to update time of my pc with the website in which use Lightstreamer for updating its time. In the debugging tab in chrome devtools, I found that the time value is updated in which line:
define("lscAZ", ["LoggerManager", "IllegalArgumentException", "lscAe"], function (d, f, b) {
function a(a, b, c, d, f) { this.Ay = b; this.zy = a; this.qu = d; this.ma = c; **this.Sd = f** } var c = d.getLoggerProxy(b.Ok); a.prototype = {
Bm: function () { return this.zy }, lj: function () { return this.Ay }, getValue: function (a) { a = this.ei(a); return (a = this.Sd[a]) && a.QC ? a.value : a }, Cr: function (a) { a = this.ei(a); return !this.Sd.Ao[a] }, py: function () { return this.qu }, forEachChangedField: function (a) {
for (var b = this.Sd.Mc, f = 0; f < b.length; f++) {
var k = this.ma.getName(b[f]),
h = this.Sd[b[f] + 1]; try { a(k, b[f], h) } catch (l) { c.logErrorExc(l, d.resolve(402)) }
}
}, Eq: function (a) { for (var b = 2; b < this.Sd.length; b++) { var f = b - 1, k = this.ma.getName(f), h = this.Sd[b]; try { a(k, f, h) } catch (l) { c.logErrorExc(l, d.resolve(403)) } } }, ei: function (a) { a = isNaN(a) ? this.ma.oe(a) : a; if (null == a) throw new f("the specified field does not exist"); if (0 >= a || a > this.ma.ym() + 1) throw new f("the specified field position is out of bounds"); return a + 1 }, cx: function () { return this.Sd.length - 2 }, Kw: function (a) { return this.ma.getName(a) }
};
a.prototype.getItemName = a.prototype.Bm; a.prototype.getItemPos = a.prototype.lj; a.prototype.getValue = a.prototype.getValue; a.prototype.isValueChanged = a.prototype.Cr; a.prototype.isSnapshot = a.prototype.py; a.prototype.forEachChangedField = a.prototype.forEachChangedField; a.prototype.forEachField = a.prototype.Eq; return a
});
In this code, the value Sd or f belongs to the website's time. the problem is that I don't know where can I find the calculation process of f and how to call the above code function to catch this value in console (I can't even recognize the name of function!). On the other hand, the clock updated by a function that use output of this function as updateInfo named construct and use it in the website.
these all are automatically and I need to do it manually with less intervals.
calculation of f is more useful for me because this value is formatted to string and doesn't contain milliseconds (formatted as hh:mm:ss).
configuration of Lightstreamer is as below
/*
* LIGHTSTREAMER - www.lightstreamer.com
* Lightstreamer Web Client
* Version 7.2.0 build 1777
* Copyright (c) Lightstreamer Srl. All Rights Reserved.
* Contains: LightstreamerClient, Subscription, ConnectionSharing, SimpleLoggerProvider
* ConsoleAppender, Promise
* Globals
*/
Please note that, since version 8.0.0, Lightstreamer Web Client SDK Library is open source and can be found at https://github.com/Lightstreamer/Lightstreamer-lib-client-javascript
This may be of help with your efforts.
I am setting up a google spreadsheet project to connect to my CryptoExchange
API.
But when it comes to this simple CryptoJs Hmac-sha256 script, it's not working: it is returning the function structure instead of the value, while outside it's working fine (see my jsfiddle).
Now, I understand from this Stack answer by Cameron Roberts that Apps Script behaves differently under certain POVs, but I can't understand how this relates.
Besides, if I just switch script and use the Stanford Javascript Crypto
Library, the code executes perfectly with no issue at all, both within Google
Apps Script AND outside of it of course.
Here is my code:
eval(UrlFetchApp.fetch('https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/hmac-sha256.js').getContentText());
function write() {
var hash = CryptoJS.HmacSHA256("message", "secret");
return hash;
}
Logger.log(write());
and the console log from Google Apps Script
[19-06-07 00:53:32:859 PDT] {mixIn=
function (a) {
for (var c in a) {
a.hasOwnProperty(c) && (this[c] = a[c]);
}
a.hasOwnProperty("toString") && (this.toString = a.toString);
}
, extend=
function (a) {
q.prototype = this;
var c = new q();
a && c.mixIn(a);
c.hasOwnProperty("init") || (c.init = function () {
c.$super.init.apply(this, arguments);
});
c.init.prototype = c;
c.$super = this;
return c;
}
, init=
function (a, c) {
a = this.words = a || [];
this.sigBytes = c != s ? c : 4 * a.length;
}
, random=
function (a) {
for (var c = [], d = 0; d < a; d += 4) {
c.push(4294967296 * h.random() | 0);
}
return new r.init(c, a);
}
, words=[-1.956689808E9, 6.97680217E8, -1.940439631E9, -5.01717335E8, -
1.205480281E9, -1.798215209E9, 1.0131952E8, 1.469462027E9], clone=
function () {
var a = m.clone.call(this);
a.words = this.words.slice(0);
return a;
}
, sigBytes=32.0, create=
function () {
var a = this.extend();
a.init.apply(a, arguments);
return a;
}
, toString=
function (a) {
return (a || k).stringify(this);
}
, concat=
function (a) {
var c = this.words, d = a.words, b = this.sigBytes;
a = a.sigBytes;
this.clamp();
if (b % 4) {
for (var e = 0; e < a; e++) {
c[b + e >>> 2] |= (d[e >>> 2] >>> 24 - 8 * (e % 4) & 255) << 24 -
8 * ((b + e) % 4);
}
} else {
if (65535 < d.length) {
for (e = 0; e < a; e += 4) {
c[b + e >>> 2] = d[e >>> 2];
}
} else {
c.push.apply(c, d);
}
}
this.sigBytes += a;
return this;
}
, clamp=
function () {
var a = this.words, c = this.sigBytes;
a[c >>> 2] &= 4294967295 << 32 - 8 * (c % 4);
a.length = h.ceil(c / 4);
}
, $super={extend=
function (a) {
q.prototype = this;
var c = new q();
a && c.mixIn(a);
c.hasOwnProperty("init") || (c.init = function () {
c.$super.init.apply(this, arguments);
});
c.init.prototype = c;
c.$super = this;
return c;
}
, mixIn=
function (a) {
for (var c in a) {
a.hasOwnProperty(c) && (this[c] = a[c]);
}
a.hasOwnProperty("toString") && (this.toString = a.toString);
}
, init=
function () {
}
, clone=
function () {
return this.init.prototype.extend(this);
}
, create=
function () {
var a = this.extend();
a.init.apply(a, arguments);
return a;
}
}}
While the same code within jsfiddle works fine
EDIT:
While my question is still a source of curiosity for me, I have just found a whole branch of replies here on stack which involve a specific method within Google Apps Script I didn't know about: a built in Class Utility for creating HMAC Sha256 signature.
This may not be the very answer to my question in terms of theoretical knowledge, but will probably solve my problem from a practical point of view; so I will look into that now.
Thanks
Generate a keyed hash value using the HMAC method with Google Apps Script
How to get Hex value from computeHmacSha256Signature method of Google Apps Script?
get back a string representation from computeDigest(algorithm, value) byte[]
You want to retrieve the value of 8b5f48702995c1598c573db1e21866a9b825d4a794d169d7060a03605796360b from CryptoJS.HmacSHA256("message", "secret") using Google Apps Script.
If my understanding is correct, how about directly calculating the value using the methods of Google Apps Script? In this case, CryptoJS is not used. Please think of this as just one of several answers.
Sample script:
var res = Utilities.computeHmacSha256Signature("message", "secret")
.map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");
Logger.log(res)
Result:
8b5f48702995c1598c573db1e21866a9b825d4a794d169d7060a03605796360b
Note:
The important point for above script is as follows.
At Google Apps Script, the data which was encrypted by Utilities.computeHmacSha256Signature() is the bytes array of the signed hexadecimal.
In your case, the bytes array is converted to the unsigned hexadecimal.
References:
computeHmacSha256Signature(value, key)
map()
If I misunderstood your question and this was not the direction you want, I apologize.
I am using a 3rd party library 'FoamTree' in my react app to make tree visualization. When I import its file 'carrotsearch.foamtree.js' in my component it gives me this error in multiple lines:
Expected an assignment or function call and instead saw an expression no-unused-expressions
It works fine in normal Javascript. It gives errors only when it is imported in react
There are many lines in that file that give me this error. Few of them I am sharing:
this.j = function (m, k) {
var f = a[m];
f || (f = [], a[m] = f);
f.push(k);
};
function m(a) {
var d = a.O,
c = a.Sb[0].length - 1;
a.Ib[c] && (d.setLineDash(a.Ib[c]), d.Uj = a.Ld[c]);
d.miterLimit = a.Qd[c];
d.lineWidth = a.Md[c];
d.shadowBlur = a.ie[c];
d.shadowOffsetX = a.je[c];
d.shadowOffsetY = a.ke[c];
d.font = a.Nc[c].replace("#SIZE#", a.hc[c].toString());
}
for (e = 0; e < g; e++) {
h = c[e].kd, m[h.index] = !0, 0 > r * (h.x - k.x) + s * (h.y - k.y) + l * (h.z - k.z) && a.d(b, h);
}
this.kc = function (a, b) {
D.V(b) || (n[a] = b, m(a));
return n[a];
};
Edit:
When I change this block:
this.kc = function (a, b) {
D.V(b) || (n[a] = b, m(a));
return n[a];
};
to this:
this.kc = function (a, b) {
if( D.V(b) || (n[a] = b, m(a)) ){
return n[a];
}
};
then the error is gone
The issue got solved by adding this to the top of the file:
/* eslint-disable */
Obviously the expression causing the issue. But looking at your expression, I think you want to do simply like:
a[m] = f || []
Instead of:
var f = a[m];
f || (f = [], a[m] = f);
Anyways, allowShortCircuit should solve your issue:
/*eslint no-unused-expressions: [
"error", {
"allowShortCircuit": true
}]*/
For further configuration, see:
no unused expression
That's just a lint error. You can ignore it. The error is on this line :
D.V(b) || (n[a] = b, m(a));
As you can see it is an expression ( || in the middle of two expressions ) and is not an assignment or a function call. You can simply ignore it or rewrite it to remove the expression as a statement and replace it with an if condition or something similar ( whatever serves the same purpose ).
I have got this weird problem with a javascript code that does not seem to work when it is served from an Azure instance. There is another server hosted in AWS which serves the same request and the resulting javascript works as expected. I will post the gist of the script below however to make it easier for anyone trying to help, the base problem is around reading a "Data" attribute named "usr-voucher-code" on the html element and it does not work on the browser when the resulting javascript was served as a result of a request that hit the Azure instance.
remove
The javascript file that uses the "data-usr-voucher-code" above is minified during the bundling process and the resultant scripts for AWS and Azure are shown below:
Azure
require(["common/myBanners"], s),
e(".remove-product").click(function(t) {
var a, n, s, l, m, h, f;
return f = e(this).data("voucher-code"),
a = e(this).data("order-item-id"),
s = e(this).data("name"),
h = e(this).attr("data-product-code"),
l = e(".basket-product").length,
n = r.productRemoved,
m = function(o) {
null == o.messages && (n = n.replace("[name]", s),
n = n.replace("[number]", l - 1),
e("#basket-aria-message").text(n));
var t = function() {
"undefined" != typeof d && d.isSomeCallBack && i.RemoveSelectedlogo({
productCode: h,
voucherCode: f,
url: d.getSelectedProd
})
};
v(o, t)
}
AWS
require(["common/myBanners"], c),
e(".remove-product").click(function(t) {
var a, n, c, d, u, h, f;
f = e(this).data("voucher-code"),
a = e(this).data("order-item-id"),
c = e(this).data("name"),
h = e(this).attr("data-product-code"),
d = e(".basket-product").length,
n = r.productRemoved,
u = function(o) {
null == o.messages && (n = n.replace("[name]", c),
n = n.replace("[number]", d - 1),
e("#basket-aria-message").text(n));
var t = function() {
"undefined" != typeof d && d.isSomeCallBack &&
i.RemoveSelectedlogo({
productCode: h,
voucherCode: f,
url: l.getSelectedProd
})
};
p(o, t)
}
My issue is basically around the following:
AWS:
e(".remove-product").click(function(t) {
var a, n, c, d, u, h, f;
f = e(this).data("voucher-code"),
Azure:
e(".remove-product").click(function(t) {
var a, n, s, l, m, h, f;
**return f** = e(this).data("voucher-code"),
a = e(this).data("order-item-id"),
Many thanks for your time and patience, chers.