Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions lib/ZeroPerl/Web.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package ZeroPerl::Web;

use strict;
use warnings;
use Exporter 'import';

our $VERSION = '0.01';
our @EXPORT_OK = qw(fetch sleep);

require XSLoader;
XSLoader::load('ZeroPerl::Web', $VERSION);

1;

__END__

=head1 NAME

ZeroPerl::Web - Asynchronous Web APIs for ZeroPerl

=head1 SYNOPSIS

use ZeroPerl::Web;

# Fetch data asynchronously (returns a Promise-like behavior via Asyncify)
my $response = ZeroPerl::Web::fetch("https://api.example.com/data");
print "Response: $response\n";

# Sleep asynchronously without blocking the browser main thread
ZeroPerl::Web::sleep(1000); # Sleep for 1 second

=head1 DESCRIPTION

This module provides access to Web APIs within the ZeroPerl WebAssembly environment.
It uses Asyncify to perform asynchronous operations transparently to Perl code.

=head2 FUNCTIONS

=over 4

=item fetch($url, [\%options])

Performs a network request using the Host's `fetch` API.
Returns the response body as a string.

=item sleep($ms)

Suspends execution for the specified number of milliseconds.
This yields control back to the browser event loop.

=back

=cut
4 changes: 3 additions & 1 deletion pipeline/build-wasm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ wasic -flto -O3 -c setjmp_core.S -o setjmp_core.o

cd "$WASM_DIR"
cp "$REPO_DIR/stubs/zeroperl.c" .
cp "$REPO_DIR/stubs/zeroperl_web.c" .

CFLAGS="-c -O3 -flto -DNO_MATHOMS -D_WASI_EMULATED_PROCESS_CLOCKS -D_WASI_EMULATED_GETPID \
-D_GNU_SOURCE -D_POSIX_C_SOURCE -DBIG_TIME -Wno-implicit-function-declaration \
Expand All @@ -30,6 +31,7 @@ CFLAGS="-c -O3 -flto -DNO_MATHOMS -D_WASI_EMULATED_PROCESS_CLOCKS -D_WASI_EMULAT
-I. -I$REPO_DIR/stubs -I$REPO_DIR/gen -cxx-isystem /opt/wasi-sdk/share/wasi-sysroot/include"

wasic $CFLAGS zeroperl.c -o zeroperl.o
wasic $CFLAGS zeroperl_web.c -o zeroperl_web.o
wasic $CFLAGS "$REPO_DIR/stubs/stubs.c" -o stubs.o

CFLAGS_DATA="-c -O0 -std=c23 \
Expand Down Expand Up @@ -59,7 +61,7 @@ wasic \
-lwasi-emulated-mman \
-Wl,--strip-all \
-Wl,--allow-undefined \
zeroperl.o stubs.o zeroperl_data.o \
zeroperl.o stubs.o zeroperl_data.o zeroperl_web.o \
-Wl,--whole-archive "$REPO_DIR/stubs/libasyncjmp.a" -Wl,--no-whole-archive \
-Wl,--whole-archive libperl.a -Wl,--no-whole-archive \
-Wl,--wrap=fopen -Wl,--wrap=open -Wl,--wrap=close -Wl,--wrap=read \
Expand Down
4 changes: 4 additions & 0 deletions pipeline/prepare-prefix.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ if [ "$BUILD_EXIFTOOL" = "true" ]; then
cp -R "$SITE_PERL/Image/"* "/zeroperl/lib/$PERL_VERSION/wasm32-wasi/Image/"
fi

# Copy internal modules
mkdir -p "/zeroperl/lib/$PERL_VERSION/ZeroPerl"
cp "$REPO_DIR/lib/ZeroPerl/Web.pm" "/zeroperl/lib/$PERL_VERSION/ZeroPerl/"

node "$REPO_DIR/tools/delete.js" "$REPO_DIR/tools/delete.txt" /zeroperl "$PERL_VERSION"

if [ "$TRIM" = "true" ]; then
Expand Down
95 changes: 3 additions & 92 deletions stubs/zeroperl.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,97 +459,6 @@ __attribute__((noinline)) int __wrap_fileno(FILE *stream) {
return realfd;
}

//! Opaque handle to a Perl scalar value
typedef struct zeroperl_value_s {
SV *sv;
} zeroperl_value;

//! Opaque handle to a Perl array
typedef struct zeroperl_array_s {
AV *av;
} zeroperl_array;

//! Opaque handle to a Perl hash
typedef struct zeroperl_hash_s {
HV *hv;
} zeroperl_hash;

//! Opaque handle to a Perl code reference
typedef struct zeroperl_code_s {
CV *cv;
} zeroperl_code;

//! Result structure for operations that return multiple values
typedef struct zeroperl_result_s {
int count;
zeroperl_value **values;
} zeroperl_result;

//! Iterator for hash traversal
typedef struct zeroperl_hash_iter_s {
HV *hv;
HE *entry;
} zeroperl_hash_iter;

//! Context type for calling Perl code
typedef enum {
ZEROPERL_VOID,
ZEROPERL_SCALAR,
ZEROPERL_LIST
} zeroperl_context_type;

