##JavaScript to PHP
This tool transforms JavaScript to PHP. Just for fun.
This is a proof-of-concept started at a hackathon recently to see if it could be done. There's some interesting aspects of the two languages that make this a really interesting challenge: lexical scope, prototypal inheritance, duality of +
operator in JS, PHP's implicit variable declaration, etc. A lot of this had to be implemented in runtime helpers with type checking, but it turns out it's totally doable.
There are dozens of "compile to JS" languages available (Coffee, TypeScript, Dart), but hardly any good choices in the PHP world**. PHP is ubiquitous in bulk hosting, it runs on Google App Engine, AppFog, Rackspace Cloud Sites and virtually every LAMP stack in the world. So if you need to host on PHP but don't like writing PHP, well tough luck. ...unless you could write in JS and deploy to PHP!
Maybe so. But if you wanted a compile-to-PHP language, JavaScript (or a subset thereof) is a pretty solid choice. There's plenty of tooling, libraries, community, etc. Plus web developers have to know JS anyway because it's in the browser. OK, I'm not suggesting you deploy this generated PHP to production, but if this project matures that might become feasable. I could imagine a JS dev creating a cool thing in JS and then compiling to PHP to put it up on CodeCanyon. The same application might then be run on Node using Fibers and the JVM via Nahsorn or DynJS. Another interesting use case is this: your web app has a need for some user-generated scripting (think plugins) but you can't just run untrusted PHP on your server. Well, what if you could expose a small API via JS instead. Then compile the user's JS into perfectly safe PHP that has no disk or network access.
Sure, you pay a performance penalty at runtime, but seriously, have you run mainstream PHP apps before? It's not like the performance bar is too high (I think a default WP install runs 27 SQL queries to render the homepage). Your app is likely not CPU bound anyway (and if it is, then you should be running Node + worker processes or some other awesome solution).
At this point I'm focusing on correctness, not performance, and this is very alpha stuff, but it works.
The core language is mostly implemented and has some tests (Object, Array, Math lib, String methods, etc) but there is no interface to the outside world besides console.log()
and process.exit()
. A basic HTTP module is in the works, but there's no file-system or database access and there's no formal way to call into PHP from JS.
Feel free to contribute if this interests you.
Install from GitHub:
git clone [email protected]:sstur/js2php.git
cd js2php
npm install
Install from npm:
npm install -g jstophp
When you install from npm using the -g
flag, you can run it from any directory by simply calling js2php
rather than calling node path/to/js2php
. The rest of the examples in this readme will call it this way.
Compile and run a simple example:
echo 'var x = "world"; console.log("hi " + x)' | js2php --quiet | php
or, a more verbose example:
echo "var a = 1; console.log(a + 1)" > example.js
js2php example.js > example.php
php example.php
We're using the awesome esprima JavaScript parser with rocambole to walk the AST and escope to figure out variable scope, hoist function declarations and so on. After AST manipulation tools/codegen.js
generates the PHP code by walking the tree.
Various constructs get wrapped in helper functions, for instance, property access, method calls and +
operator. The runtime helpers can be found in php/helpers
and there are a bunch of classes in php/classes
for Array, RegExp and such. All this PHP gets packaged into your output file, or you can save it to a standalone runtime and reference that from your output file like so:
js2php --runtime-only > runtime.php
js2php --runtime runtime.php example.js > example.php
You can also specify the output file using -o
or --out
and you can compile multiple input files into one output file like so:
js2php -o example.php file1.js file2.js
Have a play with the online demo. The generated code will look something like this:
<?php
$HelloWorld = new Func("HelloWorld", function($this_, $arguments, $greeting) {
set($this_, "greeting", $greeting);
});
set(get($HelloWorld, "prototype"), "go", new Func(function($this_, $arguments, $subject) use (&$console) {
call_method($console, "log", get($this_, "greeting"), $subject);
}));
call_method(_new($HelloWorld, "Hi"), "go", "world");
It's not particularly elegant, but it's human-readable and has all the basics we need to implement standards-compliant JS in PHP.
There's a handful of other "compile to PHP" languages I want to mention. Haxe is probably the most popular and is a solid statically-typed language. I also came across Pharen (a Lisp implementation), Mammouth (similar to CoffeeScript) and Pratphall (TypeScript syntax). There's also another JS to PHP project from a few years back which is written in PHP but has similar goals as this project. Yet another JS to PHP project I just recently learned about (with the same name as this one) is @endel's js2php which is similar to this project at the parsing level, but somewhat different beyond that. It translates JS syntax to PHP but doesn't use a runtime and doesn't attempt to implement the actual ECMAScript spec. It's more like writing PHP but in a friendlier syntax, which is a very cool idea in itself!
Run npm test
. Requires PHP 5.3+ or HHVM.
Copyright (c) 2014, [email protected]. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-
Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.