title: How do I pass an object to Adobe ExtendScript from Javascript (Adobe CEP)?
body: <p>I'm working with <a href="https://github.com/Adobe-CEP/Getting-Started-guides" rel="nofollow noreferrer">Adobe CEP</a> (it lets developers create windowed extensions for Adobe CC products).  The bulk of my code is modern JavaScript (the platform uses Chromium 57, Node.js 7.7.4).  <em>However</em>, in order to access the DOM, I need to write some functions in Adobe <a href="https://en.wikipedia.org/wiki/ExtendScript" rel="nofollow noreferrer">ExtendScript</a> and execute them from normal JS.  The only way is to execute a script using their provided <code>csInterface.evalScript(script, callback)</code>.  <code>script</code> has to be a string, which in my case is a function call converted to a string. <strong>I want to be able to pass an object to and from ExtendScript via <code>evalScript</code></strong>, but <code>evalScript</code> only takes and returns a string.</p>
  
  <p>Currently, I am passing each object property as its own argument.  This is unwieldy, but it works.</p>
  
  <p>My first though was <code>JSON.stringify()</code>, but unfortunately ExtendScript is a dialect of ECMAScript 3, which means <strong>no <code>JSON.parse()</code> support</strong>.</p>
  
  <p>I can't just concat the object argument into the script function call, because then the string evaluates to <code>foo([object Object])</code>.</p>
  
  <p>I've seen there are functions like <code>eval()</code>/<code>uneval()</code> or <code>Object.toSource()</code>, but those are not supported by Chromium.</p>
  
  <p>Here's an example, similar to my current method:</p>
  
  <p><strong>functions.js</strong> (ES3/ExtendScript)</p>
  
  <pre class="lang-js prettyprint-override"><code>function drawCircle(x, y, name) {
      // pick a layer
      var layer = app.activeDocument.layers[0];
  
      var diameter = 10;
      var top = y + diameter / 2;
      var left = x - diameter / 2;
  
      // draw ellipse in layer
      var circle = layer.pathItems.ellipse(top, left, diameter, diameter);
  
      circle.name = name;
      circle.filled = true;
  
      return true;
  }
  </code></pre>
  
  <p><strong>app.js</strong> (ES6)</p>
  
  <pre class="lang-js prettyprint-override"><code>const csInterface = new CSInterface();    // provided by Adobe
  async function circle() {
      const dataObject = {x: 10, y: 10, name: 'Hello world!'};
  
      // the script to call
      // evaluates to drawCircle(10,10,'Hello world!');
      const script = "drawCircle(" + dataObject.x + "," + dataObject.y + ",'" + dataObject.name + "');";
  
      return new Promise((resolve, reject) =&gt; {
          csInterface.evalScript(script, (result) =&gt; {
              resolve(result);
          });
      });
  }
  </code></pre>
  
  <p>As expected, <code>circle()</code> calls <code>drawCircle()</code> just fine, and an ellipse appears in the document I'm working on.  However, executing a script/calling a function by concatenation feels very <em>wrong</em>. So in summary,</p>
  
  <ol>
  <li>I would like some (neater) way of turning <code>dataObject</code> into a string and passing it to <code>drawCircle()</code> via <code>evalScript()</code>,</li>
  <li>and I would like to return <code>dataObject</code> from <code>drawCircle()</code> and receive it back as an object.  Currently, returning an object only results in <code>"[object Object]"</code> as a return value.</li>
  </ol>