diff --git a/dapp/.gitignore b/dapp/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/dapp/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/dapp/node_modules/@parcel/watcher-wasm/README.md b/dapp/node_modules/@parcel/watcher-wasm/README.md deleted file mode 100644 index 5c34150..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/README.md +++ /dev/null @@ -1,135 +0,0 @@ -# @parcel/watcher - -A native C++ Node module for querying and subscribing to filesystem events. Used by [Parcel 2](https://github.com/parcel-bundler/parcel). - -## Features - -- **Watch** - subscribe to realtime recursive directory change notifications when files or directories are created, updated, or deleted. -- **Query** - performantly query for historical change events in a directory, even when your program is not running. -- **Native** - implemented in C++ for performance and low-level integration with the operating system. -- **Cross platform** - includes backends for macOS, Linux, Windows, FreeBSD, and Watchman. -- **Performant** - events are throttled in C++ so the JavaScript thread is not overwhelmed during large filesystem changes (e.g. `git checkout` or `npm install`). -- **Scalable** - tens of thousands of files can be watched or queried at once with good performance. - -## Example - -```javascript -const watcher = require('@parcel/watcher'); -const path = require('path'); - -// Subscribe to events -let subscription = await watcher.subscribe(process.cwd(), (err, events) => { - console.log(events); -}); - -// later on... -await subscription.unsubscribe(); - -// Get events since some saved snapshot in the past -let snapshotPath = path.join(process.cwd(), 'snapshot.txt'); -let events = await watcher.getEventsSince(process.cwd(), snapshotPath); - -// Save a snapshot for later -await watcher.writeSnapshot(process.cwd(), snapshotPath); -``` - -## Watching - -`@parcel/watcher` supports subscribing to realtime notifications of changes in a directory. It works recursively, so changes in sub-directories will also be emitted. - -Events are throttled and coalesced for performance during large changes like `git checkout` or `npm install`, and a single notification will be emitted with all of the events at the end. - -Only one notification will be emitted per file. For example, if a file was both created and updated since the last event, you'll get only a `create` event. If a file is both created and deleted, you will not be notifed of that file. Renames cause two events: a `delete` for the old name, and a `create` for the new name. - -```javascript -let subscription = await watcher.subscribe(process.cwd(), (err, events) => { - console.log(events); -}); -``` - -Events have two properties: - -- `type` - the event type: `create`, `update`, or `delete`. -- `path` - the absolute path to the file or directory. - -To unsubscribe from change notifications, call the `unsubscribe` method on the returned subscription object. - -```javascript -await subscription.unsubscribe(); -``` - -`@parcel/watcher` has the following watcher backends, listed in priority order: - -- [FSEvents](https://developer.apple.com/documentation/coreservices/file_system_events) on macOS -- [Watchman](https://facebook.github.io/watchman/) if installed -- [inotify](http://man7.org/linux/man-pages/man7/inotify.7.html) on Linux -- [ReadDirectoryChangesW](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v%3Dvs.85%29.aspx) on Windows -- [kqueue](https://man.freebsd.org/cgi/man.cgi?kqueue) on FreeBSD, or as an alternative to FSEvents on macOS - -You can specify the exact backend you wish to use by passing the `backend` option. If that backend is not available on the current platform, the default backend will be used instead. See below for the list of backend names that can be passed to the options. - -## Querying - -`@parcel/watcher` also supports querying for historical changes made in a directory, even when your program is not running. This makes it easy to invalidate a cache and re-build only the files that have changed, for example. It can be **significantly** faster than traversing the entire filesystem to determine what files changed, depending on the platform. - -In order to query for historical changes, you first need a previous snapshot to compare to. This can be saved to a file with the `writeSnapshot` function, e.g. just before your program exits. - -```javascript -await watcher.writeSnapshot(dirPath, snapshotPath); -``` - -When your program starts up, you can query for changes that have occurred since that snapshot using the `getEventsSince` function. - -```javascript -let events = await watcher.getEventsSince(dirPath, snapshotPath); -``` - -The events returned are exactly the same as the events that would be passed to the `subscribe` callback (see above). - -`@parcel/watcher` has the following watcher backends, listed in priority order: - -- [FSEvents](https://developer.apple.com/documentation/coreservices/file_system_events) on macOS -- [Watchman](https://facebook.github.io/watchman/) if installed -- [fts](http://man7.org/linux/man-pages/man3/fts.3.html) (brute force) on Linux and FreeBSD -- [FindFirstFile](https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-findfirstfilea) (brute force) on Windows - -The FSEvents (macOS) and Watchman backends are significantly more performant than the brute force backends used by default on Linux and Windows, for example returning results in miliseconds instead of seconds for large directory trees. This is because a background daemon monitoring filesystem changes on those platforms allows us to query cached data rather than traversing the filesystem manually (brute force). - -macOS has good performance with FSEvents by default. For the best performance on other platforms, install [Watchman](https://facebook.github.io/watchman/) and it will be used by `@parcel/watcher` automatically. - -You can specify the exact backend you wish to use by passing the `backend` option. If that backend is not available on the current platform, the default backend will be used instead. See below for the list of backend names that can be passed to the options. - -## Options - -All of the APIs in `@parcel/watcher` support the following options, which are passed as an object as the last function argument. - -- `ignore` - an array of paths or glob patterns to ignore. uses [`is-glob`](https://github.com/micromatch/is-glob) to distinguish paths from globs. glob patterns are parsed with [`micromatch`](https://github.com/micromatch/micromatch) (see [features](https://github.com/micromatch/micromatch#matching-features)). - - paths can be relative or absolute and can either be files or directories. No events will be emitted about these files or directories or their children. - - glob patterns match on relative paths from the root that is watched. No events will be emitted for matching paths. -- `backend` - the name of an explicitly chosen backend to use. Allowed options are `"fs-events"`, `"watchman"`, `"inotify"`, `"kqueue"`, `"windows"`, or `"brute-force"` (only for querying). If the specified backend is not available on the current platform, the default backend will be used instead. - -## WASM - -The `@parcel/watcher-wasm` package can be used in place of `@parcel/watcher` on unsupported platforms. It relies on the Node `fs` module, so in non-Node environments such as browsers, an `fs` polyfill will be needed. The `@parcel/watcher-wasm` package is published as an ESM-only module. - -**Note**: the WASM implementation is significantly less efficient than the native implementations because it must crawl the file system to watch each directory individually. Use the native `@parcel/watcher` package wherever possible. - -```js -import {subscribe} from '@parcel/watcher-wasm'; - -// Use the module as documented above. -subscribe(/* ... */); -``` - -## Who is using this? - -- [Parcel 2](https://parceljs.org/) -- [VSCode](https://code.visualstudio.com/updates/v1_62#_file-watching-changes) -- [Tailwind CSS Intellisense](https://github.com/tailwindlabs/tailwindcss-intellisense) -- [Gatsby Cloud](https://twitter.com/chatsidhartha/status/1435647412828196867) -- [Nx](https://nx.dev) -- [Nuxt](https://nuxt.com) - -## License - -MIT diff --git a/dapp/node_modules/@parcel/watcher-wasm/index.d.ts b/dapp/node_modules/@parcel/watcher-wasm/index.d.ts deleted file mode 100644 index 8f70382..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/index.d.ts +++ /dev/null @@ -1,51 +0,0 @@ -declare type FilePath = string; -declare type GlobPattern = string; - -declare namespace ParcelWatcher { - export type BackendType = - | 'fs-events' - | 'watchman' - | 'inotify' - | 'windows' - | 'brute-force'; - export type EventType = 'create' | 'update' | 'delete'; - export interface Options { - ignore?: (FilePath|GlobPattern)[]; - backend?: BackendType; - } - export type SubscribeCallback = ( - err: Error | null, - events: Event[] - ) => unknown; - export interface AsyncSubscription { - unsubscribe(): Promise; - } - export interface Event { - path: FilePath; - type: EventType; - } - export function getEventsSince( - dir: FilePath, - snapshot: FilePath, - opts?: Options - ): Promise; - export function subscribe( - dir: FilePath, - fn: SubscribeCallback, - opts?: Options - ): Promise; - export function unsubscribe( - dir: FilePath, - fn: SubscribeCallback, - opts?: Options - ): Promise; - export function writeSnapshot( - dir: FilePath, - snapshot: FilePath, - opts?: Options - ): Promise; -} - -export = ParcelWatcher; -/** Initializes the web assembly module. */ -export default function init(input?: string | URL | Request): Promise; diff --git a/dapp/node_modules/@parcel/watcher-wasm/index.mjs b/dapp/node_modules/@parcel/watcher-wasm/index.mjs deleted file mode 100644 index e4fd052..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/index.mjs +++ /dev/null @@ -1,326 +0,0 @@ -import { Environment, napi } from 'napi-wasm'; -import fs from 'fs'; -import Path from 'path'; -import { createWrapper } from './wrapper.js'; - -let env; -let encoder = new TextEncoder; - -let constants = { - O_ACCMODE: 0o00000003, - O_RDONLY: 0, - O_WRONLY: 0o00000001, - O_RDWR: 0o00000002, - O_CREAT: 0o00000100, - O_EXCL: 0o00000200, - O_NOCTTY: 0o00000400, - O_TRUNC: 0o00001000, - O_APPEND: 0o00002000, - O_NONBLOCK: 0o00004000, - O_SYNC: 0o00010000, - FASYNC: 0o00020000, - O_DIRECT: 0o00040000, - O_LARGEFILE: 0o00100000, - O_DIRECTORY: 0o00200000, - O_NOFOLLOW: 0o00400000, - O_NOATIME: 0o01000000, - O_CLOEXEC: 0o02000000 -}; - -napi.napi_get_last_error_info = () => {}; - -const fds = new Map(); -const dirs = new Map(); -const regexCache = new Map(); -const watches = [null]; - -const wasm_env = { - __syscall_newfstatat(dirfd, path, buf, flags) { - let dir = dirfd === -100 ? process.cwd() : fds.get(dirfd).path; - let p = Path.resolve(dir, env.getString(path)); - let nofollow = flags & 256; - try { - let stat = nofollow ? fs.lstatSync(p, {bigint: true}) : fs.statSync(p, {bigint: true}); - return writeStat(stat, buf); - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - }, - __syscall_lstat64(path, buf) { - let p = env.getString(path); - try { - let stat = fs.lstatSync(p, {bigint: true}); - return writeStat(stat, buf); - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - }, - __syscall_fstat64(fd, buf) { - try { - let stat = fs.fstatSync(fd, {bigint: true}); - return writeStat(stat, buf); - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - }, - __syscall_stat64(path, buf) { - let p = env.getString(path); - try { - let stat = fs.statSync(p, {bigint: true}); - return writeStat(stat, buf); - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - }, - __syscall_getdents64(fd, dirp, count) { - let p = fds.get(fd).path; - let dir = dirs.get(fd); - let entries = dir?.entries; - if (!entries) { - try { - entries = fs.readdirSync(p, {withFileTypes: true}); - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - } - - let start = dirp; - let i = dir?.index || 0; - for (; i < entries.length; i++) { - let entry = entries[i]; - let type = entry.isFIFO() ? 1 - : entry.isCharacterDevice() ? 2 - : entry.isDirectory() ? 4 - : entry.isBlockDevice() ? 6 - : entry.isFile() ? 8 - : entry.isSymbolicLink() ? 10 - : entry.isSocket() ? 12 - : 0; - let len = align(utf8Length(entry.name) + 20, 8); - if ((dirp - start + len) > count) { - break; - } - - // Write a linux_dirent64 struct into wasm memory. - env.u64[dirp >> 3] = 1n; // ino - env.u64[(dirp + 8) >> 3] = BigInt((dirp - start) + len); // offset - env.u16[(dirp + 16) >> 1] = len; - env.memory[dirp + 18] = type; - let {written} = encoder.encodeInto(entry.name, env.memory.subarray(dirp + 19)); - env.memory[dirp + 19 + written] = 0; // null terminate - dirp += len; - } - - dirs.set(fd, {index: i, entries}); - return dirp - start; - }, - __syscall_openat(dirfd, path, flags, mode) { - // Convert flags to Node values. - let f = 0; - for (let c in constants) { - if (flags & constants[c]) { - f |= fs.constants[c] || 0; - } - } - let dir = dirfd === -100 ? process.cwd() : fds.get(dirfd)?.path; - if (!dir) { - env.i32[env.instance.exports.__errno_location >> 2] = 9970; // ENOTDIR - return -1; - } - let p = Path.resolve(dir, env.getString(path)); - try { - let fd = fs.openSync(p, f); - fds.set(fd, {path: p, flags}); - return fd; - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - }, - __syscall_fcntl64(fd, cmd) { - switch (cmd) { - case 3: - return fds.get(fd).flags; - case 2: - return 0; - default: - throw new Error('Unknown fcntl64 call: ' + cmd); - } - }, - __syscall_ioctl() {}, - emscripten_resize_heap() { - return 0; - }, - abort() {}, - wasm_backend_add_watch(filename, backend) { - let path = env.getString(filename); - let watch = fs.watch(path, {encoding: 'buffer'}, (eventType, filename) => { - if (filename) { - let type = eventType === 'change' ? 1 : 2; - let fptr = env.instance.exports.malloc(filename.byteLength + 1); - env.memory.set(filename, fptr); - env.memory[fptr + filename.byteLength] = 0; - env.instance.exports.wasm_backend_event_handler(backend, wd, type, fptr); - env.instance.exports.free(fptr); - } - }); - - let wd = watches.length; - watches.push(watch); - return wd; - }, - wasm_backend_remove_watch(wd) { - watches[wd].close(); - watches[wd] = undefined; - }, - set_timeout(ms, ctx) { - return setTimeout(() => { - env.instance.exports.on_timeout(ctx); - }, ms); - }, - clear_timeout(t) { - clearTimeout(t); - }, - emscripten_date_now() { - return Date.now(); - }, - _emscripten_get_now_is_monotonic() { - return true; - }, - emscripten_get_now() { - return performance.now(); - }, - wasm_regex_match(string, regex) { - let re = regexCache.get(regex); - if (!re) { - re = new RegExp(env.getString(regex)); - regexCache.set(regex, re); - } - return re.test(env.getString(string)) ? 1 : 0; - } -}; - -const wasi = { - fd_close(fd) { - fs.closeSync(fd); - fds.delete(fd); - dirs.delete(fd); - return 0; - }, - fd_seek(fd, offset_low, offset_high, whence, newOffset) { - return 0; - }, - fd_write(fd, iov, iovcnt, pnum) { - let buffers = []; - for (let i = 0; i < iovcnt; i++) { - let ptr = env.u32[iov >> 2]; - let len = env.u32[(iov + 4) >> 2]; - iov += 8; - if (len > 0) { - buffers.push(env.memory.subarray(ptr, ptr + len)); - } - } - let wrote = fs.writevSync(fd, buffers); - env.u32[pnum >> 2] = wrote; - return 0; - }, - fd_read(fd, iov, iovcnt, pnum) { - let buffers = []; - for (let i = 0; i < iovcnt; i++) { - let ptr = env.u32[iov >> 2]; - let len = env.u32[(iov + 4) >> 2]; - iov += 8; - if (len > 0) { - buffers.push(env.memory.subarray(ptr, ptr + len)); - } - } - - let read = fs.readvSync(fd, buffers); - env.u32[pnum >> 2] = read; - return 0; - } -}; - -function writeStat(stat, buf) { - env.i32[buf >> 2] = Number(stat.dev); - env.i32[(buf + 4) >> 2] = Number(stat.mode); - env.u32[(buf + 8) >> 2] = Number(stat.nlink); - env.i32[(buf + 12) >> 2] = Number(stat.uid); - env.i32[(buf + 16) >> 2] = Number(stat.gid); - env.i32[(buf + 20) >> 2] = Number(stat.rdev); - env.u64[(buf + 24) >> 3] = stat.size; - env.i32[(buf + 32) >> 2] = Number(stat.blksize); - env.i32[(buf + 36) >> 2] = Number(stat.blocks); - env.u64[(buf + 40) >> 3] = stat.atimeMs; - env.u32[(buf + 48) >> 2] = Number(stat.atimeNs); - env.u64[(buf + 56) >> 3] = stat.mtimeMs; - env.u32[(buf + 64) >> 2] = Number(stat.mtimeNs); - env.u64[(buf + 72) >> 3] = stat.ctimeMs; - env.u32[(buf + 80) >> 2] = Number(stat.ctimeNs); - env.u64[(buf + 88) >> 3] = stat.ino; - return 0; -} - -function utf8Length(string) { - let len = 0; - for (let i = 0; i < string.length; i++) { - let c = string.charCodeAt(i); - - if (c >= 0xd800 && c <= 0xdbff && i < string.length - 1) { - let c2 = string.charCodeAt(++i); - if ((c2 & 0xfc00) === 0xdc00) { - c = ((c & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000; - } else { - // unmatched surrogate. - i--; - } - } - - if ((c & 0xffffff80) === 0) { - len++; - } else if ((c & 0xfffff800) === 0) { - len += 2; - } else if ((c & 0xffff0000) === 0) { - len += 3; - } else if ((c & 0xffe00000) === 0) { - len += 4; - } - } - return len; -} - -function align(len, p) { - return Math.ceil(len / p) * p; -} - -let wasmBytes = fs.readFileSync(new URL('watcher.wasm', import.meta.url)); -let wasmModule = new WebAssembly.Module(wasmBytes); -let instance = new WebAssembly.Instance(wasmModule, { - napi, - env: wasm_env, - wasi_snapshot_preview1: wasi -}); - -env = new Environment(instance); -let wrapper = createWrapper(env.exports); - -export function writeSnapshot(dir, snapshot, opts) { - return wrapper.writeSnapshot(dir, snapshot, opts); -} - -export function getEventsSince(dir, snapshot, opts) { - return wrapper.getEventsSince(dir, snapshot, opts); -} - -export function subscribe(dir, fn, opts) { - return wrapper.subscribe(dir, fn, opts); -} - -export function unsubscribe(dir, fn, opts) { - return wrapper.unsubscribe(dir, fn, opts); -} diff --git a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/README.md b/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/README.md deleted file mode 100644 index ca23160..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/README.md +++ /dev/null @@ -1,100 +0,0 @@ -# napi-wasm - -An implementation of the [napi](https://nodejs.org/api/n-api.html) API for WASM. Enables using some native Node modules in browsers and other environments. - -## Setup - -To use napi-wasm, there are a few requirements: - -1. Configure your linker to export an indirect function table. With ldd, this is the `--export-table` flag. This enables JavaScript to call callback functions registered by WASM. It is exposed in the WebAssembly exports as `__indirect_function_table`. -2. Export a function from your WASM build named `napi_register_module_v1` (Node's default), or `napi_register_wasm_v1` for WASM-specific builds. This is called during initialization to setup the `exports` object for your module. It receives an environment and an exports object pointer as arguments, which you can add properties to. -3. Include a function named `napi_wasm_malloc` in your WASM build. This is called from JavaScript by napi-wasm to allocate memory in the WASM heap. It should accept a `uint32` size argument indicating the number of bytes to allocate, and return a `uint8` pointer to allocated memory. -4. Compile for the `wasm32-unknown-unknown` target. - -### In Rust - -The above steps should apply for any programming language, but here's an example in Rust. First, define a `napi_wasm_malloc` function so JavaScript can allocate memory in the WASM heap using the default allocator. - -```rust -use std::alloc::{alloc, Layout}; - -#[no_mangle] -pub extern "C" fn napi_wasm_malloc(size: usize) -> *mut u8 { - let align = std::mem::align_of::(); - if let Ok(layout) = Layout::from_size_align(size, align) { - unsafe { - if layout.size() > 0 { - let ptr = alloc(layout); - if !ptr.is_null() { - return ptr; - } - } else { - return align as *mut u8; - } - } - } - - std::process::abort(); -} -``` - -Next, implement `napi_register_wasm_v1` to register your module exports. We'll use the [napi-rs](https://github.com/napi-rs/napi-rs) bindings in this example to make it a bit nicer than calling C APIs directly. Note that the napi-rs `#[module_exports]` macro currently doesn't work in WASM because Rust doesn't support ctor setup functions in WASM targets yet, so we'll need to do this manually. - -```rust -use napi::{Env, JsObject, NapiValue}; - -#[no_mangle] -pub unsafe extern "C" fn napi_register_wasm_v1(raw_env: napi::sys::napi_env, raw_exports: napi::sys::napi_value) { - let env = Env::from_raw(raw_env); - let exports = JsObject::from_raw_unchecked(raw_env, raw_exports); - - exports.create_named_method("transform", transform); -} - -#[js_function(1)] -fn transform(ctx: CallContext) -> napi::Result { - // ... -} -``` - -To compile, you need to export a function table and use the correct target. - -```shell - RUSTFLAGS="-C link-arg=--export-table" cargo build --target wasm32-unknown-unknown -``` - -This will output a file in `target/wasm32-unknown-unknown/debug/YOUR_CRATE.wasm` which you can load in a JavaScript environment. - -You can also put the rust flags in a `.cargo/config.toml` file so you don't need to provide the environment variable each time you run `cargo build`. - -```toml -[target.wasm32-unknown-unknown] -rustflags = ["-C", "link-arg=--export-table"] -``` - -### Loading - -To load a WASM file and initialize a napi environment, you'll need to import the `napi-wasm` package. You instantiate a WASM module as usual, providing `napi` as the `env` import key. This provides the napi functions for your WASM module to use. - -Then, pass the WASM instance to the `Environment` constructor to setup a napi environment. This will call `napi_register_wasm_v1` or `napi_register_module_v1` to setup the exports object. Then you can call functions on the exports object as you would in Node. - -```js -import { Environment, napi } from 'napi-wasm'; - -// Construct a URL and instantiate a WebAssembly module as usual. -const url = new URL('path/to/lib.wasm', import.meta.url); -const { instance } = await WebAssembly.instantiateStreaming(fetch(url), { - env: napi -}); - -// Create an environment. -let env = new Environment(instance); -let exports = env.exports; - -// Use exports as usual! -exports.transform({ - // ... -}); -``` - -When you are done with an `Environment`, call the `destroy()` function to clean up memory. diff --git a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.js b/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.js deleted file mode 100644 index 6f6e6d9..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.js +++ /dev/null @@ -1,1374 +0,0 @@ -const NAPI_OK = 0; -const NAPI_GENERIC_FAILURE = 9; -const NAPI_PENDING_EXCEPTION = 10; -const NAPI_CANCELED = 11; -const NAPI_HANDLE_SCOPE_MISMATCH = 13; -const NAPI_NO_EXTERNAL_BUFFERS_ALLOWED = 22; - -// https://nodejs.org/api/n-api.html#napi_property_attributes -const NAPI_WRITABLE = 1 << 0; -const NAPI_ENUMERABLE = 1 << 1; -const NAPI_CONFIGURABLE = 1 << 2; -const NAPI_STATIC = 1 << 10; - -// https://nodejs.org/api/n-api.html#napi_typedarray_type -const typedArrays = [ - Int8Array, - Uint8Array, - Uint8ClampedArray, - Int16Array, - Uint16Array, - Int32Array, - Uint32Array, - Float32Array, - Float64Array, - BigInt64Array, - BigUint64Array -]; - -const environments = []; - -class Environment { - scopes = []; - referenceId = 1; - references = new Map(); - deferred = [null]; - wrappedObjects = new WeakMap(); - externalObjects = new WeakMap(); - buffers = new Map(); - instanceData = 0; - pendingException = null; - - constructor(instance) { - this.id = environments.length; - environments.push(this); - - this.instance = instance; - this.table = instance.exports.__indirect_function_table; - this.exports = {}; - - this.pushScope(); - let values = this.scopes[this.scopes.length - 1]; - let exports = values.length; - values.push(this.exports); - - try { - if (this.instance.exports.napi_register_module_v1) { - this.instance.exports.napi_register_module_v1(this.id, exports); - } - - if (this.instance.exports.napi_register_wasm_v1) { - this.instance.exports.napi_register_wasm_v1(this.id, exports); - } - } finally { - this.popScope(); - if (this.pendingException) { - let e = this.pendingException; - this.pendingException = null; - throw e; - } - } - } - - destroy() { - environments[this.id] = undefined; - } - - getString(ptr, len = strlen(this.memory, ptr)) { - return decoder.decode(this.memory.subarray(ptr, Math.max(0, ptr + len))); - } - - pushScope() { - let id = this.scopes.length; - this.scopes.push(id ? [...this.scopes[id - 1]] : [undefined, null, globalThis, true, false]); - return id; - } - - popScope() { - this.scopes.pop(); - - // Update any buffers with values which might have been modified in WASM copy. - for (let [buffer, slice] of this.buffers) { - // Ignore if buffer or slice has been detached. - if (buffer.byteLength && slice.byteLength) { - buffer.set(slice); - } - } - - this.buffers.clear(); - } - - get(idx) { - return this.scopes[this.scopes.length - 1][idx]; - } - - set(idx, value) { - this.scopes[this.scopes.length - 1][idx] = value; - } - - pushValue(value, scope = this.scopes.length - 1) { - let values = this.scopes[scope]; - let id = values.length; - values.push(value); - return id; - } - - createValue(value, result, scope) { - if (typeof value === 'boolean') { - this.setPointer(result, value ? 3 : 4); - return NAPI_OK; - } else if (typeof value === 'undefined') { - this.setPointer(result, 0); - return NAPI_OK; - } else if (value === null) { - this.setPointer(result, 1); - return NAPI_OK; - } else if (value === globalThis) { - this.setPointer(result, 2); - return NAPI_OK; - } - - let id = this.pushValue(value, scope); - this.setPointer(result, id); - return NAPI_OK; - } - - setPointer(ptr, value) { - this.u32[ptr >> 2] = value; - return NAPI_OK; - } - - _u32 = new Uint32Array(); - get u32() { - if (this._u32.byteLength === 0) { - this._u32 = new Uint32Array(this.instance.exports.memory.buffer); - } - - return this._u32; - } - - _i32 = new Int32Array(); - get i32() { - if (this._i32.byteLength === 0) { - this._i32 = new Int32Array(this.instance.exports.memory.buffer); - } - - return this._i32; - } - - _u16 = new Uint16Array(); - get u16() { - if (this._u16.byteLength === 0) { - this._u16 = new Uint16Array(this.instance.exports.memory.buffer); - } - - return this._u16; - } - - _u64 = new BigUint64Array(); - get u64() { - if (this._u64.byteLength === 0) { - this._u64 = new BigUint64Array(this.instance.exports.memory.buffer); - } - - return this._u64; - } - - _i64 = new BigInt64Array(); - get i64() { - if (this._i64.byteLength === 0) { - this._i64 = new BigInt64Array(this.instance.exports.memory.buffer); - } - - return this._i64; - } - - _f64 = new Float64Array(); - get f64() { - if (this._f64.byteLength === 0) { - this._f64 = new Float64Array(this.instance.exports.memory.buffer); - } - - return this._f64; - } - - _buf = new Uint8Array(); - get memory() { - if (this._buf.byteLength === 0) { - this._buf = new Uint8Array(this.instance.exports.memory.buffer); - } - - return this._buf; - } - - getBufferInfo(buf, ptr) { - if (this.buffers.has(buf)) { - let b = this.buffers.get(buf); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - if (buf instanceof ArrayBuffer) { - let b = this.copyBuffer(new Uint8Array(buf)); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - // If this is a view into WASM memory, no copies needed. - if (buf.buffer === this.instance.exports.memory.buffer) { - this.setPointer(ptr, buf.byteOffset); - return buf.byteLength; - } - - let b = this.copyBuffer(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - copyBuffer(data) { - let ptr = this.instance.exports.napi_wasm_malloc(data.byteLength); - let mem = this.memory; - mem.set(data, ptr); - let buf = mem.subarray(ptr, ptr + data.byteLength); - this.buffers.set(data, buf); - return buf; - } - - createFunction(cb, data) { - let env = this; - let fn = env.table.get(cb); - let func = function (...args) { - let scope = env.pushScope(); - - try { - let values = env.scopes[scope]; - let info = values.length; - values.push({ - thisArg: this, - args, - data, - newTarget: new.target - }); - - let res = fn(env.id, info); - return env.get(res); - } finally { - env.popScope(); - if (env.pendingException) { - let e = env.pendingException; - env.pendingException = null; - throw e; - } - } - }; - - return func; - } - - readPropertyDescriptor(ptr) { - // https://nodejs.org/api/n-api.html#napi_property_descriptor - let buf = this.u32; - let utf8name = buf[ptr++]; - let nameValue = buf[ptr++]; - let method = buf[ptr++]; - let getter = buf[ptr++]; - let setter = buf[ptr++]; - let val = buf[ptr++]; - let attrs = buf[ptr++]; - let data = buf[ptr++]; - - let name = utf8name ? this.getString(utf8name) : this.get(nameValue); - let writable = Boolean(attrs & NAPI_WRITABLE); - let enumerable = Boolean(attrs & NAPI_ENUMERABLE); - let configurable = Boolean(attrs & NAPI_CONFIGURABLE); - let isStatic = Boolean(attrs & NAPI_STATIC); - let get = getter ? this.createFunction(getter, data) : undefined; - let set = setter ? this.createFunction(setter, data) : undefined; - let value = method ? this.createFunction(method, data) : val ? this.get(val) : undefined; - - let descriptor = { - name, - static: isStatic, - configurable, - enumerable - }; - if (get || set) { - descriptor.get = get; - descriptor.set = set; - } else if (value) { - descriptor.writable = writable; - descriptor.value = value; - } - - return descriptor; - } -} - -const decoder = new TextDecoder("utf-8", { ignoreBOM: true, fatal: true }); -const latin1Decoder = new TextDecoder('latin1'); -const utf16Decoder = new TextDecoder('utf-16'); -const encoder = new TextEncoder(); - -class FinalizeRecord { - constructor(env, finalize, hint, data) { - this.env = env; - this.finalize = finalize; - this.hint = hint; - this.data = data; - } -} - -const finalizationRegistry = new FinalizationRegistry(buffer => { - if (buffer.finalize) { - buffer.finalize(buffer.env, buffer.data, buffer.hint); - } -}); - -class ExternalValue {} - -const threadsafeFunctions = []; - -class ThreadSafeFunction { - constructor(env, fn, nativeFn, context) { - this.env = env; - this.fn = fn; - this.nativeFn = nativeFn; - this.context = context; - this.id = threadsafeFunctions.length; - threadsafeFunctions.push(this); - } -} - -const asyncWork = [null]; - -class AsyncWork { - constructor(env, execute, complete, data) { - this.env = env; - this.execute = execute; - this.complete = complete; - this.data = data; - this.id = asyncWork.length; - asyncWork.push(this); - } -} - -const napi = { - napi_open_handle_scope(env_id, result) { - let env = environments[env_id]; - let id = env.pushScope(); - return env.setPointer(result, id); - }, - napi_close_handle_scope(env_id, scope) { - let env = environments[env_id]; - if (scope !== env.scopes.length - 1) { - return NAPI_HANDLE_SCOPE_MISMATCH; - } - env.popScope(); - return NAPI_OK; - }, - napi_open_escapable_handle_scope(env_id, result) { - let env = environments[env_id]; - let id = env.pushScope(); - return env.setPointer(result, id); - }, - napi_close_escapable_handle_scope(env_id, scope) { - let env = environments[env_id]; - if (scope !== env.scopes.length - 1) { - return NAPI_HANDLE_SCOPE_MISMATCH; - } - env.popScope(); - return NAPI_OK; - }, - napi_escape_handle(env_id, scope_id, escapee, result) { - let env = environments[env_id]; - let value = env.get(escapee); - // Create a value in the outer scope. - return env.createValue(value, result, scope_id - 1); - }, - napi_create_object(env_id, result) { - let env = environments[env_id]; - return env.createValue({}, result); - }, - napi_set_property(env_id, object, key, value) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - let val = env.get(value); - obj[name] = val; - return NAPI_OK; - }, - napi_get_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - return env.createValue(obj[name], result); - }, - napi_delete_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - let res = false; - try { - res = delete obj[name]; - } catch (err) {} - if (result) { - env.memory[result] = res ? 1 : 0; - } - return NAPI_OK; - }, - napi_has_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - // return env.setPointer(result, name in obj ? 1 : 0); - env.memory[result] = name in obj ? 1 : 0; - return NAPI_OK; - }, - napi_has_own_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - env.memory[result] = obj.hasOwnProperty(name) ? 1 : 0; - return NAPI_OK; - }, - napi_set_named_property(env_id, object, utf8Name, value) { - let env = environments[env_id]; - let obj = env.get(object); - let val = env.get(value); - let name = env.getString(utf8Name); - obj[name] = val; - return NAPI_OK; - }, - napi_get_named_property(env_id, object, utf8Name, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.getString(utf8Name); - return env.createValue(obj[name], result); - }, - napi_has_named_property(env_id, object, utf8Name, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.getString(utf8Name); - env.memory[result] = name in obj ? 1 : 0; - return NAPI_OK; - }, - napi_get_property_names(env_id, object, result) { - let env = environments[env_id]; - let obj = env.get(object); - let properties = Object.keys(obj); - return env.createValue(properties, result); - }, - napi_get_all_property_names(env_id, object, key_mode, key_filter, key_conversion, result) { - throw new Error('not implemented'); - }, - napi_define_properties(env_id, object, property_count, properties) { - let env = environments[env_id]; - let obj = env.get(object); - let ptr = properties >> 2; - for (let i = 0; i < property_count; i++) { - let descriptor = env.readPropertyDescriptor(ptr); - Object.defineProperty(obj, descriptor.name, descriptor); - ptr += 8; - } - return NAPI_OK; - }, - napi_object_freeze(env_id, object) { - let env = environments[env_id]; - let obj = env.get(object); - Object.freeze(obj); - return NAPI_OK; - }, - napi_object_seal(env_id, object) { - let env = environments[env_id]; - let obj = env.get(object); - Object.seal(obj); - return NAPI_OK; - }, - napi_get_prototype(env_id, object, result) { - let env = environments[env_id]; - let obj = env.get(object); - return env.createValue(Object.getPrototypeOf(obj), result); - }, - napi_define_class(env_id, utf8name, length, constructor, data, property_count, properties, result) { - let env = environments[env_id]; - let func = env.createFunction(constructor, data); - - Object.defineProperty(func, 'name', { - value: env.getString(utf8name, length), - configurable: true - }); - - let ptr = properties >> 2; - for (let i = 0; i < property_count; i++) { - let descriptor = env.readPropertyDescriptor(ptr); - if (descriptor.static) { - Object.defineProperty(func, descriptor.name, descriptor); - } else { - Object.defineProperty(func.prototype, descriptor.name, descriptor); - } - ptr += 8; - } - - return env.createValue(func, result); - }, - napi_create_reference(env_id, value, refcount, result) { - let env = environments[env_id]; - let id = env.referenceId++; - env.references.set(id, { - value: env.get(value), - refcount - }); - return env.setPointer(result, id); - }, - napi_delete_reference(env_id, ref) { - let env = environments[env_id]; - env.references.delete(ref); - return NAPI_OK; - }, - napi_get_reference_value(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - return env.createValue(reference.value, result); - }, - napi_reference_ref(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - reference.refcount++; - return env.setPointer(result, reference.refcount); - }, - napi_reference_unref(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - if (reference.refcount === 0) { - return NAPI_GENERIC_FAILURE; - } - reference.refcount--; - return env.setPointer(result, reference.refcount); - }, - napi_add_env_cleanup_hook() { - return NAPI_OK; - }, - napi_remove_env_cleanup_hook() { - return NAPI_OK; - }, - napi_add_async_cleanup_hook() { - return NAPI_OK; - }, - napi_remove_async_cleanup_hook() { - return NAPI_OK; - }, - napi_set_instance_data(env_id, data, finalize_cb, finalize_hint) { - let env = environments[env_id]; - env.instanceData = data; - return NAPI_OK; - }, - napi_get_instance_data(env_id, data) { - let env = environments[env_id]; - return env.setPointer(data, env.instanceData); - }, - napi_get_boolean(env_id, value, result) { - let env = environments[env_id]; - return env.setPointer(result, value ? 3 : 4); - }, - napi_get_value_bool(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val ? 1 : 0; - return NAPI_OK; - }, - napi_create_int32(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_int32(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.i32[result >> 2] = val; - return NAPI_OK; - }, - napi_create_uint32(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_uint32(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, val); - }, - napi_create_int64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Number(value), result); - }, - napi_get_value_int64(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.i64[result >> 3] = val; - return NAPI_OK; - }, - napi_create_double(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_double(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.f64[result >> 3] = val; - return NAPI_OK; - }, - napi_create_bigint_int64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(BigInt.asIntN(64, value), result); - }, - napi_get_value_bigint_int64(env_id, value, result, lossless) { - let env = environments[env_id]; - let val = env.get(value); - env.i64[result >> 3] = val; - if (lossless) { - env.memory[lossless] = BigInt.asIntN(64, val) === val ? 1 : 0; - } - return NAPI_OK; - }, - napi_create_bigint_uint64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(BigInt.asUintN(64, value), result); - }, - napi_get_value_bigint_uint64(env_id, value, result, lossless) { - let env = environments[env_id]; - let val = env.get(value); - env.u64[result >> 3] = val; - if (lossless) { - env.memory[lossless] = BigInt.asUintN(64, val) === val ? 1 : 0; - } - return NAPI_OK; - }, - napi_create_bigint_words(env_id, sign_bit, word_count, words, result) { - let env = environments[env_id]; - let buf = env.u64; - let ptr = words >> 3; - let res = 0n; - let shift = 0n; - - for (let i = 0; i < word_count; i++) { - let word = buf[ptr++]; - res += word << shift; - shift += 64n; - } - - res *= BigInt((-1) ** sign_bit); - return env.createValue(res, result); - }, - napi_get_value_bigint_words(env_id, value, sign_bit, word_count, words) { - let env = environments[env_id]; - let val = env.get(value); - let count = env.u32[word_count >> 2]; - - if (sign_bit) { - env.i32[sign_bit] = val < 0n ? 1 : 0; - } - - let i = 0; - if (words) { - let mask = (1n << 64n) - 1n; - let buf = env.u64; - let ptr = words >> 3; - if (val < 0n) { - val = -val; - } - - for (; i < count && val !== 0n; i++) { - buf[ptr++] = val & mask; - val >>= 64n; - } - } - - while (val > 0n) { - i++; - val >>= 64n; - } - - return env.setPointer(word_count, i); - }, - napi_get_null(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 1); - }, - napi_create_array(env_id, result) { - let env = environments[env_id]; - return env.createValue([], result); - }, - napi_create_array_with_length(env_id, length, result) { - let env = environments[env_id]; - return env.createValue(new Array(length), result); - }, - napi_set_element(env_id, object, index, value) { - let env = environments[env_id]; - let obj = env.get(object); - let val = env.get(value); - obj[index] = val; - return NAPI_OK; - }, - napi_get_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - let val = obj[index]; - return env.createValue(val, result); - }, - napi_has_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - env.memory[result] = obj.hasOwnProperty(index) ? 1 : 0; - return NAPI_OK; - }, - napi_delete_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - let res = false; - try { - res = delete obj[index]; - } catch (err) {} - if (result) { - env.memory[result] = res ? 1 : 0; - } - return NAPI_OK; - }, - napi_get_array_length(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, val.length); - }, - napi_get_undefined(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 0); - }, - napi_create_function(env_id, utf8name, length, cb, data, result) { - let env = environments[env_id]; - let func = env.createFunction(cb, data); - - Object.defineProperty(func, 'name', { - value: env.getString(utf8name, length), - configurable: true - }); - - return env.createValue(func, result); - }, - napi_call_function(env_id, recv, func, argc, argv, result) { - let env = environments[env_id]; - let thisArg = env.get(recv); - let fn = env.get(func); - let args = new Array(argc); - let mem = env.u32; - for (let i = 0; i < argc; i++) { - args[i] = env.get(mem[argv >> 2]); - argv += 4; - } - - try { - let res = fn.apply(thisArg, args); - return env.createValue(res, result); - } catch (err) { - env.pendingException = err; - return NAPI_PENDING_EXCEPTION; - } - }, - napi_new_instance(env_id, cons, argc, argv, result) { - let env = environments[env_id]; - let Class = env.get(cons); - let args = new Array(argc); - let mem = env.u32; - for (let i = 0; i < argc; i++) { - args[i] = env.get(mem[argv >> 2]); - argv += 4; - } - - try { - let value = new Class(...args); - return env.createValue(value, result); - } catch (err) { - env.pendingException = err; - return NAPI_PENDING_EXCEPTION; - } - }, - napi_get_cb_info(env_id, cbinfo, argc, argv, thisArg, data) { - let env = environments[env_id]; - let info = env.get(cbinfo); - env.setPointer(argc, info.args.length); - for (let i = 0; i < info.args.length; i++) { - env.createValue(info.args[i], argv); - argv += 4; - } - env.createValue(info.thisArg, thisArg); - env.setPointer(data, info.data); - return NAPI_OK; - }, - napi_get_new_target(env_id, cbinfo, result) { - let env = environments[env_id]; - let info = env.get(cbinfo); - return env.createValue(info.newTarget, result); - }, - napi_create_threadsafe_function( - env_id, - func, - async_resource, - async_resource_name, - max_queue_size, - initial_thread_count, - thread_finalize_data, - thread_finalize_cb, - context, - call_js_cb, - result - ) { - let env = environments[env_id]; - let fn = func ? env.get(func) : undefined; - let cb = call_js_cb ? env.table.get(call_js_cb) : undefined; - let f = new ThreadSafeFunction(env, fn, cb, context); - - if (thread_finalize_cb) { - let cb = env.table.get(thread_finalize_cb); - finalizationRegistry.register(f, new FinalizeRecord(env_id, cb, 0, f.id)); - } - - env.setPointer(result, f.id); - return NAPI_OK; - }, - napi_ref_threadsafe_function() { - return NAPI_OK; - }, - napi_unref_threadsafe_function() { - return NAPI_OK; - }, - napi_acquire_threadsafe_function() { - return NAPI_OK; - }, - napi_release_threadsafe_function(func, mode) { - threadsafeFunctions[func] = undefined; - return NAPI_OK; - }, - napi_call_threadsafe_function(func, data, is_blocking) { - let f = threadsafeFunctions[func]; - f.env.pushScope(); - try { - if (f.nativeFn) { - let id = f.fn ? f.env.pushValue(f.fn) : 0; - f.nativeFn(f.env.id, id, f.context, data); - } else if (f.fn) { - f.fn(); - } - } finally { - f.env.popScope(); - } - }, - napi_get_threadsafe_function_context(func, result) { - let f = threadsafeFunctions[func]; - f.env.setPointer(result, f.context); - return NAPI_OK; - }, - napi_create_async_work(env_id, async_resource, async_resource_name, execute, complete, data, result) { - let env = environments[env_id]; - let executeFn = execute ? env.table.get(execute) : undefined; - let completeFn = complete ? env.table.get(complete) : undefined; - let w = new AsyncWork(env, executeFn, completeFn, data); - env.setPointer(result, w.id); - return NAPI_OK; - }, - napi_delete_async_work(env, work) { - asyncWork[work] = undefined; - return NAPI_OK; - }, - napi_queue_async_work(env, work) { - queueMicrotask(() => { - let w = asyncWork[work]; - if (w) { - w.execute(env, w.data); - w.complete(env, NAPI_OK, w.data); - } - }); - return NAPI_OK; - }, - napi_cancel_async_work() { - let w = asyncWork[work]; - w.complete(env, NAPI_CANCELED, w.data); - asyncWork[work] = undefined; - return NAPI_OK; - }, - napi_throw(env_id, error) { - let env = environments[env_id]; - env.pendingException = env.get(error); - return NAPI_OK; - }, - napi_throw_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new Error(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_throw_type_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new TypeError(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_throw_range_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new RangeError(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_create_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new Error(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_create_type_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new TypeError(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_create_range_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new RangeError(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_get_and_clear_last_exception(env_id, result) { - let env = environments[env_id]; - let e = env.pendingException; - env.pendingException = null; - return env.createValue(e, result); - }, - napi_is_exception_pending(env_id, result) { - let env = environments[env_id]; - env.memory[result] = env.pendingException ? 1 : 0; - return NAPI_OK; - }, - napi_fatal_exception(env_id, err) { - throw new Error('not implemented'); - }, - napi_fatal_error(location, location_len, message, message_len) { - throw new Error('not implemented'); - }, - napi_get_global(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 2); - }, - napi_create_buffer(env_id, length, data, result) { - let env = environments[env_id]; - let ptr = env.instance.exports.napi_wasm_malloc(length); - if (data) { - env.setPointer(data, ptr); - } - - // Return a view into WASM memory. - let buf = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, ptr, length) - : env.memory.subarray(ptr, ptr + length); - return env.createValue(buf, result); - }, - napi_create_buffer_copy(env_id, length, data, result_data, result) { - let env = environments[env_id]; - let ptr = env.instance.exports.napi_wasm_malloc(length); - env.memory.set(env.memory.subarray(data, data + length), ptr); - if (result_data) { - env.setPointer(result_data, ptr); - } - - // Return a view into WASM memory. - let res = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, ptr, length) - : env.memory.subarray(ptr, ptr + length); - return env.createValue(res, result); - }, - napi_create_external_buffer(env_id, length, data, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let buf = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, data, length) - : env.memory.subarray(data, data + length); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(buf, new FinalizeRecord(env_id, cb, finalize_hint, data)); - } - - return env.createValue(buf, result); - }, - napi_get_buffer_info(env_id, value, data, length) { - let env = environments[env_id]; - let buf = env.get(value); - let len = env.getBufferInfo(buf, data); - return env.setPointer(length, len); - }, - napi_create_arraybuffer(env_id, length, data, result) { - let env = environments[env_id]; - let buf = new ArrayBuffer(length); - if (data) { - // This copies the ArrayBuffer into the WASM memory. - env.getBufferInfo(buf, data); - } - return env.createValue(buf, result); - }, - napi_create_external_arraybuffer(env_id, data, length, finalize_cb, finalize_hint, result) { - // There is no way to actually create an external ArrayBuffer without copying. - // You can only create typed arrays as subarrays, not ArrayBuffer. - return NAPI_NO_EXTERNAL_BUFFERS_ALLOWED; - }, - napi_get_arraybuffer_info(env_id, value, data, length) { - let env = environments[env_id]; - let len = env.getBufferInfo(env.get(value), data); - return env.setPointer(length, len); - }, - napi_detach_arraybuffer(env_id, arraybuffer) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - if (typeof structuredClone === 'function') { - structuredClone(buffer, {transfer: [buffer]}); - } - return NAPI_OK; - }, - napi_is_detached_arraybuffer(env_id, arraybuffer, result) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - env.memory[result] = buffer.byteLength === 0 ? 1 : 0; // ?? - return NAPI_OK; - }, - napi_create_typedarray(env_id, type, length, arraybuffer, offset, result) { - let env = environments[env_id]; - let Class = typedArrays[type]; - let buffer = env.get(arraybuffer); - let buf = new Class(buffer, offset, length); - return env.createValue(buf, result); - }, - napi_create_dataview(env_id, byte_length, arraybuffer, byte_offset, result) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - let view = new DataView(buffer, byte_offset, byte_length); - return env.createValue(view, result); - }, - napi_get_typedarray_info(env_id, typedarray, type, length, data, arraybuffer, byte_offset) { - let env = environments[env_id]; - let val = env.get(typedarray); - env.setPointer(type, typedArrays.indexOf(val.constructor)); - env.setPointer(length, val.length); - env.getBufferInfo(val, data); - env.createValue(val.buffer, arraybuffer); - return env.setPointer(byte_offset, val.byteOffset); - }, - napi_get_dataview_info(env_id, dataview, byte_length, data, arraybuffer, byte_offset) { - let env = environments[env_id]; - let val = env.get(dataview); - env.setPointer(byte_length, val.byteLength); - env.getBufferInfo(val, data); - env.createValue(val.buffer, arraybuffer); - return env.setPointer(byte_offset, val.byteOffset); - }, - napi_create_string_utf8(env_id, str, length, result) { - let env = environments[env_id]; - let s = decoder.decode(env.memory.subarray(str, str + length)); - return env.createValue(s, result); - }, - napi_get_value_string_utf8(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, utf8Length(val)); - } - let res = encoder.encodeInto(val, env.memory.subarray(buf, buf + bufsize - 1)); - env.memory[buf + res.written] = 0; // null terminate - return env.setPointer(result, res.written); - }, - napi_create_string_latin1(env_id, str, length, result) { - let env = environments[env_id]; - let s = latin1Decoder.decode(env.memory.subarray(str, str + length)); - return env.createValue(s, result); - }, - napi_get_value_string_latin1(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, val.length); - } - let mem = env.memory; - let len = Math.min(val.length, bufsize - 1); - for (let i = 0; i < len; i++) { - let code = val.charCodeAt(i); - mem[buf++] = code; - } - mem[buf] = 0; // null terminate - return env.setPointer(result, len); - }, - napi_create_string_utf16(env_id, str, length, result) { - let env = environments[env_id]; - let s = utf16Decoder.decode(env.memory.subarray(str, str + length * 2)); - return env.createValue(s, result); - }, - napi_get_value_string_utf16(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, val.length); - } - let mem = env.u16; - let ptr = buf >> 1; - let len = Math.min(val.length, bufsize - 1); - for (let i = 0; i < len; i++) { - let code = val.charCodeAt(i); - mem[ptr++] = code; - } - mem[ptr] = 0; // null terminate - return env.setPointer(result, len); - }, - napi_create_date(env_id, time, result) { - let env = environments[env_id]; - return env.createValue(new Date(time), result); - }, - napi_get_date_value(env_id, value, result) { - let env = environments[env_id]; - let date = env.get(value); - env.f64[result >> 3] = date.valueOf(); - }, - napi_create_symbol(env_id, description, result) { - let env = environments[env_id]; - let desc = env.get(description); - return env.createValue(Symbol(desc), result); - }, - napi_coerce_to_bool(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Boolean(env.get(value)), result); - }, - napi_coerce_to_number(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Number(env.get(value)), result); - }, - napi_coerce_to_object(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Object(env.get(value)), result); - }, - napi_coerce_to_string(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(String(env.get(value)), result); - }, - napi_typeof(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, (() => { - switch (typeof val) { - case 'undefined': - return 0; - case 'boolean': - return 2; - case 'number': - return 3; - case 'string': - return 4; - case 'symbol': - return 5; - case 'object': - if (val === null) { - return 1; - } else if (val instanceof ExternalValue) { - return 8; - } - return 6; - case 'function': - return 7; - case 'bigint': - return 9; - } - })()); - }, - napi_instanceof(env_id, object, constructor, result) { - let env = environments[env_id]; - let obj = env.get(object); - let cons = env.get(constructor); - env.memory[result] = obj instanceof cons ? 1 : 0; - return NAPI_OK; - }, - napi_is_array(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = Array.isArray(val) ? 1 : 0; - return NAPI_OK; - }, - napi_is_buffer(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = (typeof globalThis.Buffer !== 'undefined' ? globalThis.Buffer.isBuffer(val) : val instanceof Uint8Array) ? 1 : 0; - return NAPI_OK; - }, - napi_is_date(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof Date ? 1 : 0; - return NAPI_OK; - }, - napi_is_error(env_id, value, result) { - let env = environments[env_id]; - let err = env.get(value); - env.memory[result] = err instanceof Error ? 1 : 0; - return NAPI_OK; - }, - napi_is_typedarray(env_id, value, result) { - let env = environments[env_id]; - let buf = env.get(value); - env.memory[result] = ArrayBuffer.isView(buf) && !(buf instanceof DataView) ? 1 : 0; - return NAPI_OK; - }, - napi_is_dataview(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof DataView ? 1 : 0; - return NAPI_OK; - }, - napi_strict_equals(env_id, lhs, rhs, result) { - let env = environments[env_id]; - env.memory[result] = env.get(lhs) === env.get(rhs) ? 1 : 0; - return NAPI_OK; - }, - napi_wrap(env_id, js_object, native_object, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - env.wrappedObjects.set(obj, native_object); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(obj, new FinalizeRecord(env_id, cb, finalize_hint, native_object)); - } - - if (result) { - return napi.napi_create_reference(env_id, js_object, 1, result); - } - - return NAPI_OK; - }, - napi_unwrap(env_id, js_object, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let native_object = env.wrappedObjects.get(obj); - env.setPointer(result, native_object); - return NAPI_OK; - }, - napi_remove_wrap(env_id, js_object, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let native_object = env.wrappedObjects.get(obj); - finalizationRegistry.unregister(obj); - env.wrappedObjects.delete(obj); - return env.setPointer(result, native_object); - }, - napi_type_tag_object(env_id, js_object, type_tag) { - throw new Error('not implemented'); - }, - napi_check_object_type_tag(env_id, js_object, type_tag) { - throw new Error('not implemented'); - }, - napi_add_finalizer(env_id, js_object, native_object, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(obj, new FinalizeRecord(env_id, cb, finalize_hint, native_object)); - if (result) { - return napi.napi_create_reference(env_id, js_object, 1, result); - } - - return NAPI_OK; - }, - napi_create_promise(env_id, deferred, promise) { - let env = environments[env_id]; - let p = new Promise((resolve, reject) => { - let id = env.deferred.length; - env.deferred.push({resolve, reject}); - env.setPointer(deferred, id); - }); - return env.createValue(p, promise); - }, - napi_resolve_deferred(env_id, deferred, resolution) { - let env = environments[env_id]; - let { resolve } = env.deferred[deferred]; - let value = env.get(resolution); - resolve(value); - env.deferred[deferred] = undefined; - return NAPI_OK; - }, - napi_reject_deferred(env_id, deferred, rejection) { - let env = environments[env_id]; - let { reject } = env.deferred[deferred]; - let value = env.get(rejection); - reject(value); - env.deferred[deferred] = undefined; - return NAPI_OK; - }, - napi_is_promise(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof Promise ? 1 : 0; - return NAPI_OK; - }, - napi_run_script(env_id, script, result) { - let env = environments[env_id]; - let source = env.get(script); - let res = (0, eval)(source); - return env.createValue(res, result); - }, - napi_create_external(env_id, data, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let external = new ExternalValue; - env.externalObjects.set(external, data); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(external, new FinalizeRecord(env_id, cb, finalize_hint, data)); - } - return env.createValue(external, result); - }, - napi_get_value_external(env_id, value, result) { - let env = environments[env_id]; - let external = env.get(value); - let val = env.externalObjects.get(external); - return env.setPointer(result, val); - }, - napi_adjust_external_memory() { - return NAPI_OK; - } -}; - -function strlen(buf, ptr) { - let len = 0; - while (buf[ptr] !== 0) { - len++; - ptr++; - } - - return len; -} - -function utf8Length(string) { - let len = 0; - for (let i = 0; i < string.length; i++) { - let c = string.charCodeAt(i); - - if (c >= 0xd800 && c <= 0xdbff && i < string.length - 1) { - let c2 = string.charCodeAt(++i); - if ((c2 & 0xfc00) === 0xdc00) { - c = ((c & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000; - } else { - // unmatched surrogate. - i--; - } - } - - if ((c & 0xffffff80) === 0) { - len++; - } else if ((c & 0xfffff800) === 0) { - len += 2; - } else if ((c & 0xffff0000) === 0) { - len += 3; - } else if ((c & 0xffe00000) === 0) { - len += 4; - } - } - return len; -} - -exports.Environment = Environment; -exports.napi = napi; diff --git a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.mjs b/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.mjs deleted file mode 100644 index 1955eb9..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.mjs +++ /dev/null @@ -1,1371 +0,0 @@ -const NAPI_OK = 0; -const NAPI_GENERIC_FAILURE = 9; -const NAPI_PENDING_EXCEPTION = 10; -const NAPI_CANCELED = 11; -const NAPI_HANDLE_SCOPE_MISMATCH = 13; -const NAPI_NO_EXTERNAL_BUFFERS_ALLOWED = 22; - -// https://nodejs.org/api/n-api.html#napi_property_attributes -const NAPI_WRITABLE = 1 << 0; -const NAPI_ENUMERABLE = 1 << 1; -const NAPI_CONFIGURABLE = 1 << 2; -const NAPI_STATIC = 1 << 10; - -// https://nodejs.org/api/n-api.html#napi_typedarray_type -const typedArrays = [ - Int8Array, - Uint8Array, - Uint8ClampedArray, - Int16Array, - Uint16Array, - Int32Array, - Uint32Array, - Float32Array, - Float64Array, - BigInt64Array, - BigUint64Array -]; - -const environments = []; - -export class Environment { - scopes = []; - referenceId = 1; - references = new Map(); - deferred = [null]; - wrappedObjects = new WeakMap(); - externalObjects = new WeakMap(); - buffers = new Map(); - instanceData = 0; - pendingException = null; - - constructor(instance) { - this.id = environments.length; - environments.push(this); - - this.instance = instance; - this.table = instance.exports.__indirect_function_table; - this.exports = {}; - - this.pushScope(); - let values = this.scopes[this.scopes.length - 1]; - let exports = values.length; - values.push(this.exports); - - try { - if (this.instance.exports.napi_register_module_v1) { - this.instance.exports.napi_register_module_v1(this.id, exports); - } - - if (this.instance.exports.napi_register_wasm_v1) { - this.instance.exports.napi_register_wasm_v1(this.id, exports); - } - } finally { - this.popScope(); - if (this.pendingException) { - let e = this.pendingException; - this.pendingException = null; - throw e; - } - } - } - - destroy() { - environments[this.id] = undefined; - } - - getString(ptr, len = strlen(this.memory, ptr)) { - return decoder.decode(this.memory.subarray(ptr, Math.max(0, ptr + len))); - } - - pushScope() { - let id = this.scopes.length; - this.scopes.push(id ? [...this.scopes[id - 1]] : [undefined, null, globalThis, true, false]); - return id; - } - - popScope() { - this.scopes.pop(); - - // Update any buffers with values which might have been modified in WASM copy. - for (let [buffer, slice] of this.buffers) { - // Ignore if buffer or slice has been detached. - if (buffer.byteLength && slice.byteLength) { - buffer.set(slice); - } - } - - this.buffers.clear(); - } - - get(idx) { - return this.scopes[this.scopes.length - 1][idx]; - } - - set(idx, value) { - this.scopes[this.scopes.length - 1][idx] = value; - } - - pushValue(value, scope = this.scopes.length - 1) { - let values = this.scopes[scope]; - let id = values.length; - values.push(value); - return id; - } - - createValue(value, result, scope) { - if (typeof value === 'boolean') { - this.setPointer(result, value ? 3 : 4); - return NAPI_OK; - } else if (typeof value === 'undefined') { - this.setPointer(result, 0); - return NAPI_OK; - } else if (value === null) { - this.setPointer(result, 1); - return NAPI_OK; - } else if (value === globalThis) { - this.setPointer(result, 2); - return NAPI_OK; - } - - let id = this.pushValue(value, scope); - this.setPointer(result, id); - return NAPI_OK; - } - - setPointer(ptr, value) { - this.u32[ptr >> 2] = value; - return NAPI_OK; - } - - _u32 = new Uint32Array(); - get u32() { - if (this._u32.byteLength === 0) { - this._u32 = new Uint32Array(this.instance.exports.memory.buffer); - } - - return this._u32; - } - - _i32 = new Int32Array(); - get i32() { - if (this._i32.byteLength === 0) { - this._i32 = new Int32Array(this.instance.exports.memory.buffer); - } - - return this._i32; - } - - _u16 = new Uint16Array(); - get u16() { - if (this._u16.byteLength === 0) { - this._u16 = new Uint16Array(this.instance.exports.memory.buffer); - } - - return this._u16; - } - - _u64 = new BigUint64Array(); - get u64() { - if (this._u64.byteLength === 0) { - this._u64 = new BigUint64Array(this.instance.exports.memory.buffer); - } - - return this._u64; - } - - _i64 = new BigInt64Array(); - get i64() { - if (this._i64.byteLength === 0) { - this._i64 = new BigInt64Array(this.instance.exports.memory.buffer); - } - - return this._i64; - } - - _f64 = new Float64Array(); - get f64() { - if (this._f64.byteLength === 0) { - this._f64 = new Float64Array(this.instance.exports.memory.buffer); - } - - return this._f64; - } - - _buf = new Uint8Array(); - get memory() { - if (this._buf.byteLength === 0) { - this._buf = new Uint8Array(this.instance.exports.memory.buffer); - } - - return this._buf; - } - - getBufferInfo(buf, ptr) { - if (this.buffers.has(buf)) { - let b = this.buffers.get(buf); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - if (buf instanceof ArrayBuffer) { - let b = this.copyBuffer(new Uint8Array(buf)); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - // If this is a view into WASM memory, no copies needed. - if (buf.buffer === this.instance.exports.memory.buffer) { - this.setPointer(ptr, buf.byteOffset); - return buf.byteLength; - } - - let b = this.copyBuffer(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - copyBuffer(data) { - let ptr = this.instance.exports.napi_wasm_malloc(data.byteLength); - let mem = this.memory; - mem.set(data, ptr); - let buf = mem.subarray(ptr, ptr + data.byteLength); - this.buffers.set(data, buf); - return buf; - } - - createFunction(cb, data) { - let env = this; - let fn = env.table.get(cb); - let func = function (...args) { - let scope = env.pushScope(); - - try { - let values = env.scopes[scope]; - let info = values.length; - values.push({ - thisArg: this, - args, - data, - newTarget: new.target - }); - - let res = fn(env.id, info); - return env.get(res); - } finally { - env.popScope(); - if (env.pendingException) { - let e = env.pendingException; - env.pendingException = null; - throw e; - } - } - }; - - return func; - } - - readPropertyDescriptor(ptr) { - // https://nodejs.org/api/n-api.html#napi_property_descriptor - let buf = this.u32; - let utf8name = buf[ptr++]; - let nameValue = buf[ptr++]; - let method = buf[ptr++]; - let getter = buf[ptr++]; - let setter = buf[ptr++]; - let val = buf[ptr++]; - let attrs = buf[ptr++]; - let data = buf[ptr++]; - - let name = utf8name ? this.getString(utf8name) : this.get(nameValue); - let writable = Boolean(attrs & NAPI_WRITABLE); - let enumerable = Boolean(attrs & NAPI_ENUMERABLE); - let configurable = Boolean(attrs & NAPI_CONFIGURABLE); - let isStatic = Boolean(attrs & NAPI_STATIC); - let get = getter ? this.createFunction(getter, data) : undefined; - let set = setter ? this.createFunction(setter, data) : undefined; - let value = method ? this.createFunction(method, data) : val ? this.get(val) : undefined; - - let descriptor = { - name, - static: isStatic, - configurable, - enumerable - }; - if (get || set) { - descriptor.get = get; - descriptor.set = set; - } else if (value) { - descriptor.writable = writable; - descriptor.value = value; - } - - return descriptor; - } -} - -const decoder = new TextDecoder("utf-8", { ignoreBOM: true, fatal: true }); -const latin1Decoder = new TextDecoder('latin1'); -const utf16Decoder = new TextDecoder('utf-16'); -const encoder = new TextEncoder(); - -class FinalizeRecord { - constructor(env, finalize, hint, data) { - this.env = env; - this.finalize = finalize; - this.hint = hint; - this.data = data; - } -} - -const finalizationRegistry = new FinalizationRegistry(buffer => { - if (buffer.finalize) { - buffer.finalize(buffer.env, buffer.data, buffer.hint); - } -}); - -class ExternalValue {} - -const threadsafeFunctions = []; - -class ThreadSafeFunction { - constructor(env, fn, nativeFn, context) { - this.env = env; - this.fn = fn; - this.nativeFn = nativeFn; - this.context = context; - this.id = threadsafeFunctions.length; - threadsafeFunctions.push(this); - } -} - -const asyncWork = [null]; - -class AsyncWork { - constructor(env, execute, complete, data) { - this.env = env; - this.execute = execute; - this.complete = complete; - this.data = data; - this.id = asyncWork.length; - asyncWork.push(this); - } -} - -export const napi = { - napi_open_handle_scope(env_id, result) { - let env = environments[env_id]; - let id = env.pushScope(); - return env.setPointer(result, id); - }, - napi_close_handle_scope(env_id, scope) { - let env = environments[env_id]; - if (scope !== env.scopes.length - 1) { - return NAPI_HANDLE_SCOPE_MISMATCH; - } - env.popScope(); - return NAPI_OK; - }, - napi_open_escapable_handle_scope(env_id, result) { - let env = environments[env_id]; - let id = env.pushScope(); - return env.setPointer(result, id); - }, - napi_close_escapable_handle_scope(env_id, scope) { - let env = environments[env_id]; - if (scope !== env.scopes.length - 1) { - return NAPI_HANDLE_SCOPE_MISMATCH; - } - env.popScope(); - return NAPI_OK; - }, - napi_escape_handle(env_id, scope_id, escapee, result) { - let env = environments[env_id]; - let value = env.get(escapee); - // Create a value in the outer scope. - return env.createValue(value, result, scope_id - 1); - }, - napi_create_object(env_id, result) { - let env = environments[env_id]; - return env.createValue({}, result); - }, - napi_set_property(env_id, object, key, value) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - let val = env.get(value); - obj[name] = val; - return NAPI_OK; - }, - napi_get_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - return env.createValue(obj[name], result); - }, - napi_delete_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - let res = false; - try { - res = delete obj[name]; - } catch (err) {} - if (result) { - env.memory[result] = res ? 1 : 0; - } - return NAPI_OK; - }, - napi_has_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - // return env.setPointer(result, name in obj ? 1 : 0); - env.memory[result] = name in obj ? 1 : 0; - return NAPI_OK; - }, - napi_has_own_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - env.memory[result] = obj.hasOwnProperty(name) ? 1 : 0; - return NAPI_OK; - }, - napi_set_named_property(env_id, object, utf8Name, value) { - let env = environments[env_id]; - let obj = env.get(object); - let val = env.get(value); - let name = env.getString(utf8Name); - obj[name] = val; - return NAPI_OK; - }, - napi_get_named_property(env_id, object, utf8Name, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.getString(utf8Name); - return env.createValue(obj[name], result); - }, - napi_has_named_property(env_id, object, utf8Name, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.getString(utf8Name); - env.memory[result] = name in obj ? 1 : 0; - return NAPI_OK; - }, - napi_get_property_names(env_id, object, result) { - let env = environments[env_id]; - let obj = env.get(object); - let properties = Object.keys(obj); - return env.createValue(properties, result); - }, - napi_get_all_property_names(env_id, object, key_mode, key_filter, key_conversion, result) { - throw new Error('not implemented'); - }, - napi_define_properties(env_id, object, property_count, properties) { - let env = environments[env_id]; - let obj = env.get(object); - let ptr = properties >> 2; - for (let i = 0; i < property_count; i++) { - let descriptor = env.readPropertyDescriptor(ptr); - Object.defineProperty(obj, descriptor.name, descriptor); - ptr += 8; - } - return NAPI_OK; - }, - napi_object_freeze(env_id, object) { - let env = environments[env_id]; - let obj = env.get(object); - Object.freeze(obj); - return NAPI_OK; - }, - napi_object_seal(env_id, object) { - let env = environments[env_id]; - let obj = env.get(object); - Object.seal(obj); - return NAPI_OK; - }, - napi_get_prototype(env_id, object, result) { - let env = environments[env_id]; - let obj = env.get(object); - return env.createValue(Object.getPrototypeOf(obj), result); - }, - napi_define_class(env_id, utf8name, length, constructor, data, property_count, properties, result) { - let env = environments[env_id]; - let func = env.createFunction(constructor, data); - - Object.defineProperty(func, 'name', { - value: env.getString(utf8name, length), - configurable: true - }); - - let ptr = properties >> 2; - for (let i = 0; i < property_count; i++) { - let descriptor = env.readPropertyDescriptor(ptr); - if (descriptor.static) { - Object.defineProperty(func, descriptor.name, descriptor); - } else { - Object.defineProperty(func.prototype, descriptor.name, descriptor); - } - ptr += 8; - } - - return env.createValue(func, result); - }, - napi_create_reference(env_id, value, refcount, result) { - let env = environments[env_id]; - let id = env.referenceId++; - env.references.set(id, { - value: env.get(value), - refcount - }); - return env.setPointer(result, id); - }, - napi_delete_reference(env_id, ref) { - let env = environments[env_id]; - env.references.delete(ref); - return NAPI_OK; - }, - napi_get_reference_value(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - return env.createValue(reference.value, result); - }, - napi_reference_ref(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - reference.refcount++; - return env.setPointer(result, reference.refcount); - }, - napi_reference_unref(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - if (reference.refcount === 0) { - return NAPI_GENERIC_FAILURE; - } - reference.refcount--; - return env.setPointer(result, reference.refcount); - }, - napi_add_env_cleanup_hook() { - return NAPI_OK; - }, - napi_remove_env_cleanup_hook() { - return NAPI_OK; - }, - napi_add_async_cleanup_hook() { - return NAPI_OK; - }, - napi_remove_async_cleanup_hook() { - return NAPI_OK; - }, - napi_set_instance_data(env_id, data, finalize_cb, finalize_hint) { - let env = environments[env_id]; - env.instanceData = data; - return NAPI_OK; - }, - napi_get_instance_data(env_id, data) { - let env = environments[env_id]; - return env.setPointer(data, env.instanceData); - }, - napi_get_boolean(env_id, value, result) { - let env = environments[env_id]; - return env.setPointer(result, value ? 3 : 4); - }, - napi_get_value_bool(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val ? 1 : 0; - return NAPI_OK; - }, - napi_create_int32(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_int32(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.i32[result >> 2] = val; - return NAPI_OK; - }, - napi_create_uint32(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_uint32(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, val); - }, - napi_create_int64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Number(value), result); - }, - napi_get_value_int64(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.i64[result >> 3] = val; - return NAPI_OK; - }, - napi_create_double(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_double(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.f64[result >> 3] = val; - return NAPI_OK; - }, - napi_create_bigint_int64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(BigInt.asIntN(64, value), result); - }, - napi_get_value_bigint_int64(env_id, value, result, lossless) { - let env = environments[env_id]; - let val = env.get(value); - env.i64[result >> 3] = val; - if (lossless) { - env.memory[lossless] = BigInt.asIntN(64, val) === val ? 1 : 0; - } - return NAPI_OK; - }, - napi_create_bigint_uint64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(BigInt.asUintN(64, value), result); - }, - napi_get_value_bigint_uint64(env_id, value, result, lossless) { - let env = environments[env_id]; - let val = env.get(value); - env.u64[result >> 3] = val; - if (lossless) { - env.memory[lossless] = BigInt.asUintN(64, val) === val ? 1 : 0; - } - return NAPI_OK; - }, - napi_create_bigint_words(env_id, sign_bit, word_count, words, result) { - let env = environments[env_id]; - let buf = env.u64; - let ptr = words >> 3; - let res = 0n; - let shift = 0n; - - for (let i = 0; i < word_count; i++) { - let word = buf[ptr++]; - res += word << shift; - shift += 64n; - } - - res *= BigInt((-1) ** sign_bit); - return env.createValue(res, result); - }, - napi_get_value_bigint_words(env_id, value, sign_bit, word_count, words) { - let env = environments[env_id]; - let val = env.get(value); - let count = env.u32[word_count >> 2]; - - if (sign_bit) { - env.i32[sign_bit] = val < 0n ? 1 : 0; - } - - let i = 0; - if (words) { - let mask = (1n << 64n) - 1n; - let buf = env.u64; - let ptr = words >> 3; - if (val < 0n) { - val = -val; - } - - for (; i < count && val !== 0n; i++) { - buf[ptr++] = val & mask; - val >>= 64n; - } - } - - while (val > 0n) { - i++; - val >>= 64n; - } - - return env.setPointer(word_count, i); - }, - napi_get_null(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 1); - }, - napi_create_array(env_id, result) { - let env = environments[env_id]; - return env.createValue([], result); - }, - napi_create_array_with_length(env_id, length, result) { - let env = environments[env_id]; - return env.createValue(new Array(length), result); - }, - napi_set_element(env_id, object, index, value) { - let env = environments[env_id]; - let obj = env.get(object); - let val = env.get(value); - obj[index] = val; - return NAPI_OK; - }, - napi_get_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - let val = obj[index]; - return env.createValue(val, result); - }, - napi_has_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - env.memory[result] = obj.hasOwnProperty(index) ? 1 : 0; - return NAPI_OK; - }, - napi_delete_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - let res = false; - try { - res = delete obj[index]; - } catch (err) {} - if (result) { - env.memory[result] = res ? 1 : 0; - } - return NAPI_OK; - }, - napi_get_array_length(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, val.length); - }, - napi_get_undefined(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 0); - }, - napi_create_function(env_id, utf8name, length, cb, data, result) { - let env = environments[env_id]; - let func = env.createFunction(cb, data); - - Object.defineProperty(func, 'name', { - value: env.getString(utf8name, length), - configurable: true - }); - - return env.createValue(func, result); - }, - napi_call_function(env_id, recv, func, argc, argv, result) { - let env = environments[env_id]; - let thisArg = env.get(recv); - let fn = env.get(func); - let args = new Array(argc); - let mem = env.u32; - for (let i = 0; i < argc; i++) { - args[i] = env.get(mem[argv >> 2]); - argv += 4; - } - - try { - let res = fn.apply(thisArg, args); - return env.createValue(res, result); - } catch (err) { - env.pendingException = err; - return NAPI_PENDING_EXCEPTION; - } - }, - napi_new_instance(env_id, cons, argc, argv, result) { - let env = environments[env_id]; - let Class = env.get(cons); - let args = new Array(argc); - let mem = env.u32; - for (let i = 0; i < argc; i++) { - args[i] = env.get(mem[argv >> 2]); - argv += 4; - } - - try { - let value = new Class(...args); - return env.createValue(value, result); - } catch (err) { - env.pendingException = err; - return NAPI_PENDING_EXCEPTION; - } - }, - napi_get_cb_info(env_id, cbinfo, argc, argv, thisArg, data) { - let env = environments[env_id]; - let info = env.get(cbinfo); - env.setPointer(argc, info.args.length); - for (let i = 0; i < info.args.length; i++) { - env.createValue(info.args[i], argv); - argv += 4; - } - env.createValue(info.thisArg, thisArg); - env.setPointer(data, info.data); - return NAPI_OK; - }, - napi_get_new_target(env_id, cbinfo, result) { - let env = environments[env_id]; - let info = env.get(cbinfo); - return env.createValue(info.newTarget, result); - }, - napi_create_threadsafe_function( - env_id, - func, - async_resource, - async_resource_name, - max_queue_size, - initial_thread_count, - thread_finalize_data, - thread_finalize_cb, - context, - call_js_cb, - result - ) { - let env = environments[env_id]; - let fn = func ? env.get(func) : undefined; - let cb = call_js_cb ? env.table.get(call_js_cb) : undefined; - let f = new ThreadSafeFunction(env, fn, cb, context); - - if (thread_finalize_cb) { - let cb = env.table.get(thread_finalize_cb); - finalizationRegistry.register(f, new FinalizeRecord(env_id, cb, 0, f.id)); - } - - env.setPointer(result, f.id); - return NAPI_OK; - }, - napi_ref_threadsafe_function() { - return NAPI_OK; - }, - napi_unref_threadsafe_function() { - return NAPI_OK; - }, - napi_acquire_threadsafe_function() { - return NAPI_OK; - }, - napi_release_threadsafe_function(func, mode) { - threadsafeFunctions[func] = undefined; - return NAPI_OK; - }, - napi_call_threadsafe_function(func, data, is_blocking) { - let f = threadsafeFunctions[func]; - f.env.pushScope(); - try { - if (f.nativeFn) { - let id = f.fn ? f.env.pushValue(f.fn) : 0; - f.nativeFn(f.env.id, id, f.context, data); - } else if (f.fn) { - f.fn(); - } - } finally { - f.env.popScope(); - } - }, - napi_get_threadsafe_function_context(func, result) { - let f = threadsafeFunctions[func]; - f.env.setPointer(result, f.context); - return NAPI_OK; - }, - napi_create_async_work(env_id, async_resource, async_resource_name, execute, complete, data, result) { - let env = environments[env_id]; - let executeFn = execute ? env.table.get(execute) : undefined; - let completeFn = complete ? env.table.get(complete) : undefined; - let w = new AsyncWork(env, executeFn, completeFn, data); - env.setPointer(result, w.id); - return NAPI_OK; - }, - napi_delete_async_work(env, work) { - asyncWork[work] = undefined; - return NAPI_OK; - }, - napi_queue_async_work(env, work) { - queueMicrotask(() => { - let w = asyncWork[work]; - if (w) { - w.execute(env, w.data); - w.complete(env, NAPI_OK, w.data); - } - }); - return NAPI_OK; - }, - napi_cancel_async_work() { - let w = asyncWork[work]; - w.complete(env, NAPI_CANCELED, w.data); - asyncWork[work] = undefined; - return NAPI_OK; - }, - napi_throw(env_id, error) { - let env = environments[env_id]; - env.pendingException = env.get(error); - return NAPI_OK; - }, - napi_throw_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new Error(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_throw_type_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new TypeError(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_throw_range_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new RangeError(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_create_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new Error(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_create_type_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new TypeError(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_create_range_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new RangeError(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_get_and_clear_last_exception(env_id, result) { - let env = environments[env_id]; - let e = env.pendingException; - env.pendingException = null; - return env.createValue(e, result); - }, - napi_is_exception_pending(env_id, result) { - let env = environments[env_id]; - env.memory[result] = env.pendingException ? 1 : 0; - return NAPI_OK; - }, - napi_fatal_exception(env_id, err) { - throw new Error('not implemented'); - }, - napi_fatal_error(location, location_len, message, message_len) { - throw new Error('not implemented'); - }, - napi_get_global(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 2); - }, - napi_create_buffer(env_id, length, data, result) { - let env = environments[env_id]; - let ptr = env.instance.exports.napi_wasm_malloc(length); - if (data) { - env.setPointer(data, ptr); - } - - // Return a view into WASM memory. - let buf = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, ptr, length) - : env.memory.subarray(ptr, ptr + length); - return env.createValue(buf, result); - }, - napi_create_buffer_copy(env_id, length, data, result_data, result) { - let env = environments[env_id]; - let ptr = env.instance.exports.napi_wasm_malloc(length); - env.memory.set(env.memory.subarray(data, data + length), ptr); - if (result_data) { - env.setPointer(result_data, ptr); - } - - // Return a view into WASM memory. - let res = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, ptr, length) - : env.memory.subarray(ptr, ptr + length); - return env.createValue(res, result); - }, - napi_create_external_buffer(env_id, length, data, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let buf = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, data, length) - : env.memory.subarray(data, data + length); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(buf, new FinalizeRecord(env_id, cb, finalize_hint, data)); - } - - return env.createValue(buf, result); - }, - napi_get_buffer_info(env_id, value, data, length) { - let env = environments[env_id]; - let buf = env.get(value); - let len = env.getBufferInfo(buf, data); - return env.setPointer(length, len); - }, - napi_create_arraybuffer(env_id, length, data, result) { - let env = environments[env_id]; - let buf = new ArrayBuffer(length); - if (data) { - // This copies the ArrayBuffer into the WASM memory. - env.getBufferInfo(buf, data); - } - return env.createValue(buf, result); - }, - napi_create_external_arraybuffer(env_id, data, length, finalize_cb, finalize_hint, result) { - // There is no way to actually create an external ArrayBuffer without copying. - // You can only create typed arrays as subarrays, not ArrayBuffer. - return NAPI_NO_EXTERNAL_BUFFERS_ALLOWED; - }, - napi_get_arraybuffer_info(env_id, value, data, length) { - let env = environments[env_id]; - let len = env.getBufferInfo(env.get(value), data); - return env.setPointer(length, len); - }, - napi_detach_arraybuffer(env_id, arraybuffer) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - if (typeof structuredClone === 'function') { - structuredClone(buffer, {transfer: [buffer]}); - } - return NAPI_OK; - }, - napi_is_detached_arraybuffer(env_id, arraybuffer, result) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - env.memory[result] = buffer.byteLength === 0 ? 1 : 0; // ?? - return NAPI_OK; - }, - napi_create_typedarray(env_id, type, length, arraybuffer, offset, result) { - let env = environments[env_id]; - let Class = typedArrays[type]; - let buffer = env.get(arraybuffer); - let buf = new Class(buffer, offset, length); - return env.createValue(buf, result); - }, - napi_create_dataview(env_id, byte_length, arraybuffer, byte_offset, result) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - let view = new DataView(buffer, byte_offset, byte_length); - return env.createValue(view, result); - }, - napi_get_typedarray_info(env_id, typedarray, type, length, data, arraybuffer, byte_offset) { - let env = environments[env_id]; - let val = env.get(typedarray); - env.setPointer(type, typedArrays.indexOf(val.constructor)); - env.setPointer(length, val.length); - env.getBufferInfo(val, data); - env.createValue(val.buffer, arraybuffer); - return env.setPointer(byte_offset, val.byteOffset); - }, - napi_get_dataview_info(env_id, dataview, byte_length, data, arraybuffer, byte_offset) { - let env = environments[env_id]; - let val = env.get(dataview); - env.setPointer(byte_length, val.byteLength); - env.getBufferInfo(val, data); - env.createValue(val.buffer, arraybuffer); - return env.setPointer(byte_offset, val.byteOffset); - }, - napi_create_string_utf8(env_id, str, length, result) { - let env = environments[env_id]; - let s = decoder.decode(env.memory.subarray(str, str + length)); - return env.createValue(s, result); - }, - napi_get_value_string_utf8(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, utf8Length(val)); - } - let res = encoder.encodeInto(val, env.memory.subarray(buf, buf + bufsize - 1)); - env.memory[buf + res.written] = 0; // null terminate - return env.setPointer(result, res.written); - }, - napi_create_string_latin1(env_id, str, length, result) { - let env = environments[env_id]; - let s = latin1Decoder.decode(env.memory.subarray(str, str + length)); - return env.createValue(s, result); - }, - napi_get_value_string_latin1(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, val.length); - } - let mem = env.memory; - let len = Math.min(val.length, bufsize - 1); - for (let i = 0; i < len; i++) { - let code = val.charCodeAt(i); - mem[buf++] = code; - } - mem[buf] = 0; // null terminate - return env.setPointer(result, len); - }, - napi_create_string_utf16(env_id, str, length, result) { - let env = environments[env_id]; - let s = utf16Decoder.decode(env.memory.subarray(str, str + length * 2)); - return env.createValue(s, result); - }, - napi_get_value_string_utf16(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, val.length); - } - let mem = env.u16; - let ptr = buf >> 1; - let len = Math.min(val.length, bufsize - 1); - for (let i = 0; i < len; i++) { - let code = val.charCodeAt(i); - mem[ptr++] = code; - } - mem[ptr] = 0; // null terminate - return env.setPointer(result, len); - }, - napi_create_date(env_id, time, result) { - let env = environments[env_id]; - return env.createValue(new Date(time), result); - }, - napi_get_date_value(env_id, value, result) { - let env = environments[env_id]; - let date = env.get(value); - env.f64[result >> 3] = date.valueOf(); - }, - napi_create_symbol(env_id, description, result) { - let env = environments[env_id]; - let desc = env.get(description); - return env.createValue(Symbol(desc), result); - }, - napi_coerce_to_bool(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Boolean(env.get(value)), result); - }, - napi_coerce_to_number(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Number(env.get(value)), result); - }, - napi_coerce_to_object(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Object(env.get(value)), result); - }, - napi_coerce_to_string(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(String(env.get(value)), result); - }, - napi_typeof(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, (() => { - switch (typeof val) { - case 'undefined': - return 0; - case 'boolean': - return 2; - case 'number': - return 3; - case 'string': - return 4; - case 'symbol': - return 5; - case 'object': - if (val === null) { - return 1; - } else if (val instanceof ExternalValue) { - return 8; - } - return 6; - case 'function': - return 7; - case 'bigint': - return 9; - } - })()); - }, - napi_instanceof(env_id, object, constructor, result) { - let env = environments[env_id]; - let obj = env.get(object); - let cons = env.get(constructor); - env.memory[result] = obj instanceof cons ? 1 : 0; - return NAPI_OK; - }, - napi_is_array(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = Array.isArray(val) ? 1 : 0; - return NAPI_OK; - }, - napi_is_buffer(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = (typeof globalThis.Buffer !== 'undefined' ? globalThis.Buffer.isBuffer(val) : val instanceof Uint8Array) ? 1 : 0; - return NAPI_OK; - }, - napi_is_date(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof Date ? 1 : 0; - return NAPI_OK; - }, - napi_is_error(env_id, value, result) { - let env = environments[env_id]; - let err = env.get(value); - env.memory[result] = err instanceof Error ? 1 : 0; - return NAPI_OK; - }, - napi_is_typedarray(env_id, value, result) { - let env = environments[env_id]; - let buf = env.get(value); - env.memory[result] = ArrayBuffer.isView(buf) && !(buf instanceof DataView) ? 1 : 0; - return NAPI_OK; - }, - napi_is_dataview(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof DataView ? 1 : 0; - return NAPI_OK; - }, - napi_strict_equals(env_id, lhs, rhs, result) { - let env = environments[env_id]; - env.memory[result] = env.get(lhs) === env.get(rhs) ? 1 : 0; - return NAPI_OK; - }, - napi_wrap(env_id, js_object, native_object, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - env.wrappedObjects.set(obj, native_object); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(obj, new FinalizeRecord(env_id, cb, finalize_hint, native_object)); - } - - if (result) { - return napi.napi_create_reference(env_id, js_object, 1, result); - } - - return NAPI_OK; - }, - napi_unwrap(env_id, js_object, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let native_object = env.wrappedObjects.get(obj); - env.setPointer(result, native_object); - return NAPI_OK; - }, - napi_remove_wrap(env_id, js_object, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let native_object = env.wrappedObjects.get(obj); - finalizationRegistry.unregister(obj); - env.wrappedObjects.delete(obj); - return env.setPointer(result, native_object); - }, - napi_type_tag_object(env_id, js_object, type_tag) { - throw new Error('not implemented'); - }, - napi_check_object_type_tag(env_id, js_object, type_tag) { - throw new Error('not implemented'); - }, - napi_add_finalizer(env_id, js_object, native_object, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(obj, new FinalizeRecord(env_id, cb, finalize_hint, native_object)); - if (result) { - return napi.napi_create_reference(env_id, js_object, 1, result); - } - - return NAPI_OK; - }, - napi_create_promise(env_id, deferred, promise) { - let env = environments[env_id]; - let p = new Promise((resolve, reject) => { - let id = env.deferred.length; - env.deferred.push({resolve, reject}); - env.setPointer(deferred, id); - }); - return env.createValue(p, promise); - }, - napi_resolve_deferred(env_id, deferred, resolution) { - let env = environments[env_id]; - let { resolve } = env.deferred[deferred]; - let value = env.get(resolution); - resolve(value); - env.deferred[deferred] = undefined; - return NAPI_OK; - }, - napi_reject_deferred(env_id, deferred, rejection) { - let env = environments[env_id]; - let { reject } = env.deferred[deferred]; - let value = env.get(rejection); - reject(value); - env.deferred[deferred] = undefined; - return NAPI_OK; - }, - napi_is_promise(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof Promise ? 1 : 0; - return NAPI_OK; - }, - napi_run_script(env_id, script, result) { - let env = environments[env_id]; - let source = env.get(script); - let res = (0, eval)(source); - return env.createValue(res, result); - }, - napi_create_external(env_id, data, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let external = new ExternalValue; - env.externalObjects.set(external, data); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(external, new FinalizeRecord(env_id, cb, finalize_hint, data)); - } - return env.createValue(external, result); - }, - napi_get_value_external(env_id, value, result) { - let env = environments[env_id]; - let external = env.get(value); - let val = env.externalObjects.get(external); - return env.setPointer(result, val); - }, - napi_adjust_external_memory() { - return NAPI_OK; - } -}; - -function strlen(buf, ptr) { - let len = 0; - while (buf[ptr] !== 0) { - len++; - ptr++; - } - - return len; -} - -function utf8Length(string) { - let len = 0; - for (let i = 0; i < string.length; i++) { - let c = string.charCodeAt(i); - - if (c >= 0xd800 && c <= 0xdbff && i < string.length - 1) { - let c2 = string.charCodeAt(++i); - if ((c2 & 0xfc00) === 0xdc00) { - c = ((c & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000; - } else { - // unmatched surrogate. - i--; - } - } - - if ((c & 0xffffff80) === 0) { - len++; - } else if ((c & 0xfffff800) === 0) { - len += 2; - } else if ((c & 0xffff0000) === 0) { - len += 3; - } else if ((c & 0xffe00000) === 0) { - len += 4; - } - } - return len; -} diff --git a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/package.json b/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/package.json deleted file mode 100644 index ce6ee25..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "napi-wasm", - "version": "1.1.0", - "description": "An implementation of napi for wasm", - "main": "index.mjs", - "exports": { - "import": "./index.mjs", - "require": "./index.js" - }, - "files": [ - "index.js", - "index.mjs" - ], - "scripts": { - "prepublishOnly": "sed 's/^export //g' index.mjs > index.js && echo '\nexports.Environment = Environment;\nexports.napi = napi;' >> index.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/devongovett/napi-wasm.git" - }, - "keywords": [ - "napi", - "wasm", - "node-api", - "rust" - ], - "author": "Devon Govett ", - "license": "MIT", - "bugs": { - "url": "https://github.com/devongovett/napi-wasm/issues" - }, - "homepage": "https://github.com/devongovett/napi-wasm#readme" -} diff --git a/dapp/node_modules/@parcel/watcher-wasm/package.json b/dapp/node_modules/@parcel/watcher-wasm/package.json deleted file mode 100644 index f4ae117..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "@parcel/watcher-wasm", - "version": "2.3.0", - "main": "index.mjs", - "types": "index.d.ts", - "repository": { - "type": "git", - "url": "https://github.com/parcel-bundler/watcher.git" - }, - "description": "A native C++ Node module for querying and subscribing to filesystem events. Used by Parcel 2.", - "license": "MIT", - "publishConfig": { - "access": "public" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "files": [ - "*.js", - "*.mjs", - "*.d.ts", - "*.wasm" - ], - "engines": { - "node": ">= 10.0.0" - }, - "dependencies": { - "napi-wasm": "^1.1.0", - "is-glob": "^4.0.3", - "micromatch": "^4.0.5" - }, - "module": "index.mjs", - "sideEffects": false, - "bundledDependencies": [ - "napi-wasm" - ] -} diff --git a/dapp/node_modules/@parcel/watcher-wasm/watcher.wasm b/dapp/node_modules/@parcel/watcher-wasm/watcher.wasm deleted file mode 100644 index 0623b49..0000000 Binary files a/dapp/node_modules/@parcel/watcher-wasm/watcher.wasm and /dev/null differ diff --git a/dapp/node_modules/@parcel/watcher-wasm/wrapper.js b/dapp/node_modules/@parcel/watcher-wasm/wrapper.js deleted file mode 100644 index 496d56b..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/wrapper.js +++ /dev/null @@ -1,77 +0,0 @@ -const path = require('path'); -const micromatch = require('micromatch'); -const isGlob = require('is-glob'); - -function normalizeOptions(dir, opts = {}) { - const { ignore, ...rest } = opts; - - if (Array.isArray(ignore)) { - opts = { ...rest }; - - for (const value of ignore) { - if (isGlob(value)) { - if (!opts.ignoreGlobs) { - opts.ignoreGlobs = []; - } - - const regex = micromatch.makeRe(value, { - // We set `dot: true` to workaround an issue with the - // regular expression on Linux where the resulting - // negative lookahead `(?!(\\/|^)` was never matching - // in some cases. See also https://bit.ly/3UZlQDm - dot: true, - // C++ does not support lookbehind regex patterns, they - // were only added later to JavaScript engines - // (https://bit.ly/3V7S6UL) - lookbehinds: false - }); - opts.ignoreGlobs.push(regex.source); - } else { - if (!opts.ignorePaths) { - opts.ignorePaths = []; - } - - opts.ignorePaths.push(path.resolve(dir, value)); - } - } - } - - return opts; -} - -exports.createWrapper = (binding) => { - return { - writeSnapshot(dir, snapshot, opts) { - return binding.writeSnapshot( - path.resolve(dir), - path.resolve(snapshot), - normalizeOptions(dir, opts), - ); - }, - getEventsSince(dir, snapshot, opts) { - return binding.getEventsSince( - path.resolve(dir), - path.resolve(snapshot), - normalizeOptions(dir, opts), - ); - }, - async subscribe(dir, fn, opts) { - dir = path.resolve(dir); - opts = normalizeOptions(dir, opts); - await binding.subscribe(dir, fn, opts); - - return { - unsubscribe() { - return binding.unsubscribe(dir, fn, opts); - }, - }; - }, - unsubscribe(dir, fn, opts) { - return binding.unsubscribe( - path.resolve(dir), - fn, - normalizeOptions(dir, opts), - ); - } - }; -}; diff --git a/src/bwc_staking_contract.cairo b/src/bwc_staking_contract.cairo index 8cc9d2d..5eff986 100644 --- a/src/bwc_staking_contract.cairo +++ b/src/bwc_staking_contract.cairo @@ -38,7 +38,7 @@ mod BWCStakingContract { staker: LegacyMap::, bwcerc20_token_address: ContractAddress, receipt_token_address: ContractAddress, - reward_token_address: ContractAddress + reward_token_address: ContractAddress, } ////////////////// @@ -77,6 +77,7 @@ mod BWCStakingContract { ///////////////// mod Errors { const INSUFFICIENT_FUND: felt252 = 'STAKE: Insufficient fund'; + const INVALID_WITHDRAW_TIME: felt252 = 'Not yet time to withdraw'; const INSUFFICIENT_BALANCE: felt252 = 'STAKE: Insufficient balance'; const ADDRESS_ZERO: felt252 = 'STAKE: Address zero'; const NOT_TOKEN_ADDRESS: felt252 = 'STAKE: Not token address'; @@ -86,7 +87,7 @@ mod BWCStakingContract { const NOT_WITHDRAW_TIME: felt252 = 'STAKE: Not yet withdraw time'; const LOW_CONTRACT_BALANCE: felt252 = 'STAKE: Low contract balance'; const AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; - const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; + const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'Withdraw amount not allowed'; } #[constructor] @@ -156,6 +157,7 @@ mod BWCStakingContract { // // Staker calls the approve function of receipt token contract and approves this contract to transfer out `amount` receipt from staker account // Reason for this is to allow this contract withdraw the receipt token before sending back stake tokens + // receipt_contract.approve(address_this, amount); self .emit( @@ -170,6 +172,7 @@ mod BWCStakingContract { self.staker.read(get_caller_address()).amount } + // Function allows caller to withdraw their staked token and get rewarded // @amount: Amount of token to withdraw // @BWCERC20TokenAddr: Contract address of token to withdraw @@ -195,9 +198,9 @@ mod BWCStakingContract { let stake_time = stake.time_staked; assert( - amount <= stake_amount, 'Withdraw amt > than stake amt' + amount <= stake_amount, Errors::WITHDRAW_AMOUNT_NOT_ALLOWED ); // Staker cannot withdraw more than staked amount - assert(self.is_time_to_withdraw(stake_time), 'Not yet time to withdraw'); + assert(self.is_time_to_withdraw(stake_time), Errors::INVALID_WITHDRAW_TIME); assert( reward_contract.balance_of(address_this) >= amount, 'Not enough reward token to send' diff --git a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo index a4159b7..6abf845 100644 --- a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo +++ b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo @@ -4,13 +4,13 @@ use core::result::ResultTrait; use core::option::OptionTrait; use basic_staking_dapp::bwc_staking_contract::{IStake, BWCStakingContract, IStakeDispatcher}; use basic_staking_dapp::erc20_token::{IERC20, ERC20, IERC20Dispatcher}; -use starknet::ContractAddress; +use starknet::{ContractAddress, get_block_timestamp}; use starknet::contract_address::contract_address_const; use core::array::ArrayTrait; -use snforge_std::{declare, ContractClassTrait, fs::{FileTrait, read_txt}}; -use snforge_std::{start_prank, stop_prank, CheatTarget}; - -use snforge_std::PrintTrait; +use snforge_std::{ + declare, ContractClassTrait, fs::{FileTrait, read_txt}, start_prank, stop_prank, CheatTarget, + start_warp, PrintTrait +}; use core::traits::{Into, TryInto}; use starknet::syscalls::deploy_syscall; use starknet::SyscallResultTrait; @@ -166,9 +166,329 @@ fn test_new_stake_detail_balance() { assert(stake_dispatcher.get_stake_balance() == (prev_stake + 6), Errors::WRONG_STAKE_BALANCE); } +#[test] +fn test_transfer_stake_token() { + let (staking_contract_address, bwc_contract_address, receipt_contract_address, _) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let prev_stake_contract_balance = bwc_dispatcher.balance_of(staking_contract_address); + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + + assert( + bwc_dispatcher.allowance(Account::user1(), staking_contract_address) == 4, + Errors::INVALID_ALLOWANCE + ); + assert( + bwc_dispatcher.balance_of(staking_contract_address) == prev_stake_contract_balance + 6, + Errors::INVALID_BALANCE + ); + stop_prank(CheatTarget::One(staking_contract_address)); +} + + +#[test] +fn test_transfer_receipt_token() { + let (staking_contract_address, bwc_contract_address, receipt_contract_address, _) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let prev_stake_contract_receipt_token_balance: u256 = receipt_dispatcher + .balance_of(staking_contract_address); + let prev_staker_receipt_token_balance: u256 = receipt_dispatcher.balance_of(Account::user1()); + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + assert( + receipt_dispatcher.balance_of(Account::user1()) == prev_staker_receipt_token_balance + 6, + Errors::INVALID_BALANCE + ); + stop_prank(CheatTarget::One(staking_contract_address)); +} + +#[test] +#[should_panic(expected: ('Withdraw amount not allowed',))] +fn test_invalid_withdrawal_amount() { + let (staking_contract_address, bwc_contract_address, receipt_contract_address, _) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + stake_dispatcher.withdraw(30); +} + + +#[test] +#[should_panic(expected: ('Not yet time to withdraw',))] +fn test_invalid_withdraw_time() { + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + stake_dispatcher.withdraw(5); +} + +#[test] +#[should_panic(expected: ('Not enough reward token to send',))] +fn test_insufficient_reward_token() { + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); + stake_dispatcher.withdraw(5); +} + +#[test] +fn test_sufficient_bwc_token_for_withdraw() { + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); + assert(bwc_dispatcher.balance_of(staking_contract_address) >= 6, Errors::INVALID_BALANCE); +} + +#[test] +fn test_sufficient_receipt_token_allowance_for_withdraw() { + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + + start_prank(CheatTarget::One(receipt_contract_address), Account::user1()); + receipt_dispatcher.approve(staking_contract_address, 6); + assert( + receipt_dispatcher.allowance(Account::user1(), staking_contract_address) >= 6, + Errors::INSUFFICIENT_BALANCE + ); +} + +#[test] +#[should_panic(expected: ('receipt tkn allowance too low',))] +fn test_insufficient_receipt_token_allowance_for_withdraw() { + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(reward_contract_address), Account::admin()); + reward_dispatcher.transfer(staking_contract_address, 50); + stop_prank(CheatTarget::One(reward_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + + start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); + stake_dispatcher.withdraw(6); +} + + +#[test] +fn test_withdraw() { + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(reward_contract_address), Account::admin()); + reward_dispatcher.transfer(staking_contract_address, 50); + stop_prank(CheatTarget::One(reward_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + + start_prank(CheatTarget::One(receipt_contract_address), Account::user1()); + receipt_dispatcher.approve(staking_contract_address, 6); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); + stake_dispatcher.withdraw(6); + + // Test that staker stake balance has been updated + assert(stake_dispatcher.get_stake_balance() == 0, Errors::INVALID_BALANCE); + + // Test that receipt tokens have removed from staker balance + assert(receipt_dispatcher.balance_of(Account::user1()) == 0, Errors::INVALID_BALANCE); + + // Test that reciept tokens have been returned to staking contract + assert(receipt_dispatcher.balance_of(staking_contract_address) == 20, Errors::INVALID_BALANCE); + + // Test that reward token has been sent to the staker + assert(reward_dispatcher.balance_of(Account::user1()) == 6, Errors::INVALID_BALANCE); + + // Test that stake token has been sent to the staker + assert(bwc_dispatcher.balance_of(Account::user1()) == 35, Errors::INVALID_BALANCE); +} mod Account { @@ -188,20 +508,22 @@ mod Account { } - ///////////////// - //CUSTOM ERRORS - ///////////////// - mod Errors { - const INSUFFICIENT_FUND: felt252 = 'STAKE: Insufficient fund'; - const INSUFFICIENT_BALANCE: felt252 = 'STAKE: Insufficient balance'; - const ADDRESS_ZERO: felt252 = 'STAKE: Address zero'; - const NOT_TOKEN_ADDRESS: felt252 = 'STAKE: Not token address'; - const ZERO_AMOUNT: felt252 = 'STAKE: Zero amount'; - const INSUFFICIENT_FUNDS: felt252 = 'STAKE: Insufficient funds'; - const LOW_CBWCRT_BALANCE: felt252 = 'STAKE: Low balance'; - const NOT_WITHDRAW_TIME: felt252 = 'STAKE: Not yet withdraw time'; - const LOW_CONTRACT_BALANCE: felt252 = 'STAKE: Low contract balance'; - const AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; - const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; - const WRONG_STAKE_BALANCE: felt252 = 'STAKE: Wrong stake balance'; - } \ No newline at end of file +///////////////// +//CUSTOM ERRORS +///////////////// +mod Errors { + const INSUFFICIENT_FUND: felt252 = 'STAKE: Insufficient fund'; + const INSUFFICIENT_BALANCE: felt252 = 'STAKE: Insufficient balance'; + const ADDRESS_ZERO: felt252 = 'STAKE: Address zero'; + const NOT_TOKEN_ADDRESS: felt252 = 'STAKE: Not token address'; + const ZERO_AMOUNT: felt252 = 'STAKE: Zero amount'; + const INSUFFICIENT_FUNDS: felt252 = 'STAKE: Insufficient funds'; + const LOW_CBWCRT_BALANCE: felt252 = 'STAKE: Low balance'; + const NOT_WITHDRAW_TIME: felt252 = 'STAKE: Not yet withdraw time'; + const LOW_CONTRACT_BALANCE: felt252 = 'STAKE: Low contract balance'; + const AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; + const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'Withdraw amount not allowed'; + const WRONG_STAKE_BALANCE: felt252 = 'STAKE: Wrong stake balance'; + const INVALID_BALANCE: felt252 = 'Invalid balance'; + const INVALID_ALLOWANCE: felt252 = 'Invalid allowance'; +}