diff --git a/globals.d.ts b/globals.d.ts
index b164955..cbbdd44 100644
--- a/globals.d.ts
+++ b/globals.d.ts
@@ -1,9 +1,150 @@
-declare class TextEncoder {
+///
+///
+// TODO: autogenerate everything below, extend from lib//api.js
+// TODO: add other libs to be used as built-in with lo.library
+// use global interface? module? import autogenerated interface from lib/@types/lib.d.ts?
+
+// generic typedef helper for classes:
+// interface IClassX { ... }
+// declare var ClassX: Constructor
+// TODO: find solution to class declaration issues (TS class declaration !== JS class declaration)
+interface Constructor {
+ readonly prototype: T;
+ new (): T;
+}
+type TextEncoderConstructor = Constructor;
+type TextDecoderConstructor = Constructor;
+
+// override types for globally available names
+declare var global: GlobalThis;
+declare var onUnhandledRejection: OnUnhandledRejection;
+declare var require: Require;
+declare var TextEncoder: TextEncoderConstructor;
+declare var TextDecoder: TextDecoderConstructor;
+declare var lo: Runtime;
+declare var console: Console;
+declare class CString extends Uint8Array {
+ ptr: number;
+ size: number;
+}
+
+interface GlobalThis extends GlobalThisBase {
+ globalThis: GlobalThis;
+ global: GlobalThis;
+ onUnhandledRejection: OnUnhandledRejection;
+ require: Require;
+ TextEncoder: TextEncoderConstructor;
+ TextDecoder: TextDecoderConstructor;
+ lo: Runtime;
+ console: Console;
+ CString: CString;
+}
+
+// keep only things that we have, no need to confuse people
+// TODO: in codegen replace with `type GlobalThisBase = typeof globalThis`
+interface GlobalThisBase
+ extends Omit,
+ // we define those manually:
+ | 'global'
+ | 'globalThis'
+ | 'lo'
+ | 'onUnhandledRejection'
+ | 'require'
+ | 'TextDecoder'
+ | 'TextEncoder'
+ | 'console'
+ > {}
+
+type OnUnhandledRejection = (error: Error) => void;
+
+type Require = >(
+ file_path: string
+) => T | undefined;
+
+interface Console {
+ log: (str: unknown) => number;
+ error: (str: unknown) => number;
+}
+
+interface ITextEncoder {
/**
* The encoding supported by the `TextEncoder` instance. Always set to `'utf-8'`.
*/
- readonly encoding: "utf-8";
- constructor(encoding?: "utf-8");
+ readonly encoding: string;
/**
* UTF-8 encodes the `input` string and returns a `Uint8Array` containing the
* encoded bytes.
@@ -23,20 +164,78 @@ declare class TextEncoder {
* @param src The text to encode.
* @param dest The array to hold the encode result.
*/
- encodeInto(src?: string, dest?: BufferSource): EncodeIntoResult;
+ encodeInto(src?: string, dest?: Uint8Array): number;
}
+interface ITextDecoder {
+ /**
+ * The encoding supported by the `TextEncoder` instance. Always set to `'utf-8'`.
+ */
+ readonly encoding: string;
+ /**
+ * UTF-8 decodes the `Uint8Array` and returns an `input` string.
+ */
+ decode(ptr_source?: typeof CString | Uint8Array): string;
+}
+
+type ZeroOrMinusOne = 0 | -1;
+type OS = 'mac' | 'win' | 'linux';
+type ARCH = 'x64' | 'arm64';
+type TypedArray =
+ | Uint8Array
+ | Int8Array
+ | Uint16Array
+ | Int16Array
+ | Uint32Array
+ | Int32Array
+ | Float32Array
+ | Float64Array
+ | BigUint64Array
+ | BigInt64Array
+ | ArrayBuffer;
+
+type Ptr = T & {
+ ptr: number;
+ size: number;
+};
+
+// TODO: find better way to type imports
+type UnknownLib = Record<
+ T | string | number | symbol,
+ unknown
+>;
+type SetLibTypeIfNameMatches<
+ T extends string | number,
+ Name,
+ LibType,
+ FallbackType
+> = Name extends T
+ ? T extends Name
+ ? Record
+ : FallbackType
+ : FallbackType;
+type Library =
+ SetLibTypeIfNameMatches>
+ & {
+ handle?: number;
+ fileName?: string;
+ internal?: boolean;
+};
+
interface RuntimeVersion {
- lo: string,
- v8: string
+ lo: string;
+ v8: string;
}
+// TODO: autogenerate
interface Core {
- O_RDONLY: number;
- open(path: string, flags: number, mode: number);
+ name: 'core',
+ // TODO: add missing declarations
+ // validate with list from: lo eval 'console.log(`"${Object.getOwnPropertyNames(lo.core).join(`":unknown;"`)}":unknown;`)'
+ open(path: string, flags: number, mode?: number): number;
dlsym(handle: number, name: string): number;
dlopen(path: string, flags: number): number;
- strnlen(str: string, size: number);
+ strnlen(str: string | number, size: number): number;
/**
* Reads a file from the given path into a Uint8Array and returns it.
* @param [path] The path to the file.
@@ -49,28 +248,134 @@ interface Core {
* @param {TypedArray}[buffer] The data write to the file.
* @returns {number} Number of bytes written
*/
- write_file(path: string, buffer: Uint8Array, flags?: number, mode?: number): number;
-}
+ write_file(
+ path: string,
+ buffer: Uint8Array,
+ flags?: number,
+ mode?: number
+ ): number;
+ os: OS;
+ arch: ARCH;
+ little_endian: boolean;
+ homedir: string;
+ defaultWriteFlags: number;
+ defaultWriteMode: number;
+ isatty(fd: number): 0 | 1;
+ mmap(
+ ptr: number,
+ length: number,
+ prot: number,
+ flags: number,
+ fd: number,
+ offset: number,
+ buf: Uint32Array
+ ): void;
+ fork(): number;
+ sysconf(num: number): number;
+ times(buf: TypedArray): number;
+ pread(num: number, buf: TypedArray, num2: number, num3: number): number;
+ waitpid(num: number, buf: TypedArray, num2: number): number;
+ execve(str: string, buf: TypedArray, buf2: TypedArray): number;
+ execvp(str: string, buf: TypedArray): number;
+ readlink(path: string, buf: TypedArray, num: number): number;
+ getcwd(ptr: number, num: number, buf: Uint32Array): void;
+ getenv(name: string, buf: Uint32Array): void;
+ setenv(name: string, value: string, overwrite?: number): ZeroOrMinusOne;
+ write_string(num: number, str: string): number;
+ fstat(fd: number, buf: TypedArray): number;
+ read(fd: number, buf: TypedArray, count: number): ZeroOrMinusOne;
+ write(fd: number, buf: TypedArray, count: number): number;
+ close(fd: number): ZeroOrMinusOne;
+ readFile(path: string, flags?: number, size?: number): Uint8Array;
+ writeFile(
+ path: string,
+ u8: Uint8Array,
+ flags?: number,
+ mode?: number
+ ): number;
-declare class CString extends Uint8Array {
- ptr: number;
- size: number;
+ isFile(path: string): boolean;
+ // conditionally defined props
+ loader?: (specifier: string, resource: string) => string;
+ sync_loader?: (specifier: string, resource: string) => string;
+ binding_loader?: (name: T) => Library;
+
+ // constants
+ S_IFBLK: number;
+ S_IFCHR: number;
+ S_IFIFO: number;
+ S_IRUSR: number;
+ S_IWUSR: number;
+ S_IRGRP: number;
+ S_IWGRP: number;
+ S_IROTH: number;
+ S_IWOTH: number;
+ O_RDONLY: number;
+ O_WRONLY: number;
+ O_CREAT: number;
+ S_IRWXU: number;
+ S_IRWXG: number;
+ S_IXOTH: number;
+ O_TRUNC: number;
+ STDIN: 0;
+ STDOUT: 1;
+ STDERR: 2;
+ O_CLOEXEC: number;
+ RUSAGE_SELF: number;
+ SEEK_SET: number;
+ SEEK_CUR: number;
+ SEEK_END: number;
+ S_IRWXO: number;
+ F_OK: number;
+ S_IFMT: number;
+ S_IFDIR: number;
+ S_IFREG: number;
+ NAME_MAX: number;
+ O_RDWR: number;
+ O_SYNC: number;
+ O_DIRECTORY: number;
+ F_SETFL: number;
+ O_NONBLOCK: number;
+ EAGAIN: number;
+ WNOHANG: number;
+ SIGTERM: number;
+ MAP_SHARED: number;
+ MAP_ANONYMOUS: number;
+ MAP_PRIVATE: number;
+ MS_ASYNC: number;
+ MS_SYNC: number;
+ MS_INVALIDATE: number;
+ _SC_CLK_TCK: number;
+ F_GETFL: number;
+ RTLD_NOW: number;
+ RTLD_LAZY: number;
+ RTLD_GLOBAL: number;
+ RTLD_LOCAL: number;
+ RTLD_NODELETE: number;
+ RTLD_NOLOAD: number;
+ RTLD_DEFAULT: number;
+ RTLD_NEXT: number;
+ PROT_READ: number;
+ PROT_WRITE: number;
+ PROT_EXEC: number;
}
+// TODO: autogenerate
interface Runtime {
- moduleCache: Map;
- libCache: Map;
- requireCache: Map;
+ // validate with list from: lo eval 'console.log(`"${Object.getOwnPropertyNames(lo).join(`":unknown;"`)}":unknown;`)'
+ moduleCache: Map>;
+ libCache: Map;
+ requireCache: Map;
start: number;
errno: number;
- colors: any;
+ colors: Record, string>;
core: Core;
- libraries(): Array;
- builtins(): Array;
+ libraries(): string[];
+ builtins(): string[];
assert(expression: any, message?: string | Function): any;
cstr(str: string): CString;
load(name: string): any;
- library(name: string): any;
+ library(name: T): Library;
/**
* Prints a string to the console
* @param [str='a string'] The text to print.
@@ -79,37 +384,97 @@ interface Runtime {
exit(status: number): void;
runMicroTasks(): void;
hrtime(): number;
- nextTick(callback: function): void;
+ nextTick(callback: Function): void;
getAddress(buf: TypedArray): number;
utf8Length(str: string): number;
utf8EncodeInto(str: string, buf: TypedArray): number;
utf8EncodeIntoAtOffset(str: string, buf: TypedArray, off: number): number;
utf8_decode(address: number, len?: number): string;
latin1Decode(address: number, len?: number): string;
- utf8Encode(str: sring): TypedArray;
- wrap(handle: TypedArray, fn: Function, plen: number): function;
+ utf8Encode(str: string): Uint8Array;
+ utf8Decode: Runtime['utf8_decode'];
+ wrap<
+ Handle extends TypedArray,
+ WrappedFnArgs extends unknown[],
+ >(
+ handle: Handle,
+ fn: (...args: [...WrappedFnArgs, Handle]) => unknown,
+ plen: number
+ ): (...args: WrappedFnArgs) => number;
addr(handle: TypedArray): number;
version: RuntimeVersion;
- args: Array;
+ args: string[];
+ argv: number;
+ argc: number;
workerSource: string;
builtin(path: string): string;
- os(): string;
- arch(): string;
- getenv(string): string;
- async evaluateModule(identifier: string): Promise