Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@thi.ng/wasm-api

Package Overview
Dependencies
Maintainers
1
Versions
132
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@thi.ng/wasm-api - npm Package Compare versions

Comparing version 0.14.0 to 0.15.0

codegen/align.d.ts

99

api.d.ts

@@ -1,2 +0,3 @@

import type { BigType, FloatType, Fn, IDeref, ILength, IObjectOf } from "@thi.ng/api";
import type { BigType, FloatType, Fn, Fn2, IDeref, ILength, IObjectOf } from "@thi.ng/api";
import type { Pow2 } from "@thi.ng/binary";
import type { WasmBridge } from "./bridge.js";

@@ -127,4 +128,8 @@ export declare const PKG_NAME = "@thi.ng/wasm-api";

* Core API of WASM imports defined by the {@link WasmBridge}. The same
* functions are declared as bindings in `/zig/core.zig`. Also see this file for
* documentation of each function...
* functions are declared as bindings in `/zig/wasmapi.zig`. **Also see this
* file for documentation of each function...**
*
* @remarks
* Zig API:
* https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api/zig/wasmapi.zig
*/

@@ -196,3 +201,3 @@ export interface CoreAPI extends WebAssembly.ModuleImports {

/**
* Auto-computed offset (in bytes) in parent struct
* Auto-computed offset (in bytes) in parent struct.
*

@@ -203,7 +208,7 @@ * @internal

/**
* Auto-computed alignment (in bytes)
* Auto-computed alignment (in bytes) actually used.
*
* @internal
*/
__align?: number;
__align?: Pow2;
}

@@ -222,3 +227,3 @@ export interface TopLevelType extends TypeInfo {

*/
type: "struct" | "enum";
type: "enum" | "struct" | "union";
/**

@@ -236,6 +241,6 @@ * Optional object of user provided source codes to be injected into the

/**
* List of struct fields (might be re-ordered if {@link Struct.auto} is
* Array of struct fields (might be re-ordered if {@link Struct.auto} is
* enabled).
*/
fields: StructField[];
fields: Field[];
/**

@@ -256,4 +261,10 @@ * If true, struct fields will be re-ordered in descending order based on

tag?: "extern" | "packed";
/**
* Optional user supplied {@link AlignStrategy}. By default uses
* {@link ALIGN_C} or {@link ALIGN_PACKED} (if using "packed" structs).
*/
align?: AlignStrategy;
}
export interface StructField extends TypeInfo {
export declare type FieldTag = "scalar" | "array" | "ptr" | "slice" | "vec";
export interface Field extends TypeInfo {
/**

@@ -273,3 +284,3 @@ * Field name (prefix: "__" is reserved)

* - Array & vector fields are statically sized (using
* {@link StructField.len})
* {@link Field.len})
* - Pointers are emitted as single-value pointers (where this distinction

@@ -284,3 +295,3 @@ * exist), i.e. even if they're pointing to multiple values, there's no

*/
tag?: "scalar" | "array" | "ptr" | "slice" | "vec";
tag?: FieldTag;
/**

@@ -308,3 +319,3 @@ * Field base type. If not a {@link WasmPrim}, `string` or `opaque`, the

/**
* Array or vector length (see {@link StructField.tag})
* Array or vector length (see {@link Field.tag})
*/

@@ -318,7 +329,25 @@ len?: number;

/**
* If defined and > 0, the field will be considered for padding purposes only and
* the value provided is the number of bytes used.
* If defined and > 0, the field will be considered for padding purposes
* only and the value provided is the number of bytes used. All other config
* for this field will be ignored!
*/
pad?: number;
}
export interface Union extends TopLevelType {
type: "union";
/**
* Array of union fields.
*/
fields: Field[];
/**
* Optional qualifier for the kind of struct to be emitted (codegen specific
* interpretation, currently only used by {@link ZIG}).
*/
tag?: "extern" | "packed";
/**
* Optional user supplied {@link AlignStrategy}. By default uses
* {@link ALIGN_C} or {@link ALIGN_PACKED} (if using "packed" union).
*/
align?: AlignStrategy;
}
export interface Enum extends TopLevelType {

@@ -353,2 +382,16 @@ type: "enum";

}
export interface AlignStrategy {
/**
* Returns implementation specific alignment for given struct field.
*/
align: Fn<Field, Pow2>;
/**
* Returns possibly rounded value for given base size & alignment.
*/
size: Fn2<number, Pow2, number>;
/**
* Returns possibly rounded value for given base offset & alignment.
*/
offset: Fn2<number, Pow2, number>;
}
export interface CodeGenOptsBase {

@@ -359,3 +402,3 @@ /**

*/
pre: string;
pre?: string;
/**

@@ -365,3 +408,3 @@ * Optional string to be injected after generated type defs (but before

*/
post: string;
post?: string;
}

@@ -373,2 +416,8 @@ /**

/**
* WASM target specification.
*
* @defaultValue {@link WASM32}
*/
target: WasmTarget;
/**
* Identifier how strings are stored on WASM side, e.g. in Zig string

@@ -426,11 +475,19 @@ * literals are slices (8 bytes), in C just plain pointers (4 bytes).

struct: (type: Struct, types: TypeColl, acc: string[], opts: CodeGenOpts) => void;
/**
* Codegen for union types.
*/
union: (type: Union, types: TypeColl, acc: string[], opts: CodeGenOpts) => void;
}
export interface WasmTarget {
usize: "u32" | "u64";
usizeBytes: number;
}
/**
* WASM usize type. Assuming wasm32 until wasm64 surfaces, then need an option.
* WASM32 target spec
*/
export declare const USIZE = "u32";
export declare const WASM32: WasmTarget;
/**
* Byte size of {@link USIZE}.
* WASM64 target spec
*/
export declare const USIZE_SIZE = 4;
export declare const WASM64: WasmTarget;
//# sourceMappingURL=api.d.ts.map
export const PKG_NAME = "@thi.ng/wasm-api";
export const EVENT_MEMORY_CHANGED = "memory-changed";
/**
* WASM usize type. Assuming wasm32 until wasm64 surfaces, then need an option.
* WASM32 target spec
*/
export const USIZE = "u32";
export const WASM32 = {
usize: "u32",
usizeBytes: 4,
};
/**
* Byte size of {@link USIZE}.
* WASM64 target spec
*/
export const USIZE_SIZE = 4;
export const WASM64 = {
usize: "u64",
usizeBytes: 8,
};
# Change Log
- **Last updated**: 2022-10-17T12:08:09Z
- **Last updated**: 2022-10-26T12:46:53Z
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)

