lua.vm.js object/array to table - javascript

I am using lua.vm.js to give users of my node application the ability to add features in realtime. For that I have some JS Classes that I want to give them in lua.
Now I have the problem, that some of my functions should return arrays or objects.
On Lua side it is translated to userdata. In the most cases this will work but not for a array that should be used in a ipairs/pairs function.
I now that "in ipairs" or "in pairs" is existing in lua.vm.js
The question is how can I write a function that returns an array in a way that lua.vm.js is using it as a table.
Some example Code:
on JS side:
let luaVM = require("lua.vm.js");
let l = new luaVM.Lua.State();
l._G.set("someExampleFunction", {
example: function(){
return [1,2,3,4,5];
}
});
on Lua Side:
local shouldBeTable = someExampleFunction.example()
-- this will not work because shouldBeTable is not a table
for key, value in pairs(shouldBeTable) do
print(value)
end
Is there a way how to do that or to write a helper Function like arrayToTable ?

Related

Loop through nested dataLayer array to return pipe delimited strings

We have a nested dataLayer variable on our booking platform. Users can make one or multiple variables are we want to pull out a string containing each of the product types contained within the array. I am hitting a error when debugging this however.
The location of the variable I would like to collect is:
dataLayer.booking.products[i].travelType
try{
var productList = {};
for(i=0;i<dataLayer.booking.products.length;i++){
productList[dataLayer.booking.products[i].travelType];
}
return productList.join('|');
}
catch(err){}
I am naive with JS so I apologies for a basic question.
M
Your code shows that you're setting a new property of the object productList, but you're not defining a value, e.g. {foo: } instead of {foo: "bar"}. It looks like what you want is an array that you can add strings to. For example:
var productList = dataLayer.booking.products.map(function(product) {
return product.travelType;
});
return productList.join('|');
Note that this is using the Array's map method as opposed to your for loop. You could also define productList as an array in a previous line, and then use the forEach method on the products Array to loop through every item, but I think this is cleaner and still legible. You can reduce the code further with ES6 syntax, but for your question it's probably better to show code that is more clearly defined.

Node.JS behaves strange

