mirror of
https://github.com/phpv8/v8js.git
synced 2024-12-23 09:31:52 +00:00
Merge pull request #189 from stesie/merge-php5-to-php7
Merge version 0.4.0 features to php7 branch
This commit is contained in:
commit
cb94958afd
13
README.md
13
README.md
@ -81,6 +81,19 @@ class V8Js
|
|||||||
public function setModuleLoader(callable $loader)
|
public function setModuleLoader(callable $loader)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a function or method to be used to normalise module paths. This can be any valid PHP callable.
|
||||||
|
* This can be used in combination with setModuleLoader to influence normalisation of the module path (which
|
||||||
|
* is normally done by V8Js itself but can be overriden this way).
|
||||||
|
* The normaliser function will receive the base path of the current module (if any; otherwise an empty string)
|
||||||
|
* and the literate string provided to the require method and should return an array of two strings (the new
|
||||||
|
* module base path as well as the normalised name). Both are joined by a '/' and then passed on to the
|
||||||
|
* module loader (unless the module was cached before).
|
||||||
|
* @param callable $normaliser
|
||||||
|
*/
|
||||||
|
public function setModuleNormaliser(callable $normaliser)
|
||||||
|
{}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiles and executes script in object's context with optional identifier string.
|
* 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.
|
* A time limit (milliseconds) and/or memory limit (bytes) can be provided to restrict execution. These options will throw a V8JsTimeLimitException or V8JsMemoryLimitException.
|
||||||
|
31
tests/commonjs_cust_normalise_001.phpt
Normal file
31
tests/commonjs_cust_normalise_001.phpt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8Js::setModuleNormaliser : Custom normalisation #001
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$JS = <<< EOT
|
||||||
|
var foo = require("./test");
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
$v8->setModuleNormaliser(function($base, $module) {
|
||||||
|
var_dump($base, $module);
|
||||||
|
return [ "", "test" ];
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->setModuleLoader(function($module) {
|
||||||
|
print("setModuleLoader called for ".$module."\n");
|
||||||
|
return 'exports.bar = 23;';
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->executeString($JS, 'module.js');
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
string(0) ""
|
||||||
|
string(6) "./test"
|
||||||
|
setModuleLoader called for test
|
||||||
|
===EOF===
|
33
tests/commonjs_cust_normalise_002.phpt
Normal file
33
tests/commonjs_cust_normalise_002.phpt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8Js::setModuleNormaliser : Custom normalisation #002
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$JS = <<< EOT
|
||||||
|
var foo = require("./test");
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
// setModuleNormaliser may redirect module requirement
|
||||||
|
// to a different path (and even rename the module)
|
||||||
|
$v8->setModuleNormaliser(function($base, $module) {
|
||||||
|
var_dump($base, $module);
|
||||||
|
return [ "path/to", "test-foo" ];
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->setModuleLoader(function($module) {
|
||||||
|
print("setModuleLoader called for ".$module."\n");
|
||||||
|
return 'exports.bar = 23;';
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->executeString($JS, 'module.js');
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
string(0) ""
|
||||||
|
string(6) "./test"
|
||||||
|
setModuleLoader called for path/to/test-foo
|
||||||
|
===EOF===
|
41
tests/commonjs_cust_normalise_003.phpt
Normal file
41
tests/commonjs_cust_normalise_003.phpt
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8Js::setModuleNormaliser : Custom normalisation #003
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$JS = <<< EOT
|
||||||
|
var foo = require("./test");
|
||||||
|
var bar = require("test");
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
// Caching is done based on the identifiers passed back
|
||||||
|
// by the module normaliser. If it returns the same id
|
||||||
|
// for multiple require calls, the module loader callback
|
||||||
|
// will be called only once (as the others are cached)
|
||||||
|
$v8->setModuleNormaliser(function($base, $module) {
|
||||||
|
var_dump($base, $module);
|
||||||
|
return [ "path/to", "test-foo" ];
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->setModuleLoader(function($module) {
|
||||||
|
print("setModuleLoader called for ".$module."\n");
|
||||||
|
if($module != "path/to/test-foo") {
|
||||||
|
throw new \Exception("module caching fails");
|
||||||
|
}
|
||||||
|
return 'exports.bar = 23;';
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->executeString($JS, 'module.js');
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
string(0) ""
|
||||||
|
string(6) "./test"
|
||||||
|
setModuleLoader called for path/to/test-foo
|
||||||
|
string(0) ""
|
||||||
|
string(4) "test"
|
||||||
|
===EOF===
|
42
tests/commonjs_cust_normalise_004.phpt
Normal file
42
tests/commonjs_cust_normalise_004.phpt
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8Js::setModuleNormaliser : Custom normalisation #004
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$JS = <<< EOT
|
||||||
|
var foo = require("foo");
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
// If a module includes another module, $base must be set to the
|
||||||
|
// path of the first module (on the second call)
|
||||||
|
$v8->setModuleNormaliser(function($base, $module) {
|
||||||
|
var_dump($base, $module);
|
||||||
|
return [ "path/to", $module ];
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->setModuleLoader(function($module) {
|
||||||
|
print("setModuleLoader called for ".$module."\n");
|
||||||
|
switch($module) {
|
||||||
|
case "path/to/foo":
|
||||||
|
return "require('bar');";
|
||||||
|
|
||||||
|
case "path/to/bar":
|
||||||
|
return 'exports.bar = 23;';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->executeString($JS, 'module.js');
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
string(0) ""
|
||||||
|
string(3) "foo"
|
||||||
|
setModuleLoader called for path/to/foo
|
||||||
|
string(7) "path/to"
|
||||||
|
string(3) "bar"
|
||||||
|
setModuleLoader called for path/to/bar
|
||||||
|
===EOF===
|
17
tests/commonjs_fatal_error.phpt
Normal file
17
tests/commonjs_fatal_error.phpt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8Js::setModuleLoader : Handle fatal errors gracefully
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
$v8->setModuleLoader(function() {
|
||||||
|
trigger_error('some fatal error', E_USER_ERROR);
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->executeString(' require("foo"); ');
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: some fatal error in %s%ecommonjs_fatal_error.php on line 5
|
27
tests/commonjs_source_naming.phpt
Normal file
27
tests/commonjs_source_naming.phpt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8Js::setModuleLoader : Module source naming
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$JS = <<< EOT
|
||||||
|
require('./foo//bar');
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
$v8->setModuleLoader(function($module) {
|
||||||
|
// return code with syntax errors to provoke script exception
|
||||||
|
return "foo(blar);";
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
$v8->executeString($JS, 'commonjs_source_naming.js');
|
||||||
|
} catch (V8JsScriptException $e) {
|
||||||
|
var_dump($e->getJsFileName());
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
string(7) "foo/bar"
|
||||||
|
===EOF===
|
36
tests/issue_185_001.phpt
Normal file
36
tests/issue_185_001.phpt
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8::executeString() : Issue #185 this on direct invocation of method
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
$JS = <<<EOT
|
||||||
|
|
||||||
|
function Bar(i) {
|
||||||
|
this.theValue = i;
|
||||||
|
}
|
||||||
|
Bar.prototype.tell = function() {
|
||||||
|
var_dump(this.theValue);
|
||||||
|
var_dump(typeof this.exit);
|
||||||
|
};
|
||||||
|
var inst = new Bar(23);
|
||||||
|
var fn = inst.tell;
|
||||||
|
fn();
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$v8->executeString($JS);
|
||||||
|
|
||||||
|
// now fetch `inst` from V8 and call method from PHP
|
||||||
|
$fn = $v8->executeString('(inst.tell)');
|
||||||
|
$fn();
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
NULL
|
||||||
|
string(8) "function"
|
||||||
|
NULL
|
||||||
|
string(8) "function"
|
||||||
|
===EOF===
|
28
tests/issue_185_002.phpt
Normal file
28
tests/issue_185_002.phpt
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8::executeString() : Issue #185 this on function invocation
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
$JS = <<<EOT
|
||||||
|
|
||||||
|
function fn() {
|
||||||
|
var_dump(typeof this.exit);
|
||||||
|
};
|
||||||
|
fn();
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$v8->executeString($JS);
|
||||||
|
|
||||||
|
// now fetch `inst` from V8 and call method from PHP
|
||||||
|
$fn = $v8->executeString('(fn)');
|
||||||
|
$fn();
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
string(8) "function"
|
||||||
|
string(8) "function"
|
||||||
|
===EOF===
|
32
tests/issue_185_basic.phpt
Normal file
32
tests/issue_185_basic.phpt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8::executeString() : Issue #185 Wrong this on V8Object method invocation
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
$JS = <<<EOT
|
||||||
|
|
||||||
|
function Bar(i) {
|
||||||
|
this.theValue = i;
|
||||||
|
}
|
||||||
|
Bar.prototype.tell = function() {
|
||||||
|
var_dump(this.theValue);
|
||||||
|
};
|
||||||
|
var inst = new Bar(23);
|
||||||
|
inst.tell();
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$v8->executeString($JS);
|
||||||
|
|
||||||
|
// now fetch `inst` from V8 and call method from PHP
|
||||||
|
$inst = $v8->executeString('(inst)');
|
||||||
|
$inst->tell();
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
int(23)
|
||||||
|
int(23)
|
||||||
|
===EOF===
|
@ -85,7 +85,9 @@ static void v8js_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
|
|||||||
v8js_ctx *c = v8js_ctx_fetch_object(object);
|
v8js_ctx *c = v8js_ctx_fetch_object(object);
|
||||||
|
|
||||||
zend_object_std_dtor(&c->std TSRMLS_CC);
|
zend_object_std_dtor(&c->std TSRMLS_CC);
|
||||||
|
|
||||||
zval_dtor(&c->pending_exception);
|
zval_dtor(&c->pending_exception);
|
||||||
|
zval_dtor(&c->module_normaliser);
|
||||||
zval_dtor(&c->module_loader);
|
zval_dtor(&c->module_loader);
|
||||||
|
|
||||||
/* Delete PHP global object from JavaScript */
|
/* Delete PHP global object from JavaScript */
|
||||||
@ -358,6 +360,7 @@ static PHP_METHOD(V8Js, __construct)
|
|||||||
c->memory_limit = 0;
|
c->memory_limit = 0;
|
||||||
c->memory_limit_hit = false;
|
c->memory_limit_hit = false;
|
||||||
|
|
||||||
|
ZVAL_NULL(&c->module_normaliser);
|
||||||
ZVAL_NULL(&c->module_loader);
|
ZVAL_NULL(&c->module_loader);
|
||||||
|
|
||||||
/* Include extensions used by this context */
|
/* Include extensions used by this context */
|
||||||
@ -671,6 +674,22 @@ static PHP_METHOD(V8Js, clearPendingException)
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ proto void V8Js::setModuleNormaliser(string base, string module_id)
|
||||||
|
*/
|
||||||
|
static PHP_METHOD(V8Js, setModuleNormaliser)
|
||||||
|
{
|
||||||
|
v8js_ctx *c;
|
||||||
|
zval *callable;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &callable) == FAILURE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = Z_V8JS_CTX_OBJ_P(getThis());
|
||||||
|
ZVAL_COPY(&c->module_normaliser, callable);
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ proto void V8Js::setModuleLoader(string module)
|
/* {{{ proto void V8Js::setModuleLoader(string module)
|
||||||
*/
|
*/
|
||||||
static PHP_METHOD(V8Js, setModuleLoader)
|
static PHP_METHOD(V8Js, setModuleLoader)
|
||||||
@ -964,6 +983,11 @@ ZEND_END_ARG_INFO()
|
|||||||
ZEND_BEGIN_ARG_INFO(arginfo_v8js_clearpendingexception, 0)
|
ZEND_BEGIN_ARG_INFO(arginfo_v8js_clearpendingexception, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_setmodulenormaliser, 0, 0, 2)
|
||||||
|
ZEND_ARG_INFO(0, base)
|
||||||
|
ZEND_ARG_INFO(0, module_id)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_setmoduleloader, 0, 0, 1)
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_setmoduleloader, 0, 0, 1)
|
||||||
ZEND_ARG_INFO(0, callable)
|
ZEND_ARG_INFO(0, callable)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
@ -997,6 +1021,7 @@ static const zend_function_entry v8js_methods[] = { /* {{{ */
|
|||||||
PHP_ME(V8Js, checkString, arginfo_v8js_checkstring, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
|
PHP_ME(V8Js, checkString, arginfo_v8js_checkstring, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
|
||||||
PHP_ME(V8Js, getPendingException, arginfo_v8js_getpendingexception, ZEND_ACC_PUBLIC)
|
PHP_ME(V8Js, getPendingException, arginfo_v8js_getpendingexception, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(V8Js, clearPendingException, arginfo_v8js_clearpendingexception, ZEND_ACC_PUBLIC)
|
PHP_ME(V8Js, clearPendingException, arginfo_v8js_clearpendingexception, ZEND_ACC_PUBLIC)
|
||||||
|
PHP_ME(V8Js, setModuleNormaliser, arginfo_v8js_setmodulenormaliser, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(V8Js, setModuleLoader, arginfo_v8js_setmoduleloader, ZEND_ACC_PUBLIC)
|
PHP_ME(V8Js, setModuleLoader, arginfo_v8js_setmoduleloader, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(V8Js, registerExtension, arginfo_v8js_registerextension, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
PHP_ME(V8Js, registerExtension, arginfo_v8js_registerextension, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||||
PHP_ME(V8Js, getExtensions, arginfo_v8js_getextensions, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
PHP_ME(V8Js, getExtensions, arginfo_v8js_getextensions, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||||
|
@ -49,7 +49,9 @@ struct v8js_ctx {
|
|||||||
v8js_tmpl_t global_template;
|
v8js_tmpl_t global_template;
|
||||||
v8js_tmpl_t array_tmpl;
|
v8js_tmpl_t array_tmpl;
|
||||||
|
|
||||||
|
zval module_normaliser;
|
||||||
zval module_loader;
|
zval module_loader;
|
||||||
|
|
||||||
std::vector<char *> modules_stack;
|
std::vector<char *> modules_stack;
|
||||||
std::vector<char *> modules_base;
|
std::vector<char *> modules_base;
|
||||||
std::map<char *, v8js_persistent_obj_t, cmp_str> modules_loaded;
|
std::map<char *, v8js_persistent_obj_t, cmp_str> modules_loaded;
|
||||||
|
153
v8js_methods.cc
153
v8js_methods.cc
@ -8,6 +8,7 @@
|
|||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Author: Jani Taskinen <jani.taskinen@iki.fi> |
|
| Author: Jani Taskinen <jani.taskinen@iki.fi> |
|
||||||
| Author: Patrick Reilly <preilly@php.net> |
|
| Author: Patrick Reilly <preilly@php.net> |
|
||||||
|
| Author: Stefan Siegl <stesie@brokenpipe.de> |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -91,10 +92,20 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local<v8::Value> var, int leve
|
|||||||
}
|
}
|
||||||
|
|
||||||
v8::TryCatch try_catch; /* object.toString() can throw an exception */
|
v8::TryCatch try_catch; /* object.toString() can throw an exception */
|
||||||
v8::Local<v8::String> details = var->ToDetailString();
|
v8::Local<v8::String> details;
|
||||||
|
|
||||||
|
if(var->IsRegExp()) {
|
||||||
|
v8::RegExp *re = v8::RegExp::Cast(*var);
|
||||||
|
details = re->GetSource();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
details = var->ToDetailString();
|
||||||
|
|
||||||
if (try_catch.HasCaught()) {
|
if (try_catch.HasCaught()) {
|
||||||
details = V8JS_SYM("<toString threw exception>");
|
details = V8JS_SYM("<toString threw exception>");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
v8::String::Utf8Value str(details);
|
v8::String::Utf8Value str(details);
|
||||||
const char *valstr = ToCString(str);
|
const char *valstr = ToCString(str);
|
||||||
size_t valstr_len = details->ToString()->Utf8Length();
|
size_t valstr_len = details->ToString()->Utf8Length();
|
||||||
@ -112,7 +123,7 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local<v8::Value> var, int leve
|
|||||||
}
|
}
|
||||||
else if (var->IsRegExp())
|
else if (var->IsRegExp())
|
||||||
{
|
{
|
||||||
php_printf("regexp(%s)\n", valstr);
|
php_printf("regexp(/%s/)\n", valstr);
|
||||||
}
|
}
|
||||||
else if (var->IsArray())
|
else if (var->IsArray())
|
||||||
{
|
{
|
||||||
@ -207,12 +218,100 @@ V8JS_METHOD(require)
|
|||||||
}
|
}
|
||||||
|
|
||||||
v8::String::Utf8Value module_id_v8(info[0]);
|
v8::String::Utf8Value module_id_v8(info[0]);
|
||||||
|
|
||||||
const char *module_id = ToCString(module_id_v8);
|
const char *module_id = ToCString(module_id_v8);
|
||||||
char *normalised_path = (char *)emalloc(PATH_MAX);
|
char *normalised_path, *module_name;
|
||||||
char *module_name = (char *)emalloc(PATH_MAX);
|
|
||||||
|
if (Z_TYPE(c->module_normaliser) == IS_NULL) {
|
||||||
|
// No custom normalisation routine registered, use internal one
|
||||||
|
normalised_path = (char *)emalloc(PATH_MAX);
|
||||||
|
module_name = (char *)emalloc(PATH_MAX);
|
||||||
|
|
||||||
v8js_commonjs_normalise_identifier(c->modules_base.back(), module_id, normalised_path, module_name);
|
v8js_commonjs_normalise_identifier(c->modules_base.back(), module_id, normalised_path, module_name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Call custom normaliser
|
||||||
|
int call_result;
|
||||||
|
zval params[2];
|
||||||
|
zval normaliser_result;
|
||||||
|
|
||||||
|
zend_try {
|
||||||
|
{
|
||||||
|
isolate->Exit();
|
||||||
|
v8::Unlocker unlocker(isolate);
|
||||||
|
|
||||||
|
ZVAL_STRING(¶ms[0], c->modules_base.back());
|
||||||
|
ZVAL_STRING(¶ms[1], module_id);
|
||||||
|
|
||||||
|
call_result = call_user_function_ex(EG(function_table), NULL, &c->module_normaliser,
|
||||||
|
&normaliser_result, 2, params, 0, NULL TSRMLS_CC);
|
||||||
|
}
|
||||||
|
|
||||||
|
isolate->Enter();
|
||||||
|
|
||||||
|
if (call_result == FAILURE) {
|
||||||
|
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module normaliser callback failed")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zend_catch {
|
||||||
|
v8js_terminate_execution(isolate);
|
||||||
|
V8JSG(fatal_error_abort) = 1;
|
||||||
|
call_result = FAILURE;
|
||||||
|
}
|
||||||
|
zend_end_try();
|
||||||
|
|
||||||
|
zval_dtor(¶ms[0]);
|
||||||
|
zval_dtor(¶ms[1]);
|
||||||
|
|
||||||
|
if(call_result == FAILURE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if an exception was thrown
|
||||||
|
if (EG(exception)) {
|
||||||
|
// Clear the PHP exception and throw it in V8 instead
|
||||||
|
zend_clear_exception(TSRMLS_C);
|
||||||
|
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module normaliser callback exception")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Z_TYPE(normaliser_result) != IS_ARRAY) {
|
||||||
|
zval_dtor(&normaliser_result);
|
||||||
|
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module normaliser didn't return an array")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashTable *ht = HASH_OF(&normaliser_result);
|
||||||
|
int num_elements = zend_hash_num_elements(ht);
|
||||||
|
|
||||||
|
if(num_elements != 2) {
|
||||||
|
zval_dtor(&normaliser_result);
|
||||||
|
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module normaliser expected to return array of 2 strings")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
zval *data;
|
||||||
|
ulong index = 0;
|
||||||
|
HashPosition pos;
|
||||||
|
|
||||||
|
ZEND_HASH_FOREACH_VAL(ht, data) {
|
||||||
|
if (Z_TYPE_P(data) != IS_STRING) {
|
||||||
|
convert_to_string(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(index++) {
|
||||||
|
case 0: // normalised path
|
||||||
|
normalised_path = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // normalised module id
|
||||||
|
module_name = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ZEND_HASH_FOREACH_END();
|
||||||
|
|
||||||
|
zval_dtor(&normaliser_result);
|
||||||
|
}
|
||||||
|
|
||||||
char *normalised_module_id = (char *)emalloc(strlen(normalised_path)+1+strlen(module_name)+1);
|
char *normalised_module_id = (char *)emalloc(strlen(normalised_path)+1+strlen(module_name)+1);
|
||||||
*normalised_module_id = 0;
|
*normalised_module_id = 0;
|
||||||
@ -252,19 +351,38 @@ V8JS_METHOD(require)
|
|||||||
// Callback to PHP to load the module code
|
// Callback to PHP to load the module code
|
||||||
|
|
||||||
zval module_code;
|
zval module_code;
|
||||||
|
int call_result;
|
||||||
zval params[1];
|
zval params[1];
|
||||||
ZVAL_STRING(¶ms[0], normalised_module_id);
|
|
||||||
|
|
||||||
if (FAILURE == call_user_function_ex(EG(function_table), NULL, &c->module_loader, &module_code, 1, params, 0, NULL TSRMLS_CC)) {
|
zend_try {
|
||||||
|
{
|
||||||
|
isolate->Exit();
|
||||||
|
v8::Unlocker unlocker(isolate);
|
||||||
|
|
||||||
|
ZVAL_STRING(¶ms[0], normalised_module_id);
|
||||||
|
call_result = call_user_function_ex(EG(function_table), NULL, &c->module_loader, &module_code, 1, params, 0, NULL TSRMLS_CC);
|
||||||
|
}
|
||||||
|
|
||||||
|
isolate->Enter();
|
||||||
|
|
||||||
|
if (call_result == FAILURE) {
|
||||||
|
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module loader callback failed")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zend_catch {
|
||||||
|
v8js_terminate_execution(isolate);
|
||||||
|
V8JSG(fatal_error_abort) = 1;
|
||||||
|
call_result = FAILURE;
|
||||||
|
}
|
||||||
|
zend_end_try();
|
||||||
|
|
||||||
zval_dtor(¶ms[0]);
|
zval_dtor(¶ms[0]);
|
||||||
|
|
||||||
|
if (call_result == FAILURE) {
|
||||||
efree(normalised_module_id);
|
efree(normalised_module_id);
|
||||||
efree(normalised_path);
|
efree(normalised_path);
|
||||||
|
|
||||||
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module loader callback failed")));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
zval_dtor(¶ms[0]);
|
|
||||||
|
|
||||||
// Check if an exception was thrown
|
// Check if an exception was thrown
|
||||||
if (EG(exception)) {
|
if (EG(exception)) {
|
||||||
@ -282,19 +400,10 @@ V8JS_METHOD(require)
|
|||||||
convert_to_string(&module_code);
|
convert_to_string(&module_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that some code has been returned
|
|
||||||
if (Z_STRLEN(module_code) == 0) {
|
|
||||||
zval_dtor(&module_code);
|
|
||||||
efree(normalised_module_id);
|
|
||||||
efree(normalised_path);
|
|
||||||
|
|
||||||
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module loader callback did not return code")));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a template for the global object and set the built-in global functions
|
// Create a template for the global object and set the built-in global functions
|
||||||
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
|
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
|
||||||
global->Set(V8JS_SYM("print"), v8::FunctionTemplate::New(isolate, V8JS_MN(print)), v8::ReadOnly);
|
global->Set(V8JS_SYM("print"), v8::FunctionTemplate::New(isolate, V8JS_MN(print)), v8::ReadOnly);
|
||||||
|
global->Set(V8JS_SYM("var_dump"), v8::FunctionTemplate::New(isolate, V8JS_MN(var_dump)), v8::ReadOnly);
|
||||||
global->Set(V8JS_SYM("sleep"), v8::FunctionTemplate::New(isolate, V8JS_MN(sleep)), v8::ReadOnly);
|
global->Set(V8JS_SYM("sleep"), v8::FunctionTemplate::New(isolate, V8JS_MN(sleep)), v8::ReadOnly);
|
||||||
global->Set(V8JS_SYM("require"), v8::FunctionTemplate::New(isolate, V8JS_MN(require), v8::External::New(isolate, c)), v8::ReadOnly);
|
global->Set(V8JS_SYM("require"), v8::FunctionTemplate::New(isolate, V8JS_MN(require), v8::External::New(isolate, c)), v8::ReadOnly);
|
||||||
|
|
||||||
@ -323,7 +432,7 @@ V8JS_METHOD(require)
|
|||||||
// Enter the module context
|
// Enter the module context
|
||||||
v8::Context::Scope scope(context);
|
v8::Context::Scope scope(context);
|
||||||
// Set script identifier
|
// Set script identifier
|
||||||
v8::Local<v8::String> sname = V8JS_SYM("require");
|
v8::Local<v8::String> sname = V8JS_STR(normalised_module_id);
|
||||||
|
|
||||||
v8::Local<v8::String> source = V8JS_ZSTR(Z_STR(module_code));
|
v8::Local<v8::String> source = V8JS_ZSTR(Z_STR(module_code));
|
||||||
zval_ptr_dtor(&module_code);
|
zval_ptr_dtor(&module_code);
|
||||||
|
@ -286,6 +286,7 @@ static int v8js_v8object_call_method(zend_string *method, zend_object *object, I
|
|||||||
|
|
||||||
v8::Local<v8::String> method_name = V8JS_ZSYM(method);
|
v8::Local<v8::String> method_name = V8JS_ZSYM(method);
|
||||||
v8::Local<v8::Object> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj)->ToObject();
|
v8::Local<v8::Object> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj)->ToObject();
|
||||||
|
v8::Local<v8::Object> thisObj;
|
||||||
v8::Local<v8::Function> cb;
|
v8::Local<v8::Function> cb;
|
||||||
|
|
||||||
if (method_name->Equals(V8JS_SYM(V8JS_V8_INVOKE_FUNC_NAME))) {
|
if (method_name->Equals(V8JS_SYM(V8JS_V8_INVOKE_FUNC_NAME))) {
|
||||||
@ -294,6 +295,15 @@ static int v8js_v8object_call_method(zend_string *method, zend_object *object, I
|
|||||||
cb = v8::Local<v8::Function>::Cast(v8obj->Get(method_name));
|
cb = v8::Local<v8::Function>::Cast(v8obj->Get(method_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a method is invoked on V8Object, then set the object itself as
|
||||||
|
// "this" on JS side. Otherwise fall back to global object.
|
||||||
|
if (obj->std.ce == php_ce_v8object) {
|
||||||
|
thisObj = v8obj;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
thisObj = V8JS_GLOBAL(isolate);
|
||||||
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> *jsArgv = static_cast<v8::Local<v8::Value> *>(alloca(sizeof(v8::Local<v8::Value>) * 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;
|
v8::Local<v8::Value> js_retval;
|
||||||
|
|
||||||
@ -302,7 +312,7 @@ static int v8js_v8object_call_method(zend_string *method, zend_object *object, I
|
|||||||
jsArgv[i] = v8::Local<v8::Value>::New(isolate, zval_to_v8js(&argv[i], isolate TSRMLS_CC));
|
jsArgv[i] = v8::Local<v8::Value>::New(isolate, zval_to_v8js(&argv[i], isolate TSRMLS_CC));
|
||||||
}
|
}
|
||||||
|
|
||||||
return cb->Call(V8JS_GLOBAL(isolate), argc, jsArgv);
|
return cb->Call(thisObj, argc, jsArgv);
|
||||||
};
|
};
|
||||||
|
|
||||||
v8js_v8_call(obj->ctx, &return_value, obj->flags, obj->ctx->time_limit, obj->ctx->memory_limit, v8_call TSRMLS_CC);
|
v8js_v8_call(obj->ctx, &return_value, obj->flags, obj->ctx->time_limit, obj->ctx->memory_limit, v8_call TSRMLS_CC);
|
||||||
|
Loading…
Reference in New Issue
Block a user