0

My need is to parse a array which contains string to eval(). I know about eval() security threats and assume in this question that everything is fine.

The array is made server-side by a PHP script, which looks into a bunch of specified folders, load every file using file_gets_contents() and inject each content into a row of the array. Then it send the final array to the client.

In my design, which has pros and cons, some scripts in the array are used to initialize some objects, others used objects for logic. For this to work smoothly it must, as you can expect, be eval()ed in the right order. Otherwise javascript throws error.

My problem is the following : the scripts in array come unordered. For specific reasons, out of the scope here, I don't want neither ordering the array server side, nor passing any indication to the client (by example in array[key]) to tell it how to reorganize the unordered scripts it receives.

In contrast, I'm trying to set up a mechanism able to parse the array, send in a queue all the scripts that come too early, eval() others scripts and finally eval() the rest of the queue.

So far, my idea has been to try ... catch each eval() during a Array.forEach() statement, splice() the array to remove each script that has been correctly eval()ed, allow the script with errors to stay in the array, then recall Array.forEach() until array.length === 0;

As a case study, I'm looking for the ability to parse each line of the array example in a loop, decide to splice() the line (because delete doesn't really delete...) or to let it in array, and re-loop to check if a line stil exists.

To illustrate my point, I provide these example which is NOT functional. Still working to debug...

this.a = [ //the array that reproduce the situation (seems to work)
    'o = {}', // I declare o as a global namespace
    'o.a.b.c = "a string"', //I declare a value in o.a.b.c, too early
    'o.a.b = {}', //I declare o.a.b, but o.a doesn't exist
    'o.a = {}', //I declare o.a, too late
];

var build = function(value,key,array){

    try{
        eval(value);
        this.a = array.slice(key);
    }catch(error){
        console.log(error.message);
        this.a.push(value);
    }finally{
        if(this.a.length === 1) this.a = [];//Take care of infinite loop risk, as the "while" below does not carry the variable to zero...
    }

}.bind(this);

while(this.a.length > 0){
    this.a.forEach(build);
    console.log(this.a.length);
};

console.log(this.a);

Does anyone with strong logic can help?

Community
  • 1
  • 1
Guillaume Fe
  • 369
  • 4
  • 16

1 Answers1

1

There are a few problems with your script:

  • this.a = array.slice(key); doesn't seem to make any sense?
  • this.a = array.push(value); sets a to the length of the array
  • if(this.a.length === 1) this.a = []; - not sure against what infinite loop you're trying to protect here?
  • this.a.forEach(build); sounds like a bad idea if you try to modify the array while you're looping over it.

My approach would be much simpler - just use the array as a queue:

this.a = [ //the array that reproduce the situation (seems to work)
    'var o = {}', // I declare o as a global namespace
    'o.a.b.c = "a string"', //I declare a value in o.a.b.c, too early
    'o.a.b = {}', //I declare o.a.b, but o.a doesn't exist
    'o.a = {}', //I declare o.a, too late
];

while (this.a.length) {
    var value = this.a.shift();
    try {
        (null, eval)(value);
    } catch(error) {
        if (error instanceof SyntaxError) break;
        this.a.push(value);
    }
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375