0
\$\begingroup\$

I am trying to accept JavaScript array literals in an HTML text input.

The problem is that HTML text inputs are captured as strings, such that an input of ['name', 'who', 1] becomes "['name', 'who', 1]".

My intention is for the following samples to yield the corresponding outputs.

"['river',"spring"]"        //  ["river","spring"]

"[{key:'value'},20,'who']"  //  [{"key":"value"},20,"who"]

The way I worked around the problem is by using eval in the code snippet below:

const form = document.querySelector('.form'); 
    const inputField = document.querySelector('.input');
    const btnParse= document.querySelector('.btn'); 
    const out = document.querySelector('.out');  
   
    form.addEventListener('submit', (e)=> {   
      e.preventDefault(); 

      try {    
        parsed = eval(inputField.value);

        if(Array.isArray(parsed)) {       
          out.textContent = JSON.stringify(parsed);
        } else throw new Error('input is  not a valid array' );
      } catch(err) {
        out.textContent = `Invalid input: ${err.message}`;
      } 
    }); 
 <form class="form">   
      <fieldset> 
        <legend>Enter array to parse</legend>      
        <input class="input" type="text">      
        <input class="btn" type="submit" value="parse">  
      </fieldset>
    </form>
    <div>   
      <p class="out"> 
      </p> 
    </div>        


My solution, however, allows for the execution of any Javascript code inputted into the text field, which is a huge vulnerability.


What alternative way is there to converting JavaScript array literal HTML text inputs into JS array objects without using eval?

\$\endgroup\$
  • \$\begingroup\$ "My solution, however, allows for the execution of any Javascript code inputted into the text field, which is a huge vulnerability." Yes, which is why we usually prefer to think eval doesn't exist. Don't be tempted to use it. For most applications, there are much better alternatives available. Anyway, I think you're asking the wrong question and that JSON is your answer. \$\endgroup\$ – Mast Nov 3 '18 at 18:57
1
\$\begingroup\$

I agree with @Mast that you are asking the wrong question. IMHO your question should be: "Is it a good idea to get user input in form of a JavaScript array?" and the short answer woudl be "no". The long answer would be:

Why did you choose this form of input? Aren't there better input methods? Where is the string coming from?

However, if you don't have any other choice, then the proper solution would be to use a more lenient "JSON" parser. One possiblity could be to use a YAML parser. YAML is a superset of JSON that allows (among other things) JSON-like markup.

\$\endgroup\$
0
\$\begingroup\$

The answer

What you're actually trying to do is only converting objects from Javascript notation to actual javascript objects. Now what if there was a well-specified data interchange format that was named "Javascript object notation"? Oh there is?

parsed = JSON.parse(inputField.value);

You're even using JSON.stringify already...


Other general advice

  • Don't use classes to identify unique elements. That's exactly not what classes are intended for. Instead use IDs.
  • Make use of the strict evaluation mode for javascript... "use strict";
  • You could avoid the e.preventDefault if you didn't use a submit button, but a normal button instead or listened to 'onblur'. I personally would prefer the last method the most, possibly combined with an 'onchange' listener with a timeout.
  • Always put braces around your stuffs, in this case around the throw new Error. This helps avoid bugs when changing the code later.
\$\endgroup\$
  • \$\begingroup\$ JSON.parse(inputField.value) throws an error if the input string is something like "[2, {name: 'some_name'}]" because the object key is unquoted and "[2, {'name': 'some_name'}]" because the key is single quoted \$\endgroup\$ – Oguntoye Nov 3 '18 at 19:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.