node.js change in concatenation? - javascript
I'm trying to debug some code that another programmer has left for me to maintain. I've just attempted to upgrade from node.js 5 to node.js 8 and my database queries are for some requests coming back with key not found errors
We're using couchbase for the database and our document keys are "encrypted" for security. So we may have a key that starts like this "User_myemail#gmail.com" but we encrypt it using the following method:
function _GetScrambledKey(dbKey)
{
//select encryption key based on db key content
var eKeyIndex = CalculateEncryptionKeyIndex(dbKey, eKeys.length);
var sha = CalculateSHA512(dbKey + eKeyIndex);
return sha;
}
function CalculateEncryptionKeyIndex(str, max)
{
var hashBuf = CalculateSHA1(str);
var count = 0;
for (var i = 0; i < hashBuf.length; i++)
{
count += hashBuf[i];
count = count % max;
}
return count;
}
We then query couchbase for the document with
cb.get("ECB_"+encryptedKey, opts, callback);
In node5 this worked but in node8 we're getting some documents return fine and others return as missing. I outputted the "ECB_"+encryptedKey as an int array and the results have only confused me more. They are different on node5 to node8 but only by one character right in the middle of the array.
Outputting the encryptedKey as an int array on both versions shows this
188,106,14,227,211,70,94,97,63,130,78,246,155,65,6,148,62,215,47,230,211,109,35,99,21,60,178,74,195,13,233,253,187,142,213,213,104,58,168,60,225,148,25,101,155,91,122,77,2,99,102,235,26,71,157,99,6,47,162,152,58,181,21,175
Then outputting the concatenated string, in the same way, shows slightly different results
This is the node8 output
Node8 key: 69,67,66,95,65533,106,14,65533,65533,70,94,97,63,65533,78,65533,65533,65,6,65533,62,65533,47,65533,65533,109,35,99,21,60,65533,74,65533,13,65533,65533,65533,65533,65533,65533,104,58,65533,60,65533,25,101,65533,91,122,77,2,99,102,65533,26,71,65533,99,6,47,65533,65533,58,65533,21,65533
And this is the node5 output
Node5 key: 69,67,66,95,65533,106,14,65533,65533,70,94,97,63,65533,78,65533,65533,65,6,65533,62,65533,47,65533,65533,109,35,99,21,60,65533,74,65533,13,65533,65533,65533,65533,65533,65533,104,58,65533,60,65533,65533,25,101,65533,91,122,77,2,99,102,65533,26,71,65533,99,6,47,65533,65533,58,65533,21,65533
I had to run it through a diff tool to see the difference
Comparing that to the original pre-append array it looks like the 225 has just been dropped in node8. Is 225 significant? I can't understand how that would be possible otherwise unless it's a bug. Does anyone have any ideas?
Looks like this was a change in v8 5.5 https://github.com/nodejs/node/issues/21278
A lot of the issues you are facing, including the concatenation can be cleaned up using newer features from ES6 that are available in node 8.
In general, you should avoid doing string concatenations with the + operator and should use string literals instead. In your case, you should replace the "ECB_"+encryptedKey with `ECB_${encryptedKey}`.
Additionally, if you want to output the contents of the integers values from this concatenated string, then you are better off using .join, the spread operator (...) and the Buffer class from Node as follows:
let encKey = `ECB_${encryptedKey}`;
let tmpBuff = Buffer.from(encKey);
let buffArrVals = [...tmpBuff];
console.log(buffArrVals.join(','));
Also, if you can help it, you really should avoid using var inside of function blocks like it exists in your sample code. var performs something called variable hoisting and causes the variable to become available outside the scope it was declared, which is seldom intended. From node 6+ onward the recommendation is to use let or const for variable declarations to ensure they stay scoped to the block they are declared.
Related
How to parseInt or ParseInt embedded data with TypeScript in Qualtrics?
Even when I save an integer to embedded data earlier in the survey flow (in previous blocks on different screens), I am not able in Javascript to get the embedded data value, ensure it is parsed as a number/integer, then use it in a loop. Is this something about TypeScript? I didn't see anything about parseInt or ParseInt in the TypeScript documentation. For example, suppose I do the following: // Draw a random number var x = Math.floor(Math.random() * 5); // Save it in embedded data Qualtrics.SurveyEngine.setEmbeddedData("foo", x); // In a later block on a different screen, get the embedded data as an integer var x_new = "${e://Field/foo}"; // not an int var x_new = parseInt("${e://Field/foo}"); // doesn't work var x_new = ParseInt("${e://Field/foo}"); // doesn't work // Loop using x_new: for(i = 0; i < x_new; i++) { console.log(i) } Any idea why this isn't working? Perhaps I just don't know how to parseint().
In "normal" JS runtime system, we have parseInt function, the function gets a string (like number string) as a parameter. In this env, we don't support your syntax - "${e://Field/foo}", because it is not a "number string". In Qualtrics system environment they have parseInt too, but they support their custom syntax "${e://Field/foo}" to get EmbeddedData. Make sure that your code is running on Qualtrics system environment.
ParseInt is just turning your string into an integer. Look at the demo below. let myVar = "${e://Field/foo}"; // This is a string console.log(myVar); // This prints a string console.log(parseInt(myVar)); // This prints "NaN", i.e. Not a Number, because the string isn't a representation of a number.
razor engine syntax inside javascript tag for non string variables [duplicate]
Can someone format the code below so that I can set srcript variables with c# code using razor? The below does not work, i've got it that way to make is easy for someone to help. #{int proID = 123; int nonProID = 456;} <script type="text/javascript"> #{ <text> var nonID =#nonProID; var proID= #proID; window.nonID = #nonProID; window.proID=#proID; </text> } </script> I am getting a design time error
You should take a look at the output that your razor page is resulting. Actually, you need to know what is executed by server-side and client-side. Try this: #{ int proID = 123; int nonProID = 456; } <script> var nonID = #nonProID; var proID = #proID; window.nonID = #nonProID; window.proID = #proID; </script> The output should be like this: Depending what version of Visual Studio you are using, it point some highlights in the design-time for views with razor.
Since razor syntax errors can become problematic while you're working on the view, I totally get why you'd want to avoid them. Here's a couple other options. <script type="text/javascript"> // #Model.Count is an int var count = '#Model.Count'; var countInt = parseInt('#Model.ActiveLocsCount'); </script> The quotes act as delimiters, so the razor parser is happy. But of course your C# int becomes a JS string in the first statement. For purists, the second option might be better. If somebody has a better way of doing this without the razor syntax errors, in particular maintaining the type of the var, I'd love to see it!
This is how I solved the problem: #{int proID = 123; int nonProID = 456;} <script type="text/javascript"> var nonID = Number(#nonProID); var proID = Number(#proID); </script> It is self-documenting and it doesn't involve conversion to and from text. Note: be careful to use the Number() function not create new Number() objects - as the exactly equals operator may behave in a non-obvious way: var y = new Number(123); // Note incorrect usage of "new" var x = new Number(123); alert(y === 123); // displays false alert(x == y); // displays false
I've seen several approaches to working around the bug, and I ran some timing tests to see what works for speed (http://jsfiddle.net/5dwwy/) Approaches: Direct assignment In this approach, the razor syntax is directly assigned to the variable. This is what throws the error. As a baseline, the JavaScript speed test simply does a straight assignment of a number to a variable. Pass through `Number` constructor In this approach, we wrap the razor syntax in a call to the `Number` constructor, as in `Number(#ViewBag.Value)`. ParseInt In this approach, the razor syntax is put inside quotes and passed to the `parseInt` function. Value-returning function In this approach, a function is created that simply takes the razor syntax as a parameter and returns it. Type-checking function In this approach, the function performs some basic type checking (looking for null, basically) and returns the value if it isn't null. Procedure: Using each approach mentioned above, a for-loop repeats each function call 10M times, getting the total time for the entire loop. Then, that for-loop is repeated 30 times to obtain an average time per 10M actions. These times were then compared to each other to determine which actions were faster than others. Note that since it is JavaScript running, the actual numbers other people receive will differ, but the importance is not in the actual number, but how the numbers compare to the other numbers. Results: Using the Direct assignment approach, the average time to process 10M assignments was 98.033ms. Using the Number constructor yielded 1554.93ms per 10M. Similarly, the parseInt method took 1404.27ms. The two function calls took 97.5ms for the simple function and 101.4ms for the more complex function. Conclusions: The cleanest code to understand is the Direct assignment. However, because of the bug in Visual Studio, this reports an error and could cause issues with Intellisense and give a vague sense of being wrong. The fastest code was the simple function call, but only by a slim margin. Since I didn't do further analysis, I do not know if this difference has a statistical significance. The type-checking function was also very fast, only slightly slower than a direct assignment, and includes the possibility that the variable may be null. It's not really practical, though, because even the basic function will return undefined if the parameter is undefined (null in razor syntax). Parsing the razor value as an int and running it through the constructor were extremely slow, on the order of 15x slower than a direct assignment. Most likely the Number constructor is actually internally calling parseInt, which would explain why it takes longer than a simple parseInt. However, they do have the advantage of being more meaningful, without requiring an externally-defined (ie somewhere else in the file or application) function to execute, with the Number constructor actually minimizing the visible casting of an integer to a string. Bottom line, these numbers were generated running through 10M iterations. On a single item, the speed is incalculably small. For most, simply running it through the Number constructor might be the most readable code, despite being the slowest.
#{ int proID = 123; int nonProID = 456; } <script> var nonID = '#nonProID'; var proID = '#proID'; window.nonID = '#nonProID'; window.proID = '#proID'; </script>
One of the easy way is: <input type="hidden" id="SaleDateValue" value="#ViewBag.SaleDate" /> <input type="hidden" id="VoidItem" value="#Model.SecurityControl["VoidItem"].ToString()" /> And then get the value in javascript: var SaleDate = document.getElementById('SaleDateValue').value; var Item = document.getElementById('VoidItem').value;
I found a very clean solution that allows separate logic and GUI: in your razor .cshtml page try this: <body id="myId" data-my-variable="myValue"> ...your page code here </body> in your .js file or .ts (if you use typeScript) to read stored value from your view put some like this (jquery library is required): $("#myId").data("my-variable")
Not so much an answer as a cautionary tale: this was bugging me as well - and I thought I had a solution by pre-pending a zero and using the #(...) syntax. i.e your code would have been: var nonID = 0#(nonProID); var proID = 0#(proID); Getting output like: var nonId = 0123; What I didn't realise was that this is how JavaScript (version 3) represents octal/base-8 numbers and is actually altering the value. Additionally, if you are using the "use strict"; command then it will break your code entirely as octal numbers have been removed. I'm still looking for a proper solution to this.
It works if you do something like this: var proID = #proID + 0; Which produces code that is something like: var proID = 4 + 0; A bit odd for sure, but no more fake syntax errors at least. Sadly the errors are still reported in VS2013, so this hasn't been properly addressed (yet).
I've been looking into this approach: function getServerObject(serverObject) { if (typeof serverObject === "undefined") { return null; } return serverObject; } var itCameFromDotNet = getServerObject(#dotNetObject); To me this seems to make it safer on the JS side... worst case you end up with a null variable.
This should cover all major types: public class ViewBagUtils { public static string ToJavascriptValue(dynamic val) { if (val == null) return "null"; if (val is string) return val; if (val is bool) return val.ToString().ToLower(); if (val is DateTime) return val.ToString(); if (double.TryParse(val.ToString(), out double dval)) return dval.ToString(); throw new ArgumentException("Could not convert value."); } } And in your .cshtml file inside the <script> tag: #using Namespace_Of_ViewBagUtils const someValue = #ViewBagUtils.ToJavascriptValue(ViewBag.SomeValue); Note that for string values, you'll have to use the #ViewBagUtils expression inside single (or double) quotes, like so: const someValue = "#ViewBagUtils.ToJavascriptValue(ViewBag.SomeValue)";
I use a very simple function to solve syntax errors in body of JavaScript codes that mixed with Razor codes ;) function n(num){return num;} var nonID = n(#nonProID); var proID= n(#proID);
This sets a JavaScript var for me directly from a web.config defined appSetting.. var pv = '#System.Web.Configuration.WebConfigurationManager.AppSettings["pv"]';
With var jsVar = JSON.parse(#Html.Raw(Json.Serialize(razorObject))); you can parse any razor object into a JavaScript object. It's long but universal
Delete multiple documents
The following code is working but extremely slow. Up till the search function all goes well. First, the search function returns a sequence and not an array (why?!). Second, the array consists of nodes and I need URI's for the delete. And third, the deleteDocument function takes a string and not an array of URI's. What would be the better way to do this? I need to delete year+ old documents. Here I use xdmp.log in stead of document.delete just te be safe. var now = new Date(); var yearBack = now.setDate(now.getDate() - 365); var date = new Date(yearBack); var b = cts.jsonPropertyRangeQuery("Dtm", "<", date); var c = cts.search(b, ['unfiltered']).toArray(); for (i=0; i<fn.count(c); i++) { xdmp.log(fn.documentUri(c[i]), "info"); };
Doing the same with cts.uris: var now = new Date(); var yearBack = now.setDate(now.getDate() - 365); var date = new Date(yearBack); var b = cts.jsonPropertyRangeQuery("Dtm", "<", date); var c = cts.uris("", [], b); while (true) { var uri = c.next(); if (uri.done == true){ break; } xdmp.log(uri.value, "info"); } HTH!
Using toArray will work but is most likely were your slowness is. The cts.search() function returns an iterator. So All you have to do is loop over it and do your deleting until there is no more items in it. Also You might want to limit your search to 1,000 items. A transaction with a large number of deletes will take a while and might time out. Here is an example of looping over the iterator var now = new Date(); var yearBack = now.setDate(now.getDate() - 365); var date = new Date(yearBack); var b = cts.jsonPropertyRangeQuery("Dtm", "<", date); var c = cts.search(b, ['unfiltered']); while (true) { var doc = c.next(); if (doc.done == true){ break; } xdmp.log(fn.documentUri(doc), "info"); } here is an example if you wanted to limit to the first 1,000. fn.subsequence(cts.search(b, ['unfiltered']), 1, 1000);
Several things to consider. 1) If you are searching for the purpose of deleting or anything that doesnt require the document body, using a search that returns URIs instead of nodes can be much faster. If that isnt convenient then getting the URI as close to the search expression can achieve similar results. You want to avoid having the server have to fetch and expand the document just to get the URI to delete it. 2) While there is full coverage in the JavaScript API's for all MarkLogic features, the JavaScript API's are based on the same underlying functions that the XQuery API's use. Its useful to understand that, and take a look at the equivalent XQuery API docs to get the big picture. For example Arrays vs Iterators - If the JS search API's returned Arrays it could be a huge performance problem because the underlying code is based on 'lazy evaluation' of sequences. For example a search could return 1 million rows but if you only look at the first one the server can often avoid accessing the remaining 999,999,999 documents. Similarly, as you iterate only the in scope referenced data needs to be in available. If they had to be put into an array then all results would have to be pre-fetched and put put in memory upfront. 3) Always keep in mind that operations which return lists of things may only be bounded by how big your database is. That is why cts.search() and other functions have built in 'pagination'. You should code for that from the start. By reading the users guides you can get a better understanding of not only how to do something, but how to do it efficiently - or even at all - once your database becomes larger than memory. In general its a good idea to always code for paginated results - it is a lot more efficient and your code will still work just as well after you add 100 docs or a million. 4) take a look at xdmp.nodeUrl https://docs.marklogic.com/xdmp.nodeUri, This function, unlike fn.documentUri(), will work on any node even if its not document node. If you can put this right next to the search instead of next to the delete then the system can optimize much better. The examples in the JavaScript guide are a good start https://docs.marklogic.com/guide/getting-started/javascript#chapter In your case I suggest something like this to experiment with both pagination and extracting the URIs without having to expand the documents .. var uris = [] for (var result of fn.subsequence(cts.search( ... ), 1 , 100 ) uris.push(xdmp.nodeUri(result)) for( i in uris ) xdmp.log( uris[i] )
What is the fastest way to read and parse a file of numerical ASCII pairs in Node.js?
I'm using Node.js to read and parse a file of pairs encoding numbers. I have a file like this: 1561 0506 1204 900 6060 44 And I want to read it as an array, like this: [[1561,0506],[1204,900],[6060,44]] For that, I am using a readStream, reading the file as chunks and using native string functions to do the parsing: fileStream.on("data",function(chunk){ var newLineIndex; file = file + chunk; while ((newLineIndex = file.indexOf("\n")) !== -1){ var spaceIndex = file.indexOf(" "); edges.push([ Number(file.slice(0,spaceIndex)), Number(file.slice(spaceIndex+1,newLineIndex))]); file = file.slice(newLineIndex+1); }; }); That took way to many time, though (4s for the file I need on my machine). I see some reasons: Use of strings; use of "Number"; Dynamic array of arrays. I've rewriten the algorithm without using the builtin string functions, but loops instead and, to my surprise, it became much slower! Is there any way to make it faster?
Caveat: I have not tested the performance of this solution, but it's complete so should be easy to try. How about using this liner implementation based on the notes in this question. Using the liner: var fs = require('fs') var liner = require('./liner') var source = fs.createReadStream('mypathhere') source.pipe(liner) liner.on('readable', function () { var line while (line = liner.read()) { var parts = line.split(" "); edges.push([Number(parts[0]), Number(parts[1])]); } }) As you can see I also moved the edge array to be an inline constant-sized array separate from the split parts, which I'm guessing would speed up allocation. You could even try swapping out using indexOf(" ") instead of split(" "). Beyond this you could instrument the code to identify any further bottlenecks.
How to set javascript variables using MVC4 with Razor
Can someone format the code below so that I can set srcript variables with c# code using razor? The below does not work, i've got it that way to make is easy for someone to help. #{int proID = 123; int nonProID = 456;} <script type="text/javascript"> #{ <text> var nonID =#nonProID; var proID= #proID; window.nonID = #nonProID; window.proID=#proID; </text> } </script> I am getting a design time error
You should take a look at the output that your razor page is resulting. Actually, you need to know what is executed by server-side and client-side. Try this: #{ int proID = 123; int nonProID = 456; } <script> var nonID = #nonProID; var proID = #proID; window.nonID = #nonProID; window.proID = #proID; </script> The output should be like this: Depending what version of Visual Studio you are using, it point some highlights in the design-time for views with razor.
Since razor syntax errors can become problematic while you're working on the view, I totally get why you'd want to avoid them. Here's a couple other options. <script type="text/javascript"> // #Model.Count is an int var count = '#Model.Count'; var countInt = parseInt('#Model.ActiveLocsCount'); </script> The quotes act as delimiters, so the razor parser is happy. But of course your C# int becomes a JS string in the first statement. For purists, the second option might be better. If somebody has a better way of doing this without the razor syntax errors, in particular maintaining the type of the var, I'd love to see it!
This is how I solved the problem: #{int proID = 123; int nonProID = 456;} <script type="text/javascript"> var nonID = Number(#nonProID); var proID = Number(#proID); </script> It is self-documenting and it doesn't involve conversion to and from text. Note: be careful to use the Number() function not create new Number() objects - as the exactly equals operator may behave in a non-obvious way: var y = new Number(123); // Note incorrect usage of "new" var x = new Number(123); alert(y === 123); // displays false alert(x == y); // displays false
I've seen several approaches to working around the bug, and I ran some timing tests to see what works for speed (http://jsfiddle.net/5dwwy/) Approaches: Direct assignment In this approach, the razor syntax is directly assigned to the variable. This is what throws the error. As a baseline, the JavaScript speed test simply does a straight assignment of a number to a variable. Pass through `Number` constructor In this approach, we wrap the razor syntax in a call to the `Number` constructor, as in `Number(#ViewBag.Value)`. ParseInt In this approach, the razor syntax is put inside quotes and passed to the `parseInt` function. Value-returning function In this approach, a function is created that simply takes the razor syntax as a parameter and returns it. Type-checking function In this approach, the function performs some basic type checking (looking for null, basically) and returns the value if it isn't null. Procedure: Using each approach mentioned above, a for-loop repeats each function call 10M times, getting the total time for the entire loop. Then, that for-loop is repeated 30 times to obtain an average time per 10M actions. These times were then compared to each other to determine which actions were faster than others. Note that since it is JavaScript running, the actual numbers other people receive will differ, but the importance is not in the actual number, but how the numbers compare to the other numbers. Results: Using the Direct assignment approach, the average time to process 10M assignments was 98.033ms. Using the Number constructor yielded 1554.93ms per 10M. Similarly, the parseInt method took 1404.27ms. The two function calls took 97.5ms for the simple function and 101.4ms for the more complex function. Conclusions: The cleanest code to understand is the Direct assignment. However, because of the bug in Visual Studio, this reports an error and could cause issues with Intellisense and give a vague sense of being wrong. The fastest code was the simple function call, but only by a slim margin. Since I didn't do further analysis, I do not know if this difference has a statistical significance. The type-checking function was also very fast, only slightly slower than a direct assignment, and includes the possibility that the variable may be null. It's not really practical, though, because even the basic function will return undefined if the parameter is undefined (null in razor syntax). Parsing the razor value as an int and running it through the constructor were extremely slow, on the order of 15x slower than a direct assignment. Most likely the Number constructor is actually internally calling parseInt, which would explain why it takes longer than a simple parseInt. However, they do have the advantage of being more meaningful, without requiring an externally-defined (ie somewhere else in the file or application) function to execute, with the Number constructor actually minimizing the visible casting of an integer to a string. Bottom line, these numbers were generated running through 10M iterations. On a single item, the speed is incalculably small. For most, simply running it through the Number constructor might be the most readable code, despite being the slowest.
#{ int proID = 123; int nonProID = 456; } <script> var nonID = '#nonProID'; var proID = '#proID'; window.nonID = '#nonProID'; window.proID = '#proID'; </script>
One of the easy way is: <input type="hidden" id="SaleDateValue" value="#ViewBag.SaleDate" /> <input type="hidden" id="VoidItem" value="#Model.SecurityControl["VoidItem"].ToString()" /> And then get the value in javascript: var SaleDate = document.getElementById('SaleDateValue').value; var Item = document.getElementById('VoidItem').value;
I found a very clean solution that allows separate logic and GUI: in your razor .cshtml page try this: <body id="myId" data-my-variable="myValue"> ...your page code here </body> in your .js file or .ts (if you use typeScript) to read stored value from your view put some like this (jquery library is required): $("#myId").data("my-variable")
Not so much an answer as a cautionary tale: this was bugging me as well - and I thought I had a solution by pre-pending a zero and using the #(...) syntax. i.e your code would have been: var nonID = 0#(nonProID); var proID = 0#(proID); Getting output like: var nonId = 0123; What I didn't realise was that this is how JavaScript (version 3) represents octal/base-8 numbers and is actually altering the value. Additionally, if you are using the "use strict"; command then it will break your code entirely as octal numbers have been removed. I'm still looking for a proper solution to this.
It works if you do something like this: var proID = #proID + 0; Which produces code that is something like: var proID = 4 + 0; A bit odd for sure, but no more fake syntax errors at least. Sadly the errors are still reported in VS2013, so this hasn't been properly addressed (yet).
I've been looking into this approach: function getServerObject(serverObject) { if (typeof serverObject === "undefined") { return null; } return serverObject; } var itCameFromDotNet = getServerObject(#dotNetObject); To me this seems to make it safer on the JS side... worst case you end up with a null variable.
This should cover all major types: public class ViewBagUtils { public static string ToJavascriptValue(dynamic val) { if (val == null) return "null"; if (val is string) return val; if (val is bool) return val.ToString().ToLower(); if (val is DateTime) return val.ToString(); if (double.TryParse(val.ToString(), out double dval)) return dval.ToString(); throw new ArgumentException("Could not convert value."); } } And in your .cshtml file inside the <script> tag: #using Namespace_Of_ViewBagUtils const someValue = #ViewBagUtils.ToJavascriptValue(ViewBag.SomeValue); Note that for string values, you'll have to use the #ViewBagUtils expression inside single (or double) quotes, like so: const someValue = "#ViewBagUtils.ToJavascriptValue(ViewBag.SomeValue)";
I use a very simple function to solve syntax errors in body of JavaScript codes that mixed with Razor codes ;) function n(num){return num;} var nonID = n(#nonProID); var proID= n(#proID);
This sets a JavaScript var for me directly from a web.config defined appSetting.. var pv = '#System.Web.Configuration.WebConfigurationManager.AppSettings["pv"]';
With var jsVar = JSON.parse(#Html.Raw(Json.Serialize(razorObject))); you can parse any razor object into a JavaScript object. It's long but universal