0
0
mirror of https://github.com/phpv8/v8js.git synced 2024-11-09 23:08:41 +00:00
V8 Javascript Engine for PHP — This PHP extension embeds the Google V8 Javascript Engine.
Go to file
Stefan Siegl d21896ab33 Test export of properties on ArrayAccess object
Private & protected properties shouldn't be accessible, also the
length property should not be overwritten by a length property of
the PHP object.
2014-11-29 21:30:44 +01:00
js Initial import 2012-04-27 16:26:15 +00:00
samples Add a test of PHP magic functions. 2013-10-25 16:47:15 -04:00
tests Test export of properties on ArrayAccess object 2014-11-29 21:30:44 +01:00
.gitignore ignore run-tests.php helper files 2014-11-13 21:13:24 +01:00
.travis.yml add PHP 5.6 to .travis.yml 2014-09-28 00:29:41 +09:00
config.m4 Move PHP to JS object wrapping into seperate file 2014-11-29 15:42:41 +01:00
config.w32 Move PHP to JS object wrapping into seperate file 2014-11-29 15:42:41 +01:00
CREDITS Added my name to the credits :-) 2013-04-09 22:52:52 +01:00
LICENSE fix license issue 2013-09-29 20:01:33 -07:00
Makefile.frag The json extension is not needed for PHP 5.4. 2013-10-02 17:12:35 -04:00
Makefile.travis Travis config update: compile against minimum supported v8 and most recent v8. 2013-10-27 02:49:24 -04:00
package.xml Added new "v8js.use_date" ini setting to convert PHP DateTime objects to Javascript Date objects 2014-03-20 16:06:18 +02:00
php_v8js_macros.h Add basic ArrayAccess wrapping 2014-11-23 23:39:15 +01:00
php_v8js.h updated package for beta release and switch license to MIT 2013-09-28 10:17:33 -07:00
README.md Merge branch 'issue-126' 2014-11-22 13:27:26 +01:00
README.Win32.md Mention to download & unpack V8Js itself 2014-11-17 00:05:35 +01:00
test.php Make sure all tests and samples use the new exception class name V8JsScriptException. 2013-04-14 00:36:31 +01:00
TODO Rework JavaScript wrapper for PHP objects. 2013-10-25 16:47:15 -04:00
v8js_array_access.cc Export extra methods on ArrayAccess 2014-11-29 20:35:32 +01:00
v8js_array_access.h Export extra methods on ArrayAccess 2014-11-29 20:35:32 +01:00
v8js_commonjs.cc updated package for beta release and switch license to MIT 2013-09-28 10:17:33 -07:00
v8js_convert.cc Move PHP to JS object wrapping into seperate file 2014-11-29 15:42:41 +01:00
v8js_methods.cc Drop old-age PHP_V8_API_VERSION #ifdef 2014-10-19 12:20:10 +00:00
v8js_object_export.cc Fix ZTS build 2014-11-29 19:49:44 +00:00
v8js_object_export.h Export extra methods on ArrayAccess 2014-11-29 20:35:32 +01:00
v8js_variables.cc Get rid of V8JS_NEW macro. 2014-10-19 11:58:21 +00:00
v8js.cc Add basic ArrayAccess wrapping 2014-11-23 23:39:15 +01:00

V8Js

V8Js is a PHP extension for Google's V8 Javascript engine.

The extension allows you to execute Javascript code in a secure sandbox from PHP. The executed code can be restricted using a time limit and/or memory limit. This provides the possibility to execute untrusted code with confidence.

Minimum requirements

  • V8 Javascript Engine library (libv8) master https://github.com/v8/v8/ (trunk)

    V8 is Google's open source Javascript engine. V8 is written in C++ and is used in Google Chrome, the open source browser from Google. V8 implements ECMAScript as specified in ECMA-262, 5th edition. This extension makes use of V8 isolates to ensure separation between multiple V8Js instances and uses the new isolate-based mechanism to throw exceptions, hence the need for 3.24.10 or above.

    For a detailed overview of which V8 version V8Js can be successfully built against, see the Jenkins V8Js build matrix.

  • PHP 5.3.3+

    This embedded implementation of the V8 engine uses thread locking so it should work with ZTS enabled. However, this has not been tested yet.

COMPILING LATEST VERSION

Instead of compiling manually you might want to pull from the V8Js docker repository.

You also might want to try the Debian & Ubuntu packages available from the Jenkins site at https://jenkins.brokenpipe.de/

Building on Microsoft Windows is more complicated, see README.Win32.md file for a quick run through.

Compile latest v8

