零点数
Perl 5 编译为 Web Assembly. 在浏览器或其他JavaScript环境中运行Perl脚本而无需安装Perl.
建造在 零点。 。 。 .
特征
- 在浏览器、Node.js、Deno和Bun运行 Perl 5
- 脚本和数据文件的虚拟文件系统
- JavaScript 和 Perl 之间的双向数据交换
- 从 Perl 调用 JavaScript 函数
- 从 JavaScript 调用 Perl 函数
- 环境变量支持
- 输出捕获(出/出)
- 包含类型脚本类型定义
安装
npm install @6over3/zeroperl-ts
# or
bun add @6over3/zeroperl-ts
或者,为了 浏览器使用,将 0perl WASM 二进制复制到您的本地网站(以避免 CORS 出错).
# The -L option allows the CDN to redirect to the latest version
curl -L -O https://esm.sh/@6over3/zeroperl-ts/zeroperl.wasm
快速启动
import { ZeroPerl } from '@6over3/zeroperl-ts';
const perl = await ZeroPerl.create();
await perl.eval('print "Hello, World!\\n"');
perl.flush(); // Required to see output
perl.dispose();
输出缓冲
Perl 缓冲器默认输出 。 选择一个方法 :
备选案文1:呼叫 flush() 打印后
await perl.eval('print "Hello!\\n"');
perl.flush();
选项 2: 在 Perl 中启用自定义
await perl.eval(`
$| = 1; # Enable autoflush
print "Hello!\\n";
`);
基本用途
评价 Perl 代码
import { ZeroPerl } from '@6over3/zeroperl-ts';
const perl = await ZeroPerl.create();
const result = await perl.eval(`
$| = 1;
my $x = 42;
print "The answer is $x\\n";
`);
if (!result.success) {
console.error('Error:', result.error);
}
perl.dispose();
抓取输出
let output = '';
const perl = await ZeroPerl.create({
stdout: (data) => {
output += typeof data === 'string' ? data : new TextDecoder().decode(data);
}
});
await perl.eval(`
$| = 1;
print "Line 1\\n";
print "Line 2\\n";
`);
console.log(output);
// Output:
// Line 1
// Line 2
perl.dispose();
交换数据
const perl = await ZeroPerl.create();
// JavaScript to Perl
perl.setVariable('name', 'Alice');
perl.setVariable('age', 30);
await perl.eval(`
$| = 1;
print "Name: $name\\n";
print "Age: $age\\n";
`);
// Perl to JavaScript
await perl.eval('$result = 2 + 2');
const result = perl.getVariable('result');
console.log(result.toInt()); // 4
result.dispose();
perl.dispose();
与阵列和哈谢斯合作
const perl = await ZeroPerl.create();
// Create array
const arr = perl.createArray([1, 2, 3, 'hello']);
perl.setVariable('myarray', arr.toValue());
// Create hash
const hash = perl.createHash({
name: 'Alice',
age: 30,
active: true
});
perl.setVariable('user', hash.toValue());
await perl.eval(`
$| = 1;
print "Array length: ", scalar(@$myarray), "\\n";
print "User: $user->{name}, Age: $user->{age}\\n";
`);
// Convert back to JavaScript
const jsArray = arr.project(); // [1, 2, 3, 'hello']
const jsObject = hash.project(); // { name: 'Alice', age: 30, active: true }
arr.dispose();
hash.dispose();
perl.dispose();
命令行参数
const perl = await ZeroPerl.create();
await perl.eval(`
$| = 1;
print "Arguments: @ARGV\\n";
foreach my $arg (@ARGV) {
print " $arg\\n";
}
`, ['foo', 'bar', 'baz']);
perl.dispose();
处理文件
创建虚拟文件系统
import { ZeroPerl, MemoryFileSystem } from '@6over3/zeroperl-ts';
const fs = new MemoryFileSystem({ "/": "" });
fs.addFile("/data.txt", "Hello from a file!");
fs.addFile("/script.pl", `
$| = 1;
open my $fh, '<', '/data.txt' or die $!;
while (my $line = <$fh>) {
print "Read: $line";
}
close $fh;
`);
const perl = await ZeroPerl.create({ fileSystem: fs });
await perl.runFile('/script.pl');
perl.dispose();
以参数运行脚本
const fs = new MemoryFileSystem({ "/": "" });
fs.addFile("/greet.pl", `
$| = 1;
my ($name, $greeting) = @ARGV;
print "$greeting, $name!\\n";
`);
const perl = await ZeroPerl.create({ fileSystem: fs });
await perl.runFile('/greet.pl', ['Alice', 'Hello']);
// Output: Hello, Alice!
perl.dispose();
读取和写入文件
const fs = new MemoryFileSystem({ "/": "" });
const perl = await ZeroPerl.create({ fileSystem: fs });
// Write from Perl
await perl.eval(`
$| = 1;
open my $fh, '>', '/output.txt' or die $!;
print $fh "Generated content\\n";
close $fh;
print "File written!\\n";
`);
// Read from JavaScript
const content = fs.readFile('/output.txt');
console.log(content); // "Generated content\n"
perl.dispose();
高级使用
正在注册 JavaScript 函数
从 Perl 调用 JavaScript 函数:
const perl = await ZeroPerl.create();
perl.registerFunction('add', (a, b) => {
const x = a.toInt();
const y = b.toInt();
return perl.createInt(x + y);
});
await perl.eval(`
$| = 1;
my $sum = add(10, 32);
print "Sum: $sum\\n";
`);
perl.dispose();
注册 JavaScript 方法
const perl = await ZeroPerl.create();
perl.registerMethod('Math', 'square', (x) => {
const num = x.toInt();
return perl.createInt(num * num);
});
await perl.eval(`
$| = 1;
my $result = Math::square(7);
print "Square: $result\\n";
`);
perl.dispose();
从 JavaScript 调用 Perl 函数
const perl = await ZeroPerl.create();
await perl.eval(`
sub greet {
my ($name) = @_;
return "Hello, $name!";
}
sub get_values {
return (1, 2, 3);
}
`);
// Scalar context (single return value)
const arg = perl.createString("Alice");
const greeting = await perl.call("greet", [arg], "scalar");
console.log(greeting?.toString()); // "Hello, Alice!"
// List context (multiple return values)
const values = await perl.call("get_values", [], "list");
console.log(values.map(v => v.toInt())); // [1, 2, 3]
// Void context (no return value)
await perl.call("some_sub", [], "void");
arg.dispose();
greeting?.dispose();
for (const v of values) v.dispose();
perl.dispose();
处理错误
const perl = await ZeroPerl.create();
const result = await perl.eval(`
die "Something went wrong!";
`);
if (!result.success) {
console.log('Exit code:', result.exitCode);
console.log('Error:', result.error);
}
// Get error directly
const error = perl.getLastError();
console.log(error); // "Something went wrong! at ..."
// Clear error
perl.clearError();
perl.dispose();
环境变量
const perl = await ZeroPerl.create({
env: {
API_KEY: 'secret123',
DEBUG: 'true'
}
});
await perl.eval(`
$| = 1;
print "API Key: $ENV{API_KEY}\\n";
print "Debug: $ENV{DEBUG}\\n";
`);
perl.dispose();
重设状态
const perl = await ZeroPerl.create();
await perl.eval('$counter = 1');
const val1 = perl.getVariable('counter');
console.log(val1?.toInt()); // 1
await perl.reset();
const val2 = perl.getVariable('counter');
console.log(val2); // null
val1?.dispose();
perl.dispose();
渐进输出
const perl = await ZeroPerl.create({
stdout: (data) => process.stdout.write(data)
});
for (let i = 0; i < 5; i++) {
await perl.eval('print "."');
perl.flush();
await new Promise(r => setTimeout(r, 500));
}
perl.dispose();
浏览器使用
带有捆绑器( 建议):
import { ZeroPerl } from '@6over3/zeroperl-ts';
import zeroperl from '@6over3/zeroperl-ts/zeroperl.wasm';
const perl = await ZeroPerl.create({
fetch: () => fetch(zeroperl),
stdout: (data) => console.log(data)
});
await perl.eval(`
$| = 1;
print "Hello from Perl!\\n";
print "Running in: $^O\\n";
`);
perl.dispose();
注:大多数捆绑者在明确导入时应该复制WASM文件. 如果您的捆绑者不处理此事宜, 请配置它复制静态资产, 或者使用下面的 CDN 方法 .
从CDN:
<!DOCTYPE html>
<html>
<body>
<div id="output"></div>
<script type="module">
import { ZeroPerl } from 'https://esm.sh/@6over3/zeroperl-ts';
const output = document.getElementById('output');
const perl = await ZeroPerl.create({
stdout: (data) => {
const text = typeof data === 'string' ? data : new TextDecoder().decode(data);
output.innerHTML += text.replace(/\n/g, '<br>');
}
});
await perl.eval(`
$| = 1;
print "Hello from Perl!\\n";
print "Running in: $^O\\n";
`);
perl.dispose();
</script>
</body>
</html>
API 参考
ZeroPerl.create(options?)
创建新的 Perl 解释器实例 .
选项 :
env- 环境变量(记录<字符串,字符串>)fileSystem- 虚拟文件系统(记忆系统)stdout- stdout callback ((数据: 字符串 QQ Uint8Array) 无效)stderr- Stderr 回调( (数据: 字符串 QQUint8Array) 无效)fetch- 自定义加载WASM
const perl = await ZeroPerl.create({
env: { KEY: 'value' },
fileSystem: fs,
stdout: (data) => console.log(data),
stderr: (data) => console.error(data)
});
perl.eval(code, args?)
评估Perl代码. 回返 { success: boolean, error?: string, exitCode: number }。 。 。 .
const result = await perl.eval('print "Hello\\n"', ['arg1', 'arg2']);
perl.runFile(path, args?)
从虚拟文件系统运行一个 Perl 脚本 .
await perl.runFile('/script.pl', ['arg1', 'arg2']);
perl.createInt(value), (中文(简体) ), perl.createDouble(value), (中文(简体) ), perl.createString(value), (中文(简体) ), perl.createBool(value), (中文(简体) ), perl.createUndef()
创建 Perl 值 。 回返 PerlValue。 。 。 .
const num = perl.createInt(42);
const str = perl.createString("hello");
const bool = perl.createBool(true);
perl.createArray(values?), (中文(简体) ), perl.createHash(object?)
创建 Perl 阵列和散列 。 回返 PerlArray 或者说 PerlHash。 。 。 .
const arr = perl.createArray([1, 2, 3]);
const hash = perl.createHash({ key: 'value' });
perl.toPerlValue(value)
将 JavaScript 值转换为 Perl 。 处理原始人、阵列和物体.
const perlVal = perl.toPerlValue({ name: 'Alice', age: 30 });
perl.setVariable(name, value), (中文(简体) ), perl.getVariable(name)
设定并获取平面变量 。 可变名称不应包括 $ 前缀.
perl.setVariable('x', 42);
const x = perl.getVariable('x');
console.log(x?.toInt()); // 42
perl.getArrayVariable(name), (中文(简体) ), perl.getHashVariable(name)
获取数组和散列变量 。 回返 PerlArray 或者说 PerlHash。 。 。 .
const arr = perl.getArrayVariable('myarray');
const hash = perl.getHashVariable('myhash');
perl.registerFunction(name, fn)
从 Perl 注册 JavaScript 函数可调用 .
perl.registerFunction('add', (a, b) => {
const x = a.toInt();
const y = b.toInt();
return perl.createInt(x + y);
});
perl.registerMethod(packageName, methodName, fn)
注册 JavaScript 从 Perl 调用的方法 .
perl.registerMethod('Math', 'square', (x) => {
const num = x.toInt();
return perl.createInt(num * num);
});
perl.call(name, args, context?)
调用 Perl 函数 。 环境可以是 "void", (中文(简体) ), "scalar",或 "list"。 。 。 .
const result = await perl.call('my_sub', [arg1, arg2], 'scalar');
const results = await perl.call('my_sub', [], 'list');
await perl.call('my_sub', [], 'void');
perl.flush()
流出输出缓冲. 如果自动擦出( N)$| = 1)没有设置.
await perl.eval('print "text"');
perl.flush();
perl.reset()
将解释器重置为干净状态 。 清除所有变量.
await perl.reset();
perl.getLastError(), (中文(简体) ), perl.clearError()
获取并清除 Perl 错误状态( N)$@) (中文(简体) ).
const error = perl.getLastError();
perl.clearError();
perl.isInitialized(), (中文(简体) ), perl.canEvaluate()
检查口译状态 .
const ready = perl.isInitialized() && perl.canEvaluate();
perl.dispose(), (中文(简体) ), perl.shutdown()
免费资源. 使用 dispose() 为了正常的清理, shutdown() 完全终止.
perl.dispose();
// or
perl.shutdown();
PerlValue 方法
toInt()- 转换为32位整数toDouble()- 转换为双精度浮标toString()- 转换为 UTF-8 字符串toBoolean()- 转换为布尔( Perl 真理测试)isUndef()- 检查是否未定义isRef()- 检查参考文献getType()- 获取Perl类型project()- 转换为 JavaScript 原始createRef()- 创建参考deref()- 参考值dispose()- 免费的记忆
佩尔阵列方法
push(value)- 添加到结束pop()- 从尾部删除get(index)- 获取指数值set(index, value)- 设定指数值getLength()- 获得阵列长度clear()- 删除所有元素toValue()- 转换为 PerlValue( 矩阵引用)project()- 转换为 JavaScript 阵列[Symbol.iterator]()- 超过价值dispose()- 免费的记忆
PerlHash 方法
set(key, value)- 设置密钥值对get(key)- 按键计值has(key)- 检查密钥是否存在delete(key)- 删除密钥clear()- 删除所有条目toValue()- 转换为 PerlValue( hash 引用)project()- 转换为 JavaScript 对象entries()- 以键值对表示keys()- 键上斜线values()- 超过价值dispose()- 免费的记忆
实例
处理 JSON
import { ZeroPerl, MemoryFileSystem } from '@6over3/zeroperl-ts';
const fs = new MemoryFileSystem({ "/": "" });
fs.addFile("/data.json", JSON.stringify({ users: ['Alice', 'Bob'] }));
fs.addFile("/process.pl", `
$| = 1;
use strict;
use warnings;
open my $fh, '<', '/data.json' or die $!;
my $json = do { local $/; <$fh> };
close $fh;
print "Processing: $json\\n";
`);
const perl = await ZeroPerl.create({ fileSystem: fs });
await perl.runFile('/process.pl');
perl.dispose();
互动反应
const perl = await ZeroPerl.create({
stdout: (data) => console.log(data)
});
await perl.eval('$| = 1');
await perl.eval('$x = 10');
await perl.eval('print "$x\\n"');
await perl.eval('$x *= 2');
await perl.eval('print "$x\\n"');
perl.dispose();
复杂数据结构
const perl = await ZeroPerl.create();
perl.setVariable('config', {
server: {
host: 'localhost',
port: 8080
},
features: ['auth', 'logging']
});
await perl.eval(`
$| = 1;
print "Host: $config->{server}{host}\\n";
print "Port: $config->{server}{port}\\n";
print "Features: @{$config->{features}}\\n";
`);
perl.dispose();
发展
npm i # Install dependencies
bun run build # Build distributions
bun test # Run tests
许可证
阿帕奇 - 2.0
关于
ZeroPerl使用符合WASI的操作将Perl 5编译为WebAssembly. 此软件包为您提供了 TypeScript/ JavaScript API 零位数 WASM模块.