funroll
funroll

Reputation: 37093

Compile coffeescript in eval

I have a node.js website where I pass javascript in the query string.

Then I eval the javascript in the request handler. (Not secure, I know.)

// web.js
var express = require("express");
var logfmt = require("logfmt");
var app = express();

app.use(logfmt.requestLogger());

app.get('/', function(req, res) {
  var code = req.query.code;
  var result = eval("(function(req, res) {" + code + "})(req, res);");
  res.send('Result: ' + result);
});

var port = process.env.PORT || 5000;
app.listen(port, function() {
  console.log("Listening on " + port);
});

I want to be able to pass coffeescript into the query string and have it be evaluated, but I don't want to change the node.js code at all. So I would need to wrap something around the coffeescript to turn it into javascript at eval time, doing the compilation and execution of the resulting javascript fully within the eval.

Is this possible?

Clarification: I don't want the source of the coffeescript compiler to exist on disk on my web server at all. (e.g. extras/coffee-script.js) I want to pass the source of the coffeescript compiler into the eval block, so the compilation itself is done without any dependencies. Then I want to execute the resulting javascript.

The coffeescript compiler probably won't fit into a query param, so conceptually it could be passed via POST body or otherwise.

Upvotes: 1

Views: 1872

Answers (1)

mu is too short
mu is too short

Reputation: 434685

From the fine manual:

"text/coffeescript" Script Tags

While it's not recommended for serious use, CoffeeScripts may be included directly within the browser using <script type="text/coffeescript"> tags. The source includes a compressed and minified version of the compiler [...] as extras/coffee-script.js. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.

[...] Including the script also gives you access to CoffeeScript.compile() so you can pop open Firebug and try compiling some strings.

That means that you can say things like:

js = CoffeeScript.compile('f = (x) -> x * x')

to get this string of JavaScript in js:

(function() {
  var f;
  f = function(x) {
    return x * x;
  };
}).call(this);

and then you can feed js to eval like any other JavaScript. If you don't want to usual scope wrapper, then include the bare: true option:

js = CoffeeScript.compile('f = (x) -> x * x', bare: true)

to get this unwrapped JavaScript:

  var f;
  f = function(x) {
    return x * x;
  };

Of course, the CoffeeScript.compile interface isn't that well documented so you might have to read the source and experiment to see what sorts of options you have and what sort of error handling you're getting yourself into.

This sort of thing may not be the best idea you've ever had but you seem to know that already.

Upvotes: 4

Related Questions