updating client time with website time that uses lightstreamer - javascript

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.

Related

Is there an easy way to deobfuscate this javascript?

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.

Crypto-Js library's hmac-256 script returning function structure instead of value within Google Apps Script, working fine outside?

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.

React: expected an assignment or function call and instead saw an expression no-unused-expressions

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 ).

Easing animations in Canvas

Trying to create a function that lets you animate any number of numerical properties with a given easing function, but it doesn't quite work... calling it doesn't result in any motion. Everything is set up correctly as when I change what the values change to, it does show, so that means it's the equation that's the problem here. It's either not giving the right value, or not getting the right ones.
function animate(obj, props, options) {
var start = Date.now(),
total = start + options.duration,
diff = total - start,
vals = {},
id;
for (var v in props) {
vals[v] = props[v];
}
(function update() {
var curr = Date.now(),
progress = Math.min((options.duration - (total - curr)) / options.duration, 1);
for (var p in props) {
console.log(obj[p] = options.equation(curr, vals[p], obj[p] - vals[p], total));
}
if (progress < 1) {
id = requestAnimationFrame(update);
} else {
id = cancelAnimationFrame(id);
if (typeof options.callback === 'function') {
options.callback();
}
}
}());
}
animate(rect, {
x: map.width / 2,
y: map.height / 2
}, {
duration: 2000,
equation: function(t, b, c, d) {
return c * (t /= d) * t + b;
},
callback: function() {
console.log('Whoa... it works.'); // ...yeah, nope. ;(
}
});
t = time, b = beginning value, c = change in value, d = duration.
Am I giving it the wrong arguments? How would I make this work?
Your time & duration arguments should not be summed with Date.now().
If you want your easing to take 2000ms then send 2000 (d) into the easing equation.
The time to send into the easing equation is the elapsed time, so send Date.now()-startTime (t) into the easing equation.
I assume you have properly set the beginning value (b) and net change in value (c).

Javascript Float32 array throws Cannot read property '0' of null even though array is well defined

Here you can see the debug window: http://i.imgur.com/ZnfeKT1.png
As you can see, the array is NOT null and has in fact 2 elements. Why the hell am I getting that error ?
Edit: This code was written in C# and converted to JS via DuoCode:
WebGL.Vector2 = $d.declare("WebGL.Vector2", null, 62, $asm, function($t, $p) {
$t.cctor = function() {
$t.GLVector2 = vec2;
};
$t.ctor = function Vector2() {
this.vec = null;
};
$t.ctor.prototype = $p;
$p.get_X = function Vector2_get_X() {
return this.vec[0]; //this is line 777
};
$p.set_X = function Vector2_set_X(value) {
this.vec[0] = value;
return value;
};
$p.get_Y = function Vector2_get_Y() {
return this.vec[1];
};
$p.set_Y = function Vector2_set_Y(value) {
this.vec[1] = value;
return value;
};
$p.get_Magnitude = function Vector2_get_Magnitude() {
return Math.sqrt(this.get_X() * this.get_X() + this.get_Y() * this.get_Y());
};
$p.get_Normalized = function Vector2_get_Normalized() {
var m = this.get_Magnitude();
return WebGL.Vector2.op_Division(this, m);
};
$t.ctor$1 = function Vector2() {
this.vec = $d.array(System.Single, 2);
this.set_X(0);
this.set_Y(0);
};
$t.ctor$1.prototype = $p;
$t.ctor$2 = function Vector2(x, y) {
this.vec = $d.array(System.Single, 2);
this.set_X(x);
this.set_Y(y);
};
$t.ctor$2.prototype = $p;
$p.Rotated = function Vector2_Rotated(angle) {
var rad = Math.PI * angle / 180;
var cs = Math.cos(rad);
var sn = Math.sin(rad);
return new WebGL.Vector2.ctor$2(this.get_X() * cs - this.get_Y() * sn, this.get_X() * sn + this.get_Y() * cs);
};
$p.Transformed = function Vector2_Transformed(matrix) {
var ret = new WebGL.Vector2.ctor$1();
$t().GLVector2.transformMat3(ret.vec, this.vec, matrix.mat);
return ret;
};
$t.op_Multiply = function Vector2_op_Multiply(v, f) {
return new WebGL.Vector2.ctor$2(v.get_X() * f, v.get_Y() * f);
};
$t.op_Division = function Vector2_op_Division(v, f) {
return new WebGL.Vector2.ctor$2(v.get_X() / f, v.get_Y() / f);
};
$t.op_Addition = function Vector2_op_Addition(v1, v2) {
return new WebGL.Vector2.ctor$2(v1.get_X() + v2.get_X(), v1.get_Y() + v2.get_Y());
};
$t.op_Subtraction = function Vector2_op_Subtraction(v1, v2) {
return new WebGL.Vector2.ctor$2(v1.get_X() - v2.get_X(), v1.get_Y() - v2.get_Y());
};
$t.Dot = function Vector2_Dot(v1, v2) {
return v1.get_X() * v2.get_X() + v1.get_Y() * v2.get_Y();
};
$p.ToString = function Vector2_ToString() {
return String.Format("[{0}, {1}]", $d.array(System.Object, [this.get_X(), this.get_Y()]));
};
});
You're right, this is a bad behavior, but it happens because of an experimental feature in C# 6 (parameterless constructors). Usually C# forbids declaring default constructors for structs, that's why there must be an automatic default ctor that initializes the struct (and sets null to reference-type fields like the array "vec").
C# 6 added the option for primary constructors - but Microsoft already realized that it's too complicated and I believe they plan to abandon this feature for now.
DuoCode uses Roslyn for compilation and that's the reason for this behavior. Next releases of Roslyn and DuoCode probably will forbid this.
I would recommend that you make your Vector2 struct as an immutable struct with two fields (x, y) - that would work the best.
Disclaimer: I work with the DuoCode developers
Edit: Oops, it's called parameterless constructors
Okay the problem was the following: For some reason, DuoCode generates a default constructor for structs which initializes value types with null. My custom default constructor is ONLY called when I explicitly call Vector2 v = new Vector2(). This behavior is pretty unexpected and quite annoying to be honest. I hope this will be fixed in later releases.

Categories

Resources