@thi.ng/wasm-api 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +77 -1
- package/README.md +248 -170
- package/api.d.ts +98 -14
- package/bin/wasm-api.mjs_ +17 -0
- package/bridge.d.ts +11 -1
- package/bridge.js +15 -10
- package/cli.js +51 -9
- package/codegen/c.d.ts +33 -0
- package/codegen/c.js +100 -0
- package/codegen/c11.d.ts +22 -0
- package/codegen/c11.js +125 -0
- package/codegen/typescript.d.ts +2 -12
- package/codegen/typescript.js +119 -88
- package/codegen/utils.d.ts +53 -4
- package/codegen/utils.js +63 -5
- package/codegen/zig.d.ts +2 -9
- package/codegen/zig.js +74 -29
- package/codegen.d.ts +1 -23
- package/codegen.js +35 -8
- package/include/wasmapi.h +34 -20
- package/include/wasmapi.zig +53 -46
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +32 -19
- package/pointer.d.ts +23 -0
- package/pointer.js +27 -0
- package/string.d.ts +96 -0
- package/string.js +145 -0
package/codegen.d.ts
CHANGED
|
@@ -1,26 +1,4 @@
|
|
|
1
|
-
import { ICodeGen, TypeColl } from "./api.js";
|
|
2
|
-
/**
|
|
3
|
-
* Global/shared code generator options.
|
|
4
|
-
*/
|
|
5
|
-
export interface CodeGenOpts {
|
|
6
|
-
/**
|
|
7
|
-
* Optional string to be injected before generated type defs (but after
|
|
8
|
-
* codegen's own prelude, if any)
|
|
9
|
-
*/
|
|
10
|
-
pre: string;
|
|
11
|
-
/**
|
|
12
|
-
* Optional string to be injected after generated type defs (but before
|
|
13
|
-
* codegen's own epilogue, if any)
|
|
14
|
-
*/
|
|
15
|
-
post: string;
|
|
16
|
-
/**
|
|
17
|
-
* Identifier how strings are stored on WASM side, e.g. in Zig string
|
|
18
|
-
* literals are slices (8 bytes), in C just plain pointers (4 bytes).
|
|
19
|
-
*
|
|
20
|
-
* @defaultValue "slice"
|
|
21
|
-
*/
|
|
22
|
-
stringType: "slice" | "ptr";
|
|
23
|
-
}
|
|
1
|
+
import { CodeGenOpts, ICodeGen, TypeColl } from "./api.js";
|
|
24
2
|
/**
|
|
25
3
|
* Takes a type collection and analyzes each analyzed to compute individual
|
|
26
4
|
* alignments and sizes.
|
package/codegen.js
CHANGED
|
@@ -4,12 +4,17 @@ import { ceilPow2 } from "@thi.ng/binary/pow";
|
|
|
4
4
|
import { compareByKey } from "@thi.ng/compare/keys";
|
|
5
5
|
import { compareNumDesc } from "@thi.ng/compare/numeric";
|
|
6
6
|
import { DEFAULT, defmulti } from "@thi.ng/defmulti/defmulti";
|
|
7
|
+
import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
|
|
7
8
|
import { PKG_NAME, USIZE_SIZE, } from "./api.js";
|
|
8
9
|
import { isNumeric, isWasmString } from "./codegen/utils.js";
|
|
9
10
|
const sizeOf = defmulti((x) => x.type, {}, {
|
|
10
11
|
[DEFAULT]: (field, types, opts) => {
|
|
11
12
|
if (field.__size)
|
|
12
13
|
return field.__size;
|
|
14
|
+
if (field.pad != null) {
|
|
15
|
+
field.pad < 1 && illegalArgs(`pad size must be > 0`);
|
|
16
|
+
return (field.__size = field.pad);
|
|
17
|
+
}
|
|
13
18
|
let size = 0;
|
|
14
19
|
if (field.tag === "ptr") {
|
|
15
20
|
size = USIZE_SIZE;
|
|
@@ -25,6 +30,9 @@ const sizeOf = defmulti((x) => x.type, {}, {
|
|
|
25
30
|
: sizeOf(types[field.type], types, opts);
|
|
26
31
|
if (field.tag == "array" || field.tag === "vec") {
|
|
27
32
|
size *= field.len;
|
|
33
|
+
if (field.sentinel !== undefined && field.tag === "array") {
|
|
34
|
+
size += SIZEOF[field.type];
|
|
35
|
+
}
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
38
|
return (field.__size = align(size, field.__align));
|
|
@@ -51,6 +59,8 @@ const alignOf = defmulti((x) => x.type, {}, {
|
|
|
51
59
|
[DEFAULT]: (field, types) => {
|
|
52
60
|
if (field.__align)
|
|
53
61
|
return field.__align;
|
|
62
|
+
if (field.pad)
|
|
63
|
+
return (field.__align = 1);
|
|
54
64
|
let align = isNumeric(field.type)
|
|
55
65
|
? SIZEOF[field.type]
|
|
56
66
|
: isWasmString(field.type)
|
|
@@ -62,7 +72,10 @@ const alignOf = defmulti((x) => x.type, {}, {
|
|
|
62
72
|
field.__align = align;
|
|
63
73
|
return align;
|
|
64
74
|
},
|
|
65
|
-
enum: (
|
|
75
|
+
enum: (type) => {
|
|
76
|
+
const e = type;
|
|
77
|
+
if (!e.tag)
|
|
78
|
+
e.tag = "i32";
|
|
66
79
|
return (e.__align = SIZEOF[e.tag]);
|
|
67
80
|
},
|
|
68
81
|
struct: (type, types) => {
|
|
@@ -130,19 +143,33 @@ export const prepareTypes = (types, opts) => {
|
|
|
130
143
|
* @param opts
|
|
131
144
|
*/
|
|
132
145
|
export const generateTypes = (types, codegen, opts = {}) => {
|
|
133
|
-
const $opts = {
|
|
146
|
+
const $opts = {
|
|
147
|
+
header: true,
|
|
148
|
+
stringType: "slice",
|
|
149
|
+
uppercaseEnums: true,
|
|
150
|
+
lineWidth: 80,
|
|
151
|
+
...opts,
|
|
152
|
+
};
|
|
134
153
|
prepareTypes(types, $opts);
|
|
135
154
|
const res = [];
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
155
|
+
if ($opts.header) {
|
|
156
|
+
codegen.doc(`Generated by ${PKG_NAME} at ${new Date().toISOString()} - DO NOT EDIT!`, res, $opts, true);
|
|
157
|
+
res.push("");
|
|
158
|
+
}
|
|
159
|
+
if (codegen.pre) {
|
|
160
|
+
const pre = codegen.pre($opts);
|
|
161
|
+
pre && res.push(pre, "");
|
|
162
|
+
}
|
|
139
163
|
$opts.pre && res.push($opts.pre, "");
|
|
140
164
|
for (let id in types) {
|
|
141
165
|
const type = types[id];
|
|
142
|
-
type.doc && codegen.doc(type.doc,
|
|
143
|
-
codegen[type.type](type, types, res);
|
|
166
|
+
type.doc && codegen.doc(type.doc, res, $opts);
|
|
167
|
+
codegen[type.type](type, types, res, $opts);
|
|
144
168
|
}
|
|
145
169
|
$opts.post && res.push("", $opts.post);
|
|
146
|
-
|
|
170
|
+
if (codegen.post) {
|
|
171
|
+
const post = codegen.post($opts);
|
|
172
|
+
post && res.push("", post);
|
|
173
|
+
}
|
|
147
174
|
return res.join("\n");
|
|
148
175
|
};
|
package/include/wasmapi.h
CHANGED
|
@@ -9,9 +9,8 @@ extern "C" {
|
|
|
9
9
|
|
|
10
10
|
// Declares an imported symbol from named import module
|
|
11
11
|
// The prefix is only used for the C side, NOT for exported name
|
|
12
|
-
#define WASM_IMPORT(MODULE, TYPE, NAME, PREFIX)
|
|
13
|
-
extern __attribute__((import_module(MODULE), import_name(#NAME)))
|
|
14
|
-
TYPE PREFIX##NAME
|
|
12
|
+
#define WASM_IMPORT(MODULE, TYPE, NAME, PREFIX) \
|
|
13
|
+
extern __attribute__((import_module(MODULE), import_name(#NAME))) TYPE PREFIX##NAME
|
|
15
14
|
|
|
16
15
|
// Same as EMSCRIPTEN_KEEP_ALIVE, ensures symbol will be exported
|
|
17
16
|
#define WASM_KEEP __attribute__((used))
|
|
@@ -19,15 +18,24 @@ extern "C" {
|
|
|
19
18
|
// Generate malloc/free wrappers only if explicitly enabled by defining this
|
|
20
19
|
// symbol. If undefined some function stubs are exported.
|
|
21
20
|
#ifdef WASMAPI_MALLOC
|
|
21
|
+
|
|
22
22
|
#include <stdlib.h>
|
|
23
23
|
size_t WASM_KEEP _wasm_allocate(size_t numBytes) {
|
|
24
24
|
return (size_t)malloc(numBytes);
|
|
25
25
|
}
|
|
26
|
-
void WASM_KEEP _wasm_free(size_t addr
|
|
26
|
+
void WASM_KEEP _wasm_free(size_t addr, size_t numBytes) {
|
|
27
|
+
free((void*)addr);
|
|
28
|
+
}
|
|
29
|
+
|
|
27
30
|
#else
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
|
|
32
|
+
size_t WASM_KEEP _wasm_allocate(size_t numBytes) {
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
void WASM_KEEP _wasm_free(size_t addr, size_t numBytes) {
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#endif // WASMAPI_MALLOC
|
|
31
39
|
|
|
32
40
|
WASM_IMPORT("wasmapi", void, printI8, wasm_)(int8_t x);
|
|
33
41
|
WASM_IMPORT("wasmapi", void, printU8, wasm_)(uint8_t x);
|
|
@@ -44,23 +52,29 @@ WASM_IMPORT("wasmapi", void, printU64Hex, wasm_)(uint64_t x);
|
|
|
44
52
|
WASM_IMPORT("wasmapi", void, printF32, wasm_)(float x);
|
|
45
53
|
WASM_IMPORT("wasmapi", void, printF64, wasm_)(double x);
|
|
46
54
|
|
|
47
|
-
WASM_IMPORT("wasmapi", void, _printI8Array, wasm)(
|
|
48
|
-
WASM_IMPORT("wasmapi", void, _printU8Array, wasm)(
|
|
49
|
-
WASM_IMPORT("wasmapi", void, _printI16Array, wasm)(
|
|
50
|
-
WASM_IMPORT("wasmapi", void, _printU16Array, wasm)(
|
|
51
|
-
WASM_IMPORT("wasmapi", void, _printI32Array, wasm)(
|
|
52
|
-
WASM_IMPORT("wasmapi", void, _printU32Array, wasm)(
|
|
53
|
-
WASM_IMPORT("wasmapi", void, _printI64Array, wasm)(
|
|
54
|
-
WASM_IMPORT("wasmapi", void, _printU64Array, wasm)(
|
|
55
|
-
WASM_IMPORT("wasmapi", void, _printF32Array, wasm)(
|
|
56
|
-
WASM_IMPORT("wasmapi", void, _printF64Array, wasm)(
|
|
55
|
+
WASM_IMPORT("wasmapi", void, _printI8Array, wasm)(const int8_t* addr, size_t len);
|
|
56
|
+
WASM_IMPORT("wasmapi", void, _printU8Array, wasm)(const uint8_t* addr, size_t len);
|
|
57
|
+
WASM_IMPORT("wasmapi", void, _printI16Array, wasm)(const int16_t* addr, size_t len);
|
|
58
|
+
WASM_IMPORT("wasmapi", void, _printU16Array, wasm)(const uint16_t* addr, size_t len);
|
|
59
|
+
WASM_IMPORT("wasmapi", void, _printI32Array, wasm)(const int32_t* addr, size_t len);
|
|
60
|
+
WASM_IMPORT("wasmapi", void, _printU32Array, wasm)(const uint32_t* addr, size_t len);
|
|
61
|
+
WASM_IMPORT("wasmapi", void, _printI64Array, wasm)(const int64_t* addr, size_t len);
|
|
62
|
+
WASM_IMPORT("wasmapi", void, _printU64Array, wasm)(const uint64_t* addr, size_t len);
|
|
63
|
+
WASM_IMPORT("wasmapi", void, _printF32Array, wasm)(const float* addr, size_t len);
|
|
64
|
+
WASM_IMPORT("wasmapi", void, _printF64Array, wasm)(const double* addr, size_t len);
|
|
57
65
|
|
|
58
|
-
WASM_IMPORT("wasmapi", void, _printStr0, wasm)(
|
|
59
|
-
WASM_IMPORT("wasmapi", void, _printStr, wasm)(
|
|
66
|
+
WASM_IMPORT("wasmapi", void, _printStr0, wasm)(const char* addr);
|
|
67
|
+
WASM_IMPORT("wasmapi", void, _printStr, wasm)(const char* addr, size_t len);
|
|
60
68
|
|
|
61
69
|
WASM_IMPORT("wasmapi", void, debug, wasm_)(void);
|
|
70
|
+
WASM_IMPORT("wasmapi", void, panic, wasm_)(const char*, size_t len);
|
|
62
71
|
|
|
63
|
-
|
|
72
|
+
WASM_IMPORT("wasmapi", double, timer, wasm_)(void);
|
|
73
|
+
WASM_IMPORT("wasmapi", uint64_t, epoch, wasm_)(void);
|
|
74
|
+
|
|
75
|
+
void wasm_printPtr(const void* ptr) {
|
|
76
|
+
wasm_printU32Hex((size_t)ptr);
|
|
77
|
+
}
|
|
64
78
|
|
|
65
79
|
#ifdef __cplusplus
|
|
66
80
|
}
|
package/include/wasmapi.zig
CHANGED
|
@@ -3,9 +3,24 @@
|
|
|
3
3
|
const std = @import("std");
|
|
4
4
|
const root = @import("root");
|
|
5
5
|
|
|
6
|
+
/// JS external part of the custom panic handler
|
|
7
|
+
/// Prints message using configured JS logger and then throws JS error
|
|
8
|
+
pub extern "wasmapi" fn _panic(addr: [*]const u8, len: usize) noreturn;
|
|
9
|
+
|
|
10
|
+
/// Custom panic handler which prints given message using configured JS logger
|
|
11
|
+
/// To use this handler, add the following line to your **root** source file:
|
|
12
|
+
///
|
|
13
|
+
/// ```
|
|
14
|
+
/// pub const panic = @import("wasmapi").panic;
|
|
15
|
+
/// ```
|
|
16
|
+
pub fn panic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
|
17
|
+
_panic(msg.ptr, msg.len);
|
|
18
|
+
unreachable;
|
|
19
|
+
}
|
|
20
|
+
|
|
6
21
|
/// Obtains the allocator to be exposed to the WASM host env
|
|
7
22
|
/// (via `_wasm_allocate()` and `_wasm_free()`).
|
|
8
|
-
/// If the user defines a public `WASM_ALLOCATOR` in their root file
|
|
23
|
+
/// If the user defines a public `WASM_ALLOCATOR` in their **root** file
|
|
9
24
|
/// then this allocator will be used, otherwise the implementations
|
|
10
25
|
/// of the two mentioned functions are no-ops.
|
|
11
26
|
/// The `WASM_ALLOCATOR` can be changed and/or enabled/disabled dynamically
|
|
@@ -32,9 +47,9 @@ pub export fn _wasm_allocate(numBytes: usize) usize {
|
|
|
32
47
|
/// Frees chunk of heap memory (previously allocated using `_wasm_allocate()`)
|
|
33
48
|
/// starting at given address and of given byte length.
|
|
34
49
|
/// Note: This is a no-op if no allocator is configured (see `allocator()`)
|
|
35
|
-
pub export fn _wasm_free(addr:
|
|
50
|
+
pub export fn _wasm_free(addr: [*]u8, numBytes: usize) void {
|
|
36
51
|
if (allocator()) |alloc| {
|
|
37
|
-
var mem = [2]usize{ addr, numBytes };
|
|
52
|
+
var mem = [2]usize{ @ptrToInt(addr), numBytes };
|
|
38
53
|
alloc.free(@ptrCast(*[]u8, &mem).*);
|
|
39
54
|
}
|
|
40
55
|
}
|
|
@@ -60,26 +75,12 @@ pub extern "wasmapi" fn printU32(x: u32) void;
|
|
|
60
75
|
/// Prints hex number using configured JS logger
|
|
61
76
|
pub extern "wasmapi" fn printU32Hex(x: u32) void;
|
|
62
77
|
|
|
63
|
-
/// Prints
|
|
64
|
-
pub extern "wasmapi" fn
|
|
65
|
-
///
|
|
66
|
-
pub fn
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
/// Prints decomposed u64 number using configured JS logger
|
|
71
|
-
pub extern "wasmapi" fn _printU64(hi: u32, lo: u32) void;
|
|
72
|
-
/// Convenience wrapper for _printU64(), accepting an u64
|
|
73
|
-
pub fn printU64(x: u64) void {
|
|
74
|
-
_printU64(@truncate(u32, x >> 32), @truncate(u32, x));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/// Prints decomposed u64 hex number using configured JS logger
|
|
78
|
-
pub extern "wasmapi" fn _printU64Hex(hi: u32, lo: u32) void;
|
|
79
|
-
/// Convenience wrapper for _printU64Hex(), accepting an u64
|
|
80
|
-
pub fn printU64Hex(x: u64) void {
|
|
81
|
-
_printU64Hex(@truncate(u32, x >> 32), @truncate(u32, x));
|
|
82
|
-
}
|
|
78
|
+
/// Prints i64 number using configured JS logger
|
|
79
|
+
pub extern "wasmapi" fn printI64(x: i64) void;
|
|
80
|
+
/// Prints u64 number using configured JS logger
|
|
81
|
+
pub extern "wasmapi" fn printU64(x: u64) void;
|
|
82
|
+
/// Prints u64 hex number using configured JS logger
|
|
83
|
+
pub extern "wasmapi" fn printU64Hex(x: u64) void;
|
|
83
84
|
|
|
84
85
|
/// Prints number using configured JS logger
|
|
85
86
|
pub extern "wasmapi" fn printF32(x: f32) void;
|
|
@@ -92,74 +93,74 @@ pub fn printPtr(ptr: *const anyopaque) void {
|
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
/// Prints number array using configured JS logger
|
|
95
|
-
pub extern "wasmapi" fn _printI8Array(addr:
|
|
96
|
+
pub extern "wasmapi" fn _printI8Array(addr: [*]const i8, len: usize) void;
|
|
96
97
|
/// Prints number array using configured JS logger
|
|
97
|
-
pub extern "wasmapi" fn _printU8Array(addr:
|
|
98
|
+
pub extern "wasmapi" fn _printU8Array(addr: [*]const u8, len: usize) void;
|
|
98
99
|
/// Prints number array using configured JS logger
|
|
99
|
-
pub extern "wasmapi" fn _printI16Array(addr:
|
|
100
|
+
pub extern "wasmapi" fn _printI16Array(addr: [*]const i16, len: usize) void;
|
|
100
101
|
/// Prints number array using configured JS logger
|
|
101
|
-
pub extern "wasmapi" fn _printU16Array(addr:
|
|
102
|
+
pub extern "wasmapi" fn _printU16Array(addr: [*]const u16, len: usize) void;
|
|
102
103
|
/// Prints number array using configured JS logger
|
|
103
|
-
pub extern "wasmapi" fn _printI32Array(addr:
|
|
104
|
+
pub extern "wasmapi" fn _printI32Array(addr: [*]const i32, len: usize) void;
|
|
104
105
|
/// Prints number array using configured JS logger
|
|
105
|
-
pub extern "wasmapi" fn _printU32Array(addr:
|
|
106
|
+
pub extern "wasmapi" fn _printU32Array(addr: [*]const u32, len: usize) void;
|
|
106
107
|
/// Prints number array using configured JS logger
|
|
107
|
-
pub extern "wasmapi" fn _printI64Array(addr:
|
|
108
|
+
pub extern "wasmapi" fn _printI64Array(addr: [*]const i64, len: usize) void;
|
|
108
109
|
/// Prints number array using configured JS logger
|
|
109
|
-
pub extern "wasmapi" fn _printU64Array(addr:
|
|
110
|
+
pub extern "wasmapi" fn _printU64Array(addr: [*]const u64, len: usize) void;
|
|
110
111
|
/// Prints number array using configured JS logger
|
|
111
|
-
pub extern "wasmapi" fn _printF32Array(addr:
|
|
112
|
+
pub extern "wasmapi" fn _printF32Array(addr: [*]const f32, len: usize) void;
|
|
112
113
|
/// Prints number array using configured JS logger
|
|
113
|
-
pub extern "wasmapi" fn _printF64Array(addr:
|
|
114
|
+
pub extern "wasmapi" fn _printF64Array(addr: [*]const f64, len: usize) void;
|
|
114
115
|
|
|
115
116
|
/// Prints number array using configured JS logger
|
|
116
117
|
pub fn printI8Array(buf: []const i8) void {
|
|
117
|
-
_printI8Array(
|
|
118
|
+
_printI8Array(buf.ptr, buf.len);
|
|
118
119
|
}
|
|
119
120
|
/// Prints number array using configured JS logger
|
|
120
121
|
pub fn printU8Array(buf: []const u8) void {
|
|
121
|
-
_printU8Array(
|
|
122
|
+
_printU8Array(buf.ptr, buf.len);
|
|
122
123
|
}
|
|
123
124
|
/// Prints number array using configured JS logger
|
|
124
125
|
pub fn printI16Array(buf: []const i16) void {
|
|
125
|
-
_printI16Array(
|
|
126
|
+
_printI16Array(buf.ptr, buf.len);
|
|
126
127
|
}
|
|
127
128
|
/// Prints number array using configured JS logger
|
|
128
129
|
pub fn printU16Array(buf: []const u16) void {
|
|
129
|
-
_printU16Array(
|
|
130
|
+
_printU16Array(buf.ptr, buf.len);
|
|
130
131
|
}
|
|
131
132
|
/// Prints number array using configured JS logger
|
|
132
133
|
pub fn printI32Array(buf: []const i32) void {
|
|
133
|
-
_printI32Array(
|
|
134
|
+
_printI32Array(buf.ptr, buf.len);
|
|
134
135
|
}
|
|
135
136
|
/// Prints number array using configured JS logger
|
|
136
137
|
pub fn printU32Array(buf: []const u32) void {
|
|
137
|
-
_printU32Array(
|
|
138
|
+
_printU32Array(buf.ptr, buf.len);
|
|
138
139
|
}
|
|
139
140
|
/// Prints number array using configured JS logger
|
|
140
141
|
pub fn printI64Array(buf: []const i64) void {
|
|
141
|
-
_printI64Array(
|
|
142
|
+
_printI64Array(buf.ptr, buf.len);
|
|
142
143
|
}
|
|
143
144
|
/// Prints number array using configured JS logger
|
|
144
145
|
pub fn printU64Array(buf: []const u64) void {
|
|
145
|
-
_printU64Array(
|
|
146
|
+
_printU64Array(buf.ptr, buf.len);
|
|
146
147
|
}
|
|
147
148
|
/// Prints number array using configured JS logger
|
|
148
149
|
pub fn printF32Array(buf: []const f32) void {
|
|
149
|
-
_printF32Array(
|
|
150
|
+
_printF32Array(buf.ptr, buf.len);
|
|
150
151
|
}
|
|
151
152
|
/// Prints number array using configured JS logger
|
|
152
153
|
pub fn printF64Array(buf: []const f64) void {
|
|
153
|
-
_printF64Array(
|
|
154
|
+
_printF64Array(buf.ptr, buf.len);
|
|
154
155
|
}
|
|
155
156
|
|
|
156
157
|
/// Prints a zero-terminated string using configured JS logger
|
|
157
|
-
pub extern "wasmapi" fn _printStr0(addr:
|
|
158
|
+
pub extern "wasmapi" fn _printStr0(addr: [*]const u8) void;
|
|
158
159
|
/// Prints a string of given length using configured JS logger
|
|
159
|
-
pub extern "wasmapi" fn _printStr(addr:
|
|
160
|
+
pub extern "wasmapi" fn _printStr(addr: [*]const u8, len: usize) void;
|
|
160
161
|
/// Convenience wrapper for _printStr, accepting a slice as arg
|
|
161
162
|
pub fn printStr(msg: []const u8) void {
|
|
162
|
-
_printStr(
|
|
163
|
+
_printStr(msg.ptr, msg.len);
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
/// Calls std.fmt.allocPrint to format given string, then calls `printStr()`
|
|
@@ -175,3 +176,9 @@ pub fn printFmt(comptime fmt: []const u8, args: anytype) void {
|
|
|
175
176
|
|
|
176
177
|
/// Triggers the JS/browser debugger
|
|
177
178
|
pub extern "wasmapi" fn debug() void;
|
|
179
|
+
|
|
180
|
+
/// Returns a JS/browser highres timer value (via `performance.now()`)
|
|
181
|
+
pub extern "wasmapi" fn timer() f64;
|
|
182
|
+
|
|
183
|
+
/// Returns a JS/browser Unix epoch (via `Date.now()`)
|
|
184
|
+
pub extern "wasmapi" fn epoch() u64;
|
package/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export * from "./api.js";
|
|
2
2
|
export * from "./bridge.js";
|
|
3
3
|
export * from "./codegen.js";
|
|
4
|
+
export * from "./codegen/c11.js";
|
|
4
5
|
export * from "./codegen/typescript.js";
|
|
5
6
|
export * from "./codegen/utils.js";
|
|
6
7
|
export * from "./codegen/zig.js";
|
|
7
8
|
export * from "./object-index.js";
|
|
9
|
+
export * from "./pointer.js";
|
|
10
|
+
export * from "./string.js";
|
|
8
11
|
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export * from "./api.js";
|
|
2
2
|
export * from "./bridge.js";
|
|
3
3
|
export * from "./codegen.js";
|
|
4
|
+
export * from "./codegen/c11.js";
|
|
4
5
|
export * from "./codegen/typescript.js";
|
|
5
6
|
export * from "./codegen/utils.js";
|
|
6
7
|
export * from "./codegen/zig.js";
|
|
7
8
|
export * from "./object-index.js";
|
|
9
|
+
export * from "./pointer.js";
|
|
10
|
+
export * from "./string.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/wasm-api",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Generic, modular, extensible API bridge, glue code and bindings code
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"description": "Generic, modular, extensible API bridge, polyglot glue code and bindings code generators for hybrid JS & WebAssembly projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
7
7
|
"typings": "./index.d.ts",
|
|
@@ -36,25 +36,27 @@
|
|
|
36
36
|
"test:build-zig": "zig build-lib -O ReleaseSmall -target wasm32-freestanding -dynamic --strip --pkg-begin wasmapi include/wasmapi.zig --pkg-end test/custom.zig && wasm-dis -o custom.wast custom.wasm && cp custom.wasm test"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@thi.ng/api": "^8.4.
|
|
40
|
-
"@thi.ng/args": "^2.2.
|
|
41
|
-
"@thi.ng/binary": "^3.3.
|
|
42
|
-
"@thi.ng/checks": "^3.2.
|
|
43
|
-
"@thi.ng/compare": "^2.1.
|
|
44
|
-
"@thi.ng/defmulti": "^2.1.
|
|
45
|
-
"@thi.ng/errors": "^2.1
|
|
46
|
-
"@thi.ng/file-io": "^0.3.
|
|
47
|
-
"@thi.ng/hex": "^2.1
|
|
48
|
-
"@thi.ng/idgen": "^2.1.
|
|
49
|
-
"@thi.ng/logger": "^1.
|
|
39
|
+
"@thi.ng/api": "^8.4.3",
|
|
40
|
+
"@thi.ng/args": "^2.2.3",
|
|
41
|
+
"@thi.ng/binary": "^3.3.6",
|
|
42
|
+
"@thi.ng/checks": "^3.2.6",
|
|
43
|
+
"@thi.ng/compare": "^2.1.13",
|
|
44
|
+
"@thi.ng/defmulti": "^2.1.15",
|
|
45
|
+
"@thi.ng/errors": "^2.2.1",
|
|
46
|
+
"@thi.ng/file-io": "^0.3.12",
|
|
47
|
+
"@thi.ng/hex": "^2.2.1",
|
|
48
|
+
"@thi.ng/idgen": "^2.1.14",
|
|
49
|
+
"@thi.ng/logger": "^1.3.1",
|
|
50
|
+
"@thi.ng/paths": "^5.1.16",
|
|
51
|
+
"@thi.ng/strings": "^3.3.13"
|
|
50
52
|
},
|
|
51
53
|
"devDependencies": {
|
|
52
|
-
"@microsoft/api-extractor": "^7.
|
|
53
|
-
"@thi.ng/testament": "^0.
|
|
54
|
+
"@microsoft/api-extractor": "^7.31.1",
|
|
55
|
+
"@thi.ng/testament": "^0.3.1",
|
|
54
56
|
"rimraf": "^3.0.2",
|
|
55
57
|
"tools": "^0.0.1",
|
|
56
58
|
"typedoc": "^0.22.17",
|
|
57
|
-
"typescript": "^4.
|
|
59
|
+
"typescript": "^4.8.3"
|
|
58
60
|
},
|
|
59
61
|
"keywords": [
|
|
60
62
|
"allocator",
|
|
@@ -62,10 +64,12 @@
|
|
|
62
64
|
"bindings",
|
|
63
65
|
"c",
|
|
64
66
|
"codegen",
|
|
67
|
+
"enum",
|
|
65
68
|
"event",
|
|
66
69
|
"id",
|
|
67
70
|
"logger",
|
|
68
71
|
"memory",
|
|
72
|
+
"polyglot",
|
|
69
73
|
"string",
|
|
70
74
|
"struct",
|
|
71
75
|
"typedarray",
|
|
@@ -103,8 +107,8 @@
|
|
|
103
107
|
"./bridge": {
|
|
104
108
|
"default": "./bridge.js"
|
|
105
109
|
},
|
|
106
|
-
"./codegen": {
|
|
107
|
-
"default": "./codegen.js"
|
|
110
|
+
"./codegen/c11": {
|
|
111
|
+
"default": "./codegen/c11.js"
|
|
108
112
|
},
|
|
109
113
|
"./codegen/typescript": {
|
|
110
114
|
"default": "./codegen/typescript.js"
|
|
@@ -115,13 +119,22 @@
|
|
|
115
119
|
"./codegen/zig": {
|
|
116
120
|
"default": "./codegen/zig.js"
|
|
117
121
|
},
|
|
122
|
+
"./codegen": {
|
|
123
|
+
"default": "./codegen.js"
|
|
124
|
+
},
|
|
118
125
|
"./object-index": {
|
|
119
126
|
"default": "./object-index.js"
|
|
127
|
+
},
|
|
128
|
+
"./pointer": {
|
|
129
|
+
"default": "./pointer.js"
|
|
130
|
+
},
|
|
131
|
+
"./string": {
|
|
132
|
+
"default": "./string.js"
|
|
120
133
|
}
|
|
121
134
|
},
|
|
122
135
|
"thi.ng": {
|
|
123
136
|
"status": "alpha",
|
|
124
137
|
"year": 2022
|
|
125
138
|
},
|
|
126
|
-
"gitHead": "
|
|
139
|
+
"gitHead": "8600007d81a7dc92634a1d54e2c32b14ab30ba80\n"
|
|
127
140
|
}
|
package/pointer.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Fn, IDeref } from "@thi.ng/api";
|
|
2
|
+
import type { IWasmMemoryAccess } from "./api.js";
|
|
3
|
+
/**
|
|
4
|
+
* Generic pointer facility which on {@link Pointer.deref()} calls wrapper
|
|
5
|
+
* function (provided as ctor arg) to realise the pointer's target value. The
|
|
6
|
+
* pointer's target address can be accessed via {@link Pointer.addr}
|
|
7
|
+
* (read/write).
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* The pointer always behaves like `volatile`, i.e. memoization of target values
|
|
11
|
+
* is purposfully avoided and the wrapper function is executed anew _each_ time
|
|
12
|
+
* the pointer is deref'd.
|
|
13
|
+
*/
|
|
14
|
+
export declare class Pointer<T> implements IDeref<T> {
|
|
15
|
+
readonly mem: IWasmMemoryAccess;
|
|
16
|
+
readonly base: number;
|
|
17
|
+
readonly fn: Fn<number, T>;
|
|
18
|
+
constructor(mem: IWasmMemoryAccess, base: number, fn: Fn<number, T>);
|
|
19
|
+
get addr(): number;
|
|
20
|
+
set addr(addr: number);
|
|
21
|
+
deref(): T;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=pointer.d.ts.map
|
package/pointer.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic pointer facility which on {@link Pointer.deref()} calls wrapper
|
|
3
|
+
* function (provided as ctor arg) to realise the pointer's target value. The
|
|
4
|
+
* pointer's target address can be accessed via {@link Pointer.addr}
|
|
5
|
+
* (read/write).
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* The pointer always behaves like `volatile`, i.e. memoization of target values
|
|
9
|
+
* is purposfully avoided and the wrapper function is executed anew _each_ time
|
|
10
|
+
* the pointer is deref'd.
|
|
11
|
+
*/
|
|
12
|
+
export class Pointer {
|
|
13
|
+
constructor(mem, base, fn) {
|
|
14
|
+
this.mem = mem;
|
|
15
|
+
this.base = base;
|
|
16
|
+
this.fn = fn;
|
|
17
|
+
}
|
|
18
|
+
get addr() {
|
|
19
|
+
return this.mem.u32[this.base >>> 2];
|
|
20
|
+
}
|
|
21
|
+
set addr(addr) {
|
|
22
|
+
this.mem.u32[this.base >>> 2] = addr;
|
|
23
|
+
}
|
|
24
|
+
deref() {
|
|
25
|
+
return this.fn(this.addr);
|
|
26
|
+
}
|
|
27
|
+
}
|
package/string.d.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { IWasmMemoryAccess, ReadonlyWasmString } from "./api.js";
|
|
2
|
+
/**
|
|
3
|
+
* Memory mapped string wrapper for Zig-style UTF-8 encoded byte slices (aka
|
|
4
|
+
* pointer & length pair). The actual JS string can be obtained via
|
|
5
|
+
* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
|
|
6
|
+
*/
|
|
7
|
+
export declare class WasmStringSlice implements ReadonlyWasmString {
|
|
8
|
+
readonly mem: IWasmMemoryAccess;
|
|
9
|
+
readonly base: number;
|
|
10
|
+
readonly isConst: boolean;
|
|
11
|
+
readonly max: number;
|
|
12
|
+
constructor(mem: IWasmMemoryAccess, base: number, isConst?: boolean);
|
|
13
|
+
/**
|
|
14
|
+
* Returns string start address (deref'd pointer).
|
|
15
|
+
*/
|
|
16
|
+
get addr(): number;
|
|
17
|
+
/**
|
|
18
|
+
* Returns string length (read from memory)
|
|
19
|
+
*/
|
|
20
|
+
get length(): number;
|
|
21
|
+
/**
|
|
22
|
+
* Returns memory as JS string (aka wrapper for
|
|
23
|
+
* {@link WasmBridge.getString}).
|
|
24
|
+
*/
|
|
25
|
+
deref(): string;
|
|
26
|
+
/**
|
|
27
|
+
* If given a JS string as arg (and if **not** a const slice), attempts to
|
|
28
|
+
* overwrite this wrapped string's memory with bytes from given string. If
|
|
29
|
+
* given another {@link WasmStringSlice} as arg, only the slice pointer &
|
|
30
|
+
* new length will be updated (always succeeds).
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* When copying bytes from a JS string, an error will be thrown if the new
|
|
34
|
+
* string is longer than the _original_ length of the slice (i.e. from when
|
|
35
|
+
* this `WasmStringSlice` wrapper instance was created). Also updates the
|
|
36
|
+
* slice's length field to new string length.
|
|
37
|
+
*
|
|
38
|
+
* Passing a `WasmString` instance as arg is faster than JS string since
|
|
39
|
+
* only the slice definition itself will be updated.
|
|
40
|
+
*
|
|
41
|
+
* @param str
|
|
42
|
+
*/
|
|
43
|
+
set(str: string | WasmStringSlice): void;
|
|
44
|
+
toJSON(): string;
|
|
45
|
+
toString(): string;
|
|
46
|
+
valueOf(): string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Memory mapped string wrapper for C-style UTF-8 encoded and zero-terminated
|
|
50
|
+
* char pointers. The actual JS string can be obtained via
|
|
51
|
+
* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
|
|
52
|
+
*/
|
|
53
|
+
export declare class WasmStringPtr implements ReadonlyWasmString {
|
|
54
|
+
readonly mem: IWasmMemoryAccess;
|
|
55
|
+
readonly base: number;
|
|
56
|
+
readonly isConst: boolean;
|
|
57
|
+
constructor(mem: IWasmMemoryAccess, base: number, isConst?: boolean);
|
|
58
|
+
/**
|
|
59
|
+
* Returns string start address (deref'd pointer).
|
|
60
|
+
*/
|
|
61
|
+
get addr(): number;
|
|
62
|
+
set addr(addr: number);
|
|
63
|
+
/**
|
|
64
|
+
* Returns computed string length (scanning memory for zero sentinel)
|
|
65
|
+
*/
|
|
66
|
+
get length(): number;
|
|
67
|
+
/**
|
|
68
|
+
* Returns memory as JS string (aka wrapper for
|
|
69
|
+
* {@link WasmBridge.getString}).
|
|
70
|
+
*/
|
|
71
|
+
deref(): string;
|
|
72
|
+
/**
|
|
73
|
+
* If given a JS string as arg (and if not a const pointer), attempts to
|
|
74
|
+
* overwrite this wrapped string's memory with bytes from given string. If
|
|
75
|
+
* given another {@link WasmStringPtr}, it merely overrides the pointer to
|
|
76
|
+
* the new one (always succeeds).
|
|
77
|
+
*
|
|
78
|
+
* @remarks
|
|
79
|
+
* Unlike with {@link WasmStringSlice.set} this implementation which
|
|
80
|
+
* performs bounds checking when copying bytes from a JS string, this method
|
|
81
|
+
* only throws an error if the new string is longer than the available
|
|
82
|
+
* memory (from the start address until the end of the WASM memory).
|
|
83
|
+
* **Therefore, this is as (un)safe as a C pointer and should be used with
|
|
84
|
+
* caution!**
|
|
85
|
+
*
|
|
86
|
+
* Passing a `WasmStringPtr` instance as arg is faster than JS string since
|
|
87
|
+
* only the pointer itself will be updated.
|
|
88
|
+
*
|
|
89
|
+
* @param str
|
|
90
|
+
*/
|
|
91
|
+
set(str: string | WasmStringPtr): void;
|
|
92
|
+
toJSON(): string;
|
|
93
|
+
toString(): string;
|
|
94
|
+
valueOf(): string;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=string.d.ts.map
|