JE是一个用纯 perl 编写的很好的 JavaScript 引擎。完美执行普通 JS 代码,他将 perl 子程序绑定(bind)到 JS 函数的能力非常棒。
require
函数中缺少什么,在“node.js”中实现了什么,并执行与 perl 的 require 类似的任务。
很高兴知道如何在 perl 中实现此类功能并将其绑定(bind)到 JE,例如在简单的骨架中:
use 5.016;
use warnings;
use Path::Tiny;
use JE::Destroyer;
use JE;
my $jslib = path("./jslib");
my $j = new JE;
$j->new_function("say", sub { say @_ }); # the "say" in the JS
$j->new_function("require", sub { # the "require"
my $source = $jslib->child($_[0])->slurp_utf8; #read the source from some file
#how to implement the require ?
#e.g. what JE object should be created and what to bind to it?
});
知道 node.js
的 require
函数是如何在 C 中实现的,以及如何在 perl 中实现吗?
编辑
对于添加更扩展骨架的更精确示例:
- 文件
./reqtest.js
(主程序)
console.log("start");
p = require('adder');
console.log(p.add(2,3));
- 文件
./node_modules/adder.js
(在“node_modules”中 - 用于node.js
测试)
exports.add = function() {
var sum = 0, i = 0, args = arguments, l = args.length;
while (i < l) {
sum += args[i++];
}
return sum;
};
运行上面的作为
node reqtest.js
打印
start
5
因此,它正确地需要 adder.js
并返回对象,但是
使用以下 perl/JE 脚本运行它:
use 5.016;
use warnings;
use JE::Destroyer;
use JE;
use Scalar::Util qw( weaken );
use Path::Tiny;
use PIR;
my $script = path("reqtest.js")->slurp_utf8;
my $j = new JE;
$j->{console} = {};
$j->{console}->new_function("log", sub { say @_ });
{
weaken(my $j = $j);
$j->new_function(require => sub {
my $source = get_source($_[0]);
$j->eval($source) if $source;
});
}
$j->eval($script);#eval the main script
JE::Destroyer::destroy($j);
undef $j;
#extremelly simplyfied
sub get_source {
my $name = shift;
return path("node_modules")->child("$name.js")->slurp_utf8;
}
仅打印:
start
因此,require
的“简单$j->eval($source)
实现不遵循CommonJS
模块规范- 它需要更多东西。
最佳答案
经过一番研究,我创建了以下(极其简化的)解决方案:
use 5.016;
use warnings;
use JE::Destroyer;
use JE;
use Scalar::Util qw( weaken );
use Path::Tiny;
my $script = path("reqtest.js")->slurp_utf8;
my $j = new JE;
$j->{console} = {};
$j->{console}->new_function("log", sub { say @_ });
{
weaken(my $j = $j); #based on ikegami's previous answer
$j->new_function(require => sub {
my $source = get_source($_[0]);
my $code = new JE::Object::Function $j, qw(exports), $source;
my $exports = $j->{Object};
$code->($exports);
return $exports;
});
}
$j->eval($script);#eval the main script
JE::Destroyer::destroy($j);
undef $j;
# extremelly simplyfied code search
# the real code-search for the requide("some") should try the following
# some.js some/index.js some.json some/index.json
# for the defined search-paths.
sub get_source {
my $name = shift;
return path("node_modules")->child("$name.js")->slurp_utf8;
}
上面是 CommonJS 要求的最短可能实现,并且打印与问题中示例的 node.js
相同
start
5
当然,需要很多额外的工作(例如代码缓存)之类的,但最小的框架是可行的。
关于javascript - 如何在 perl 的 JE 引擎中实现 "JS' s require"函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30982898/