mirror of
https://github.com/phpv8/v8js.git
synced 2024-12-22 12:51:52 +00:00
Merge remote-tracking branch 'remotes/stesie/global-object' into php7
This commit is contained in:
commit
278b4fbedb
28
tests/commonjs_node_compat_001.phpt
Normal file
28
tests/commonjs_node_compat_001.phpt
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8Js::setModuleLoader : this === module.exports
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
$v8->setModuleLoader(function ($moduleName) {
|
||||||
|
return <<<'EOJS'
|
||||||
|
var_dump(this === global);
|
||||||
|
var_dump(this === module.exports);
|
||||||
|
EOJS
|
||||||
|
;
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->executeString(<<<'EOJS'
|
||||||
|
var result = require('foo');
|
||||||
|
EOJS
|
||||||
|
);
|
||||||
|
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
bool(false)
|
||||||
|
bool(true)
|
||||||
|
===EOF===
|
29
tests/commonjs_node_compat_002.phpt
Normal file
29
tests/commonjs_node_compat_002.phpt
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8Js::setModuleLoader : modules can return arbitrary values
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
$v8->setModuleLoader(function ($moduleName) {
|
||||||
|
return <<<'EOJS'
|
||||||
|
module.exports = 23;
|
||||||
|
EOJS
|
||||||
|
;
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->executeString(<<<'EOJS'
|
||||||
|
var result = require('foo');
|
||||||
|
var_dump(typeof result);
|
||||||
|
var_dump(result);
|
||||||
|
EOJS
|
||||||
|
);
|
||||||
|
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
string(6) "number"
|
||||||
|
int(23)
|
||||||
|
===EOF===
|
27
tests/commonjs_node_compat_003.phpt
Normal file
27
tests/commonjs_node_compat_003.phpt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8Js::setModuleLoader : delete module.exports yields undefined
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
$v8->setModuleLoader(function ($moduleName) {
|
||||||
|
return <<<'EOJS'
|
||||||
|
delete module.exports;
|
||||||
|
EOJS
|
||||||
|
;
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->executeString(<<<'EOJS'
|
||||||
|
var result = require('foo');
|
||||||
|
var_dump(typeof result);
|
||||||
|
EOJS
|
||||||
|
);
|
||||||
|
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
string(9) "undefined"
|
||||||
|
===EOF===
|
41
tests/commonjs_node_compat_basic.phpt
Normal file
41
tests/commonjs_node_compat_basic.phpt
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8Js::setModuleLoader : exports/module.exports behaviour
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
$v8->setModuleLoader(function ($moduleName) {
|
||||||
|
return <<<'EOJS'
|
||||||
|
var_dump(typeof exports);
|
||||||
|
var_dump(typeof module.exports);
|
||||||
|
|
||||||
|
// for compatibility both should be linked
|
||||||
|
var_dump(exports === module.exports);
|
||||||
|
|
||||||
|
exports = { number: 23 };
|
||||||
|
module.exports = { number: 42 };
|
||||||
|
EOJS
|
||||||
|
;
|
||||||
|
});
|
||||||
|
|
||||||
|
$v8->executeString(<<<'EOJS'
|
||||||
|
var result = require('foo');
|
||||||
|
|
||||||
|
// expect module.exports value to be picked up
|
||||||
|
var_dump(typeof result);
|
||||||
|
var_dump(result.number);
|
||||||
|
EOJS
|
||||||
|
);
|
||||||
|
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
string(6) "object"
|
||||||
|
string(6) "object"
|
||||||
|
bool(true)
|
||||||
|
string(6) "object"
|
||||||
|
int(42)
|
||||||
|
===EOF===
|
25
tests/global_object_basic.phpt
Normal file
25
tests/global_object_basic.phpt
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8Js::executeString : Global scope links global object
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$JS = <<< EOT
|
||||||
|
var_dump(typeof global);
|
||||||
|
var_dump(global.var_dump === var_dump);
|
||||||
|
|
||||||
|
// also this is equal to global scope, at least in global execution context
|
||||||
|
// (i.e. off modules)
|
||||||
|
var_dump(this === global);
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
$v8->executeString($JS);
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
string(6) "object"
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
===EOF===
|
@ -113,21 +113,21 @@ static void v8js_free_storage(zend_object *object) /* {{{ */
|
|||||||
c->array_tmpl.~Persistent();
|
c->array_tmpl.~Persistent();
|
||||||
|
|
||||||
/* Clear persistent call_impl & method_tmpls templates */
|
/* Clear persistent call_impl & method_tmpls templates */
|
||||||
for (std::map<v8js_tmpl_t *, v8js_tmpl_t>::iterator it = c->call_impls.begin();
|
for (std::map<v8js_function_tmpl_t *, v8js_function_tmpl_t>::iterator it = c->call_impls.begin();
|
||||||
it != c->call_impls.end(); ++it) {
|
it != c->call_impls.end(); ++it) {
|
||||||
// No need to free it->first, as it is stored in c->template_cache and freed below
|
// No need to free it->first, as it is stored in c->template_cache and freed below
|
||||||
it->second.Reset();
|
it->second.Reset();
|
||||||
}
|
}
|
||||||
c->call_impls.~map();
|
c->call_impls.~map();
|
||||||
|
|
||||||
for (std::map<zend_function *, v8js_tmpl_t>::iterator it = c->method_tmpls.begin();
|
for (std::map<zend_function *, v8js_function_tmpl_t>::iterator it = c->method_tmpls.begin();
|
||||||
it != c->method_tmpls.end(); ++it) {
|
it != c->method_tmpls.end(); ++it) {
|
||||||
it->second.Reset();
|
it->second.Reset();
|
||||||
}
|
}
|
||||||
c->method_tmpls.~map();
|
c->method_tmpls.~map();
|
||||||
|
|
||||||
/* Clear persistent handles in template cache */
|
/* Clear persistent handles in template cache */
|
||||||
for (std::map<const zend_string *,v8js_tmpl_t>::iterator it = c->template_cache.begin();
|
for (std::map<const zend_string *,v8js_function_tmpl_t>::iterator it = c->template_cache.begin();
|
||||||
it != c->template_cache.end(); ++it) {
|
it != c->template_cache.end(); ++it) {
|
||||||
it->second.Reset();
|
it->second.Reset();
|
||||||
}
|
}
|
||||||
@ -158,9 +158,9 @@ static void v8js_free_storage(zend_object *object) /* {{{ */
|
|||||||
}
|
}
|
||||||
c->weak_objects.~map();
|
c->weak_objects.~map();
|
||||||
|
|
||||||
for (std::map<v8js_tmpl_t *, v8js_persistent_obj_t>::iterator it = c->weak_closures.begin();
|
for (std::map<v8js_function_tmpl_t *, v8js_persistent_obj_t>::iterator it = c->weak_closures.begin();
|
||||||
it != c->weak_closures.end(); ++it) {
|
it != c->weak_closures.end(); ++it) {
|
||||||
v8js_tmpl_t *persist_tpl_ = it->first;
|
v8js_function_tmpl_t *persist_tpl_ = it->first;
|
||||||
persist_tpl_->Reset();
|
persist_tpl_->Reset();
|
||||||
delete persist_tpl_;
|
delete persist_tpl_;
|
||||||
it->second.Reset();
|
it->second.Reset();
|
||||||
@ -182,7 +182,7 @@ static void v8js_free_storage(zend_object *object) /* {{{ */
|
|||||||
c->script_objects.~vector();
|
c->script_objects.~vector();
|
||||||
|
|
||||||
/* Clear persistent handles in module cache */
|
/* Clear persistent handles in module cache */
|
||||||
for (std::map<char *, v8js_persistent_obj_t>::iterator it = c->modules_loaded.begin();
|
for (std::map<char *, v8js_persistent_value_t>::iterator it = c->modules_loaded.begin();
|
||||||
it != c->modules_loaded.end(); ++it) {
|
it != c->modules_loaded.end(); ++it) {
|
||||||
efree(it->first);
|
efree(it->first);
|
||||||
it->second.Reset();
|
it->second.Reset();
|
||||||
@ -227,15 +227,15 @@ static zend_object* v8js_new(zend_class_entry *ce) /* {{{ */
|
|||||||
|
|
||||||
new(&c->modules_stack) std::vector<char*>();
|
new(&c->modules_stack) std::vector<char*>();
|
||||||
new(&c->modules_base) std::vector<char*>();
|
new(&c->modules_base) std::vector<char*>();
|
||||||
new(&c->modules_loaded) std::map<char *, v8js_persistent_obj_t, cmp_str>;
|
new(&c->modules_loaded) std::map<char *, v8js_persistent_value_t, cmp_str>;
|
||||||
|
|
||||||
new(&c->template_cache) std::map<const zend_string *,v8js_tmpl_t>();
|
new(&c->template_cache) std::map<const zend_string *,v8js_function_tmpl_t>();
|
||||||
new(&c->accessor_list) std::vector<v8js_accessor_ctx *>();
|
new(&c->accessor_list) std::vector<v8js_accessor_ctx *>();
|
||||||
|
|
||||||
new(&c->weak_closures) std::map<v8js_tmpl_t *, v8js_persistent_obj_t>();
|
new(&c->weak_closures) std::map<v8js_function_tmpl_t *, v8js_persistent_obj_t>();
|
||||||
new(&c->weak_objects) std::map<zend_object *, v8js_persistent_obj_t>();
|
new(&c->weak_objects) std::map<zend_object *, v8js_persistent_obj_t>();
|
||||||
new(&c->call_impls) std::map<v8js_tmpl_t *, v8js_tmpl_t>();
|
new(&c->call_impls) std::map<v8js_function_tmpl_t *, v8js_function_tmpl_t>();
|
||||||
new(&c->method_tmpls) std::map<zend_function *, v8js_tmpl_t>();
|
new(&c->method_tmpls) std::map<zend_function *, v8js_function_tmpl_t>();
|
||||||
|
|
||||||
new(&c->v8js_v8objects) std::list<v8js_v8object *>();
|
new(&c->v8js_v8objects) std::list<v8js_v8object *>();
|
||||||
new(&c->script_objects) std::vector<v8js_script *>();
|
new(&c->script_objects) std::vector<v8js_script *>();
|
||||||
@ -434,16 +434,14 @@ static PHP_METHOD(V8Js, __construct)
|
|||||||
/* Create global template for global object */
|
/* Create global template for global object */
|
||||||
// Now we are using multiple isolates this needs to be created for every context
|
// Now we are using multiple isolates this needs to be created for every context
|
||||||
|
|
||||||
v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(c->isolate, 0);
|
v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(c->isolate);
|
||||||
|
c->global_template.Reset(isolate, global_template);
|
||||||
tpl->SetClassName(V8JS_SYM("V8Js"));
|
|
||||||
c->global_template.Reset(isolate, tpl);
|
|
||||||
|
|
||||||
/* Register builtin methods */
|
/* Register builtin methods */
|
||||||
v8js_register_methods(tpl->InstanceTemplate(), c);
|
v8js_register_methods(global_template, c);
|
||||||
|
|
||||||
/* Create context */
|
/* Create context */
|
||||||
v8::Local<v8::Context> context = v8::Context::New(isolate, &extension_conf, tpl->InstanceTemplate());
|
v8::Local<v8::Context> context = v8::Context::New(isolate, &extension_conf, global_template);
|
||||||
|
|
||||||
if (exts) {
|
if (exts) {
|
||||||
v8js_free_ext_strarr(exts, exts_count);
|
v8js_free_ext_strarr(exts, exts_count);
|
||||||
@ -458,6 +456,7 @@ static PHP_METHOD(V8Js, __construct)
|
|||||||
}
|
}
|
||||||
|
|
||||||
context->SetAlignedPointerInEmbedderData(1, c);
|
context->SetAlignedPointerInEmbedderData(1, c);
|
||||||
|
context->Global()->Set(context, V8JS_SYM("global"), context->Global());
|
||||||
c->context.Reset(isolate, context);
|
c->context.Reset(isolate, context);
|
||||||
|
|
||||||
/* Enter context */
|
/* Enter context */
|
||||||
@ -598,7 +597,7 @@ static PHP_METHOD(V8Js, __construct)
|
|||||||
ft = v8::FunctionTemplate::New(isolate, v8js_php_callback,
|
ft = v8::FunctionTemplate::New(isolate, v8js_php_callback,
|
||||||
v8::External::New((isolate), method_ptr));
|
v8::External::New((isolate), method_ptr));
|
||||||
// @fixme add/check Signature v8::Signature::New((isolate), tmpl));
|
// @fixme add/check Signature v8::Signature::New((isolate), tmpl));
|
||||||
v8js_tmpl_t *persistent_ft = &c->method_tmpls[method_ptr];
|
v8js_function_tmpl_t *persistent_ft = &c->method_tmpls[method_ptr];
|
||||||
persistent_ft->Reset(isolate, ft);
|
persistent_ft->Reset(isolate, ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
v8js_class.h
18
v8js_class.h
@ -17,8 +17,10 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Abbreviate long type names */
|
/* Abbreviate long type names */
|
||||||
typedef v8::Persistent<v8::FunctionTemplate, v8::CopyablePersistentTraits<v8::FunctionTemplate> > v8js_tmpl_t;
|
typedef v8::Persistent<v8::FunctionTemplate, v8::CopyablePersistentTraits<v8::FunctionTemplate> > v8js_function_tmpl_t;
|
||||||
|
typedef v8::Persistent<v8::ObjectTemplate, v8::CopyablePersistentTraits<v8::ObjectTemplate> > v8js_object_tmpl_t;
|
||||||
typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> > v8js_persistent_obj_t;
|
typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> > v8js_persistent_obj_t;
|
||||||
|
typedef v8::Persistent<v8::Value, v8::CopyablePersistentTraits<v8::Value> > v8js_persistent_value_t;
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
struct v8js_v8object;
|
struct v8js_v8object;
|
||||||
@ -48,21 +50,21 @@ struct v8js_ctx {
|
|||||||
bool memory_limit_hit;
|
bool memory_limit_hit;
|
||||||
long average_object_size;
|
long average_object_size;
|
||||||
|
|
||||||
v8js_tmpl_t global_template;
|
v8js_object_tmpl_t global_template;
|
||||||
v8js_tmpl_t array_tmpl;
|
v8js_function_tmpl_t array_tmpl;
|
||||||
|
|
||||||
zval module_normaliser;
|
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_value_t, cmp_str> modules_loaded;
|
||||||
std::map<const zend_string *,v8js_tmpl_t> template_cache;
|
std::map<const zend_string *,v8js_function_tmpl_t> template_cache;
|
||||||
|
|
||||||
std::map<zend_object *, v8js_persistent_obj_t> weak_objects;
|
std::map<zend_object *, v8js_persistent_obj_t> weak_objects;
|
||||||
std::map<v8js_tmpl_t *, v8js_persistent_obj_t> weak_closures;
|
std::map<v8js_function_tmpl_t *, v8js_persistent_obj_t> weak_closures;
|
||||||
std::map<v8js_tmpl_t *, v8js_tmpl_t> call_impls;
|
std::map<v8js_function_tmpl_t *, v8js_function_tmpl_t> call_impls;
|
||||||
std::map<zend_function *, v8js_tmpl_t> method_tmpls;
|
std::map<zend_function *, v8js_function_tmpl_t> method_tmpls;
|
||||||
|
|
||||||
std::list<v8js_v8object *> v8js_v8objects;
|
std::list<v8js_v8object *> v8js_v8objects;
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ V8JS_METHOD(require)
|
|||||||
|
|
||||||
// If we have already loaded and cached this module then use it
|
// If we have already loaded and cached this module then use it
|
||||||
if (c->modules_loaded.count(normalised_module_id) > 0) {
|
if (c->modules_loaded.count(normalised_module_id) > 0) {
|
||||||
v8::Persistent<v8::Object> newobj;
|
v8::Persistent<v8::Value> newobj;
|
||||||
newobj.Reset(isolate, c->modules_loaded[normalised_module_id]);
|
newobj.Reset(isolate, c->modules_loaded[normalised_module_id]);
|
||||||
info.GetReturnValue().Set(newobj);
|
info.GetReturnValue().Set(newobj);
|
||||||
|
|
||||||
@ -400,24 +400,7 @@ V8JS_METHOD(require)
|
|||||||
convert_to_string(&module_code);
|
convert_to_string(&module_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a template for the global object and set the built-in global functions
|
v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate, c->context);
|
||||||
v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
|
|
||||||
global_template->Set(V8JS_SYM("print"), v8::FunctionTemplate::New(isolate, V8JS_MN(print)), v8::ReadOnly);
|
|
||||||
global_template->Set(V8JS_SYM("var_dump"), v8::FunctionTemplate::New(isolate, V8JS_MN(var_dump)), v8::ReadOnly);
|
|
||||||
global_template->Set(V8JS_SYM("sleep"), v8::FunctionTemplate::New(isolate, V8JS_MN(sleep)), v8::ReadOnly);
|
|
||||||
global_template->Set(V8JS_SYM("require"), v8::FunctionTemplate::New(isolate, V8JS_MN(require), v8::External::New(isolate, c)), v8::ReadOnly);
|
|
||||||
|
|
||||||
// Add the exports object in which the module can return its API
|
|
||||||
v8::Local<v8::ObjectTemplate> exports_template = v8::ObjectTemplate::New(isolate);
|
|
||||||
global_template->Set(V8JS_SYM("exports"), exports_template);
|
|
||||||
|
|
||||||
// Add the module object in which the module can have more fine-grained control over what it can return
|
|
||||||
v8::Local<v8::ObjectTemplate> module_template = v8::ObjectTemplate::New(isolate);
|
|
||||||
module_template->Set(V8JS_SYM("id"), V8JS_STR(normalised_module_id));
|
|
||||||
global_template->Set(V8JS_SYM("module"), module_template);
|
|
||||||
|
|
||||||
// Each module gets its own context so different modules do not affect each other
|
|
||||||
v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate, v8::Context::New(isolate, NULL, global_template));
|
|
||||||
|
|
||||||
// Catch JS exceptions
|
// Catch JS exceptions
|
||||||
v8::TryCatch try_catch(isolate);
|
v8::TryCatch try_catch(isolate);
|
||||||
@ -429,6 +412,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_STR(normalised_module_id);
|
v8::Local<v8::String> sname = V8JS_STR(normalised_module_id);
|
||||||
|
|
||||||
@ -438,9 +422,12 @@ V8JS_METHOD(require)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::String> source = V8JS_STRL(Z_STRVAL(module_code), static_cast<int>(Z_STRLEN(module_code)));
|
v8::Local<v8::String> source = V8JS_ZSTR(Z_STR(module_code));
|
||||||
zval_ptr_dtor(&module_code);
|
zval_ptr_dtor(&module_code);
|
||||||
|
|
||||||
|
source = v8::String::Concat(V8JS_SYM("(function (exports, module) {"), source);
|
||||||
|
source = v8::String::Concat(source, V8JS_SYM("\n});"));
|
||||||
|
|
||||||
// Create and compile script
|
// Create and compile script
|
||||||
v8::Local<v8::Script> script = v8::Script::Compile(source, sname);
|
v8::Local<v8::Script> script = v8::Script::Compile(source, sname);
|
||||||
|
|
||||||
@ -454,11 +441,29 @@ V8JS_METHOD(require)
|
|||||||
|
|
||||||
// Add this module and path to the stack
|
// Add this module and path to the stack
|
||||||
c->modules_stack.push_back(normalised_module_id);
|
c->modules_stack.push_back(normalised_module_id);
|
||||||
|
|
||||||
c->modules_base.push_back(normalised_path);
|
c->modules_base.push_back(normalised_path);
|
||||||
|
|
||||||
// Run script
|
// Run script to evaluate closure
|
||||||
script->Run();
|
v8::Local<v8::Value> module_function = script->Run();
|
||||||
|
|
||||||
|
// Prepare exports & module object
|
||||||
|
v8::Local<v8::Object> exports = v8::Object::New(isolate);
|
||||||
|
|
||||||
|
v8::Local<v8::Object> module = v8::Object::New(isolate);
|
||||||
|
module->Set(V8JS_SYM("id"), V8JS_STR(normalised_module_id));
|
||||||
|
module->Set(V8JS_SYM("exports"), exports);
|
||||||
|
|
||||||
|
if (module_function->IsFunction()) {
|
||||||
|
v8::Local<v8::Value> *jsArgv = static_cast<v8::Local<v8::Value> *>(alloca(2 * sizeof(v8::Local<v8::Value>)));
|
||||||
|
new(&jsArgv[0]) v8::Local<v8::Value>;
|
||||||
|
jsArgv[0] = exports;
|
||||||
|
|
||||||
|
new(&jsArgv[1]) v8::Local<v8::Value>;
|
||||||
|
jsArgv[1] = module;
|
||||||
|
|
||||||
|
// actually call the module
|
||||||
|
v8::Local<v8::Function>::Cast(module_function)->Call(exports, 2, jsArgv);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove this module and path from the stack
|
// Remove this module and path from the stack
|
||||||
c->modules_stack.pop_back();
|
c->modules_stack.pop_back();
|
||||||
@ -466,6 +471,12 @@ V8JS_METHOD(require)
|
|||||||
|
|
||||||
efree(normalised_path);
|
efree(normalised_path);
|
||||||
|
|
||||||
|
if (!module_function->IsFunction()) {
|
||||||
|
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Wrapped module script failed to return function")));
|
||||||
|
efree(normalised_module_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Script possibly terminated, return immediately
|
// Script possibly terminated, return immediately
|
||||||
if (!try_catch.CanContinue()) {
|
if (!try_catch.CanContinue()) {
|
||||||
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module script compile failed")));
|
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module script compile failed")));
|
||||||
@ -481,19 +492,12 @@ V8JS_METHOD(require)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Object> newobj;
|
v8::Local<v8::Value> newobj;
|
||||||
|
|
||||||
// Cache the module so it doesn't need to be compiled and run again
|
// Cache the module so it doesn't need to be compiled and run again
|
||||||
// Ensure compatibility with CommonJS implementations such as NodeJS by playing nicely with module.exports and exports
|
// Ensure compatibility with CommonJS implementations such as NodeJS by playing nicely with module.exports and exports
|
||||||
if (context->Global()->Has(V8JS_SYM("module"))
|
if (module->Has(V8JS_SYM("exports"))) {
|
||||||
&& context->Global()->Get(V8JS_SYM("module"))->IsObject()
|
newobj = module->Get(V8JS_SYM("exports"));
|
||||||
&& context->Global()->Get(V8JS_SYM("module"))->ToObject()->Has(V8JS_SYM("exports"))
|
|
||||||
&& context->Global()->Get(V8JS_SYM("module"))->ToObject()->Get(V8JS_SYM("exports"))->IsObject()) {
|
|
||||||
// If module.exports has been set then we cache this arbitrary value...
|
|
||||||
newobj = context->Global()->Get(V8JS_SYM("module"))->ToObject()->Get(V8JS_SYM("exports"))->ToObject();
|
|
||||||
} else {
|
|
||||||
// ...otherwise we cache the exports object itself
|
|
||||||
newobj = context->Global()->Get(V8JS_SYM("exports"))->ToObject();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c->modules_loaded[normalised_module_id].Reset(isolate, newobj);
|
c->modules_loaded[normalised_module_id].Reset(isolate, newobj);
|
||||||
|
@ -291,10 +291,10 @@ static void v8js_weak_object_callback(const v8::WeakCallbackInfo<zend_object> &d
|
|||||||
isolate->AdjustAmountOfExternalAllocatedMemory(-ctx->average_object_size);
|
isolate->AdjustAmountOfExternalAllocatedMemory(-ctx->average_object_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void v8js_weak_closure_callback(const v8::WeakCallbackInfo<v8js_tmpl_t> &data) {
|
static void v8js_weak_closure_callback(const v8::WeakCallbackInfo<v8js_function_tmpl_t> &data) {
|
||||||
v8::Isolate *isolate = data.GetIsolate();
|
v8::Isolate *isolate = data.GetIsolate();
|
||||||
|
|
||||||
v8js_tmpl_t *persist_tpl_ = data.GetParameter();
|
v8js_function_tmpl_t *persist_tpl_ = data.GetParameter();
|
||||||
persist_tpl_->Reset();
|
persist_tpl_->Reset();
|
||||||
delete persist_tpl_;
|
delete persist_tpl_;
|
||||||
|
|
||||||
@ -559,7 +559,7 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo<v8::Value>& info)
|
|||||||
|
|
||||||
v8::Local<v8::FunctionTemplate> tmpl =
|
v8::Local<v8::FunctionTemplate> tmpl =
|
||||||
v8::Local<v8::FunctionTemplate>::New
|
v8::Local<v8::FunctionTemplate>::New
|
||||||
(isolate, *reinterpret_cast<v8js_tmpl_t *>(self->GetAlignedPointerFromInternalField(0)));
|
(isolate, *reinterpret_cast<v8js_function_tmpl_t *>(self->GetAlignedPointerFromInternalField(0)));
|
||||||
// use v8js_php_callback to actually execute the method
|
// use v8js_php_callback to actually execute the method
|
||||||
v8::Local<v8::Function> cb = PHP_V8JS_CALLBACK(isolate, method_ptr, tmpl);
|
v8::Local<v8::Function> cb = PHP_V8JS_CALLBACK(isolate, method_ptr, tmpl);
|
||||||
uint32_t i, argc = args->Length();
|
uint32_t i, argc = args->Length();
|
||||||
@ -597,7 +597,7 @@ v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> property
|
|||||||
zval zobject;
|
zval zobject;
|
||||||
ZVAL_OBJ(&zobject, object);
|
ZVAL_OBJ(&zobject, object);
|
||||||
|
|
||||||
v8js_tmpl_t *tmpl_ptr = reinterpret_cast<v8js_tmpl_t *>(self->GetAlignedPointerFromInternalField(0));
|
v8js_function_tmpl_t *tmpl_ptr = reinterpret_cast<v8js_function_tmpl_t *>(self->GetAlignedPointerFromInternalField(0));
|
||||||
v8::Local<v8::FunctionTemplate> tmpl = v8::Local<v8::FunctionTemplate>::New(isolate, *tmpl_ptr);
|
v8::Local<v8::FunctionTemplate> tmpl = v8::Local<v8::FunctionTemplate>::New(isolate, *tmpl_ptr);
|
||||||
ce = scope = object->ce;
|
ce = scope = object->ce;
|
||||||
|
|
||||||
@ -641,7 +641,7 @@ v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> property
|
|||||||
ft = v8::FunctionTemplate::New(isolate,
|
ft = v8::FunctionTemplate::New(isolate,
|
||||||
v8js_fake_call_impl, V8JS_NULL,
|
v8js_fake_call_impl, V8JS_NULL,
|
||||||
v8::Signature::New(isolate, tmpl));
|
v8::Signature::New(isolate, tmpl));
|
||||||
v8js_tmpl_t *persistent_ft = &ctx->call_impls[tmpl_ptr];
|
v8js_function_tmpl_t *persistent_ft = &ctx->call_impls[tmpl_ptr];
|
||||||
persistent_ft->Reset(isolate, ft);
|
persistent_ft->Reset(isolate, ft);
|
||||||
}
|
}
|
||||||
v8::Local<v8::Function> cb = ft->GetFunction();
|
v8::Local<v8::Function> cb = ft->GetFunction();
|
||||||
@ -657,7 +657,7 @@ v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> property
|
|||||||
ft = v8::FunctionTemplate::New(isolate, v8js_php_callback,
|
ft = v8::FunctionTemplate::New(isolate, v8js_php_callback,
|
||||||
v8::External::New((isolate), method_ptr),
|
v8::External::New((isolate), method_ptr),
|
||||||
v8::Signature::New((isolate), tmpl));
|
v8::Signature::New((isolate), tmpl));
|
||||||
v8js_tmpl_t *persistent_ft = &ctx->method_tmpls[method_ptr];
|
v8js_function_tmpl_t *persistent_ft = &ctx->method_tmpls[method_ptr];
|
||||||
persistent_ft->Reset(isolate, ft);
|
persistent_ft->Reset(isolate, ft);
|
||||||
}
|
}
|
||||||
ret_value = ft->GetFunction();
|
ret_value = ft->GetFunction();
|
||||||
@ -814,7 +814,7 @@ static v8::MaybeLocal<v8::Object> v8js_wrap_object(v8::Isolate *isolate, zend_cl
|
|||||||
{
|
{
|
||||||
v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
|
v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
|
||||||
v8::Local<v8::FunctionTemplate> new_tpl;
|
v8::Local<v8::FunctionTemplate> new_tpl;
|
||||||
v8js_tmpl_t *persist_tpl_;
|
v8js_function_tmpl_t *persist_tpl_;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new_tpl = v8::Local<v8::FunctionTemplate>::New
|
new_tpl = v8::Local<v8::FunctionTemplate>::New
|
||||||
@ -835,7 +835,7 @@ static v8::MaybeLocal<v8::Object> v8js_wrap_object(v8::Isolate *isolate, zend_cl
|
|||||||
|
|
||||||
if (ce == zend_ce_closure) {
|
if (ce == zend_ce_closure) {
|
||||||
/* Got a closure, mustn't cache ... */
|
/* Got a closure, mustn't cache ... */
|
||||||
persist_tpl_ = new v8js_tmpl_t(isolate, new_tpl);
|
persist_tpl_ = new v8js_function_tmpl_t(isolate, new_tpl);
|
||||||
/* We'll free persist_tpl_ via v8js_weak_closure_callback, below */
|
/* We'll free persist_tpl_ via v8js_weak_closure_callback, below */
|
||||||
new_tpl->InstanceTemplate()->SetCallAsFunctionHandler(v8js_php_callback);
|
new_tpl->InstanceTemplate()->SetCallAsFunctionHandler(v8js_php_callback);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user