cd /tmp
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"
git clone https://github.com/v8/v8.git
cd v8
make dependencies
make native library=shared -j8
sudo mkdir -p /usr/lib /usr/include
sudo cp out/native/lib.target/lib*.so /usr/lib/
echo -e "create /usr/lib/libv8_libplatform.a\naddlib out/native/obj.target/tools/gyp/libv8_libplatform.a\nsave\nend" | sudo ar -M
sudo cp -R include/* /usr/include

If you don't want to overwrite the system copy of v8, replace /usr in the above commands with /tmp/v8-install and then add --with-v8js=/tmp/v8-install to the php-v8js ./configure command below.

libv8_libplatform.a should not be copied directly since it's a thin archive, i.e. it contains only pointers to the build objects, which otherwise must not be deleted. The simple mri-script converts the thin archive to a normal archive.

Compile php-v8js itself

cd /tmp
git clone https://github.com/preillyme/v8js.git
cd v8js
phpize
./configure
make
sudo make install

PHP API

    class V8Js
    {
        /* Constants */

        const string V8_VERSION;

        const int FLAG_NONE;
        const int FLAG_FORCE_ARRAY;

        const int DEBUG_AUTO_BREAK_NEVER;
        const int DEBUG_AUTO_BREAK_ONCE;
        const int DEBUG_AUTO_BREAK_ALWAYS;
    
        /* Methods */

        // Initializes and starts V8 engine and Returns new V8Js object with it's own V8 context.
        public __construct ( [ string $object_name = "PHP" [, array $variables = NULL [, array $extensions = NULL [, bool $report_uncaught_exceptions = TRUE ] ] ] )

        // Provide a function or method to be used to load required modules. This can be any valid PHP callable.
        // The loader function will receive the normalised module path and should return Javascript code to be executed.
        public setModuleLoader ( callable $loader )

        // Compiles and executes script in object's context with optional identifier string.
        // A time limit (milliseconds) and/or memory limit (bytes) can be provided to restrict execution. These options will throw a V8JsTimeLimitException or V8JsMemoryLimitException.
        public mixed V8Js::executeString( string $script [, string $identifier [, int $flags = V8Js::FLAG_NONE [, int $time_limit = 0 [, int $memory_limit = 0]]]])

        // Compiles a script in object's context with optional identifier string.
        public mixed V8Js::compileString( string $script [, string $identifier ])

        // Executes a precompiled script in object's context.
        // A time limit (milliseconds) and/or memory limit (bytes) can be provided to restrict execution. These options will throw a V8JsTimeLimitException or V8JsMemoryLimitException.
        public mixed V8Js::executeScript( resource $script [, int $flags = V8Js::FLAG_NONE [, int $time_limit = 0 [, int $memory_limit = 0]]])

        // Returns uncaught pending exception or null if there is no pending exception.
        public V8JsScriptException V8Js::getPendingException( )

        // Clears the uncaught pending exception
        public clearPendingException( )

        // Starts V8 debug agent for use with Google Chrome Developer Tools (Eclipse Plugin)
        public bool startDebugAgent( [ string $agent_name = "V8Js" [, $port = 9222 [, $auto_break = V8Js::DEBUG_AUTO_BREAK_NEVER ] ] ] )

        /** Static methods **/

        // Registers persistent context independent global Javascript extension.
        // NOTE! These extensions exist until PHP is shutdown and they need to be registered before V8 is initialized. 
        // For best performance V8 is initialized only once per process thus this call has to be done before any V8Js objects are created!
        public static bool V8Js::registerExtension( string $extension_name, string $code [, array $dependenciess [, bool $auto_enable = FALSE ] ] )

        // Returns extensions successfully registered with V8Js::registerExtension().
        public static array V8Js::getExtensions( )
    }

    final class V8JsScriptException extends Exception
    {
        /* Properties */
        protected string JsFileName = NULL;
        protected int JsLineNumber = NULL;
        protected int JsStartColumn = NULL;
        protected int JsEndColumn = NULL;
        protected string JsSourceLine = NULL;
        protected string JsTrace = NULL;
        
        /* Methods */
        final public string getJsFileName( )
        final public int getJsLineNumber( )
        final public int getJsStartColumn( )
        final public int getJsEndColumn( )
        final public string getJsSourceLine( )
        final public string getJsTrace( )
    }

    final class V8JsTimeLimitException extends Exception
    {
    }

    final class V8JsMemoryLimitException extends Exception
    {
    }

Javascript API

    // Print a string.
    print(string);

    // Dump the contents of a variable.
    var_dump(value);

    // Terminate Javascript execution immediately.
    exit();

    // CommonJS Module support to require external code.
    // This makes use of the PHP module loader provided via V8Js::setModuleLoader (see PHP API above).
    require("path/to/module");

The JavaScript in operator, when applied to a wrapped PHP object, works the same as the PHP isset() function. Similarly, when applied to a wrapped PHP object, JavaScript delete works like PHP unset.

<?php
class Foo {
  var $bar = null;
}
$v8 = new V8Js();
$v8->foo = new Foo;
// This prints "no"
$v8->executeString('print( "bar" in PHP.foo ? "yes" : "no" );');
?>

PHP has separate namespaces for properties and methods, while JavaScript has just one. Usually this isn't an issue, but if you need to you can use a leading $ to specify a property, or __call to specifically invoke a method.

<?php
class Foo {
	var $bar = "bar";
	function bar($what) { echo "I'm a ", $what, "!\n"; }
}

$foo = new Foo;
// This prints 'bar'
echo $foo->bar, "\n";
// This prints "I'm a function!"
$foo->bar("function");

$v8 = new V8Js();
$v8->foo = new Foo;
// This prints 'bar'
$v8->executeString('print(PHP.foo.$bar, "\n");');
// This prints "I'm a function!"
$v8->executeString('PHP.foo.__call("bar", ["function"]);');
?>