an efficient javascript split function to save bytes - javascript

I'm trying to minify my javascript code as much as possible.
What I have 14 times is code like this:
o.split('x');
where o is the object name and x is the delimiter.
To cut code size down, I created this function:
function X(o,d){return o.split(d)}
This allows me to call the same split function like this:
X(o,'x');
Each function call saves me about 3 bytes per call. After the changes, I saved about 20 bytes.
Now what I want to do is convert the second parameter into a number that changes into the delimiter inside the function. I'm using up to 5 different delimiters. I'm not sure if this can be done since I want to support internet explorer 7.
Here's my thoughts on how I would modify the function but I'm not sure which is compatible with every browser new and old including Internet explorer 7.
Idea 1:
function X(o,d){var x=[';','.','=',' ','+'];return o.split(x[d])}
Idea 2:
function X(o,d){var x=';.= +';return o.split(x[d])}
Idea 3 (probably doesn't execute but it would allow me to save tons of bytes):
function X(o,d){return o.split(';.= +'[d])}
Idea 4 (same as idea 3):
function X(o,d){return o.split(';.= +'.substr(d,1))}
I'm just trying to condense the function and make it work for everyone.
The basic idea I'm trying to achieve is that I want a catalog of delimiters in my function that I can choose using a number as the second parameter of the function. The first parameter of the same function is the string that is to be split.
How can I properly write my function with the fewest lines of code possible? or do I have to resort to using a single-quoted character as my second parameter?

Related

Node - safest way to execute code from a string during runtime

My Node app gets an HTML page via axios, parses it via htmlparser2 then sends the valuable information to a frontend JS app as JSON.
The HTML page has some JavaScript in it that creates an array, and I need to work with that array in my code. htmlparser2 gets the content of the script as a string. I have two options to handle it as far as I know:
Write a parser that goes through the string and extracts the required info (doable, but complicated)
Run string as some JavaScript code and handle the values from that.
Assume I want to go with option 2. According to this StackOverflow question, using Node's VM module is possible, but the official documentation says "The node:vm module is not a security mechanism. Do not use it to run untrusted code."
I consider the code in my use case untrusted. What would be a safe solution for this?
EDIT: A snippet from the string:
hatizsakCucc = new Array();
hazbanCucc = new Array();
function adatokMessage(targyIndexStr,tomb) {
var targyIndex = parseInt(targyIndexStr);
if (tomb.length<1) alert("Nincs semmi!");
else alert(tomb[targyIndex]);
}
hatizsakCucc[0]="Név: ezüst\nSúly: 0.0001 kg.\nMennyiség: 453\nÖsszsúly: 0.0453 kg.\n";
hatizsakCucc[1]="Név: kaja\nSúly: 0.4 kg.\nÁr: 2 ezüst\nMennyiség: 68\nÖsszár: 136 ezüst\nÖsszsúly: 27.2 kg.\n";
hatizsakCucc[2]="Típus: fegyver\nNév: bot\nSúly: 2 kg.\nÁr: 6 ezüst\nMin. szint: 1\nMaximum sebzés: 6\nSebzés szórás: 5\nFajta: ütő/zúzó\n";
hatizsakCucc[3]="Típus: fegyver\nNév: parittya\nSúly: 0.3 kg.\nÁr: 14 ezüst\nMin. szint: 1\nMaximum sebzés: 7\nSebzés szórás: 4\nFajta: távolsági\n";
hatizsakCucc[4]="Név: csodatarisznya\nSúly: 4 kg.\nÁr: 1000 ezüst\nExtra: templomi árú\n";
hatizsakCucc[5]="Név: imamalom\nSúly: 5 kg.\nÁr: 150 ezüst\nExtra: templomi árú\n";
The whole string is about 100 lines of this, so it's not too much data.
What I need is the contents of the hatizsakCucc array. Actually, getting an array of that it not too difficult with a regex, I'm realizing now.
hatizsakSzkript.match(/hatizsakCucc(.*)\\n/g);
This gives me an array of the hatizsakCucc elements, so I guess my problem is solved.
That said, I'm still curious about the possibility of running "untrusted" code safely.
Further context:
I plan parse each array element so it will be an object, the object elements will be the substring separated by the \n-s
So the expected result for the first array element will be:
hatizsakCucc[0]{
nev: "ezüst",
suly: 0.0001,
mennyiseg: ...
}
I'll write a function that splits the string to substrings at the \n then parse the data with a match().

How to create push a large number of string elements into array in javascript without error

I'm using the following function to take a large array of strings (user names) and check them for single quotes, then push them into my new array and return that.
Recently, the number of users in this list increased dramatically (7418 currently) and now this function is getting an error:
Caused by: java.lang.ClassFormatError: Invalid method Code length
105684 in class file org/mozilla/javascript/gen/c135516
The version of javascript is embedded in the application so upgrading that is not an option at this time.
Is there a better way to do this? or a different way to try to avoid this error?
function listExcludedUsers(rInactive) {
var result = new Array('user1', 'user2', 'user3', 'user4');
for (var i = 0; i < rInactive.length; i++) {
//replace single quote with two single quotes for DQL
if (rInactive[i].indexOf("'") > 0) {
rInactive[i] = rInactive[i].replace(/'/g, "''");
}
result.push(rInactive[i]);
}
return result;
}
Thhe JVM restricts the length of methods to 65536 bytes, so it seems as if you have found a bug in Mozilla. Please file it (with example if possible) at https://bugzilla.mozilla.org/.
Meanwhile: try to cut your method in multiple smaller parts, e.g.: chop the input and push it into several smaller arrays and concatenate those at the end. You should do it with several different functions.
This code looks like you are running a jvm that does not take very long methods name and those methods are because of the JavaScript input you are giving, it would be nice to try to reproduce the case, I would
Try to change the input of your JavaScript code that makes those methods in jvm too longs, may be in several sets of inputs.

Execute just part of a method in JavaScript

I have a method that could potentially do both parts of the greater task at hand. Basically I have two buttons one button uses the entire method and returns a result at the bottom of the method. Now, my question is about the second button. The second button needs to do everything in that same method but only from line x of said method. Instead of writing a second method that repeats the same exact code from line x down of said method is there a way to jump over bits of code and only execute portions of a method in javascript? Or perhaps I am thinking about this all wrong?
Do two separate methods like this:
function a(){
//do first half of function
b();
}
function b(){
//do second half of function
}
2 ways,
split out the chunk that gets used twice into a separate method, and call from either within the first method, or from the other context directly.
add another argument to the method that expects a boolean value. The function then skips over the unneeded bits based on that value passed in. It can then be called differently from different contexts.
you can call String(yourfunc) to get code, then dynamically create second function by cutting only further lines, you can get array of lines by splitting by ('\n') then join array elements from place you want to begin and evaluate new function, code:
function split(bigfunc,line){
for(var small = String(bigfunc).split('\n'), i=line,n='',l=small.length;++i<l;)
n+=small[i];
return eval('(function(args){'+n+')'};
}
where args in last line you need to replace with args from original function, eventually you can assume args will be the same, then replace line with:
return eval('('+small[0]+n+')') if you're putting { after arguments of function like me or put +'{'+ between small[0] and n if you're putting { in new line.
it'll return new function with only code after line.
Dude, look how many lines of code will you save...
To be serious - it's overkill. I'm using dynamic code manipulation like this to dynamically create webworkers only with parts of code from primary thread and crafting blobs and urls to them in fly to reduce loading time. But it's way more serious purpose than just making code shorter, but...
at least it'll be soooo pro xD

Passing hexadecimal color values from Xcode to Javascript

I am trying to pass a Hexadecimal color value from objectiveC to Javascript. I am displaying a graph and I am trying to pass the color to javascript so that I dont need to hardcode it in my html page.
Here is what I do -
In my .m File,
NSArray *colorArray = [NSArray arrayWithObjects:#"FFFFFF",#"000000", nil];
colorString = [[colorArray valueForKey:#"description"] componentsJoinedByString:#","];
In my webViewDidFinishLoad function,
[graphView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"methodName1([%#])", colorString]];
However, the javascript is not able to accept the values.
In my Javascript function, what should I do to accept the values - FFFFFF and 000000 so that I can use them.
I am trying to use the colors like this -
line1.Set('chart.colors', ['FF0000', '000000']);
where instead of giving the hexadecimal values there, I would like to get it from objC.
Update -
Here is the javascript function I use -
function methodName1(val)
{
alert("hi");
}
However, the function does not even get called.. I feel the issue is with the way I pass the values...
It would be great if someone could help me out with this.
You're calling
methodName1([FFFFFF,000000]); // will fail since FFFFFF is not defined
But you want
methodName1(['FFFFFF','000000']);
You probably need to add an "#" character before each color.

Calling toString on a javascript function returns source code

I just found out that when you call toString() on a javascript function, as in myFunction.toString(), the source code of that function is returned.
If you try it in the Firebug or Chrome console it will even go as far as formatting it nicely for you, even for minimized javascript files.
I don't know what is does for obfuscated files.
What's the use of such a toString implementation?
It has some use for debugging, since it lets you see the code of the function. You can check if a function has been overwritten, and if a variable points to the right function.
It has some uses for obfuscated javascript code. If you want to do hardcore obfuscation in javascript, you can transform your whole code into a bunch of special characters, and leave no numbers or letters. This technique relies heavily on being able to access most letters of the alphabet by forcing the toString call on everything with +""
example: (![]+"")[+[]] is f since (![]+"") evaluates to the string "false" and [+[]] evaluates to [0], thus you get "false"[0] which extracts the first letter f.
Some letters like v can only be accessed by calling toString on a native function like [].sort. The letter v is important for obfuscated code, since it lets you call eval, which lets you execute anything, even loops, without using any letters. Here is an example of this.
function.ToString - Returns a string representing the source code of the function. For Function objects, the built-in toString method decompiles the function back into the JavaScript source that defines the function.
Read this on mozilla.
You can use it as an implementation for multi-line strings in Javascript source.
As described in this blog post by #tjanczuk, one of the massive inconveniences in Javascript is multi-line strings. But you can leverage .toString() and the syntax for multi-line comments (/* ... */) to produce the same results.
By using the following function:
function uncomment(fn){
return fn.toString().split(/\/\*\n|\n\*\//g).slice(1,-1).join();
};
…you can then pass in multi-line comments in the following format:
var superString = uncomment(function(){/*
String line 1
String line 2
String line 3
*/});
In the original article, it was noted that Function.toString()'s behaviour is not standardised and therefore implementation-discrete — and the recommended usage was for Node.js (where the V8 interpreter can be relied on); however, a Fiddle I wrote seems to work on every browser I have available to me (Chrome 27, Firefox 21, Opera 12, Internet Explorer 8).
A nice use case is remoting. Just toString the function in the client, send it over the wire and execute it on the server.
My use case - I have a node program that processes data and produces interactive reports as html/js/css files. To generate a js function, my node code calls myfunc.toString() and writes it to a file.
You can use it to create a Web Worker from function defined in the main script:
onmessage = function(e) {
console.log('[Worker] Message received from main script:',e.data);
postMessage('Worker speaking.');
}
b = new Blob(["onmessage = " + onmessage.toString()], {type: 'text/javascript'})
w = new Worker(window.URL.createObjectURL(b));
w.onmessage = function(e) {
console.log('[Main] Message received from worker script:' + e.data);
};
w.postMessage('Main speaking.');

Categories

Resources