Comments (5)
Hi Sebastian, thanks for writing!
It would be nice to see your wrapper as I also have a one, though, it's heavily in progress at this time and I don't publish it to github yet.
As to modules, there are two types of it from API perspective: native and source-based module. With a native one it's pretty simple: you return some value for require()
call.
With source-based you may follow simple path: populate context's global
object with necessary exports
, require
, module
variable and then return modules.exports
result or you can do like node.js does - wrap module source code and evaluate it with passing necessary values for exports
, require
, module
and so on.
As for caching, it's pretty trivial, just maintain an array of normalized module name to what it exports and on consecutive calls return that value. This is how node.js does afair.
Here is very basic require()
implementation I use in one of tests - tests/V8FunctionTemplate_require_implementation.phpt
from php-v8.
Closing this issue for now as it not much to do at this time with it. If you feels there is something we missed here - please, drop a comment or feels free to open a new issue.
I'm also working on a library for php-v8 which also provides node-like modules functionality, however, no ETA at this time.
from php-v8.
Sorry for the late response. Thanks for the explanation, I see it's little bit more work than expected. I saw the the parallel v8 extension for php that they had a hook function which get the requested module as string passed and you have to return the code/path (don't know anymore). But I thought v8 do a little bit more since it's "module" flag.
I will post the wrapper ASAP here.
from php-v8.
The simplest implementation for require()
is available in tests/V8FunctionTemplate_require_implementation.phpt:26:41. While php-v8 is more low-level than v8js, there is a bit more to do pass data back to v8 runtime, but basically, if you replace tests/V8FunctionTemplate_require_implementation.phpt:33:37 with calling your external function, you should get very similar behavior to v8js.
I guess something like this should do the job:
Note, this is meta-code which may need to be polished in order to work
use V8\Value;
use V8\Context;
use V8\NumberValue;
use V8\StringValue;
use V8\ObjectValue;
use V8\Script;
use V8\ScriptOrigin;
use V8\FunctionTemplate;
use V8\FunctionCallbackInfo;
interface ModuleLoaderInterface {
public function load(string $name, Context $context) : Value;
}
class ModuleLoader implements ModuleLoaderInterface {
public function load(string $name, Context $context): Value
{
$isolate = $context->GetIsolate();
$module_is_native = 'TODO'; // figure it out
// here you can actually evaluate your script
if ($module_is_native) {
// in real life you will normally build necessary v8 value and return it
return new NumberValue($isolate, 42);
}
$path = $name;
$source = 'TODO'; // you will actually get it somehow from your db, filesystem or so
$wrapped_source =
"(function (exports, require, module, __filename, __dirname) {\n" .
$source . // you will actually get it somehow from your db, filesystem or so
"\n});";
$script = new Script($context, new StringValue($isolate, $wrapped_source), new ScriptOrigin($path, -1));
$func = $script->Run($context);
$exports = new ObjectValue($context);
$module_obj = new ObjectValue($context); // you actually have to build it properly - https://nodejs.org/api/modules.html#modules_the_module_object
$require = $context->GlobalObject()->Get($context, new StringValue($isolate, 'require');
$filename = new StringValue($isolate, $path);
$dirname = new StringValue($isolate, dirname($path));
// exports, require, module, __filename, __dirname
$arguments = [$exports, $require, $module_obj, $filename, $dirname];
return $func->Call($context, $func, $arguments);
}
}
$loader = new ModuleLoader();
$require_func_tpl_cache = new FunctionTemplate($isolate, function (FunctionCallbackInfo $info) use (&$loaded_cache, &$code, $loader) {
$context = $info->GetContext();
$module = $info->Arguments()[0]->ToString($context)->Value();
if (!isset($loaded_cache[$module])) {
$loaded_cache[$module] = $loader->load($module, $context);
}
$info->GetReturnValue()->Set($loaded_cache[$module]);
});
or even
class CacheableModuleLoader implements ModuleLoaderInterface
{
/**
* @var Value[]
*/
private $cache = [];
/**
* @var ModuleLoaderInterface
*/
private $loader;
public function __construct(ModuleLoaderInterface $loader)
{
$this->loader = $loader;
}
public function load(string $name, Context $context): Value
{
if (!isset($this->cache[$name])) {
$this->cache[$name] = $this->loader->load($name, $context);
}
return $this->cache[$name];
}
}
$loader = new CacheableModuleLoader(new ModuleLoader());
$require_func_tpl_cache = new FunctionTemplate($isolate, function (FunctionCallbackInfo $info) use (&$loaded_cache, &$code, $loader) {
$context = $info->GetContext();
$module = $info->Arguments()[0]->ToString($context)->Value();
$info->GetReturnValue()->Set($loader->load($module, $context));
});
from php-v8.
Thank you for bringing up this question. I plan to release higher level wrapper for php-v8 which should include modules support, so I'm closing this issue for now.
from php-v8.
Related Issues (20)
- Write docs on how to use caching and snapshots HOT 2
- Add support for BigInt API HOT 1
- Call to undefined method V8\ObjectValue::value() HOT 2
- Reflect changes to libv8 PPA layout
- Add support for near-heap-limit callback HOT 1
- PHP API HOT 2
- Rep 404 HOT 2
- Hello, can you tell me how to compile v8js? HOT 3
- what is the difference HOT 2
- Still maintained? HOT 1
- it is not installing - PHP 7.4 / umbuntu server 18.4 HOT 2
- Create and publish docker image for php-v8 HOT 2
- V8Js::executeString HOT 4
- v8::Proxy API has changed (V8 6.5.164) HOT 6
- Warning: Calling <<-EOS.undent is deprecated HOT 2
- Resolving/rejecting Promise in non-pending state leads to segfault HOT 2
- GetOwnPropertyNames and GetPropertyNames should return Strings
- Implement v8::Object::SetLazyDataProperty.
- Add BigInt64Array, BigUint64Array
- Script cache creating is broken after bumping v8 version to 6.6.313 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from php-v8.