1219 lines
44 KiB
Zig
1219 lines
44 KiB
Zig
const std = @import("std");
|
|
|
|
/// Manually translated quickjs.h, only for 64-bit targets.
|
|
const import = struct {
|
|
comptime {
|
|
// 64-bit targets only
|
|
std.debug.assert(@sizeOf(usize) == 8);
|
|
// all c_int has been translated to i32
|
|
std.debug.assert(@sizeOf(c_int) == @sizeOf(i32));
|
|
}
|
|
|
|
pub const JSRuntime = opaque {};
|
|
pub const JSContext = opaque {};
|
|
pub const JSClass = opaque {};
|
|
pub const JSGCObjectHeader = opaque {};
|
|
|
|
pub const JS_BOOL = i32;
|
|
pub const JSClassID = u32;
|
|
pub const JSAtom = u32;
|
|
pub const JSShortBigInt = i64;
|
|
|
|
pub const JS_TAG = enum(i32) {
|
|
/// First negative tag.
|
|
pub const FIRST: i32 = -9;
|
|
|
|
BIG_INT = -9,
|
|
SYMBOL = -8,
|
|
STRING = -7,
|
|
STRING_ROPE = -6,
|
|
/// Used internally.
|
|
MODULE = -3,
|
|
/// Used internally.
|
|
FUNCTION_BYTECODE = -2,
|
|
OBJECT = -1,
|
|
|
|
INT = 0,
|
|
BOOL = 1,
|
|
NULL = 2,
|
|
UNDEFINED = 3,
|
|
UNINITIALIZED = 4,
|
|
CATCH_OFFSET = 5,
|
|
EXCEPTION = 6,
|
|
SHORT_BIG_INT = 7,
|
|
FLOAT64 = 8,
|
|
|
|
_,
|
|
};
|
|
|
|
pub const JSRefCountHeader = extern struct {
|
|
ref_count: i32,
|
|
};
|
|
|
|
pub const JSValueUnion = extern union {
|
|
int32: i32,
|
|
float64: f64,
|
|
ptr: ?*anyopaque,
|
|
short_big_int: JSShortBigInt,
|
|
};
|
|
|
|
pub const JSValue = extern struct {
|
|
value: JSValueUnion,
|
|
tag: i64,
|
|
};
|
|
|
|
pub const JSValueConst = JSValue;
|
|
|
|
pub inline fn JS_VALUE_GET_TAG(v: JSValue) JS_TAG {
|
|
return @enumFromInt(@as(i32, @intCast(v.tag)));
|
|
}
|
|
|
|
pub inline fn JS_VALUE_GET_NORM_TAG(v: JSValue) JS_TAG {
|
|
return JS_VALUE_GET_TAG(v);
|
|
}
|
|
|
|
pub inline fn JS_VALUE_GET_INT(v: JSValue) i32 {
|
|
return v.value.int32;
|
|
}
|
|
|
|
pub inline fn JS_VALUE_GET_BOOL(v: JSValue) JS_BOOL {
|
|
return v.value.int32;
|
|
}
|
|
|
|
pub inline fn JS_VALUE_GET_FLOAT64(v: JSValue) f64 {
|
|
return v.value.float64;
|
|
}
|
|
|
|
pub inline fn JS_VALUE_GET_PTR(v: JSValue) ?*anyopaque {
|
|
return v.value.ptr;
|
|
}
|
|
|
|
pub inline fn JS_VALUE_GET_SHORT_BIG_INT(v: JSValue) JSShortBigInt {
|
|
return v.value.short_big_int;
|
|
}
|
|
|
|
pub inline fn JS_MKVAL(tag: JS_TAG, val: i32) JSValue {
|
|
return .{
|
|
.value = .{ .int32 = val },
|
|
.tag = @intFromEnum(tag),
|
|
};
|
|
}
|
|
|
|
pub inline fn JS_MKPTR(tag: JS_TAG, ptr: ?*anyopaque) JSValue {
|
|
return .{
|
|
.value = .{ .ptr = ptr },
|
|
.tag = @intFromEnum(tag),
|
|
};
|
|
}
|
|
|
|
pub inline fn JS_TAG_IS_FLOAT64(tag: JS_TAG) bool {
|
|
return tag == JS_TAG.FLOAT64;
|
|
}
|
|
|
|
pub inline fn JS_VALUE_IS_NAN(v: JSValue) bool {
|
|
if (v.tag != JS_TAG.FLOAT64) {
|
|
return false;
|
|
}
|
|
const u: u64 = @bitCast(v.u.float64);
|
|
return (u & 0x7FFFFFFFFFFFFFFF) > 0x7FF0000000000000;
|
|
}
|
|
|
|
pub const JS_NAN: JSValue = .{
|
|
.value = .{ .float64 = std.math.nan(f64) },
|
|
.tag = @intFromEnum(JS_TAG.FLOAT64),
|
|
};
|
|
|
|
pub inline fn JS_VALUE_IS_BOTH_INT(v1: JSValue, v2: JSValue) bool {
|
|
return @intFromEnum(JS_VALUE_GET_TAG(v1)) | @intFromEnum(JS_VALUE_GET_TAG(v2)) == 0;
|
|
}
|
|
|
|
pub inline fn JS_VALUE_IS_BOTH_FLOAT(v1: JSValue, v2: JSValue) bool {
|
|
return JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) and JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2));
|
|
}
|
|
|
|
pub inline fn JS_VALUE_HAS_REF_COUNT(v: JSValue) bool {
|
|
return @as(u32, @bitCast(@intFromEnum(JS_VALUE_GET_TAG(v)))) >= @as(u32, @bitCast(JS_TAG.FIRST));
|
|
}
|
|
|
|
pub const JS_NULL = JS_MKVAL(JS_TAG.NULL, 0);
|
|
pub const JS_UNDEFINED = JS_MKVAL(JS_TAG.UNDEFINED, 0);
|
|
pub const JS_FALSE = JS_MKVAL(JS_TAG.BOOL, 0);
|
|
pub const JS_TRUE = JS_MKVAL(JS_TAG.BOOL, 1);
|
|
pub const JS_EXCEPTION = JS_MKVAL(JS_TAG.EXCEPTION, 0);
|
|
pub const JS_UNINITIALIZED = JS_MKVAL(JS_TAG.UNINITIALIZED, 0);
|
|
|
|
pub inline fn __JS_NewFloat64(ctx: *JSContext, d: f64) JSValue {
|
|
_ = ctx;
|
|
return .{
|
|
.value = .{ .float64 = d },
|
|
.tag = @intFromEnum(JS_TAG.FLOAT64),
|
|
};
|
|
}
|
|
|
|
pub inline fn __JS_NewShortBigInt(ctx: *JSContext, d: JSShortBigInt) JSValue {
|
|
_ = ctx;
|
|
return .{
|
|
.value = .{ .short_big_int = d },
|
|
.tag = @intFromEnum(JS_TAG.SHORT_BIG_INT),
|
|
};
|
|
}
|
|
|
|
pub const JS_PROP = packed struct(u32) {
|
|
props: packed struct(u4) {
|
|
configurable: bool = false,
|
|
writable: bool = false,
|
|
enumerable: bool = false,
|
|
/// Used internally in Arrays.
|
|
length: bool = false,
|
|
|
|
pub const cwe = @This(){
|
|
.configurable = true,
|
|
.writable = true,
|
|
.enumerable = true,
|
|
};
|
|
} = .{},
|
|
tmask: enum(u2) {
|
|
NORMAL = 0,
|
|
GETSET = 1,
|
|
/// Used internally.
|
|
VARREF = 2,
|
|
/// Used internally.
|
|
AUTOINIT = 3,
|
|
} = .NORMAL,
|
|
_pad6: u2 = 0,
|
|
has: packed struct(u6) {
|
|
configurable: bool = false,
|
|
writable: bool = false,
|
|
enumerable: bool = false,
|
|
get: bool = false,
|
|
set: bool = false,
|
|
value: bool = false,
|
|
} = .{},
|
|
throw: bool = false,
|
|
throw_strict: bool = false,
|
|
/// Internal use.
|
|
no_add: bool = false,
|
|
/// Internal use.
|
|
no_exotic: bool = false,
|
|
_pad14: u18 = 0,
|
|
};
|
|
|
|
pub const JS_EVAL = packed struct(u32) {
|
|
type: enum(u2) {
|
|
/// Global code (default).
|
|
GLOBAL = 0,
|
|
/// Module code.
|
|
MODULE = 1,
|
|
/// Direct call (internal use).
|
|
DIRECT = 2,
|
|
/// Indirect call (internal use).
|
|
INDIRECT = 3,
|
|
} = .GLOBAL,
|
|
flags: packed struct(u30) {
|
|
_pad2: u1 = 0,
|
|
/// Force "strict" mode.
|
|
strict: bool = false,
|
|
_pad4: u1 = 0,
|
|
/// Compile but do not run. The result is an object with a
|
|
/// JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed
|
|
/// with JS_EvalFunction().
|
|
compile_only: bool = false,
|
|
/// Don't include the stack frames before this eval in the Error()
|
|
/// backtraces.
|
|
backtrace_barrier: bool = false,
|
|
/// Allow top-level await in normal script. JS_Eval() returns a promise.
|
|
/// Only allowed with .type == .GLOBAL
|
|
async: bool = false,
|
|
_pad8: u24 = 0,
|
|
} = .{},
|
|
};
|
|
|
|
pub const JSCFunction = fn (ctx: *JSContext, this_val: JSValueConst, argc: i32, argv: [*]JSValueConst) callconv(.c) JSValue;
|
|
pub const JSCFunctionMagic = fn (ctx: *JSContext, this_val: JSValueConst, argc: i32, argv: [*]JSValueConst, magic: i32) callconv(.c) JSValue;
|
|
pub const JSCFunctionData = fn (ctx: *JSContext, this_val: JSValueConst, argc: i32, argv: [*]JSValueConst, magic: i32, func_data: *JSValue) callconv(.c) JSValue;
|
|
pub const JS_MarkFunc = fn (rt: *JSRuntime, gp: *JSGCObjectHeader) callconv(.c) void;
|
|
|
|
pub const JSMallocState = extern struct {
|
|
malloc_count: usize,
|
|
malloc_suze: usize,
|
|
malloc_limit: usize,
|
|
/// User opaque.
|
|
@"opaque": ?*anyopaque,
|
|
};
|
|
|
|
pub const JSMallocFunctions = extern struct {
|
|
js_malloc: *const fn (s: *JSMallocState, size: usize) callconv(.c) ?*anyopaque,
|
|
js_free: *const fn (s: *JSMallocState, ptr: ?*anyopaque) callconv(.c) void,
|
|
js_realloc: *const fn (s: *JSMallocState, ptr: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque,
|
|
js_malloc_usable_size: ?*const fn (ptr: ?*const anyopaque) callconv(.c) usize,
|
|
};
|
|
|
|
pub extern fn JS_NewRuntime() ?*JSRuntime;
|
|
pub extern fn JS_SetRuntimeInfo(rt: *JSRuntime, info: [*:0]const u8) void;
|
|
pub extern fn JS_SetMemoryLimit(rt: *JSRuntime, limit: usize) void;
|
|
pub extern fn JS_SetGCThreshold(rt: *JSRuntime, gc_threshold: usize) void;
|
|
pub extern fn JS_SetMaxStackSize(rt: *JSRuntime, stack_size: usize) void;
|
|
pub extern fn JS_UpdateStackTop(rt: *JSRuntime) void;
|
|
pub extern fn JS_NewRuntime2(mf: *const JSMallocFunctions, @"opaque": ?*anyopaque) ?*JSRuntime;
|
|
pub extern fn JS_FreeRuntime(rt: ?*JSRuntime) void;
|
|
pub extern fn JS_GetRuntimeOpaque(rt: *JSRuntime) ?*anyopaque;
|
|
pub extern fn JS_SetRuntimeOpaque(rt: *JSRuntime, @"opaque": ?*anyopaque) void;
|
|
pub extern fn JS_MarkValue(rt: *JSRuntime, val: JSValue, mark_func: ?*const JS_MarkFunc) void;
|
|
pub extern fn JS_RunGC(rt: *JSRuntime) void;
|
|
pub extern fn JS_IsLiveObject(rt: *JSRuntime, obj: JSValue) JS_BOOL;
|
|
|
|
pub extern fn JS_NewContext(rt: *JSRuntime) ?*JSContext;
|
|
pub extern fn JS_FreeContext(s: ?*JSContext) void;
|
|
pub extern fn JS_DupContext(ctx: *JSContext) ?*JSContext;
|
|
pub extern fn JS_GetContextOpaque(ctx: *JSContext) ?*anyopaque;
|
|
pub extern fn JS_SetContextOpaque(ctx: *JSContext, @"opaque": ?*anyopaque) void;
|
|
pub extern fn JS_GetRuntime(ctx: *JSContext) *JSRuntime;
|
|
pub extern fn JS_SetClassProto(ctx: *JSContext, class_id: JSClassID, obj: JSValue) void;
|
|
pub extern fn JS_GetClassProto(ctx: *JSContext, class_id: JSClassID) JSValue;
|
|
|
|
pub extern fn JS_NewContextRaw(rt: *JSRuntime) ?*JSContext;
|
|
pub extern fn JS_AddIntrinsicBaseObjects(ctx: *JSContext) void;
|
|
pub extern fn JS_AddIntrinsicDate(ctx: *JSContext) void;
|
|
pub extern fn JS_AddIntrinsicEval(ctx: *JSContext) void;
|
|
pub extern fn JS_AddIntrinsicStringNormalize(ctx: *JSContext) void;
|
|
pub extern fn JS_AddIntrinsicRegExpCompiler(ctx: *JSContext) void;
|
|
pub extern fn JS_AddIntrinsicRegExp(ctx: *JSContext) void;
|
|
pub extern fn JS_AddIntrinsicJSON(ctx: *JSContext) void;
|
|
pub extern fn JS_AddIntrinsicProxy(ctx: *JSContext) void;
|
|
pub extern fn JS_AddIntrinsicMapSet(ctx: *JSContext) void;
|
|
pub extern fn JS_AddIntrinsicTypedArrays(ctx: *JSContext) void;
|
|
pub extern fn JS_AddIntrinsicPromise(ctx: *JSContext) void;
|
|
pub extern fn JS_AddIntrinsicWeakRef(ctx: *JSContext) void;
|
|
|
|
pub extern fn js_malloc_rt(rt: *JSRuntime, size: usize) ?*anyopaque;
|
|
pub extern fn js_free_rt(rt: *JSRuntime, ptr: ?*anyopaque) void;
|
|
pub extern fn js_realloc_rt(rt: *JSRuntime, ptr: ?*anyopaque, size: usize) ?*anyopaque;
|
|
pub extern fn js_malloc_usable_size_rt(rt: *JSRuntime, ptr: ?*const anyopaque) usize;
|
|
pub extern fn js_mallocz_rt(rt: *JSRuntime, size: usize) ?*anyopaque;
|
|
|
|
pub extern fn js_malloc(ctx: *JSContext, size: usize) ?*anyopaque;
|
|
pub extern fn js_free(ctx: *JSContext, ptr: ?*anyopaque) void;
|
|
pub extern fn js_realloc(ctx: *JSContext, ptr: ?*anyopaque, size: usize) ?*anyopaque;
|
|
pub extern fn js_malloc_usable_size(ctx: *JSContext, ptr: ?*const anyopaque) usize;
|
|
pub extern fn js_realloc2(ctx: *JSContext, ptr: ?*anyopaque, size: usize, pslack: ?*usize) ?*anyopaque;
|
|
pub extern fn js_mallocz(ctx: *JSContext, size: usize) ?*anyopaque;
|
|
pub extern fn js_strdup(ctx: *JSContext, str: [*:0]const u8) ?[*:0]u8;
|
|
pub extern fn js_strndup(ctx: *JSContext, s: [*]const u8, n: usize) ?[*]u8;
|
|
|
|
pub const JSMemoryUsage = extern struct {
|
|
malloc_size: i64,
|
|
malloc_limit: i64,
|
|
memory_used_size: i64,
|
|
malloc_count: i64,
|
|
memory_used_count: i64,
|
|
atom_count: i64,
|
|
atom_size: i64,
|
|
str_count: i64,
|
|
str_size: i64,
|
|
obj_count: i64,
|
|
obj_size: i64,
|
|
prop_count: i64,
|
|
prop_size: i64,
|
|
shape_count: i64,
|
|
shape_size: i64,
|
|
js_func_count: i64,
|
|
js_func_size: i64,
|
|
js_func_code_size: i64,
|
|
js_func_pc2line_count: i64,
|
|
js_func_pc2line_size: i64,
|
|
c_func_count: i64,
|
|
array_count: i64,
|
|
fast_array_count: i64,
|
|
fast_array_elements: i64,
|
|
binary_object_count: i64,
|
|
binary_object_size: i64,
|
|
};
|
|
|
|
pub extern fn JS_ComputeMemoryUsage(rt: *JSRuntime, s: *JSMemoryUsage) void;
|
|
pub extern fn JS_DumpMemoryUsage(fp: *std.c.FILE, s: *const JSMemoryUsage, rt: ?*JSRuntime) void;
|
|
|
|
pub const JS_ATOM_NULL: JSAtom = 0;
|
|
|
|
pub extern fn JS_NewAtomLen(ctx: *JSContext, str: [*]const u8, len: usize) JSAtom;
|
|
pub extern fn JS_NewAtom(ctx: *JSContext, str: [*:0]const u8) JSAtom;
|
|
pub extern fn JS_NewAtomUInt32(ctx: *JSContext, n: u32) JSAtom;
|
|
pub extern fn JS_DupAtom(ctx: *JSContext, v: JSAtom) JSAtom;
|
|
pub extern fn JS_FreeAtom(ctx: *JSContext, v: JSAtom) void;
|
|
pub extern fn JS_FreeAtomRT(rt: *JSRuntime, v: JSAtom) void;
|
|
pub extern fn JS_AtomToValue(ctx: *JSContext, atom: JSAtom) JSValue;
|
|
pub extern fn JS_AtomToString(ctx: *JSContext, atom: JSAtom) JSValue;
|
|
pub extern fn JS_AtomToCStringLen(ctx: *JSContext, plen: ?*usize, atom: JSAtom) ?[*:0]const u8;
|
|
pub inline fn JS_AtomToCString(ctx: *JSContext, atom: JSAtom) ?[*:0]const u8 {
|
|
return JS_AtomToCStringLen(ctx, null, atom);
|
|
}
|
|
pub extern fn JS_ValueToAtom(ctx: *JSContext, val: JSValue) JSAtom;
|
|
|
|
pub const JSPropertyEnum = extern struct {
|
|
is_enumerable: JS_BOOL,
|
|
atom: JSAtom,
|
|
};
|
|
|
|
pub const JSPropertyDescriptor = extern struct {
|
|
flags: JS_PROP,
|
|
value: JSValue,
|
|
getter: JSValue,
|
|
setter: JSValue,
|
|
};
|
|
|
|
pub const JSClassExoticMethods = extern struct {
|
|
/// Return -1 if exception (can only happen in case of Proxy object), 0
|
|
/// if the property does not exists, 1 if it exists. If 1 is returned,
|
|
/// the property descriptor 'desc' is filled if != NULL.
|
|
get_own_property: ?*const fn (ctx: *JSContext, desc: *JSPropertyDescriptor, obj: JSValueConst, prop: JSAtom) callconv(.c) i32 = null,
|
|
/// `ptab.*` should hold the `plen.*` property keys. Return 0 if OK, -1
|
|
/// if exception. The `is_enumerable` field is ignored.
|
|
get_own_property_names: ?*const fn (ctx: *JSContext, ptab: *[*]JSPropertyEnum, plen: *u32, obj: JSValueConst) callconv(.c) i32 = null,
|
|
/// return < 0 if exception or 1/0
|
|
delete_property: ?*const fn (ctx: *JSContext, obj: JSValueConst, prop: JSAtom) callconv(.c) i32 = null,
|
|
/// return < 0 if exception or 1/0
|
|
define_own_property: ?*const fn (ctx: *JSContext, this_obj: JSValueConst, prop: JSAtom, val: JSValueConst, getter: JSValueConst, setter: JSValueConst, flags: JS_PROP) callconv(.c) i32 = null,
|
|
|
|
// The following methods can be emulated with the previous ones, so they
|
|
// are usually not needed.
|
|
|
|
/// return < 0 if exception or 1/0
|
|
has_property: ?*const fn (ctx: *JSContext, obj: JSValueConst, prop: JSAtom) callconv(.c) i32 = null,
|
|
get_property: ?*const fn (ctx: *JSContext, obj: JSValueConst, prop: JSAtom, receiver: JSValueConst) callconv(.c) JSValue = null,
|
|
/// return < 0 if exception or 1/0
|
|
set_property: ?*const fn (ctx: *JSContext, obj: JSValueConst, atom: JSAtom, value: JSValueConst, receiver: JSValueConst, flags: JS_PROP) callconv(.c) i32 = null,
|
|
/// To get a consistent object behavior when get_prototype != null,
|
|
/// get_property, set_property and set_prototype must be != null and the
|
|
/// object must be created with a JS_NULL prototype.
|
|
get_prototype: ?*const fn (ctx: *JSContext, obj: JSValueConst) callconv(.c) JSValue = null,
|
|
/// return < 0 if exception or 1/0
|
|
set_prototype: ?*const fn (ctx: *JSContext, obj: JSValueConst, proto_val: JSValueConst) callconv(.c) i32 = null,
|
|
/// return < 0 if exception or 1/0
|
|
is_extensible: ?*const fn (ctx: *JSContext, obj: JSValueConst) callconv(.c) i32 = null,
|
|
/// return < 0 if exception or 1/0
|
|
prevent_extensions: ?*const fn (ctx: *JSContext, obj: JSValueConst) callconv(.c) i32 = null,
|
|
};
|
|
|
|
pub const JS_CALL_FLAG = packed struct(u32) {
|
|
constructor: bool = false,
|
|
_pad1: u31 = 0,
|
|
};
|
|
|
|
pub const JSClassFinalizer = fn (rt: *JSRuntime, val: JSValue) callconv(.c) void;
|
|
pub const JSClassGCMark = fn (rt: *JSRuntime, val: JSValueConst, mark_func: *const JS_MarkFunc) void;
|
|
pub const JSClassCall = fn (ctx: *JSContext, func_obj: JSValueConst, this_val: JSValueConst, argc: i32, argv: [*]JSValueConst, flags: JS_CALL_FLAG) JSValue;
|
|
|
|
pub const JSClassDef = extern struct {
|
|
class_name: [*:0]const u8,
|
|
finalizer: ?*const JSClassFinalizer,
|
|
gc_mark: ?*const JSClassGCMark,
|
|
/// if `call != null`, the object is a function. If
|
|
/// `flags.constructor == true`, the function is called as a
|
|
/// constructor. In this case, `this_val` is new.target. A constructor
|
|
/// call only happens if the object constructor bit is set (see
|
|
/// `JS_SetConstructorBit`).
|
|
call: ?*const JSClassCall,
|
|
exotic: ?*const JSClassExoticMethods,
|
|
};
|
|
|
|
pub const JS_INVALID_CLASS_ID: JSClassID = 0;
|
|
|
|
pub extern fn JS_NewClassID(pclass_id: *JSClassID) JSClassID;
|
|
/// Returns the class ID if `v` is an object, otherwise returns
|
|
/// `JS_INVALID_CLASS_ID`.
|
|
pub extern fn JS_GetClassID(v: JSValue) JSClassID;
|
|
pub extern fn JS_NewClass(rt: *JSRuntime, class_id: JSClassID, class_def: *const JSClassDef) i32;
|
|
pub extern fn JS_IsRegisteredClass(rt: ?*JSRuntime, class_id: JSClassID) i32;
|
|
|
|
pub inline fn JS_NewBool(ctx: *JSContext, val: JS_BOOL) JSValue {
|
|
_ = ctx;
|
|
return JS_MKVAL(JS_TAG.BOOL, @intFromBool(val != 0));
|
|
}
|
|
|
|
pub inline fn JS_NewInt32(ctx: *JSContext, val: i32) JSValue {
|
|
_ = ctx;
|
|
return JS_MKVAL(JS_TAG.INT, val);
|
|
}
|
|
|
|
pub inline fn JS_NewCatchOffset(ctx: *JSContext, val: i32) JSValue {
|
|
_ = ctx;
|
|
return JS_MKVAL(JS_TAG.CATCH_OFFSET, val);
|
|
}
|
|
|
|
pub inline fn JS_NewInt64(ctx: *JSContext, val: i64) JSValue {
|
|
if (val == @as(i64, @as(i32, @truncate(val)))) {
|
|
return JS_NewInt32(ctx, @truncate(val));
|
|
} else {
|
|
return __JS_NewFloat64(ctx, @floatFromInt(val));
|
|
}
|
|
}
|
|
|
|
pub inline fn JS_NewUint32(ctx: *JSContext, val: u32) JSValue {
|
|
if (val <= 0x7FFFFFFF) {
|
|
return JS_NewInt32(ctx, @intCast(val));
|
|
} else {
|
|
return JS_NewFloat64(ctx, @floatFromInt(val));
|
|
}
|
|
}
|
|
|
|
pub inline fn JS_NewFloat64(ctx: *JSContext, d: f64) JSValue {
|
|
if (d >= @as(f64, @floatFromInt(std.math.minInt(i32))) and d <= @as(f64, @floatFromInt(std.math.maxInt(i32)))) {
|
|
const val: i32 = @intFromFloat(d);
|
|
// -0 cannot be represented as integer, so we compare the bit representation
|
|
if (@as(u64, @bitCast(d)) == @as(u64, @bitCast(@as(f64, @floatFromInt(val))))) {
|
|
return JS_MKVAL(JS_TAG.INT, val);
|
|
}
|
|
}
|
|
return __JS_NewFloat64(ctx, d);
|
|
}
|
|
|
|
pub extern fn JS_NewBigInt64(ctx: *JSContext, v: i64) JSValue;
|
|
pub extern fn JS_NewBigUint64(ctx: *JSContext, v: u64) JSValue;
|
|
|
|
pub inline fn JS_IsNumber(v: JSValue) bool {
|
|
const tag = JS_VALUE_GET_TAG(v);
|
|
return tag == JS_TAG.INT or JS_TAG_IS_FLOAT64(tag);
|
|
}
|
|
|
|
pub inline fn JS_IsBigInt(v: JSValue) bool {
|
|
const tag = JS_VALUE_GET_TAG(v);
|
|
return tag == JS_TAG.BIG_INT or tag == JS_TAG.SHORT_BIG_INT;
|
|
}
|
|
|
|
pub inline fn JS_IsBool(v: JSValue) bool {
|
|
return JS_VALUE_GET_TAG(v) == JS_TAG.BOOL;
|
|
}
|
|
|
|
pub inline fn JS_IsNull(v: JSValue) bool {
|
|
return JS_VALUE_GET_TAG(v) == JS_TAG.NULL;
|
|
}
|
|
|
|
pub inline fn JS_IsUndefined(v: JSValue) bool {
|
|
return JS_VALUE_GET_TAG(v) == JS_TAG.UNDEFINED;
|
|
}
|
|
|
|
pub inline fn JS_IsException(v: JSValue) bool {
|
|
if (JS_VALUE_GET_TAG(v) == JS_TAG.EXCEPTION) {
|
|
@branchHint(.unlikely);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
pub inline fn JS_IsUninitialized(v: JSValue) bool {
|
|
if (JS_VALUE_GET_TAG(v) == JS_TAG.UNINITIALIZED) {
|
|
@branchHint(.unlikely);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
pub inline fn JS_IsString(v: JSValue) bool {
|
|
return JS_VALUE_GET_TAG(v) == JS_TAG.STRING or JS_VALUE_GET_TAG(v) == JS_TAG.STRING_ROPE;
|
|
}
|
|
|
|
pub inline fn JS_IsSymbol(v: JSValue) bool {
|
|
return JS_VALUE_GET_TAG(v) == JS_TAG.SYMBOL;
|
|
}
|
|
|
|
pub inline fn JS_IsObject(v: JSValue) bool {
|
|
return JS_VALUE_GET_TAG(v) == JS_TAG.OBJECT;
|
|
}
|
|
|
|
pub extern fn JS_Throw(ctx: *JSContext, obj: JSValue) JSValue;
|
|
pub extern fn JS_SetUncatchableException(ctx: *JSContext, flag: JS_BOOL) void;
|
|
pub extern fn JS_GetException(ctx: *JSContext) JSValue;
|
|
pub extern fn JS_HasException(ctx: *JSContext) JS_BOOL;
|
|
pub extern fn JS_IsError(ctx: *JSContext, val: JSValue) JS_BOOL;
|
|
pub extern fn JS_NewError(ctx: *JSContext) JSValue;
|
|
pub extern fn JS_ThrowSyntaxError(ctx: *JSContext, fmt: [*:0]const u8, ...) JSValue;
|
|
pub extern fn JS_ThrowTypeError(ctx: *JSContext, fmt: [*:0]const u8, ...) JSValue;
|
|
pub extern fn JS_ThrowReferenceError(ctx: *JSContext, fmt: [*:0]const u8, ...) JSValue;
|
|
pub extern fn JS_ThrowRangeError(ctx: *JSContext, fmt: [*:0]const u8, ...) JSValue;
|
|
pub extern fn JS_ThrowInternalError(ctx: *JSContext, fmt: [*:0]const u8, ...) JSValue;
|
|
pub extern fn JS_ThrowOutOfMemory(ctx: *JSContext) JSValue;
|
|
|
|
pub extern fn __JS_FreeValue(ctx: *JSContext, v: JSValue) void;
|
|
pub extern fn __JS_FreeValueRT(rt: *JSRuntime, v: JSValue) void;
|
|
|
|
pub inline fn JS_FreeValue(ctx: *JSContext, v: JSValue) void {
|
|
if (JS_VALUE_HAS_REF_COUNT(v)) {
|
|
const p: *JSRefCountHeader = @ptrCast(@alignCast(JS_VALUE_GET_PTR(v).?));
|
|
p.ref_count -= 1;
|
|
if (p.ref_count <= 0) {
|
|
__JS_FreeValue(ctx, v);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub inline fn JS_FreeValueRT(rt: *JSRuntime, v: JSValue) void {
|
|
if (JS_VALUE_HAS_REF_COUNT(v)) {
|
|
const p: *JSRefCountHeader = @ptrCast(@alignCast(JS_VALUE_GET_PTR(v).?));
|
|
p.ref_count -= 1;
|
|
if (p.ref_count <= 0) {
|
|
__JS_FreeValueRT(rt, v);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub inline fn JS_DupValue(ctx: *JSContext, v: JSValueConst) JSValue {
|
|
_ = ctx;
|
|
if (JS_VALUE_HAS_REF_COUNT(v)) {
|
|
const p: *JSRefCountHeader = @ptrCast(@alignCast(JS_VALUE_GET_PTR(v).?));
|
|
p.ref_count += 1;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
pub inline fn JS_DupValueRT(rt: *JSRuntime, v: JSValueConst) JSValue {
|
|
_ = rt;
|
|
if (JS_VALUE_HAS_REF_COUNT(v)) {
|
|
const p: *JSRefCountHeader = @ptrCast(@alignCast(JS_VALUE_GET_PTR(v).?));
|
|
p.ref_count += 1;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
pub extern fn JS_StrictEq(ctx: *JSContext, op1: JSValue, op2: JSValue) JS_BOOL;
|
|
pub extern fn JS_SameValue(ctx: *JSContext, op1: JSValue, op2: JSValue) JS_BOOL;
|
|
pub extern fn JS_SameValueZero(ctx: *JSContext, op1: JSValue, op2: JSValue) JS_BOOL;
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
pub extern fn JS_NewObject(ctx: *JSContext) JSValue;
|
|
pub extern fn JS_NewObjectProto(ctx: *JSContext, proto: JSValueConst) JSValue;
|
|
|
|
pub extern fn JS_IsFunction(ctx: *JSContext, val: JSValueConst) JS_BOOL;
|
|
pub extern fn JS_IsConstructor(ctx: *JSContext, val: JSValueConst) JS_BOOL;
|
|
pub extern fn JS_SetConstructorBit(ctx: *JSContext, func_obj: JSValueConst, val: JS_BOOL) JS_BOOL;
|
|
|
|
pub extern fn JS_NewArray(ctx: *JSContext) JSValue;
|
|
pub extern fn JS_IsArray(ctx: *JSContext, val: JSValue) JS_BOOL;
|
|
|
|
pub extern fn JS_NewDate(ctx: *JSContext, epoch_ms: f64) JSValue;
|
|
|
|
pub extern fn JS_Eval(ctx: *JSContext, input: [*:0]const u8, input_len: usize, filename: [*:0]const u8, eval_flags: JS_EVAL) JSValue;
|
|
pub extern fn JS_EvalThis(ctx: *JSContext, this_obj: JSValue, input: [*:0]const u8, input_len: usize, filename: [*:0]const u8, eval_flags: JS_EVAL) JSValue;
|
|
};
|
|
|
|
pub const Allocator = struct {
|
|
const alignment_bytes = 16;
|
|
const alignment: std.mem.Alignment = .fromByteUnits(alignment_bytes);
|
|
|
|
const AllocationPtr = *align(alignment_bytes) anyopaque;
|
|
const AllocationSlice = []align(alignment_bytes) u8;
|
|
const LengthPtr = *align(alignment_bytes) usize;
|
|
|
|
const Allocation = struct {
|
|
allocation_ptr: AllocationPtr,
|
|
|
|
pub fn fromAllocationSlice(slice: AllocationSlice) Allocation {
|
|
return .{
|
|
.allocation_ptr = @ptrCast(slice.ptr),
|
|
};
|
|
}
|
|
|
|
pub fn fromForeignPtr(ptr: *anyopaque) Allocation {
|
|
return .{
|
|
.allocation_ptr = @ptrCast(@alignCast(@as([*]u8, @ptrCast(ptr)) - alignment_bytes)),
|
|
};
|
|
}
|
|
|
|
pub fn getAllocationSize(self: Allocation) usize {
|
|
return @as(LengthPtr, @ptrCast(self.allocation_ptr)).*;
|
|
}
|
|
|
|
pub fn setAllocationSize(self: Allocation, allocation_size: usize) void {
|
|
@as(LengthPtr, @ptrCast(self.allocation_ptr)).* = allocation_size;
|
|
}
|
|
|
|
pub fn toAllocationSlice(self: Allocation) AllocationSlice {
|
|
return @alignCast(@as([*]u8, @ptrCast(self.allocation_ptr))[0..self.getAllocationSize()]);
|
|
}
|
|
|
|
pub fn toForeignPtr(self: Allocation) *anyopaque {
|
|
return @ptrCast(@alignCast(@as([*]u8, @ptrCast(self.allocation_ptr)) + alignment_bytes));
|
|
}
|
|
};
|
|
|
|
pub const adapter: *const import.JSMallocFunctions = &.{
|
|
.js_malloc = &js_malloc,
|
|
.js_free = &js_free,
|
|
.js_realloc = &js_realloc,
|
|
.js_malloc_usable_size = null,
|
|
};
|
|
|
|
fn js_malloc(s: *import.JSMallocState, size: usize) callconv(.c) ?*anyopaque {
|
|
const allocator: *const std.mem.Allocator = @ptrCast(@alignCast(s.@"opaque".?));
|
|
|
|
const allocation_size = alignment_bytes + size;
|
|
const allocation_slice: AllocationSlice = allocator.alignedAlloc(u8, alignment, allocation_size) catch return null;
|
|
|
|
const allocation = Allocation.fromAllocationSlice(allocation_slice);
|
|
allocation.setAllocationSize(allocation_size);
|
|
|
|
return allocation.toForeignPtr();
|
|
}
|
|
|
|
fn js_free(s: *import.JSMallocState, maybe_foreign_ptr: ?*anyopaque) callconv(.c) void {
|
|
if (maybe_foreign_ptr) |foreign_ptr| {
|
|
const allocator: *const std.mem.Allocator = @ptrCast(@alignCast(s.@"opaque".?));
|
|
|
|
const allocation = Allocation.fromForeignPtr(foreign_ptr);
|
|
const allocation_slice = allocation.toAllocationSlice();
|
|
|
|
allocator.free(allocation_slice);
|
|
}
|
|
}
|
|
|
|
fn js_realloc(s: *import.JSMallocState, maybe_foreign_ptr: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque {
|
|
if (maybe_foreign_ptr) |foreign_ptr| {
|
|
const allocator: *const std.mem.Allocator = @ptrCast(@alignCast(s.@"opaque".?));
|
|
|
|
const old_allocation = Allocation.fromForeignPtr(foreign_ptr);
|
|
const old_allocation_slice = old_allocation.toAllocationSlice();
|
|
|
|
if (size > 0) {
|
|
const new_allocation_size = alignment_bytes + size;
|
|
const new_allocation_slice = allocator.realloc(old_allocation_slice, new_allocation_size) catch return null;
|
|
|
|
const new_allocation = Allocation.fromAllocationSlice(new_allocation_slice);
|
|
new_allocation.setAllocationSize(new_allocation_size);
|
|
|
|
return new_allocation.toForeignPtr();
|
|
} else {
|
|
allocator.free(old_allocation_slice);
|
|
return null;
|
|
}
|
|
} else {
|
|
return js_malloc(s, size);
|
|
}
|
|
}
|
|
};
|
|
|
|
pub const Runtime = extern struct {
|
|
runtime: *import.JSRuntime,
|
|
|
|
pub fn newRuntime() error{OutOfMemory}!Runtime {
|
|
if (import.JS_NewRuntime()) |runtime| {
|
|
return .{ .runtime = runtime };
|
|
} else {
|
|
return error.OutOfMemory;
|
|
}
|
|
}
|
|
|
|
/// Create a new runtime with provided allocator.
|
|
///
|
|
/// `std.mem.Allocator` is a fat pointer, i.e. two pointers in a struct,
|
|
/// usually passed around as value. However, QuickJS only supports a single
|
|
/// context pointer. Therefore, you have to allocate the fat pointer
|
|
/// structure yourself (e.g. as a stack variable) and provide a pointer to
|
|
/// it. The pointer must be valid as long as the runtime is being used.
|
|
pub fn newRuntimeAllocator(allocator: *const std.mem.Allocator) error{OutOfMemory}!Runtime {
|
|
if (import.JS_NewRuntime2(Allocator.adapter, @ptrCast(@constCast(allocator)))) |runtime| {
|
|
return .{ .runtime = runtime };
|
|
} else {
|
|
return error.OutOfMemory;
|
|
}
|
|
}
|
|
|
|
/// The lifetime of `info` must exceed that of `self`.
|
|
pub fn setRuntimeinfo(self: Runtime, info: [*:0]const u8) void {
|
|
import.JS_SetRuntimeInfo(self.runtime, info);
|
|
}
|
|
|
|
pub fn setMemoryLimit(self: Runtime, limit: usize) void {
|
|
import.JS_SetMemoryLimit(self.runtime, limit);
|
|
}
|
|
|
|
pub fn setGcThreshold(self: Runtime, gc_threshold: usize) void {
|
|
import.JS_SetGCThreshold(self.runtime, gc_threshold);
|
|
}
|
|
|
|
/// Use `0` to disable maximum stack size check.
|
|
pub fn setMaxStackSize(self: Runtime, stack_size: usize) void {
|
|
import.JS_SetMaxStackSize(self.runtime, stack_size);
|
|
}
|
|
|
|
/// Should be called when changing thread to update the stack top value used
|
|
/// to check stack overflow.
|
|
pub fn updateStackTop(self: Runtime) void {
|
|
import.JS_UpdateStackTop(self.runtime);
|
|
}
|
|
|
|
pub fn freeRuntime(self: *Runtime) void {
|
|
import.JS_FreeRuntime(self.runtime);
|
|
self.* = undefined;
|
|
}
|
|
|
|
pub fn getRuntimeOpaque(self: Runtime) ?*anyopaque {
|
|
return import.JS_GetRuntimeOpaque(self.runtime);
|
|
}
|
|
|
|
pub fn setRuntimeOpaque(self: Runtime, @"opaque": ?*anyopaque) void {
|
|
import.JS_SetRuntimeOpaque(self.runtime, @"opaque");
|
|
}
|
|
|
|
pub fn markValue(self: Runtime, value: Value, mark_func: *const import.JS_MarkFunc) void {
|
|
import.JS_MarkValue(self.runtime, value.value, mark_func);
|
|
}
|
|
|
|
pub fn runGc(self: Runtime) void {
|
|
import.JS_RunGC(self.runtime);
|
|
}
|
|
|
|
pub fn isLiveObject(self: Runtime, object: Value) bool {
|
|
return import.JS_IsLiveObject(self.runtime, object.value) != 0;
|
|
}
|
|
|
|
pub fn newContext(self: Runtime) error{OutOfMemory}!Context {
|
|
if (import.JS_NewContext(self.runtime)) |context| {
|
|
return .{ .context = context };
|
|
} else {
|
|
return error.OutOfMemory;
|
|
}
|
|
}
|
|
|
|
pub fn newContextRaw(self: Runtime) error{OutOfMemory}!Context {
|
|
if (import.JS_NewContextRaw(self.runtime)) |context| {
|
|
return .{ .context = context };
|
|
} else {
|
|
return error.OutOfMemory;
|
|
}
|
|
}
|
|
|
|
pub fn malloc(self: Runtime, size: usize) error{OutOfMemory}!*anyopaque {
|
|
return import.js_malloc_rt(self.runtime, size) orelse error.OutOfMemory;
|
|
}
|
|
|
|
pub fn free(self: Runtime, ptr: ?*anyopaque) void {
|
|
import.js_free_rt(self.runtime, ptr);
|
|
}
|
|
|
|
pub fn realloc(self: Runtime, ptr: ?*anyopaque, size: usize) error{OutOfMemory}!*anyopaque {
|
|
return import.js_realloc_rt(self.runtime, ptr, size) orelse error.OutOfMemory;
|
|
}
|
|
|
|
pub fn mallocUsableSize(self: Runtime, ptr: ?*const anyopaque) usize {
|
|
return import.js_malloc_usable_size_rt(self.runtime, ptr);
|
|
}
|
|
|
|
pub fn mallocz(self: Runtime, size: usize) error{OutOfMemory}!*anyopaque {
|
|
return import.js_mallocz_rt(self.runtime, size) orelse error.OutOfMemory;
|
|
}
|
|
|
|
pub fn computeMemoryUsage(self: Runtime) import.JSMemoryUsage {
|
|
var ret: import.JSMemoryUsage = undefined;
|
|
import.JS_ComputeMemoryUsage(self.runtime, &ret);
|
|
return ret;
|
|
}
|
|
|
|
pub fn freeAtom(self: Runtime, v: Atom) void {
|
|
import.JS_FreeAtomRT(self.runtime, v.atom);
|
|
}
|
|
|
|
pub fn newClass(self: Runtime, class_id: ClassId, class_def: *const import.JSClassDef) error{Exception}!void {
|
|
const res = import.JS_NewClass(self.runtime, class_id.class_id, class_def);
|
|
if (res < 0) {
|
|
return error.Exception;
|
|
}
|
|
}
|
|
|
|
pub fn isRegisteredClass(self: Runtime, class_id: ClassId) bool {
|
|
return import.JS_IsRegisteredClass(self.runtime, class_id.class_id) != 0;
|
|
}
|
|
|
|
pub fn freeValue(self: Runtime, v: Value) void {
|
|
import.JS_FreeValueRT(self.runtime, v.value);
|
|
}
|
|
|
|
pub fn dupValue(self: Runtime, v: Value) Value {
|
|
return .{ .value = import.JS_DupValueRT(self.runtime, v.value) };
|
|
}
|
|
};
|
|
|
|
pub const Context = extern struct {
|
|
context: *import.JSContext,
|
|
|
|
pub fn freeContext(self: *Context) void {
|
|
import.JS_FreeContext(self.context);
|
|
self.* = undefined;
|
|
}
|
|
|
|
pub fn dupContext(self: Context) error{OutOfMemory}!Context {
|
|
if (import.JS_DupContext(self.context)) |context| {
|
|
return .{ .context = context };
|
|
} else {
|
|
return error.OutOfMemory;
|
|
}
|
|
}
|
|
|
|
pub fn getContextOpaque(self: Context) ?*anyopaque {
|
|
return import.JS_GetContextOpaque(self.context);
|
|
}
|
|
|
|
pub fn setContextOpaque(self: Context, @"opaque": ?*anyopaque) void {
|
|
import.JS_SetContextOpaque(self.context, @"opaque");
|
|
}
|
|
|
|
pub fn getRuntime(self: Context) Runtime {
|
|
return .{ .runtime = import.JS_GetRuntime(self.context) };
|
|
}
|
|
|
|
pub fn setClassProto(self: Context, class_id: import.JSClassID, object: Value) void {
|
|
import.JS_SetClassProto(self.context, class_id, object.value);
|
|
}
|
|
|
|
pub fn getClassProto(self: Context, class_id: import.JSClassID) Value {
|
|
return .{ .value = import.JS_GetClassProto(self.context, class_id) };
|
|
}
|
|
|
|
pub fn addIntrinsicBaseObjects(self: Context) void {
|
|
import.JS_AddIntrinsicBaseObjects(self.context);
|
|
}
|
|
|
|
pub fn addIntrinsicDate(self: Context) void {
|
|
import.JS_AddIntrinsicDate(self.context);
|
|
}
|
|
|
|
pub fn addIntrinsicEval(self: Context) void {
|
|
import.JS_AddIntrinsicEval(self.context);
|
|
}
|
|
|
|
pub fn addIntrinsicStringNormalize(self: Context) void {
|
|
import.JS_AddIntrinsicStringNormalize(self.context);
|
|
}
|
|
|
|
pub fn addIntrinsicRegExpCompiler(self: Context) void {
|
|
import.JS_AddIntrinsicRegExpCompiler(self.context);
|
|
}
|
|
|
|
pub fn addIntrinsicRegExp(self: Context) void {
|
|
import.JS_AddIntrinsicRegExp(self.context);
|
|
}
|
|
|
|
pub fn addIntrinsicJSON(self: Context) void {
|
|
import.JS_AddIntrinsicJSON(self.context);
|
|
}
|
|
|
|
pub fn addIntrinsicProxy(self: Context) void {
|
|
import.JS_AddIntrinsicProxy(self.context);
|
|
}
|
|
|
|
pub fn addIntrinsicMapSet(self: Context) void {
|
|
import.JS_AddIntrinsicMapSet(self.context);
|
|
}
|
|
|
|
pub fn addIntrinsicTypedArrays(self: Context) void {
|
|
import.JS_AddIntrinsicTypedArrays(self.context);
|
|
}
|
|
|
|
pub fn addIntrinsicPromise(self: Context) void {
|
|
import.JS_AddIntrinsicPromise(self.context);
|
|
}
|
|
|
|
pub fn addIntrinsicWeakRef(self: Context) void {
|
|
import.JS_AddIntrinsicWeakRef(self.context);
|
|
}
|
|
|
|
pub fn malloc(self: Context, size: usize) error{OutOfMemory}!*anyopaque {
|
|
return import.js_malloc(self.context, size) orelse error.OutOfMemory;
|
|
}
|
|
|
|
pub fn free(self: Context, ptr: ?*anyopaque) void {
|
|
import.js_free(self.context, ptr);
|
|
}
|
|
|
|
pub fn realloc(self: Context, ptr: ?*anyopaque, size: usize) error{OutOfMemory}!*anyopaque {
|
|
return import.js_realloc(self.context, ptr, size) orelse error.OutOfMemory;
|
|
}
|
|
|
|
pub fn mallocUsableSize(self: Context, ptr: ?*const anyopaque) usize {
|
|
return import.js_malloc_usable_size(self.context, ptr);
|
|
}
|
|
|
|
pub const Realloc2Result = struct {
|
|
ptr: *anyopaque,
|
|
slack: usize,
|
|
};
|
|
|
|
pub fn realloc2(self: Context, ptr: ?*anyopaque, size: usize) error{OutOfMemory}!Realloc2Result {
|
|
var slack: usize = undefined;
|
|
if (import.js_realloc2(self.context, ptr, size, &slack)) |next_ptr| {
|
|
return .{ .ptr = next_ptr, .slack = slack };
|
|
} else {
|
|
return error.OutOfMemory;
|
|
}
|
|
}
|
|
|
|
pub fn mallocz(self: Context, size: usize) error{OutOfMemory}!*anyopaque {
|
|
return import.js_mallocz(self.context, size) orelse error.OutOfMemory;
|
|
}
|
|
|
|
pub fn strdup(self: Context, str: [*:0]const u8) error{OutOfMemory}![*:0]u8 {
|
|
return import.js_strdup(self.context, str) orelse error.OutOfMemory;
|
|
}
|
|
|
|
pub fn strndup(self: Context, s: [*]const u8, n: usize) error{OutOfMemory}![*]u8 {
|
|
return import.js_strndup(self.context, s, n) orelse error.OutOfMemory;
|
|
}
|
|
|
|
pub fn newAtomLen(self: Context, str: []const u8) Atom {
|
|
return .{ .atom = import.JS_NewAtomLen(self.context, str.ptr, str.len) };
|
|
}
|
|
|
|
pub fn newAtom(self: Context, str: [*:0]const u8) Atom {
|
|
return .{ .atom = import.JS_NewAtom(self.context, str) };
|
|
}
|
|
|
|
pub fn newAtomUInt32(self: Context, n: u32) Atom {
|
|
return .{ .atom = import.JS_NewAtomUInt32(self.context, n) };
|
|
}
|
|
|
|
pub fn dupAtom(self: Context, v: Atom) Atom {
|
|
return .{ .atom = import.JS_DupAtom(self.context, v.atom) };
|
|
}
|
|
|
|
pub fn freeAtom(self: Context, v: Atom) void {
|
|
import.JS_FreeAtom(self.context, v.atom);
|
|
}
|
|
|
|
pub fn atomToValue(self: Context, atom: Atom) Value {
|
|
return .{ .value = import.JS_AtomToValue(self.context, atom.atom) };
|
|
}
|
|
|
|
pub fn atomToString(self: Context, atom: Atom) Value {
|
|
return .{ .value = import.JS_AtomToString(self.context, atom.atom) };
|
|
}
|
|
|
|
pub fn atomToCString(self: Context, atom: Atom) ?[:0]const u8 {
|
|
var len: usize = undefined;
|
|
if (import.JS_AtomToCStringLen(self.context, &len, atom.atom)) |ptr| {
|
|
return ptr[0..len :0];
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
pub fn valueToAtom(self: Context, val: Value) Atom {
|
|
return .{ .atom = import.JS_ValueToAtom(self.context, val.value) };
|
|
}
|
|
|
|
pub fn newBool(self: Context, val: bool) Value {
|
|
return .{ .value = import.JS_NewBool(self.context, @intFromBool(val)) };
|
|
}
|
|
|
|
pub fn newInt32(self: Context, val: i32) Value {
|
|
return .{ .value = import.JS_NewInt32(self.context, val) };
|
|
}
|
|
|
|
pub fn newCatchOffset(self: Context, val: i32) Value {
|
|
return .{ .value = import.JS_NewCatchOffset(self.context, val) };
|
|
}
|
|
|
|
pub fn newInt64(self: Context, val: i64) Value {
|
|
return .{ .value = import.JS_NewInt64(self.context, val) };
|
|
}
|
|
|
|
pub fn newUint32(self: Context, val: u32) Value {
|
|
return .{ .value = import.JS_NewUint32(self.context, val) };
|
|
}
|
|
|
|
pub fn newFloat64(self: Context, val: f64) Value {
|
|
return .{ .value = import.JS_NewFloat64(self.context, val) };
|
|
}
|
|
|
|
pub fn newBigInt64(self: Context, val: i64) Value {
|
|
return .{ .value = import.JS_NewBigInt64(self.context, val) };
|
|
}
|
|
|
|
pub fn throw(self: Context, obj: Value) Value {
|
|
return .{ .value = import.JS_Throw(self.context, obj.value) };
|
|
}
|
|
|
|
pub fn setUncatchableException(self: Context, flag: bool) void {
|
|
import.JS_SetUncatchableException(self.context, @intFromBool(flag));
|
|
}
|
|
|
|
pub fn getException(self: Context) Value {
|
|
return .{ .value = import.JS_GetException(self.context) };
|
|
}
|
|
|
|
pub fn hasException(self: Context) bool {
|
|
return import.JS_HasException(self.context) != 0;
|
|
}
|
|
|
|
pub fn isError(self: Context, val: Value) bool {
|
|
return import.JS_IsError(self.context, val.value) != 0;
|
|
}
|
|
|
|
pub fn newError(self: Context) Value {
|
|
return .{ .value = import.JS_NewError(self.context) };
|
|
}
|
|
|
|
pub fn throwOutOfMemory(self: Context) Value {
|
|
return .{ .value = import.JS_ThrowOutOfMemory(self.context) };
|
|
}
|
|
|
|
pub fn freeValue(self: Context, v: Value) void {
|
|
import.JS_FreeValue(self.context, v.value);
|
|
}
|
|
|
|
pub fn dupValue(self: Context, v: Value) Value {
|
|
return .{ .value = import.JS_DupValue(self.context, v.value) };
|
|
}
|
|
|
|
pub fn strictEq(self: Context, op1: Value, op2: Value) bool {
|
|
return import.JS_StrictEq(self.context, op1.value, op2.value) != 0;
|
|
}
|
|
|
|
pub fn sameValue(self: Context, op1: Value, op2: Value) bool {
|
|
return import.JS_SameValue(self.context, op1.value, op2.value) != 0;
|
|
}
|
|
|
|
pub fn sameValueZero(self: Context, op1: Value, op2: Value) bool {
|
|
return import.JS_SameValueZero(self.context, op1.value, op2.value) != 0;
|
|
}
|
|
|
|
pub fn newObject(self: Context) Value {
|
|
return .{ .value = import.JS_NewObject(self.context) };
|
|
}
|
|
|
|
pub fn newObjectProto(self: Context, proto: Value) Value {
|
|
return .{ .value = import.JS_NewObjectProto(self.context, proto.value) };
|
|
}
|
|
|
|
pub fn isFunction(self: Context, val: Value) bool {
|
|
return import.JS_IsFunction(self.context, val.value) != 0;
|
|
}
|
|
|
|
pub fn isConstructor(self: Context, val: Value) bool {
|
|
return import.JS_IsConstructor(self.context, val.value) != 0;
|
|
}
|
|
|
|
pub fn setConstructorBit(self: Context, func_obj: Value, val: bool) bool {
|
|
return import.JS_SetConstructorBit(self.context, func_obj.value, @intFromBool(val)) != 0;
|
|
}
|
|
|
|
pub fn newArray(self: Context) Value {
|
|
return .{ .value = import.JS_NewArray(self.context) };
|
|
}
|
|
|
|
pub fn isArray(self: Context, val: Value) bool {
|
|
return import.JS_IsArray(self.context, val.value) != 0;
|
|
}
|
|
|
|
pub fn newDate(self: Context, epoch_ms: f64) Value {
|
|
return .{ .value = import.JS_NewDate(self.context, epoch_ms) };
|
|
}
|
|
|
|
pub fn eval(self: Context, input: [:0]const u8, filename: [*:0]const u8, eval_flags: import.JS_EVAL) Value {
|
|
return .{ .value = import.JS_Eval(self.context, input.ptr, input.len, filename, eval_flags) };
|
|
}
|
|
|
|
pub fn evalThis(self: Context, this_obj: Value, input: [:0]const u8, filename: [*:0]const u8, eval_flags: import.JS_EVAL) Value {
|
|
return .{ .value = import.JS_EvalThis(self.context, this_obj.value, input.ptr, input.len, filename, eval_flags) };
|
|
}
|
|
};
|
|
|
|
pub const Value = extern struct {
|
|
value: import.JSValue,
|
|
|
|
pub const @"null": Value = .{ .value = import.JS_NULL };
|
|
pub const @"undefined": Value = .{ .value = import.JS_UNDEFINED };
|
|
pub const @"false": Value = .{ .value = import.JS_FALSE };
|
|
pub const @"true": Value = .{ .value = import.JS_TRUE };
|
|
pub const exception: Value = .{ .value = import.JS_EXCEPTION };
|
|
pub const uninitialized: Value = .{ .value = import.JS_UNINITIALIZED };
|
|
|
|
pub fn isNumber(self: Value) bool {
|
|
return import.JS_IsNumber(self.value);
|
|
}
|
|
|
|
pub fn isBigInt(self: Value) bool {
|
|
return import.JS_IsBigInt(self.value);
|
|
}
|
|
|
|
pub fn isBool(self: Value) bool {
|
|
return import.JS_IsBool(self.value);
|
|
}
|
|
|
|
pub fn isNull(self: Value) bool {
|
|
return import.JS_IsNull(self.value);
|
|
}
|
|
|
|
pub fn isUndefined(self: Value) bool {
|
|
return import.JS_IsUndefined(self.value);
|
|
}
|
|
|
|
pub fn isException(self: Value) bool {
|
|
return import.JS_IsException(self.value);
|
|
}
|
|
|
|
pub fn isUninitialized(self: Value) bool {
|
|
return import.JS_IsUninitialized(self.value);
|
|
}
|
|
|
|
pub fn isString(self: Value) bool {
|
|
return import.JS_IsString(self.value);
|
|
}
|
|
|
|
pub fn isSymbol(self: Value) bool {
|
|
return import.JS_IsSymbol(self.value);
|
|
}
|
|
|
|
pub fn isObject(self: Value) bool {
|
|
return import.JS_IsObject(self.value);
|
|
}
|
|
|
|
pub fn getClassId(self: Value) ClassId {
|
|
return .{ .class_id = import.JS_GetClassID(self) };
|
|
}
|
|
};
|
|
|
|
pub const Atom = extern struct {
|
|
atom: import.JSAtom,
|
|
};
|
|
|
|
pub const ClassId = extern struct {
|
|
class_id: import.JSClassID,
|
|
|
|
pub const invalid: ClassId = .{ .class_id = 0 };
|
|
|
|
pub fn new() ClassId {
|
|
var class_id: import.JSClassId = 0;
|
|
return .{ .class_id = import.JS_NewClassID(&class_id) };
|
|
}
|
|
};
|
|
|
|
test "refAllDecls" {
|
|
std.testing.refAllDeclsRecursive(import);
|
|
std.testing.refAllDeclsRecursive(@This());
|
|
}
|
|
|
|
test "runtime and context - custom allocator" {
|
|
const allocator = std.testing.allocator;
|
|
|
|
var runtime = try Runtime.newRuntimeAllocator(&allocator);
|
|
defer runtime.freeRuntime();
|
|
|
|
var context = try runtime.newContext();
|
|
defer context.freeContext();
|
|
}
|
|
|
|
test "eval" {
|
|
const allocator = std.testing.allocator;
|
|
|
|
var runtime = try Runtime.newRuntimeAllocator(&allocator);
|
|
defer runtime.freeRuntime();
|
|
|
|
var context = try runtime.newContext();
|
|
defer context.freeContext();
|
|
|
|
const result = context.eval("1 + 2", "eval.js", .{});
|
|
|
|
try std.testing.expectEqual(.INT, import.JS_VALUE_GET_TAG(result.value));
|
|
try std.testing.expectEqual(3, import.JS_VALUE_GET_INT(result.value));
|
|
}
|