@@ -12,2 +12,37 @@

## [0.15.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@0.15.0) (2022-10-26)
#### 🚀 Features
- import ManagedIndex, migrate Zig API ([d8bb3ee](https://github.com/thi-ng/umbrella/commit/d8bb3ee))
- migrate ManagedIndex from [@thi.ng/wasm-api-dom](https://github.com/thi-ng/umbrella/tree/main/packages/wasm-api-dom)
- move all Zig sources from /include => /zig
- update pkg
- add codegen support for union types ([bbc1f98](https://github.com/thi-ng/umbrella/commit/bbc1f98))
- add Union type, update TopLevelType
- update all codegens (C,TS,Zig)
- update alignOf(), sizeOf()
- update selectAlignment()
- add/update codegen alignment logic ([9c19ad9](https://github.com/thi-ng/umbrella/commit/9c19ad9))
- add AlignmentStrategy & impls
- update alignOf(), sizeOf(), prepareType()
- extract DEFAULT_CODEGEN_OPTS
- add Struct.align config option
- add WasmTarget codegen opt & usize support ([62c049b](https://github.com/thi-ng/umbrella/commit/62c049b))
#### 🩹 Bug fixes
- update CLI wrapper to allow unions ([904716c](https://github.com/thi-ng/umbrella/commit/904716c))
- fix i64/u64 handling in sizeof() ([825add3](https://github.com/thi-ng/umbrella/commit/825add3))
- fix padding in Zig packed structs ([8d70cf6](https://github.com/thi-ng/umbrella/commit/8d70cf6))
- since packed structs can't contain `[n]u8` types,
generate padding as potentially multiple `uXXX` fields
#### ♻️ Refactoring
- rename types, use predicates ([4148e1e](https://github.com/thi-ng/umbrella/commit/4148e1e))
- rename StructField => Field
- update codegens to use more predicates instead of inline checks
- minor updates C & Zig codegens ([a94e1cc](https://github.com/thi-ng/umbrella/commit/a94e1cc))
## [0.14.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@0.14.0) (2022-10-17)

@@ -14,0 +49,0 @@

@@ -25,3 +25,7 @@ import { flag, oneOf, oneOfMulti, parse, ParseError, string, strings, usage, } from "@thi.ng/args";

}),
debug: flag({ alias: "d", default: false, desc: "enable debug output" }),
debug: flag({
alias: "d",
default: false,
desc: "enable debug output & functions",
}),
dryRun: flag({

@@ -75,3 +79,3 @@ default: false,

invalidSpec(path);
if (!(spec.type === "enum" || spec.type === "struct"))
if (!["enum", "struct", "union"].includes(spec.type))
invalidSpec(path, `${spec.name} type: ${spec.type}`);

@@ -78,0 +82,0 @@ if (coll[spec.name])

import { CodeGenOpts, ICodeGen, TypeColl } from "./api.js";
export declare const DEFAULT_CODEGEN_OPTS: CodeGenOpts;
/**

@@ -14,3 +15,3 @@ * Takes a type collection and analyzes each analyzed to compute individual

*/
export declare const prepareTypes: (types: TypeColl, opts: CodeGenOpts) => void;
export declare const prepareTypes: (types: TypeColl, opts: CodeGenOpts) => TypeColl;
/**

@@ -17,0 +18,0 @@ * Code generator main entry point. Takes an object of {@link TopLevelType}

import { SIZEOF } from "@thi.ng/api/typedarray";
import { align } from "@thi.ng/binary/align";
import { ceilPow2 } from "@thi.ng/binary/pow";
import { compareByKey } from "@thi.ng/compare/keys";

@@ -8,6 +6,15 @@ import { compareNumDesc } from "@thi.ng/compare/numeric";

import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
import { PKG_NAME, USIZE_SIZE, } from "./api.js";
import { isNumeric, isWasmString } from "./codegen/utils.js";
import { PKG_NAME, WASM32, } from "./api.js";
import { selectAlignment } from "./codegen/align.js";
import { isBigNumeric, isNumeric, isPointer, isPointerLike, isSlice, isStringSlice, isWasmString, } from "./codegen/utils.js";
export const DEFAULT_CODEGEN_OPTS = {
debug: false,
header: true,
lineWidth: 80,
stringType: "slice",
target: WASM32,
uppercaseEnums: true,
};
const sizeOf = defmulti((x) => x.type, {}, {
[DEFAULT]: (field, types, opts) => {
[DEFAULT]: (field, types, align, opts) => {
if (field.__size)

@@ -20,14 +27,16 @@ return field.__size;

let size = 0;
if (field.tag === "ptr") {
size = USIZE_SIZE;
if (isPointer(field)) {
size = opts.target.usizeBytes;
}
else if (field.tag === "slice") {
size = USIZE_SIZE * 2;
else if (isSlice(field)) {
size = opts.target.usizeBytes * 2;
}
else {
size = isNumeric(field.type)
? SIZEOF[field.type]
: isWasmString(field.type)
? USIZE_SIZE * (opts.stringType === "slice" ? 2 : 1)
: sizeOf(types[field.type], types, opts);
size =
isNumeric(field.type) || isBigNumeric(field.type)
? SIZEOF[field.type]
: isWasmString(field.type)
? opts.target.usizeBytes *
(isStringSlice(opts.stringType) ? 2 : 1)
: sizeOf(types[field.type], types, align, opts);
if (field.tag == "array" || field.tag === "vec") {

@@ -40,3 +49,3 @@ size *= field.len;

}
return (field.__size = align(size, field.__align));
return (field.__size = align.size(size, field.__align));
},

@@ -48,59 +57,74 @@ enum: (type) => {

},
struct: (type, types, opts) => {
struct: (type, types, align, opts) => {
if (type.__size)
return type.__size;
const struct = type;
let size = 0;
for (let f of struct.fields) {
size = align(size, f.__align);
f.__offset = size;
size += sizeOf(f, types, opts);
let offset = 0;
for (let f of type.fields) {
offset = align.offset(offset, f.__align);
f.__offset = offset;
offset += sizeOf(f, types, align, opts);
}
return (type.__size = align(size, type.__align));
return (type.__size = align.size(offset, type.__align));
},
union: (type, types, align, opts) => {
if (type.__size)
return type.__size;
let maxSize = 0;
for (let f of type.fields) {
f.__offset = 0;
maxSize = Math.max(maxSize, sizeOf(f, types, align, opts));
}
return (type.__size = align.size(maxSize, type.__align));
},
});
const alignOf = defmulti((x) => x.type, {}, {
[DEFAULT]: (field, types) => {
[DEFAULT]: (field, types, align, opts) => {
if (field.__align)
return field.__align;
if (field.type === "usize") {
field.type = opts.target.usize;
}
if (field.pad)
return (field.__align = 1);
let align = isNumeric(field.type)
? SIZEOF[field.type]
: isWasmString(field.type)
? USIZE_SIZE
: alignOf(types[field.type], types);
if (field.tag === "vec") {
align *= ceilPow2(field.len);
}
field.__align = align;
return align;
return (field.__align = isPointerLike(field)
? align.align({ type: opts.target.usize })
: isNumeric(field.type) || isBigNumeric(field.type)
? align.align(field)
: alignOf(types[field.type], types, selectAlignment(types[field.type]), opts));
},
enum: (type) => {
enum: (type, _, align) => {
const e = type;
if (!e.tag)
e.tag = "i32";
return (e.__align = SIZEOF[e.tag]);
return (e.__align = align.align({
type: e.tag,
}));
},
struct: (type, types) => {
const struct = type;
let maxAlign = 0;
for (let f of struct.fields) {
maxAlign = Math.max(maxAlign, alignOf(f, types));
struct: (type, types, align, opts) => {
let maxAlign = 1;
for (let f of type.fields) {
maxAlign = Math.max(maxAlign, alignOf(f, types, align, opts));
}
return (type.__align = maxAlign);
},
union: (type, types, align, opts) => {
let maxAlign = 1;
for (let f of type.fields) {
maxAlign = Math.max(maxAlign, alignOf(f, types, align, opts));
}
return (type.__align = maxAlign);
},
});
const prepareType = defmulti((x) => x.type, {}, {
[DEFAULT]: (x, types, opts) => {
[DEFAULT]: (x, types, alignImpl, opts) => {
if (x.__align && x.__size)
return;
alignOf(x, types);
sizeOf(x, types, opts);
alignOf(x, types, alignImpl, opts);
sizeOf(x, types, alignImpl, opts);
},
struct: (x, types, opts) => {
struct: (x, types, align, opts) => {
if (x.__align && x.__size)
return;
const struct = x;
alignOf(struct, types);
alignOf(struct, types, align, opts);
if (struct.auto) {

@@ -110,7 +134,8 @@ struct.fields.sort(compareByKey("__align", compareNumDesc));

for (let f of struct.fields) {
if (types[f.type]) {
prepareType(types[f.type], types, opts);
const type = types[f.type];
if (type) {
prepareType(type, types, selectAlignment(type), opts);
}
}
sizeOf(struct, types, opts);
sizeOf(struct, types, align, opts);
},

@@ -132,4 +157,5 @@ });

for (let id in types) {
prepareType(types[id], types, opts);
prepareType(types[id], types, selectAlignment(types[id]), opts);
}
return types;
};

@@ -153,6 +179,3 @@ /**

const $opts = {
header: true,
stringType: "slice",
uppercaseEnums: true,
lineWidth: 80,
...DEFAULT_CODEGEN_OPTS,
...opts,

@@ -159,0 +182,0 @@ };

import { isString } from "@thi.ng/checks/is-string";
import { unsupported } from "@thi.ng/errors/unsupported";
import { enumName, isPadding, isStringSlice, prefixLines, withIndentation, } from "./utils.js";
import { enumName, isPadding, isStringSlice, isWasmString, prefixLines, withIndentation, } from "./utils.js";
const PRIM_ALIASES = {

@@ -71,60 +71,76 @@ i8: "int8_t",

const name = typePrefix + struct.name;
const res = [];
res.push(`typedef struct ${name} ${name};`, `struct ${name} {`);
const ftypes = {};
let padID = 0;
for (let f of struct.fields) {
// autolabel explicit padding fields
if (isPadding(f)) {
res.push(`uint8_t __pad${padID++}[${f.pad}];`);
continue;
}
f.doc && gen.doc(f.doc, res, opts);
const fconst = f.const ? "const " : "";
let ftype = f.type === "string"
? isStringSlice(opts.stringType)
? __slice("char", fconst)
: `${f.const !== false ? "const " : ""}char*`
: PRIM_ALIASES[f.type] || f.type;
if (coll[ftype])
ftype = typePrefix + ftype;
switch (f.tag) {
case "array":
case "vec":
res.push(`${fconst}${ftype} ${f.name}[${f.len}];`);
ftype = `${ftype}[${f.len}]`;
break;
case "slice":
ftype = __slice(ftype, fconst);
res.push(`${ftype} ${f.name};`);
break;
case "ptr":
ftype = `${fconst}${ftype}*`;
res.push(`${ftype} ${f.name};`);
break;
case "scalar":
default:
res.push(`${ftype} ${f.name};`);
}
ftypes[f.name] = ftype;
}
res.push("};");
if (opts.debug) {
const fn = (fname, body) => res.push("", `size_t __attribute__((used)) ${name}_${fname}() {`, `return ${body};`, `}`);
fn("align", `alignof(${name})`);
fn("size", `sizeof(${name})`);
for (let f of struct.fields) {
if (isPadding(f))
continue;
fn(f.name + "_align", `alignof(${ftypes[f.name]})`);
fn(f.name + "_offset", `offsetof(${name}, ${f.name})`);
fn(f.name + "_size", `sizeof(${ftypes[f.name]})`);
}
}
res.push("");
acc.push(...withIndentation(res, INDENT, ...SCOPES));
acc.push(...withIndentation([
`typedef struct ${name} ${name};`,
`struct ${name} {`,
...__generateFields(gen, struct, coll, opts, typePrefix),
], INDENT, ...SCOPES));
},
union: (union, coll, acc, opts) => {
const name = typePrefix + union.name;
acc.push(...withIndentation([
`typedef union ${name} ${name};`,
`union ${name} {`,
...__generateFields(gen, union, coll, opts, typePrefix),
], INDENT, ...SCOPES));
},
};
return gen;
};
const __generateFields = (gen, parent, coll, opts, typePrefix) => {
const res = [];
const ftypes = {};
const isUnion = parent.type === "union";
const name = typePrefix + parent.name;
let padID = 0;
for (let f of parent.fields) {
// autolabel explicit padding fields
if (isPadding(f)) {
res.push(`uint8_t __pad${padID++}[${f.pad}];`);
continue;
}
f.doc && gen.doc(f.doc, res, opts);
const fconst = f.const ? "const " : "";
let ftype = isWasmString(f.type)
? isStringSlice(opts.stringType)
? __slice("char", fconst)
: `${f.const !== false ? "const " : ""}char*`
: PRIM_ALIASES[f.type] || f.type;
if (coll[ftype])
ftype = typePrefix + ftype;
switch (f.tag) {
case "array":
case "vec":
res.push(`${fconst}${ftype} ${f.name}[${f.len}];`);
ftype = `${ftype}[${f.len}]`;
break;
case "slice":
ftype = __slice(ftype, fconst);
res.push(`${ftype} ${f.name};`);
break;
case "ptr":
ftype = `${fconst}${ftype}*`;
res.push(`${ftype} ${f.name};`);
break;
case "scalar":
default:
res.push(`${ftype} ${f.name};`);
}
ftypes[f.name] = ftype;
}
res.push("};");
if (opts.debug) {
const fn = (fname, body) => res.push("", `size_t __attribute__((used)) ${name}_${fname}() {`, `return ${body};`, `}`);
fn("align", `alignof(${name})`);
fn("size", `sizeof(${name})`);
for (let f of parent.fields) {
if (isPadding(f))
continue;
fn(f.name + "_align", `alignof(${ftypes[f.name]})`);
!isUnion && fn(f.name + "_offset", `offsetof(${name}, ${f.name})`);
fn(f.name + "_size", `sizeof(${ftypes[f.name]})`);
}
}
res.push("");
return res;
};
const __slice = (type, $const) => `struct { ${$const}${type} *ptr; size_t len; }`;
import { BIGINT_ARRAY_CTORS, BIT_SHIFTS, TYPEDARRAY_CTORS, } from "@thi.ng/api/typedarray";
import { isString } from "@thi.ng/checks/is-string";
import { PKG_NAME, USIZE, USIZE_SIZE, } from "../api.js";
import { PKG_NAME, } from "../api.js";
import { enumName, isBigNumeric, isNumeric, isPadding, isStringSlice, isWasmPrim, isWasmString, pointerFields, prefixLines, stringFields, withIndentation, } from "./utils.js";

@@ -94,3 +94,3 @@ /**

`(addr) => {`,
...__mapStringArray("buf", $stringImpl, f.len, isConst, true),
...__mapStringArray(opts.target, "buf", $stringImpl, f.len, isConst, true),
`}`,

@@ -111,11 +111,11 @@ ]

else if (f.tag === "slice") {
lines.push(`const len = ${__ptr(offset + 4)};`);
lines.push(`const len = ${__ptr(opts.target, offset + 4)};`);
if (isPrim) {
lines.push(`const addr = ${__ptrShift(offset, f.type)};`, `return mem.${f.type}.subarray(addr, addr + len);`);
lines.push(`const addr = ${__ptrShift(opts.target, offset, f.type)};`, `return mem.${f.type}.subarray(addr, addr + len);`);
}
else if (isStr) {
lines.push(`const addr = ${__ptr(offset)};`, ...__mapStringArray("buf", $stringImpl, "len", isConst));
lines.push(`const addr = ${__ptr(opts.target, offset)};`, ...__mapStringArray(opts.target, "buf", $stringImpl, "len", isConst));
}
else {
lines.push(`const addr = ${__ptr(offset)};`, ...__mapArray(f));
lines.push(`const addr = ${__ptr(opts.target, offset)};`, ...__mapArray(f));
}

@@ -128,3 +128,3 @@ }

else if (isStr) {
lines.push(`if ($${f.name}) return $${f.name};`, `const addr = ${__addr(offset)};`, ...__mapStringArray(f.name, $stringImpl, f.len, isConst));
lines.push(`if ($${f.name}) return $${f.name};`, `const addr = ${__addr(offset)};`, ...__mapStringArray(opts.target, f.name, $stringImpl, f.len, isConst));
}

@@ -168,2 +168,5 @@ else {

},
union: (type, coll, acc, opts) => {
gen.struct(type, coll, acc, opts);
},
};

@@ -208,5 +211,5 @@ return gen;

/** @internal */
const __ptr = (offset) => `mem.${USIZE}[${__addrShift(offset, USIZE)}]`;
const __ptr = (target, offset) => `mem.${target.usize}[${__addrShift(offset, target.usize)}]`;
/** @internal */
const __ptrShift = (offset, shift) => __ptr(offset) + " >>> " + __shift(shift);
const __ptrShift = (target, offset, shift) => __ptr(target, offset) + " >>> " + __shift(shift);
const __mem = (type, offset) => `mem.${type}[${__addrShift(offset, type)}]`;

@@ -221,6 +224,6 @@ /** @internal */

/** @internal */
const __mapStringArray = (name, type, len, isConst, isLocal = false) => [
const __mapStringArray = (target, name, type, len, isConst, isLocal = false) => [
isLocal ? `const $${name}: ${type}[] = [];` : `$${name} = [];`,
`for(let i = 0; i < ${len}; i++) $${name}.push(new ${type}(mem, addr + i * ${USIZE_SIZE * (type === "WasmStringSlice" ? 2 : 1)}, ${isConst}));`,
`for(let i = 0; i < ${len}; i++) $${name}.push(new ${type}(mem, addr + i * ${target.usizeBytes * (type === "WasmStringSlice" ? 2 : 1)}, ${isConst}));`,
`return $${name};`,
];
import type { BigType } from "@thi.ng/api";
import type { CodeGenOpts, StructField, WasmPrim, WasmPrim32 } from "../api.js";
import type { CodeGenOpts, Field, WasmPrim, WasmPrim32 } from "../api.js";
/**

@@ -22,4 +22,12 @@ * Returns true iff `x` is a {@link WasmPrim32}.

export declare const isWasmString: (x: string) => x is "string";
export declare const isPadding: (f: StructField) => boolean;
export declare const isPadding: (f: Field) => boolean;
export declare const isPointer: (f: Field) => boolean;
export declare const isSlice: (f: Field) => boolean;
/**
* Returns true iff the struct field is a pointer, slice or "string" type
*
* @param f
*/
export declare const isPointerLike: (f: Field) => boolean;
/**
* Takes an array of strings or splits given string into lines, word wraps and

@@ -47,3 +55,3 @@ * then prefixes each line with given `width` and `prefix`. Returns array of new

*/
export declare const pointerFields: (fields: StructField[]) => StructField[];
export declare const pointerFields: (fields: Field[]) => Field[];
/**

@@ -56,3 +64,3 @@ * Returns filtered array of struct fields of only "string" fields.

*/
export declare const stringFields: (fields: StructField[]) => StructField[];
export declare const stringFields: (fields: Field[]) => Field[];
/**

@@ -59,0 +67,0 @@ * Returns enum identifier formatted according to given opts.

@@ -23,3 +23,11 @@ import { isString } from "@thi.ng/checks/is-string";

export const isPadding = (f) => f.pad != null && f.pad > 0;
export const isPointer = (f) => f.tag === "ptr";
export const isSlice = (f) => f.tag === "slice";
/**
* Returns true iff the struct field is a pointer, slice or "string" type
*
* @param f
*/
export const isPointerLike = (f) => isPointer(f) || isSlice(f) || isWasmString(f.type);
/**
* Takes an array of strings or splits given string into lines, word wraps and

@@ -26,0 +34,0 @@ * then prefixes each line with given `width` and `prefix`. Returns array of new

@@ -5,3 +5,3 @@ import { isNumber } from "@thi.ng/checks/is-number";

import { split } from "@thi.ng/strings/split";
import { enumName, isPadding, isStringSlice, prefixLines, withIndentation, } from "./utils.js";
import { enumName, isPadding, isStringSlice, isWasmString, prefixLines, withIndentation, } from "./utils.js";
/**

@@ -49,73 +49,97 @@ * Zig code generator. Call with options and then pass to {@link generateTypes}

struct: (struct, _, acc, opts) => {
const name = struct.name;
const res = [];
res.push(`pub const ${name} = ${struct.tag ? struct.tag + " " : ""}struct {`);
const ftypes = {};
let padID = 0;
for (let f of struct.fields) {
// autolabel explicit padding fields
if (isPadding(f)) {
res.push(`__pad${padID++}: [${f.pad}]u8,`);
continue;
}
f.doc && gen.doc(f.doc, res, opts);
let ftype = f.type === "string"
? isStringSlice(opts.stringType)
? f.const !== false
? "[]const u8"
: "[]u8"
: f.const !== false
? "[*:0]const u8"
: "[*:0]u8"
: f.type;
let defaultVal = "";
switch (f.tag) {
case "array":
ftype =
f.sentinel !== undefined
? `[${f.len}:${f.sentinel}]${ftype}`
: `[${f.len}]${ftype}`;
break;
case "slice":
ftype = `[${f.sentinel !== undefined ? ":" + f.sentinel : ""}]${f.const ? "const " : ""}${ftype}`;
break;
case "vec":
ftype = `@Vector(${f.len}, ${ftype})`;
break;
case "ptr":
ftype = `*${f.const ? "const " : ""}${f.len ? `[${f.len}]` : ""}${ftype}`;
break;
case "scalar":
default:
if (f.default != undefined) {
if (!(isString(f.default) || isNumber(f.default))) {
unsupported(`wrong default value for ${name}.${f.name} (${f.default})`);
}
defaultVal = ` = ${JSON.stringify(f.default)}`;
}
}
ftypes[f.name] = ftype;
res.push(`${f.name}: ${ftype}${defaultVal},`);
}
if (struct.body?.zig) {
res.push("", ...split(struct.body.zig), "");
}
res.push("};");
if (opts.debug) {
const fn = (fname, body) => res.push("", `export fn ${name}_${fname}() usize {`, `return ${body};`, `}`);
fn("align", `@alignOf(${name})`);
fn("size", `@sizeOf(${name})`);
for (let f of struct.fields) {
if (isPadding(f))
continue;
fn(f.name + "_align", `@alignOf(${ftypes[f.name]})`);
fn(f.name + "_offset", `@offsetOf(${name}, "${f.name}")`);
fn(f.name + "_size", `@sizeOf(${ftypes[f.name]})`);
}
}
res.push("");
acc.push(...withIndentation(res, INDENT, ...SCOPES));
acc.push(...withIndentation([
`pub const ${struct.name} = ${struct.tag ? struct.tag + " " : ""}struct {`,
...__generateFields(gen, struct, opts),
], INDENT, ...SCOPES));
},
union: (union, _, acc, opts) => {
acc.push(...withIndentation([
`pub const ${union.name} = ${union.tag ? union.tag + " " : ""}union {`,
...__generateFields(gen, union, opts),
], INDENT, ...SCOPES));
},
};
return gen;
};
const __generateFields = (gen, parent, opts) => {
const res = [];
const ftypes = {};
const isUnion = parent.type === "union";
const name = parent.name;
let padID = 0;
for (let f of parent.fields) {
// autolabel explicit padding fields
if (isPadding(f)) {
parent.tag === "packed"
? __packedPadding(padID, f.pad, res)
: res.push(`__pad${padID}: [${f.pad}]u8,`);
padID++;
continue;
}
f.doc && gen.doc(f.doc, res, opts);
let ftype = isWasmString(f.type)
? isStringSlice(opts.stringType)
? f.const !== false
? "[]const u8"
: "[]u8"
: f.const !== false
? "[*:0]const u8"
: "[*:0]u8"
: f.type;
let defaultVal = "";
switch (f.tag) {
case "array":
ftype =
f.sentinel !== undefined
? `[${f.len}:${f.sentinel}]${ftype}`
: `[${f.len}]${ftype}`;
break;
case "slice":
ftype = `[${f.sentinel !== undefined ? ":" + f.sentinel : ""}]${f.const ? "const " : ""}${ftype}`;
break;
case "vec":
ftype = `@Vector(${f.len}, ${ftype})`;
break;
case "ptr":
ftype = `*${f.const ? "const " : ""}${f.len ? `[${f.len}]` : ""}${ftype}`;
break;
case "scalar":
default:
if (f.default != undefined) {
if (!(isString(f.default) || isNumber(f.default))) {
unsupported(`wrong default value for ${name}.${f.name} (${f.default})`);
}
defaultVal = ` = ${JSON.stringify(f.default)}`;
}
}
ftypes[f.name] = ftype;
res.push(`${f.name}: ${ftype}${defaultVal},`);
}
if (parent.body?.zig) {
res.push("", ...split(parent.body.zig), "");
}
res.push("};");
if (opts.debug) {
const fn = (fname, body) => res.push("", `export fn ${name}_${fname}() usize {`, `return ${body};`, `}`);
fn("align", `@alignOf(${name})`);
fn("size", `@sizeOf(${name})`);
for (let f of parent.fields) {
if (isPadding(f))
continue;
fn(f.name + "_align", `@alignOf(${ftypes[f.name]})`);
!isUnion &&
fn(f.name + "_offset", `@offsetOf(${name}, "${f.name}")`);
fn(f.name + "_size", `@sizeOf(${ftypes[f.name]})`);
}
}
res.push("");
return res;
};
const __packedPadding = (id, n, res) => {
let i = 0;
n <<= 3;
for (; n >= 128; n -= 128, i++) {
res.push(`__pad${id}_${i}: u128,`);
}
res.push(`__pad${id}_${i}: u${n},`);
};
{
"name": "@thi.ng/wasm-api",
"version": "0.14.0",
"version": "0.15.0",
"description": "Generic, modular, extensible API bridge, polyglot glue code and bindings code generators for hybrid JS & WebAssembly projects",

@@ -36,17 +36,17 @@ "type": "module",

"test": "testament test",
"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"
"test:build-zig": "zig build-lib -O ReleaseSmall -target wasm32-freestanding -dynamic --strip --pkg-begin wasmapi zig/wasmapi.zig --pkg-end test/custom.zig && wasm-dis -o custom.wast custom.wasm && cp custom.wasm test"
},
"dependencies": {
"@thi.ng/api": "^8.4.3",
"@thi.ng/args": "^2.2.5",
"@thi.ng/binary": "^3.3.6",
"@thi.ng/checks": "^3.3.0",
"@thi.ng/args": "^2.2.6",
"@thi.ng/binary": "^3.3.7",
"@thi.ng/checks": "^3.3.1",
"@thi.ng/compare": "^2.1.13",
"@thi.ng/defmulti": "^2.1.18",
"@thi.ng/errors": "^2.2.2",
"@thi.ng/file-io": "^0.3.15",
"@thi.ng/file-io": "^0.3.16",
"@thi.ng/hex": "^2.2.1",
"@thi.ng/idgen": "^2.1.15",
"@thi.ng/logger": "^1.4.1",
"@thi.ng/paths": "^5.1.18",
"@thi.ng/paths": "^5.1.19",
"@thi.ng/strings": "^3.3.14"

@@ -100,3 +100,4 @@ },

"codegen",
"include"
"include",
"zig"
],

@@ -113,2 +114,5 @@ "exports": {

},
"./codegen/align": {
"default": "./codegen/align.js"
},
"./codegen/c11": {

@@ -143,3 +147,3 @@ "default": "./codegen/c11.js"

},
"gitHead": "612b1b0bdf442473f04c2edac3012975a6ca28bb\n"
"gitHead": "cc61bc0a890288bea00b8df81ffd73bc4851ffd3\n"
}

@@ -48,12 +48,15 @@ <!-- This file is generated - DO NOT EDIT! -->

WebGL, WebGPU, WebAudio etc. is being actively worked on.
3. [Include files for C11/C++ and
Zig](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api/include),
defining WASM imports of the extern JS [core
3. Include files for
[C11/C++](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api/include)
and
[Zig](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api/zig),
defining glue code for the JS [core
API](https://docs.thi.ng/umbrella/wasm-api/interfaces/CoreAPI.html) defined
by this package
4. Extensible shared datatype code generators for (currently) C11, TypeScript &
[Zig](https://ziglang.org). The latter also generates fully type checked
memory-mapped (zero-copy) accessors of WASM-side data. In general, all
languages with a WebAssembly target are supported, however currently only
bindings for these mentioned langs are included.
4. Extensible shared datatype code generators for (currently) C11, Zig &
TypeScript. The latter also generates fully type checked memory-mapped
(zero-copy) accessors of WASM-side data. In general, all languages with a
WebAssembly target are supported, however currently only bindings for these
mentioned langs are included. Other languages require custom bindings, e.g.
based on the flexible primitives provided here.
5. [CLI frontend/utility](#cli-generator) to invoke the code generator(s)

@@ -65,4 +68,4 @@

bilateral design & exchange of data structures shared between the WASM & JS host
env. Currently, code generators for TypeScript & Zig are supplied (more are
planned). A CLI wrapper is available too. See the
env. Currently, code generators for TypeScript, Zig and C11 are supplied. A CLI
wrapper is available too. See the
[@thi.ng/wasm-api-dom](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api-dom/)

@@ -83,3 +86,3 @@ support package for a more thorough realworld example...

██ █ │
█ █ █ █ █ █ █ █ │ @thi.ng/wasm-api 0.12.0
█ █ █ █ █ █ █ █ │ @thi.ng/wasm-api 0.15.0
█ █ █ █ █ █ █ █ █ │ Multi-language data bindings code generator

@@ -94,3 +97,3 @@ █ │

-d, --debug enable debug output
-d, --debug enable debug output & functions
--dry-run enable dry run (don't overwrite files)

@@ -109,4 +112,4 @@

Order is important, since the output file paths must be given in the same order
as the target languages. It's recommended to be more explicit with this. An
example invocation looks like:
as the target languages. It's recommended to be explicit with this. An example
invocation looks like:

@@ -153,9 +156,10 @@ ```bash

Currently, the code generator supports structs and enums. See API docs for
Currently, the code generator supports enums, structs and unions. See API docs for
further details:
- [`Enum`](https://docs.thi.ng/umbrella/wasm-api/interfaces/Enum.html)
- [`EnumValue`](https://docs.thi.ng/umbrella/wasm-api/interfaces/EnumValue.html)
- [`EnumValue`](https://docs.thi.ng/umbrella/wasm-api/interfaces/EnumValue.html) (individual enum value spec)
- [`Field`](https://docs.thi.ng/umbrella/wasm-api/interfaces/Field.html) (individual spec for values contained in structs/unions)
- [`Struct`](https://docs.thi.ng/umbrella/wasm-api/interfaces/Struct.html)
- [`StructField`](https://docs.thi.ng/umbrella/wasm-api/interfaces/StructField.html)
- [`Union`](https://docs.thi.ng/umbrella/wasm-api/interfaces/Union.html)
- [`TopLevelType`](https://docs.thi.ng/umbrella/wasm-api/interfaces/TopLevelType.html)

@@ -165,4 +169,4 @@

Below is an example file with JSON type definitions and the resulting source
codes:
The following example defines 1x enum, 2x structs and 1x union. Shown here are
the JSON type definitions and the resulting source codes:

@@ -173,31 +177,39 @@ **⬇︎ CLICK TO EXPAND EACH CODE BLOCK ⬇︎**

```json
```json tangle:export/readme-types.json
[
{
"name": "Foo",
"name": "EventType",
"type": "enum",
"tag": "u8",
"values": [
"unknown",
{ "name": "mouse", "value": 16 },
{ "name": "key", "value": 32 }
]
},
{
"name": "MouseEvent",
"type": "struct",
"doc": "Example struct",
"auto": true,
"fields": [
{ "name": "id", "type": "u8", "doc": "Unique ID" },
{ "name": "bars", "type": "Bar", "tag": "array", "len": 3 },
{ "name": "color", "type": "f32", "tag": "vec", "len": 4 }
{ "name": "type", "type": "EventType" },
{ "name": "pos", "type": "u16", "tag": "vec", "len": 2 }
]
},
{
"name": "Bar",
"name": "KeyEvent",
"type": "struct",
"doc": "Example struct",
"fields": [
{ "name": "kind", "type": "Kind" },
{ "name": "flags", "type": "u32" }
{ "name": "type", "type": "EventType" },
{ "name": "key", "type": "string" },
{ "name": "modifiers", "type": "u8", "doc": "Bitmask of modifier keys" }
]
},
{
"name": "Kind",
"type": "enum",
"tag": "u16",
"values": [
"unknown",
{ "name": "good", "value": 100 },
{ "name": "best", "value": 1000 }
"name": "Event",
"type": "union",
"fields": [
{ "name": "mouse", "type": "MouseEvent" },
{ "name": "key", "type": "KeyEvent" }
]

@@ -213,3 +225,3 @@ }

/**
* Generated by @thi.ng/wasm-api at 2022-10-03T15:32:12.339Z - DO NOT EDIT!
* Generated by @thi.ng/wasm-api at 2022-10-26T08:36:16.825Z - DO NOT EDIT!
*/

@@ -220,22 +232,66 @@

export enum EventType {
UNKNOWN,
MOUSE = 16,
KEY = 32,
}
/**
* Example struct
*/
export interface Foo extends WasmTypeBase {
color: Float32Array;
bars: Bar[];
export interface MouseEvent extends WasmTypeBase {
type: EventType;
pos: Uint16Array;
}
export const $MouseEvent: WasmTypeConstructor<MouseEvent> = (mem) => ({
get align() {
return 4;
},
get size() {
return 8;
},
instance: (base) => {
return {
get __base() {
return base;
},
get __bytes() {
return mem.u8.subarray(base, base + 8);
},
get type(): EventType {
return mem.u8[base];
},
set type(x: EventType) {
mem.u8[base] = x;
},
get pos(): Uint16Array {
const addr = (base + 4) >>> 1;
return mem.u16.subarray(addr, addr + 2);
},
};
}
});
/**
* Example struct
*/
export interface KeyEvent extends WasmTypeBase {
type: EventType;
key: WasmStringSlice;
/**
* Unique ID
* Bitmask of modifier keys
*/
id: number;
modifiers: number;
}
export const $Foo: WasmTypeConstructor<Foo> = (mem) => ({
export const $KeyEvent: WasmTypeConstructor<KeyEvent> = (mem) => ({
get align() {
return 16;
return 4;
},
get size() {
return 48;
return 16;
},
instance: (base) => {
let $key: WasmStringSlice | null = null;
return {

@@ -246,21 +302,19 @@ get __base() {

get __bytes() {
return mem.u8.subarray(base, base + 48);
return mem.u8.subarray(base, base + 16);
},
get color(): Float32Array {
const addr = base >>> 2;
return mem.f32.subarray(addr, addr + 4);
get type(): EventType {
return mem.u8[base];
},
get bars(): Bar[] {
const addr = (base + 16);
const inst = $Bar(mem);
const slice: Bar[] = [];
for(let i = 0; i < 3; i++) slice.push(inst.instance(addr + i * 24));
return slice;
set type(x: EventType) {
mem.u8[base] = x;
},
get id(): number {
return mem.u8[(base + 40)];
get key(): WasmStringSlice {
return $key || ($key = new WasmStringSlice(mem, (base + 4), true));
},
set id(x: number) {
mem.u8[(base + 40)] = x;
get modifiers(): number {
return mem.u8[(base + 12)];
},
set modifiers(x: number) {
mem.u8[(base + 12)] = x;
},
};

@@ -270,8 +324,8 @@ }

export interface Bar extends WasmTypeBase {
kind: Kind;
flags: number;
export interface Event extends WasmTypeBase {
mouse: MouseEvent;
key: KeyEvent;
}
export const $Bar: WasmTypeConstructor<Bar> = (mem) => ({
export const $Event: WasmTypeConstructor<Event> = (mem) => ({
get align() {

@@ -281,3 +335,3 @@ return 4;

get size() {
return 8;
return 16;
},

@@ -290,15 +344,15 @@ instance: (base) => {

get __bytes() {
return mem.u8.subarray(base, base + 8);
return mem.u8.subarray(base, base + 16);
},
get kind(): Kind {
return mem.u16[base >>> 1];
get mouse(): MouseEvent {
return $MouseEvent(mem).instance(base);
},
set kind(x: Kind) {
mem.u16[base >>> 1] = x;
set mouse(x: MouseEvent) {
mem.u8.set(x.__bytes, base);
},
get flags(): number {
return mem.u32[(base + 4) >>> 2];
get key(): KeyEvent {
return $KeyEvent(mem).instance(base);
},
set flags(x: number) {
mem.u32[(base + 4) >>> 2] = x;
set key(x: KeyEvent) {
mem.u8.set(x.__bytes, base);
},

@@ -308,8 +362,2 @@ };

});
export enum Kind {
UNKNOWN,
GOOD = 100,
BEST = 1000,
}
```

@@ -321,23 +369,29 @@ </details>

```zig
//! Generated by @thi.ng/wasm-api at 2022-10-03T15:32:12.341Z - DO NOT EDIT!
//! Generated by @thi.ng/wasm-api at 2022-10-26T08:36:16.827Z - DO NOT EDIT!
const std = @import("std");
pub const EventType = enum(u8) {
UNKNOWN,
MOUSE = 16,
KEY = 32,
};
/// Example struct
pub const Foo = struct {
color: @Vector(4, f32),
bars: [3]Bar,
/// Unique ID
id: u8,
pub const MouseEvent = struct {
type: EventType,
pos: @Vector(2, u16),
};
pub const Bar = struct {
kind: Kind,
flags: u32,
/// Example struct
pub const KeyEvent = struct {
type: EventType,
key: []const u8,
/// Bitmask of modifier keys
modifiers: u8,
};
pub const Kind = enum(u16) {
UNKNOWN,
GOOD = 100,
BEST = 1000,
pub const Event = union {
mouse: MouseEvent,
key: KeyEvent,
};

@@ -347,3 +401,3 @@ ```

On the TypeScript/JS side, the memory-mapped wrappers (e.g. `$Foo` and `$Bar`)
On the TypeScript/JS side, the memory-mapped wrappers (e.g. `$Event`)
can be used in combination with the `WasmBridge` to obtain fully typed views

@@ -355,3 +409,3 @@ (according to the generated types) of the underlying WASM memory. Basic usage is

import { WasmBridge } from "@thi.ng/wasm-api";
import { $Foo, Kind } from "./generated.ts";
import { $Event, EventType } from "./generated.ts";

@@ -363,19 +417,20 @@ const bridge = new WasmBridge();

// Create an instance using the bridge's memory views
// and mapping a `Foo` struct from given address
// and mapping a `Event` union from given address
// (e.g. obtained from an exported WASM function/value)
const foo = $Foo(bridge).instance(0x10000);
const event = $Event(bridge).instance(0x10000);
// then use like normal JS object
foo.color
// Float32Array(4) [0.1, 0.2, 0.3, 0.4]
event.mouse.pos
// Uint16Array(2) [100, 200]
// this even applies to arrays using other types
foo.bars[2].kind = Kind.BEST;
// IMPORTANT: any modifications like this are directly
// applied to the underlying WASM memory...
event.mouse.pos[0] = 300;
event.mouse.type === EventType.MOUSE
// true
```
**IMPORTANT:** Struct field setters are currently only supported for single
values, incl. enums, strings, structs. The latter 2 will always be copied by
**IMPORTANT:** Field setters are currently only supported for single values,
incl. enums, strings, structs, unions. The latter 2 will always be copied by
value (mem copy). Arrays or slices of strings do not currently provide write

@@ -417,5 +472,5 @@ access...

- [`/include/wasmapi.zig`](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api/include/wasmapi.zig#L6):
- [`/zig/wasmapi.zig`](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api/zig/wasmapi.zig#L64):
comments about WASM-side allocator handling in Zig
- [`/include/wasmapi.h`](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api/include/wasmapi.h#L19):
- [`/include/wasmapi.h`](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api/include/wasmapi.h#L18):
comments about WASM-side allocator handling in C/C++

@@ -513,2 +568,4 @@ - [`WasmBridge.allocate()`](https://docs.thi.ng/umbrella/wasm-api/classes/WasmBridge.html#allocate):

Bindings file / lib:
```zig

@@ -522,5 +579,7 @@ //! custom.zig - extern definitions of custom JS API

/// The bridge core API uses "wasmapi" as reserved import group name
extern "custom" fn fillRandom(addr: usize, num: usize) void;
extern "custom" fn fillRandom(addr: [*]f32, num: usize) void;
```
Main Zig file:
```zig

@@ -538,3 +597,3 @@ // Import JS core API

// populate foo with random numbers
custom.fillRandom(@ptrToInt(&foo), foo.len);
custom.fillRandom(&foo, foo.len);

@@ -593,2 +652,8 @@ // print result

Since v0.15.0, the supplied Zig core bindings lib also includes a
[`ManagedIndex`](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api/zig/managed-index.zig)
for similar dealings on the Zig side of the application. For example, in the
[@thi.ng/wasm-api-dom](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api-dom/)
module this is used to manage Zig event listeners.
## Status

@@ -627,3 +692,3 @@

Package sizes (gzipped, pre-treeshake): ESM: 6.29 KB
Package sizes (gzipped, pre-treeshake): ESM: 6.84 KB

@@ -719,3 +784,3 @@ **IMPORTANT:** The package includes code generators for various languages which

zig build-lib \
--pkg-begin wasmapi node_modules/@thi.ng/wasm-api/include/wasmapi.zig --pkg-end \
--pkg-begin wasmapi node_modules/@thi.ng/wasm-api/zig/wasmapi.zig --pkg-end \
-target wasm32-freestanding \

@@ -722,0 +787,0 @@ -O ReleaseSmall -dynamic --strip \

@@ -6,2 +6,6 @@ import type { IWasmMemoryAccess, ReadonlyWasmString } from "./api.js";

* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
*
* @remarks
* Currently only supports wasm32 target, need alt. solution for 64bit (possibly
* diff implementation) using bigint addresses (TODO)
*/

@@ -8,0 +12,0 @@ export declare class WasmStringSlice implements ReadonlyWasmString {

@@ -6,2 +6,6 @@ import { unsupported } from "@thi.ng/errors/unsupported";

* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
*
* @remarks
* Currently only supports wasm32 target, need alt. solution for 64bit (possibly
* diff implementation) using bigint addresses (TODO)
*/

@@ -8,0 +12,0 @@ export class WasmStringSlice {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc