mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
wasi: introduce initial WASI support
Co-authored-by: Gus Caplan <me@gus.host> Co-authored-by: Daniel Bevenius <daniel.bevenius@gmail.com> Co-authored-by: Jiawen Geng <technicalcute@gmail.com> Co-authored-by: Tobias Nießen <tniessen@tnie.de> Co-authored-by: Chengzhong Wu <legendecas@gmail.com> PR-URL: https://github.com/nodejs/node/pull/30258 Refs: https://github.com/nodejs/node/pull/27850 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Wyatt Preul <wpreul@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
This commit is contained in:
parent
73c837b1ae
commit
09b1228c3a
84 changed files with 12753 additions and 4 deletions
25
LICENSE
25
LICENSE
|
@ -1503,3 +1503,28 @@ The externally maintained libraries used by Node.js are:
|
|||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
"""
|
||||
|
||||
- uvwasi, located at deps/uvwasi, is licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Colin Ihrig and Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
|
21
deps/uvwasi/LICENSE
vendored
Normal file
21
deps/uvwasi/LICENSE
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Colin Ihrig and Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
13
deps/uvwasi/include/clocks.h
vendored
Normal file
13
deps/uvwasi/include/clocks.h
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef __UVWASI_CLOCKS_H__
|
||||
#define __UVWASI_CLOCKS_H__
|
||||
|
||||
#include "wasi_types.h"
|
||||
|
||||
uvwasi_errno_t uvwasi__clock_gettime_realtime(uvwasi_timestamp_t* time);
|
||||
uvwasi_errno_t uvwasi__clock_gettime_process_cputime(uvwasi_timestamp_t* time);
|
||||
uvwasi_errno_t uvwasi__clock_gettime_thread_cputime(uvwasi_timestamp_t* time);
|
||||
|
||||
uvwasi_errno_t uvwasi__clock_getres_process_cputime(uvwasi_timestamp_t* time);
|
||||
uvwasi_errno_t uvwasi__clock_getres_thread_cputime(uvwasi_timestamp_t* time);
|
||||
|
||||
#endif /* __UVWASI_CLOCKS_H__ */
|
60
deps/uvwasi/include/fd_table.h
vendored
Normal file
60
deps/uvwasi/include/fd_table.h
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
#ifndef __UVWASI_FD_TABLE_H__
|
||||
#define __UVWASI_FD_TABLE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "uv.h"
|
||||
#include "wasi_types.h"
|
||||
#include "uv_mapping.h"
|
||||
|
||||
/* TODO(cjihrig): PATH_MAX_BYTES shouldn't be stack allocated. On Windows, paths
|
||||
can be 32k long, and this PATH_MAX_BYTES is an artificial limitation. */
|
||||
#ifdef _WIN32
|
||||
/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
|
||||
# define PATH_MAX_BYTES (MAX_PATH * 4)
|
||||
#else
|
||||
# include <limits.h>
|
||||
# define PATH_MAX_BYTES (PATH_MAX)
|
||||
#endif
|
||||
|
||||
|
||||
struct uvwasi_fd_wrap_t {
|
||||
uvwasi_fd_t id;
|
||||
uv_file fd;
|
||||
char path[PATH_MAX_BYTES];
|
||||
char real_path[PATH_MAX_BYTES];
|
||||
uvwasi_filetype_t type;
|
||||
uvwasi_rights_t rights_base;
|
||||
uvwasi_rights_t rights_inheriting;
|
||||
int preopen;
|
||||
int valid;
|
||||
};
|
||||
|
||||
struct uvwasi_fd_table_t {
|
||||
struct uvwasi_fd_wrap_t* fds;
|
||||
uint32_t size;
|
||||
uint32_t used;
|
||||
};
|
||||
|
||||
uvwasi_errno_t uvwasi_fd_table_init(struct uvwasi_fd_table_t* table,
|
||||
uint32_t init_size);
|
||||
void uvwasi_fd_table_free(struct uvwasi_fd_table_t* table);
|
||||
uvwasi_errno_t uvwasi_fd_table_insert_preopen(struct uvwasi_fd_table_t* table,
|
||||
const uv_file fd,
|
||||
const char* path,
|
||||
const char* real_path);
|
||||
uvwasi_errno_t uvwasi_fd_table_insert_fd(struct uvwasi_fd_table_t* table,
|
||||
const uv_file fd,
|
||||
const int flags,
|
||||
const char* path,
|
||||
uvwasi_rights_t rights_base,
|
||||
uvwasi_rights_t rights_inheriting,
|
||||
struct uvwasi_fd_wrap_t* wrap);
|
||||
uvwasi_errno_t uvwasi_fd_table_get(const struct uvwasi_fd_table_t* table,
|
||||
const uvwasi_fd_t id,
|
||||
struct uvwasi_fd_wrap_t** wrap,
|
||||
uvwasi_rights_t rights_base,
|
||||
uvwasi_rights_t rights_inheriting);
|
||||
uvwasi_errno_t uvwasi_fd_table_remove(struct uvwasi_fd_table_t* table,
|
||||
const uvwasi_fd_t id);
|
||||
|
||||
#endif /* __UVWASI_FD_TABLE_H__ */
|
15
deps/uvwasi/include/uv_mapping.h
vendored
Normal file
15
deps/uvwasi/include/uv_mapping.h
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef __UVWASI_UV_MAPPING_H__
|
||||
#define __UVWASI_UV_MAPPING_H__
|
||||
|
||||
#include "uv.h"
|
||||
#include "wasi_types.h"
|
||||
|
||||
#define NANOS_PER_SEC 1000000000
|
||||
|
||||
uvwasi_errno_t uvwasi__translate_uv_error(int err);
|
||||
int uvwasi__translate_to_uv_signal(uvwasi_signal_t sig);
|
||||
uvwasi_timestamp_t uvwasi__timespec_to_timestamp(const uv_timespec_t* ts);
|
||||
uvwasi_filetype_t uvwasi__stat_to_filetype(const uv_stat_t* stat);
|
||||
void uvwasi__stat_to_filestat(const uv_stat_t* stat, uvwasi_filestat_t* fs);
|
||||
|
||||
#endif /* __UVWASI_UV_MAPPING_H__ */
|
252
deps/uvwasi/include/uvwasi.h
vendored
Normal file
252
deps/uvwasi/include/uvwasi.h
vendored
Normal file
|
@ -0,0 +1,252 @@
|
|||
#ifndef __UVWASI_H__
|
||||
#define __UVWASI_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "wasi_types.h"
|
||||
#include "uv_mapping.h"
|
||||
#include "fd_table.h"
|
||||
|
||||
#define UVWASI_VERSION_MAJOR 0
|
||||
#define UVWASI_VERSION_MINOR 0
|
||||
#define UVWASI_VERSION_PATCH 1
|
||||
#define UVWASI_VERSION_HEX ((UVWASI_VERSION_MAJOR << 16) | \
|
||||
(UVWASI_VERSION_MINOR << 8) | \
|
||||
(UVWASI_VERSION_PATCH))
|
||||
#define UVWASI_STRINGIFY(v) UVWASI_STRINGIFY_HELPER(v)
|
||||
#define UVWASI_STRINGIFY_HELPER(v) #v
|
||||
#define UVWASI_VERSION_STRING UVWASI_STRINGIFY(UVWASI_VERSION_MAJOR) "." \
|
||||
UVWASI_STRINGIFY(UVWASI_VERSION_MINOR) "." \
|
||||
UVWASI_STRINGIFY(UVWASI_VERSION_PATCH)
|
||||
|
||||
|
||||
typedef struct uvwasi_s {
|
||||
struct uvwasi_fd_table_t fds;
|
||||
size_t argc;
|
||||
char** argv;
|
||||
char* argv_buf;
|
||||
size_t argv_buf_size;
|
||||
size_t envc;
|
||||
char** env;
|
||||
char* env_buf;
|
||||
size_t env_buf_size;
|
||||
} uvwasi_t;
|
||||
|
||||
typedef struct uvwasi_preopen_s {
|
||||
char* mapped_path;
|
||||
char* real_path;
|
||||
} uvwasi_preopen_t;
|
||||
|
||||
typedef struct uvwasi_options_s {
|
||||
size_t fd_table_size;
|
||||
size_t preopenc;
|
||||
uvwasi_preopen_t* preopens;
|
||||
size_t argc;
|
||||
char** argv;
|
||||
char** envp;
|
||||
} uvwasi_options_t;
|
||||
|
||||
|
||||
// Embedder API.
|
||||
uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options);
|
||||
void uvwasi_destroy(uvwasi_t* uvwasi);
|
||||
uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi,
|
||||
const uvwasi_fd_t fd,
|
||||
uv_file new_host_fd);
|
||||
|
||||
|
||||
// WASI system call API.
|
||||
uvwasi_errno_t uvwasi_args_get(uvwasi_t* uvwasi, char** argv, char* argv_buf);
|
||||
uvwasi_errno_t uvwasi_args_sizes_get(uvwasi_t* uvwasi,
|
||||
size_t* argc,
|
||||
size_t* argv_buf_size);
|
||||
uvwasi_errno_t uvwasi_clock_res_get(uvwasi_t* uvwasi,
|
||||
uvwasi_clockid_t clock_id,
|
||||
uvwasi_timestamp_t* resolution);
|
||||
uvwasi_errno_t uvwasi_clock_time_get(uvwasi_t* uvwasi,
|
||||
uvwasi_clockid_t clock_id,
|
||||
uvwasi_timestamp_t precision,
|
||||
uvwasi_timestamp_t* time);
|
||||
uvwasi_errno_t uvwasi_environ_get(uvwasi_t* uvwasi,
|
||||
char** environment,
|
||||
char* environ_buf);
|
||||
uvwasi_errno_t uvwasi_environ_sizes_get(uvwasi_t* uvwasi,
|
||||
size_t* environ_count,
|
||||
size_t* environ_buf_size);
|
||||
uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_filesize_t offset,
|
||||
uvwasi_filesize_t len,
|
||||
uvwasi_advice_t advice);
|
||||
uvwasi_errno_t uvwasi_fd_allocate(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_filesize_t offset,
|
||||
uvwasi_filesize_t len);
|
||||
uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd);
|
||||
uvwasi_errno_t uvwasi_fd_datasync(uvwasi_t* uvwasi, uvwasi_fd_t fd);
|
||||
uvwasi_errno_t uvwasi_fd_fdstat_get(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_fdstat_t* buf);
|
||||
uvwasi_errno_t uvwasi_fd_fdstat_set_flags(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_fdflags_t flags);
|
||||
uvwasi_errno_t uvwasi_fd_fdstat_set_rights(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_rights_t fs_rights_base,
|
||||
uvwasi_rights_t fs_rights_inheriting
|
||||
);
|
||||
uvwasi_errno_t uvwasi_fd_filestat_get(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_filestat_t* buf);
|
||||
uvwasi_errno_t uvwasi_fd_filestat_set_size(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_filesize_t st_size);
|
||||
uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_timestamp_t st_atim,
|
||||
uvwasi_timestamp_t st_mtim,
|
||||
uvwasi_fstflags_t fst_flags);
|
||||
uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
const uvwasi_iovec_t* iovs,
|
||||
size_t iovs_len,
|
||||
uvwasi_filesize_t offset,
|
||||
size_t* nread);
|
||||
uvwasi_errno_t uvwasi_fd_prestat_get(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_prestat_t* buf);
|
||||
uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
char* path,
|
||||
size_t path_len);
|
||||
uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
const uvwasi_ciovec_t* iovs,
|
||||
size_t iovs_len,
|
||||
uvwasi_filesize_t offset,
|
||||
size_t* nwritten);
|
||||
uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
const uvwasi_iovec_t* iovs,
|
||||
size_t iovs_len,
|
||||
size_t* nread);
|
||||
uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
void* buf,
|
||||
size_t buf_len,
|
||||
uvwasi_dircookie_t cookie,
|
||||
size_t* bufused);
|
||||
uvwasi_errno_t uvwasi_fd_renumber(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t from,
|
||||
uvwasi_fd_t to);
|
||||
uvwasi_errno_t uvwasi_fd_seek(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_filedelta_t offset,
|
||||
uvwasi_whence_t whence,
|
||||
uvwasi_filesize_t* newoffset);
|
||||
uvwasi_errno_t uvwasi_fd_sync(uvwasi_t* uvwasi, uvwasi_fd_t fd);
|
||||
uvwasi_errno_t uvwasi_fd_tell(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_filesize_t* offset);
|
||||
uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
const uvwasi_ciovec_t* iovs,
|
||||
size_t iovs_len,
|
||||
size_t* nwritten);
|
||||
uvwasi_errno_t uvwasi_path_create_directory(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
const char* path,
|
||||
size_t path_len);
|
||||
uvwasi_errno_t uvwasi_path_filestat_get(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_lookupflags_t flags,
|
||||
const char* path,
|
||||
size_t path_len,
|
||||
uvwasi_filestat_t* buf);
|
||||
uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
uvwasi_lookupflags_t flags,
|
||||
const char* path,
|
||||
size_t path_len,
|
||||
uvwasi_timestamp_t st_atim,
|
||||
uvwasi_timestamp_t st_mtim,
|
||||
uvwasi_fstflags_t fst_flags);
|
||||
uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t old_fd,
|
||||
uvwasi_lookupflags_t old_flags,
|
||||
const char* old_path,
|
||||
size_t old_path_len,
|
||||
uvwasi_fd_t new_fd,
|
||||
const char* new_path,
|
||||
size_t new_path_len);
|
||||
uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t dirfd,
|
||||
uvwasi_lookupflags_t dirflags,
|
||||
const char* path,
|
||||
size_t path_len,
|
||||
uvwasi_oflags_t o_flags,
|
||||
uvwasi_rights_t fs_rights_base,
|
||||
uvwasi_rights_t fs_rights_inheriting,
|
||||
uvwasi_fdflags_t fs_flags,
|
||||
uvwasi_fd_t* fd);
|
||||
uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
const char* path,
|
||||
size_t path_len,
|
||||
char* buf,
|
||||
size_t buf_len,
|
||||
size_t* bufused);
|
||||
uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
const char* path,
|
||||
size_t path_len);
|
||||
uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t old_fd,
|
||||
const char* old_path,
|
||||
size_t old_path_len,
|
||||
uvwasi_fd_t new_fd,
|
||||
const char* new_path,
|
||||
size_t new_path_len);
|
||||
uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi,
|
||||
const char* old_path,
|
||||
size_t old_path_len,
|
||||
uvwasi_fd_t fd,
|
||||
const char* new_path,
|
||||
size_t new_path_len);
|
||||
uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t fd,
|
||||
const char* path,
|
||||
size_t path_len);
|
||||
uvwasi_errno_t uvwasi_poll_oneoff(uvwasi_t* uvwasi,
|
||||
const uvwasi_subscription_t* in,
|
||||
uvwasi_event_t* out,
|
||||
size_t nsubscriptions,
|
||||
size_t* nevents);
|
||||
uvwasi_errno_t uvwasi_proc_exit(uvwasi_t* uvwasi, uvwasi_exitcode_t rval);
|
||||
uvwasi_errno_t uvwasi_proc_raise(uvwasi_t* uvwasi, uvwasi_signal_t sig);
|
||||
uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, void* buf, size_t buf_len);
|
||||
uvwasi_errno_t uvwasi_sched_yield(uvwasi_t* uvwasi);
|
||||
uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t sock,
|
||||
const uvwasi_iovec_t* ri_data,
|
||||
size_t ri_data_len,
|
||||
uvwasi_riflags_t ri_flags,
|
||||
size_t* ro_datalen,
|
||||
uvwasi_roflags_t* ro_flags);
|
||||
uvwasi_errno_t uvwasi_sock_send(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t sock,
|
||||
const uvwasi_ciovec_t* si_data,
|
||||
size_t si_data_len,
|
||||
uvwasi_siflags_t si_flags,
|
||||
size_t* so_datalen);
|
||||
uvwasi_errno_t uvwasi_sock_shutdown(uvwasi_t* uvwasi,
|
||||
uvwasi_fd_t sock,
|
||||
uvwasi_sdflags_t how);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __UVWASI_H__ */
|
323
deps/uvwasi/include/wasi_types.h
vendored
Normal file
323
deps/uvwasi/include/wasi_types.h
vendored
Normal file
|
@ -0,0 +1,323 @@
|
|||
#ifndef __UVWASI_WASI_TYPES_H__
|
||||
#define __UVWASI_WASI_TYPES_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* API: https://github.com/WebAssembly/WASI/blob/master/phases/unstable/docs/wasi_unstable_preview0.md */
|
||||
|
||||
typedef uint8_t uvwasi_advice_t;
|
||||
#define UVWASI_ADVICE_NORMAL 0
|
||||
#define UVWASI_ADVICE_SEQUENTIAL 1
|
||||
#define UVWASI_ADVICE_RANDOM 2
|
||||
#define UVWASI_ADVICE_WILLNEED 3
|
||||
#define UVWASI_ADVICE_DONTNEED 4
|
||||
#define UVWASI_ADVICE_NOREUSE 5
|
||||
|
||||
typedef struct uvwasi_ciovec_s {
|
||||
const void* buf;
|
||||
size_t buf_len;
|
||||
} uvwasi_ciovec_t;
|
||||
|
||||
typedef uint32_t uvwasi_clockid_t;
|
||||
#define UVWASI_CLOCK_REALTIME 0
|
||||
#define UVWASI_CLOCK_MONOTONIC 1
|
||||
#define UVWASI_CLOCK_PROCESS_CPUTIME_ID 2
|
||||
#define UVWASI_CLOCK_THREAD_CPUTIME_ID 3
|
||||
|
||||
typedef uint64_t uvwasi_device_t;
|
||||
|
||||
typedef uint64_t uvwasi_dircookie_t;
|
||||
#define UVWASI_DIRCOOKIE_START 0
|
||||
|
||||
typedef uint16_t uvwasi_errno_t;
|
||||
#define UVWASI_ESUCCESS 0
|
||||
#define UVWASI_E2BIG 1
|
||||
#define UVWASI_EACCES 2
|
||||
#define UVWASI_EADDRINUSE 3
|
||||
#define UVWASI_EADDRNOTAVAIL 4
|
||||
#define UVWASI_EAFNOSUPPORT 5
|
||||
#define UVWASI_EAGAIN 6
|
||||
#define UVWASI_EALREADY 7
|
||||
#define UVWASI_EBADF 8
|
||||
#define UVWASI_EBADMSG 9
|
||||
#define UVWASI_EBUSY 10
|
||||
#define UVWASI_ECANCELED 11
|
||||
#define UVWASI_ECHILD 12
|
||||
#define UVWASI_ECONNABORTED 13
|
||||
#define UVWASI_ECONNREFUSED 14
|
||||
#define UVWASI_ECONNRESET 15
|
||||
#define UVWASI_EDEADLK 16
|
||||
#define UVWASI_EDESTADDRREQ 17
|
||||
#define UVWASI_EDOM 18
|
||||
#define UVWASI_EDQUOT 19
|
||||
#define UVWASI_EEXIST 20
|
||||
#define UVWASI_EFAULT 21
|
||||
#define UVWASI_EFBIG 22
|
||||
#define UVWASI_EHOSTUNREACH 23
|
||||
#define UVWASI_EIDRM 24
|
||||
#define UVWASI_EILSEQ 25
|
||||
#define UVWASI_EINPROGRESS 26
|
||||
#define UVWASI_EINTR 27
|
||||
#define UVWASI_EINVAL 28
|
||||
#define UVWASI_EIO 29
|
||||
#define UVWASI_EISCONN 30
|
||||
#define UVWASI_EISDIR 31
|
||||
#define UVWASI_ELOOP 32
|
||||
#define UVWASI_EMFILE 33
|
||||
#define UVWASI_EMLINK 34
|
||||
#define UVWASI_EMSGSIZE 35
|
||||
#define UVWASI_EMULTIHOP 36
|
||||
#define UVWASI_ENAMETOOLONG 37
|
||||
#define UVWASI_ENETDOWN 38
|
||||
#define UVWASI_ENETRESET 39
|
||||
#define UVWASI_ENETUNREACH 40
|
||||
#define UVWASI_ENFILE 41
|
||||
#define UVWASI_ENOBUFS 42
|
||||
#define UVWASI_ENODEV 43
|
||||
#define UVWASI_ENOENT 44
|
||||
#define UVWASI_ENOEXEC 45
|
||||
#define UVWASI_ENOLCK 46
|
||||
#define UVWASI_ENOLINK 47
|
||||
#define UVWASI_ENOMEM 48
|
||||
#define UVWASI_ENOMSG 49
|
||||
#define UVWASI_ENOPROTOOPT 50
|
||||
#define UVWASI_ENOSPC 51
|
||||
#define UVWASI_ENOSYS 52
|
||||
#define UVWASI_ENOTCONN 53
|
||||
#define UVWASI_ENOTDIR 54
|
||||
#define UVWASI_ENOTEMPTY 55
|
||||
#define UVWASI_ENOTRECOVERABLE 56
|
||||
#define UVWASI_ENOTSOCK 57
|
||||
#define UVWASI_ENOTSUP 58
|
||||
#define UVWASI_ENOTTY 59
|
||||
#define UVWASI_ENXIO 60
|
||||
#define UVWASI_EOVERFLOW 61
|
||||
#define UVWASI_EOWNERDEAD 62
|
||||
#define UVWASI_EPERM 63
|
||||
#define UVWASI_EPIPE 64
|
||||
#define UVWASI_EPROTO 65
|
||||
#define UVWASI_EPROTONOSUPPORT 66
|
||||
#define UVWASI_EPROTOTYPE 67
|
||||
#define UVWASI_ERANGE 68
|
||||
#define UVWASI_EROFS 69
|
||||
#define UVWASI_ESPIPE 70
|
||||
#define UVWASI_ESRCH 71
|
||||
#define UVWASI_ESTALE 72
|
||||
#define UVWASI_ETIMEDOUT 73
|
||||
#define UVWASI_ETXTBSY 74
|
||||
#define UVWASI_EXDEV 75
|
||||
#define UVWASI_ENOTCAPABLE 76
|
||||
|
||||
typedef uint16_t uvwasi_eventrwflags_t; /* Bitfield */
|
||||
#define UVWASI_EVENT_FD_READWRITE_HANGUP (1 << 0)
|
||||
|
||||
typedef uint8_t uvwasi_eventtype_t;
|
||||
#define UVWASI_EVENTTYPE_CLOCK 0
|
||||
#define UVWASI_EVENTTYPE_FD_READ 1
|
||||
#define UVWASI_EVENTTYPE_FD_WRITE 2
|
||||
|
||||
typedef uint32_t uvwasi_exitcode_t;
|
||||
|
||||
typedef uint32_t uvwasi_fd_t;
|
||||
|
||||
typedef uint16_t uvwasi_fdflags_t; /* Bitfield */
|
||||
#define UVWASI_FDFLAG_APPEND (1 << 0)
|
||||
#define UVWASI_FDFLAG_DSYNC (1 << 1)
|
||||
#define UVWASI_FDFLAG_NONBLOCK (1 << 2)
|
||||
#define UVWASI_FDFLAG_RSYNC (1 << 3)
|
||||
#define UVWASI_FDFLAG_SYNC (1 << 4)
|
||||
|
||||
typedef int64_t uvwasi_filedelta_t;
|
||||
|
||||
typedef uint64_t uvwasi_filesize_t;
|
||||
|
||||
typedef uint8_t uvwasi_filetype_t;
|
||||
#define UVWASI_FILETYPE_UNKNOWN 0
|
||||
#define UVWASI_FILETYPE_BLOCK_DEVICE 1
|
||||
#define UVWASI_FILETYPE_CHARACTER_DEVICE 2
|
||||
#define UVWASI_FILETYPE_DIRECTORY 3
|
||||
#define UVWASI_FILETYPE_REGULAR_FILE 4
|
||||
#define UVWASI_FILETYPE_SOCKET_DGRAM 5
|
||||
#define UVWASI_FILETYPE_SOCKET_STREAM 6
|
||||
#define UVWASI_FILETYPE_SYMBOLIC_LINK 7
|
||||
|
||||
typedef uint16_t uvwasi_fstflags_t; /* Bitfield */
|
||||
#define UVWASI_FILESTAT_SET_ATIM (1 << 0)
|
||||
#define UVWASI_FILESTAT_SET_ATIM_NOW (1 << 1)
|
||||
#define UVWASI_FILESTAT_SET_MTIM (1 << 2)
|
||||
#define UVWASI_FILESTAT_SET_MTIM_NOW (1 << 3)
|
||||
|
||||
typedef uint64_t uvwasi_inode_t;
|
||||
|
||||
typedef struct uvwasi_iovec_s {
|
||||
void* buf;
|
||||
size_t buf_len;
|
||||
} uvwasi_iovec_t;
|
||||
|
||||
typedef uint32_t uvwasi_linkcount_t;
|
||||
|
||||
typedef uint32_t uvwasi_lookupflags_t; /* Bitfield */
|
||||
#define UVWASI_LOOKUP_SYMLINK_FOLLOW (1 << 0)
|
||||
|
||||
typedef uint16_t uvwasi_oflags_t; /* Bitfield */
|
||||
#define UVWASI_O_CREAT (1 << 0)
|
||||
#define UVWASI_O_DIRECTORY (1 << 1)
|
||||
#define UVWASI_O_EXCL (1 << 2)
|
||||
#define UVWASI_O_TRUNC (1 << 3)
|
||||
|
||||
typedef uint8_t uvwasi_preopentype_t;
|
||||
#define UVWASI_PREOPENTYPE_DIR 0
|
||||
|
||||
typedef struct uvwasi_prestat_s {
|
||||
uvwasi_preopentype_t pr_type;
|
||||
union uvwasi_prestat_u {
|
||||
struct uvwasi_prestat_dir_t {
|
||||
size_t pr_name_len;
|
||||
} dir;
|
||||
} u;
|
||||
} uvwasi_prestat_t;
|
||||
|
||||
typedef uint16_t uvwasi_riflags_t; /* Bitfield */
|
||||
#define UVWASI_SOCK_RECV_PEEK (1 << 0)
|
||||
#define UVWASI_SOCK_RECV_WAITALL (1 << 1)
|
||||
|
||||
typedef uint64_t uvwasi_rights_t; /* Bitfield */
|
||||
#define UVWASI_RIGHT_FD_DATASYNC (1 << 0)
|
||||
#define UVWASI_RIGHT_FD_READ (1 << 1)
|
||||
#define UVWASI_RIGHT_FD_SEEK (1 << 2)
|
||||
#define UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS (1 << 3)
|
||||
#define UVWASI_RIGHT_FD_SYNC (1 << 4)
|
||||
#define UVWASI_RIGHT_FD_TELL (1 << 5)
|
||||
#define UVWASI_RIGHT_FD_WRITE (1 << 6)
|
||||
#define UVWASI_RIGHT_FD_ADVISE (1 << 7)
|
||||
#define UVWASI_RIGHT_FD_ALLOCATE (1 << 8)
|
||||
#define UVWASI_RIGHT_PATH_CREATE_DIRECTORY (1 << 9)
|
||||
#define UVWASI_RIGHT_PATH_CREATE_FILE (1 << 10)
|
||||
#define UVWASI_RIGHT_PATH_LINK_SOURCE (1 << 11)
|
||||
#define UVWASI_RIGHT_PATH_LINK_TARGET (1 << 12)
|
||||
#define UVWASI_RIGHT_PATH_OPEN (1 << 13)
|
||||
#define UVWASI_RIGHT_FD_READDIR (1 << 14)
|
||||
#define UVWASI_RIGHT_PATH_READLINK (1 << 15)
|
||||
#define UVWASI_RIGHT_PATH_RENAME_SOURCE (1 << 16)
|
||||
#define UVWASI_RIGHT_PATH_RENAME_TARGET (1 << 17)
|
||||
#define UVWASI_RIGHT_PATH_FILESTAT_GET (1 << 18)
|
||||
#define UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE (1 << 19)
|
||||
#define UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES (1 << 20)
|
||||
#define UVWASI_RIGHT_FD_FILESTAT_GET (1 << 21)
|
||||
#define UVWASI_RIGHT_FD_FILESTAT_SET_SIZE (1 << 22)
|
||||
#define UVWASI_RIGHT_FD_FILESTAT_SET_TIMES (1 << 23)
|
||||
#define UVWASI_RIGHT_PATH_SYMLINK (1 << 24)
|
||||
#define UVWASI_RIGHT_PATH_REMOVE_DIRECTORY (1 << 25)
|
||||
#define UVWASI_RIGHT_PATH_UNLINK_FILE (1 << 26)
|
||||
#define UVWASI_RIGHT_POLL_FD_READWRITE (1 << 27)
|
||||
#define UVWASI_RIGHT_SOCK_SHUTDOWN (1 << 28)
|
||||
|
||||
typedef uint16_t uvwasi_roflags_t; /* Bitfield */
|
||||
#define UVWASI_SOCK_RECV_DATA_TRUNCATED (1 << 0)
|
||||
|
||||
typedef uint8_t uvwasi_sdflags_t; /* Bitfield */
|
||||
#define UVWASI_SHUT_RD (1 << 0)
|
||||
#define UVWASI_SHUT_WR (1 << 1)
|
||||
|
||||
typedef uint16_t uvwasi_siflags_t; /* Bitfield */
|
||||
|
||||
typedef uint8_t uvwasi_signal_t;
|
||||
#define UVWASI_SIGHUP 1
|
||||
#define UVWASI_SIGINT 2
|
||||
#define UVWASI_SIGQUIT 3
|
||||
#define UVWASI_SIGILL 4
|
||||
#define UVWASI_SIGTRAP 5
|
||||
#define UVWASI_SIGABRT 6
|
||||
#define UVWASI_SIGBUS 7
|
||||
#define UVWASI_SIGFPE 8
|
||||
#define UVWASI_SIGKILL 9
|
||||
#define UVWASI_SIGUSR1 10
|
||||
#define UVWASI_SIGSEGV 11
|
||||
#define UVWASI_SIGUSR2 12
|
||||
#define UVWASI_SIGPIPE 13
|
||||
#define UVWASI_SIGALRM 14
|
||||
#define UVWASI_SIGTERM 15
|
||||
#define UVWASI_SIGCHLD 16
|
||||
#define UVWASI_SIGCONT 17
|
||||
#define UVWASI_SIGSTOP 18
|
||||
#define UVWASI_SIGTSTP 19
|
||||
#define UVWASI_SIGTTIN 20
|
||||
#define UVWASI_SIGTTOU 21
|
||||
#define UVWASI_SIGURG 22
|
||||
#define UVWASI_SIGXCPU 23
|
||||
#define UVWASI_SIGXFSZ 24
|
||||
#define UVWASI_SIGVTALRM 25
|
||||
#define UVWASI_SIGPROF 26
|
||||
#define UVWASI_SIGWINCH 27
|
||||
#define UVWASI_SIGPOLL 28
|
||||
#define UVWASI_SIGPWR 29
|
||||
#define UVWASI_SIGSYS 30
|
||||
|
||||
typedef uint16_t uvwasi_subclockflags_t; /* Bitfield */
|
||||
#define UVWASI_SUBSCRIPTION_CLOCK_ABSTIME (1 << 0)
|
||||
|
||||
typedef uint64_t uvwasi_timestamp_t;
|
||||
|
||||
typedef uint64_t uvwasi_userdata_t;
|
||||
|
||||
typedef struct uvwasi_subscription_s {
|
||||
uvwasi_userdata_t userdata;
|
||||
uvwasi_eventtype_t type;
|
||||
union {
|
||||
struct {
|
||||
uvwasi_userdata_t identifier;
|
||||
uvwasi_clockid_t clock_id;
|
||||
uvwasi_timestamp_t timeout;
|
||||
uvwasi_timestamp_t precision;
|
||||
uvwasi_subclockflags_t flags;
|
||||
} clock;
|
||||
struct {
|
||||
uvwasi_fd_t fd;
|
||||
} fd_readwrite;
|
||||
} u;
|
||||
} uvwasi_subscription_t;
|
||||
|
||||
typedef struct uvwasi_dirent_s {
|
||||
uvwasi_dircookie_t d_next;
|
||||
uvwasi_inode_t d_ino;
|
||||
uint32_t d_namlen;
|
||||
uvwasi_filetype_t d_type;
|
||||
} uvwasi_dirent_t;
|
||||
|
||||
typedef struct uvwasi_fdstat_s {
|
||||
uvwasi_filetype_t fs_filetype;
|
||||
uvwasi_fdflags_t fs_flags;
|
||||
uvwasi_rights_t fs_rights_base;
|
||||
uvwasi_rights_t fs_rights_inheriting;
|
||||
} uvwasi_fdstat_t;
|
||||
|
||||
typedef struct uvwasi_filestat_s {
|
||||
uvwasi_device_t st_dev;
|
||||
uvwasi_inode_t st_ino;
|
||||
uvwasi_filetype_t st_filetype;
|
||||
uvwasi_linkcount_t st_nlink;
|
||||
uvwasi_filesize_t st_size;
|
||||
uvwasi_timestamp_t st_atim;
|
||||
uvwasi_timestamp_t st_mtim;
|
||||
uvwasi_timestamp_t st_ctim;
|
||||
} uvwasi_filestat_t;
|
||||
|
||||
typedef struct uvwasi_event_s {
|
||||
uvwasi_userdata_t userdata;
|
||||
uvwasi_errno_t error;
|
||||
uvwasi_eventtype_t type;
|
||||
union {
|
||||
struct {
|
||||
uvwasi_filesize_t nbytes;
|
||||
uvwasi_eventrwflags_t flags;
|
||||
} fd_readwrite;
|
||||
} u;
|
||||
} uvwasi_event_t;
|
||||
|
||||
typedef uint8_t uvwasi_whence_t;
|
||||
#define UVWASI_WHENCE_CUR 0
|
||||
#define UVWASI_WHENCE_END 1
|
||||
#define UVWASI_WHENCE_SET 2
|
||||
|
||||
#endif /* __UVWASI_WASI_TYPES_H__ */
|
194
deps/uvwasi/src/clocks.c
vendored
Normal file
194
deps/uvwasi/src/clocks.c
vendored
Normal file
|
@ -0,0 +1,194 @@
|
|||
#ifndef _WIN32
|
||||
# include <errno.h>
|
||||
# include <sys/time.h>
|
||||
# include <sys/resource.h>
|
||||
# include <time.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "uv.h"
|
||||
#include "wasi_types.h"
|
||||
#include "uv_mapping.h"
|
||||
|
||||
|
||||
#define UVWASI__WIN_TIME_AND_RETURN(handle, time) \
|
||||
do { \
|
||||
FILETIME create; \
|
||||
FILETIME exit; \
|
||||
FILETIME system; \
|
||||
FILETIME user; \
|
||||
SYSTEMTIME sys_system; \
|
||||
SYSTEMTIME sys_user; \
|
||||
if (0 == GetProcessTimes((handle), &create, &exit, &system, &user)) { \
|
||||
return uvwasi__translate_uv_error( \
|
||||
uv_translate_sys_error(GetLastError()) \
|
||||
); \
|
||||
} \
|
||||
\
|
||||
if (0 == FileTimeToSystemTime(&system, &sys_system)) { \
|
||||
return uvwasi__translate_uv_error( \
|
||||
uv_translate_sys_error(GetLastError()) \
|
||||
); \
|
||||
} \
|
||||
\
|
||||
if (0 == FileTimeToSystemTime(&user, &sys_user)) { \
|
||||
return uvwasi__translate_uv_error( \
|
||||
uv_translate_sys_error(GetLastError()) \
|
||||
); \
|
||||
} \
|
||||
\
|
||||
(time) = (((sys_system.wHour * 3600) + (sys_system.wMinute * 60) + \
|
||||
sys_system.wSecond) * NANOS_PER_SEC) + \
|
||||
(sys_system.wMilliseconds * 1000000) + \
|
||||
(((sys_user.wHour * 3600) + (sys_user.wMinute * 60) + \
|
||||
sys_user.wSecond) * NANOS_PER_SEC) + \
|
||||
(sys_user.wMilliseconds * 1000000); \
|
||||
return UVWASI_ESUCCESS; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define UVWASI__CLOCK_GETTIME_AND_RETURN(clk, time) \
|
||||
do { \
|
||||
struct timespec ts; \
|
||||
if (0 != clock_gettime((clk), &ts)) \
|
||||
return uvwasi__translate_uv_error(uv_translate_sys_error(errno)); \
|
||||
(time) = (ts.tv_sec * NANOS_PER_SEC) + ts.tv_nsec; \
|
||||
return UVWASI_ESUCCESS; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define UVWASI__GETRUSAGE_AND_RETURN(who, time) \
|
||||
do { \
|
||||
struct rusage ru; \
|
||||
if (0 != getrusage((who), &ru)) \
|
||||
return uvwasi__translate_uv_error(uv_translate_sys_error(errno)); \
|
||||
(time) = (ru.ru_utime.tv_sec * NANOS_PER_SEC) + \
|
||||
(ru.ru_utime.tv_usec * 1000) + \
|
||||
(ru.ru_stime.tv_sec * NANOS_PER_SEC) + \
|
||||
(ru.ru_stime.tv_usec * 1000); \
|
||||
return UVWASI_ESUCCESS; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define UVWASI__OSX_THREADTIME_AND_RETURN(time) \
|
||||
do { \
|
||||
mach_port_t thread; \
|
||||
thread_basic_info_data_t info; \
|
||||
mach_msg_type_number_t count; \
|
||||
count = THREAD_BASIC_INFO_COUNT; \
|
||||
thread = pthread_mach_thread_np(pthread_self()); \
|
||||
if (KERN_SUCCESS != thread_info(thread, \
|
||||
THREAD_BASIC_INFO, \
|
||||
(thread_info_t) &info, \
|
||||
&count)) { \
|
||||
return UVWASI_ENOSYS; \
|
||||
} \
|
||||
(time) = (info.user_time.seconds * NANOS_PER_SEC) + \
|
||||
(info.user_time.microseconds * 1000) + \
|
||||
(info.system_time.seconds * NANOS_PER_SEC) + \
|
||||
(info.system_time.microseconds * 1000); \
|
||||
return UVWASI_ESUCCESS; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define UVWASI__WIN_GETRES_AND_RETURN(time) \
|
||||
do { \
|
||||
/* The GetProcessTimes() docs claim a resolution of 100 ns. */ \
|
||||
(time) = 100; \
|
||||
return UVWASI_ESUCCESS; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define UVWASI__CLOCK_GETRES_AND_RETURN(clk, time) \
|
||||
do { \
|
||||
struct timespec ts; \
|
||||
/* Try calling clock_getres(). If it doesn't succeed, then default to \
|
||||
1000000. We implement all of the clocks, and some platforms (such as \
|
||||
SmartOS) don't support all of the clocks, even though they define \
|
||||
the constants for them. */ \
|
||||
if (0 != clock_getres((clk), &ts)) \
|
||||
(time) = 1000000; \
|
||||
else \
|
||||
(time) = (ts.tv_sec * NANOS_PER_SEC) + ts.tv_nsec; \
|
||||
return UVWASI_ESUCCESS; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define UVWASI__SLOW_GETRES_AND_RETURN(time) \
|
||||
do { \
|
||||
/* Assume a "worst case" of 1000000 ns resolution. */ \
|
||||
(time) = 1000000; \
|
||||
return UVWASI_ESUCCESS; \
|
||||
} while (0)
|
||||
|
||||
|
||||
uvwasi_errno_t uvwasi__clock_gettime_realtime(uvwasi_timestamp_t* time) {
|
||||
uv_timeval64_t tv;
|
||||
int r;
|
||||
|
||||
r = uv_gettimeofday(&tv);
|
||||
if (r != 0)
|
||||
return uvwasi__translate_uv_error(r);
|
||||
|
||||
*time = (tv.tv_sec * NANOS_PER_SEC) + (tv.tv_usec * 1000);
|
||||
return UVWASI_ESUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uvwasi_errno_t uvwasi__clock_gettime_process_cputime(uvwasi_timestamp_t* time) {
|
||||
#if defined(_WIN32)
|
||||
UVWASI__WIN_TIME_AND_RETURN(GetCurrentProcess(), *time);
|
||||
#elif defined(CLOCK_PROCESS_CPUTIME_ID) && \
|
||||
!defined(__APPLE__) && \
|
||||
!defined(__sun)
|
||||
UVWASI__CLOCK_GETTIME_AND_RETURN(CLOCK_PROCESS_CPUTIME_ID, *time);
|
||||
#else
|
||||
UVWASI__GETRUSAGE_AND_RETURN(RUSAGE_SELF, *time);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
uvwasi_errno_t uvwasi__clock_gettime_thread_cputime(uvwasi_timestamp_t* time) {
|
||||
#if defined(_WIN32)
|
||||
UVWASI__WIN_TIME_AND_RETURN(GetCurrentThread(), *time);
|
||||
#elif defined(__APPLE__)
|
||||
UVWASI__OSX_THREADTIME_AND_RETURN(*time);
|
||||
#elif defined(CLOCK_THREAD_CPUTIME_ID) && !defined(__sun)
|
||||
UVWASI__CLOCK_GETTIME_AND_RETURN(CLOCK_THREAD_CPUTIME_ID, *time);
|
||||
#else
|
||||
# if defined(RUSAGE_LWP)
|
||||
UVWASI__GETRUSAGE_AND_RETURN(RUSAGE_LWP, *time);
|
||||
# elif defined(RUSAGE_THREAD)
|
||||
UVWASI__GETRUSAGE_AND_RETURN(RUSAGE_THREAD, *time);
|
||||
# else
|
||||
return UVWASI_ENOSYS;
|
||||
# endif /* RUSAGE_LWP */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
uvwasi_errno_t uvwasi__clock_getres_process_cputime(uvwasi_timestamp_t* time) {
|
||||
#if defined(_WIN32)
|
||||
UVWASI__WIN_GETRES_AND_RETURN(*time);
|
||||
#elif defined(CLOCK_PROCESS_CPUTIME_ID) && \
|
||||
!defined(__APPLE__) && \
|
||||
!defined(__sun)
|
||||
UVWASI__CLOCK_GETRES_AND_RETURN(CLOCK_PROCESS_CPUTIME_ID, *time);
|
||||
#else
|
||||
UVWASI__SLOW_GETRES_AND_RETURN(*time);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
uvwasi_errno_t uvwasi__clock_getres_thread_cputime(uvwasi_timestamp_t* time) {
|
||||
#if defined(_WIN32)
|
||||
UVWASI__WIN_GETRES_AND_RETURN(*time);
|
||||
#elif defined(__APPLE__)
|
||||
UVWASI__SLOW_GETRES_AND_RETURN(*time);
|
||||
#elif defined(CLOCK_THREAD_CPUTIME_ID) && !defined(__sun)
|
||||
UVWASI__CLOCK_GETTIME_AND_RETURN(CLOCK_THREAD_CPUTIME_ID, *time);
|
||||
#elif defined(RUSAGE_THREAD) || defined(RUSAGE_LWP)
|
||||
UVWASI__SLOW_GETRES_AND_RETURN(*time);
|
||||
#else
|
||||
return UVWASI_ENOSYS;
|
||||
#endif
|
||||
}
|
422
deps/uvwasi/src/fd_table.c
vendored
Normal file
422
deps/uvwasi/src/fd_table.c
vendored
Normal file
|
@ -0,0 +1,422 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <sys/types.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "uv.h"
|
||||
#include "fd_table.h"
|
||||
#include "wasi_types.h"
|
||||
#include "uv_mapping.h"
|
||||
|
||||
|
||||
#define UVWASI__RIGHTS_ALL (UVWASI_RIGHT_FD_DATASYNC | \
|
||||
UVWASI_RIGHT_FD_READ | \
|
||||
UVWASI_RIGHT_FD_SEEK | \
|
||||
UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
|
||||
UVWASI_RIGHT_FD_SYNC | \
|
||||
UVWASI_RIGHT_FD_TELL | \
|
||||
UVWASI_RIGHT_FD_WRITE | \
|
||||
UVWASI_RIGHT_FD_ADVISE | \
|
||||
UVWASI_RIGHT_FD_ALLOCATE | \
|
||||
UVWASI_RIGHT_PATH_CREATE_DIRECTORY | \
|
||||
UVWASI_RIGHT_PATH_CREATE_FILE | \
|
||||
UVWASI_RIGHT_PATH_LINK_SOURCE | \
|
||||
UVWASI_RIGHT_PATH_LINK_TARGET | \
|
||||
UVWASI_RIGHT_PATH_OPEN | \
|
||||
UVWASI_RIGHT_FD_READDIR | \
|
||||
UVWASI_RIGHT_PATH_READLINK | \
|
||||
UVWASI_RIGHT_PATH_RENAME_SOURCE | \
|
||||
UVWASI_RIGHT_PATH_RENAME_TARGET | \
|
||||
UVWASI_RIGHT_PATH_FILESTAT_GET | \
|
||||
UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE | \
|
||||
UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES | \
|
||||
UVWASI_RIGHT_FD_FILESTAT_GET | \
|
||||
UVWASI_RIGHT_FD_FILESTAT_SET_TIMES | \
|
||||
UVWASI_RIGHT_FD_FILESTAT_SET_SIZE | \
|
||||
UVWASI_RIGHT_PATH_SYMLINK | \
|
||||
UVWASI_RIGHT_PATH_UNLINK_FILE | \
|
||||
UVWASI_RIGHT_PATH_REMOVE_DIRECTORY | \
|
||||
UVWASI_RIGHT_POLL_FD_READWRITE | \
|
||||
UVWASI_RIGHT_SOCK_SHUTDOWN)
|
||||
|
||||
#define UVWASI__RIGHTS_BLOCK_DEVICE_BASE UVWASI__RIGHTS_ALL
|
||||
#define UVWASI__RIGHTS_BLOCK_DEVICE_INHERITING UVWASI__RIGHTS_ALL
|
||||
|
||||
#define UVWASI__RIGHTS_CHARACTER_DEVICE_BASE UVWASI__RIGHTS_ALL
|
||||
#define UVWASI__RIGHTS_CHARACTER_DEVICE_INHERITING UVWASI__RIGHTS_ALL
|
||||
|
||||
#define UVWASI__RIGHTS_REGULAR_FILE_BASE (UVWASI_RIGHT_FD_DATASYNC | \
|
||||
UVWASI_RIGHT_FD_READ | \
|
||||
UVWASI_RIGHT_FD_SEEK | \
|
||||
UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
|
||||
UVWASI_RIGHT_FD_SYNC | \
|
||||
UVWASI_RIGHT_FD_TELL | \
|
||||
UVWASI_RIGHT_FD_WRITE | \
|
||||
UVWASI_RIGHT_FD_ADVISE | \
|
||||
UVWASI_RIGHT_FD_ALLOCATE | \
|
||||
UVWASI_RIGHT_FD_FILESTAT_GET | \
|
||||
UVWASI_RIGHT_FD_FILESTAT_SET_SIZE | \
|
||||
UVWASI_RIGHT_FD_FILESTAT_SET_TIMES |\
|
||||
UVWASI_RIGHT_POLL_FD_READWRITE)
|
||||
#define UVWASI__RIGHTS_REGULAR_FILE_INHERITING 0
|
||||
|
||||
#define UVWASI__RIGHTS_DIRECTORY_BASE (UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
|
||||
UVWASI_RIGHT_FD_SYNC | \
|
||||
UVWASI_RIGHT_FD_ADVISE | \
|
||||
UVWASI_RIGHT_PATH_CREATE_DIRECTORY | \
|
||||
UVWASI_RIGHT_PATH_CREATE_FILE | \
|
||||
UVWASI_RIGHT_PATH_LINK_SOURCE | \
|
||||
UVWASI_RIGHT_PATH_LINK_TARGET | \
|
||||
UVWASI_RIGHT_PATH_OPEN | \
|
||||
UVWASI_RIGHT_FD_READDIR | \
|
||||
UVWASI_RIGHT_PATH_READLINK | \
|
||||
UVWASI_RIGHT_PATH_RENAME_SOURCE | \
|
||||
UVWASI_RIGHT_PATH_RENAME_TARGET | \
|
||||
UVWASI_RIGHT_PATH_FILESTAT_GET | \
|
||||
UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE | \
|
||||
UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES | \
|
||||
UVWASI_RIGHT_FD_FILESTAT_GET | \
|
||||
UVWASI_RIGHT_FD_FILESTAT_SET_TIMES | \
|
||||
UVWASI_RIGHT_PATH_SYMLINK | \
|
||||
UVWASI_RIGHT_PATH_UNLINK_FILE | \
|
||||
UVWASI_RIGHT_PATH_REMOVE_DIRECTORY | \
|
||||
UVWASI_RIGHT_POLL_FD_READWRITE)
|
||||
#define UVWASI__RIGHTS_DIRECTORY_INHERITING (UVWASI__RIGHTS_DIRECTORY_BASE | \
|
||||
UVWASI__RIGHTS_REGULAR_FILE_BASE)
|
||||
|
||||
#define UVWASI__RIGHTS_SOCKET_BASE (UVWASI_RIGHT_FD_READ | \
|
||||
UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
|
||||
UVWASI_RIGHT_FD_WRITE | \
|
||||
UVWASI_RIGHT_FD_FILESTAT_GET | \
|
||||
UVWASI_RIGHT_POLL_FD_READWRITE | \
|
||||
UVWASI_RIGHT_SOCK_SHUTDOWN)
|
||||
#define UVWASI__RIGHTS_SOCKET_INHERITING UVWASI__RIGHTS_ALL;
|
||||
|
||||
#define UVWASI__RIGHTS_TTY_BASE (UVWASI_RIGHT_FD_READ | \
|
||||
UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
|
||||
UVWASI_RIGHT_FD_WRITE | \
|
||||
UVWASI_RIGHT_FD_FILESTAT_GET | \
|
||||
UVWASI_RIGHT_POLL_FD_READWRITE)
|
||||
#define UVWASI__RIGHTS_TTY_INHERITING 0
|
||||
|
||||
static uvwasi_errno_t uvwasi__get_type_and_rights(uv_file fd,
|
||||
int flags,
|
||||
uvwasi_filetype_t* type,
|
||||
uvwasi_rights_t* rights_base,
|
||||
uvwasi_rights_t* rights_inheriting) {
|
||||
uv_fs_t req;
|
||||
uvwasi_filetype_t filetype;
|
||||
int read_or_write_only;
|
||||
int r;
|
||||
|
||||
r = uv_fs_fstat(NULL, &req, fd, NULL);
|
||||
filetype = uvwasi__stat_to_filetype(&req.statbuf);
|
||||
uv_fs_req_cleanup(&req);
|
||||
if (r != 0)
|
||||
return uvwasi__translate_uv_error(r);
|
||||
|
||||
*type = filetype;
|
||||
switch (filetype) {
|
||||
case UVWASI_FILETYPE_REGULAR_FILE:
|
||||
*rights_base = UVWASI__RIGHTS_REGULAR_FILE_BASE;
|
||||
*rights_inheriting = UVWASI__RIGHTS_REGULAR_FILE_INHERITING;
|
||||
break;
|
||||
|
||||
case UVWASI_FILETYPE_DIRECTORY:
|
||||
*rights_base = UVWASI__RIGHTS_DIRECTORY_BASE;
|
||||
*rights_inheriting = UVWASI__RIGHTS_DIRECTORY_INHERITING;
|
||||
break;
|
||||
|
||||
/* uvwasi__stat_to_filetype() cannot differentiate socket types. It only
|
||||
returns UVWASI_FILETYPE_SOCKET_STREAM. */
|
||||
case UVWASI_FILETYPE_SOCKET_STREAM:
|
||||
if (uv_guess_handle(fd) == UV_UDP)
|
||||
*type = UVWASI_FILETYPE_SOCKET_DGRAM;
|
||||
|
||||
*rights_base = UVWASI__RIGHTS_SOCKET_BASE;
|
||||
*rights_inheriting = UVWASI__RIGHTS_SOCKET_INHERITING;
|
||||
break;
|
||||
|
||||
case UVWASI_FILETYPE_CHARACTER_DEVICE:
|
||||
if (uv_guess_handle(fd) == UV_TTY) {
|
||||
*rights_base = UVWASI__RIGHTS_TTY_BASE;
|
||||
*rights_inheriting = UVWASI__RIGHTS_TTY_INHERITING;
|
||||
} else {
|
||||
*rights_base = UVWASI__RIGHTS_CHARACTER_DEVICE_BASE;
|
||||
*rights_inheriting = UVWASI__RIGHTS_CHARACTER_DEVICE_INHERITING;
|
||||
}
|
||||
break;
|
||||
|
||||
case UVWASI_FILETYPE_BLOCK_DEVICE:
|
||||
*rights_base = UVWASI__RIGHTS_BLOCK_DEVICE_BASE;
|
||||
*rights_inheriting = UVWASI__RIGHTS_BLOCK_DEVICE_INHERITING;
|
||||
break;
|
||||
|
||||
default:
|
||||
*rights_base = 0;
|
||||
*rights_inheriting = 0;
|
||||
}
|
||||
|
||||
if (*type == UVWASI_FILETYPE_UNKNOWN)
|
||||
return UVWASI_EINVAL;
|
||||
|
||||
/* Disable read/write bits depending on access mode. */
|
||||
read_or_write_only = flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
|
||||
|
||||
if (read_or_write_only == UV_FS_O_RDONLY)
|
||||
*rights_base &= ~UVWASI_RIGHT_FD_WRITE;
|
||||
else if (read_or_write_only == UV_FS_O_WRONLY)
|
||||
*rights_base &= ~UVWASI_RIGHT_FD_READ;
|
||||
|
||||
return UVWASI_ESUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static uvwasi_errno_t uvwasi__fd_table_insert(struct uvwasi_fd_table_t* table,
|
||||
uv_file fd,
|
||||
const char* mapped_path,
|
||||
const char* real_path,
|
||||
uvwasi_filetype_t type,
|
||||
uvwasi_rights_t rights_base,
|
||||
uvwasi_rights_t rights_inheriting,
|
||||
int preopen,
|
||||
struct uvwasi_fd_wrap_t** wrap) {
|
||||
struct uvwasi_fd_wrap_t* entry;
|
||||
struct uvwasi_fd_wrap_t* new_fds;
|
||||
uint32_t new_size;
|
||||
int index;
|
||||
uint32_t i;
|
||||
|
||||
/* Check that there is room for a new item. If there isn't, grow the table. */
|
||||
if (table->used >= table->size) {
|
||||
new_size = table->size * 2;
|
||||
new_fds = realloc(table->fds, new_size * sizeof(*new_fds));
|
||||
if (new_fds == NULL)
|
||||
return UVWASI_ENOMEM;
|
||||
|
||||
for (i = table->size; i < new_size; ++i)
|
||||
new_fds[i].valid = 0;
|
||||
|
||||
index = table->size;
|
||||
table->fds = new_fds;
|
||||
table->size = new_size;
|
||||
} else {
|
||||
/* The table is big enough, so find an empty slot for the new data. */
|
||||
index = -1;
|
||||
for (i = 0; i < table->size; ++i) {
|
||||
if (table->fds[i].valid != 1) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* index should never be -1. */
|
||||
if (index == -1)
|
||||
return UVWASI_ENOSPC;
|
||||
}
|
||||
|
||||
entry = &table->fds[index];
|
||||
entry->id = index;
|
||||
entry->fd = fd;
|
||||
strcpy(entry->path, mapped_path);
|
||||
strcpy(entry->real_path, real_path);
|
||||
entry->type = type;
|
||||
entry->rights_base = rights_base;
|
||||
entry->rights_inheriting = rights_inheriting;
|
||||
entry->preopen = preopen;
|
||||
entry->valid = 1;
|
||||
table->used++;
|
||||
|
||||
if (wrap != NULL)
|
||||
*wrap = entry;
|
||||
|
||||
return UVWASI_ESUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uvwasi_errno_t uvwasi_fd_table_init(struct uvwasi_fd_table_t* table,
|
||||
uint32_t init_size) {
|
||||
struct uvwasi_fd_wrap_t* wrap;
|
||||
uvwasi_filetype_t type;
|
||||
uvwasi_rights_t base;
|
||||
uvwasi_rights_t inheriting;
|
||||
uvwasi_errno_t err;
|
||||
uvwasi_fd_t i;
|
||||
|
||||
/* Require an initial size of at least three to store the stdio FDs. */
|
||||
if (table == NULL || init_size < 3)
|
||||
return UVWASI_EINVAL;
|
||||
|
||||
table->used = 0;
|
||||
table->size = init_size;
|
||||
table->fds = calloc(init_size, sizeof(struct uvwasi_fd_wrap_t));
|
||||
|
||||
if (table->fds == NULL)
|
||||
return UVWASI_ENOMEM;
|
||||
|
||||
/* Create the stdio FDs. */
|
||||
for (i = 0; i < 3; ++i) {
|
||||
err = uvwasi__get_type_and_rights(i,
|
||||
UV_FS_O_RDWR,
|
||||
&type,
|
||||
&base,
|
||||
&inheriting);
|
||||
if (err != UVWASI_ESUCCESS)
|
||||
goto error_exit;
|
||||
|
||||
err = uvwasi__fd_table_insert(table,
|
||||
i,
|
||||
"",
|
||||
"",
|
||||
type,
|
||||
base,
|
||||
inheriting,
|
||||
0,
|
||||
&wrap);
|
||||
if (err != UVWASI_ESUCCESS)
|
||||
goto error_exit;
|
||||
|
||||
if (wrap->id != i || wrap->id != (uvwasi_fd_t) wrap->fd) {
|
||||
err = UVWASI_EBADF;
|
||||
goto error_exit;
|
||||
}
|
||||
}
|
||||
|
||||
return UVWASI_ESUCCESS;
|
||||
error_exit:
|
||||
uvwasi_fd_table_free(table);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void uvwasi_fd_table_free(struct uvwasi_fd_table_t* table) {
|
||||
if (table == NULL)
|
||||
return;
|
||||
|
||||
free(table->fds);
|
||||
table->fds = NULL;
|
||||
table->size = 0;
|
||||
table->used = 0;
|
||||
}
|
||||
|
||||
|
||||
uvwasi_errno_t uvwasi_fd_table_insert_preopen(struct uvwasi_fd_table_t* table,
|
||||
const uv_file fd,
|
||||
const char* path,
|
||||
const char* real_path) {
|
||||
uvwasi_filetype_t type;
|
||||
uvwasi_rights_t base;
|
||||
uvwasi_rights_t inheriting;
|
||||
uvwasi_errno_t err;
|
||||
|
||||
if (table == NULL || path == NULL || real_path == NULL)
|
||||
return UVWASI_EINVAL;
|
||||
|
||||
err = uvwasi__get_type_and_rights(fd, 0, &type, &base, &inheriting);
|
||||
if (err != UVWASI_ESUCCESS)
|
||||
return err;
|
||||
|
||||
if (type != UVWASI_FILETYPE_DIRECTORY)
|
||||
return UVWASI_ENOTDIR;
|
||||
|
||||
err = uvwasi__fd_table_insert(table,
|
||||
fd,
|
||||
path,
|
||||
real_path,
|
||||
UVWASI_FILETYPE_DIRECTORY,
|
||||
UVWASI__RIGHTS_DIRECTORY_BASE,
|
||||
UVWASI__RIGHTS_DIRECTORY_INHERITING,
|
||||
1,
|
||||
NULL);
|
||||
if (err != UVWASI_ESUCCESS)
|
||||
return err;
|
||||
|
||||
return UVWASI_ESUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uvwasi_errno_t uvwasi_fd_table_insert_fd(struct uvwasi_fd_table_t* table,
|
||||
const uv_file fd,
|
||||
const int flags,
|
||||
const char* path,
|
||||
uvwasi_rights_t rights_base,
|
||||
uvwasi_rights_t rights_inheriting,
|
||||
struct uvwasi_fd_wrap_t* wrap) {
|
||||
struct uvwasi_fd_wrap_t* fd_wrap;
|
||||
uvwasi_filetype_t type;
|
||||
uvwasi_rights_t max_base;
|
||||
uvwasi_rights_t max_inheriting;
|
||||
uvwasi_errno_t r;
|
||||
|
||||
if (table == NULL || path == NULL || wrap == NULL)
|
||||
return UVWASI_EINVAL;
|
||||
|
||||
r = uvwasi__get_type_and_rights(fd, flags, &type, &max_base, &max_inheriting);
|
||||
if (r != UVWASI_ESUCCESS)
|
||||
return r;
|
||||
|
||||
r = uvwasi__fd_table_insert(table,
|
||||
fd,
|
||||
path,
|
||||
path,
|
||||
type,
|
||||
rights_base & max_base,
|
||||
rights_inheriting & max_inheriting,
|
||||
0,
|
||||
&fd_wrap);
|
||||
if (r != UVWASI_ESUCCESS)
|
||||
return r;
|
||||
|
||||
*wrap = *fd_wrap;
|
||||
return UVWASI_ESUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uvwasi_errno_t uvwasi_fd_table_get(const struct uvwasi_fd_table_t* table,
|
||||
const uvwasi_fd_t id,
|
||||
struct uvwasi_fd_wrap_t** wrap,
|
||||
uvwasi_rights_t rights_base,
|
||||
uvwasi_rights_t rights_inheriting) {
|
||||
struct uvwasi_fd_wrap_t* entry;
|
||||
|
||||
if (table == NULL || wrap == NULL)
|
||||
return UVWASI_EINVAL;
|
||||
if (id >= table->size)
|
||||
return UVWASI_EBADF;
|
||||
|
||||
entry = &table->fds[id];
|
||||
|
||||
if (entry->valid != 1 || entry->id != id)
|
||||
return UVWASI_EBADF;
|
||||
|
||||
/* Validate that the fd has the necessary rights. */
|
||||
if ((~entry->rights_base & rights_base) != 0 ||
|
||||
(~entry->rights_inheriting & rights_inheriting) != 0)
|
||||
return UVWASI_ENOTCAPABLE;
|
||||
|
||||
*wrap = entry;
|
||||
return UVWASI_ESUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uvwasi_errno_t uvwasi_fd_table_remove(struct uvwasi_fd_table_t* table,
|
||||
const uvwasi_fd_t id) {
|
||||
struct uvwasi_fd_wrap_t* entry;
|
||||
|
||||
if (table == NULL)
|
||||
return UVWASI_EINVAL;
|
||||
if (id >= table->size)
|
||||
return UVWASI_EBADF;
|
||||
|
||||
entry = &table->fds[id];
|
||||
|
||||
if (entry->valid != 1 || entry->id != id)
|
||||
return UVWASI_EBADF;
|
||||
|
||||
entry->valid = 0;
|
||||
table->used--;
|
||||
return UVWASI_ESUCCESS;
|
||||
}
|
243
deps/uvwasi/src/uv_mapping.c
vendored
Normal file
243
deps/uvwasi/src/uv_mapping.c
vendored
Normal file
|
@ -0,0 +1,243 @@
|
|||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <sys/types.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "uv.h"
|
||||
#include "wasi_types.h"
|
||||
#include "uv_mapping.h"
|
||||
|
||||
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
|
||||
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
|
||||
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISCHR) && defined(S_IFMT) && defined(S_IFCHR)
|
||||
# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISLNK) && defined(S_IFMT) && defined(S_IFLNK)
|
||||
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
|
||||
|
||||
uvwasi_errno_t uvwasi__translate_uv_error(int err) {
|
||||
switch (err) {
|
||||
case UV_E2BIG: return UVWASI_E2BIG;
|
||||
case UV_EACCES: return UVWASI_EACCES;
|
||||
case UV_EADDRINUSE: return UVWASI_EADDRINUSE;
|
||||
case UV_EADDRNOTAVAIL: return UVWASI_EADDRNOTAVAIL;
|
||||
case UV_EAFNOSUPPORT: return UVWASI_EAFNOSUPPORT;
|
||||
case UV_EAGAIN: return UVWASI_EAGAIN;
|
||||
case UV_EALREADY: return UVWASI_EALREADY;
|
||||
case UV_EBADF: return UVWASI_EBADF;
|
||||
case UV_EBUSY: return UVWASI_EBUSY;
|
||||
case UV_ECANCELED: return UVWASI_ECANCELED;
|
||||
case UV_ECONNABORTED: return UVWASI_ECONNABORTED;
|
||||
case UV_ECONNREFUSED: return UVWASI_ECONNREFUSED;
|
||||
case UV_ECONNRESET: return UVWASI_ECONNRESET;
|
||||
case UV_EDESTADDRREQ: return UVWASI_EDESTADDRREQ;
|
||||
case UV_EEXIST: return UVWASI_EEXIST;
|
||||
case UV_EFAULT: return UVWASI_EFAULT;
|
||||
case UV_EFBIG: return UVWASI_EFBIG;
|
||||
case UV_EHOSTUNREACH: return UVWASI_EHOSTUNREACH;
|
||||
case UV_EINTR: return UVWASI_EINTR;
|
||||
case UV_EINVAL: return UVWASI_EINVAL;
|
||||
case UV_EIO: return UVWASI_EIO;
|
||||
case UV_EISCONN: return UVWASI_EISCONN;
|
||||
case UV_EISDIR: return UVWASI_EISDIR;
|
||||
case UV_ELOOP: return UVWASI_ELOOP;
|
||||
case UV_EMFILE: return UVWASI_EMFILE;
|
||||
case UV_EMLINK: return UVWASI_EMLINK;
|
||||
case UV_EMSGSIZE: return UVWASI_EMSGSIZE;
|
||||
case UV_ENAMETOOLONG: return UVWASI_ENAMETOOLONG;
|
||||
case UV_ENETDOWN: return UVWASI_ENETDOWN;
|
||||
case UV_ENETUNREACH: return UVWASI_ENETUNREACH;
|
||||
case UV_ENFILE: return UVWASI_ENFILE;
|
||||
case UV_ENOBUFS: return UVWASI_ENOBUFS;
|
||||
case UV_ENODEV: return UVWASI_ENODEV;
|
||||
case UV_ENOENT: return UVWASI_ENOENT;
|
||||
case UV_ENOMEM: return UVWASI_ENOMEM;
|
||||
case UV_ENOPROTOOPT: return UVWASI_ENOPROTOOPT;
|
||||
case UV_ENOSPC: return UVWASI_ENOSPC;
|
||||
case UV_ENOSYS: return UVWASI_ENOSYS;
|
||||
case UV_ENOTCONN: return UVWASI_ENOTCONN;
|
||||
case UV_ENOTDIR: return UVWASI_ENOTDIR;
|
||||
/* On at least some AIX machines, ENOTEMPTY and EEXIST are equivalent. */
|
||||
#if ENOTEMPTY != EEXIST
|
||||
case UV_ENOTEMPTY: return UVWASI_ENOTEMPTY;
|
||||
#endif /* ENOTEMPTY != EEXIST */
|
||||
case UV_ENOTSOCK: return UVWASI_ENOTSOCK;
|
||||
case UV_ENOTSUP: return UVWASI_ENOTSUP;
|
||||
case UV_ENXIO: return UVWASI_ENXIO;
|
||||
case UV_EPERM: return UVWASI_EPERM;
|
||||
case UV_EPIPE: return UVWASI_EPIPE;
|
||||
case UV_EPROTO: return UVWASI_EPROTO;
|
||||
case UV_EPROTONOSUPPORT: return UVWASI_EPROTONOSUPPORT;
|
||||
case UV_EPROTOTYPE: return UVWASI_EPROTOTYPE;
|
||||
case UV_ERANGE: return UVWASI_ERANGE;
|
||||
case UV_EROFS: return UVWASI_EROFS;
|
||||
case UV_ESPIPE: return UVWASI_ESPIPE;
|
||||
case UV_ESRCH: return UVWASI_ESRCH;
|
||||
case UV_ETIMEDOUT: return UVWASI_ETIMEDOUT;
|
||||
case UV_ETXTBSY: return UVWASI_ETXTBSY;
|
||||
case UV_EXDEV: return UVWASI_EXDEV;
|
||||
case 0: return UVWASI_ESUCCESS;
|
||||
/* The following libuv error codes have no corresponding WASI error code:
|
||||
UV_EAI_ADDRFAMILY, UV_EAI_AGAIN, UV_EAI_BADFLAGS, UV_EAI_BADHINTS,
|
||||
UV_EAI_CANCELED, UV_EAI_FAIL, UV_EAI_FAMILY, UV_EAI_MEMORY,
|
||||
UV_EAI_NODATA, UV_EAI_NONAME, UV_EAI_OVERFLOW, UV_EAI_PROTOCOL,
|
||||
UV_EAI_SERVICE, UV_EAI_SOCKTYPE, UV_ECHARSET, UV_ENONET, UV_EOF,
|
||||
UV_ESHUTDOWN, UV_UNKNOWN
|
||||
*/
|
||||
default:
|
||||
/* libuv errors are < 0 */
|
||||
if (err > 0)
|
||||
return err;
|
||||
|
||||
return UVWASI_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uvwasi__translate_to_uv_signal(uvwasi_signal_t sig) {
|
||||
switch (sig) {
|
||||
#ifdef SIGABRT
|
||||
case UVWASI_SIGABRT: return SIGABRT;
|
||||
#endif
|
||||
#ifdef SIGALRM
|
||||
case UVWASI_SIGALRM: return SIGALRM;
|
||||
#endif
|
||||
#ifdef SIGBUS
|
||||
case UVWASI_SIGBUS: return SIGBUS;
|
||||
#endif
|
||||
#ifdef SIGCHLD
|
||||
case UVWASI_SIGCHLD: return SIGCHLD;
|
||||
#endif
|
||||
#ifdef SIGCONT
|
||||
case UVWASI_SIGCONT: return SIGCONT;
|
||||
#endif
|
||||
#ifdef SIGFPE
|
||||
case UVWASI_SIGFPE: return SIGFPE;
|
||||
#endif
|
||||
#ifdef SIGHUP
|
||||
case UVWASI_SIGHUP: return SIGHUP;
|
||||
#endif
|
||||
#ifdef SIGILL
|
||||
case UVWASI_SIGILL: return SIGILL;
|
||||
#endif
|
||||
#ifdef SIGINT
|
||||
case UVWASI_SIGINT: return SIGINT;
|
||||
#endif
|
||||
#ifdef SIGKILL
|
||||
case UVWASI_SIGKILL: return SIGKILL;
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
case UVWASI_SIGPIPE: return SIGPIPE;
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
case UVWASI_SIGQUIT: return SIGQUIT;
|
||||
#endif
|
||||
#ifdef SIGSEGV
|
||||
case UVWASI_SIGSEGV: return SIGSEGV;
|
||||
#endif
|
||||
#ifdef SIGSTOP
|
||||
case UVWASI_SIGSTOP: return SIGSTOP;
|
||||
#endif
|
||||
#ifdef SIGSYS
|
||||
case UVWASI_SIGSYS: return SIGSYS;
|
||||
#endif
|
||||
#ifdef SIGTERM
|
||||
case UVWASI_SIGTERM: return SIGTERM;
|
||||
#endif
|
||||
#ifdef SIGTRAP
|
||||
case UVWASI_SIGTRAP: return SIGTRAP;
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
case UVWASI_SIGTSTP: return SIGTSTP;
|
||||
#endif
|
||||
#ifdef SIGTTIN
|
||||
case UVWASI_SIGTTIN: return SIGTTIN;
|
||||
#endif
|
||||
#ifdef SIGTTOU
|
||||
case UVWASI_SIGTTOU: return SIGTTOU;
|
||||
#endif
|
||||
#ifdef SIGURG
|
||||
case UVWASI_SIGURG: return SIGURG;
|
||||
#endif
|
||||
#ifdef SIGUSR1
|
||||
case UVWASI_SIGUSR1: return SIGUSR1;
|
||||
#endif
|
||||
#ifdef SIGUSR2
|
||||
case UVWASI_SIGUSR2: return SIGUSR2;
|
||||
#endif
|
||||
#ifdef SIGVTALRM
|
||||
case UVWASI_SIGVTALRM: return SIGVTALRM;
|
||||
#endif
|
||||
#ifdef SIGXCPU
|
||||
case UVWASI_SIGXCPU: return SIGXCPU;
|
||||
#endif
|
||||
#ifdef SIGXFSZ
|
||||
case UVWASI_SIGXFSZ: return SIGXFSZ;
|
||||
#endif
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uvwasi_timestamp_t uvwasi__timespec_to_timestamp(const uv_timespec_t* ts) {
|
||||
/* TODO(cjihrig): Handle overflow. */
|
||||
return (uvwasi_timestamp_t) ts->tv_sec * NANOS_PER_SEC + ts->tv_nsec;
|
||||
}
|
||||
|
||||
|
||||
uvwasi_filetype_t uvwasi__stat_to_filetype(const uv_stat_t* stat) {
|
||||
uint64_t mode;
|
||||
|
||||
mode = stat->st_mode;
|
||||
|
||||
if (S_ISREG(mode))
|
||||
return UVWASI_FILETYPE_REGULAR_FILE;
|
||||
|
||||
if (S_ISDIR(mode))
|
||||
return UVWASI_FILETYPE_DIRECTORY;
|
||||
|
||||
if (S_ISCHR(mode))
|
||||
return UVWASI_FILETYPE_CHARACTER_DEVICE;
|
||||
|
||||
if (S_ISLNK(mode))
|
||||
return UVWASI_FILETYPE_SYMBOLIC_LINK;
|
||||
|
||||
#ifdef S_ISSOCK
|
||||
if (S_ISSOCK(mode))
|
||||
return UVWASI_FILETYPE_SOCKET_STREAM;
|
||||
#endif /* S_ISSOCK */
|
||||
|
||||
#ifdef S_ISFIFO
|
||||
if (S_ISFIFO(mode))
|
||||
return UVWASI_FILETYPE_SOCKET_STREAM;
|
||||
#endif /* S_ISFIFO */
|
||||
|
||||
#ifdef S_ISBLK
|
||||
if (S_ISBLK(mode))
|
||||
return UVWASI_FILETYPE_BLOCK_DEVICE;
|
||||
#endif /* S_ISBLK */
|
||||
|
||||
return UVWASI_FILETYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
void uvwasi__stat_to_filestat(const uv_stat_t* stat, uvwasi_filestat_t* fs) {
|
||||
fs->st_dev = stat->st_dev;
|
||||
fs->st_ino = stat->st_ino;
|
||||
fs->st_nlink = stat->st_nlink;
|
||||
fs->st_size = stat->st_size;
|
||||
fs->st_filetype = uvwasi__stat_to_filetype(stat);
|
||||
fs->st_atim = uvwasi__timespec_to_timestamp(&stat->st_atim);
|
||||
fs->st_mtim = uvwasi__timespec_to_timestamp(&stat->st_mtim);
|
||||
fs->st_ctim = uvwasi__timespec_to_timestamp(&stat->st_ctim);
|
||||
}
|
1918
deps/uvwasi/src/uvwasi.c
vendored
Normal file
1918
deps/uvwasi/src/uvwasi.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
25
deps/uvwasi/uvwasi.gyp
vendored
Normal file
25
deps/uvwasi/uvwasi.gyp
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'uvwasi',
|
||||
'type': 'static_library',
|
||||
'cflags': ['-fvisibility=hidden'],
|
||||
'xcode_settings': {
|
||||
'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
|
||||
},
|
||||
'include_dirs': ['include'],
|
||||
'sources': [
|
||||
'src/clocks.c',
|
||||
'src/fd_table.c',
|
||||
'src/uv_mapping.c',
|
||||
'src/uvwasi.c',
|
||||
],
|
||||
'dependencies': [
|
||||
'../uv/uv.gyp:libuv',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': ['include']
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
|
@ -230,6 +230,13 @@ added: v9.6.0
|
|||
|
||||
Enable experimental ES Module support in the `vm` module.
|
||||
|
||||
### `--experimental-wasi-unstable-preview0`
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
Enable experimental WebAssembly System Interface (WASI) support.
|
||||
|
||||
### `--experimental-wasm-modules`
|
||||
<!-- YAML
|
||||
added: v12.3.0
|
||||
|
@ -1048,6 +1055,7 @@ Node.js options that are allowed are:
|
|||
* `--experimental-report`
|
||||
* `--experimental-resolve-self`
|
||||
* `--experimental-vm-modules`
|
||||
* `--experimental-wasi-unstable-preview0`
|
||||
* `--experimental-wasm-modules`
|
||||
* `--force-context-aware`
|
||||
* `--force-fips`
|
||||
|
|
|
@ -1992,6 +1992,11 @@ The fulfilled value of a linking promise is not a `vm.Module` object.
|
|||
The current module's status does not allow for this operation. The specific
|
||||
meaning of the error depends on the specific function.
|
||||
|
||||
<a id="ERR_WASI_ALREADY_STARTED"></a>
|
||||
### ERR_WASI_ALREADY_STARTED
|
||||
|
||||
The WASI instance has already started.
|
||||
|
||||
<a id="ERR_WORKER_INVALID_EXEC_ARGV"></a>
|
||||
### ERR_WORKER_INVALID_EXEC_ARGV
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
* [Utilities](util.html)
|
||||
* [V8](v8.html)
|
||||
* [VM](vm.html)
|
||||
* [WASI](wasi.html)
|
||||
* [Worker Threads](worker_threads.html)
|
||||
* [Zlib](zlib.html)
|
||||
|
||||
|
|
90
doc/api/wasi.md
Normal file
90
doc/api/wasi.md
Normal file
|
@ -0,0 +1,90 @@
|
|||
# WebAssembly System Interface (WASI)
|
||||
|
||||
<!--introduced_in=REPLACEME-->
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
The WASI API provides an implementation of the [WebAssembly System Interface][]
|
||||
specification. WASI gives sandboxed WebAssembly applications access to the
|
||||
underlying operating system via a collection of POSIX-like functions.
|
||||
|
||||
```js
|
||||
'use strict';
|
||||
const fs = require('fs');
|
||||
const { WASI } = require('wasi');
|
||||
const wasi = new WASI({
|
||||
args: process.argv,
|
||||
env: process.env,
|
||||
preopens: {
|
||||
'/sandbox': '/some/real/path/that/wasm/can/access'
|
||||
}
|
||||
});
|
||||
const importObject = { wasi_unstable: wasi.wasiImport };
|
||||
|
||||
(async () => {
|
||||
const wasm = await WebAssembly.compile(fs.readFileSync('./binary.wasm'));
|
||||
const instance = await WebAssembly.instantiate(wasm, importObject);
|
||||
|
||||
wasi.start(instance);
|
||||
})();
|
||||
```
|
||||
|
||||
The `--experimental-wasi-unstable-preview0` and `--experimental-wasm-bigint`
|
||||
CLI arguments are needed for the previous example to run.
|
||||
|
||||
## Class: WASI
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
The `WASI` class provides the WASI system call API and additional convenience
|
||||
methods for working with WASI-based applications. Each `WASI` instance
|
||||
represents a distinct sandbox environment. For security purposes, each `WASI`
|
||||
instance must have its command line arguments, environment variables, and
|
||||
sandbox directory structure configured explicitly.
|
||||
|
||||
### new WASI(\[options\])
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
* `options` {Object}
|
||||
* `args` {Array} An array of strings that the WebAssembly application will
|
||||
see as command line arguments. The first argument is the virtual path to the
|
||||
WASI command itself. **Default:** `[]`.
|
||||
* `env` {Object} An object similar to `process.env` that the WebAssembly
|
||||
application will see as its environment. **Default:** `{}`.
|
||||
* `preopens` {Object} This object represents the WebAssembly application's
|
||||
sandbox directory structure. The string keys of `preopens` are treated as
|
||||
directories within the sandbox. The corresponding values in `preopens` are
|
||||
the real paths to those directories on the host machine.
|
||||
|
||||
### wasi.start(instance)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
* `instance` {WebAssembly.Instance}
|
||||
|
||||
Attempt to begin execution of `instance` by invoking its `_start()` export.
|
||||
If `instance` does not contain a `_start()` export, then `start()` attempts to
|
||||
invoke the `__wasi_unstable_reactor_start()` export. If neither of those exports
|
||||
is present on `instance`, then `start()` does nothing.
|
||||
|
||||
`start()` requires that `instance` exports a [`WebAssembly.Memory`][] named
|
||||
`memory`. If `instance` does not have a `memory` export an exception is thrown.
|
||||
|
||||
### wasi.wasiImport
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
* {Object}
|
||||
|
||||
`wasiImport` is an object that implements the WASI system call API. This object
|
||||
should be passed as the `wasi_unstable` import during the instantiation of a
|
||||
[`WebAssembly.Instance`][].
|
||||
|
||||
[`WebAssembly.Instance`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance
|
||||
[`WebAssembly.Memory`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory
|
||||
[WebAssembly System Interface]: https://wasi.dev/
|
|
@ -141,6 +141,9 @@ Enable experimental support for a package to load itself.
|
|||
.It Fl -experimental-vm-modules
|
||||
Enable experimental ES module support in VM module.
|
||||
.
|
||||
.It Fl -experimental-wasi-unstable-preview0
|
||||
Enable experimental WebAssembly System Interface support.
|
||||
.
|
||||
.It Fl -experimental-wasm-modules
|
||||
Enable experimental WebAssembly module support.
|
||||
.
|
||||
|
|
|
@ -157,6 +157,9 @@ function NativeModule(id) {
|
|||
this.loaded = false;
|
||||
this.loading = false;
|
||||
this.canBeRequiredByUsers = !id.startsWith('internal/');
|
||||
|
||||
if (id === 'wasi')
|
||||
this.canBeRequiredByUsers = !!internalBinding('config').experimentalWasi;
|
||||
}
|
||||
|
||||
// To be called during pre-execution when --expose-internals is on.
|
||||
|
|
|
@ -1229,6 +1229,7 @@ E('ERR_VM_MODULE_LINKING_ERRORED',
|
|||
E('ERR_VM_MODULE_NOT_MODULE',
|
||||
'Provided module is not an instance of Module', Error);
|
||||
E('ERR_VM_MODULE_STATUS', 'Module status %s', Error);
|
||||
E('ERR_WASI_ALREADY_STARTED', 'WASI instance has already started', Error);
|
||||
E('ERR_WORKER_INVALID_EXEC_ARGV', (errors) =>
|
||||
`Initiated Worker with invalid execArgv flags: ${errors.join(', ')}`,
|
||||
Error);
|
||||
|
|
|
@ -117,6 +117,11 @@ const builtinLibs = [
|
|||
'v8', 'vm', 'worker_threads', 'zlib'
|
||||
];
|
||||
|
||||
if (internalBinding('config').experimentalWasi) {
|
||||
builtinLibs.push('wasi');
|
||||
builtinLibs.sort();
|
||||
}
|
||||
|
||||
if (typeof internalBinding('inspector').open === 'function') {
|
||||
builtinLibs.push('inspector');
|
||||
builtinLibs.sort();
|
||||
|
|
105
lib/wasi.js
Normal file
105
lib/wasi.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
'use strict';
|
||||
/* global WebAssembly */
|
||||
const {
|
||||
ArrayIsArray,
|
||||
ArrayPrototypeForEach,
|
||||
ArrayPrototypeMap,
|
||||
FunctionPrototypeBind,
|
||||
ObjectKeys
|
||||
} = primordials;
|
||||
const {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_WASI_ALREADY_STARTED
|
||||
} = require('internal/errors').codes;
|
||||
const { emitExperimentalWarning } = require('internal/util');
|
||||
const { WASI: _WASI } = internalBinding('wasi');
|
||||
const kSetMemory = Symbol('setMemory');
|
||||
const kStarted = Symbol('started');
|
||||
|
||||
emitExperimentalWarning('WASI');
|
||||
|
||||
|
||||
class WASI {
|
||||
constructor(options = {}) {
|
||||
if (options === null || typeof options !== 'object')
|
||||
throw new ERR_INVALID_ARG_TYPE('options', 'object', options);
|
||||
|
||||
// eslint-disable-next-line prefer-const
|
||||
let { args, env, preopens } = options;
|
||||
|
||||
if (ArrayIsArray(args))
|
||||
args = ArrayPrototypeMap(args, (arg) => { return String(arg); });
|
||||
else if (args === undefined)
|
||||
args = [];
|
||||
else
|
||||
throw new ERR_INVALID_ARG_TYPE('options.args', 'Array', args);
|
||||
|
||||
const envPairs = [];
|
||||
|
||||
if (env !== null && typeof env === 'object') {
|
||||
for (const key in env) {
|
||||
const value = env[key];
|
||||
if (value !== undefined)
|
||||
envPairs.push(`${key}=${value}`);
|
||||
}
|
||||
} else if (env !== undefined) {
|
||||
throw new ERR_INVALID_ARG_TYPE('options.env', 'Object', env);
|
||||
}
|
||||
|
||||
const preopenArray = [];
|
||||
|
||||
if (typeof preopens === 'object' && preopens !== null) {
|
||||
ArrayPrototypeForEach(ObjectKeys(preopens), (key) => {
|
||||
preopenArray.push(String(key));
|
||||
preopenArray.push(String(preopens[key]));
|
||||
});
|
||||
} else if (preopens !== undefined) {
|
||||
throw new ERR_INVALID_ARG_TYPE('options.preopens', 'Object', preopens);
|
||||
}
|
||||
|
||||
const wrap = new _WASI(args, envPairs, preopenArray);
|
||||
|
||||
for (const prop in wrap) {
|
||||
wrap[prop] = FunctionPrototypeBind(wrap[prop], wrap);
|
||||
}
|
||||
|
||||
this[kSetMemory] = wrap._setMemory;
|
||||
delete wrap._setMemory;
|
||||
this.wasiImport = wrap;
|
||||
this[kStarted] = false;
|
||||
}
|
||||
|
||||
start(instance) {
|
||||
if (!(instance instanceof WebAssembly.Instance)) {
|
||||
throw new ERR_INVALID_ARG_TYPE(
|
||||
'instance', 'WebAssembly.Instance', instance);
|
||||
}
|
||||
|
||||
const exports = instance.exports;
|
||||
|
||||
if (exports === null || typeof exports !== 'object')
|
||||
throw new ERR_INVALID_ARG_TYPE('instance.exports', 'Object', exports);
|
||||
|
||||
const { memory } = exports;
|
||||
|
||||
if (!(memory instanceof WebAssembly.Memory)) {
|
||||
throw new ERR_INVALID_ARG_TYPE(
|
||||
'instance.exports.memory', 'WebAssembly.Memory', memory);
|
||||
}
|
||||
|
||||
if (this[kStarted]) {
|
||||
throw new ERR_WASI_ALREADY_STARTED();
|
||||
}
|
||||
|
||||
this[kStarted] = true;
|
||||
this[kSetMemory](memory);
|
||||
|
||||
if (exports._start)
|
||||
exports._start();
|
||||
else if (exports.__wasi_unstable_reactor_start)
|
||||
exports.__wasi_unstable_reactor_start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = { WASI };
|
19
node.gyp
19
node.gyp
|
@ -82,6 +82,7 @@
|
|||
'lib/util.js',
|
||||
'lib/v8.js',
|
||||
'lib/vm.js',
|
||||
'lib/wasi.js',
|
||||
'lib/worker_threads.js',
|
||||
'lib/zlib.js',
|
||||
'lib/internal/assert.js',
|
||||
|
@ -321,7 +322,10 @@
|
|||
'src/node_main.cc'
|
||||
],
|
||||
|
||||
'dependencies': [ 'deps/histogram/histogram.gyp:histogram' ],
|
||||
'dependencies': [
|
||||
'deps/histogram/histogram.gyp:histogram',
|
||||
'deps/uvwasi/uvwasi.gyp:uvwasi',
|
||||
],
|
||||
|
||||
'msvs_settings': {
|
||||
'VCLinkerTool': {
|
||||
|
@ -495,7 +499,10 @@
|
|||
'src',
|
||||
'<(SHARED_INTERMEDIATE_DIR)' # for node_natives.h
|
||||
],
|
||||
'dependencies': [ 'deps/histogram/histogram.gyp:histogram' ],
|
||||
'dependencies': [
|
||||
'deps/histogram/histogram.gyp:histogram',
|
||||
'deps/uvwasi/uvwasi.gyp:uvwasi',
|
||||
],
|
||||
|
||||
'sources': [
|
||||
'src/api/async_resource.cc',
|
||||
|
@ -560,6 +567,7 @@
|
|||
'src/node_url.cc',
|
||||
'src/node_util.cc',
|
||||
'src/node_v8.cc',
|
||||
'src/node_wasi.cc',
|
||||
'src/node_watchdog.cc',
|
||||
'src/node_worker.cc',
|
||||
'src/node_zlib.cc',
|
||||
|
@ -638,6 +646,7 @@
|
|||
'src/node_url.h',
|
||||
'src/node_version.h',
|
||||
'src/node_v8_platform-inl.h',
|
||||
'src/node_wasi.h',
|
||||
'src/node_watchdog.h',
|
||||
'src/node_worker.h',
|
||||
'src/pipe_wrap.h',
|
||||
|
@ -1072,6 +1081,7 @@
|
|||
'dependencies': [
|
||||
'<(node_lib_target_name)',
|
||||
'deps/histogram/histogram.gyp:histogram',
|
||||
'deps/uvwasi/uvwasi.gyp:uvwasi',
|
||||
'node_dtrace_header',
|
||||
'node_dtrace_ustack',
|
||||
'node_dtrace_provider',
|
||||
|
@ -1087,6 +1097,7 @@
|
|||
'deps/v8/include',
|
||||
'deps/cares/include',
|
||||
'deps/uv/include',
|
||||
'deps/uvwasi/include',
|
||||
'test/cctest',
|
||||
],
|
||||
|
||||
|
@ -1181,6 +1192,7 @@
|
|||
'dependencies': [
|
||||
'<(node_lib_target_name)',
|
||||
'deps/histogram/histogram.gyp:histogram',
|
||||
'deps/uvwasi/uvwasi.gyp:uvwasi',
|
||||
],
|
||||
|
||||
'includes': [
|
||||
|
@ -1193,6 +1205,7 @@
|
|||
'deps/v8/include',
|
||||
'deps/cares/include',
|
||||
'deps/uv/include',
|
||||
'deps/uvwasi/include',
|
||||
],
|
||||
|
||||
'defines': [
|
||||
|
@ -1224,6 +1237,7 @@
|
|||
'dependencies': [
|
||||
'<(node_lib_target_name)',
|
||||
'deps/histogram/histogram.gyp:histogram',
|
||||
'deps/uvwasi/uvwasi.gyp:uvwasi',
|
||||
],
|
||||
|
||||
'includes': [
|
||||
|
@ -1236,6 +1250,7 @@
|
|||
'deps/v8/include',
|
||||
'deps/cares/include',
|
||||
'deps/uv/include',
|
||||
'deps/uvwasi/include',
|
||||
],
|
||||
|
||||
'defines': [ 'NODE_WANT_INTERNALS=1' ],
|
||||
|
|
|
@ -1102,6 +1102,21 @@ inline void Environment::SetProtoMethodNoSideEffect(
|
|||
t->SetClassName(name_string); // NODE_SET_PROTOTYPE_METHOD() compatibility.
|
||||
}
|
||||
|
||||
inline void Environment::SetInstanceMethod(v8::Local<v8::FunctionTemplate> that,
|
||||
const char* name,
|
||||
v8::FunctionCallback callback) {
|
||||
v8::Local<v8::Signature> signature = v8::Signature::New(isolate(), that);
|
||||
v8::Local<v8::FunctionTemplate> t =
|
||||
NewFunctionTemplate(callback, signature, v8::ConstructorBehavior::kThrow,
|
||||
v8::SideEffectType::kHasSideEffect);
|
||||
// kInternalized strings are created in the old space.
|
||||
const v8::NewStringType type = v8::NewStringType::kInternalized;
|
||||
v8::Local<v8::String> name_string =
|
||||
v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
|
||||
that->InstanceTemplate()->Set(name_string, t);
|
||||
t->SetClassName(name_string);
|
||||
}
|
||||
|
||||
void Environment::AddCleanupHook(void (*fn)(void*), void* arg) {
|
||||
auto insertion_info = cleanup_hooks_.emplace(CleanupHookCallback {
|
||||
fn, arg, cleanup_hook_counter_++
|
||||
|
|
|
@ -541,7 +541,8 @@ struct ContextInfo {
|
|||
#define DEBUG_CATEGORY_NAMES(V) \
|
||||
NODE_ASYNC_PROVIDER_TYPES(V) \
|
||||
V(INSPECTOR_SERVER) \
|
||||
V(INSPECTOR_PROFILER)
|
||||
V(INSPECTOR_PROFILER) \
|
||||
V(WASI)
|
||||
|
||||
enum class DebugCategory {
|
||||
#define V(name) name,
|
||||
|
@ -1114,6 +1115,11 @@ class Environment : public MemoryRetainer {
|
|||
const char* name,
|
||||
v8::FunctionCallback callback);
|
||||
|
||||
inline void SetInstanceMethod(v8::Local<v8::FunctionTemplate> that,
|
||||
const char* name,
|
||||
v8::FunctionCallback callback);
|
||||
|
||||
|
||||
// Safe variants denote the function has no side effects.
|
||||
inline void SetMethodNoSideEffect(v8::Local<v8::Object> that,
|
||||
const char* name,
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
V(util) \
|
||||
V(uv) \
|
||||
V(v8) \
|
||||
V(wasi) \
|
||||
V(worker) \
|
||||
V(zlib)
|
||||
|
||||
|
|
|
@ -84,6 +84,9 @@ static void Initialize(Local<Object> target,
|
|||
|
||||
READONLY_PROPERTY(target, "hasCachedBuiltins",
|
||||
v8::Boolean::New(isolate, native_module::has_code_cache));
|
||||
|
||||
if (env->options()->experimental_wasi)
|
||||
READONLY_TRUE_PROPERTY(target, "experimentalWasi");
|
||||
} // InitConfig
|
||||
|
||||
} // namespace node
|
||||
|
|
|
@ -347,6 +347,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
|
|||
&EnvironmentOptions::experimental_report,
|
||||
kAllowedInEnvironment);
|
||||
#endif // NODE_REPORT
|
||||
AddOption("--experimental-wasi-unstable-preview0",
|
||||
"experimental WASI support",
|
||||
&EnvironmentOptions::experimental_wasi,
|
||||
kAllowedInEnvironment);
|
||||
AddOption("--expose-internals", "", &EnvironmentOptions::expose_internals);
|
||||
AddOption("--frozen-intrinsics",
|
||||
"experimental frozen intrinsics support",
|
||||
|
|
|
@ -151,6 +151,7 @@ class EnvironmentOptions : public Options {
|
|||
#ifdef NODE_REPORT
|
||||
bool experimental_report = false;
|
||||
#endif // NODE_REPORT
|
||||
bool experimental_wasi = false;
|
||||
std::string eval_string;
|
||||
bool print_eval = false;
|
||||
bool force_repl = false;
|
||||
|
|
1802
src/node_wasi.cc
Normal file
1802
src/node_wasi.cc
Normal file
File diff suppressed because it is too large
Load diff
103
src/node_wasi.h
Normal file
103
src/node_wasi.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
#ifndef SRC_NODE_WASI_H_
|
||||
#define SRC_NODE_WASI_H_
|
||||
|
||||
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
||||
|
||||
#include "base_object.h"
|
||||
#include "memory_tracker-inl.h"
|
||||
#include "uvwasi.h"
|
||||
|
||||
namespace node {
|
||||
namespace wasi {
|
||||
|
||||
|
||||
class WASI : public BaseObject {
|
||||
public:
|
||||
WASI(Environment* env,
|
||||
v8::Local<v8::Object> object,
|
||||
uvwasi_options_t* options);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
void MemoryInfo(MemoryTracker* tracker) const override {
|
||||
/* TODO(cjihrig): Get memory consumption from uvwasi. */
|
||||
tracker->TrackField("memory", memory_);
|
||||
}
|
||||
|
||||
SET_MEMORY_INFO_NAME(WASI)
|
||||
SET_SELF_SIZE(WASI)
|
||||
|
||||
static void ArgsGet(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ArgsSizesGet(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ClockResGet(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ClockTimeGet(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void EnvironGet(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void EnvironSizesGet(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdAdvise(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdAllocate(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdClose(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdDatasync(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdFdstatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdFdstatSetFlags(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdFdstatSetRights(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdFilestatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdFilestatSetSize(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdFilestatSetTimes(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdPread(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdPrestatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdPrestatDirName(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdPwrite(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdRead(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdReaddir(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdRenumber(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdSeek(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdSync(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdTell(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void FdWrite(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PathCreateDirectory(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PathFilestatGet(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PathFilestatSetTimes(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PathLink(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PathOpen(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PathReadlink(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PathRemoveDirectory(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PathRename(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PathSymlink(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PathUnlinkFile(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PollOneoff(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ProcExit(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ProcRaise(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void RandomGet(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SchedYield(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SockRecv(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SockSend(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SockShutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
static void _SetMemory(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
private:
|
||||
~WASI() override;
|
||||
inline void readUInt8(char* memory, uint8_t* value, uint32_t offset);
|
||||
inline void readUInt16(char* memory, uint16_t* value, uint32_t offset);
|
||||
inline void readUInt32(char* memory, uint32_t* value, uint32_t offset);
|
||||
inline void readUInt64(char* memory, uint64_t* value, uint32_t offset);
|
||||
inline void writeUInt8(char* memory, uint8_t value, uint32_t offset);
|
||||
inline void writeUInt16(char* memory, uint16_t value, uint32_t offset);
|
||||
inline void writeUInt32(char* memory, uint32_t value, uint32_t offset);
|
||||
inline void writeUInt64(char* memory, uint64_t value, uint32_t offset);
|
||||
uvwasi_errno_t backingStore(char** store, size_t* byte_length);
|
||||
uvwasi_t uvw_;
|
||||
v8::Global<v8::Object> memory_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace wasi
|
||||
} // namespace node
|
||||
|
||||
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
||||
|
||||
#endif // SRC_NODE_WASI_H_
|
2
test/fixtures/outside.txt
vendored
Normal file
2
test/fixtures/outside.txt
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
this file is part of the WASI tests. it exists outside of the sandbox, and
|
||||
should be inaccessible from the WASI tests.
|
1
test/fixtures/wasi/input.txt
vendored
Normal file
1
test/fixtures/wasi/input.txt
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
hello from input.txt
|
0
test/fixtures/wasi/notadir
vendored
Normal file
0
test/fixtures/wasi/notadir
vendored
Normal file
BIN
test/fixtures/wasi/simple-wasi.wasm
vendored
Executable file
BIN
test/fixtures/wasi/simple-wasi.wasm
vendored
Executable file
Binary file not shown.
6533
test/fixtures/wasi/simple-wasi.wat
vendored
Normal file
6533
test/fixtures/wasi/simple-wasi.wat
vendored
Normal file
File diff suppressed because it is too large
Load diff
1
test/fixtures/wasi/subdir/input_link.txt
vendored
Symbolic link
1
test/fixtures/wasi/subdir/input_link.txt
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../input.txt
|
1
test/fixtures/wasi/subdir/loop1
vendored
Symbolic link
1
test/fixtures/wasi/subdir/loop1
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
./loop2
|
1
test/fixtures/wasi/subdir/loop2
vendored
Symbolic link
1
test/fixtures/wasi/subdir/loop2
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
./loop1
|
1
test/fixtures/wasi/subdir/outside.txt
vendored
Symbolic link
1
test/fixtures/wasi/subdir/outside.txt
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../outside.txt
|
12
test/wasi/Makefile
Normal file
12
test/wasi/Makefile
Normal file
|
@ -0,0 +1,12 @@
|
|||
CC = /opt/wasi-sdk/bin/clang
|
||||
TARGET = wasm32-unknown-wasi
|
||||
SYSROOT =
|
||||
|
||||
OBJ = $(patsubst c/%.c, wasm/%.wasm, $(wildcard c/*.c))
|
||||
all: $(OBJ)
|
||||
|
||||
wasm/%.wasm : c/%.c
|
||||
$(CC) $< --target=$(TARGET) --sysroot=$(SYSROOT) -s -o $@
|
||||
|
||||
.PHONY clean:
|
||||
rm -f $(OBJ)
|
8
test/wasi/README.md
Normal file
8
test/wasi/README.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# WASI Tests
|
||||
|
||||
Compile with clang and `wasm32-wasi` target. The clang version used must be
|
||||
built with wasi-libc. You can specify the location for clang and the sysroot
|
||||
if needed when running make:
|
||||
```console
|
||||
$ make CC=/usr/local/opt/llvm/bin/clang SYSROOT=/path/to/wasi-libc/sysroot
|
||||
```
|
11
test/wasi/c/cant_dotdot.c
Normal file
11
test/wasi/c/cant_dotdot.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
FILE* file = fopen("/sandbox/../outside.txt", "r");
|
||||
assert(file == NULL);
|
||||
assert(errno == ENOTCAPABLE);
|
||||
|
||||
return 0;
|
||||
}
|
17
test/wasi/c/clock_getres.c
Normal file
17
test/wasi/c/clock_getres.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
int main() {
|
||||
struct timespec ts;
|
||||
int r;
|
||||
|
||||
// supported clocks
|
||||
r = clock_getres(CLOCK_REALTIME, &ts);
|
||||
assert(r == 0);
|
||||
r = clock_getres(CLOCK_MONOTONIC, &ts);
|
||||
assert(r == 0);
|
||||
r = clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts);
|
||||
assert(r == 0);
|
||||
r = clock_getres(CLOCK_THREAD_CPUTIME_ID, &ts);
|
||||
assert(r == 0);
|
||||
}
|
3
test/wasi/c/exitcode.c
Normal file
3
test/wasi/c/exitcode.c
Normal file
|
@ -0,0 +1,3 @@
|
|||
int main() {
|
||||
return 120;
|
||||
}
|
8
test/wasi/c/fd_prestat_get_refresh.c
Normal file
8
test/wasi/c/fd_prestat_get_refresh.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <unistd.h>
|
||||
|
||||
int main(void) {
|
||||
isatty(1);
|
||||
__builtin_wasm_memory_grow(0, 1);
|
||||
isatty(1);
|
||||
return 0;
|
||||
}
|
14
test/wasi/c/follow_symlink.c
Normal file
14
test/wasi/c/follow_symlink.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
FILE* file = fopen("/sandbox/subdir/input_link.txt", "r");
|
||||
assert(file != NULL);
|
||||
|
||||
char c = fgetc(file);
|
||||
while (c != EOF) {
|
||||
int wrote = fputc(c, stdout);
|
||||
assert(wrote != EOF);
|
||||
c = fgetc(file);
|
||||
}
|
||||
}
|
18
test/wasi/c/getentropy.c
Normal file
18
test/wasi/c/getentropy.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
char buf[256] = {0};
|
||||
int r = getentropy(buf, 256);
|
||||
assert(r == 0);
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if (buf[i] != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// if this ever is reached, we either have a bug or should buy a lottery
|
||||
// ticket
|
||||
return 1;
|
||||
}
|
34
test/wasi/c/getrusage.c
Normal file
34
test/wasi/c/getrusage.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include <assert.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
int main() {
|
||||
struct rusage ru1;
|
||||
struct rusage ru2;
|
||||
long long s1;
|
||||
long long us1;
|
||||
long long s2;
|
||||
long long us2;
|
||||
int r;
|
||||
int success = 0;
|
||||
|
||||
r = getrusage(RUSAGE_SELF, &ru1);
|
||||
assert(r == 0);
|
||||
s1 = ru1.ru_utime.tv_sec;
|
||||
us1 = ru1.ru_utime.tv_usec;
|
||||
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
r = getrusage(RUSAGE_SELF, &ru2);
|
||||
assert(r == 0);
|
||||
s2 = ru2.ru_utime.tv_sec;
|
||||
us2 = ru2.ru_utime.tv_usec;
|
||||
assert(s1 <= s2);
|
||||
|
||||
// Verify that some time has passed.
|
||||
if (s2 > s1 || (s2 == s1 && us2 > us1)) {
|
||||
success = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(success == 1);
|
||||
}
|
35
test/wasi/c/gettimeofday.c
Normal file
35
test/wasi/c/gettimeofday.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
int main() {
|
||||
struct timeval tv1;
|
||||
struct timeval tv2;
|
||||
long long s1;
|
||||
long long us1;
|
||||
long long s2;
|
||||
long long us2;
|
||||
int r;
|
||||
int success = 0;
|
||||
|
||||
r = gettimeofday(&tv1, NULL);
|
||||
assert(r == 0);
|
||||
s1 = tv1.tv_sec;
|
||||
us1 = tv1.tv_usec;
|
||||
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
r = gettimeofday(&tv2, NULL);
|
||||
assert(r == 0);
|
||||
s2 = tv2.tv_sec;
|
||||
us2 = tv2.tv_usec;
|
||||
assert(s1 <= s2);
|
||||
|
||||
// Verify that some time has passed.
|
||||
if (s2 > s1 || (s2 == s1 && us2 > us1)) {
|
||||
success = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(success == 1);
|
||||
}
|
11
test/wasi/c/notdir.c
Normal file
11
test/wasi/c/notdir.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main() {
|
||||
DIR* dir = opendir("/sandbox/notadir");
|
||||
assert(dir == NULL);
|
||||
assert(errno == ENOTDIR);
|
||||
|
||||
return 0;
|
||||
}
|
31
test/wasi/c/poll.c
Normal file
31
test/wasi/c/poll.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include <assert.h>
|
||||
#include <poll.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(void) {
|
||||
struct pollfd fds[2];
|
||||
time_t before, now;
|
||||
int ret;
|
||||
|
||||
fds[0] = (struct pollfd){.fd = 1, .events = POLLOUT, .revents = 0};
|
||||
fds[1] = (struct pollfd){.fd = 2, .events = POLLOUT, .revents = 0};
|
||||
|
||||
ret = poll(fds, 2, -1);
|
||||
assert(ret == 2);
|
||||
assert(fds[0].revents == POLLOUT);
|
||||
assert(fds[1].revents == POLLOUT);
|
||||
|
||||
fds[0] = (struct pollfd){.fd = 0, .events = POLLIN, .revents = 0};
|
||||
time(&before);
|
||||
ret = poll(fds, 1, 2000);
|
||||
time(&now);
|
||||
assert(ret == 0);
|
||||
assert(now - before >= 2);
|
||||
|
||||
sleep(1);
|
||||
time(&now);
|
||||
assert(now - before >= 3);
|
||||
|
||||
return 0;
|
||||
}
|
3
test/wasi/c/preopen_populates.c
Normal file
3
test/wasi/c/preopen_populates.c
Normal file
|
@ -0,0 +1,3 @@
|
|||
int main(void) {
|
||||
return 0;
|
||||
}
|
14
test/wasi/c/read_file.c
Normal file
14
test/wasi/c/read_file.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
FILE* file = fopen("/sandbox/input.txt", "r");
|
||||
assert(file != NULL);
|
||||
|
||||
char c = fgetc(file);
|
||||
while (c != EOF) {
|
||||
int wrote = fputc(c, stdout);
|
||||
assert(wrote != EOF);
|
||||
c = fgetc(file);
|
||||
}
|
||||
}
|
16
test/wasi/c/read_file_twice.c
Normal file
16
test/wasi/c/read_file_twice.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
FILE* file = fopen("/sandbox/input.txt", "r");
|
||||
assert(file != NULL);
|
||||
|
||||
char c = fgetc(file);
|
||||
while (c != EOF) {
|
||||
int wrote = fputc(c, stdout);
|
||||
assert(wrote != EOF);
|
||||
c = fgetc(file);
|
||||
}
|
||||
}
|
||||
}
|
53
test/wasi/c/stat.c
Normal file
53
test/wasi/c/stat.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include <sys/stat.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define BASE_DIR "/tmp"
|
||||
#define OUTPUT_DIR BASE_DIR "/testdir"
|
||||
#define PATH OUTPUT_DIR "/output.txt"
|
||||
#define SIZE 500
|
||||
|
||||
int main(void) {
|
||||
struct stat st;
|
||||
int fd;
|
||||
int ret;
|
||||
off_t pos;
|
||||
|
||||
(void)st;
|
||||
ret = mkdir(OUTPUT_DIR, 0755);
|
||||
assert(ret == 0);
|
||||
|
||||
fd = open(PATH, O_CREAT | O_WRONLY, 0666);
|
||||
assert(fd != -1);
|
||||
|
||||
pos = lseek(fd, SIZE - 1, SEEK_SET);
|
||||
assert(pos == SIZE - 1);
|
||||
|
||||
ret = (int)write(fd, "", 1);
|
||||
assert(ret == 1);
|
||||
|
||||
ret = fstat(fd, &st);
|
||||
assert(ret == 0);
|
||||
assert(st.st_size == SIZE);
|
||||
|
||||
ret = close(fd);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = access(PATH, R_OK);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = stat(PATH, &st);
|
||||
assert(ret == 0);
|
||||
assert(st.st_size == SIZE);
|
||||
|
||||
ret = unlink(PATH);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = stat(PATH, &st);
|
||||
assert(ret == -1);
|
||||
|
||||
return 0;
|
||||
}
|
13
test/wasi/c/stdin.c
Normal file
13
test/wasi/c/stdin.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
char x[32];
|
||||
|
||||
if (fgets(x, sizeof x, stdin) == NULL) {
|
||||
return ferror(stdin);
|
||||
}
|
||||
if (fputs(x, stdout) == EOF) {
|
||||
return ferror(stdout);
|
||||
}
|
||||
return 0;
|
||||
}
|
9
test/wasi/c/symlink_escape.c
Normal file
9
test/wasi/c/symlink_escape.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
FILE* file = fopen("/sandbox/subdir/outside.txt", "r");
|
||||
assert(file == NULL);
|
||||
assert(errno == ENOTCAPABLE);
|
||||
}
|
9
test/wasi/c/symlink_loop.c
Normal file
9
test/wasi/c/symlink_loop.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
FILE* file = fopen("/sandbox/subdir/loop1", "r");
|
||||
assert(file == NULL);
|
||||
assert(errno == ELOOP);
|
||||
}
|
15
test/wasi/c/write_file.c
Normal file
15
test/wasi/c/write_file.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static char* message = "hello, file!";
|
||||
|
||||
int main() {
|
||||
FILE* file = fopen("/tmp/output.txt", "w");
|
||||
assert(file != NULL);
|
||||
|
||||
int nwritten = fprintf(file, "%s", message);
|
||||
assert(nwritten == strlen(message));
|
||||
int r = fclose(file);
|
||||
assert(r == 0);
|
||||
}
|
19
test/wasi/test-wasi-binding.js
Normal file
19
test/wasi/test-wasi-binding.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Flags: --experimental-wasi-unstable-preview0
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const buffer = fixtures.readSync(['wasi', 'simple-wasi.wasm']);
|
||||
const { WASI } = require('wasi');
|
||||
const wasi = new WASI({ args: [], env: process.env });
|
||||
const importObject = {
|
||||
wasi_unstable: wasi.wasiImport
|
||||
};
|
||||
|
||||
WebAssembly.instantiate(buffer, importObject)
|
||||
.then(common.mustCall((results) => {
|
||||
assert(results.instance.exports._start);
|
||||
wasi.start(results.instance);
|
||||
}));
|
78
test/wasi/test-wasi-symlinks.js
Normal file
78
test/wasi/test-wasi-symlinks.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
if (process.argv[2] === 'wasi-child') {
|
||||
common.expectWarning('ExperimentalWarning',
|
||||
'WASI is an experimental feature. This feature could ' +
|
||||
'change at any time');
|
||||
|
||||
const { WASI } = require('wasi');
|
||||
const wasmDir = path.join(__dirname, 'wasm');
|
||||
const wasi = new WASI({
|
||||
args: [],
|
||||
env: process.env,
|
||||
preopens: {
|
||||
'/sandbox': process.argv[4]
|
||||
}
|
||||
});
|
||||
const importObject = { wasi_unstable: wasi.wasiImport };
|
||||
const modulePath = path.join(wasmDir, `${process.argv[3]}.wasm`);
|
||||
const buffer = fs.readFileSync(modulePath);
|
||||
|
||||
(async () => {
|
||||
const { instance } = await WebAssembly.instantiate(buffer, importObject);
|
||||
|
||||
wasi.start(instance);
|
||||
})();
|
||||
} else {
|
||||
if (!common.canCreateSymLink()) {
|
||||
common.skip('insufficient privileges');
|
||||
}
|
||||
|
||||
const assert = require('assert');
|
||||
const cp = require('child_process');
|
||||
const tmpdir = require('../../test/common/tmpdir');
|
||||
|
||||
// Setup the sandbox environment.
|
||||
tmpdir.refresh();
|
||||
const sandbox = path.join(tmpdir.path, 'sandbox');
|
||||
const sandboxedFile = path.join(sandbox, 'input.txt');
|
||||
const externalFile = path.join(tmpdir.path, 'outside.txt');
|
||||
const sandboxedDir = path.join(sandbox, 'subdir');
|
||||
const sandboxedSymlink = path.join(sandboxedDir, 'input_link.txt');
|
||||
const escapingSymlink = path.join(sandboxedDir, 'outside.txt');
|
||||
const loopSymlink1 = path.join(sandboxedDir, 'loop1');
|
||||
const loopSymlink2 = path.join(sandboxedDir, 'loop2');
|
||||
|
||||
fs.mkdirSync(sandbox);
|
||||
fs.mkdirSync(sandboxedDir);
|
||||
fs.writeFileSync(sandboxedFile, 'hello from input.txt', 'utf8');
|
||||
fs.writeFileSync(externalFile, 'this should be inaccessible', 'utf8');
|
||||
fs.symlinkSync(sandboxedFile, sandboxedSymlink, 'file');
|
||||
fs.symlinkSync(externalFile, escapingSymlink, 'file');
|
||||
fs.symlinkSync(loopSymlink2, loopSymlink1, 'file');
|
||||
fs.symlinkSync(loopSymlink1, loopSymlink2, 'file');
|
||||
|
||||
function runWASI(options) {
|
||||
console.log('executing', options.test);
|
||||
const opts = { env: { ...process.env, NODE_DEBUG_NATIVE: 'wasi' } };
|
||||
const child = cp.spawnSync(process.execPath, [
|
||||
'--experimental-wasi-unstable-preview0',
|
||||
'--experimental-wasm-bigint',
|
||||
__filename,
|
||||
'wasi-child',
|
||||
options.test,
|
||||
sandbox
|
||||
], opts);
|
||||
console.log(child.stderr.toString());
|
||||
assert.strictEqual(child.status, 0);
|
||||
assert.strictEqual(child.signal, null);
|
||||
assert.strictEqual(child.stdout.toString(), options.stdout || '');
|
||||
}
|
||||
|
||||
runWASI({ test: 'follow_symlink', stdout: 'hello from input.txt' });
|
||||
runWASI({ test: 'symlink_escape' });
|
||||
runWASI({ test: 'symlink_loop' });
|
||||
}
|
81
test/wasi/test-wasi.js
Normal file
81
test/wasi/test-wasi.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (process.argv[2] === 'wasi-child') {
|
||||
const fixtures = require('../common/fixtures');
|
||||
const tmpdir = require('../../test/common/tmpdir');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
common.expectWarning('ExperimentalWarning',
|
||||
'WASI is an experimental feature. This feature could ' +
|
||||
'change at any time');
|
||||
|
||||
const { WASI } = require('wasi');
|
||||
tmpdir.refresh();
|
||||
const wasmDir = path.join(__dirname, 'wasm');
|
||||
const wasi = new WASI({
|
||||
args: [],
|
||||
env: process.env,
|
||||
preopens: {
|
||||
'/sandbox': fixtures.path('wasi'),
|
||||
'/tmp': tmpdir.path
|
||||
}
|
||||
});
|
||||
const importObject = { wasi_unstable: wasi.wasiImport };
|
||||
const modulePath = path.join(wasmDir, `${process.argv[3]}.wasm`);
|
||||
const buffer = fs.readFileSync(modulePath);
|
||||
|
||||
(async () => {
|
||||
const { instance } = await WebAssembly.instantiate(buffer, importObject);
|
||||
|
||||
wasi.start(instance);
|
||||
})();
|
||||
} else {
|
||||
const assert = require('assert');
|
||||
const cp = require('child_process');
|
||||
const { EOL } = require('os');
|
||||
|
||||
function runWASI(options) {
|
||||
console.log('executing', options.test);
|
||||
const opts = { env: { ...process.env, NODE_DEBUG_NATIVE: 'wasi' } };
|
||||
|
||||
if (options.stdin !== undefined)
|
||||
opts.input = options.stdin;
|
||||
|
||||
const child = cp.spawnSync(process.execPath, [
|
||||
'--experimental-wasi-unstable-preview0',
|
||||
'--experimental-wasm-bigint',
|
||||
__filename,
|
||||
'wasi-child',
|
||||
options.test
|
||||
], opts);
|
||||
console.log(child.stderr.toString());
|
||||
assert.strictEqual(child.status, options.exitCode || 0);
|
||||
assert.strictEqual(child.signal, null);
|
||||
assert.strictEqual(child.stdout.toString(), options.stdout || '');
|
||||
}
|
||||
|
||||
runWASI({ test: 'cant_dotdot' });
|
||||
runWASI({ test: 'clock_getres' });
|
||||
runWASI({ test: 'exitcode', exitCode: 120 });
|
||||
runWASI({ test: 'fd_prestat_get_refresh' });
|
||||
runWASI({ test: 'getentropy' });
|
||||
runWASI({ test: 'getrusage' });
|
||||
runWASI({ test: 'gettimeofday' });
|
||||
runWASI({ test: 'notdir' });
|
||||
// runWASI({ test: 'poll' });
|
||||
runWASI({ test: 'preopen_populates' });
|
||||
runWASI({ test: 'read_file', stdout: `hello from input.txt${EOL}` });
|
||||
runWASI({
|
||||
test: 'read_file_twice',
|
||||
stdout: `hello from input.txt${EOL}hello from input.txt${EOL}`
|
||||
});
|
||||
runWASI({ test: 'stat' });
|
||||
runWASI({ test: 'write_file' });
|
||||
|
||||
// Tests that are currently unsupported on Windows.
|
||||
if (!common.isWindows) {
|
||||
runWASI({ test: 'stdin', stdin: 'hello world', stdout: 'hello world' });
|
||||
}
|
||||
}
|
6
test/wasi/testcfg.py
Normal file
6
test/wasi/testcfg.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
import sys, os
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
import testpy
|
||||
|
||||
def GetConfiguration(context, root):
|
||||
return testpy.ParallelTestConfiguration(context, root, 'wasi')
|
7
test/wasi/wasi.status
Normal file
7
test/wasi/wasi.status
Normal file
|
@ -0,0 +1,7 @@
|
|||
prefix wasi
|
||||
|
||||
# To mark a test as flaky, list the test name in the appropriate section
|
||||
# below, without ".js", followed by ": PASS,FLAKY". Example:
|
||||
# sample-test : PASS,FLAKY
|
||||
|
||||
[true] # This section applies to all platforms
|
BIN
test/wasi/wasm/cant_dotdot.wasm
Executable file
BIN
test/wasi/wasm/cant_dotdot.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/clock_getres.wasm
Executable file
BIN
test/wasi/wasm/clock_getres.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/exitcode.wasm
Executable file
BIN
test/wasi/wasm/exitcode.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/fd_prestat_get_refresh.wasm
Executable file
BIN
test/wasi/wasm/fd_prestat_get_refresh.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/follow_symlink.wasm
Executable file
BIN
test/wasi/wasm/follow_symlink.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/getentropy.wasm
Executable file
BIN
test/wasi/wasm/getentropy.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/getrusage.wasm
Executable file
BIN
test/wasi/wasm/getrusage.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/gettimeofday.wasm
Executable file
BIN
test/wasi/wasm/gettimeofday.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/notdir.wasm
Executable file
BIN
test/wasi/wasm/notdir.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/poll.wasm
Executable file
BIN
test/wasi/wasm/poll.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/preopen_populates.wasm
Executable file
BIN
test/wasi/wasm/preopen_populates.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/read_file.wasm
Executable file
BIN
test/wasi/wasm/read_file.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/read_file_twice.wasm
Executable file
BIN
test/wasi/wasm/read_file_twice.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/stat.wasm
Executable file
BIN
test/wasi/wasm/stat.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/stdin.wasm
Executable file
BIN
test/wasi/wasm/stdin.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/symlink_escape.wasm
Executable file
BIN
test/wasi/wasm/symlink_escape.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/symlink_loop.wasm
Executable file
BIN
test/wasi/wasm/symlink_loop.wasm
Executable file
Binary file not shown.
BIN
test/wasi/wasm/write_file.wasm
Executable file
BIN
test/wasi/wasm/write_file.wasm
Executable file
Binary file not shown.
|
@ -18,7 +18,7 @@ const jsGlobalTypes = [
|
|||
'Array', 'ArrayBuffer', 'ArrayBufferView', 'DataView', 'Date', 'Error',
|
||||
'EvalError', 'Function', 'Map', 'Object', 'Promise', 'RangeError',
|
||||
'ReferenceError', 'RegExp', 'Set', 'SharedArrayBuffer', 'SyntaxError',
|
||||
'TypeError', 'TypedArray', 'URIError', 'Uint8Array',
|
||||
'TypeError', 'TypedArray', 'URIError', 'Uint8Array', 'WebAssembly.Instance',
|
||||
];
|
||||
|
||||
const customTypesMap = {
|
||||
|
|
|
@ -108,4 +108,6 @@ addlicense "node-heapdump" "src/heap_utils.cc" \
|
|||
addlicense "rimraf" "lib/internal/fs/rimraf.js" \
|
||||
"$(curl -sL https://raw.githubusercontent.com/isaacs/rimraf/0e365ac4e4d64a25aa2a3cc026348f13410210e1/LICENSE)"
|
||||
|
||||
addlicense "uvwasi" "deps/uvwasi" "$(cat ${rootdir}/deps/uvwasi/LICENSE)"
|
||||
|
||||
mv $tmplicense $licensefile
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue