Javascript inside PHP

Posted on: September 26th, 2011 by Spade 2 Comments »

Иногда возникает необходимость выполнить код JavaScript на стороне сервера. Например, если вы парсите сохраненные html-страницы и не хотите жесткой привязки к исходным кодам, или же пишите паука, который пользуется данными с какого-то публичного сервиса (принимая во внимание наличие разрешения от владельцев сервиса на такие действия), где JavaScript может менять содержимое страницы уже после выдачи сгенерированного html. В этой статье мы рассмотрим вариант решения данной проблемы с помощью javascript движка от Mozilla.org – SpiderMonkey.

SpiderMonkey – это ECMAScript-совместимый движок от Мозиллы, который используется в их браузере (с помощью патча TraceMonkey этот движок был ускорен). Его можно установить просто как Javascript shell консоль, посылать туда файлы и получать ответ. Понятно, что сам по себе он не поддерживает DOM дерево объектов, их реализация остается на совести конкретного браузера. Потому, если в вашем скрипте такие объекты есть – надо будет их почистить. В принципе эту консоль можно использовать в теневом режиме для любого языка программирования – с помощью запуска отдельного процесса. Например, в Java:

ProcessBuilder processBuilder = new ProcessBuilder(commands);
Process process = processBuilder.redirectErrorStream(true).start();

Но мы рассмотрим наиболее популярный вариант серверных скриптов – PHP. Поддержку для этого языка можно реализовать с помощью PECL spidermonkey расширения. Оно все еще на стадии бета версии, но в принципе, работать способно. Мы будем пробовать версию 1.7 (есть более поздняя – 1.8.5, но лично у меня она не поднялась до рабочего состояния). Разберем установку по шагам.

Выполним это на *NIX системе (я производил все это на Ubuntu 11.04 на VirtualBox). Будем считать что вы уже выполнили установку всего необходимого:

apt-get-install apache2
apt-get-install php5
apt-get install libapache2-mod-php5
apt-get install php5-dev

Последний нужен для использования phpize

/etc/init.d/apache2 restart

Перезапуск…

Версия PHP должна быть не ниже 5.3, чтоб все это взлетело.  Скачиваем библиотеки с сайта мозиллы: http://ftp.mozilla.org/pub/mozilla.org/js/ . Распаковываем архив и войдя в js/src директорию запускаем сборку:

make -f Makefile.ref

Копируем созданные файлы по нужным местам :) :

mkdir -p /usr/local/include/js/
cp *.{h,tbl} /usr/local/include/js/
cd Linux_All_DBG.OBJ
cp *.h /usr/local/include/js/
cp js /usr/local/bin/
cp libjs.so /usr/local/lib/

Переконфигурируем лоадер библиотек:

ldconfig

По окончании, делаем checkout SVN (для начала его нужно установить: apt-get install subversion) – расширение для SpiderMonkey. https://ookoo.org/svn/pecl-spidermonkey/ – установка идет с помощью phpize.

cd /home/svn/php-spidermonkey
phpize
./configure
make
make install

Это создаст загружаемую библиотеку в директории расширений для PHP. Чтобы оно подгрузилось, сделаем следующее: в директорию /etc/php5/apache2/conf.d добавим файл spidermonkey.ini, со строками:

extension=spidermonkey.so

Перезапуск:

/etc/init.d/apache2 restart

Дальше запуская phpinfo(); проверяем, что .ini был учтен

и что расширение было загружено:

Теперь создаем тестовый файл в вэб-руте /var/www/test.php

<?php
 
$js = new JSContext();
 
$script = "
 
    function AddUnsigned(lX,lY) {
        var lX4,lY4,lX8,lY8,lResult;
        lX8 = (lX & 0x80000000);
        lY8 = (lY & 0x80000000);
        lX4 = (lX & 0x40000000);
        lY4 = (lY & 0x40000000);
        lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
        if (lX4 & lY4) {
            return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
        }
        if (lX4 | lY4) {
            if (lResult & 0x40000000) {
                return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            } else {
                return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
            }
        } else {
            return (lResult ^ lX8 ^ lY8);
        }
     }
 
res = AddUnsigned(23, 12);
 
";
 
// evaluate script and display result
echo "JS call Result: " . $js->evaluateScript($script);

в качестве скрипта взяли заковыристую функцию, в которой совершенно непонятно что происходит :)

В браузере вводим http://localhost/test.php
Что-то вывелось:

JS call Result: 35

Ура, товарищи! Потестируйте со своими функциями (только без DOM-объектов).

В завершении отметим, что есть достойный конкурент – V8, opensource движок javascript используемый в браузере Google Chrome. Возможно в одной из следующих статей мы рассмотрим и этот вариант.

Данная статья основана на англоязычном варианте.

2 Responses

  1. yakoff says:

    Откуда ты это скопипастил?)

    • Spade says:

      Внизу ссылка на англоязычный источник

Leave a Reply