wasienv.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  1. unit wasienv;
  2. {$mode ObjFPC}
  3. {$modeswitch externalclass}
  4. {$INTERFACES CORBA}
  5. interface
  6. uses
  7. SysUtils, Classes, JS, WebAssembly, types;
  8. Const
  9. WASI_ESUCCESS = 0;
  10. WASI_E2BIG = 1;
  11. WASI_EACCES = 2;
  12. WASI_EADDRINUSE = 3;
  13. WASI_EADDRNOTAVAIL = 4;
  14. WASI_EAFNOSUPPORT = 5;
  15. WASI_EAGAIN = 6;
  16. WASI_EALREADY = 7;
  17. WASI_EBADF = 8;
  18. WASI_EBADMSG = 9;
  19. WASI_EBUSY = 10;
  20. WASI_ECANCELED = 11;
  21. WASI_ECHILD = 12;
  22. WASI_ECONNABORTED = 13;
  23. WASI_ECONNREFUSED = 14;
  24. WASI_ECONNRESET = 15;
  25. WASI_EDEADLK = 16;
  26. WASI_EDESTADDRREQ = 17;
  27. WASI_EDOM = 18;
  28. WASI_EDQUOT = 19;
  29. WASI_EEXIST = 20;
  30. WASI_EFAULT = 21;
  31. WASI_EFBIG = 22;
  32. WASI_EHOSTUNREACH = 23;
  33. WASI_EIDRM = 24;
  34. WASI_EILSEQ = 25;
  35. WASI_EINPROGRESS = 26;
  36. WASI_EINTR = 27;
  37. WASI_EINVAL = 28;
  38. WASI_EIO = 29;
  39. WASI_EISCONN = 30;
  40. WASI_EISDIR = 31;
  41. WASI_ELOOP = 32;
  42. WASI_EMFILE = 33;
  43. WASI_EMLINK = 34;
  44. WASI_EMSGSIZE = 35;
  45. WASI_EMULTIHOP = 36;
  46. WASI_ENAMETOOLONG = 37;
  47. WASI_ENETDOWN = 38;
  48. WASI_ENETRESET = 39;
  49. WASI_ENETUNREACH = 40;
  50. WASI_ENFILE = 41;
  51. WASI_ENOBUFS = 42;
  52. WASI_ENODEV = 43;
  53. WASI_ENOENT = 44;
  54. WASI_ENOEXEC = 45;
  55. WASI_ENOLCK = 46;
  56. WASI_ENOLINK = 47;
  57. WASI_ENOMEM = 48;
  58. WASI_ENOMSG = 49;
  59. WASI_ENOPROTOOPT = 50;
  60. WASI_ENOSPC = 51;
  61. WASI_ENOSYS = 52;
  62. WASI_ENOTCONN = 53;
  63. WASI_ENOTDIR = 54;
  64. WASI_ENOTEMPTY = 55;
  65. WASI_ENOTRECOVERABLE = 56;
  66. WASI_ENOTSOCK = 57;
  67. WASI_ENOTSUP = 58;
  68. WASI_ENOTTY = 59;
  69. WASI_ENXIO = 60;
  70. WASI_EOVERFLOW = 61;
  71. WASI_EOWNERDEAD = 62;
  72. WASI_EPERM = 63;
  73. WASI_EPIPE = 64;
  74. WASI_EPROTO = 65;
  75. WASI_EPROTONOSUPPORT = 66;
  76. WASI_EPROTOTYPE = 67;
  77. WASI_ERANGE = 68;
  78. WASI_EROFS = 69;
  79. WASI_ESPIPE = 70;
  80. WASI_ESRCH = 71;
  81. WASI_ESTALE = 72;
  82. WASI_ETIMEDOUT = 73;
  83. WASI_ETXTBSY = 74;
  84. WASI_EXDEV = 75;
  85. WASI_ENOTCAPABLE = 76;
  86. WASI_SIGABRT = 0;
  87. WASI_SIGALRM = 1;
  88. WASI_SIGBUS = 2;
  89. WASI_SIGCHLD = 3;
  90. WASI_SIGCONT = 4;
  91. WASI_SIGFPE = 5;
  92. WASI_SIGHUP = 6;
  93. WASI_SIGILL = 7;
  94. WASI_SIGINT = 8;
  95. WASI_SIGKILL = 9;
  96. WASI_SIGPIPE = 10;
  97. WASI_SIGQUIT = 11;
  98. WASI_SIGSEGV = 12;
  99. WASI_SIGSTOP = 13;
  100. WASI_SIGTERM = 14;
  101. WASI_SIGTRAP = 15;
  102. WASI_SIGTSTP = 16;
  103. WASI_SIGTTIN = 17;
  104. WASI_SIGTTOU = 18;
  105. WASI_SIGURG = 19;
  106. WASI_SIGUSR1 = 20;
  107. WASI_SIGUSR2 = 21;
  108. WASI_SIGVTALRM = 22;
  109. WASI_SIGXCPU = 23;
  110. WASI_SIGXFSZ = 24;
  111. WASI_FILETYPE_UNKNOWN = 0;
  112. WASI_FILETYPE_BLOCK_DEVICE = 1;
  113. WASI_FILETYPE_CHARACTER_DEVICE = 2;
  114. WASI_FILETYPE_DIRECTORY = 3;
  115. WASI_FILETYPE_REGULAR_FILE = 4;
  116. WASI_FILETYPE_SOCKET_DGRAM = 5;
  117. WASI_FILETYPE_SOCKET_STREAM = 6;
  118. WASI_FILETYPE_SYMBOLIC_LINK = 7;
  119. WASI_FDFLAG_APPEND = $0001;
  120. WASI_FDFLAG_DSYNC = $0002;
  121. WASI_FDFLAG_NONBLOCK = $0004;
  122. WASI_FDFLAG_RSYNC = $0008;
  123. WASI_FDFLAG_SYNC = $0010;
  124. WASI_RIGHT_FD_DATASYNC = $0000000000000001;
  125. WASI_RIGHT_FD_READ = $0000000000000002;
  126. WASI_RIGHT_FD_SEEK = $0000000000000004;
  127. WASI_RIGHT_FD_FDSTAT_SET_FLAGS = $0000000000000008;
  128. WASI_RIGHT_FD_SYNC = $0000000000000010;
  129. WASI_RIGHT_FD_TELL = $0000000000000020;
  130. WASI_RIGHT_FD_WRITE = $0000000000000040;
  131. WASI_RIGHT_FD_ADVISE = $0000000000000080;
  132. WASI_RIGHT_FD_ALLOCATE = $0000000000000100;
  133. WASI_RIGHT_PATH_CREATE_DIRECTORY = $0000000000000200;
  134. WASI_RIGHT_PATH_CREATE_FILE = $0000000000000400;
  135. WASI_RIGHT_PATH_LINK_SOURCE = $0000000000000800;
  136. WASI_RIGHT_PATH_LINK_TARGET = $0000000000001000;
  137. WASI_RIGHT_PATH_OPEN = $0000000000002000;
  138. WASI_RIGHT_FD_READDIR = $0000000000004000;
  139. WASI_RIGHT_PATH_READLINK = $0000000000008000;
  140. WASI_RIGHT_PATH_RENAME_SOURCE = $0000000000010000;
  141. WASI_RIGHT_PATH_RENAME_TARGET = $0000000000020000;
  142. WASI_RIGHT_PATH_FILESTAT_GET = $0000000000040000;
  143. WASI_RIGHT_PATH_FILESTAT_SET_SIZE = $0000000000080000;
  144. WASI_RIGHT_PATH_FILESTAT_SET_TIMES = $0000000000100000;
  145. WASI_RIGHT_FD_FILESTAT_GET = $0000000000200000;
  146. WASI_RIGHT_FD_FILESTAT_SET_SIZE = $0000000000400000;
  147. WASI_RIGHT_FD_FILESTAT_SET_TIMES = $0000000000800000;
  148. WASI_RIGHT_PATH_SYMLINK = $0000000001000000;
  149. WASI_RIGHT_PATH_REMOVE_DIRECTORY = $0000000002000000;
  150. WASI_RIGHT_PATH_UNLINK_FILE = $0000000004000000;
  151. WASI_RIGHT_POLL_FD_READWRITE = $0000000008000000;
  152. WASI_RIGHT_SOCK_SHUTDOWN = $0000000010000000;
  153. RIGHTS_ALL = WASI_RIGHT_FD_DATASYNC or WASI_RIGHT_FD_READ
  154. or WASI_RIGHT_FD_SEEK or WASI_RIGHT_FD_FDSTAT_SET_FLAGS or WASI_RIGHT_FD_SYNC
  155. or WASI_RIGHT_FD_TELL or WASI_RIGHT_FD_WRITE or WASI_RIGHT_FD_ADVISE
  156. or WASI_RIGHT_FD_ALLOCATE or WASI_RIGHT_PATH_CREATE_DIRECTORY
  157. or WASI_RIGHT_PATH_CREATE_FILE or WASI_RIGHT_PATH_LINK_SOURCE
  158. or WASI_RIGHT_PATH_LINK_TARGET or WASI_RIGHT_PATH_OPEN or WASI_RIGHT_FD_READDIR
  159. or WASI_RIGHT_PATH_READLINK or WASI_RIGHT_PATH_RENAME_SOURCE
  160. or WASI_RIGHT_PATH_RENAME_TARGET or WASI_RIGHT_PATH_FILESTAT_GET
  161. or WASI_RIGHT_PATH_FILESTAT_SET_SIZE or WASI_RIGHT_PATH_FILESTAT_SET_TIMES
  162. or WASI_RIGHT_FD_FILESTAT_GET or WASI_RIGHT_FD_FILESTAT_SET_TIMES
  163. or WASI_RIGHT_FD_FILESTAT_SET_SIZE or WASI_RIGHT_PATH_SYMLINK
  164. or WASI_RIGHT_PATH_UNLINK_FILE or WASI_RIGHT_PATH_REMOVE_DIRECTORY
  165. or WASI_RIGHT_POLL_FD_READWRITE or WASI_RIGHT_SOCK_SHUTDOWN;
  166. RIGHTS_BLOCK_DEVICE_BASE = RIGHTS_ALL;
  167. RIGHTS_BLOCK_DEVICE_INHERITING = RIGHTS_ALL;
  168. RIGHTS_CHARACTER_DEVICE_BASE = RIGHTS_ALL;
  169. RIGHTS_CHARACTER_DEVICE_INHERITING = RIGHTS_ALL;
  170. RIGHTS_REGULAR_FILE_BASE = WASI_RIGHT_FD_DATASYNC or WASI_RIGHT_FD_READ
  171. or WASI_RIGHT_FD_SEEK or WASI_RIGHT_FD_FDSTAT_SET_FLAGS or WASI_RIGHT_FD_SYNC
  172. or WASI_RIGHT_FD_TELL or WASI_RIGHT_FD_WRITE or WASI_RIGHT_FD_ADVISE
  173. or WASI_RIGHT_FD_ALLOCATE or WASI_RIGHT_FD_FILESTAT_GET
  174. or WASI_RIGHT_FD_FILESTAT_SET_SIZE or WASI_RIGHT_FD_FILESTAT_SET_TIMES
  175. or WASI_RIGHT_POLL_FD_READWRITE;
  176. RIGHTS_REGULAR_FILE_INHERITING = 00;
  177. RIGHTS_DIRECTORY_BASE = WASI_RIGHT_FD_FDSTAT_SET_FLAGS
  178. or WASI_RIGHT_FD_SYNC or WASI_RIGHT_FD_ADVISE or WASI_RIGHT_PATH_CREATE_DIRECTORY
  179. or WASI_RIGHT_PATH_CREATE_FILE or WASI_RIGHT_PATH_LINK_SOURCE
  180. or WASI_RIGHT_PATH_LINK_TARGET or WASI_RIGHT_PATH_OPEN or WASI_RIGHT_FD_READDIR
  181. or WASI_RIGHT_PATH_READLINK or WASI_RIGHT_PATH_RENAME_SOURCE
  182. or WASI_RIGHT_PATH_RENAME_TARGET or WASI_RIGHT_PATH_FILESTAT_GET
  183. or WASI_RIGHT_PATH_FILESTAT_SET_SIZE or WASI_RIGHT_PATH_FILESTAT_SET_TIMES
  184. or WASI_RIGHT_FD_FILESTAT_GET or WASI_RIGHT_FD_FILESTAT_SET_TIMES
  185. or WASI_RIGHT_PATH_SYMLINK or WASI_RIGHT_PATH_UNLINK_FILE
  186. or WASI_RIGHT_PATH_REMOVE_DIRECTORY or WASI_RIGHT_POLL_FD_READWRITE;
  187. RIGHTS_DIRECTORY_INHERITING = RIGHTS_DIRECTORY_BASE
  188. or RIGHTS_REGULAR_FILE_BASE;
  189. RIGHTS_SOCKET_BASE = WASI_RIGHT_FD_READ or WASI_RIGHT_FD_FDSTAT_SET_FLAGS
  190. or WASI_RIGHT_FD_WRITE or WASI_RIGHT_FD_FILESTAT_GET
  191. or WASI_RIGHT_POLL_FD_READWRITE or WASI_RIGHT_SOCK_SHUTDOWN;
  192. RIGHTS_SOCKET_INHERITING = RIGHTS_ALL;
  193. RIGHTS_TTY_BASE = WASI_RIGHT_FD_READ or WASI_RIGHT_FD_FDSTAT_SET_FLAGS
  194. or WASI_RIGHT_FD_WRITE or WASI_RIGHT_FD_FILESTAT_GET
  195. or WASI_RIGHT_POLL_FD_READWRITE;
  196. RIGHTS_TTY_INHERITING = 0;
  197. WASI_CLOCK_MONOTONIC = 0;
  198. WASI_CLOCK_PROCESS_CPUTIME_ID = 1;
  199. WASI_CLOCK_REALTIME = 2;
  200. WASI_CLOCK_THREAD_CPUTIME_ID = 3;
  201. WASI_EVENTTYPE_CLOCK = 0;
  202. WASI_EVENTTYPE_FD_READ = 1;
  203. WASI_EVENTTYPE_FD_WRITE = 2;
  204. WASI_FILESTAT_SET_ATIM = 1 << 0;
  205. WASI_FILESTAT_SET_ATIM_NOW = 1 << 1;
  206. WASI_FILESTAT_SET_MTIM = 1 << 2;
  207. WASI_FILESTAT_SET_MTIM_NOW = 1 << 3;
  208. WASI_O_CREAT = 1 << 0;
  209. WASI_O_DIRECTORY = 1 << 1;
  210. WASI_O_EXCL = 1 << 2;
  211. WASI_O_TRUNC = 1 << 3;
  212. WASI_PREOPENTYPE_DIR = 0;
  213. WASI_DIRCOOKIE_START = 0;
  214. WASI_STDIN_FILENO = 0;
  215. WASI_STDOUT_FILENO = 1;
  216. WASI_STDERR_FILENO = 2;
  217. WASI_WHENCE_CUR = 0;
  218. WASI_WHENCE_END = 1;
  219. WASI_WHENCE_SET = 2;
  220. type
  221. // The imports as expected by WASI
  222. IWASI = interface ['{A03AC61B-3C68-4DA8-AC4F-53ED01814673}']
  223. // Please keep these sorted !!
  224. function args_get(argc, argvBufSize : NativeInt) : NativeInt;
  225. function args_sizes_get(argc, argvBufSize : NativeInt) : NativeInt;
  226. function clock_res_get(clockId, resolution: NativeInt): NativeInt;
  227. function clock_time_get(clockId, precision, time: NativeInt): NativeInt;
  228. function environ_get(environ, environBuf : NativeInt) : NativeInt;
  229. function environ_sizes_get(environCount, environBufSize : NativeInt) : NativeInt;
  230. function fd_advise (fd, offset, len, advice : NativeInt) : NativeInt;
  231. function fd_allocate (fd, offset, len : NativeInt) : NativeInt;
  232. function fd_close(fd : NativeInt) : NativeInt;
  233. function fd_datasync (fd : NativeInt) : NativeInt;
  234. function fd_fdstat_get(fd,bufPtr : NativeInt) : NativeInt;
  235. function fd_fdstat_set_flags (fd, flags: NativeInt) : NativeInt;
  236. function fd_fdstat_set_rights (fd, fsRightsBase, fsRightsInheriting: NativeInt) : NativeInt;
  237. function fd_filestat_get(fd, bufPtr : NativeInt) : NativeInt;
  238. function fd_filestat_set_size (fd, stSize: NativeInt) : NativeInt;
  239. function fd_filestat_set_times (fd, stAtim, stMtim, fstflags: NativeInt) : NativeInt;
  240. function fd_pread(fd, iovs, iovsLen, offset, nread : NativeInt) : NativeInt;
  241. function fd_prestat_dir_name(fd, pathPtr, pathLen : NativeInt) : NativeInt;
  242. function fd_prestat_get(fd, bufPtr: NativeInt) : NativeInt;
  243. function fd_pwrite(fd, iovs, iovsLen, offset, nwritten : NativeInt) : NativeInt;
  244. function fd_read(fd, iovs, iovsLen, nread : NativeInt) : NativeInt;
  245. function fd_readdir(fd, bufPtr, bufLen, cookie, bufusedPtr : NativeInt) : NativeInt;
  246. function fd_renumber(afrom,ato : NativeInt) : NativeInt;
  247. function fd_seek(fd, offset, whence, newOffsetPtr : NativeInt) : NativeInt;
  248. function fd_sync(fd : NativeInt) : NativeInt;
  249. function fd_tell(fd, offsetPtr: NativeInt) : NativeInt;
  250. function fd_write(fd,iovs,iovsLen,nwritten : NativeInt) : NativeInt;
  251. function path_create_directory (fd, pathPtr, pathLen : NativeInt) : NativeInt;
  252. function path_filestat_get (fd, flags, pathPtr, pathLen, bufPtr : NativeInt) : NativeInt;
  253. function path_filestat_set_times(fd, fstflags, pathPtr, pathLen, stAtim, stMtim : NativeInt) : NativeInt;
  254. function path_link (oldFd, oldFlags, oldPath, oldPathLen, newFd, newPath, newPathLen: NativeInt) : NativeInt;
  255. function path_open (dirfd, dirflags, pathPtr, pathLen, oflags, fsRightsBase, fsRightsInheriting, fsFlags, fd : NativeInt) : NativeInt;
  256. function path_readlink (fd, pathPtr, pathLen, buf, bufLen, bufused : NativeInt) : NativeInt;
  257. function path_remove_directory (fd, pathPtr, pathLen : NativeInt) : NativeInt;
  258. function path_rename (oldFd, oldPath, oldPathLen, newFd, newPath, newPathLen : NativeInt) : NativeInt;
  259. function path_symlink (oldPath, oldPathLen, fd, newPath, newPathLen : NativeInt) : NativeInt;
  260. function path_unlink_file (fd, pathPtr, pathLen : NativeInt) : NativeInt;
  261. function poll_oneoff(sin, sout, nsubscriptions, nevents : NativeInt) : NativeInt;
  262. function proc_exit(rval : NativeInt) : NativeInt;
  263. function proc_raise (sig : NativeInt) : NativeInt;
  264. function random_get (bufPtr, bufLen: NativeInt) : NativeInt;
  265. function sched_yield() : NativeInt;
  266. function sock_recv() : NativeInt;
  267. function sock_send() : NativeInt;
  268. function sock_shutdown() : NativeInt;
  269. end;
  270. TWASIWriteEvent = Reference to Procedure(Sender : TObject; Const aOutput : String);
  271. // Standard FPC exports.
  272. TWASIExports = Class External name 'Object' (TJSModulesExports)
  273. Public
  274. Procedure start; external name '_start';
  275. end;
  276. TGetConsoleInputBufferEvent = Reference to Procedure(Sender : TObject; Var AInput : TJSUint8Array);
  277. TGetConsoleInputStringEvent =Reference to Procedure (Sender : TObject; Var AInput : string);
  278. TImportExtension = Class;
  279. { TPas2JSWASIEnvironment }
  280. TPas2JSWASIEnvironment = class (TObject,IWASI)
  281. Private
  282. FExitCode: Nativeint;
  283. FImportObject : TJSObject;
  284. Finstance: TJSWebAssemblyInstance;
  285. FIsLittleEndian: Boolean;
  286. FModuleInstanceExports : TJSModulesExports;
  287. FOnGetConsoleInputBuffer: TGetConsoleInputBufferEvent;
  288. FOnGetConsoleInputString: TGetConsoleInputStringEvent;
  289. FOnStdErrorWrite: TWASIWriteEvent;
  290. FOnStdOutputWrite: TWASIWriteEvent;
  291. FImportExtensions : TFPList;
  292. FWASIImportName : string;
  293. function GetConsoleInputBuffer: TJSUint8Array;
  294. function GetFileBuffer(FD: NativeInt): TJSUint8Array;
  295. function GetImportObject: TJSObject;
  296. function getiovs(view: TJSDataView; iovs, iovsLen: NativeInt): TJSArray;
  297. procedure SetInstance(AValue: TJSWebAssemblyInstance);
  298. Protected
  299. Class Var UTF8TextDecoder: TJSTextDecoder;
  300. Protected
  301. class procedure setBigUint64(View: TJSDataView; byteOffset, value: NativeInt; littleEndian: Boolean);
  302. procedure DoConsoleWrite(IsStdErr: Boolean; aBytes: TJSArray); virtual;
  303. procedure GetImports(aImports: TJSObject); virtual;
  304. Function GetTime(aClockID : NativeInt): NativeInt; virtual;
  305. function getModuleMemoryDataView : TJSDataView;
  306. procedure AddExtension(aExtension : TImportExtension); virtual;
  307. procedure RemoveExtension(aExtension : TImportExtension); virtual;
  308. // IWASI calls
  309. // !! Please keep these sorted !!
  310. function args_get(argv, argvBuf : NativeInt) : NativeInt; virtual;
  311. function args_sizes_get(argc, argvBufSize : NativeInt) : NativeInt; virtual;
  312. function clock_res_get(clockId, resolution: NativeInt): NativeInt; virtual;
  313. function clock_time_get(clockId, precision, time: NativeInt): NativeInt; virtual;
  314. function environ_get(environ, environBuf : NativeInt) : NativeInt; virtual;
  315. function environ_sizes_get(environCount, environBufSize : NativeInt) : NativeInt; virtual;
  316. function fd_advise (fd, offset, len, advice : NativeInt) : NativeInt; virtual;
  317. function fd_allocate (fd, offset, len : NativeInt) : NativeInt; virtual;
  318. function fd_close(fd : NativeInt) : NativeInt; virtual;
  319. function fd_datasync (fd : NativeInt) : NativeInt; virtual;
  320. function fd_fdstat_get(fd,bufPtr : NativeInt) : NativeInt; virtual;
  321. function fd_fdstat_set_flags (fd, flags: NativeInt) : NativeInt; virtual;
  322. function fd_fdstat_set_rights (fd, fsRightsBase, fsRightsInheriting: NativeInt) : NativeInt; virtual;
  323. function fd_filestat_get (fd, bufPtr: NativeInt) : NativeInt; virtual;
  324. function fd_filestat_set_size (fd, stSize: NativeInt) : NativeInt; virtual;
  325. function fd_filestat_set_times (fd, stAtim, stMtim, fstflags: NativeInt) : NativeInt; virtual;
  326. function fd_pread(fd, iovs, iovsLen, offset, nread : NativeInt) : NativeInt; virtual;
  327. function fd_prestat_dir_name(fd, pathPtr, pathLen : NativeInt) : NativeInt; virtual;
  328. function fd_prestat_get(fd, bufPtr: NativeInt) : NativeInt; virtual;
  329. function fd_pwrite(fd, iovs, iovsLen, offset, nwritten : NativeInt) : NativeInt;virtual;
  330. function fd_read(fd, iovs, iovsLen, nread : NativeInt) : NativeInt; virtual;
  331. function fd_readdir(fd, bufPtr, bufLen, cookie, bufusedPtr : NativeInt) : NativeInt; virtual;
  332. function fd_renumber(afrom,ato : NativeInt) : NativeInt; virtual;
  333. function fd_seek(fd, offset, whence, newOffsetPtr : NativeInt) : NativeInt; virtual;
  334. function fd_sync(fd : NativeInt) : NativeInt; virtual;
  335. function fd_tell(fd, offsetPtr: NativeInt) : NativeInt; virtual;
  336. function fd_write(fd,iovs,iovsLen,nwritten : NativeInt) : NativeInt; virtual;
  337. function path_create_directory (fd, pathPtr, pathLen : NativeInt) : NativeInt;
  338. function path_filestat_get (fd, flags, pathPtr, pathLen, bufPtr : NativeInt) : NativeInt;
  339. function path_filestat_set_times(fd, fstflags, pathPtr, pathLen, stAtim, stMtim : NativeInt) : NativeInt;
  340. function path_link (oldFd, oldFlags, oldPath, oldPathLen, newFd, newPath, newPathLen: NativeInt) : NativeInt;
  341. function path_open (dirfd, dirflags, pathPtr, pathLen, oflags, fsRightsBase, fsRightsInheriting, fsFlags, fd : NativeInt) : NativeInt; virtual;
  342. function path_readlink (fd, pathPtr, pathLen, buf, bufLen, bufused : NativeInt) : NativeInt; virtual;
  343. function path_remove_directory (fd, pathPtr, pathLen : NativeInt) : NativeInt;
  344. function path_rename (oldFd, oldPath, oldPathLen, newFd, newPath, newPathLen : NativeInt) : NativeInt;
  345. function path_symlink (oldPath, oldPathLen, fd, newPath, newPathLen : NativeInt) : NativeInt;
  346. function path_unlink_file (fd, pathPtr, pathLen : NativeInt) : NativeInt;
  347. function poll_oneoff(sin, sout, nsubscriptions, nevents : NativeInt) : NativeInt; virtual;
  348. function proc_exit(rval : NativeInt) : NativeInt; virtual;
  349. function proc_raise (sig : NativeInt) : NativeInt; virtual;
  350. function random_get (bufPtr, bufLen: NativeInt) : NativeInt; virtual;
  351. function sched_yield() : NativeInt; virtual;
  352. function sock_recv() : NativeInt; virtual;
  353. function sock_send() : NativeInt; virtual;
  354. function sock_shutdown() : NativeInt; virtual;
  355. Public
  356. class constructor init;
  357. Constructor Create;
  358. Destructor Destroy; override;
  359. Function GetUTF8StringFromMem(aLoc, aLen : Longint) : String;
  360. // Add imports
  361. Procedure AddImports(aObject: TJSObject);
  362. Property ImportObject : TJSObject Read GetImportObject;
  363. Property IsLittleEndian : Boolean Read FIsLittleEndian Write FIsLittleEndian;
  364. Property OnStdOutputWrite : TWASIWriteEvent Read FOnStdOutputWrite Write FOnStdOutputWrite;
  365. Property OnStdErrorWrite : TWASIWriteEvent Read FOnStdErrorWrite Write FOnStdErrorWrite;
  366. Property OnGetConsoleInputBuffer : TGetConsoleInputBufferEvent Read FOnGetConsoleInputBuffer Write FOnGetConsoleInputBuffer;
  367. Property OnGetConsoleInputString : TGetConsoleInputStringEvent Read FOnGetConsoleInputString Write FOnGetConsoleInputString;
  368. Property Instance : TJSWebAssemblyInstance Read Finstance Write SetInstance;
  369. Property Exitcode : Nativeint Read FExitCode;
  370. // Default is set to the one expected by FPC runtime: wasi_snapshot_preview1
  371. Property WASIImportName : String Read FWASIImportName Write FWASIImportName;
  372. end;
  373. { TImportExtension }
  374. TImportExtension = class (TObject)
  375. Private
  376. FEnv : TPas2JSWASIEnvironment;
  377. Protected
  378. function getModuleMemoryDataView : TJSDataView;
  379. Public
  380. Constructor Create(aEnv : TPas2JSWASIEnvironment); virtual;
  381. Destructor Destroy; override;
  382. Procedure FillImportObject(aObject : TJSObject); virtual; abstract;
  383. Function ImportName : String; virtual; abstract;
  384. Property Env : TPas2JSWASIEnvironment Read FEnv;
  385. end;
  386. implementation
  387. uses web;
  388. function TImportExtension.getModuleMemoryDataView : TJSDataView;
  389. begin
  390. Result:=FEnv.getModuleMemoryDataView;
  391. end;
  392. constructor TImportExtension.Create(aEnv: TPas2JSWASIEnvironment);
  393. begin
  394. FEnv:=aEnv;
  395. if Assigned(Fenv) then
  396. Fenv.AddExtension(Self);
  397. end;
  398. destructor TImportExtension.Destroy;
  399. begin
  400. if Assigned(Fenv) then
  401. Fenv.RemoveExtension(Self);
  402. inherited Destroy;
  403. end;
  404. procedure TPas2JSWASIEnvironment.AddImports(aObject: TJSObject);
  405. Var
  406. Ext : TImportExtension;
  407. I : Integer;
  408. O : TJSObject;
  409. begin
  410. aObject[WASIImportName]:=ImportObject;
  411. if Assigned(FImportExtensions) then
  412. For I:=0 to FImportExtensions.Count-1 do
  413. begin
  414. Ext:=TImportExtension(FImportExtensions[i]);
  415. O:=TJSObject.New;
  416. Ext.FillImportObject(O);
  417. aObject[Ext.ImportName]:=O;
  418. end;
  419. end;
  420. procedure TPas2JSWASIEnvironment.AddExtension(aExtension : TImportExtension);
  421. begin
  422. if Not Assigned(FImportExtensions) then
  423. FImportExtensions:=TFPList.Create;
  424. FImportExtensions.Add(aExtension);
  425. end;
  426. procedure TPas2JSWASIEnvironment.RemoveExtension(aExtension: TImportExtension);
  427. begin
  428. if Assigned(FImportExtensions) then
  429. FImportExtensions.Remove(aExtension);
  430. end;
  431. function TPas2JSWASIEnvironment.getModuleMemoryDataView: TJSDataView;
  432. begin
  433. Result:=TJSDataView.New(FModuleInstanceExports.memory.buffer);
  434. end;
  435. function TPas2JSWASIEnvironment.fd_prestat_get(fd, bufPtr: NativeInt
  436. ): NativeInt;
  437. begin
  438. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_prestat_get');
  439. Result:=WASI_EBADF;
  440. end;
  441. function TPas2JSWASIEnvironment.fd_prestat_dir_name(fd, pathPtr,
  442. pathLen: NativeInt): NativeInt;
  443. begin
  444. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_prestat_dir_name');
  445. Result:=WASI_ENOSYS;
  446. end;
  447. function TPas2JSWASIEnvironment.environ_sizes_get(environCount,
  448. environBufSize: NativeInt): NativeInt;
  449. Var
  450. View : TJSDataView;
  451. begin
  452. view:=getModuleMemoryDataView();
  453. view.setUint32(environCount, 0, IsLittleEndian);
  454. view.setUint32(environBufSize, 0, IsLittleEndian);
  455. Result:= WASI_ESUCCESS;
  456. end;
  457. function TPas2JSWASIEnvironment.environ_get(environ, environBuf: NativeInt
  458. ): NativeInt;
  459. begin
  460. Result:= WASI_ESUCCESS;
  461. end;
  462. function TPas2JSWASIEnvironment.args_sizes_get(argc, argvBufSize: NativeInt
  463. ): NativeInt;
  464. Var
  465. View : TJSDataView;
  466. begin
  467. view:=getModuleMemoryDataView();
  468. view.setUint32(argc, 0, IsLittleEndian);
  469. view.setUint32(argvBufSize, 0, IsLittleEndian);
  470. Result:=WASI_ESUCCESS;
  471. end;
  472. function TPas2JSWASIEnvironment.args_get(argv, argvBuf: NativeInt): NativeInt;
  473. begin
  474. Result:=WASI_ESUCCESS;
  475. end;
  476. class procedure TPas2JSWASIEnvironment.setBigUint64(View: TJSDataView;
  477. byteOffset, value: NativeInt; littleEndian: Boolean);
  478. Var
  479. LowWord,HighWord : Integer;
  480. begin
  481. lowWord:=value;
  482. highWord:=0;
  483. if LittleEndian then
  484. begin
  485. view.setUint32(ByteOffset+0, lowWord, littleEndian);
  486. view.setUint32(ByteOffset+4, highWord, littleEndian);
  487. end
  488. else
  489. begin
  490. view.setUint32(ByteOffset+4, lowWord, littleEndian);
  491. view.setUint32(ByteOffset+0, highWord, littleEndian);
  492. end;
  493. end;
  494. procedure TPas2JSWASIEnvironment.SetInstance(AValue: TJSWebAssemblyInstance);
  495. begin
  496. if Finstance=AValue then Exit;
  497. Finstance:=AValue;
  498. FModuleInstanceExports:=Finstance.exports_;
  499. end;
  500. function TPas2JSWASIEnvironment.GetTime(aClockID: NativeInt): NativeInt;
  501. begin
  502. Result:=-1;
  503. Case aClockId of
  504. WASI_CLOCK_MONOTONIC:
  505. Result:=TJSDate.Now;
  506. WASI_CLOCK_REALTIME:
  507. Result:=TJSDate.Now;
  508. WASI_CLOCK_PROCESS_CPUTIME_ID,
  509. WASI_CLOCK_THREAD_CPUTIME_ID:
  510. Result:=TJSDate.Now;
  511. end;
  512. end;
  513. function TPas2JSWASIEnvironment.fd_fdstat_get(fd, bufPtr: NativeInt): NativeInt;
  514. Var
  515. View : TJSDataView;
  516. begin
  517. view:=getModuleMemoryDataView();
  518. view.setUint8(bufPtr, fd);
  519. view.setUint16(bufPtr + 2, 0, IsLittleEndian);
  520. view.setUint16(bufPtr + 4, 0, IsLittleEndian);
  521. setBigUint64(View, bufPtr + 8, 0, IsLittleEndian);
  522. setBigUint64(View, bufPtr + 8 + 8, 0, IsLittleEndian);
  523. Result:= WASI_ESUCCESS;
  524. end;
  525. function TPas2JSWASIEnvironment.fd_fdstat_set_flags(fd, flags: NativeInt): NativeInt;
  526. begin
  527. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_fdstat_set_flags');
  528. Result:= WASI_ENOSYS;
  529. end;
  530. function TPas2JSWASIEnvironment.fd_fdstat_set_rights(fd, fsRightsBase, fsRightsInheriting: NativeInt): NativeInt;
  531. begin
  532. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_fdstat_set_rights');
  533. Result:= WASI_ENOSYS;
  534. end;
  535. function TPas2JSWASIEnvironment.getiovs(view: TJSDataView; iovs,
  536. iovsLen: NativeInt): TJSArray;
  537. Var
  538. I : integer;
  539. ArrayBuf : TJSUint8Array;
  540. Ptr,Buf,BufLen : Integer;
  541. begin
  542. Result:=TJSArray.New;
  543. For I:=0 to iovsLen-1 do
  544. begin
  545. ptr:=iovs + i * 8;
  546. buf:=view.getUint32(ptr, IsLittleEndian);
  547. bufLen:=view.getUint32(ptr + 4, IsLittleEndian);
  548. ArrayBuf:=TJSUint8Array.New(FModuleInstanceExports.memory.buffer, buf, bufLen);
  549. Result.Push(ArrayBuf);
  550. end;
  551. end;
  552. function TPas2JSWASIEnvironment.fd_write(fd, iovs, iovsLen, nwritten: NativeInt): NativeInt;
  553. var
  554. view : TJSDataView;
  555. written : NativeInt;
  556. bufferBytes : TJSArray;
  557. Buffers : TJSArray;
  558. function writev(element : JSValue; index: NativeInt; anArray : TJSArray) : Boolean;
  559. var
  560. b : NativeInt;
  561. iov: TJSUint8Array absolute Element;
  562. begin
  563. For b:=0 to iov.byteLength-1 do
  564. bufferBytes.push(iov[b]);
  565. Inc(Written,iov.byteLength);
  566. Result:=true;
  567. end;
  568. begin
  569. BufferBytes:=TJSArray.New;
  570. view:=getModuleMemoryDataView();
  571. written:=0;
  572. buffers:=getiovs(view, iovs, iovsLen);
  573. buffers.forEach(@writev);
  574. if (fd = WASI_STDOUT_FILENO) or (fd = WASI_STDERR_FILENO) then
  575. DoConsoleWrite((fd=WASI_STDERR_FILENO),BufferBytes);
  576. view.setUint32(nwritten, written, IsLittleEndian);
  577. Result:=WASI_ESUCCESS;
  578. end;
  579. function TPas2JSWASIEnvironment.fd_pwrite(fd, iovs, iovsLen, offset,
  580. nwritten: NativeInt): NativeInt;
  581. begin
  582. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_pwrite');
  583. Result:=WASI_ENOSYS;
  584. end;
  585. procedure TPas2JSWASIEnvironment.DoConsoleWrite(IsStdErr: Boolean;
  586. aBytes: TJSArray);
  587. Var
  588. S : String;
  589. begin
  590. asm
  591. // Result=String.fromCharCode.apply(null, new Uint16Array(a));
  592. S=String.fromCharCode.apply(null, aBytes);
  593. end;
  594. if IsStdErr then
  595. begin
  596. if Assigned(FOnStdErrorWrite) then
  597. FOnStdErrorWrite(Self,S)
  598. end
  599. else
  600. begin
  601. if Assigned(FOnStdOutputWrite) then
  602. FOnStdOutputWrite(Self,S)
  603. end
  604. end;
  605. function TPas2JSWASIEnvironment.clock_res_get (clockId, resolution : NativeInt) : NativeInt;
  606. Var
  607. view: TJSDataView;
  608. begin
  609. view:=getModuleMemoryDataView;
  610. setBigUint64(view,resolution, 0,IsLittleEndian);
  611. Result:=WASI_ESUCCESS;
  612. end;
  613. function TPas2JSWASIEnvironment.clock_time_get(clockId, precision, time: NativeInt) : NativeInt;
  614. Var
  615. view: TJSDataView;
  616. n : NativeInt;
  617. begin
  618. view:=getModuleMemoryDataView;
  619. n:=GetTime(clockId);
  620. if N=-1 then
  621. Result:=WASI_EINVAL
  622. else
  623. begin
  624. setBigUint64(view,time,n,IsLittleEndian);
  625. Result:=WASI_ESUCCESS;
  626. end;
  627. end;
  628. function TPas2JSWASIEnvironment.GetImportObject: TJSObject;
  629. begin
  630. // We need this trick to be able to access self or this.
  631. // The webassembly callbacks get called without a this.
  632. if Not Assigned(FImportObject) then
  633. begin
  634. FImportObject:=TJSObject.New;
  635. GetImports(FImportObject);
  636. end;
  637. Result:=FImportObject;
  638. end;
  639. procedure TPas2JSWASIEnvironment.GetImports(aImports: TJSObject);
  640. begin
  641. aImports['args_get']:=@args_get;
  642. aImports['args_sizes_get']:=@args_sizes_get;
  643. aImports['clock_res_get']:=@clock_res_get;
  644. aImports['clock_time_get']:=@clock_time_get;
  645. aImports['environ_get']:=@environ_get;
  646. aImports['environ_sizes_get']:=@environ_sizes_get;
  647. aImports['fd_advise']:=@fd_advise;
  648. aImports['fd_allocate']:=@fd_allocate;
  649. aImports['fd_close']:=@fd_close;
  650. aImports['fd_datasync']:=@fd_datasync;
  651. aImports['fd_fdstat_get']:=@fd_fdstat_get;
  652. aImports['fd_fdstat_set_flags']:=@fd_fdstat_set_flags;
  653. aImports['fd_fdstat_set_rights']:=@fd_fdstat_set_rights;
  654. aImports['fd_filestat_get']:=@fd_filestat_get;
  655. aImports['fd_filestat_set_size']:=@fd_filestat_set_size;
  656. aImports['fd_filestat_set_times']:=@fd_filestat_set_times;
  657. aImports['fd_pread']:=@fd_pread;
  658. aImports['fd_prestat_dir_name']:=@fd_prestat_dir_name;
  659. aImports['fd_prestat_get']:=@fd_prestat_get;
  660. aImports['fd_pwrite']:=@fd_pwrite;
  661. aImports['fd_read']:=@fd_read;
  662. aImports['fd_readdir']:=@fd_readdir;
  663. aImports['fd_renumber']:=@fd_renumber;
  664. aImports['fd_seek']:=@fd_seek;
  665. aImports['fd_sync']:=@fd_sync;
  666. aImports['fd_tell']:=@fd_tell;
  667. aImports['fd_write']:=@fd_write;
  668. aImports['path_create_directory']:=@path_create_directory;
  669. aImports['path_filestat_get']:=@path_filestat_get;
  670. aImports['path_filestat_set_times']:=@path_filestat_set_times;
  671. aImports['path_link']:=@path_link;
  672. aImports['path_open']:=@path_open;
  673. aImports['path_readlink']:=@path_readlink;
  674. aImports['path_remove_directory']:=@path_remove_directory;
  675. aImports['path_rename']:=@path_rename;
  676. aImports['path_symlink']:=@path_symlink;
  677. aImports['path_unlink_file']:=@path_unlink_file;
  678. aImports['poll_oneoff']:=@poll_oneoff;
  679. aImports['proc_exit']:=@proc_exit;
  680. aImports['proc_raise']:=@proc_raise;
  681. aImports['random_get']:=@random_get;
  682. aImports['sched_yield']:=@sched_yield;
  683. aImports['sock_recv']:=@sock_recv;
  684. aImports['sock_recv']:=@sock_recv;
  685. aImports['sock_shutdown']:=@sock_shutdown;
  686. end;
  687. function TPas2JSWASIEnvironment.poll_oneoff(sin, sout, nsubscriptions,
  688. nevents: NativeInt): NativeInt;
  689. begin
  690. console.log('Unimplemented: TPas2JSWASIEnvironment.poll_oneoff');
  691. Result:= WASI_ENOSYS;
  692. end;
  693. function TPas2JSWASIEnvironment.proc_exit(rval: NativeInt): NativeInt;
  694. begin
  695. FExitCode:=rval;
  696. Result:=WASI_ESUCCESS;
  697. end;
  698. function TPas2JSWASIEnvironment.proc_raise(sig: NativeInt): NativeInt;
  699. begin
  700. console.log('Unimplemented: TPas2JSWASIEnvironment.proc_raise');
  701. Result:=WASI_ENOSYS;
  702. end;
  703. function TPas2JSWASIEnvironment.random_get(bufPtr, bufLen: NativeInt ): NativeInt;
  704. var
  705. arr: TJSUint8Array;
  706. I : integer;
  707. View : TJSDataView;
  708. begin
  709. arr:=TJSUint8Array.new(BufLen);
  710. window.crypto.getRandomValues(arr);
  711. view:=getModuleMemoryDataView;
  712. For I:=0 to arr.length-1 do
  713. view.setInt8(bufptr+i,arr[i]);
  714. Result:=WASI_ESUCCESS;
  715. end;
  716. function TPas2JSWASIEnvironment.sched_yield: NativeInt;
  717. begin
  718. Result:=WASI_ESUCCESS;
  719. end;
  720. function TPas2JSWASIEnvironment.sock_recv: NativeInt;
  721. begin
  722. console.log('Unimplemented: TPas2JSWASIEnvironment.sock_recv');
  723. Result:=WASI_ENOSYS;
  724. end;
  725. function TPas2JSWASIEnvironment.sock_send: NativeInt;
  726. begin
  727. console.log('Unimplemented: TPas2JSWASIEnvironment.sock_recv');
  728. Result:=WASI_ENOSYS;
  729. end;
  730. function TPas2JSWASIEnvironment.sock_shutdown: NativeInt;
  731. begin
  732. console.log('Unimplemented: TPas2JSWASIEnvironment.sock_shutdown');
  733. Result:=WASI_ENOSYS;
  734. end;
  735. class constructor TPas2JSWASIEnvironment.init;
  736. Var
  737. Opts : TJSTextDecoderOptions;
  738. begin
  739. Opts:=TJSTextDecoderOptions.New;
  740. Opts.ignoreBOM:=true;
  741. Opts.fatal:=True;
  742. UTF8TextDecoder:=TJSTextDecoder.new ('utf-8',Opts);
  743. end;
  744. function TPas2JSWASIEnvironment.fd_advise(fd, offset, len, advice: NativeInt
  745. ): NativeInt;
  746. begin
  747. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_advise');
  748. Result:= WASI_ENOSYS;
  749. end;
  750. function TPas2JSWASIEnvironment.fd_allocate(fd, offset, len: NativeInt
  751. ): NativeInt;
  752. begin
  753. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_allocate');
  754. Result:= WASI_ENOSYS;
  755. end;
  756. function TPas2JSWASIEnvironment.fd_close(fd: NativeInt): NativeInt;
  757. begin
  758. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_close');
  759. Result:= WASI_ENOSYS;
  760. end;
  761. function TPas2JSWASIEnvironment.fd_datasync(fd: NativeInt): NativeInt;
  762. begin
  763. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_datasync');
  764. Result:= WASI_ENOSYS;
  765. end;
  766. function TPas2JSWASIEnvironment.fd_seek(fd, offset, whence,
  767. newOffsetPtr: NativeInt): NativeInt;
  768. begin
  769. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_seek');
  770. Result:= WASI_ENOSYS;
  771. end;
  772. function TPas2JSWASIEnvironment.fd_sync(fd: NativeInt): NativeInt;
  773. begin
  774. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_sync');
  775. Result:= WASI_ENOSYS;
  776. end;
  777. function TPas2JSWASIEnvironment.fd_pread(fd, iovs, iovsLen, offset,
  778. nread: NativeInt): NativeInt;
  779. begin
  780. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_pread');
  781. Result:= WASI_ENOSYS;
  782. end;
  783. function toUTF8Array(str : string) : TJSUint8Array;
  784. Var
  785. Len,I,P : integer;
  786. charCode : NativeInt;
  787. procedure push (abyte : Byte);
  788. begin
  789. Result[P]:=aByte;
  790. inc(P);
  791. end;
  792. begin
  793. Result:=TJSUint8Array.new(Length(str)*4);
  794. P:=0;
  795. Len:=Length(str);
  796. I:=1;
  797. While i<=Len do
  798. begin
  799. charcode:=Ord(Str[i]);
  800. if (charcode < $80) then
  801. push(charcode)
  802. else if (charcode < $800) then
  803. begin
  804. push($c0 or (charcode shr 6));
  805. push($80 or (charcode and $3f));
  806. end
  807. else if (charcode < $d800) or (charcode >= $e000) then
  808. begin
  809. push($e0 or (charcode shr 12));
  810. push($80 or ((charcode shr 6) and $3f));
  811. push($80 or (charcode and $3f));
  812. end
  813. else
  814. begin
  815. Inc(I);
  816. // UTF-16 encodes 0x10000-0x10FFFF by
  817. // subtracting 0x10000 and splitting the
  818. // 20 bits of 0x0-0xFFFFF into two halves
  819. charcode := $10000 + (((charcode and $3ff) shl 10) or (Ord(Str[i]) and $3ff));
  820. push($f0 or (charcode shr 18));
  821. push($80 or ((charcode shr 12) and $3f));
  822. push($80 or ((charcode shr 6) and $3f));
  823. push($80 or (charcode and $3f));
  824. end;
  825. inc(I);
  826. end;
  827. Result:=TJSUint8Array(Result.slice(0,p));
  828. end;
  829. function TPas2JSWASIEnvironment.fd_read(fd, iovs, iovsLen, nread: NativeInt
  830. ): NativeInt;
  831. var
  832. view : TJSDataView;
  833. bytesRead : NativeInt;
  834. bufferBytes : TJSUint8Array;
  835. Buffers : TJSArray;
  836. function readv(element : JSValue; index: NativeInt; anArray : TJSArray) : Boolean;
  837. var
  838. b : NativeInt;
  839. iov: TJSUint8Array absolute Element;
  840. begin
  841. b:=0;
  842. While (B<iov.byteLength) and (BytesRead<BufferBytes.Length) do
  843. begin
  844. iov[b]:=BufferBytes[BytesRead];
  845. inc(b);
  846. inc(BytesRead);
  847. end;
  848. Result:=true;
  849. end;
  850. begin
  851. bytesRead:=0;
  852. view:=getModuleMemoryDataView();
  853. if (fd = WASI_STDIN_FILENO) then
  854. begin
  855. BufferBytes:=GetConsoleInputBuffer
  856. end
  857. else
  858. BufferBytes:=GetFileBuffer(FD);
  859. if BufferBytes.length>0 then
  860. begin
  861. buffers:=getiovs(view, iovs, iovsLen);
  862. buffers.forEach(@readv);
  863. end;
  864. view.setUint32(nread, bytesRead, IsLittleEndian);
  865. Result:=WASI_ESUCCESS;
  866. end;
  867. function TPas2JSWASIEnvironment.GetFileBuffer(FD : NativeInt): TJSUint8Array;
  868. begin
  869. Result:=TJSUint8Array.new(0);
  870. end;
  871. function TPas2JSWASIEnvironment.GetConsoleInputBuffer : TJSUint8Array;
  872. Var
  873. S : String;
  874. begin
  875. Result:=Nil;
  876. If Assigned(OnGetConsoleInputBuffer) then
  877. OnGetConsoleInputBuffer(Self,Result)
  878. else If Assigned(OnGetConsoleInputString) then
  879. begin
  880. S:='';
  881. OnGetConsoleInputString(Self,S);
  882. Result:=toUTF8Array(S);
  883. end
  884. else
  885. Result:=TJSUint8Array.New(0);
  886. end;
  887. function TPas2JSWASIEnvironment.fd_readdir(fd, bufPtr, bufLen, cookie,
  888. bufusedPtr: NativeInt): NativeInt;
  889. begin
  890. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_readdir');
  891. Result:= WASI_ENOSYS;
  892. end;
  893. function TPas2JSWASIEnvironment.fd_renumber(afrom, ato: NativeInt): NativeInt;
  894. begin
  895. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_renumber');
  896. Result:= WASI_ENOSYS;
  897. end;
  898. function TPas2JSWASIEnvironment.fd_tell(fd, offsetPtr: NativeInt): NativeInt;
  899. begin
  900. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_tell');
  901. Result:= WASI_ENOSYS;
  902. end;
  903. function TPas2JSWASIEnvironment.fd_filestat_get(fd, bufPtr: NativeInt
  904. ): NativeInt;
  905. begin
  906. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_filestat_get');
  907. Result:= WASI_ENOSYS;
  908. end;
  909. function TPas2JSWASIEnvironment.fd_filestat_set_size(fd, stSize: NativeInt
  910. ): NativeInt;
  911. begin
  912. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_filestat_set_size');
  913. Result:= WASI_ENOSYS;
  914. end;
  915. function TPas2JSWASIEnvironment.fd_filestat_set_times(fd, stAtim, stMtim,
  916. fstflags: NativeInt): NativeInt;
  917. begin
  918. console.log('Unimplemented: TPas2JSWASIEnvironment.fd_filestat_set_times');
  919. Result:= WASI_ENOSYS;
  920. end;
  921. function TPas2JSWASIEnvironment.path_readlink(fd, pathPtr, pathLen, buf,
  922. bufLen, bufused: NativeInt): NativeInt;
  923. begin
  924. console.log('Unimplemented: TPas2JSWASIEnvironment.path_readlink');
  925. Result:= WASI_ENOSYS;
  926. end;
  927. function TPas2JSWASIEnvironment.path_create_directory(fd, pathPtr,
  928. pathLen: NativeInt): NativeInt;
  929. begin
  930. console.log('Unimplemented: TPas2JSWASIEnvironment.path_create_directory');
  931. Result:= WASI_ENOSYS;
  932. end;
  933. function TPas2JSWASIEnvironment.path_filestat_get(fd, flags, pathPtr, pathLen,
  934. bufPtr: NativeInt): NativeInt;
  935. begin
  936. console.log('Unimplemented: TPas2JSWASIEnvironment.path_filestat_get');
  937. Result:= WASI_ENOSYS;
  938. end;
  939. function TPas2JSWASIEnvironment.path_link(oldFd, oldFlags, oldPath, oldPathLen,
  940. newFd, newPath, newPathLen: NativeInt): NativeInt;
  941. begin
  942. console.log('Unimplemented: TPas2JSWASIEnvironment.path_link');
  943. Result:= WASI_ENOSYS;
  944. end;
  945. function TPas2JSWASIEnvironment.path_remove_directory(fd, pathPtr,
  946. pathLen: NativeInt): NativeInt;
  947. begin
  948. console.log('Unimplemented: TPas2JSWASIEnvironment.path_remove_directory');
  949. Result:= WASI_ENOSYS;
  950. end;
  951. function TPas2JSWASIEnvironment.path_rename(oldFd, oldPath, oldPathLen, newFd,
  952. newPath, newPathLen: NativeInt): NativeInt;
  953. begin
  954. console.log('Unimplemented: TPas2JSWASIEnvironment.path_rename');
  955. Result:= WASI_ENOSYS;
  956. end;
  957. function TPas2JSWASIEnvironment.path_symlink(oldPath, oldPathLen, fd, newPath,
  958. newPathLen: NativeInt): NativeInt;
  959. begin
  960. console.log('Unimplemented: TPas2JSWASIEnvironment.path_symlink');
  961. Result:= WASI_ENOSYS;
  962. end;
  963. function TPas2JSWASIEnvironment.path_unlink_file(fd, pathPtr, pathLen: NativeInt
  964. ): NativeInt;
  965. begin
  966. console.log('Unimplemented: TPas2JSWASIEnvironment.path_unlink_file');
  967. Result:= WASI_ENOSYS;
  968. end;
  969. function TPas2JSWASIEnvironment.path_open(dirfd, dirflags, pathPtr, pathLen,
  970. oflags, fsRightsBase, fsRightsInheriting, fsFlags, fd: NativeInt): NativeInt;
  971. begin
  972. console.log('Unimplemented: TPas2JSWASIEnvironment.path_open');
  973. Result:= WASI_ENOSYS;
  974. end;
  975. function TPas2JSWASIEnvironment.path_filestat_set_times(fd, fstflags, pathPtr,
  976. pathLen, stAtim, stMtim: NativeInt): NativeInt;
  977. begin
  978. console.log('Unimplemented: TPas2JSWASIEnvironment.path_filestat_set_times');
  979. Result:= WASI_ENOSYS;
  980. end;
  981. constructor TPas2JSWASIEnvironment.Create;
  982. begin
  983. FIsLittleEndian:=True;
  984. // Default expected by FPC runtime
  985. WASIImportName:='wasi_snapshot_preview1';
  986. end;
  987. destructor TPas2JSWASIEnvironment.Destroy;
  988. begin
  989. FreeAndNil(FImportExtensions);
  990. inherited Destroy;
  991. end;
  992. function TPas2JSWASIEnvironment.GetUTF8StringFromMem(aLoc, aLen: Longint): String;
  993. begin
  994. Result:=UTF8TextDecoder.Decode(getModuleMemoryDataView.buffer.slice(aLoc,aLoc+alen));
  995. end;
  996. initialization
  997. end.