//! Value type enumeration
typedef enum {
ZEROPERL_TYPE_UNDEF,
ZEROPERL_TYPE_TRUE,
ZEROPERL_TYPE_FALSE,
ZEROPERL_TYPE_INT,
ZEROPERL_TYPE_DOUBLE,
ZEROPERL_TYPE_STRING,
ZEROPERL_TYPE_ARRAY,
ZEROPERL_TYPE_HASH,
ZEROPERL_TYPE_CODE,
ZEROPERL_TYPE_REF
} zeroperl_type;

//! Operation type for unified context
typedef enum {
ZEROPERL_OP_INIT,
ZEROPERL_OP_EVAL,
ZEROPERL_OP_RUN_FILE,
ZEROPERL_OP_RESET,
ZEROPERL_OP_CALL
} zeroperl_op_type;

//! Unified context structure for all Perl operations
typedef struct {
zeroperl_op_type op_type;
int result;
union {
struct {
int argc;
char **argv;
} init;
struct {
const char *code;
int argc;
char **argv;
zeroperl_context_type context;
} eval;
struct {
const char *filepath;
int argc;
char **argv;
} run_file;
struct {
const char *name;
int argc;
zeroperl_value **argv;
zeroperl_context_type context;
} call;
} data;
} zeroperl_context;

//! Host-implemented function for calling back into the host environment
ZEROPERL_IMPORT("call_host_function")
zeroperl_value *host_call_function(int32_t func_id, int32_t argc,
Expand Down Expand Up @@ -2241,7 +2150,8 @@ EXTERN_C void boot_Cwd(pTHX_ CV *cv);
EXTERN_C void boot_List__Util(pTHX_ CV *cv);
EXTERN_C void boot_Fcntl(pTHX_ CV *cv);
EXTERN_C void boot_Opcode(pTHX_ CV *cv);
EXTERN_C void boot_Time__HiRes(pTHX_ CV* cv);
EXTERN_C void boot_Time__HiRes(pTHX_ CV *cv);
EXTERN_C void boot_ZeroPerl__Web(pTHX_ CV *cv);

static void xs_init(pTHX) {
static const char file[] = __FILE__;
Expand Down Expand Up @@ -2285,4 +2195,5 @@ static void xs_init(pTHX) {
newXS("Fcntl::bootstrap", boot_Fcntl, file);
newXS("Opcode::bootstrap", boot_Opcode, file);
newXS("Time::HiRes::bootstrap", boot_Time__HiRes, file);
newXS("ZeroPerl::Web::bootstrap", boot_ZeroPerl__Web, file);
}
118 changes: 118 additions & 0 deletions stubs/zeroperl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#ifndef ZEROPERL_H
#define ZEROPERL_H

#include "EXTERN.h"
#include "XSUB.h"
#include "perl.h"
#include <stdint.h>


// Defined for SFS (Simple File System) prefix
#ifndef SFS_BUILTIN_PREFIX
#define SFS_BUILTIN_PREFIX "builtin:"
#endif

// Opaque handle to a Perl scalar value
typedef struct zeroperl_value_s {
SV *sv;
} zeroperl_value;

// Opaque handle to a Perl array
typedef struct zeroperl_array_s {
AV *av;
} zeroperl_array;

// Opaque handle to a Perl hash
typedef struct zeroperl_hash_s {
HV *hv;
} zeroperl_hash;

// Opaque handle to a Perl code reference
typedef struct zeroperl_code_s {
CV *cv;
} zeroperl_code;

// Result structure for operations that return multiple values
typedef struct zeroperl_result_s {
int count;
zeroperl_value **values;
} zeroperl_result;

// Iterator for hash traversal
typedef struct zeroperl_hash_iter_s {
HV *hv;
HE *entry;
} zeroperl_hash_iter;

// Context type for calling Perl code
typedef enum {
ZEROPERL_VOID,
ZEROPERL_SCALAR,
ZEROPERL_LIST
} zeroperl_context_type;

// Value type enumeration
typedef enum {
ZEROPERL_TYPE_UNDEF,
ZEROPERL_TYPE_TRUE,
ZEROPERL_TYPE_FALSE,
ZEROPERL_TYPE_INT,
ZEROPERL_TYPE_DOUBLE,
ZEROPERL_TYPE_STRING,
ZEROPERL_TYPE_ARRAY,
ZEROPERL_TYPE_HASH,
ZEROPERL_TYPE_CODE,
ZEROPERL_TYPE_REF
} zeroperl_type;

// Operation type for unified context
typedef enum {
ZEROPERL_OP_INIT,
ZEROPERL_OP_EVAL,
ZEROPERL_OP_RUN_FILE,
ZEROPERL_OP_RESET,
ZEROPERL_OP_CALL
} zeroperl_op_type;

// Unified context structure for all Perl operations
typedef struct {
zeroperl_op_type op_type;
int result;
union {
struct {
int argc;
char **argv;
} init;
struct {
const char *code;
int argc;
char **argv;
zeroperl_context_type context;
} eval;
struct {
const char *filepath;
int argc;
char **argv;
} run_file;
struct {
const char *name;
int argc;
zeroperl_value **argv;
zeroperl_context_type context;
} call;
} data;
} zeroperl_context;

// Cleanup helper
void zeroperl_value_free(zeroperl_value *val);

// Host call function
zeroperl_value *host_call_function(int32_t func_id, int32_t argc,
zeroperl_value **argv);

// Error handling functions
void zeroperl_set_host_error(const char *error);
const char *zeroperl_get_host_error(void);
void zeroperl_clear_host_error(void);

#endif // ZEROPERL_H
Loading