The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <JavaScript.h>
#define PJS_ERROR_OPCODELILMIT_EXCEEDED "JavaScript::Error::OpcodeLimitExceeded"
struct PJS_Runtime_OpcodeCounting {
U32 count;
U32 limit;
};
typedef struct PJS_Runtime_OpcodeCounting PJS_Runtime_OpcodeCounting;
static JSTrapStatus opcodecounting_interrupt_handler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *data) {
PJS_Runtime_OpcodeCounting *opcount = (PJS_Runtime_OpcodeCounting *) data;
opcount->count++;
if (opcount->limit > 0 && opcount->count > opcount->limit) {
sv_setsv(ERRSV, newRV_inc(newSViv(opcount->limit)));
sv_bless(ERRSV, gv_stashpvn(PJS_ERROR_OPCODELILMIT_EXCEEDED, strlen(PJS_ERROR_OPCODELILMIT_EXCEEDED), TRUE));
return JSTRAP_ERROR;
}
return JSTRAP_CONTINUE;
}
MODULE = JavaScript::Runtime::OpcodeCounting PACKAGE = JavaScript::Runtime::OpcodeCounting
PJS_TrapHandler *
jsr_init()
PREINIT:
PJS_TrapHandler *handler;
PJS_Runtime_OpcodeCounting *opcount;
CODE:
Newz(1, opcount, 1, PJS_Runtime_OpcodeCounting);
if (opcount == NULL) {
croak("Failed to allocate memory for PJS_Runtime_OpcodeCounting");
}
opcount->count = 0;
opcount->limit = 0;
Newz(1, handler, 1, PJS_TrapHandler);
if (handler == NULL) {
Safefree(opcount);
croak("Failed to allocate memory for PJS_TrapHandler");
}
handler->handler = opcodecounting_interrupt_handler;
handler->data = (void *) opcount;
RETVAL = handler;
OUTPUT:
RETVAL
void
jsr_destroy(handler)
PJS_TrapHandler *handler;
CODE:
Safefree(handler->data);
Safefree(handler);
I32
jsr_get_opcount(handler)
PJS_TrapHandler *handler;
PREINIT:
PJS_Runtime_OpcodeCounting *opcount;
CODE:
opcount = (PJS_Runtime_OpcodeCounting *) handler->data;
RETVAL = opcount->count;
OUTPUT:
RETVAL
void
jsr_set_opcount(handler,count)
PJS_TrapHandler *handler;
I32 count;
PREINIT:
PJS_Runtime_OpcodeCounting *opcount;
CODE:
opcount = (PJS_Runtime_OpcodeCounting *) handler->data;
opcount->count = count;
I32
jsr_get_opcount_limit(handler)
PJS_TrapHandler *handler;
PREINIT:
PJS_Runtime_OpcodeCounting *opcount;
CODE:
opcount = (PJS_Runtime_OpcodeCounting *) handler->data;
RETVAL = opcount->limit;
OUTPUT:
RETVAL
void
jsr_set_opcount_limit(handler,limit)
PJS_TrapHandler *handler;
I32 limit;
PREINIT:
PJS_Runtime_OpcodeCounting *opcount;
CODE:
opcount = (PJS_Runtime_OpcodeCounting *) handler->data;
opcount->limit = limit;