I have a variable called uids
var uids = [];
Then I write some value to it property
uids[16778923] = "3fd6335d-b0e4-4d77-b304-d30c651ed509"
But before it
if (!uids[user.id]) {
uids[user.id] = generateKey(user);
}
This thing behaves ok. If I try to get the value of it property
uids[currentUser.id]
It will give me a value of this property. If I try to call some methods like
Object.keys(uids);
It will give me, what I expected. And here the mystery comes...
uids;
RAM rest in piece. See the node eating ram
I am very confused now. What's wrong?
This is because you are creating a huge array and node will reserve memory for it - who knows what comes. I'd say that's a scenario where you would use a Map (or a plain object, but Map feels better here.
var uids = new Map();
var key = 456464564564654;
if (! uids.has(key)) {
uids.set(key, generateKey(user))
}
You are creating an empty array (length is zero), then you assign some value to an arbitrary index. This will make the array grow as big as the index and assign the value to that index. Look at this example using node.js REPL:
> var a = []
undefined
> a[5] = "something"
'something'
> a
[ , , , , , 'something' ]
> a.length
6
Instead of creating an array, you could create a Map() or an common javascript object (singleton). Javascript objects behave like Maps but only Strings can be used as keys. If you assign a Number to be key, javascript will convert it to String automatically.
Personally, I would go with objects because they perform better. Instantiating an object takes longer than instantiating a Map (and it doesn't seem like you need to create several groups of "uids"), but once done, adding new keys and retrieving values from any key in faster when using common objects. At least that's how things go in my node.js v6.7.0 on ubuntu 14.04 but you could try for yourself. And it would also make the least alteration to your code.
var uids = {} // common/ordinary empty javascript object instead of array.
if (!uids[user.id]) { // getting value from one key works the same.
uids[user.id] = generateKey(user) // assignment works the same.
}
////
uids[16778923] = "3fd6335d-b0e4-4d77-b304-d30c651ed509" // key will be "16778923".
uids[16778923] // getting value for key "16778923" can be done using 16778923 instead of "16778923".
////
uids[currentUser.id] // still returning values like this.
Object.keys(uids) // still returning an array of keys like this. but they are all Strings.

Creating a Dart List from a Javascript array

I am trying to learn client-side Dart, coming from a server-side Java EE world, and I am having trouble converting an array from an existing JavaScript library into a Dart List.
I am trying to learn by building on the Javascript Interop example that uses Google Maps. In Google's Maps API's documentation, the DirectionsLeg object's step property returns.
array of DirectionsSteps, each of which contains information about the individual steps in this leg
How can I convert this var into a Dart List? I have tried the following:
final List<maps.DirectionsStep> steps = List.from(directionsLeg.steps);
But Dart Editor tells me cannot resolve method 'from' in class 'List'. My imports are:
import 'dart:html';
import 'dart:core';
import 'package:js/js.dart' as js;
What am I doing wrong? Is it even possible or must I just accept using a var?
There's no built-in way in js-interop for now to use Dart List when a js Array is returned.
directionsLeg.steps returns a js.Proxy which handles like js Array. You can iterate on it like this :
final steps = directionsLeg.steps;
for (var i = 0; i < steps.length ; i++) {
final step = steps[i];
// do the job with step
}
If you really want to use a Dart List you can convert the js.Proxy of js Array to a Dart List with something like :
List<js.Proxy> convertToList(js.Proxy arrayProxy){
final result = new List<js.Proxy>();
for (var i = 0; i < arrayProxy.length ; i++) {
result.add(arrayProxy[i]);
}
return result;
}
About your code :
You can't define List<maps.DirectionsStep> : maps.DirectionsStep is not a type, it's a js.Proxy on js google.maps.DirectionsStep (moreover it don't really exist - only a container js object {}).
List.from(...) : here, you try to call a static method named from on Dart List object. That why you get your error. List.from is actually a factory named constructor and has to be used with the new keyword ( new List.from(otherIterable) ).

Pass IEnumerable List to javascript

I was wondering if I could pass a IEnumerable Collection into a Javascript method on the page load. So something like this...
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MyAppMVC.Models.ViewModels.News.NewsIndexViewData>" %>
<div id="container">
<%= String.Format("<script type='text/javascript'>testMethod({0})</script>", Model.NewsList) %>
</div>
I realize JS is client side, just didn't know if there was any way possible to do that?
Thanks!
No, you cannot. For several reasons.
1) There is no IEnumerable in JavaScript, as you use it in .NET. There is something similar, but it is implemented completely differently. In .NET, IEnumerable just means the class provides a method, GetEnumerator(), which returns an IEnumerator (which itself only contains Current, MoveNExt, and Reset methods). In JavaScript, when you do a for iteration on an item, you are iterating over the names of its properties.
var myObj = { 'a' = 1, 'b' = 2 };
for (var name in myObj) { alert(name); } // will alert 'a', and 'b'
Even when working with JavaScript arrays, the above loop returns the index of the array element, not the actual member at that index.
2) By doing a String.Format() on your list, you wouldn't have been passing the list as an object to your JavaScript but just the ToString() result of your list. Which probably just returns "System.Collections.Generic.List`1[System.String]"
3) Unless your developing environment explicitly allows it, you can assume that passing arguments from one language into another is not going to work. Much like you can't write JavaScript inside your .NET code, you can't write .NET code in your JavaScript. These languages have different feature sets, different syntax, and are executed with completely different mechanisms - .NET is compiled, and JavaScript (generally, speaking) is interpreted (Compiled vs. Interpreted languages).
What you have to do is transform your data into a format that can be used by JavaScript. Most likely this means converting it into something called JSON. You didn't provide a lot of details as to what exactly Model.NewList is, or what your testMethod() expects as an argument. But for the sake of an example lets assume NewList is a list of strings. In that case, your JSON would look something like this:
{ 'NewList' : ['string1', 'string2', 'string3'] }
The easiest way to convert your .NET data into JSON is to use built-in libraries, such as JavaScriptSerializer:
System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
string json = serializer.Serialize(Mdoel.NewList);
You can register the javascript in the code behind in the Page_Load with the following code (Note I am assuming that Model.NewsList is a string enumeration or array):
StringBuilder sb = new StringBuilder();
bool isFirst = true;
//build a comma seperated list.
foreach (string s in Model.NewsList)
{
if (isFirst)
isFirst = false;
else
sb.Append(", ");
sb.Append("'").Append(s.Replace("'", "''")).Append("'");
}
//create the javascript array
string javascript = String.Format(#"var news = [{0}];", sb);
//put the array in the generated page.
Page.ClientScript.RegisterClientScriptBlock(GetType(), "newsList", javascript);
This will put the javascript on the page accessible from other javascript functions.

jQuery/Javascript pulling info from an object

I am trying to use the following code to create a list of client names from some json returned from an Ajax call.
The data is as follows:
{"status":1,"data":{"clients":[{"ClientID":"1","AccountID":"1","ClientName":"Access Loan Mitigation","Active":"1"},{"ClientID":"2","AccountID":"1","ClientName":"Big Time Business","Active":"1"},{"ClientID":"3","AccountID":"1","ClientName":"Bill Releford","Active":"1"},{"ClientID":"4","AccountID":"1","ClientName":"Bonnie Silverman","Active":"1"},{"ClientID":"5","AccountID":"1","ClientName":"Dear Holdings","Active":"1"},{"ClientID":"6","AccountID":"1","ClientName":"Calm Dental","Active":"1"},{"ClientID":"7","AccountID":"1","ClientName":"Eva Field","Active":"1"},{"ClientID":"8","AccountID":"1","ClientName":"First Independent Pictures","Active":"1"},{"ClientID":"9","AccountID":"1","ClientName":"Gallery 825","Active":"1"},{"ClientID":"10","AccountID":"1","ClientName":"Greenway Arts Alliance","Active":"1"},{"ClientID":"11","AccountID":"1","ClientName":"International Strategy Group","Active":"1"},{"ClientID":"12","AccountID":"1","ClientName":"Ramtin","Active":"1"},{"ClientID":"13","AccountID":"1","ClientName":"Spabro","Active":"1"},{"ClientID":"14","AccountID":"1","ClientName":"LMGA","Active":"1"},{"ClientID":"15","AccountID":"1","ClientName":"Main Street Business Association","Active":"1"},{"ClientID":"16","AccountID":"1","ClientName":"Rabbit Animation","Active":"1"},{"ClientID":"17","AccountID":"1","ClientName":"Rooms & Gardens","Active":"1"},{"ClientID":"18","AccountID":"1","ClientName":"Summertime","Active":"1"},{"ClientID":"19","AccountID":"1","ClientName":"Sue Shellock","Active":"1"},{"ClientID":"20","AccountID":"1","ClientName":"Susan Gates","Active":"1"},{"ClientID":"21","AccountID":"1","ClientName":"The Park Entertainment","Active":"1"},{"ClientID":"22","AccountID":"1","ClientName":"Unified Dispatch","Active":"1"},{"ClientID":"23","AccountID":"1","ClientName":"Westside Media Group","Active":"1"},{"ClientID":"24","AccountID":"1","ClientName":"YHD","Active":"1"},{"ClientID":"25","AccountID":"1","ClientName":"Discoverfire, Inc.","Active":"1"}]}}
and the code is like so:
for (var Client in o.data.clients) {
$('#list_container').append("<div>"+Client.ClientName+"</div>");
}
Not quite working, and I've tried a few different ways of accessing the ClientName property. Javascript isn't my strongest language, and getting data out of objects just kills me - used to PHP object and arrays.
I'm sure this is simple - can somebody show the right syntax?
Thanks!
Clients is an array so it's better to use jQuery's each on it:
$.each( o.data,clients, function(idx, client) {
// use client.ClientName here
});
That's not quite how the for loop works. An easier, more accurate, and more reliable way to tackle this is to use the traditional for syntax like so:
for (var i = 0; i < o.data.clients.length; i++) {
var client = o.data.clients[i];
$('#list_container').append("<div>"+client.ClientName+"</div>");
}
The for syntax you were using will work, but it's still iterating over indices (not values), and even then it's not limited to just the integer indices in the array — it could also include other properties defined on the array prototype, or even on the particular array object. Iterating using the boring i = 0 syntax is a far better option for traditional arrays like this.

Categories

Resources