mirror of
https://github.com/phpv8/v8js.git
synced 2024-12-22 19:51:51 +00:00
commit
75b7b27587
6
.gitignore
vendored
6
.gitignore
vendored
@ -28,3 +28,9 @@ modules
|
||||
v8js.la
|
||||
/run-tests.php
|
||||
.*.sw[poq]
|
||||
|
||||
/tests/*.diff
|
||||
/tests/*.exp
|
||||
/tests/*.out
|
||||
/tests/*.php
|
||||
/tests/*.sh
|
||||
|
125
README.Win32.md
Normal file
125
README.Win32.md
Normal file
@ -0,0 +1,125 @@
|
||||
V8Js on Windows
|
||||
===============
|
||||
|
||||
The V8Js PHP extension is primarily targeted at Unix platforms, especially
|
||||
GNU/Linux. However it is possible (and supported) to build on Windows, using
|
||||
Microsoft Visual Studio.
|
||||
|
||||
Building with MinGW or Cygwin is not officially supported; mainly since
|
||||
Google v8 does not support builds on Cygwin (and building it on Cygwin is
|
||||
currently broken).
|
||||
|
||||
Compared to installation on GNU/Linux it's way more tedious to install V8Js
|
||||
on Windows, since you need to compile PHP with all its dependencies beforehand.
|
||||
|
||||
The problem is that Google v8 requires (at least) Visual Studio 2013 as it
|
||||
uses certain C++11 features not available in Visual Studio 2012.
|
||||
|
||||
Unfortunately the [PHP for Windows](http://windows.php.net/) project still
|
||||
relies on either Visual Studio 2012 or Visual Studio 2008.
|
||||
It supplies pre-compiled binary archives of required dependencies, however also
|
||||
compiled with Visual Studio 2008 and 2012 only.
|
||||
|
||||
Since it is not compatible to link a v8 compiled with Visual Studio 2013 with
|
||||
a PHP interpreter compiled with Visual Studio 2012, you need to step up and
|
||||
compile PHP with Visual Studio 2013. This requires to compile dependencies as
|
||||
well, if you would like to use certain extensions or e.g. the Apache SAPI.
|
||||
|
||||
|
||||
Compiling v8
|
||||
------------
|
||||
|
||||
The Google v8 project already has excellent step-by-step guide on
|
||||
[how to build with gyp](https://code.google.com/p/v8-wiki/wiki/BuildingWithGYP).
|
||||
|
||||
As a short run through:
|
||||
|
||||
* Download and install Python (make sure it adds python.exe to PATH during install)
|
||||
from http://www.python.org/download/
|
||||
* Install Git from https://github.com/msysgit/msysgit/releases/download/Git-1.9.4-preview20140929/Git-1.9.4-preview20140929.exe
|
||||
* Install Subversion from http://sourceforge.net/projects/win32svn/files/latest/download
|
||||
|
||||
Then open a command prompt
|
||||
|
||||
```
|
||||
cd \
|
||||
git clone https://github.com/v8/v8.git
|
||||
cd v8
|
||||
svn co http://gyp.googlecode.com/svn/trunk build/gyp
|
||||
svn co https://src.chromium.org/chrome/trunk/deps/third_party/icu46 third_party/icu
|
||||
svn co http://src.chromium.org/svn/trunk/tools/third_party/python_26@89111 third_party/python_26
|
||||
svn co http://src.chromium.org/svn/trunk/deps/third_party/cygwin@66844 third_party/cygwin
|
||||
svn co http://googletest.googlecode.com/svn/trunk testing/gtest --revision 643
|
||||
svn co http://googlemock.googlecode.com/svn/trunk testing/gmock --revision 410
|
||||
|
||||
python build\gyp_v8 -Dcomponent=shared_library
|
||||
"\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.com" /build Release build/All.sln
|
||||
```
|
||||
|
||||
(alternatively `start build/all.sln` ... and build within the Visual Studio GUI)
|
||||
|
||||
|
||||
|
||||
Compiling PHP
|
||||
-------------
|
||||
|
||||
There [Build your own PHP on Windows](https://wiki.php.net/internals/windows/stepbystepbuild)
|
||||
guide on the PHP wiki. However it concentrates on Visual Studio 2008 and 2012.
|
||||
Since you need to use Visual Studio 2013 it doesn't apply very well.
|
||||
|
||||
This document concentrates on building V8Js for CLI SAPI (only). In order
|
||||
to enable more extensions you need to provide further dependencies, which may
|
||||
be more or less cumbersome to build with Visual Studio beforehand.
|
||||
|
||||
A quick run through:
|
||||
|
||||
* install 7Zip from http://downloads.sourceforge.net/sevenzip/7z920-x64.msi
|
||||
* create directory \php-sdk
|
||||
* Download http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip
|
||||
* ... and unpack to \php-sdk
|
||||
|
||||
Open "VS2013 x86 Native Tools Command Prompt"
|
||||
|
||||
```
|
||||
cd \php-sdk
|
||||
bin\phpsdk_setvars.bat
|
||||
bin\phpsdk_buildtree.bat phpdev
|
||||
|
||||
mkdir vc12
|
||||
mkdir vc12\x86
|
||||
mkdir vc12\x86\deps
|
||||
mkdir vc12\x86\deps\bin
|
||||
mkdir vc12\x86\deps\include
|
||||
mkdir vc12\x86\deps\lib
|
||||
```
|
||||
|
||||
* download PHP from http://php.net/get/php-5.5.18.tar.gz/from/a/mirror
|
||||
and unpack to below `\php-sdk\phpdev\vc12\x86`
|
||||
* from `\v8\build\Release\lib` copy `icui18n.lib`, `icuuc.lib` and `v8.lib`
|
||||
to deps\lib folder
|
||||
* from `\v8\include copy` all v8*.h files to deps\include folder
|
||||
|
||||
(still in "VS2013 x86 Native Tools Command Prompt")
|
||||
|
||||
```
|
||||
cd \php-sdk\phpdev\vc12\x86\php-5.5.18\
|
||||
|
||||
buildconf
|
||||
configure --disable-all --enable-cli --with-v8js
|
||||
nmake
|
||||
```
|
||||
|
||||
After nmake completes the php.exe is in Release_TS\ directory.
|
||||
|
||||
In order to try things out in place, copy over `icui18n.dll`, `icuuc.dll` and
|
||||
`v8.dll` file from `\v8\build\Release` folder to
|
||||
`\php-sdk\phpdev\vc12\x86\php-5.5.18\Release_TS\` first.
|
||||
|
||||
Then run
|
||||
|
||||
```
|
||||
php.exe -d extension=php_v8js.dll -d extension_dir=\php-sdk\phpdev\vc12\x86\php-5.5.18\Release_TS\
|
||||
```
|
||||
|
||||
Alternatively copy all stuff to c:\php\ (including the three DLL files from
|
||||
v8 build).
|
@ -33,6 +33,9 @@ repository](https://registry.hub.docker.com/u/stesie/v8js/).
|
||||
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
|
||||
-----------------
|
||||
|
||||
|
@ -7,11 +7,13 @@ if (PHP_V8JS != "no") {
|
||||
|
||||
ADD_FLAG("CFLAGS_V8JS", "/EHcs");
|
||||
ADD_FLAG("CFLAGS_V8JS", "/D _ALLOW_KEYWORD_MACROS");
|
||||
ADD_FLAG("CFLAGS_V8JS", "/D ZEND_WIN32_FORCE_INLINE");
|
||||
ADD_FLAG("CFLAGS_V8JS", "/D __STDC_LIMIT_MACROS");
|
||||
|
||||
AC_DEFINE("PHP_V8_API_VERSION", "3017015", "", false);
|
||||
AC_DEFINE("PHP_V8_VERSION", "3.17.15", "", true);
|
||||
|
||||
EXTENSION("v8js", "v8js.cc v8js_convert.cc v8js_methods.cc v8js_variables.cc", "yes");
|
||||
EXTENSION("v8js", "v8js.cc v8js_commonjs.cc v8js_convert.cc v8js_methods.cc v8js_variables.cc", "yes");
|
||||
|
||||
} else {
|
||||
WARNING("v8js not enabled, headers or libs not found");
|
||||
|
@ -25,6 +25,12 @@ extern "C" {
|
||||
#include "php_v8js.h"
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* On Windows a symbol COMPILER is defined. However v8.h has an enum with that
|
||||
* name which hence would be broken unless undefined here. */
|
||||
#undef COMPILER
|
||||
#endif
|
||||
|
||||
#include <v8.h>
|
||||
|
||||
#include <chrono>
|
||||
@ -36,6 +42,14 @@ extern "C" {
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
/* Some platforms (Windows among others) don't have a PATH_MAX, for the moment
|
||||
* just assume an arbitrary upper bound of 4096 chars.
|
||||
* Anyways we should fix (get rid of) the code that uses PATH_MAX as it doesn't
|
||||
* even check for buffer overflows. FIXME */
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
/* V8Js Version */
|
||||
#define V8JS_VERSION "0.1.5"
|
||||
|
||||
|
@ -1,7 +1,12 @@
|
||||
--TEST--
|
||||
Test V8Js::setModuleLoader : CommonJS modules
|
||||
--SKIPIF--
|
||||
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||
<?php
|
||||
if(!function_exists('json_encode')) {
|
||||
die('SKIP');
|
||||
}
|
||||
require_once(dirname(__FILE__) . '/skipif.inc');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
|
@ -46,10 +46,10 @@ object(V8Object)#%d (0) {
|
||||
}
|
||||
string(55) "Can't access V8Object after V8Js instance is destroyed!"
|
||||
|
||||
Warning: Uncaught exception 'V8JsScriptException' with message 'Can't access V8Object after V8Js instance is destroyed!' in %s/tests/ctx_lifetime.php:35
|
||||
Warning: Uncaught exception 'V8JsScriptException' with message 'Can't access V8Object after V8Js instance is destroyed!' in %s%etests%ectx_lifetime.php:35
|
||||
Stack trace:
|
||||
#0 %s/tests/ctx_lifetime.php(35): unknown()
|
||||
#0 %s%etests%ectx_lifetime.php(35): unknown()
|
||||
#1 {main}
|
||||
thrown in %s/tests/ctx_lifetime.php on line 35
|
||||
thrown in %s%etests%ectx_lifetime.php on line 35
|
||||
|
||||
Fatal error: Call to undefined method V8Object::hello() in %s/tests/ctx_lifetime.php on line 35
|
||||
Fatal error: Call to undefined method V8Object::hello() in %s%etests%ectx_lifetime.php on line 35
|
||||
|
@ -24,8 +24,8 @@ $js->executeString($script);
|
||||
?>
|
||||
===EOF===
|
||||
--EXPECTF--
|
||||
Notice: Undefined variable: bar in %s/fatal_error_ignore_non_fatals.php on line 6
|
||||
Notice: Undefined variable: bar in %s%efatal_error_ignore_non_fatals.php on line 6
|
||||
|
||||
Warning: Foo Bar! in %s/fatal_error_ignore_non_fatals.php on line 7
|
||||
Warning: Foo Bar! in %s%efatal_error_ignore_non_fatals.php on line 7
|
||||
blar foo
|
||||
===EOF===
|
@ -27,4 +27,4 @@ $js->executeString("PHP.foo();");
|
||||
--EXPECTF--
|
||||
nothing.
|
||||
|
||||
Fatal error: Call to a member function foo() on %s in %s/fatal_error_no_uninstall_inner_frame.php on line 15
|
||||
Fatal error: Call to a member function foo() on %s in %s%efatal_error_no_uninstall_inner_frame.php on line 15
|
||||
|
@ -23,4 +23,4 @@ $js->executeString($script);
|
||||
?>
|
||||
===EOF===
|
||||
--EXPECTF--
|
||||
Fatal error: Call to a member function bar() on %s in %s/fatal_error_rethrow.php on line 7
|
||||
Fatal error: Call to a member function bar() on %s in %s%efatal_error_rethrow.php on line 7
|
||||
|
@ -29,4 +29,4 @@ $bar->foo();
|
||||
--EXPECTF--
|
||||
nothing.
|
||||
|
||||
Fatal error: Call to a member function foo() on %s in %s/fatal_error_uninstall_in_first_frame.php on line 20
|
||||
Fatal error: Call to a member function foo() on %s in %s%efatal_error_uninstall_in_first_frame.php on line 20
|
||||
|
@ -7,8 +7,11 @@ Test V8::executeString() : Time limit
|
||||
$JS = <<< EOT
|
||||
var text = "abcdefghijklmnopqrstuvwyxz0123456789";
|
||||
var memory = "";
|
||||
for (var i = 0; i < 1000000; ++i) {
|
||||
memory += text;
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
for (var j = 0; j < 10000; ++j) {
|
||||
memory += text;
|
||||
}
|
||||
sleep(0);
|
||||
}
|
||||
EOT;
|
||||
|
||||
|
@ -1,7 +1,12 @@
|
||||
--TEST--
|
||||
Test V8::executeString() : DOM object passed from PHP
|
||||
--SKIPIF--
|
||||
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||
<?php
|
||||
if(!class_exists('DomDocument')) {
|
||||
die('skip');
|
||||
}
|
||||
require_once(dirname(__FILE__) . '/skipif.inc');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
|
@ -1,7 +1,12 @@
|
||||
--TEST--
|
||||
Test V8::executeString() : Check timezone handling
|
||||
--SKIPIF--
|
||||
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||
<?php
|
||||
if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
||||
die('SKIP TZ not handled by v8 on Windows');
|
||||
}
|
||||
require_once(dirname(__FILE__) . '/skipif.inc');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
|
25
v8js.cc
25
v8js.cc
@ -21,7 +21,7 @@
|
||||
|
||||
#include <v8-debug.h>
|
||||
|
||||
#if PHP_V8_API_VERSION >= 3029036
|
||||
#if !defined(_WIN32) && PHP_V8_API_VERSION >= 3029036
|
||||
#include <libplatform/libplatform.h>
|
||||
#endif
|
||||
|
||||
@ -478,10 +478,11 @@ static int php_v8js_v8_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) /
|
||||
cb = v8::Local<v8::Function>::Cast(v8obj->Get(method_name));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> jsArgv[argc];
|
||||
v8::Local<v8::Value> *jsArgv = static_cast<v8::Local<v8::Value> *>(alloca(sizeof(v8::Local<v8::Value>) * argc));
|
||||
v8::Local<v8::Value> js_retval;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
new(&jsArgv[i]) v8::Local<v8::Value>;
|
||||
jsArgv[i] = v8::Local<v8::Value>::New(isolate, zval_to_v8js(*argv[i], isolate TSRMLS_CC));
|
||||
}
|
||||
|
||||
@ -676,20 +677,6 @@ static void php_v8js_free_storage(void *object TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
c->context.~Persistent();
|
||||
|
||||
/* Force garbage collection on our isolate, this is needed that V8 triggers
|
||||
* our MakeWeak callbacks. Without these we won't remove our references
|
||||
* on the PHP objects leading to memory leaks in PHP context.
|
||||
*/
|
||||
{
|
||||
v8::Locker locker(c->isolate);
|
||||
v8::Isolate::Scope isolate_scope(c->isolate);
|
||||
#if PHP_V8_API_VERSION < 3028036
|
||||
while(!v8::V8::IdleNotification()) {};
|
||||
#else
|
||||
while(!c->isolate->IdleNotification(500)) {};
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Dispose yet undisposed weak refs */
|
||||
for (std::map<zval *, v8js_persistent_obj_t>::iterator it = c->weak_objects.begin();
|
||||
it != c->weak_objects.end(); ++it) {
|
||||
@ -869,7 +856,7 @@ static void php_v8js_init(TSRMLS_D) /* {{{ */
|
||||
return;
|
||||
}
|
||||
|
||||
#if PHP_V8_API_VERSION >= 3029036
|
||||
#if !defined(_WIN32) && PHP_V8_API_VERSION >= 3029036
|
||||
v8::Platform* platform = v8::platform::CreateDefaultPlatform();
|
||||
v8::V8::InitializePlatform(platform);
|
||||
#endif
|
||||
@ -1133,8 +1120,12 @@ static void php_v8js_timer_thread(TSRMLS_D)
|
||||
}
|
||||
|
||||
// Sleep for 10ms
|
||||
#ifdef _WIN32
|
||||
concurrency::wait(10);
|
||||
#else
|
||||
std::chrono::milliseconds duration(10);
|
||||
std::this_thread::sleep_for(duration);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,10 +471,11 @@ static void php_v8js_named_property_enumerator(const v8::PropertyCallbackInfo<v8
|
||||
// prefix enumerated property names with '$' so they can be
|
||||
// dereferenced unambiguously (ie, don't conflict with method
|
||||
// names)
|
||||
char prefixed[key_len + 1];
|
||||
char *prefixed = static_cast<char *>(emalloc(key_len + 1));
|
||||
prefixed[0] = '$';
|
||||
strncpy(prefixed + 1, key, key_len);
|
||||
result->Set(result_len++, V8JS_STRL(prefixed, key_len));
|
||||
efree(prefixed);
|
||||
} else {
|
||||
// even numeric indices are enumerated as strings in JavaScript
|
||||
result->Set(result_len++, V8JS_FLOAT((double) index)->ToString());
|
||||
@ -492,12 +493,13 @@ static void php_v8js_invoke_callback(const v8::FunctionCallbackInfo<v8::Value>&
|
||||
v8::Local<v8::Object> self = info.Holder();
|
||||
v8::Local<v8::Function> cb = v8::Local<v8::Function>::Cast(info.Data());
|
||||
int argc = info.Length(), i;
|
||||
v8::Local<v8::Value> argv[argc];
|
||||
v8::Local<v8::Value> *argv = static_cast<v8::Local<v8::Value> *>(alloca(sizeof(v8::Local<v8::Value>) * argc));
|
||||
v8::Local<v8::Value> result;
|
||||
|
||||
V8JS_TSRMLS_FETCH();
|
||||
|
||||
for (i=0; i<argc; i++) {
|
||||
new(&argv[i]) v8::Local<v8::Value>;
|
||||
argv[i] = info[i];
|
||||
}
|
||||
|
||||
@ -595,8 +597,9 @@ static void php_v8js_fake_call_impl(const v8::FunctionCallbackInfo<v8::Value>& i
|
||||
// use php_v8js_php_callback to actually execute the method
|
||||
v8::Local<v8::Function> cb = PHP_V8JS_CALLBACK(isolate, method_ptr, tmpl);
|
||||
uint32_t i, argc = args->Length();
|
||||
v8::Local<v8::Value> argv[argc];
|
||||
v8::Local<v8::Value> *argv = static_cast<v8::Local<v8::Value> *>(alloca(sizeof(v8::Local<v8::Value>) * argc));
|
||||
for (i=0; i<argc; i++) {
|
||||
new(&argv[i]) v8::Local<v8::Value>;
|
||||
argv[i] = args->Get(i);
|
||||
}
|
||||
return_value = cb->Call(info.This(), (int) argc, argv);
|
||||
@ -1093,6 +1096,10 @@ v8::Handle<v8::Value> zval_to_v8js(zval *value, v8::Isolate *isolate TSRMLS_DC)
|
||||
|
||||
case IS_LONG:
|
||||
v = Z_LVAL_P(value);
|
||||
/* On Windows there are max and min macros, which would clobber the
|
||||
* method names of std::numeric_limits< > otherwise. */
|
||||
#undef max
|
||||
#undef min
|
||||
if (v < - std::numeric_limits<int32_t>::min() || v > std::numeric_limits<int32_t>::max()) {
|
||||
jsValue = V8JS_FLOAT((double)v);
|
||||
} else {
|
||||
@ -1142,12 +1149,32 @@ int v8js_to_zval(v8::Handle<v8::Value> jsValue, zval *return_value, int flags, v
|
||||
{
|
||||
v8::String::Utf8Value str(jsValue);
|
||||
const char *cstr = ToCString(str);
|
||||
|
||||
/* cstr has two timezone specifications:
|
||||
*
|
||||
* example from Linux:
|
||||
* Mon Sep 08 1975 09:00:00 GMT+0000 (UTC)
|
||||
*
|
||||
* example from Windows:
|
||||
* Mon Sep 08 1975 11:00:00 GMT+0200 (W. Europe Daylight Time)
|
||||
*
|
||||
* ... problem is, that PHP can't parse the second timezone
|
||||
* specification as returned by v8 running on Windows. And as a
|
||||
* matter of that fails due to inconsistent second timezone spec
|
||||
*/
|
||||
char *date_str = estrdup(cstr);
|
||||
char *paren_ptr = strchr(date_str, '(');
|
||||
|
||||
if (paren_ptr != NULL) {
|
||||
*paren_ptr = 0;
|
||||
}
|
||||
|
||||
zend_class_entry *ce = php_date_get_date_ce();
|
||||
#if PHP_VERSION_ID < 50304
|
||||
zval *param;
|
||||
|
||||
MAKE_STD_ZVAL(param);
|
||||
ZVAL_STRING(param, cstr, 1);
|
||||
ZVAL_STRING(param, date_str, 0);
|
||||
|
||||
object_init_ex(return_value, ce TSRMLS_CC);
|
||||
zend_call_method_with_1_params(&return_value, ce, &ce->constructor, "__construct", NULL, param);
|
||||
@ -1158,9 +1185,12 @@ int v8js_to_zval(v8::Handle<v8::Value> jsValue, zval *return_value, int flags, v
|
||||
}
|
||||
#else
|
||||
php_date_instantiate(ce, return_value TSRMLS_CC);
|
||||
if (!php_date_initialize((php_date_obj *) zend_object_store_get_object(return_value TSRMLS_CC), (char *) cstr, strlen(cstr), NULL, NULL, 0 TSRMLS_CC)) {
|
||||
if (!php_date_initialize((php_date_obj *) zend_object_store_get_object(return_value TSRMLS_CC), date_str, strlen(date_str), NULL, NULL, 0 TSRMLS_CC)) {
|
||||
efree(date_str);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
efree(date_str);
|
||||
#endif
|
||||
}
|
||||
else if (jsValue->IsObject())
|
||||
|
Loading…
Reference in New Issue
Block a user