├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── deno.d.ts ├── fixtures └── sample.txt ├── package.json ├── src ├── __tests__ │ ├── fs.test.ts │ ├── io.test.ts │ └── os.test.ts ├── buffer.ts ├── deno.ts ├── encoding.ts ├── file.ts ├── net.ts ├── polyfill.ts ├── process.ts ├── resources.ts └── util.ts ├── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_size = 2 3 | 4 | [Makefile] 5 | indent_style = tab -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_store 3 | .idea 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Yusuke Sakurai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [WIP] denode 2 | Deno polyfill for Node.js 3 | -------------------------------------------------------------------------------- /deno.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. 2 | 3 | /* eslint-disable @typescript-eslint/no-explicit-any */ 4 | /* eslint-disable @typescript-eslint/no-empty-interface */ 5 | 6 | /// 7 | /// 8 | 9 | declare namespace Deno { 10 | // @url js/os.d.ts 11 | 12 | /** The current process id of the runtime. */ 13 | export let pid: number; 14 | /** Reflects the NO_COLOR environment variable: https://no-color.org/ */ 15 | export let noColor: boolean; 16 | /** Check if running in terminal. 17 | * 18 | * console.log(Deno.isTTY().stdout); 19 | */ 20 | export function isTTY(): { 21 | stdin: boolean; 22 | stdout: boolean; 23 | stderr: boolean; 24 | }; 25 | /** Get the hostname. 26 | * Requires the `--allow-env` flag. 27 | * 28 | * console.log(Deno.hostname()); 29 | */ 30 | export function hostname(): string; 31 | /** Exit the Deno process with optional exit code. */ 32 | export function exit(code?: number): never; 33 | /** Returns a snapshot of the environment variables at invocation. Mutating a 34 | * property in the object will set that variable in the environment for 35 | * the process. The environment object will only accept `string`s 36 | * as values. 37 | * 38 | * const myEnv = Deno.env(); 39 | * console.log(myEnv.SHELL); 40 | * myEnv.TEST_VAR = "HELLO"; 41 | * const newEnv = Deno.env(); 42 | * console.log(myEnv.TEST_VAR == newEnv.TEST_VAR); 43 | */ 44 | export function env(): { 45 | [index: string]: string; 46 | }; 47 | /** Returns the value of an environment variable at invocation. 48 | * If the variable is not present, `undefined` will be returned. 49 | * 50 | * const myEnv = Deno.env(); 51 | * console.log(myEnv.SHELL); 52 | * myEnv.TEST_VAR = "HELLO"; 53 | * const newEnv = Deno.env(); 54 | * console.log(myEnv.TEST_VAR == newEnv.TEST_VAR); 55 | */ 56 | export function env(key: string): string | undefined; 57 | /** 58 | * Returns the current user's home directory. 59 | * Requires the `--allow-env` flag. 60 | */ 61 | export function homeDir(): string; 62 | /** 63 | * Returns the path to the current deno executable. 64 | * Requires the `--allow-env` flag. 65 | */ 66 | export function execPath(): string; 67 | 68 | // @url js/dir.d.ts 69 | 70 | /** 71 | * `cwd()` Return a string representing the current working directory. 72 | * If the current directory can be reached via multiple paths 73 | * (due to symbolic links), `cwd()` may return 74 | * any one of them. 75 | * throws `NotFound` exception if directory not available 76 | */ 77 | export function cwd(): string; 78 | /** 79 | * `chdir()` Change the current working directory to path. 80 | * throws `NotFound` exception if directory not available 81 | */ 82 | export function chdir(directory: string): void; 83 | 84 | // @url js/io.d.ts 85 | 86 | export const EOF: unique symbol; 87 | export type EOF = typeof EOF; 88 | export enum SeekMode { 89 | SEEK_START = 0, 90 | SEEK_CURRENT = 1, 91 | SEEK_END = 2 92 | } 93 | export interface Reader { 94 | /** Reads up to p.byteLength bytes into `p`. It resolves to the number 95 | * of bytes read (`0` < `n` <= `p.byteLength`) and rejects if any error encountered. 96 | * Even if `read()` returns `n` < `p.byteLength`, it may use all of `p` as 97 | * scratch space during the call. If some data is available but not 98 | * `p.byteLength` bytes, `read()` conventionally returns what is available 99 | * instead of waiting for more. 100 | * 101 | * When `read()` encounters end-of-file condition, it returns EOF symbol. 102 | * 103 | * When `read()` encounters an error, it rejects with an error. 104 | * 105 | * Callers should always process the `n` > `0` bytes returned before 106 | * considering the EOF. Doing so correctly handles I/O errors that happen 107 | * after reading some bytes and also both of the allowed EOF behaviors. 108 | * 109 | * Implementations must not retain `p`. 110 | */ 111 | read(p: Uint8Array): Promise; 112 | } 113 | export interface SyncReader { 114 | readSync(p: Uint8Array): number | EOF; 115 | } 116 | export interface Writer { 117 | /** Writes `p.byteLength` bytes from `p` to the underlying data 118 | * stream. It resolves to the number of bytes written from `p` (`0` <= `n` <= 119 | * `p.byteLength`) and any error encountered that caused the write to stop 120 | * early. `write()` must return a non-null error if it returns `n` < 121 | * `p.byteLength`. write() must not modify the slice data, even temporarily. 122 | * 123 | * Implementations must not retain `p`. 124 | */ 125 | write(p: Uint8Array): Promise; 126 | } 127 | export interface SyncWriter { 128 | writeSync(p: Uint8Array): number; 129 | } 130 | export interface Closer { 131 | close(): void; 132 | } 133 | export interface Seeker { 134 | /** Seek sets the offset for the next `read()` or `write()` to offset, 135 | * interpreted according to `whence`: `SeekStart` means relative to the start 136 | * of the file, `SeekCurrent` means relative to the current offset, and 137 | * `SeekEnd` means relative to the end. Seek returns the new offset relative 138 | * to the start of the file and an error, if any. 139 | * 140 | * Seeking to an offset before the start of the file is an error. Seeking to 141 | * any positive offset is legal, but the behavior of subsequent I/O operations 142 | * on the underlying object is implementation-dependent. 143 | */ 144 | seek(offset: number, whence: SeekMode): Promise; 145 | } 146 | export interface SyncSeeker { 147 | seekSync(offset: number, whence: SeekMode): void; 148 | } 149 | export interface ReadCloser extends Reader, Closer {} 150 | export interface WriteCloser extends Writer, Closer {} 151 | export interface ReadSeeker extends Reader, Seeker {} 152 | export interface WriteSeeker extends Writer, Seeker {} 153 | export interface ReadWriteCloser extends Reader, Writer, Closer {} 154 | export interface ReadWriteSeeker extends Reader, Writer, Seeker {} 155 | /** Copies from `src` to `dst` until either `EOF` is reached on `src` 156 | * or an error occurs. It returns the number of bytes copied and the first 157 | * error encountered while copying, if any. 158 | * 159 | * Because `copy()` is defined to read from `src` until `EOF`, it does not 160 | * treat an `EOF` from `read()` as an error to be reported. 161 | */ 162 | export function copy(dst: Writer, src: Reader): Promise; 163 | /** Turns `r` into async iterator. 164 | * 165 | * for await (const chunk of toAsyncIterator(reader)) { 166 | * console.log(chunk) 167 | * } 168 | */ 169 | export function toAsyncIterator(r: Reader): AsyncIterableIterator; 170 | 171 | // @url js/files.d.ts 172 | 173 | /** Open a file and return an instance of the `File` object 174 | * synchronously. 175 | * 176 | * const file = Deno.openSync("/foo/bar.txt"); 177 | */ 178 | export function openSync(filename: string, mode?: OpenMode): File; 179 | /** Open a file and return an instance of the `File` object. 180 | * 181 | * (async () => { 182 | * const file = await Deno.open("/foo/bar.txt"); 183 | * })(); 184 | */ 185 | export function open(filename: string, mode?: OpenMode): Promise; 186 | /** Read synchronously from a file ID into an array buffer. 187 | * 188 | * Return `number | EOF` for the operation. 189 | * 190 | * const file = Deno.openSync("/foo/bar.txt"); 191 | * const buf = new Uint8Array(100); 192 | * const nread = Deno.readSync(file.rid, buf); 193 | * const text = new TextDecoder().decode(buf); 194 | * 195 | */ 196 | export function readSync(rid: number, p: Uint8Array): number | EOF; 197 | /** Read from a file ID into an array buffer. 198 | * 199 | * Resolves with the `number | EOF` for the operation. 200 | * 201 | * (async () => { 202 | * const file = await Deno.open("/foo/bar.txt"); 203 | * const buf = new Uint8Array(100); 204 | * const nread = await Deno.read(file.rid, buf); 205 | * const text = new TextDecoder().decode(buf); 206 | * })(); 207 | */ 208 | export function read(rid: number, p: Uint8Array): Promise; 209 | /** Write synchronously to the file ID the contents of the array buffer. 210 | * 211 | * Resolves with the number of bytes written. 212 | * 213 | * const encoder = new TextEncoder(); 214 | * const data = encoder.encode("Hello world\n"); 215 | * const file = Deno.openSync("/foo/bar.txt"); 216 | * Deno.writeSync(file.rid, data); 217 | */ 218 | export function writeSync(rid: number, p: Uint8Array): number; 219 | /** Write to the file ID the contents of the array buffer. 220 | * 221 | * Resolves with the number of bytes written. 222 | * 223 | * (async () => { 224 | * const encoder = new TextEncoder(); 225 | * const data = encoder.encode("Hello world\n"); 226 | * const file = await Deno.open("/foo/bar.txt"); 227 | * await Deno.write(file.rid, data); 228 | * })(); 229 | * 230 | */ 231 | export function write(rid: number, p: Uint8Array): Promise; 232 | /** Seek a file ID synchronously to the given offset under mode given by `whence`. 233 | * 234 | * const file = Deno.openSync("/foo/bar.txt"); 235 | * Deno.seekSync(file.rid, 0, 0); 236 | */ 237 | export function seekSync(rid: number, offset: number, whence: SeekMode): void; 238 | /** Seek a file ID to the given offset under mode given by `whence`. 239 | * 240 | * (async () => { 241 | * const file = await Deno.open("/foo/bar.txt"); 242 | * await Deno.seek(file.rid, 0, 0); 243 | * })(); 244 | */ 245 | export function seek( 246 | rid: number, 247 | offset: number, 248 | whence: SeekMode 249 | ): Promise; 250 | /** Close the file ID. */ 251 | export function close(rid: number): void; 252 | /** The Deno abstraction for reading and writing files. */ 253 | export class File 254 | implements 255 | Reader, 256 | SyncReader, 257 | Writer, 258 | SyncWriter, 259 | Seeker, 260 | SyncSeeker, 261 | Closer { 262 | readonly rid: number; 263 | constructor(rid: number); 264 | write(p: Uint8Array): Promise; 265 | writeSync(p: Uint8Array): number; 266 | read(p: Uint8Array): Promise; 267 | readSync(p: Uint8Array): number | EOF; 268 | seek(offset: number, whence: SeekMode): Promise; 269 | seekSync(offset: number, whence: SeekMode): void; 270 | close(): void; 271 | } 272 | /** An instance of `File` for stdin. */ 273 | export const stdin: File; 274 | /** An instance of `File` for stdout. */ 275 | export const stdout: File; 276 | /** An instance of `File` for stderr. */ 277 | export const stderr: File; 278 | export type OpenMode = 279 | | "r" 280 | /** Read-write. Start at beginning of file. */ 281 | | "r+" 282 | /** Write-only. Opens and truncates existing file or creates new one for 283 | * writing only. 284 | */ 285 | | "w" 286 | /** Read-write. Opens and truncates existing file or creates new one for 287 | * writing and reading. 288 | */ 289 | | "w+" 290 | /** Write-only. Opens existing file or creates new one. Each write appends 291 | * content to the end of file. 292 | */ 293 | | "a" 294 | /** Read-write. Behaves like "a" and allows to read from file. */ 295 | | "a+" 296 | /** Write-only. Exclusive create - creates new file only if one doesn't exist 297 | * already. 298 | */ 299 | | "x" 300 | /** Read-write. Behaves like `x` and allows to read from file. */ 301 | | "x+"; 302 | 303 | // @url js/buffer.d.ts 304 | 305 | /** A Buffer is a variable-sized buffer of bytes with read() and write() 306 | * methods. Based on https://golang.org/pkg/bytes/#Buffer 307 | */ 308 | export class Buffer implements Reader, SyncReader, Writer, SyncWriter { 309 | private buf; 310 | private off; 311 | constructor(ab?: ArrayBuffer); 312 | /** bytes() returns a slice holding the unread portion of the buffer. 313 | * The slice is valid for use only until the next buffer modification (that 314 | * is, only until the next call to a method like read(), write(), reset(), or 315 | * truncate()). The slice aliases the buffer content at least until the next 316 | * buffer modification, so immediate changes to the slice will affect the 317 | * result of future reads. 318 | */ 319 | bytes(): Uint8Array; 320 | /** toString() returns the contents of the unread portion of the buffer 321 | * as a string. Warning - if multibyte characters are present when data is 322 | * flowing through the buffer, this method may result in incorrect strings 323 | * due to a character being split. 324 | */ 325 | toString(): string; 326 | /** empty() returns whether the unread portion of the buffer is empty. */ 327 | empty(): boolean; 328 | /** length is a getter that returns the number of bytes of the unread 329 | * portion of the buffer 330 | */ 331 | readonly length: number; 332 | /** Returns the capacity of the buffer's underlying byte slice, that is, 333 | * the total space allocated for the buffer's data. 334 | */ 335 | readonly capacity: number; 336 | /** truncate() discards all but the first n unread bytes from the buffer but 337 | * continues to use the same allocated storage. It throws if n is negative or 338 | * greater than the length of the buffer. 339 | */ 340 | truncate(n: number): void; 341 | /** reset() resets the buffer to be empty, but it retains the underlying 342 | * storage for use by future writes. reset() is the same as truncate(0) 343 | */ 344 | reset(): void; 345 | /** _tryGrowByReslice() is a version of grow for the fast-case 346 | * where the internal buffer only needs to be resliced. It returns the index 347 | * where bytes should be written and whether it succeeded. 348 | * It returns -1 if a reslice was not needed. 349 | */ 350 | private _tryGrowByReslice; 351 | private _reslice; 352 | /** readSync() reads the next len(p) bytes from the buffer or until the buffer 353 | * is drained. The return value n is the number of bytes read. If the 354 | * buffer has no data to return, eof in the response will be true. 355 | */ 356 | readSync(p: Uint8Array): number | EOF; 357 | read(p: Uint8Array): Promise; 358 | writeSync(p: Uint8Array): number; 359 | write(p: Uint8Array): Promise; 360 | /** _grow() grows the buffer to guarantee space for n more bytes. 361 | * It returns the index where bytes should be written. 362 | * If the buffer can't grow it will throw with ErrTooLarge. 363 | */ 364 | private _grow; 365 | /** grow() grows the buffer's capacity, if necessary, to guarantee space for 366 | * another n bytes. After grow(n), at least n bytes can be written to the 367 | * buffer without another allocation. If n is negative, grow() will panic. If 368 | * the buffer can't grow it will throw ErrTooLarge. 369 | * Based on https://golang.org/pkg/bytes/#Buffer.Grow 370 | */ 371 | grow(n: number): void; 372 | /** readFrom() reads data from r until EOF and appends it to the buffer, 373 | * growing the buffer as needed. It returns the number of bytes read. If the 374 | * buffer becomes too large, readFrom will panic with ErrTooLarge. 375 | * Based on https://golang.org/pkg/bytes/#Buffer.ReadFrom 376 | */ 377 | readFrom(r: Reader): Promise; 378 | /** Sync version of `readFrom` 379 | */ 380 | readFromSync(r: SyncReader): number; 381 | } 382 | /** Read `r` until EOF and return the content as `Uint8Array`. 383 | */ 384 | export function readAll(r: Reader): Promise; 385 | /** Read synchronously `r` until EOF and return the content as `Uint8Array`. 386 | */ 387 | export function readAllSync(r: SyncReader): Uint8Array; 388 | /** Write all the content of `arr` to `w`. 389 | */ 390 | export function writeAll(w: Writer, arr: Uint8Array): Promise; 391 | /** Write synchronously all the content of `arr` to `w`. 392 | */ 393 | export function writeAllSync(w: SyncWriter, arr: Uint8Array): void; 394 | 395 | // @url js/mkdir.d.ts 396 | 397 | /** Creates a new directory with the specified path synchronously. 398 | * If `recursive` is set to true, nested directories will be created (also known 399 | * as "mkdir -p"). 400 | * `mode` sets permission bits (before umask) on UNIX and does nothing on 401 | * Windows. 402 | * 403 | * Deno.mkdirSync("new_dir"); 404 | * Deno.mkdirSync("nested/directories", true); 405 | */ 406 | export function mkdirSync( 407 | path: string, 408 | recursive?: boolean, 409 | mode?: number 410 | ): void; 411 | /** Creates a new directory with the specified path. 412 | * If `recursive` is set to true, nested directories will be created (also known 413 | * as "mkdir -p"). 414 | * `mode` sets permission bits (before umask) on UNIX and does nothing on 415 | * Windows. 416 | * 417 | * await Deno.mkdir("new_dir"); 418 | * await Deno.mkdir("nested/directories", true); 419 | */ 420 | export function mkdir( 421 | path: string, 422 | recursive?: boolean, 423 | mode?: number 424 | ): Promise; 425 | 426 | // @url js/make_temp_dir.d.ts 427 | 428 | export interface MakeTempDirOptions { 429 | dir?: string; 430 | prefix?: string; 431 | suffix?: string; 432 | } 433 | /** makeTempDirSync is the synchronous version of `makeTempDir`. 434 | * 435 | * const tempDirName0 = Deno.makeTempDirSync(); 436 | * const tempDirName1 = Deno.makeTempDirSync({ prefix: 'my_temp' }); 437 | */ 438 | export function makeTempDirSync(options?: MakeTempDirOptions): string; 439 | /** makeTempDir creates a new temporary directory in the directory `dir`, its 440 | * name beginning with `prefix` and ending with `suffix`. 441 | * It returns the full path to the newly created directory. 442 | * If `dir` is unspecified, tempDir uses the default directory for temporary 443 | * files. Multiple programs calling tempDir simultaneously will not choose the 444 | * same directory. It is the caller's responsibility to remove the directory 445 | * when no longer needed. 446 | * 447 | * const tempDirName0 = await Deno.makeTempDir(); 448 | * const tempDirName1 = await Deno.makeTempDir({ prefix: 'my_temp' }); 449 | */ 450 | export function makeTempDir(options?: MakeTempDirOptions): Promise; 451 | 452 | // @url js/chmod.d.ts 453 | 454 | /** Changes the permission of a specific file/directory of specified path 455 | * synchronously. 456 | * 457 | * Deno.chmodSync("/path/to/file", 0o666); 458 | */ 459 | export function chmodSync(path: string, mode: number): void; 460 | /** Changes the permission of a specific file/directory of specified path. 461 | * 462 | * await Deno.chmod("/path/to/file", 0o666); 463 | */ 464 | export function chmod(path: string, mode: number): Promise; 465 | 466 | // @url js/chown.d.ts 467 | 468 | /** 469 | * Change owner of a regular file or directory synchronously. Unix only at the moment. 470 | * @param path path to the file 471 | * @param uid user id of the new owner 472 | * @param gid group id of the new owner 473 | */ 474 | export function chownSync(path: string, uid: number, gid: number): void; 475 | /** 476 | * Change owner of a regular file or directory asynchronously. Unix only at the moment. 477 | * @param path path to the file 478 | * @param uid user id of the new owner 479 | * @param gid group id of the new owner 480 | */ 481 | export function chown(path: string, uid: number, gid: number): Promise; 482 | 483 | // @url js/utime.d.ts 484 | 485 | /** Synchronously changes the access and modification times of a file system 486 | * object referenced by `filename`. Given times are either in seconds 487 | * (Unix epoch time) or as `Date` objects. 488 | * 489 | * Deno.utimeSync("myfile.txt", 1556495550, new Date()); 490 | */ 491 | export function utimeSync( 492 | filename: string, 493 | atime: number | Date, 494 | mtime: number | Date 495 | ): void; 496 | /** Changes the access and modification times of a file system object 497 | * referenced by `filename`. Given times are either in seconds 498 | * (Unix epoch time) or as `Date` objects. 499 | * 500 | * await Deno.utime("myfile.txt", 1556495550, new Date()); 501 | */ 502 | export function utime( 503 | filename: string, 504 | atime: number | Date, 505 | mtime: number | Date 506 | ): Promise; 507 | 508 | // @url js/remove.d.ts 509 | 510 | export interface RemoveOption { 511 | recursive?: boolean; 512 | } 513 | /** Removes the named file or directory synchronously. Would throw 514 | * error if permission denied, not found, or directory not empty if `recursive` 515 | * set to false. 516 | * `recursive` is set to false by default. 517 | * 518 | * Deno.removeSync("/path/to/dir/or/file", {recursive: false}); 519 | */ 520 | export function removeSync(path: string, options?: RemoveOption): void; 521 | /** Removes the named file or directory. Would throw error if 522 | * permission denied, not found, or directory not empty if `recursive` set 523 | * to false. 524 | * `recursive` is set to false by default. 525 | * 526 | * await Deno.remove("/path/to/dir/or/file", {recursive: false}); 527 | */ 528 | export function remove(path: string, options?: RemoveOption): Promise; 529 | 530 | // @url js/rename.d.ts 531 | 532 | /** Synchronously renames (moves) `oldpath` to `newpath`. If `newpath` already 533 | * exists and is not a directory, `renameSync()` replaces it. OS-specific 534 | * restrictions may apply when `oldpath` and `newpath` are in different 535 | * directories. 536 | * 537 | * Deno.renameSync("old/path", "new/path"); 538 | */ 539 | export function renameSync(oldpath: string, newpath: string): void; 540 | /** Renames (moves) `oldpath` to `newpath`. If `newpath` already exists and is 541 | * not a directory, `rename()` replaces it. OS-specific restrictions may apply 542 | * when `oldpath` and `newpath` are in different directories. 543 | * 544 | * await Deno.rename("old/path", "new/path"); 545 | */ 546 | export function rename(oldpath: string, newpath: string): Promise; 547 | 548 | // @url js/read_file.d.ts 549 | 550 | /** Read the entire contents of a file synchronously. 551 | * 552 | * const decoder = new TextDecoder("utf-8"); 553 | * const data = Deno.readFileSync("hello.txt"); 554 | * console.log(decoder.decode(data)); 555 | */ 556 | export function readFileSync(filename: string): Uint8Array; 557 | /** Read the entire contents of a file. 558 | * 559 | * const decoder = new TextDecoder("utf-8"); 560 | * const data = await Deno.readFile("hello.txt"); 561 | * console.log(decoder.decode(data)); 562 | */ 563 | export function readFile(filename: string): Promise; 564 | 565 | /** Synchronously write string `data` to the given `path`, by default creating a new file if needed, 566 | * else overwriting. 567 | * 568 | * ```ts 569 | * await Deno.writeTextFileSync("hello1.txt", "Hello world\n"); // overwrite "hello1.txt" or create it 570 | * ``` 571 | * 572 | * Requires `allow-write` permission, and `allow-read` if `options.create` is `false`. 573 | */ 574 | 575 | /** Synchronously reads and returns the entire contents of a file as utf8 encoded string 576 | * encoded string. Reading a directory returns an empty string. 577 | * 578 | * ```ts 579 | * const data = Deno.readTextFileSync("hello.txt"); 580 | * console.log(data); 581 | * ``` 582 | * 583 | * Requires `allow-read` permission. */ 584 | export function readTextFileSync(path: string): string; 585 | 586 | /** Asynchronously reads and returns the entire contents of a file as a utf8 587 | * encoded string. Reading a directory returns an empty data array. 588 | * 589 | * ```ts 590 | * const data = await Deno.readTextFile("hello.txt"); 591 | * console.log(data); 592 | * ``` 593 | * 594 | * Requires `allow-read` permission. */ 595 | 596 | export function readTextFile(path: string): Promise; 597 | 598 | /** Asynchronously write string `data` to the given `path`, by default creating a new file if needed, 599 | * else overwriting. 600 | * 601 | * ```ts 602 | * await Deno.writeTextFile("hello1.txt", "Hello world\n"); // overwrite "hello1.txt" or create it 603 | * ``` 604 | * 605 | * Requires `allow-write` permission, and `allow-read` if `options.create` is `false`. 606 | */ 607 | 608 | export function writeTextFileSync( 609 | path: string | URL, 610 | data: string, 611 | options?: WriteFileOptions 612 | ): void; 613 | 614 | /** Asynchronously write string `data` to the given `path`, by default creating a new file if needed, 615 | * else overwriting. 616 | * 617 | * ```ts 618 | * await Deno.writeTextFile("hello1.txt", "Hello world\n"); // overwrite "hello1.txt" or create it 619 | * ``` 620 | * 621 | * Requires `allow-write` permission, and `allow-read` if `options.create` is `false`. 622 | */ 623 | export function writeTextFile( 624 | path: string | URL, 625 | data: string, 626 | options?: WriteFileOptions 627 | ): Promise; 628 | 629 | // @url js/file_info.d.ts 630 | 631 | /** A FileInfo describes a file and is returned by `stat`, `lstat`, 632 | * `statSync`, `lstatSync`. 633 | */ 634 | export interface FileInfo { 635 | /** The size of the file, in bytes. */ 636 | len: number; 637 | /** The last modification time of the file. This corresponds to the `mtime` 638 | * field from `stat` on Unix and `ftLastWriteTime` on Windows. This may not 639 | * be available on all platforms. 640 | */ 641 | modified: number | null; 642 | /** The last access time of the file. This corresponds to the `atime` 643 | * field from `stat` on Unix and `ftLastAccessTime` on Windows. This may not 644 | * be available on all platforms. 645 | */ 646 | accessed: number | null; 647 | /** The last access time of the file. This corresponds to the `birthtime` 648 | * field from `stat` on Unix and `ftCreationTime` on Windows. This may not 649 | * be available on all platforms. 650 | */ 651 | created: number | null; 652 | /** The underlying raw st_mode bits that contain the standard Unix permissions 653 | * for this file/directory. TODO Match behavior with Go on windows for mode. 654 | */ 655 | mode: number | null; 656 | /** The file or directory name. */ 657 | name: string | null; 658 | /** Returns whether this is info for a regular file. This result is mutually 659 | * exclusive to `FileInfo.isDirectory` and `FileInfo.isSymlink`. 660 | */ 661 | isFile(): boolean; 662 | /** Returns whether this is info for a regular directory. This result is 663 | * mutually exclusive to `FileInfo.isFile` and `FileInfo.isSymlink`. 664 | */ 665 | isDirectory(): boolean; 666 | /** Returns whether this is info for a symlink. This result is 667 | * mutually exclusive to `FileInfo.isFile` and `FileInfo.isDirectory`. 668 | */ 669 | isSymlink(): boolean; 670 | } 671 | 672 | // @url js/read_dir.d.ts 673 | 674 | /** Reads the directory given by path and returns a list of file info 675 | * synchronously. 676 | * 677 | * const files = Deno.readDirSync("/"); 678 | */ 679 | export function readDirSync(path: string): FileInfo[]; 680 | /** Reads the directory given by path and returns a list of file info. 681 | * 682 | * const files = await Deno.readDir("/"); 683 | */ 684 | export function readDir(path: string): Promise; 685 | 686 | // @url js/copy_file.d.ts 687 | 688 | /** Copies the contents of a file to another by name synchronously. 689 | * Creates a new file if target does not exists, and if target exists, 690 | * overwrites original content of the target file. 691 | * 692 | * It would also copy the permission of the original file 693 | * to the destination. 694 | * 695 | * Deno.copyFileSync("from.txt", "to.txt"); 696 | */ 697 | export function copyFileSync(from: string, to: string): void; 698 | /** Copies the contents of a file to another by name. 699 | * 700 | * Creates a new file if target does not exists, and if target exists, 701 | * overwrites original content of the target file. 702 | * 703 | * It would also copy the permission of the original file 704 | * to the destination. 705 | * 706 | * await Deno.copyFile("from.txt", "to.txt"); 707 | */ 708 | export function copyFile(from: string, to: string): Promise; 709 | 710 | // @url js/read_link.d.ts 711 | 712 | /** Returns the destination of the named symbolic link synchronously. 713 | * 714 | * const targetPath = Deno.readlinkSync("symlink/path"); 715 | */ 716 | export function readlinkSync(name: string): string; 717 | /** Returns the destination of the named symbolic link. 718 | * 719 | * const targetPath = await Deno.readlink("symlink/path"); 720 | */ 721 | export function readlink(name: string): Promise; 722 | 723 | // @url js/stat.d.ts 724 | 725 | interface StatResponse { 726 | isFile: boolean; 727 | isSymlink: boolean; 728 | len: number; 729 | modified: number; 730 | accessed: number; 731 | created: number; 732 | mode: number; 733 | hasMode: boolean; 734 | name: string | null; 735 | } 736 | /** Queries the file system for information on the path provided. If the given 737 | * path is a symlink information about the symlink will be returned. 738 | * 739 | * const fileInfo = await Deno.lstat("hello.txt"); 740 | * assert(fileInfo.isFile()); 741 | */ 742 | export function lstat(filename: string): Promise; 743 | /** Queries the file system for information on the path provided synchronously. 744 | * If the given path is a symlink information about the symlink will be 745 | * returned. 746 | * 747 | * const fileInfo = Deno.lstatSync("hello.txt"); 748 | * assert(fileInfo.isFile()); 749 | */ 750 | export function lstatSync(filename: string): FileInfo; 751 | /** Queries the file system for information on the path provided. `stat` Will 752 | * always follow symlinks. 753 | * 754 | * const fileInfo = await Deno.stat("hello.txt"); 755 | * assert(fileInfo.isFile()); 756 | */ 757 | export function stat(filename: string): Promise; 758 | /** Queries the file system for information on the path provided synchronously. 759 | * `statSync` Will always follow symlinks. 760 | * 761 | * const fileInfo = Deno.statSync("hello.txt"); 762 | * assert(fileInfo.isFile()); 763 | */ 764 | export function statSync(filename: string): FileInfo; 765 | 766 | // @url js/link.d.ts 767 | 768 | /** Synchronously creates `newname` as a hard link to `oldname`. 769 | * 770 | * Deno.linkSync("old/name", "new/name"); 771 | */ 772 | export function linkSync(oldname: string, newname: string): void; 773 | /** Creates `newname` as a hard link to `oldname`. 774 | * 775 | * await Deno.link("old/name", "new/name"); 776 | */ 777 | export function link(oldname: string, newname: string): Promise; 778 | 779 | // @url js/symlink.d.ts 780 | 781 | /** Synchronously creates `newname` as a symbolic link to `oldname`. The type 782 | * argument can be set to `dir` or `file` and is only available on Windows 783 | * (ignored on other platforms). 784 | * 785 | * Deno.symlinkSync("old/name", "new/name"); 786 | */ 787 | export function symlinkSync( 788 | oldname: string, 789 | newname: string, 790 | type?: string 791 | ): void; 792 | /** Creates `newname` as a symbolic link to `oldname`. The type argument can be 793 | * set to `dir` or `file` and is only available on Windows (ignored on other 794 | * platforms). 795 | * 796 | * await Deno.symlink("old/name", "new/name"); 797 | */ 798 | export function symlink( 799 | oldname: string, 800 | newname: string, 801 | type?: string 802 | ): Promise; 803 | 804 | // @url js/write_file.d.ts 805 | 806 | /** Options for writing to a file. 807 | * `perm` would change the file's permission if set. 808 | * `create` decides if the file should be created if not exists (default: true) 809 | * `append` decides if the file should be appended (default: false) 810 | */ 811 | export interface WriteFileOptions { 812 | perm?: number; 813 | create?: boolean; 814 | append?: boolean; 815 | } 816 | /** Write a new file, with given filename and data synchronously. 817 | * 818 | * const encoder = new TextEncoder(); 819 | * const data = encoder.encode("Hello world\n"); 820 | * Deno.writeFileSync("hello.txt", data); 821 | */ 822 | export function writeFileSync( 823 | filename: string, 824 | data: Uint8Array, 825 | options?: WriteFileOptions 826 | ): void; 827 | /** Write a new file, with given filename and data. 828 | * 829 | * const encoder = new TextEncoder(); 830 | * const data = encoder.encode("Hello world\n"); 831 | * await Deno.writeFile("hello.txt", data); 832 | */ 833 | export function writeFile( 834 | filename: string, 835 | data: Uint8Array, 836 | options?: WriteFileOptions 837 | ): Promise; 838 | 839 | // @url js/error_stack.d.ts 840 | 841 | interface Location { 842 | /** The full url for the module, e.g. `file://some/file.ts` or 843 | * `https://some/file.ts`. */ 844 | filename: string; 845 | /** The line number in the file. It is assumed to be 1-indexed. */ 846 | line: number; 847 | /** The column number in the file. It is assumed to be 1-indexed. */ 848 | column: number; 849 | } 850 | /** Given a current location in a module, lookup the source location and 851 | * return it. 852 | * 853 | * When Deno transpiles code, it keep source maps of the transpiled code. This 854 | * function can be used to lookup the original location. This is automatically 855 | * done when accessing the `.stack` of an error, or when an uncaught error is 856 | * logged. This function can be used to perform the lookup for creating better 857 | * error handling. 858 | * 859 | * **Note:** `line` and `column` are 1 indexed, which matches display 860 | * expectations, but is not typical of most index numbers in Deno. 861 | * 862 | * An example: 863 | * 864 | * const orig = Deno.applySourceMap({ 865 | * location: "file://my/module.ts", 866 | * line: 5, 867 | * column: 15 868 | * }); 869 | * console.log(`${orig.filename}:${orig.line}:${orig.column}`); 870 | * 871 | */ 872 | export function applySourceMap(location: Location): Location; 873 | 874 | // @url js/errors.d.ts 875 | 876 | /** A Deno specific error. The `kind` property is set to a specific error code 877 | * which can be used to in application logic. 878 | * 879 | * try { 880 | * somethingThatMightThrow(); 881 | * } catch (e) { 882 | * if ( 883 | * e instanceof Deno.DenoError && 884 | * e.kind === Deno.ErrorKind.Overflow 885 | * ) { 886 | * console.error("Overflow error!"); 887 | * } 888 | * } 889 | * 890 | */ 891 | export class DenoError extends Error { 892 | readonly kind: T; 893 | constructor(kind: T, msg: string); 894 | } 895 | export enum ErrorKind { 896 | NoError = 0, 897 | NotFound = 1, 898 | PermissionDenied = 2, 899 | ConnectionRefused = 3, 900 | ConnectionReset = 4, 901 | ConnectionAborted = 5, 902 | NotConnected = 6, 903 | AddrInUse = 7, 904 | AddrNotAvailable = 8, 905 | BrokenPipe = 9, 906 | AlreadyExists = 10, 907 | WouldBlock = 11, 908 | InvalidInput = 12, 909 | InvalidData = 13, 910 | TimedOut = 14, 911 | Interrupted = 15, 912 | WriteZero = 16, 913 | Other = 17, 914 | UnexpectedEof = 18, 915 | BadResource = 19, 916 | CommandFailed = 20, 917 | EmptyHost = 21, 918 | IdnaError = 22, 919 | InvalidPort = 23, 920 | InvalidIpv4Address = 24, 921 | InvalidIpv6Address = 25, 922 | InvalidDomainCharacter = 26, 923 | RelativeUrlWithoutBase = 27, 924 | RelativeUrlWithCannotBeABaseBase = 28, 925 | SetHostOnCannotBeABaseUrl = 29, 926 | Overflow = 30, 927 | HttpUser = 31, 928 | HttpClosed = 32, 929 | HttpCanceled = 33, 930 | HttpParse = 34, 931 | HttpOther = 35, 932 | TooLarge = 36, 933 | InvalidUri = 37, 934 | InvalidSeekMode = 38, 935 | OpNotAvailable = 39, 936 | WorkerInitFailed = 40, 937 | UnixError = 41, 938 | NoAsyncSupport = 42, 939 | NoSyncSupport = 43, 940 | ImportMapError = 44, 941 | InvalidPath = 45, 942 | ImportPrefixMissing = 46, 943 | UnsupportedFetchScheme = 47, 944 | TooManyRedirects = 48, 945 | Diagnostic = 49, 946 | JSError = 50 947 | } 948 | 949 | // @url js/permissions.d.ts 950 | /** Permissions as granted by the caller 951 | * See: https://w3c.github.io/permissions/#permission-registry 952 | */ 953 | export type PermissionName = 954 | | "run" 955 | | "read" 956 | | "write" 957 | | "net" 958 | | "env" 959 | | "hrtime"; 960 | /** https://w3c.github.io/permissions/#status-of-a-permission */ 961 | export type PermissionState = "granted" | "denied" | "prompt"; 962 | interface RunPermissionDescriptor { 963 | name: "run"; 964 | } 965 | interface ReadWritePermissionDescriptor { 966 | name: "read" | "write"; 967 | path?: string; 968 | } 969 | interface NetPermissionDescriptor { 970 | name: "net"; 971 | url?: string; 972 | } 973 | interface EnvPermissionDescriptor { 974 | name: "env"; 975 | } 976 | interface HrtimePermissionDescriptor { 977 | name: "hrtime"; 978 | } 979 | /** See: https://w3c.github.io/permissions/#permission-descriptor */ 980 | type PermissionDescriptor = 981 | | RunPermissionDescriptor 982 | | ReadWritePermissionDescriptor 983 | | NetPermissionDescriptor 984 | | EnvPermissionDescriptor 985 | | HrtimePermissionDescriptor; 986 | 987 | export class Permissions { 988 | /** Queries the permission. 989 | * const status = await Deno.permissions.query({ name: "read", path: "/etc" }); 990 | * if (status.state === "granted") { 991 | * data = await Deno.readFile("/etc/passwd"); 992 | * } 993 | */ 994 | query(d: PermissionDescriptor): Promise; 995 | /** Revokes the permission. 996 | * const status = await Deno.permissions.revoke({ name: "run" }); 997 | * assert(status.state !== "granted") 998 | */ 999 | revoke(d: PermissionDescriptor): Promise; 1000 | } 1001 | export const permissions: Permissions; 1002 | 1003 | /** https://w3c.github.io/permissions/#permissionstatus */ 1004 | export class PermissionStatus { 1005 | state: PermissionState; 1006 | constructor(state: PermissionState); 1007 | } 1008 | 1009 | // @url js/truncate.d.ts 1010 | 1011 | /** Truncates or extends the specified file synchronously, updating the size of 1012 | * this file to become size. 1013 | * 1014 | * Deno.truncateSync("hello.txt", 10); 1015 | */ 1016 | export function truncateSync(name: string, len?: number): void; 1017 | /** 1018 | * Truncates or extends the specified file, updating the size of this file to 1019 | * become size. 1020 | * 1021 | * await Deno.truncate("hello.txt", 10); 1022 | */ 1023 | export function truncate(name: string, len?: number): Promise; 1024 | 1025 | // @url js/net.d.ts 1026 | 1027 | type Transport = "tcp"; 1028 | interface Addr { 1029 | transport: Transport; 1030 | address: string; 1031 | } 1032 | 1033 | /** A Listener is a generic network listener for stream-oriented protocols. */ 1034 | export interface Listener extends AsyncIterator { 1035 | /** Waits for and resolves to the next connection to the `Listener`. */ 1036 | accept(): Promise; 1037 | /** Close closes the listener. Any pending accept promises will be rejected 1038 | * with errors. 1039 | */ 1040 | close(): void; 1041 | /** Return the address of the `Listener`. */ 1042 | addr(): Addr; 1043 | [Symbol.asyncIterator](): AsyncIterator; 1044 | } 1045 | export interface Conn extends Reader, Writer, Closer { 1046 | /** The local address of the connection. */ 1047 | localAddr: string; 1048 | /** The remote address of the connection. */ 1049 | remoteAddr: string; 1050 | /** The resource ID of the connection. */ 1051 | rid: number; 1052 | /** Shuts down (`shutdown(2)`) the reading side of the TCP connection. Most 1053 | * callers should just use `close()`. 1054 | */ 1055 | closeRead(): void; 1056 | /** Shuts down (`shutdown(2)`) the writing side of the TCP connection. Most 1057 | * callers should just use `close()`. 1058 | */ 1059 | closeWrite(): void; 1060 | } 1061 | 1062 | export interface ListenOptions { 1063 | port: number; 1064 | hostname?: string; 1065 | transport?: Transport; 1066 | } 1067 | 1068 | /** Listen announces on the local transport address. 1069 | * 1070 | * @param options 1071 | * @param options.port The port to connect to. (Required.) 1072 | * @param options.hostname A literal IP address or host name that can be 1073 | * resolved to an IP address. If not specified, defaults to 0.0.0.0 1074 | * @param options.transport Defaults to "tcp". Later we plan to add "tcp4", 1075 | * "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6", "unix", "unixgram" and 1076 | * "unixpacket". 1077 | * 1078 | * Examples: 1079 | * 1080 | * listen({ port: 80 }) 1081 | * listen({ hostname: "192.0.2.1", port: 80 }) 1082 | * listen({ hostname: "[2001:db8::1]", port: 80 }); 1083 | * listen({ hostname: "golang.org", port: 80, transport: "tcp" }) 1084 | */ 1085 | export function listen(options: ListenOptions): Listener; 1086 | 1087 | export interface ListenTLSOptions { 1088 | port: number; 1089 | hostname?: string; 1090 | transport?: Transport; 1091 | certFile: string; 1092 | keyFile: string; 1093 | } 1094 | 1095 | /** Listen announces on the local transport address over TLS (transport layer security). 1096 | * 1097 | * @param options 1098 | * @param options.port The port to connect to. (Required.) 1099 | * @param options.hostname A literal IP address or host name that can be 1100 | * resolved to an IP address. If not specified, defaults to 0.0.0.0 1101 | * @param options.certFile Server certificate file 1102 | * @param options.keyFile Server public key file 1103 | * 1104 | * Examples: 1105 | * 1106 | * Deno.listenTLS({ port: 443, certFile: "./my_server.crt", keyFile: "./my_server.key" }) 1107 | */ 1108 | export function listenTLS(options: ListenTLSOptions): Listener; 1109 | 1110 | export interface DialOptions { 1111 | port: number; 1112 | hostname?: string; 1113 | transport?: Transport; 1114 | } 1115 | 1116 | /** Dial connects to the address on the named transport. 1117 | * 1118 | * @param options 1119 | * @param options.port The port to connect to. (Required.) 1120 | * @param options.hostname A literal IP address or host name that can be 1121 | * resolved to an IP address. If not specified, defaults to 127.0.0.1 1122 | * @param options.transport Defaults to "tcp". Later we plan to add "tcp4", 1123 | * "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6", "unix", "unixgram" and 1124 | * "unixpacket". 1125 | * 1126 | * Examples: 1127 | * 1128 | * dial({ port: 80 }) 1129 | * dial({ hostname: "192.0.2.1", port: 80 }) 1130 | * dial({ hostname: "[2001:db8::1]", port: 80 }); 1131 | * dial({ hostname: "golang.org", port: 80, transport: "tcp" }) 1132 | */ 1133 | export function dial(options: DialOptions): Promise; 1134 | 1135 | export interface DialTLSOptions { 1136 | port: number; 1137 | hostname?: string; 1138 | certFile?: string; 1139 | } 1140 | 1141 | /** 1142 | * dialTLS establishes a secure connection over TLS (transport layer security). 1143 | */ 1144 | export function dialTLS(options: DialTLSOptions): Promise; 1145 | 1146 | // @url js/metrics.d.ts 1147 | export interface Metrics { 1148 | opsDispatched: number; 1149 | opsCompleted: number; 1150 | bytesSentControl: number; 1151 | bytesSentData: number; 1152 | bytesReceived: number; 1153 | } 1154 | /** Receive metrics from the privileged side of Deno. 1155 | * 1156 | * > console.table(Deno.metrics()) 1157 | * ┌──────────────────┬────────┐ 1158 | * │ (index) │ Values │ 1159 | * ├──────────────────┼────────┤ 1160 | * │ opsDispatched │ 9 │ 1161 | * │ opsCompleted │ 9 │ 1162 | * │ bytesSentControl │ 504 │ 1163 | * │ bytesSentData │ 0 │ 1164 | * │ bytesReceived │ 856 │ 1165 | * └──────────────────┴────────┘ 1166 | */ 1167 | export function metrics(): Metrics; 1168 | 1169 | // @url js/resources.d.ts 1170 | 1171 | interface ResourceMap { 1172 | [rid: number]: string; 1173 | } 1174 | /** Returns a map of open _file like_ resource ids along with their string 1175 | * representation. 1176 | */ 1177 | export function resources(): ResourceMap; 1178 | 1179 | // @url js/process.d.ts 1180 | 1181 | /** How to handle subprocess stdio. 1182 | * 1183 | * "inherit" The default if unspecified. The child inherits from the 1184 | * corresponding parent descriptor. 1185 | * 1186 | * "piped" A new pipe should be arranged to connect the parent and child 1187 | * subprocesses. 1188 | * 1189 | * "null" This stream will be ignored. This is the equivalent of attaching the 1190 | * stream to /dev/null. 1191 | */ 1192 | type ProcessStdio = "inherit" | "piped" | "null"; 1193 | export interface RunOptions { 1194 | args: string[]; 1195 | cwd?: string; 1196 | env?: { 1197 | [key: string]: string; 1198 | }; 1199 | stdout?: ProcessStdio | number; 1200 | stderr?: ProcessStdio | number; 1201 | stdin?: ProcessStdio | number; 1202 | } 1203 | /** Send a signal to process under given PID. Unix only at this moment. 1204 | * If pid is negative, the signal will be sent to the process group identified 1205 | * by -pid. 1206 | * Requires the `--allow-run` flag. 1207 | */ 1208 | export function kill(pid: number, signo: number): void; 1209 | export class Process { 1210 | readonly rid: number; 1211 | readonly pid: number; 1212 | readonly stdin?: WriteCloser; 1213 | readonly stdout?: ReadCloser; 1214 | readonly stderr?: ReadCloser; 1215 | status(): Promise; 1216 | /** Buffer the stdout and return it as Uint8Array after EOF. 1217 | * You must set stdout to "piped" when creating the process. 1218 | * This calls close() on stdout after its done. 1219 | */ 1220 | output(): Promise; 1221 | /** Buffer the stderr and return it as Uint8Array after EOF. 1222 | * You must set stderr to "piped" when creating the process. 1223 | * This calls close() on stderr after its done. 1224 | */ 1225 | stderrOutput(): Promise; 1226 | close(): void; 1227 | kill(signo: number): void; 1228 | } 1229 | export interface ProcessStatus { 1230 | success: boolean; 1231 | code?: number; 1232 | signal?: number; 1233 | } 1234 | /** 1235 | * Spawns new subprocess. 1236 | * 1237 | * Subprocess uses same working directory as parent process unless `opt.cwd` 1238 | * is specified. 1239 | * 1240 | * Environmental variables for subprocess can be specified using `opt.env` 1241 | * mapping. 1242 | * 1243 | * By default subprocess inherits stdio of parent process. To change that 1244 | * `opt.stdout`, `opt.stderr` and `opt.stdin` can be specified independently - 1245 | * they can be set to either `ProcessStdio` or `rid` of open file. 1246 | */ 1247 | export function run(opt: RunOptions): Process; 1248 | enum LinuxSignal { 1249 | SIGHUP = 1, 1250 | SIGINT = 2, 1251 | SIGQUIT = 3, 1252 | SIGILL = 4, 1253 | SIGTRAP = 5, 1254 | SIGABRT = 6, 1255 | SIGBUS = 7, 1256 | SIGFPE = 8, 1257 | SIGKILL = 9, 1258 | SIGUSR1 = 10, 1259 | SIGSEGV = 11, 1260 | SIGUSR2 = 12, 1261 | SIGPIPE = 13, 1262 | SIGALRM = 14, 1263 | SIGTERM = 15, 1264 | SIGSTKFLT = 16, 1265 | SIGCHLD = 17, 1266 | SIGCONT = 18, 1267 | SIGSTOP = 19, 1268 | SIGTSTP = 20, 1269 | SIGTTIN = 21, 1270 | SIGTTOU = 22, 1271 | SIGURG = 23, 1272 | SIGXCPU = 24, 1273 | SIGXFSZ = 25, 1274 | SIGVTALRM = 26, 1275 | SIGPROF = 27, 1276 | SIGWINCH = 28, 1277 | SIGIO = 29, 1278 | SIGPWR = 30, 1279 | SIGSYS = 31 1280 | } 1281 | enum MacOSSignal { 1282 | SIGHUP = 1, 1283 | SIGINT = 2, 1284 | SIGQUIT = 3, 1285 | SIGILL = 4, 1286 | SIGTRAP = 5, 1287 | SIGABRT = 6, 1288 | SIGEMT = 7, 1289 | SIGFPE = 8, 1290 | SIGKILL = 9, 1291 | SIGBUS = 10, 1292 | SIGSEGV = 11, 1293 | SIGSYS = 12, 1294 | SIGPIPE = 13, 1295 | SIGALRM = 14, 1296 | SIGTERM = 15, 1297 | SIGURG = 16, 1298 | SIGSTOP = 17, 1299 | SIGTSTP = 18, 1300 | SIGCONT = 19, 1301 | SIGCHLD = 20, 1302 | SIGTTIN = 21, 1303 | SIGTTOU = 22, 1304 | SIGIO = 23, 1305 | SIGXCPU = 24, 1306 | SIGXFSZ = 25, 1307 | SIGVTALRM = 26, 1308 | SIGPROF = 27, 1309 | SIGWINCH = 28, 1310 | SIGINFO = 29, 1311 | SIGUSR1 = 30, 1312 | SIGUSR2 = 31 1313 | } 1314 | /** Signals numbers. This is platform dependent. 1315 | */ 1316 | export const Signal: typeof MacOSSignal | typeof LinuxSignal; 1317 | export {}; 1318 | 1319 | // @url js/console.d.ts 1320 | 1321 | type ConsoleOptions = Partial<{ 1322 | showHidden: boolean; 1323 | depth: number; 1324 | colors: boolean; 1325 | indentLevel: number; 1326 | }>; 1327 | /** A symbol which can be used as a key for a custom method which will be called 1328 | * when `Deno.inspect()` is called, or when the object is logged to the console. 1329 | */ 1330 | export const customInspect: unique symbol; 1331 | /** 1332 | * `inspect()` converts input into string that has the same format 1333 | * as printed by `console.log(...)`; 1334 | */ 1335 | export function inspect(value: unknown, options?: ConsoleOptions): string; 1336 | 1337 | // @url js/build.d.ts 1338 | 1339 | export type OperatingSystem = "mac" | "win" | "linux"; 1340 | export type Arch = "x64" | "arm64"; 1341 | /** Build related information */ 1342 | interface BuildInfo { 1343 | /** The CPU architecture. */ 1344 | arch: Arch; 1345 | /** The operating system. */ 1346 | os: OperatingSystem; 1347 | } 1348 | export const build: BuildInfo; 1349 | 1350 | // @url js/version.d.ts 1351 | 1352 | interface Version { 1353 | deno: string; 1354 | v8: string; 1355 | typescript: string; 1356 | } 1357 | export const version: Version; 1358 | export {}; 1359 | 1360 | // @url js/deno.d.ts 1361 | 1362 | export const args: string[]; 1363 | } 1364 | // @url js/globals.ts 1365 | 1366 | declare interface Window { 1367 | window: Window & typeof globalThis; 1368 | atob: typeof textEncoding.atob; 1369 | btoa: typeof textEncoding.btoa; 1370 | fetch: typeof fetchTypes.fetch; 1371 | clearTimeout: typeof timers.clearTimeout; 1372 | clearInterval: typeof timers.clearInterval; 1373 | console: consoleTypes.Console; 1374 | setTimeout: typeof timers.setTimeout; 1375 | setInterval: typeof timers.setInterval; 1376 | location: domTypes.Location; 1377 | onload: Function | undefined; 1378 | onunload: Function | undefined; 1379 | crypto: Crypto; 1380 | Blob: typeof blob.DenoBlob; 1381 | File: domTypes.DomFileConstructor; 1382 | CustomEvent: typeof customEvent.CustomEvent; 1383 | Event: typeof event.Event; 1384 | EventTarget: typeof eventTarget.EventTarget; 1385 | URL: typeof url.URL; 1386 | URLSearchParams: typeof urlSearchParams.URLSearchParams; 1387 | Headers: domTypes.HeadersConstructor; 1388 | FormData: domTypes.FormDataConstructor; 1389 | TextEncoder: typeof textEncoding.TextEncoder; 1390 | TextDecoder: typeof textEncoding.TextDecoder; 1391 | Request: domTypes.RequestConstructor; 1392 | Response: typeof fetchTypes.Response; 1393 | performance: performanceUtil.Performance; 1394 | onmessage: (e: { data: any }) => void; 1395 | workerMain: typeof workers.workerMain; 1396 | workerClose: typeof workers.workerClose; 1397 | postMessage: typeof workers.postMessage; 1398 | Worker: typeof workers.WorkerImpl; 1399 | addEventListener: ( 1400 | type: string, 1401 | callback: (event: domTypes.Event) => void | null, 1402 | options?: boolean | domTypes.AddEventListenerOptions | undefined 1403 | ) => void; 1404 | dispatchEvent: (event: domTypes.Event) => boolean; 1405 | removeEventListener: ( 1406 | type: string, 1407 | callback: (event: domTypes.Event) => void | null, 1408 | options?: boolean | domTypes.EventListenerOptions | undefined 1409 | ) => void; 1410 | queueMicrotask: (task: () => void) => void; 1411 | Deno: typeof Deno; 1412 | } 1413 | 1414 | declare const window: Window & typeof globalThis; 1415 | declare const atob: typeof textEncoding.atob; 1416 | declare const btoa: typeof textEncoding.btoa; 1417 | declare const fetch: typeof fetchTypes.fetch; 1418 | declare const clearTimeout: typeof timers.clearTimeout; 1419 | declare const clearInterval: typeof timers.clearInterval; 1420 | declare const console: consoleTypes.Console; 1421 | declare const setTimeout: typeof timers.setTimeout; 1422 | declare const setInterval: typeof timers.setInterval; 1423 | declare const location: domTypes.Location; 1424 | declare const onload: Function | undefined; 1425 | declare const onunload: Function | undefined; 1426 | declare const crypto: Crypto; 1427 | declare const Blob: typeof blob.DenoBlob; 1428 | declare const File: domTypes.DomFileConstructor; 1429 | declare const CustomEventInit: typeof customEvent.CustomEventInit; 1430 | declare const CustomEvent: typeof customEvent.CustomEvent; 1431 | declare const EventInit: typeof event.EventInit; 1432 | declare const Event: typeof event.Event; 1433 | declare const EventListener: typeof eventTarget.EventListener; 1434 | declare const EventTarget: typeof eventTarget.EventTarget; 1435 | declare const URL: typeof url.URL; 1436 | declare const URLSearchParams: typeof urlSearchParams.URLSearchParams; 1437 | declare const Headers: domTypes.HeadersConstructor; 1438 | declare const FormData: domTypes.FormDataConstructor; 1439 | declare const TextEncoder: typeof textEncoding.TextEncoder; 1440 | declare const TextDecoder: typeof textEncoding.TextDecoder; 1441 | declare const Request: domTypes.RequestConstructor; 1442 | declare const Response: typeof fetchTypes.Response; 1443 | declare const performance: performanceUtil.Performance; 1444 | declare let onmessage: (e: { data: any }) => void; 1445 | declare const workerMain: typeof workers.workerMain; 1446 | declare const workerClose: typeof workers.workerClose; 1447 | declare const postMessage: typeof workers.postMessage; 1448 | declare const Worker: typeof workers.WorkerImpl; 1449 | declare const addEventListener: ( 1450 | type: string, 1451 | callback: (event: domTypes.Event) => void | null, 1452 | options?: boolean | domTypes.AddEventListenerOptions | undefined 1453 | ) => void; 1454 | declare const dispatchEvent: (event: domTypes.Event) => boolean; 1455 | declare const removeEventListener: ( 1456 | type: string, 1457 | callback: (event: domTypes.Event) => void | null, 1458 | options?: boolean | domTypes.EventListenerOptions | undefined 1459 | ) => void; 1460 | 1461 | declare type Blob = domTypes.Blob; 1462 | declare type Body = domTypes.Body; 1463 | declare type File = domTypes.DomFile; 1464 | declare type CustomEventInit = domTypes.CustomEventInit; 1465 | declare type CustomEvent = domTypes.CustomEvent; 1466 | declare type EventInit = domTypes.EventInit; 1467 | declare type Event = domTypes.Event; 1468 | declare type EventListener = domTypes.EventListener; 1469 | declare type EventTarget = domTypes.EventTarget; 1470 | declare type URL = url.URL; 1471 | declare type URLSearchParams = domTypes.URLSearchParams; 1472 | declare type Headers = domTypes.Headers; 1473 | declare type FormData = domTypes.FormData; 1474 | declare type TextEncoder = textEncoding.TextEncoder; 1475 | declare type TextDecoder = textEncoding.TextDecoder; 1476 | declare type Request = domTypes.Request; 1477 | declare type Response = domTypes.Response; 1478 | declare type Worker = workers.Worker; 1479 | 1480 | declare interface ImportMeta { 1481 | url: string; 1482 | main: boolean; 1483 | } 1484 | 1485 | declare interface Crypto { 1486 | readonly subtle: null; 1487 | getRandomValues: < 1488 | T extends 1489 | | Int8Array 1490 | | Uint8Array 1491 | | Uint8ClampedArray 1492 | | Int16Array 1493 | | Uint16Array 1494 | | Int32Array 1495 | | Uint32Array 1496 | >( 1497 | typedArray: T 1498 | ) => T; 1499 | } 1500 | 1501 | declare namespace domTypes { 1502 | // @url js/dom_types.d.ts 1503 | 1504 | export type BufferSource = ArrayBufferView | ArrayBuffer; 1505 | export type HeadersInit = 1506 | | Headers 1507 | | Array<[string, string]> 1508 | | Record; 1509 | export type URLSearchParamsInit = 1510 | | string 1511 | | string[][] 1512 | | Record; 1513 | type BodyInit = 1514 | | Blob 1515 | | BufferSource 1516 | | FormData 1517 | | URLSearchParams 1518 | | ReadableStream 1519 | | string; 1520 | export type RequestInfo = Request | string; 1521 | type ReferrerPolicy = 1522 | | "" 1523 | | "no-referrer" 1524 | | "no-referrer-when-downgrade" 1525 | | "origin-only" 1526 | | "origin-when-cross-origin" 1527 | | "unsafe-url"; 1528 | export type BlobPart = BufferSource | Blob | string; 1529 | export type FormDataEntryValue = DomFile | string; 1530 | export interface DomIterable { 1531 | keys(): IterableIterator; 1532 | values(): IterableIterator; 1533 | entries(): IterableIterator<[K, V]>; 1534 | [Symbol.iterator](): IterableIterator<[K, V]>; 1535 | forEach( 1536 | callback: (value: V, key: K, parent: this) => void, 1537 | thisArg?: any 1538 | ): void; 1539 | } 1540 | type EndingType = "transparent" | "native"; 1541 | export interface BlobPropertyBag { 1542 | type?: string; 1543 | ending?: EndingType; 1544 | } 1545 | interface AbortSignalEventMap { 1546 | abort: ProgressEvent; 1547 | } 1548 | export enum NodeType { 1549 | ELEMENT_NODE = 1, 1550 | TEXT_NODE = 3, 1551 | DOCUMENT_FRAGMENT_NODE = 11 1552 | } 1553 | export const eventTargetHost: unique symbol; 1554 | export const eventTargetListeners: unique symbol; 1555 | export const eventTargetMode: unique symbol; 1556 | export const eventTargetNodeType: unique symbol; 1557 | export interface EventTarget { 1558 | [eventTargetHost]: EventTarget | null; 1559 | [eventTargetListeners]: { [type in string]: EventListener[] }; 1560 | [eventTargetMode]: string; 1561 | [eventTargetNodeType]: NodeType; 1562 | addEventListener( 1563 | type: string, 1564 | callback: (event: Event) => void | null, 1565 | options?: boolean | AddEventListenerOptions 1566 | ): void; 1567 | dispatchEvent(event: Event): boolean; 1568 | removeEventListener( 1569 | type: string, 1570 | callback?: (event: Event) => void | null, 1571 | options?: EventListenerOptions | boolean 1572 | ): void; 1573 | } 1574 | export interface ProgressEventInit extends EventInit { 1575 | lengthComputable?: boolean; 1576 | loaded?: number; 1577 | total?: number; 1578 | } 1579 | export interface URLSearchParams extends DomIterable { 1580 | /** 1581 | * Appends a specified key/value pair as a new search parameter. 1582 | */ 1583 | append(name: string, value: string): void; 1584 | /** 1585 | * Deletes the given search parameter, and its associated value, 1586 | * from the list of all search parameters. 1587 | */ 1588 | delete(name: string): void; 1589 | /** 1590 | * Returns the first value associated to the given search parameter. 1591 | */ 1592 | get(name: string): string | null; 1593 | /** 1594 | * Returns all the values association with a given search parameter. 1595 | */ 1596 | getAll(name: string): string[]; 1597 | /** 1598 | * Returns a Boolean indicating if such a search parameter exists. 1599 | */ 1600 | has(name: string): boolean; 1601 | /** 1602 | * Sets the value associated to a given search parameter to the given value. 1603 | * If there were several values, delete the others. 1604 | */ 1605 | set(name: string, value: string): void; 1606 | /** 1607 | * Sort all key/value pairs contained in this object in place 1608 | * and return undefined. The sort order is according to Unicode 1609 | * code points of the keys. 1610 | */ 1611 | sort(): void; 1612 | /** 1613 | * Returns a query string suitable for use in a URL. 1614 | */ 1615 | toString(): string; 1616 | /** 1617 | * Iterates over each name-value pair in the query 1618 | * and invokes the given function. 1619 | */ 1620 | forEach( 1621 | callbackfn: (value: string, key: string, parent: this) => void, 1622 | thisArg?: any 1623 | ): void; 1624 | } 1625 | export interface EventListener { 1626 | handleEvent(event: Event): void; 1627 | readonly callback: (event: Event) => void | null; 1628 | readonly options: boolean | AddEventListenerOptions; 1629 | } 1630 | export interface EventInit { 1631 | bubbles?: boolean; 1632 | cancelable?: boolean; 1633 | composed?: boolean; 1634 | } 1635 | export interface CustomEventInit extends EventInit { 1636 | detail?: any; 1637 | } 1638 | export enum EventPhase { 1639 | NONE = 0, 1640 | CAPTURING_PHASE = 1, 1641 | AT_TARGET = 2, 1642 | BUBBLING_PHASE = 3 1643 | } 1644 | export interface EventPath { 1645 | item: EventTarget; 1646 | itemInShadowTree: boolean; 1647 | relatedTarget: EventTarget | null; 1648 | rootOfClosedTree: boolean; 1649 | slotInClosedTree: boolean; 1650 | target: EventTarget | null; 1651 | touchTargetList: EventTarget[]; 1652 | } 1653 | export interface Event { 1654 | readonly type: string; 1655 | target: EventTarget | null; 1656 | currentTarget: EventTarget | null; 1657 | composedPath(): EventPath[]; 1658 | eventPhase: number; 1659 | stopPropagation(): void; 1660 | stopImmediatePropagation(): void; 1661 | readonly bubbles: boolean; 1662 | readonly cancelable: boolean; 1663 | preventDefault(): void; 1664 | readonly defaultPrevented: boolean; 1665 | readonly composed: boolean; 1666 | isTrusted: boolean; 1667 | readonly timeStamp: Date; 1668 | dispatched: boolean; 1669 | readonly initialized: boolean; 1670 | inPassiveListener: boolean; 1671 | cancelBubble: boolean; 1672 | cancelBubbleImmediately: boolean; 1673 | path: EventPath[]; 1674 | relatedTarget: EventTarget | null; 1675 | } 1676 | export interface CustomEvent extends Event { 1677 | readonly detail: any; 1678 | initCustomEvent( 1679 | type: string, 1680 | bubbles?: boolean, 1681 | cancelable?: boolean, 1682 | detail?: any | null 1683 | ): void; 1684 | } 1685 | export interface DomFile extends Blob { 1686 | readonly lastModified: number; 1687 | readonly name: string; 1688 | } 1689 | export interface DomFileConstructor { 1690 | new ( 1691 | bits: BlobPart[], 1692 | filename: string, 1693 | options?: FilePropertyBag 1694 | ): DomFile; 1695 | prototype: DomFile; 1696 | } 1697 | export interface FilePropertyBag extends BlobPropertyBag { 1698 | lastModified?: number; 1699 | } 1700 | interface ProgressEvent extends Event { 1701 | readonly lengthComputable: boolean; 1702 | readonly loaded: number; 1703 | readonly total: number; 1704 | } 1705 | export interface EventListenerOptions { 1706 | capture: boolean; 1707 | } 1708 | export interface AddEventListenerOptions extends EventListenerOptions { 1709 | once: boolean; 1710 | passive: boolean; 1711 | } 1712 | interface AbortSignal extends EventTarget { 1713 | readonly aborted: boolean; 1714 | onabort: ((this: AbortSignal, ev: ProgressEvent) => any) | null; 1715 | addEventListener( 1716 | type: K, 1717 | listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, 1718 | options?: boolean | AddEventListenerOptions 1719 | ): void; 1720 | addEventListener( 1721 | type: string, 1722 | listener: EventListener, 1723 | options?: boolean | AddEventListenerOptions 1724 | ): void; 1725 | removeEventListener( 1726 | type: K, 1727 | listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, 1728 | options?: boolean | EventListenerOptions 1729 | ): void; 1730 | removeEventListener( 1731 | type: string, 1732 | listener: EventListener, 1733 | options?: boolean | EventListenerOptions 1734 | ): void; 1735 | } 1736 | export interface ReadableStream { 1737 | readonly locked: boolean; 1738 | cancel(): Promise; 1739 | getReader(): ReadableStreamReader; 1740 | tee(): [ReadableStream, ReadableStream]; 1741 | } 1742 | export interface ReadableStreamReader { 1743 | cancel(): Promise; 1744 | read(): Promise; 1745 | releaseLock(): void; 1746 | } 1747 | export interface FormData extends DomIterable { 1748 | append(name: string, value: string | Blob, fileName?: string): void; 1749 | delete(name: string): void; 1750 | get(name: string): FormDataEntryValue | null; 1751 | getAll(name: string): FormDataEntryValue[]; 1752 | has(name: string): boolean; 1753 | set(name: string, value: string | Blob, fileName?: string): void; 1754 | } 1755 | export interface FormDataConstructor { 1756 | new (): FormData; 1757 | prototype: FormData; 1758 | } 1759 | /** A blob object represents a file-like object of immutable, raw data. */ 1760 | export interface Blob { 1761 | /** The size, in bytes, of the data contained in the `Blob` object. */ 1762 | readonly size: number; 1763 | /** A string indicating the media type of the data contained in the `Blob`. 1764 | * If the type is unknown, this string is empty. 1765 | */ 1766 | readonly type: string; 1767 | /** Returns a new `Blob` object containing the data in the specified range of 1768 | * bytes of the source `Blob`. 1769 | */ 1770 | slice(start?: number, end?: number, contentType?: string): Blob; 1771 | } 1772 | export interface Body { 1773 | /** A simple getter used to expose a `ReadableStream` of the body contents. */ 1774 | readonly body: ReadableStream | null; 1775 | /** Stores a `Boolean` that declares whether the body has been used in a 1776 | * response yet. 1777 | */ 1778 | readonly bodyUsed: boolean; 1779 | /** Takes a `Response` stream and reads it to completion. It returns a promise 1780 | * that resolves with an `ArrayBuffer`. 1781 | */ 1782 | arrayBuffer(): Promise; 1783 | /** Takes a `Response` stream and reads it to completion. It returns a promise 1784 | * that resolves with a `Blob`. 1785 | */ 1786 | blob(): Promise; 1787 | /** Takes a `Response` stream and reads it to completion. It returns a promise 1788 | * that resolves with a `FormData` object. 1789 | */ 1790 | formData(): Promise; 1791 | /** Takes a `Response` stream and reads it to completion. It returns a promise 1792 | * that resolves with the result of parsing the body text as JSON. 1793 | */ 1794 | json(): Promise; 1795 | /** Takes a `Response` stream and reads it to completion. It returns a promise 1796 | * that resolves with a `USVString` (text). 1797 | */ 1798 | text(): Promise; 1799 | } 1800 | export interface Headers extends DomIterable { 1801 | /** Appends a new value onto an existing header inside a `Headers` object, or 1802 | * adds the header if it does not already exist. 1803 | */ 1804 | append(name: string, value: string): void; 1805 | /** Deletes a header from a `Headers` object. */ 1806 | delete(name: string): void; 1807 | /** Returns an iterator allowing to go through all key/value pairs 1808 | * contained in this Headers object. The both the key and value of each pairs 1809 | * are ByteString objects. 1810 | */ 1811 | entries(): IterableIterator<[string, string]>; 1812 | /** Returns a `ByteString` sequence of all the values of a header within a 1813 | * `Headers` object with a given name. 1814 | */ 1815 | get(name: string): string | null; 1816 | /** Returns a boolean stating whether a `Headers` object contains a certain 1817 | * header. 1818 | */ 1819 | has(name: string): boolean; 1820 | /** Returns an iterator allowing to go through all keys contained in 1821 | * this Headers object. The keys are ByteString objects. 1822 | */ 1823 | keys(): IterableIterator; 1824 | /** Sets a new value for an existing header inside a Headers object, or adds 1825 | * the header if it does not already exist. 1826 | */ 1827 | set(name: string, value: string): void; 1828 | /** Returns an iterator allowing to go through all values contained in 1829 | * this Headers object. The values are ByteString objects. 1830 | */ 1831 | values(): IterableIterator; 1832 | forEach( 1833 | callbackfn: (value: string, key: string, parent: this) => void, 1834 | thisArg?: any 1835 | ): void; 1836 | /** The Symbol.iterator well-known symbol specifies the default 1837 | * iterator for this Headers object 1838 | */ 1839 | [Symbol.iterator](): IterableIterator<[string, string]>; 1840 | } 1841 | export interface HeadersConstructor { 1842 | new (init?: HeadersInit): Headers; 1843 | prototype: Headers; 1844 | } 1845 | type RequestCache = 1846 | | "default" 1847 | | "no-store" 1848 | | "reload" 1849 | | "no-cache" 1850 | | "force-cache" 1851 | | "only-if-cached"; 1852 | type RequestCredentials = "omit" | "same-origin" | "include"; 1853 | type RequestDestination = 1854 | | "" 1855 | | "audio" 1856 | | "audioworklet" 1857 | | "document" 1858 | | "embed" 1859 | | "font" 1860 | | "image" 1861 | | "manifest" 1862 | | "object" 1863 | | "paintworklet" 1864 | | "report" 1865 | | "script" 1866 | | "sharedworker" 1867 | | "style" 1868 | | "track" 1869 | | "video" 1870 | | "worker" 1871 | | "xslt"; 1872 | type RequestMode = "navigate" | "same-origin" | "no-cors" | "cors"; 1873 | type RequestRedirect = "follow" | "error" | "manual"; 1874 | type ResponseType = 1875 | | "basic" 1876 | | "cors" 1877 | | "default" 1878 | | "error" 1879 | | "opaque" 1880 | | "opaqueredirect"; 1881 | export interface RequestInit { 1882 | body?: BodyInit | null; 1883 | cache?: RequestCache; 1884 | credentials?: RequestCredentials; 1885 | headers?: HeadersInit; 1886 | integrity?: string; 1887 | keepalive?: boolean; 1888 | method?: string; 1889 | mode?: RequestMode; 1890 | redirect?: RequestRedirect; 1891 | referrer?: string; 1892 | referrerPolicy?: ReferrerPolicy; 1893 | signal?: AbortSignal | null; 1894 | window?: any; 1895 | } 1896 | export interface ResponseInit { 1897 | headers?: HeadersInit; 1898 | status?: number; 1899 | statusText?: string; 1900 | } 1901 | export interface RequestConstructor { 1902 | new (input: RequestInfo, init?: RequestInit): Request; 1903 | prototype: Request; 1904 | } 1905 | export interface Request extends Body { 1906 | /** Returns the cache mode associated with request, which is a string 1907 | * indicating how the the request will interact with the browser's cache when 1908 | * fetching. 1909 | */ 1910 | readonly cache?: RequestCache; 1911 | /** Returns the credentials mode associated with request, which is a string 1912 | * indicating whether credentials will be sent with the request always, never, 1913 | * or only when sent to a same-origin URL. 1914 | */ 1915 | readonly credentials?: RequestCredentials; 1916 | /** Returns the kind of resource requested by request, (e.g., `document` or 1917 | * `script`). 1918 | */ 1919 | readonly destination?: RequestDestination; 1920 | /** Returns a Headers object consisting of the headers associated with 1921 | * request. 1922 | * 1923 | * Note that headers added in the network layer by the user agent 1924 | * will not be accounted for in this object, (e.g., the `Host` header). 1925 | */ 1926 | readonly headers: Headers; 1927 | /** Returns request's subresource integrity metadata, which is a cryptographic 1928 | * hash of the resource being fetched. Its value consists of multiple hashes 1929 | * separated by whitespace. [SRI] 1930 | */ 1931 | readonly integrity?: string; 1932 | /** Returns a boolean indicating whether or not request is for a history 1933 | * navigation (a.k.a. back-forward navigation). 1934 | */ 1935 | readonly isHistoryNavigation?: boolean; 1936 | /** Returns a boolean indicating whether or not request is for a reload 1937 | * navigation. 1938 | */ 1939 | readonly isReloadNavigation?: boolean; 1940 | /** Returns a boolean indicating whether or not request can outlive the global 1941 | * in which it was created. 1942 | */ 1943 | readonly keepalive?: boolean; 1944 | /** Returns request's HTTP method, which is `GET` by default. */ 1945 | readonly method: string; 1946 | /** Returns the mode associated with request, which is a string indicating 1947 | * whether the request will use CORS, or will be restricted to same-origin 1948 | * URLs. 1949 | */ 1950 | readonly mode?: RequestMode; 1951 | /** Returns the redirect mode associated with request, which is a string 1952 | * indicating how redirects for the request will be handled during fetching. 1953 | * 1954 | * A request will follow redirects by default. 1955 | */ 1956 | readonly redirect?: RequestRedirect; 1957 | /** Returns the referrer of request. Its value can be a same-origin URL if 1958 | * explicitly set in init, the empty string to indicate no referrer, and 1959 | * `about:client` when defaulting to the global's default. 1960 | * 1961 | * This is used during fetching to determine the value of the `Referer` 1962 | * header of the request being made. 1963 | */ 1964 | readonly referrer?: string; 1965 | /** Returns the referrer policy associated with request. This is used during 1966 | * fetching to compute the value of the request's referrer. 1967 | */ 1968 | readonly referrerPolicy?: ReferrerPolicy; 1969 | /** Returns the signal associated with request, which is an AbortSignal object 1970 | * indicating whether or not request has been aborted, and its abort event 1971 | * handler. 1972 | */ 1973 | readonly signal?: AbortSignal; 1974 | /** Returns the URL of request as a string. */ 1975 | readonly url: string; 1976 | clone(): Request; 1977 | } 1978 | export interface Response extends Body { 1979 | /** Contains the `Headers` object associated with the response. */ 1980 | readonly headers: Headers; 1981 | /** Contains a boolean stating whether the response was successful (status in 1982 | * the range 200-299) or not. 1983 | */ 1984 | readonly ok: boolean; 1985 | /** Indicates whether or not the response is the result of a redirect; that 1986 | * is, its URL list has more than one entry. 1987 | */ 1988 | readonly redirected: boolean; 1989 | /** Contains the status code of the response (e.g., `200` for a success). */ 1990 | readonly status: number; 1991 | /** Contains the status message corresponding to the status code (e.g., `OK` 1992 | * for `200`). 1993 | */ 1994 | readonly statusText: string; 1995 | readonly trailer: Promise; 1996 | /** Contains the type of the response (e.g., `basic`, `cors`). */ 1997 | readonly type: ResponseType; 1998 | /** Contains the URL of the response. */ 1999 | readonly url: string; 2000 | /** Creates a clone of a `Response` object. */ 2001 | clone(): Response; 2002 | } 2003 | export interface Location { 2004 | /** 2005 | * Returns a DOMStringList object listing the origins of the ancestor browsing 2006 | * contexts, from the parent browsing context to the top-level browsing 2007 | * context. 2008 | */ 2009 | readonly ancestorOrigins: string[]; 2010 | /** 2011 | * Returns the Location object's URL's fragment (includes leading "#" if 2012 | * non-empty). 2013 | * Can be set, to navigate to the same URL with a changed fragment (ignores 2014 | * leading "#"). 2015 | */ 2016 | hash: string; 2017 | /** 2018 | * Returns the Location object's URL's host and port (if different from the 2019 | * default port for the scheme). Can be set, to navigate to the same URL with 2020 | * a changed host and port. 2021 | */ 2022 | host: string; 2023 | /** 2024 | * Returns the Location object's URL's host. Can be set, to navigate to the 2025 | * same URL with a changed host. 2026 | */ 2027 | hostname: string; 2028 | /** 2029 | * Returns the Location object's URL. Can be set, to navigate to the given 2030 | * URL. 2031 | */ 2032 | href: string; 2033 | /** Returns the Location object's URL's origin. */ 2034 | readonly origin: string; 2035 | /** 2036 | * Returns the Location object's URL's path. 2037 | * Can be set, to navigate to the same URL with a changed path. 2038 | */ 2039 | pathname: string; 2040 | /** 2041 | * Returns the Location object's URL's port. 2042 | * Can be set, to navigate to the same URL with a changed port. 2043 | */ 2044 | port: string; 2045 | /** 2046 | * Returns the Location object's URL's scheme. 2047 | * Can be set, to navigate to the same URL with a changed scheme. 2048 | */ 2049 | protocol: string; 2050 | /** 2051 | * Returns the Location object's URL's query (includes leading "?" if 2052 | * non-empty). Can be set, to navigate to the same URL with a changed query 2053 | * (ignores leading "?"). 2054 | */ 2055 | search: string; 2056 | /** 2057 | * Navigates to the given URL. 2058 | */ 2059 | assign(url: string): void; 2060 | /** 2061 | * Reloads the current page. 2062 | */ 2063 | reload(): void; 2064 | /** @deprecated */ 2065 | reload(forcedReload: boolean): void; 2066 | /** 2067 | * Removes the current page from the session history and navigates to the 2068 | * given URL. 2069 | */ 2070 | replace(url: string): void; 2071 | } 2072 | } 2073 | 2074 | declare namespace blob { 2075 | // @url js/blob.d.ts 2076 | 2077 | export const bytesSymbol: unique symbol; 2078 | export const blobBytesWeakMap: WeakMap; 2079 | export class DenoBlob implements domTypes.Blob { 2080 | private readonly [bytesSymbol]; 2081 | readonly size: number; 2082 | readonly type: string; 2083 | /** A blob object represents a file-like object of immutable, raw data. */ 2084 | constructor( 2085 | blobParts?: domTypes.BlobPart[], 2086 | options?: domTypes.BlobPropertyBag 2087 | ); 2088 | slice(start?: number, end?: number, contentType?: string): DenoBlob; 2089 | } 2090 | } 2091 | 2092 | declare namespace consoleTypes { 2093 | // @url js/console.d.ts 2094 | 2095 | type ConsoleOptions = Partial<{ 2096 | showHidden: boolean; 2097 | depth: number; 2098 | colors: boolean; 2099 | indentLevel: number; 2100 | }>; 2101 | export class CSI { 2102 | static kClear: string; 2103 | static kClearScreenDown: string; 2104 | } 2105 | const isConsoleInstance: unique symbol; 2106 | export class Console { 2107 | private printFunc; 2108 | indentLevel: number; 2109 | [isConsoleInstance]: boolean; 2110 | /** Writes the arguments to stdout */ 2111 | log: (...args: unknown[]) => void; 2112 | /** Writes the arguments to stdout */ 2113 | debug: (...args: unknown[]) => void; 2114 | /** Writes the arguments to stdout */ 2115 | info: (...args: unknown[]) => void; 2116 | /** Writes the properties of the supplied `obj` to stdout */ 2117 | dir: ( 2118 | obj: unknown, 2119 | options?: Partial<{ 2120 | showHidden: boolean; 2121 | depth: number; 2122 | colors: boolean; 2123 | indentLevel: number; 2124 | }> 2125 | ) => void; 2126 | 2127 | /** From MDN: 2128 | * Displays an interactive tree of the descendant elements of 2129 | * the specified XML/HTML element. If it is not possible to display 2130 | * as an element the JavaScript Object view is shown instead. 2131 | * The output is presented as a hierarchical listing of expandable 2132 | * nodes that let you see the contents of child nodes. 2133 | * 2134 | * Since we write to stdout, we can't display anything interactive 2135 | * we just fall back to `console.dir`. 2136 | */ 2137 | dirxml: ( 2138 | obj: unknown, 2139 | options?: Partial<{ 2140 | showHidden: boolean; 2141 | depth: number; 2142 | colors: boolean; 2143 | indentLevel: number; 2144 | }> 2145 | ) => void; 2146 | 2147 | /** Writes the arguments to stdout */ 2148 | warn: (...args: unknown[]) => void; 2149 | /** Writes the arguments to stdout */ 2150 | error: (...args: unknown[]) => void; 2151 | /** Writes an error message to stdout if the assertion is `false`. If the 2152 | * assertion is `true`, nothing happens. 2153 | * 2154 | * ref: https://console.spec.whatwg.org/#assert 2155 | */ 2156 | assert: (condition?: boolean, ...args: unknown[]) => void; 2157 | count: (label?: string) => void; 2158 | countReset: (label?: string) => void; 2159 | table: (data: unknown, properties?: string[] | undefined) => void; 2160 | time: (label?: string) => void; 2161 | timeLog: (label?: string, ...args: unknown[]) => void; 2162 | timeEnd: (label?: string) => void; 2163 | group: (...label: unknown[]) => void; 2164 | groupCollapsed: (...label: unknown[]) => void; 2165 | groupEnd: () => void; 2166 | clear: () => void; 2167 | trace: (...args: unknown[]) => void; 2168 | static [Symbol.hasInstance](instance: Console): boolean; 2169 | } 2170 | /** A symbol which can be used as a key for a custom method which will be called 2171 | * when `Deno.inspect()` is called, or when the object is logged to the console. 2172 | */ 2173 | export const customInspect: unique symbol; 2174 | /** 2175 | * `inspect()` converts input into string that has the same format 2176 | * as printed by `console.log(...)`; 2177 | */ 2178 | export function inspect(value: unknown, options?: ConsoleOptions): string; 2179 | } 2180 | 2181 | declare namespace event { 2182 | // @url js/event.d.ts 2183 | 2184 | export const eventAttributes: WeakMap; 2185 | export class EventInit implements domTypes.EventInit { 2186 | bubbles: boolean; 2187 | cancelable: boolean; 2188 | composed: boolean; 2189 | constructor({ 2190 | bubbles, 2191 | cancelable, 2192 | composed 2193 | }?: { 2194 | bubbles?: boolean | undefined; 2195 | cancelable?: boolean | undefined; 2196 | composed?: boolean | undefined; 2197 | }); 2198 | } 2199 | export class Event implements domTypes.Event { 2200 | isTrusted: boolean; 2201 | private _canceledFlag; 2202 | private _dispatchedFlag; 2203 | private _initializedFlag; 2204 | private _inPassiveListenerFlag; 2205 | private _stopImmediatePropagationFlag; 2206 | private _stopPropagationFlag; 2207 | private _path; 2208 | constructor(type: string, eventInitDict?: domTypes.EventInit); 2209 | readonly bubbles: boolean; 2210 | cancelBubble: boolean; 2211 | cancelBubbleImmediately: boolean; 2212 | readonly cancelable: boolean; 2213 | readonly composed: boolean; 2214 | currentTarget: domTypes.EventTarget; 2215 | readonly defaultPrevented: boolean; 2216 | dispatched: boolean; 2217 | eventPhase: number; 2218 | readonly initialized: boolean; 2219 | inPassiveListener: boolean; 2220 | path: domTypes.EventPath[]; 2221 | relatedTarget: domTypes.EventTarget; 2222 | target: domTypes.EventTarget; 2223 | readonly timeStamp: Date; 2224 | readonly type: string; 2225 | /** Returns the event’s path (objects on which listeners will be 2226 | * invoked). This does not include nodes in shadow trees if the 2227 | * shadow root was created with its ShadowRoot.mode closed. 2228 | * 2229 | * event.composedPath(); 2230 | */ 2231 | composedPath(): domTypes.EventPath[]; 2232 | /** Cancels the event (if it is cancelable). 2233 | * See https://dom.spec.whatwg.org/#set-the-canceled-flag 2234 | * 2235 | * event.preventDefault(); 2236 | */ 2237 | preventDefault(): void; 2238 | /** Stops the propagation of events further along in the DOM. 2239 | * 2240 | * event.stopPropagation(); 2241 | */ 2242 | stopPropagation(): void; 2243 | /** For this particular event, no other listener will be called. 2244 | * Neither those attached on the same element, nor those attached 2245 | * on elements which will be traversed later (in capture phase, 2246 | * for instance). 2247 | * 2248 | * event.stopImmediatePropagation(); 2249 | */ 2250 | stopImmediatePropagation(): void; 2251 | } 2252 | } 2253 | 2254 | declare namespace customEvent { 2255 | // @url js/custom_event.d.ts 2256 | 2257 | export const customEventAttributes: WeakMap; 2258 | export class CustomEventInit 2259 | extends event.EventInit 2260 | implements domTypes.CustomEventInit { 2261 | detail: any; 2262 | constructor({ 2263 | bubbles, 2264 | cancelable, 2265 | composed, 2266 | detail 2267 | }: domTypes.CustomEventInit); 2268 | } 2269 | export class CustomEvent extends event.Event implements domTypes.CustomEvent { 2270 | constructor(type: string, customEventInitDict?: domTypes.CustomEventInit); 2271 | readonly detail: any; 2272 | initCustomEvent( 2273 | type: string, 2274 | bubbles?: boolean, 2275 | cancelable?: boolean, 2276 | detail?: any 2277 | ): void; 2278 | readonly [Symbol.toStringTag]: string; 2279 | } 2280 | } 2281 | 2282 | declare namespace eventTarget { 2283 | // @url js/event_target.d.ts 2284 | 2285 | export class EventListenerOptions implements domTypes.EventListenerOptions { 2286 | _capture: boolean; 2287 | constructor({ capture }?: { capture?: boolean | undefined }); 2288 | readonly capture: boolean; 2289 | } 2290 | export class AddEventListenerOptions 2291 | extends EventListenerOptions 2292 | implements domTypes.AddEventListenerOptions { 2293 | _passive: boolean; 2294 | _once: boolean; 2295 | constructor({ 2296 | capture, 2297 | passive, 2298 | once 2299 | }?: { 2300 | capture?: boolean | undefined; 2301 | passive?: boolean | undefined; 2302 | once?: boolean | undefined; 2303 | }); 2304 | readonly passive: boolean; 2305 | readonly once: boolean; 2306 | } 2307 | export class EventListener implements domTypes.EventListener { 2308 | allEvents: domTypes.Event[]; 2309 | atEvents: domTypes.Event[]; 2310 | bubbledEvents: domTypes.Event[]; 2311 | capturedEvents: domTypes.Event[]; 2312 | private _callback; 2313 | private _options; 2314 | constructor( 2315 | callback: (event: domTypes.Event) => void | null, 2316 | options: boolean | domTypes.AddEventListenerOptions 2317 | ); 2318 | handleEvent(event: domTypes.Event): void; 2319 | readonly callback: (event: domTypes.Event) => void | null; 2320 | readonly options: domTypes.AddEventListenerOptions | boolean; 2321 | } 2322 | export const eventTargetAssignedSlot: unique symbol; 2323 | export const eventTargetHasActivationBehavior: unique symbol; 2324 | export class EventTarget implements domTypes.EventTarget { 2325 | [domTypes.eventTargetHost]: domTypes.EventTarget | null; 2326 | [domTypes.eventTargetListeners]: { 2327 | [type in string]: domTypes.EventListener[]; 2328 | }; 2329 | [domTypes.eventTargetMode]: string; 2330 | [domTypes.eventTargetNodeType]: domTypes.NodeType; 2331 | private [eventTargetAssignedSlot]; 2332 | private [eventTargetHasActivationBehavior]; 2333 | addEventListener( 2334 | type: string, 2335 | callback: (event: domTypes.Event) => void | null, 2336 | options?: domTypes.AddEventListenerOptions | boolean 2337 | ): void; 2338 | removeEventListener( 2339 | type: string, 2340 | callback: (event: domTypes.Event) => void | null, 2341 | options?: domTypes.EventListenerOptions | boolean 2342 | ): void; 2343 | dispatchEvent(event: domTypes.Event): boolean; 2344 | readonly [Symbol.toStringTag]: string; 2345 | } 2346 | } 2347 | 2348 | declare namespace io { 2349 | // @url js/io.d.ts 2350 | 2351 | export enum SeekMode { 2352 | SEEK_START = 0, 2353 | SEEK_CURRENT = 1, 2354 | SEEK_END = 2 2355 | } 2356 | export interface Reader { 2357 | /** Reads up to p.byteLength bytes into `p`. It resolves to the number 2358 | * of bytes read (`0` < `n` <= `p.byteLength`) and rejects if any error encountered. 2359 | * Even if `read()` returns `n` < `p.byteLength`, it may use all of `p` as 2360 | * scratch space during the call. If some data is available but not 2361 | * `p.byteLength` bytes, `read()` conventionally returns what is available 2362 | * instead of waiting for more. 2363 | * 2364 | * When `read()` encounters end-of-file condition, it returns EOF symbol. 2365 | * 2366 | * When `read()` encounters an error, it rejects with an error. 2367 | * 2368 | * Callers should always process the `n` > `0` bytes returned before 2369 | * considering the EOF. Doing so correctly handles I/O errors that happen 2370 | * after reading some bytes and also both of the allowed EOF behaviors. 2371 | * 2372 | * Implementations must not retain `p`. 2373 | */ 2374 | read(p: Uint8Array): Promise; 2375 | } 2376 | export interface SyncReader { 2377 | readSync(p: Uint8Array): number | Deno.EOF; 2378 | } 2379 | export interface Writer { 2380 | /** Writes `p.byteLength` bytes from `p` to the underlying data 2381 | * stream. It resolves to the number of bytes written from `p` (`0` <= `n` <= 2382 | * `p.byteLength`) and any error encountered that caused the write to stop 2383 | * early. `write()` must return a non-null error if it returns `n` < 2384 | * `p.byteLength`. write() must not modify the slice data, even temporarily. 2385 | * 2386 | * Implementations must not retain `p`. 2387 | */ 2388 | write(p: Uint8Array): Promise; 2389 | } 2390 | export interface SyncWriter { 2391 | writeSync(p: Uint8Array): number; 2392 | } 2393 | export interface Closer { 2394 | close(): void; 2395 | } 2396 | export interface Seeker { 2397 | /** Seek sets the offset for the next `read()` or `write()` to offset, 2398 | * interpreted according to `whence`: `SeekStart` means relative to the start 2399 | * of the file, `SeekCurrent` means relative to the current offset, and 2400 | * `SeekEnd` means relative to the end. Seek returns the new offset relative 2401 | * to the start of the file and an error, if any. 2402 | * 2403 | * Seeking to an offset before the start of the file is an error. Seeking to 2404 | * any positive offset is legal, but the behavior of subsequent I/O operations 2405 | * on the underlying object is implementation-dependent. 2406 | */ 2407 | seek(offset: number, whence: SeekMode): Promise; 2408 | } 2409 | export interface SyncSeeker { 2410 | seekSync(offset: number, whence: SeekMode): void; 2411 | } 2412 | export interface ReadCloser extends Reader, Closer {} 2413 | export interface WriteCloser extends Writer, Closer {} 2414 | export interface ReadSeeker extends Reader, Seeker {} 2415 | export interface WriteSeeker extends Writer, Seeker {} 2416 | export interface ReadWriteCloser extends Reader, Writer, Closer {} 2417 | export interface ReadWriteSeeker extends Reader, Writer, Seeker {} 2418 | /** Copies from `src` to `dst` until either `EOF` is reached on `src` 2419 | * or an error occurs. It returns the number of bytes copied and the first 2420 | * error encountered while copying, if any. 2421 | * 2422 | * Because `copy()` is defined to read from `src` until `EOF`, it does not 2423 | * treat an `EOF` from `read()` as an error to be reported. 2424 | */ 2425 | export function copy(dst: Writer, src: Reader): Promise; 2426 | /** Turns `r` into async iterator. 2427 | * 2428 | * for await (const chunk of toAsyncIterator(reader)) { 2429 | * console.log(chunk) 2430 | * } 2431 | */ 2432 | export function toAsyncIterator(r: Reader): AsyncIterableIterator; 2433 | } 2434 | 2435 | declare namespace fetchTypes { 2436 | // @url js/fetch.d.ts 2437 | 2438 | class Body implements domTypes.Body, domTypes.ReadableStream, io.ReadCloser { 2439 | private rid; 2440 | readonly contentType: string; 2441 | bodyUsed: boolean; 2442 | private _bodyPromise; 2443 | private _data; 2444 | readonly locked: boolean; 2445 | readonly body: null | Body; 2446 | constructor(rid: number, contentType: string); 2447 | private _bodyBuffer; 2448 | arrayBuffer(): Promise; 2449 | blob(): Promise; 2450 | formData(): Promise; 2451 | json(): Promise; 2452 | text(): Promise; 2453 | read(p: Uint8Array): Promise; 2454 | close(): void; 2455 | cancel(): Promise; 2456 | getReader(): domTypes.ReadableStreamReader; 2457 | tee(): [domTypes.ReadableStream, domTypes.ReadableStream]; 2458 | [Symbol.asyncIterator](): AsyncIterableIterator; 2459 | } 2460 | export class Response implements domTypes.Response { 2461 | readonly url: string; 2462 | readonly status: number; 2463 | statusText: string; 2464 | readonly type = "basic"; 2465 | readonly redirected: boolean; 2466 | headers: domTypes.Headers; 2467 | readonly trailer: Promise; 2468 | bodyUsed: boolean; 2469 | readonly body: Body; 2470 | constructor( 2471 | url: string, 2472 | status: number, 2473 | headersList: Array<[string, string]>, 2474 | rid: number, 2475 | redirected_: boolean, 2476 | body_?: null | Body 2477 | ); 2478 | arrayBuffer(): Promise; 2479 | blob(): Promise; 2480 | formData(): Promise; 2481 | json(): Promise; 2482 | text(): Promise; 2483 | readonly ok: boolean; 2484 | clone(): domTypes.Response; 2485 | } 2486 | /** Fetch a resource from the network. */ 2487 | export function fetch( 2488 | input: domTypes.Request | string, 2489 | init?: domTypes.RequestInit 2490 | ): Promise; 2491 | } 2492 | 2493 | declare namespace textEncoding { 2494 | // @url js/text_encoding.d.ts 2495 | 2496 | export function atob(s: string): string; 2497 | /** Creates a base-64 ASCII string from the input string. */ 2498 | export function btoa(s: string): string; 2499 | export interface TextDecodeOptions { 2500 | stream?: false; 2501 | } 2502 | export interface TextDecoderOptions { 2503 | fatal?: boolean; 2504 | ignoreBOM?: boolean; 2505 | } 2506 | export class TextDecoder { 2507 | private _encoding; 2508 | /** Returns encoding's name, lowercased. */ 2509 | readonly encoding: string; 2510 | /** Returns `true` if error mode is "fatal", and `false` otherwise. */ 2511 | readonly fatal: boolean; 2512 | /** Returns `true` if ignore BOM flag is set, and `false` otherwise. */ 2513 | readonly ignoreBOM = false; 2514 | constructor(label?: string, options?: TextDecoderOptions); 2515 | /** Returns the result of running encoding's decoder. */ 2516 | decode(input?: domTypes.BufferSource, options?: TextDecodeOptions): string; 2517 | readonly [Symbol.toStringTag]: string; 2518 | } 2519 | interface TextEncoderEncodeIntoResult { 2520 | read: number; 2521 | written: number; 2522 | } 2523 | export class TextEncoder { 2524 | /** Returns "utf-8". */ 2525 | readonly encoding = "utf-8"; 2526 | /** Returns the result of running UTF-8's encoder. */ 2527 | encode(input?: string): Uint8Array; 2528 | encodeInto(input: string, dest: Uint8Array): TextEncoderEncodeIntoResult; 2529 | readonly [Symbol.toStringTag]: string; 2530 | } 2531 | } 2532 | 2533 | declare namespace timers { 2534 | // @url js/timers.d.ts 2535 | 2536 | export type Args = unknown[]; 2537 | /** Sets a timer which executes a function once after the timer expires. */ 2538 | export function setTimeout( 2539 | cb: (...args: Args) => void, 2540 | delay?: number, 2541 | ...args: Args 2542 | ): number; 2543 | /** Repeatedly calls a function , with a fixed time delay between each call. */ 2544 | export function setInterval( 2545 | cb: (...args: Args) => void, 2546 | delay?: number, 2547 | ...args: Args 2548 | ): number; 2549 | export function clearTimeout(id?: number): void; 2550 | export function clearInterval(id?: number): void; 2551 | } 2552 | 2553 | declare namespace urlSearchParams { 2554 | // @url js/url_search_params.d.ts 2555 | 2556 | export class URLSearchParams { 2557 | private params; 2558 | private url; 2559 | constructor(init?: string | string[][] | Record); 2560 | private updateSteps; 2561 | /** Appends a specified key/value pair as a new search parameter. 2562 | * 2563 | * searchParams.append('name', 'first'); 2564 | * searchParams.append('name', 'second'); 2565 | */ 2566 | append(name: string, value: string): void; 2567 | /** Deletes the given search parameter and its associated value, 2568 | * from the list of all search parameters. 2569 | * 2570 | * searchParams.delete('name'); 2571 | */ 2572 | delete(name: string): void; 2573 | /** Returns all the values associated with a given search parameter 2574 | * as an array. 2575 | * 2576 | * searchParams.getAll('name'); 2577 | */ 2578 | getAll(name: string): string[]; 2579 | /** Returns the first value associated to the given search parameter. 2580 | * 2581 | * searchParams.get('name'); 2582 | */ 2583 | get(name: string): string | null; 2584 | /** Returns a Boolean that indicates whether a parameter with the 2585 | * specified name exists. 2586 | * 2587 | * searchParams.has('name'); 2588 | */ 2589 | has(name: string): boolean; 2590 | /** Sets the value associated with a given search parameter to the 2591 | * given value. If there were several matching values, this method 2592 | * deletes the others. If the search parameter doesn't exist, this 2593 | * method creates it. 2594 | * 2595 | * searchParams.set('name', 'value'); 2596 | */ 2597 | set(name: string, value: string): void; 2598 | /** Sort all key/value pairs contained in this object in place and 2599 | * return undefined. The sort order is according to Unicode code 2600 | * points of the keys. 2601 | * 2602 | * searchParams.sort(); 2603 | */ 2604 | sort(): void; 2605 | /** Calls a function for each element contained in this object in 2606 | * place and return undefined. Optionally accepts an object to use 2607 | * as this when executing callback as second argument. 2608 | * 2609 | * searchParams.forEach((value, key, parent) => { 2610 | * console.log(value, key, parent); 2611 | * }); 2612 | * 2613 | */ 2614 | forEach( 2615 | callbackfn: (value: string, key: string, parent: this) => void, 2616 | thisArg?: any 2617 | ): void; 2618 | /** Returns an iterator allowing to go through all keys contained 2619 | * in this object. 2620 | * 2621 | * for (const key of searchParams.keys()) { 2622 | * console.log(key); 2623 | * } 2624 | */ 2625 | keys(): IterableIterator; 2626 | /** Returns an iterator allowing to go through all values contained 2627 | * in this object. 2628 | * 2629 | * for (const value of searchParams.values()) { 2630 | * console.log(value); 2631 | * } 2632 | */ 2633 | values(): IterableIterator; 2634 | /** Returns an iterator allowing to go through all key/value 2635 | * pairs contained in this object. 2636 | * 2637 | * for (const [key, value] of searchParams.entries()) { 2638 | * console.log(key, value); 2639 | * } 2640 | */ 2641 | entries(): IterableIterator<[string, string]>; 2642 | /** Returns an iterator allowing to go through all key/value 2643 | * pairs contained in this object. 2644 | * 2645 | * for (const [key, value] of searchParams[Symbol.iterator]()) { 2646 | * console.log(key, value); 2647 | * } 2648 | */ 2649 | [Symbol.iterator](): IterableIterator<[string, string]>; 2650 | /** Returns a query string suitable for use in a URL. 2651 | * 2652 | * searchParams.toString(); 2653 | */ 2654 | toString(): string; 2655 | private _handleStringInitialization; 2656 | private _handleArrayInitialization; 2657 | } 2658 | } 2659 | 2660 | declare namespace url { 2661 | // @url js/url.d.ts 2662 | 2663 | export const blobURLMap: Map; 2664 | export class URL { 2665 | private _parts; 2666 | private _searchParams; 2667 | private _updateSearchParams; 2668 | hash: string; 2669 | host: string; 2670 | hostname: string; 2671 | href: string; 2672 | readonly origin: string; 2673 | password: string; 2674 | pathname: string; 2675 | port: string; 2676 | protocol: string; 2677 | search: string; 2678 | username: string; 2679 | readonly searchParams: urlSearchParams.URLSearchParams; 2680 | constructor(url: string, base?: string | URL); 2681 | toString(): string; 2682 | toJSON(): string; 2683 | static createObjectURL(b: domTypes.Blob): string; 2684 | static revokeObjectURL(url: string): void; 2685 | } 2686 | } 2687 | 2688 | declare namespace workers { 2689 | // @url js/workers.d.ts 2690 | 2691 | export function encodeMessage(data: any): Uint8Array; 2692 | export function decodeMessage(dataIntArray: Uint8Array): any; 2693 | export let onmessage: (e: { data: any }) => void; 2694 | export function postMessage(data: any): void; 2695 | export function getMessage(): Promise; 2696 | export let isClosing: boolean; 2697 | export function workerClose(): void; 2698 | export function workerMain(): Promise; 2699 | export interface Worker { 2700 | onerror?: () => void; 2701 | onmessage?: (e: { data: any }) => void; 2702 | onmessageerror?: () => void; 2703 | postMessage(data: any): void; 2704 | closed: Promise; 2705 | } 2706 | export interface WorkerOptions {} 2707 | /** Extended Deno Worker initialization options. 2708 | * `noDenoNamespace` hides global `window.Deno` namespace for 2709 | * spawned worker and nested workers spawned by it (default: false). 2710 | */ 2711 | export interface DenoWorkerOptions extends WorkerOptions { 2712 | noDenoNamespace?: boolean; 2713 | } 2714 | export class WorkerImpl implements Worker { 2715 | private readonly rid; 2716 | private isClosing; 2717 | private readonly isClosedPromise; 2718 | onerror?: () => void; 2719 | onmessage?: (data: any) => void; 2720 | onmessageerror?: () => void; 2721 | constructor(specifier: string, options?: DenoWorkerOptions); 2722 | readonly closed: Promise; 2723 | postMessage(data: any): void; 2724 | private run; 2725 | } 2726 | } 2727 | 2728 | declare namespace performanceUtil { 2729 | // @url js/performance.d.ts 2730 | 2731 | export class Performance { 2732 | /** Returns a current time from Deno's start in milliseconds. 2733 | * 2734 | * Use the flag --allow-hrtime return a precise value. 2735 | * 2736 | * const t = performance.now(); 2737 | * console.log(`${t} ms since start!`); 2738 | */ 2739 | now(): number; 2740 | } 2741 | } 2742 | 2743 | // @url js/lib.web_assembly.d.ts 2744 | 2745 | // This follows the WebIDL at: https://webassembly.github.io/spec/js-api/ 2746 | // And follow on WebIDL at: https://webassembly.github.io/spec/web-api/ 2747 | 2748 | /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any */ 2749 | 2750 | declare namespace WebAssembly { 2751 | interface WebAssemblyInstantiatedSource { 2752 | module: Module; 2753 | instance: Instance; 2754 | } 2755 | 2756 | /** Compiles a `WebAssembly.Module` from WebAssembly binary code. This 2757 | * function is useful if it is necessary to a compile a module before it can 2758 | * be instantiated (otherwise, the `WebAssembly.instantiate()` function 2759 | * should be used). */ 2760 | function compile(bufferSource: domTypes.BufferSource): Promise; 2761 | 2762 | /** Compiles a `WebAssembly.Module` directly from a streamed underlying 2763 | * source. This function is useful if it is necessary to a compile a module 2764 | * before it can be instantiated (otherwise, the 2765 | * `WebAssembly.instantiateStreaming()` function should be used). */ 2766 | function compileStreaming( 2767 | source: Promise 2768 | ): Promise; 2769 | 2770 | /** Takes the WebAssembly binary code, in the form of a typed array or 2771 | * `ArrayBuffer`, and performs both compilation and instantiation in one step. 2772 | * The returned `Promise` resolves to both a compiled `WebAssembly.Module` and 2773 | * its first `WebAssembly.Instance`. */ 2774 | function instantiate( 2775 | bufferSource: domTypes.BufferSource, 2776 | importObject?: object 2777 | ): Promise; 2778 | 2779 | /** Takes an already-compiled `WebAssembly.Module` and returns a `Promise` 2780 | * that resolves to an `Instance` of that `Module`. This overload is useful if 2781 | * the `Module` has already been compiled. */ 2782 | function instantiate( 2783 | module: Module, 2784 | importObject?: object 2785 | ): Promise; 2786 | 2787 | /** Compiles and instantiates a WebAssembly module directly from a streamed 2788 | * underlying source. This is the most efficient, optimized way to load wasm 2789 | * code. */ 2790 | function instantiateStreaming( 2791 | source: Promise, 2792 | importObject?: object 2793 | ): Promise; 2794 | 2795 | /** Validates a given typed array of WebAssembly binary code, returning 2796 | * whether the bytes form a valid wasm module (`true`) or not (`false`). */ 2797 | function validate(bufferSource: domTypes.BufferSource): boolean; 2798 | 2799 | type ImportExportKind = "function" | "table" | "memory" | "global"; 2800 | 2801 | interface ModuleExportDescriptor { 2802 | name: string; 2803 | kind: ImportExportKind; 2804 | } 2805 | interface ModuleImportDescriptor { 2806 | module: string; 2807 | name: string; 2808 | kind: ImportExportKind; 2809 | } 2810 | 2811 | class Module { 2812 | constructor(bufferSource: domTypes.BufferSource); 2813 | 2814 | /** Given a `Module` and string, returns a copy of the contents of all 2815 | * custom sections in the module with the given string name. */ 2816 | static customSections( 2817 | moduleObject: Module, 2818 | sectionName: string 2819 | ): ArrayBuffer; 2820 | 2821 | /** Given a `Module`, returns an array containing descriptions of all the 2822 | * declared exports. */ 2823 | static exports(moduleObject: Module): ModuleExportDescriptor[]; 2824 | 2825 | /** Given a `Module`, returns an array containing descriptions of all the 2826 | * declared imports. */ 2827 | static imports(moduleObject: Module): ModuleImportDescriptor[]; 2828 | } 2829 | 2830 | class Instance { 2831 | constructor(module: Module, importObject?: object); 2832 | 2833 | /** An object containing as its members all the functions exported from the 2834 | * WebAssembly module instance, to allow them to be accessed and used by 2835 | * JavaScript. */ 2836 | readonly exports: T; 2837 | } 2838 | 2839 | interface MemoryDescriptor { 2840 | initial: number; 2841 | maximum?: number; 2842 | } 2843 | 2844 | class Memory { 2845 | constructor(descriptor: MemoryDescriptor); 2846 | 2847 | /** An accessor property that returns the buffer contained in the memory. */ 2848 | readonly buffer: ArrayBuffer; 2849 | 2850 | /** Increases the size of the memory instance by a specified number of 2851 | * WebAssembly pages (each one is 64KB in size). */ 2852 | grow(delta: number): number; 2853 | } 2854 | 2855 | type TableKind = "anyfunc"; 2856 | 2857 | interface TableDescriptor { 2858 | element: TableKind; 2859 | initial: number; 2860 | maximum?: number; 2861 | } 2862 | 2863 | class Table { 2864 | constructor(descriptor: TableDescriptor); 2865 | 2866 | /** Returns the length of the table, i.e. the number of elements. */ 2867 | readonly length: number; 2868 | 2869 | /** Accessor function — gets the element stored at a given index. */ 2870 | get(index: number): (...args: any[]) => any; 2871 | 2872 | /** Increases the size of the Table instance by a specified number of 2873 | * elements. */ 2874 | grow(delta: number): number; 2875 | 2876 | /** Sets an element stored at a given index to a given value. */ 2877 | set(index: number, value: (...args: any[]) => any): void; 2878 | } 2879 | 2880 | interface GlobalDescriptor { 2881 | value: string; 2882 | mutable?: boolean; 2883 | } 2884 | 2885 | /** Represents a global variable instance, accessible from both JavaScript and 2886 | * importable/exportable across one or more `WebAssembly.Module` instances. 2887 | * This allows dynamic linking of multiple modules. */ 2888 | class Global { 2889 | constructor(descriptor: GlobalDescriptor, value?: any); 2890 | 2891 | /** Old-style method that returns the value contained inside the global 2892 | * variable. */ 2893 | valueOf(): any; 2894 | 2895 | /** The value contained inside the global variable — this can be used to 2896 | * directly set and get the global's value. */ 2897 | value: any; 2898 | } 2899 | 2900 | /** Indicates an error during WebAssembly decoding or validation */ 2901 | class CompileError extends Error { 2902 | constructor(message: string, fileName?: string, lineNumber?: string); 2903 | } 2904 | 2905 | /** Indicates an error during module instantiation (besides traps from the 2906 | * start function). */ 2907 | class LinkError extends Error { 2908 | constructor(message: string, fileName?: string, lineNumber?: string); 2909 | } 2910 | 2911 | /** Is thrown whenever WebAssembly specifies a trap. */ 2912 | class RuntimeError extends Error { 2913 | constructor(message: string, fileName?: string, lineNumber?: string); 2914 | } 2915 | } 2916 | 2917 | /* eslint-enable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any */ 2918 | -------------------------------------------------------------------------------- /fixtures/sample.txt: -------------------------------------------------------------------------------- 1 | Deno and Node -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "denode", 3 | "version": "0.1.0", 4 | "main": "index.js", 5 | "author": "keroxp ", 6 | "license": "MIT", 7 | "scripts": { 8 | "fmt": "prettier --write 'src/**/*.ts'", 9 | "test": "jest --forceExit --detectOpenHandles" 10 | }, 11 | "devDependencies": { 12 | "@types/jest": "^24.0.22", 13 | "@types/node": "^12.12.6", 14 | "jest": "^24.9.0", 15 | "prettier": "^1.19.1", 16 | "ts-jest": "^26.4.3", 17 | "ts-node": "^8.4.1", 18 | "typescript": "^3.7.2" 19 | }, 20 | "dependencies": { 21 | "js-base64": "^2.5.1", 22 | "node-fetch": "^2.6.0" 23 | }, 24 | "jest": { 25 | "preset": "ts-jest" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/__tests__/fs.test.ts: -------------------------------------------------------------------------------- 1 | import * as Deno from "../deno"; 2 | import { encode } from "../util"; 3 | import * as fs from "fs"; 4 | 5 | describe("fs", () => { 6 | describe("read", () => { 7 | const decode = (s: Uint8Array) => Buffer.from(s).toString(); 8 | test("readFileSync", () => { 9 | const buf = Deno.readFileSync("./fixtures/sample.txt"); 10 | expect(decode(buf)).toBe("Deno and Node"); 11 | }); 12 | test("readFile", async () => { 13 | const buf = await Deno.readFile("./fixtures/sample.txt"); 14 | expect(decode(buf)).toBe("Deno and Node"); 15 | }); 16 | test("open", async () => { 17 | const f = await Deno.open("./fixtures/sample.txt"); 18 | const buf = new Deno.Buffer(); 19 | await Deno.copy(buf, f); 20 | f.close(); 21 | expect(buf.toString()).toBe("Deno and Node"); 22 | }); 23 | test("openSync", async () => { 24 | expect(() => { 25 | Deno.openSync("./fixtures/sample.txt"); 26 | }).toThrowError(Error); 27 | }); 28 | test("close", async () => { 29 | const resCount = Object.entries(Deno.resources()).length; 30 | const f = await Deno.open("./fixtures/sample.txt"); 31 | expect(Object.entries(Deno.resources()).length).toBe(resCount + 1); 32 | expect(Deno.resources()[f.rid]).toBe("file"); 33 | Deno.close(f.rid); 34 | expect(Object.entries(Deno.resources()).length).toBe(resCount); 35 | }); 36 | }); 37 | describe("write", () => { 38 | beforeAll(async () => { 39 | await fs.promises.mkdir("./tmp"); 40 | }); 41 | async function assertFile(path: string, content: string) { 42 | const v = await fs.promises.readFile(path); 43 | expect(v.toString()).toBe(content); 44 | } 45 | afterAll(async () => { 46 | await fs.promises.rmdir("./tmp", { recursive: true }); 47 | }); 48 | test("writeFileSync", async () => { 49 | const dest = "./tmp/writeFileSync.txt"; 50 | const exp = "Deno and Node"; 51 | Deno.writeFileSync(dest, encode(exp)); 52 | await assertFile(dest, exp); 53 | }); 54 | test("writeFile", async () => { 55 | const dest = "./tmp/writeFile.txt"; 56 | const exp = "Deno and Node"; 57 | await Deno.writeFile(dest, encode(exp)); 58 | await assertFile(dest, exp); 59 | }); 60 | test("writeSync", async () => { 61 | const dest = "./tmp/writeSync.txt"; 62 | const exp = "Deno and Node"; 63 | const f = await Deno.open(dest, "w"); 64 | Deno.writeSync(f.rid, encode(exp)); 65 | f.close(); 66 | await assertFile(dest, exp); 67 | }); 68 | test("write", async () => { 69 | const dest = "./tmp/write.txt"; 70 | const exp = "Deno and Node"; 71 | const f = await Deno.open(dest, "w"); 72 | await Deno.write(f.rid, encode(exp)); 73 | f.close(); 74 | await assertFile(dest, exp); 75 | }); 76 | }); 77 | test("mkdir", async () => { 78 | await Deno.mkdir("./mkdir"); 79 | const stat = await fs.promises.stat("./mkdir"); 80 | expect(stat.isDirectory()).toBe(true); 81 | await fs.promises.rmdir("./mkdir"); 82 | }); 83 | test("mkdir -p", async () => { 84 | await Deno.mkdir("./mkdir/sub/dir", true); 85 | const stat = await fs.promises.stat("./mkdir/sub/dir"); 86 | expect(stat.isDirectory()).toBe(true); 87 | await fs.promises.rmdir("./mkdir/sub/dir", { recursive: true }); 88 | }); 89 | test("mkdirSync", async () => { 90 | Deno.mkdirSync("./mkdirSync"); 91 | const stat = await fs.promises.stat("./mkdirSync"); 92 | expect(stat.isDirectory()).toBe(true); 93 | await fs.promises.rmdir("./mkdirSync"); 94 | }); 95 | test("mkdirSync -p", async () => { 96 | Deno.mkdirSync("./mkdirSync/sub/dir", true); 97 | const stat = await fs.promises.stat("./mkdirSync/sub/dir"); 98 | expect(stat.isDirectory()).toBe(true); 99 | await fs.promises.rmdir("./mkdirSync/sub/dir"); 100 | }); 101 | }); 102 | -------------------------------------------------------------------------------- /src/__tests__/io.test.ts: -------------------------------------------------------------------------------- 1 | import * as Deno from "../deno"; 2 | describe("io", () => { 3 | test("copy", async () => { 4 | const dest = new Deno.Buffer(); 5 | const src = await Deno.open("fixtures/sample.txt"); 6 | await Deno.copy(dest, src); 7 | expect(dest.toString()).toBe("Deno and Node"); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /src/__tests__/os.test.ts: -------------------------------------------------------------------------------- 1 | import * as Deno from "../deno"; 2 | import * as os from "os"; 3 | import * as path from "path"; 4 | 5 | describe("main", () => { 6 | test("pid", () => { 7 | expect(Deno.pid).toBe(process.pid); 8 | }); 9 | test("noColor", () => { 10 | expect(Deno.noColor).toBe(true); 11 | }); 12 | test("isTTY", () => { 13 | expect(Deno.isTTY()).toMatchObject({ 14 | stdin: process.stdin.isTTY, 15 | stdout: process.stdout.isTTY, 16 | stderr: process.stderr.isTTY 17 | }); 18 | }); 19 | test("hostname", () => { 20 | expect(Deno.hostname()).toBe(os.hostname()); 21 | }); 22 | test("homedir", () => { 23 | expect(Deno.homeDir()).toBe(os.homedir()); 24 | }); 25 | test("execPath", () => { 26 | expect(Deno.execPath()).toBe(process.execPath); 27 | }); 28 | test("cwd", () => { 29 | expect(Deno.cwd()).toBe(process.cwd()); 30 | }); 31 | test("chdir", () => { 32 | const cwd = process.cwd(); 33 | Deno.chdir("node_modules"); 34 | expect(Deno.cwd()).toBe(process.cwd()); 35 | expect(Deno.cwd()).toBe(path.join(cwd, "node_modules")); 36 | Deno.chdir(cwd); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /src/buffer.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. 2 | 3 | // This code has been ported almost directly from Go's src/bytes/buffer.go 4 | // Copyright 2009 The Go Authors. All rights reserved. BSD license. 5 | // https://github.com/golang/go/blob/master/LICENSE 6 | 7 | import { TextDecoder } from "./encoding"; 8 | import { 9 | DenoError, 10 | EOF, 11 | ErrorKind, 12 | Reader, 13 | SyncReader, 14 | SyncWriter, 15 | Writer 16 | } from "./deno"; 17 | 18 | // MIN_READ is the minimum ArrayBuffer size passed to a read call by 19 | // buffer.ReadFrom. As long as the Buffer has at least MIN_READ bytes beyond 20 | // what is required to hold the contents of r, readFrom() will not grow the 21 | // underlying buffer. 22 | const MIN_READ = 512; 23 | const MAX_SIZE = 2 ** 32 - 2; 24 | 25 | // `off` is the offset into `dst` where it will at which to begin writing values 26 | // from `src`. 27 | // Returns the number of bytes copied. 28 | function copyBytes(dst: Uint8Array, src: Uint8Array, off = 0): number { 29 | const r = dst.byteLength - off; 30 | if (src.byteLength > r) { 31 | src = src.subarray(0, r); 32 | } 33 | dst.set(src, off); 34 | return src.byteLength; 35 | } 36 | 37 | /** A Buffer is a variable-sized buffer of bytes with read() and write() 38 | * methods. Based on https://golang.org/pkg/bytes/#Buffer 39 | */ 40 | export class Buffer implements Reader, SyncReader, Writer, SyncWriter { 41 | private buf: Uint8Array; // contents are the bytes buf[off : len(buf)] 42 | private off = 0; // read at buf[off], write at buf[buf.byteLength] 43 | 44 | constructor(ab?: ArrayBuffer) { 45 | if (ab == null) { 46 | this.buf = new Uint8Array(0); 47 | return; 48 | } 49 | 50 | this.buf = new Uint8Array(ab); 51 | } 52 | 53 | /** bytes() returns a slice holding the unread portion of the buffer. 54 | * The slice is valid for use only until the next buffer modification (that 55 | * is, only until the next call to a method like read(), write(), reset(), or 56 | * truncate()). The slice aliases the buffer content at least until the next 57 | * buffer modification, so immediate changes to the slice will affect the 58 | * result of future reads. 59 | */ 60 | bytes(): Uint8Array { 61 | return this.buf.subarray(this.off); 62 | } 63 | 64 | /** toString() returns the contents of the unread portion of the buffer 65 | * as a string. Warning - if multibyte characters are present when data is 66 | * flowing through the buffer, this method may result in incorrect strings 67 | * due to a character being split. 68 | */ 69 | toString(): string { 70 | const decoder = new TextDecoder(); 71 | return decoder.decode(this.buf.subarray(this.off)); 72 | } 73 | 74 | /** empty() returns whether the unread portion of the buffer is empty. */ 75 | empty(): boolean { 76 | return this.buf.byteLength <= this.off; 77 | } 78 | 79 | /** length is a getter that returns the number of bytes of the unread 80 | * portion of the buffer 81 | */ 82 | get length(): number { 83 | return this.buf.byteLength - this.off; 84 | } 85 | 86 | /** Returns the capacity of the buffer's underlying byte slice, that is, 87 | * the total space allocated for the buffer's data. 88 | */ 89 | get capacity(): number { 90 | return this.buf.buffer.byteLength; 91 | } 92 | 93 | /** truncate() discards all but the first n unread bytes from the buffer but 94 | * continues to use the same allocated storage. It throws if n is negative or 95 | * greater than the length of the buffer. 96 | */ 97 | truncate(n: number): void { 98 | if (n === 0) { 99 | this.reset(); 100 | return; 101 | } 102 | if (n < 0 || n > this.length) { 103 | throw Error("bytes.Buffer: truncation out of range"); 104 | } 105 | this._reslice(this.off + n); 106 | } 107 | 108 | /** reset() resets the buffer to be empty, but it retains the underlying 109 | * storage for use by future writes. reset() is the same as truncate(0) 110 | */ 111 | reset(): void { 112 | this._reslice(0); 113 | this.off = 0; 114 | } 115 | 116 | /** _tryGrowByReslice() is a version of grow for the fast-case 117 | * where the internal buffer only needs to be resliced. It returns the index 118 | * where bytes should be written and whether it succeeded. 119 | * It returns -1 if a reslice was not needed. 120 | */ 121 | private _tryGrowByReslice(n: number): number { 122 | const l = this.buf.byteLength; 123 | if (n <= this.capacity - l) { 124 | this._reslice(l + n); 125 | return l; 126 | } 127 | return -1; 128 | } 129 | 130 | private _reslice(len: number): void { 131 | if (len > this.buf.buffer.byteLength) { 132 | throw new Error("short len"); 133 | } 134 | this.buf = new Uint8Array(this.buf.buffer, 0, len); 135 | } 136 | 137 | /** readSync() reads the next len(p) bytes from the buffer or until the buffer 138 | * is drained. The return value n is the number of bytes read. If the 139 | * buffer has no data to return, eof in the response will be true. 140 | */ 141 | readSync(p: Uint8Array): number | EOF { 142 | if (this.empty()) { 143 | // Buffer is empty, reset to recover space. 144 | this.reset(); 145 | if (p.byteLength === 0) { 146 | // this edge case is tested in 'bufferReadEmptyAtEOF' test 147 | return 0; 148 | } 149 | return EOF; 150 | } 151 | const nread = copyBytes(p, this.buf.subarray(this.off)); 152 | this.off += nread; 153 | return nread; 154 | } 155 | 156 | async read(p: Uint8Array): Promise { 157 | const rr = this.readSync(p); 158 | return Promise.resolve(rr); 159 | } 160 | 161 | writeSync(p: Uint8Array): number { 162 | const m = this._grow(p.byteLength); 163 | return copyBytes(this.buf, p, m); 164 | } 165 | 166 | async write(p: Uint8Array): Promise { 167 | const n = this.writeSync(p); 168 | return Promise.resolve(n); 169 | } 170 | 171 | /** _grow() grows the buffer to guarantee space for n more bytes. 172 | * It returns the index where bytes should be written. 173 | * If the buffer can't grow it will throw with ErrTooLarge. 174 | */ 175 | private _grow(n: number): number { 176 | const m = this.length; 177 | // If buffer is empty, reset to recover space. 178 | if (m === 0 && this.off !== 0) { 179 | this.reset(); 180 | } 181 | // Fast: Try to grow by means of a reslice. 182 | const i = this._tryGrowByReslice(n); 183 | if (i >= 0) { 184 | return i; 185 | } 186 | const c = this.capacity; 187 | if (n <= Math.floor(c / 2) - m) { 188 | // We can slide things down instead of allocating a new 189 | // ArrayBuffer. We only need m+n <= c to slide, but 190 | // we instead let capacity get twice as large so we 191 | // don't spend all our time copying. 192 | copyBytes(this.buf, this.buf.subarray(this.off)); 193 | } else if (c > MAX_SIZE - c - n) { 194 | throw new DenoError( 195 | ErrorKind.TooLarge, 196 | "The buffer cannot be grown beyond the maximum size." 197 | ); 198 | } else { 199 | // Not enough space anywhere, we need to allocate. 200 | const buf = new Uint8Array(2 * c + n); 201 | copyBytes(buf, this.buf.subarray(this.off)); 202 | this.buf = buf; 203 | } 204 | // Restore this.off and len(this.buf). 205 | this.off = 0; 206 | this._reslice(m + n); 207 | return m; 208 | } 209 | 210 | /** grow() grows the buffer's capacity, if necessary, to guarantee space for 211 | * another n bytes. After grow(n), at least n bytes can be written to the 212 | * buffer without another allocation. If n is negative, grow() will panic. If 213 | * the buffer can't grow it will throw ErrTooLarge. 214 | * Based on https://golang.org/pkg/bytes/#Buffer.Grow 215 | */ 216 | grow(n: number): void { 217 | if (n < 0) { 218 | throw Error("Buffer.grow: negative count"); 219 | } 220 | const m = this._grow(n); 221 | this._reslice(m); 222 | } 223 | 224 | /** readFrom() reads data from r until EOF and appends it to the buffer, 225 | * growing the buffer as needed. It returns the number of bytes read. If the 226 | * buffer becomes too large, readFrom will panic with ErrTooLarge. 227 | * Based on https://golang.org/pkg/bytes/#Buffer.ReadFrom 228 | */ 229 | async readFrom(r: Reader): Promise { 230 | let n = 0; 231 | while (true) { 232 | try { 233 | const i = this._grow(MIN_READ); 234 | this._reslice(i); 235 | const fub = new Uint8Array(this.buf.buffer, i); 236 | const nread = await r.read(fub); 237 | if (nread === EOF) { 238 | return n; 239 | } 240 | this._reslice(i + nread); 241 | n += nread; 242 | } catch (e) { 243 | return n; 244 | } 245 | } 246 | } 247 | 248 | /** Sync version of `readFrom` 249 | */ 250 | readFromSync(r: SyncReader): number { 251 | let n = 0; 252 | while (true) { 253 | try { 254 | const i = this._grow(MIN_READ); 255 | this._reslice(i); 256 | const fub = new Uint8Array(this.buf.buffer, i); 257 | const nread = r.readSync(fub); 258 | if (nread === EOF) { 259 | return n; 260 | } 261 | this._reslice(i + nread); 262 | n += nread; 263 | } catch (e) { 264 | return n; 265 | } 266 | } 267 | } 268 | } 269 | 270 | /** Read `r` until EOF and return the content as `Uint8Array`. 271 | */ 272 | export async function readAll(r: Reader): Promise { 273 | const buf = new Buffer(); 274 | await buf.readFrom(r); 275 | return buf.bytes(); 276 | } 277 | 278 | /** Read synchronously `r` until EOF and return the content as `Uint8Array`. 279 | */ 280 | export function readAllSync(r: SyncReader): Uint8Array { 281 | const buf = new Buffer(); 282 | buf.readFromSync(r); 283 | return buf.bytes(); 284 | } 285 | 286 | /** Write all the content of `arr` to `w`. 287 | */ 288 | export async function writeAll(w: Writer, arr: Uint8Array): Promise { 289 | let nwritten = 0; 290 | while (nwritten < arr.length) { 291 | nwritten += await w.write(arr.subarray(nwritten)); 292 | } 293 | } 294 | 295 | /** Write synchronously all the content of `arr` to `w`. 296 | */ 297 | export function writeAllSync(w: SyncWriter, arr: Uint8Array): void { 298 | let nwritten = 0; 299 | while (nwritten < arr.length) { 300 | nwritten += w.writeSync(arr.subarray(nwritten)); 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /src/deno.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as util from "util"; 3 | import * as os from "os"; 4 | import * as path from "path"; 5 | import * as cp from "child_process"; 6 | import { ResourceTable } from "./resources"; 7 | import { DenoFileImpl } from "./file"; 8 | import { DenoProcessImpl } from "./process"; 9 | 10 | // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. 11 | 12 | /* eslint-disable @typescript-eslint/no-explicit-any */ 13 | /* eslint-disable @typescript-eslint/no-empty-interface */ 14 | 15 | /// 16 | /// 17 | 18 | // @url js/os.d.ts 19 | 20 | /** The current process id of the runtime. */ 21 | export let pid: number = process.pid; 22 | /** Reflects the NO_COLOR environment variable: https://no-color.org/ */ 23 | export let noColor: boolean = true; 24 | 25 | /** Check if running in terminal. 26 | * 27 | * console.log(Deno.isTTY().stdout); 28 | */ 29 | export function isTTY(): { 30 | stdin: boolean; 31 | stdout: boolean; 32 | stderr: boolean; 33 | } { 34 | return { 35 | stdin: process.stdin.isTTY, 36 | stdout: process.stdout.isTTY, 37 | stderr: process.stderr.isTTY 38 | }; 39 | } 40 | 41 | /** Get the hostname. 42 | * Requires the `--allow-env` flag. 43 | * 44 | * console.log(Deno.hostname()); 45 | */ 46 | export function hostname(): string { 47 | return os.hostname(); 48 | } 49 | 50 | /** Exit the Deno process with optional exit code. */ 51 | export function exit(code?: number): void { 52 | process.exit(code); 53 | } 54 | 55 | /** Returns a snapshot of the environment variables at invocation. Mutating a 56 | * property in the object will set that variable in the environment for 57 | * the process. The environment object will only accept `string`s 58 | * as values. 59 | * 60 | * const myEnv = Deno.env(); 61 | * console.log(myEnv.SHELL); 62 | * myEnv.TEST_VAR = "HELLO"; 63 | * const newEnv = Deno.env(); 64 | * console.log(myEnv.TEST_VAR == newEnv.TEST_VAR); 65 | */ 66 | export function env(): { 67 | [index: string]: string; 68 | }; 69 | /** Returns the value of an environment variable at invocation. 70 | * If the variable is not present, `undefined` will be returned. 71 | * 72 | * const myEnv = Deno.env(); 73 | * console.log(myEnv.SHELL); 74 | * myEnv.TEST_VAR = "HELLO"; 75 | * const newEnv = Deno.env(); 76 | * console.log(myEnv.TEST_VAR == newEnv.TEST_VAR); 77 | */ 78 | export function env(key: string): string | undefined; 79 | export function env(key?: string) { 80 | if (key != null) { 81 | return process.env[key]; 82 | } 83 | return process.env; 84 | } 85 | 86 | /** 87 | * Returns the current user's home directory. 88 | * Requires the `--allow-env` flag. 89 | */ 90 | export function homeDir(): string { 91 | return os.homedir(); 92 | } 93 | 94 | /** 95 | * Returns the path to the current deno executable. 96 | * Requires the `--allow-env` flag. 97 | */ 98 | export function execPath(): string { 99 | return process.execPath; 100 | } 101 | 102 | // @url js/dir.d.ts 103 | 104 | /** 105 | * `cwd()` Return a string representing the current working directory. 106 | * If the current directory can be reached via multiple paths 107 | * (due to symbolic links), `cwd()` may return 108 | * any one of them. 109 | * throws `NotFound` exception if directory not available 110 | */ 111 | export function cwd(): string { 112 | return process.cwd(); 113 | } 114 | 115 | /** 116 | * `chdir()` Change the current working directory to path. 117 | * throws `NotFound` exception if directory not available 118 | */ 119 | export function chdir(directory: string): void { 120 | process.chdir(directory); 121 | } 122 | export const EOF = Symbol("EOF"); 123 | export type EOF = typeof EOF; 124 | 125 | export enum SeekMode { 126 | SEEK_START = 0, 127 | SEEK_CURRENT = 1, 128 | SEEK_END = 2 129 | } 130 | export interface Reader { 131 | /** Reads up to p.byteLength bytes into `p`. It resolves to the number 132 | * of bytes read (`0` < `n` <= `p.byteLength`) and rejects if any error encountered. 133 | * Even if `read()` returns `n` < `p.byteLength`, it may use all of `p` as 134 | * scratch space during the call. If some data is available but not 135 | * `p.byteLength` bytes, `read()` conventionally returns what is available 136 | * instead of waiting for more. 137 | * 138 | * When `read()` encounters end-of-file condition, it returns EOF symbol. 139 | * 140 | * When `read()` encounters an error, it rejects with an error. 141 | * 142 | * Callers should always process the `n` > `0` bytes returned before 143 | * considering the EOF. Doing so correctly handles I/O errors that happen 144 | * after reading some bytes and also both of the allowed EOF behaviors. 145 | * 146 | * Implementations must not retain `p`. 147 | */ 148 | read(p: Uint8Array): Promise; 149 | } 150 | export interface SyncReader { 151 | readSync(p: Uint8Array): number | EOF; 152 | } 153 | export interface Writer { 154 | /** Writes `p.byteLength` bytes from `p` to the underlying data 155 | * stream. It resolves to the number of bytes written from `p` (`0` <= `n` <= 156 | * `p.byteLength`) and any error encountered that caused the write to stop 157 | * early. `write()` must return a non-null error if it returns `n` < 158 | * `p.byteLength`. write() must not modify the slice data, even temporarily. 159 | * 160 | * Implementations must not retain `p`. 161 | */ 162 | write(p: Uint8Array): Promise; 163 | } 164 | export interface SyncWriter { 165 | writeSync(p: Uint8Array): number; 166 | } 167 | export interface Closer { 168 | close(): void; 169 | } 170 | export interface Seeker { 171 | /** Seek sets the offset for the next `read()` or `write()` to offset, 172 | * interpreted according to `whence`: `SeekStart` means relative to the start 173 | * of the file, `SeekCurrent` means relative to the current offset, and 174 | * `SeekEnd` means relative to the end. Seek returns the new offset relative 175 | * to the start of the file and an error, if any. 176 | * 177 | * Seeking to an offset before the start of the file is an error. Seeking to 178 | * any positive offset is legal, but the behavior of subsequent I/O operations 179 | * on the underlying object is implementation-dependent. 180 | */ 181 | seek(offset: number, whence: SeekMode): Promise; 182 | } 183 | export interface SyncSeeker { 184 | seekSync(offset: number, whence: SeekMode): void; 185 | } 186 | export interface ReadCloser extends Reader, Closer {} 187 | export interface WriteCloser extends Writer, Closer {} 188 | export interface ReadSeeker extends Reader, Seeker {} 189 | export interface WriteSeeker extends Writer, Seeker {} 190 | export interface ReadWriteCloser extends Reader, Writer, Closer {} 191 | export interface ReadWriteSeeker extends Reader, Writer, Seeker {} 192 | 193 | /** Copies from `src` to `dst` until either `EOF` is reached on `src` 194 | * or an error occurs. It returns the number of bytes copied and the first 195 | * error encountered while copying, if any. 196 | * 197 | * Because `copy()` is defined to read from `src` until `EOF`, it does not 198 | * treat an `EOF` from `read()` as an error to be reported. 199 | */ 200 | export async function copy(dst: Writer, src: Reader): Promise { 201 | const buf = new Uint8Array(2048); 202 | let result: EOF | number; 203 | let total = 0; 204 | while ((result = await src.read(buf)) !== EOF) { 205 | if (result === buf.byteLength) { 206 | await dst.write(buf); 207 | } else { 208 | await dst.write(buf.subarray(0, result)); 209 | } 210 | total += result; 211 | } 212 | return total; 213 | } 214 | 215 | /** Turns `r` into async iterator. 216 | * 217 | * for await (const chunk of toAsyncIterator(reader)) { 218 | * console.log(chunk) 219 | * } 220 | */ 221 | export async function* toAsyncIterator( 222 | r: Reader 223 | ): AsyncIterableIterator { 224 | let result: EOF | number; 225 | const buf = new Uint8Array(2048); 226 | while ((result = await r.read(buf)) !== EOF) { 227 | if (result === buf.byteLength) { 228 | yield buf; 229 | } else { 230 | yield buf.subarray(0, result); 231 | } 232 | } 233 | } 234 | 235 | export interface DenoFile 236 | extends Reader, 237 | SyncReader, 238 | Writer, 239 | SyncWriter, 240 | Seeker, 241 | SyncSeeker, 242 | Closer { 243 | readonly rid: number; 244 | } 245 | 246 | class DenoStdioImpl implements DenoFile { 247 | readonly rid = this.fd; 248 | constructor(readonly fd: 0 | 1 | 2) {} 249 | close(): void { 250 | // noop 251 | } 252 | 253 | offs = 0; 254 | read(p: Uint8Array): Promise { 255 | return new Promise((resolve, reject) => { 256 | fs.read(this.fd, p, 0, p.byteLength, this.offs, (err, bytesRead) => { 257 | if (err) { 258 | reject(err); 259 | } else if (bytesRead === 0) { 260 | resolve(EOF); 261 | } else { 262 | this.offs += bytesRead; 263 | resolve(bytesRead); 264 | } 265 | }); 266 | }); 267 | } 268 | 269 | readSync(p: Uint8Array): number | EOF { 270 | const bytesRead = fs.readSync(this.fd, p, 0, p.byteLength, this.offs); 271 | this.offs += bytesRead; 272 | return bytesRead === 0 ? EOF : bytesRead; 273 | } 274 | 275 | seek(offset: number, whence: SeekMode): Promise { 276 | throw new Error("stdin/stdout/stderr can't be seeked"); 277 | } 278 | 279 | seekSync(offset: number, whence: SeekMode): void { 280 | throw new Error("stdin/stdout/stderr can't be seeked"); 281 | } 282 | 283 | write(p: Uint8Array): Promise { 284 | return new Promise((resolve, reject) => { 285 | fs.write(this.fd, p, 0, p.byteLength, this.offs, (err, written) => { 286 | if (err) { 287 | reject(err); 288 | } else { 289 | this.offs += written; 290 | resolve(written); 291 | } 292 | }); 293 | }); 294 | } 295 | 296 | writeSync(p: Uint8Array): number { 297 | return fs.writeSync(this.fd, p, 0, p.byteLength, this.offs); 298 | } 299 | } 300 | 301 | export { DenoFileImpl as File }; 302 | 303 | // @url js/files.d.ts 304 | 305 | /** Open a file and return an instance of the `File` object 306 | * synchronously. 307 | * 308 | * const file = Deno.openSync("/foo/bar.txt"); 309 | */ 310 | /** @deprecated */ 311 | export function openSync(filename: string, mode?: OpenMode): DenoFile { 312 | // const file = awaitPromiseSync(fs.promises.open(filename, mode)); 313 | // return ResourceTable.openFile(file); 314 | throw new Error("openSync is unsupported because of technical reason."); 315 | } 316 | 317 | /** Open a file and return an instance of the `File` object. 318 | * 319 | * (async () => { 320 | * const file = await Deno.open("/foo/bar.txt"); 321 | * })(); 322 | */ 323 | export async function open( 324 | filename: string, 325 | mode?: OpenMode 326 | ): Promise { 327 | const fileHandle = await fs.promises.open(filename, mode); 328 | return ResourceTable.openFile(fileHandle); 329 | } 330 | 331 | /** Read synchronously from a file ID into an array buffer. 332 | * 333 | * Return `number | EOF` for the operation. 334 | * 335 | * const file = Deno.openSync("/foo/bar.txt"); 336 | * const buf = new Uint8Array(100); 337 | * const nread = Deno.readSync(file.rid, buf); 338 | * const text = new TextDecoder().decode(buf); 339 | * 340 | */ 341 | export function readSync(rid: number, p: Uint8Array): number | EOF { 342 | return ResourceTable.getFile(rid).readSync(p); 343 | } 344 | 345 | /** Read from a file ID into an array buffer. 346 | * 347 | * Resolves with the `number | EOF` for the operation. 348 | * 349 | * (async () => { 350 | * const file = await Deno.open("/foo/bar.txt"); 351 | * const buf = new Uint8Array(100); 352 | * const nread = await Deno.read(file.rid, buf); 353 | * const text = new TextDecoder().decode(buf); 354 | * })(); 355 | */ 356 | export function read(rid: number, p: Uint8Array): Promise { 357 | return ResourceTable.getFile(rid).read(p); 358 | } 359 | 360 | /** Write synchronously to the file ID the contents of the array buffer. 361 | * 362 | * Resolves with the number of bytes written. 363 | * 364 | * const encoder = new TextEncoder(); 365 | * const data = encoder.encode("Hello world\n"); 366 | * const file = Deno.openSync("/foo/bar.txt"); 367 | * Deno.writeSync(file.rid, data); 368 | */ 369 | export function writeSync(rid: number, p: Uint8Array): number { 370 | return ResourceTable.getFile(rid).writeSync(p); 371 | } 372 | 373 | /** Write to the file ID the contents of the array buffer. 374 | * 375 | * Resolves with the number of bytes written. 376 | * 377 | * (async () => { 378 | * const encoder = new TextEncoder(); 379 | * const data = encoder.encode("Hello world\n"); 380 | * const file = await Deno.open("/foo/bar.txt"); 381 | * await Deno.write(file.rid, data); 382 | * })(); 383 | * 384 | */ 385 | export function write(rid: number, p: Uint8Array): Promise { 386 | return ResourceTable.getFile(rid).write(p); 387 | } 388 | 389 | /** Seek a file ID synchronously to the given offset under mode given by `whence`. 390 | * 391 | * const file = Deno.openSync("/foo/bar.txt"); 392 | * Deno.seekSync(file.rid, 0, 0); 393 | */ 394 | export function seekSync(rid: number, offset: number, whence: SeekMode): void { 395 | ResourceTable.getFile(rid).seekSync(offset, whence); 396 | } 397 | 398 | /** Seek a file ID to the given offset under mode given by `whence`. 399 | * 400 | * (async () => { 401 | * const file = await Deno.open("/foo/bar.txt"); 402 | * await Deno.seek(file.rid, 0, 0); 403 | * })(); 404 | */ 405 | export function seek( 406 | rid: number, 407 | offset: number, 408 | whence: SeekMode 409 | ): Promise { 410 | return ResourceTable.getFile(rid).seek(offset, whence); 411 | } 412 | 413 | /** Close the file ID. */ 414 | export function close(rid: number): void { 415 | ResourceTable.close(rid); 416 | } 417 | 418 | /** An instance of `File` for stdin. */ 419 | export const stdin: DenoFile = new DenoStdioImpl(0); 420 | /** An instance of `File` for stdout. */ 421 | export const stdout: DenoFile = new DenoStdioImpl(1); 422 | /** An instance of `File` for stderr. */ 423 | export const stderr: DenoFile = new DenoStdioImpl(2); 424 | 425 | export type OpenMode = 426 | | "r" 427 | /** Read-write. Start at beginning of file. */ 428 | | "r+" 429 | /** Write-only. Opens and truncates existing file or creates new one for 430 | * writing only. 431 | */ 432 | | "w" 433 | /** Read-write. Opens and truncates existing file or creates new one for 434 | * writing and reading. 435 | */ 436 | | "w+" 437 | /** Write-only. Opens existing file or creates new one. Each write appends 438 | * content to the end of file. 439 | */ 440 | | "a" 441 | /** Read-write. Behaves like "a" and allows to read from file. */ 442 | | "a+" 443 | /** Write-only. Exclusive create - creates new file only if one doesn't exist 444 | * already. 445 | */ 446 | | "x" 447 | /** Read-write. Behaves like `x` and allows to read from file. */ 448 | | "x+"; 449 | 450 | // @url js/mkdir.d.ts 451 | 452 | /** Creates a new directory with the specified path synchronously. 453 | * If `recursive` is set to true, nested directories will be created (also known 454 | * as "mkdir -p"). 455 | * `mode` sets permission bits (before umask) on UNIX and does nothing on 456 | * Windows. 457 | * 458 | * Deno.mkdirSync("new_dir"); 459 | * Deno.mkdirSync("nested/directories", true); 460 | */ 461 | export function mkdirSync( 462 | path: string, 463 | recursive?: boolean, 464 | mode?: number 465 | ): void { 466 | fs.mkdirSync(path, { recursive, mode }); 467 | } 468 | 469 | /** Creates a new directory with the specified path. 470 | * If `recursive` is set to true, nested directories will be created (also known 471 | * as "mkdir -p"). 472 | * `mode` sets permission bits (before umask) on UNIX and does nothing on 473 | * Windows. 474 | * 475 | * await Deno.mkdir("new_dir"); 476 | * await Deno.mkdir("nested/directories", true); 477 | */ 478 | export function mkdir( 479 | path: string, 480 | recursive?: boolean, 481 | mode?: number 482 | ): Promise { 483 | return new Promise((resolve, reject) => { 484 | fs.mkdir(path, { mode, recursive }, err => { 485 | err ? reject(err) : resolve(); 486 | }); 487 | }); 488 | } 489 | 490 | export interface MakeTempDirOptions { 491 | dir?: string; 492 | prefix?: string; 493 | suffix?: string; 494 | } 495 | 496 | /** makeTempDirSync is the synchronous version of `makeTempDir`. 497 | * 498 | * const tempDirName0 = Deno.makeTempDirSync(); 499 | * const tempDirName1 = Deno.makeTempDirSync({ prefix: 'my_temp' }); 500 | */ 501 | export function makeTempDirSync(options?: MakeTempDirOptions): string { 502 | if (!options) { 503 | return fs.mkdtempSync(""); 504 | } else { 505 | let dir = options.dir || os.tmpdir(); 506 | const prefix = options.prefix || ""; 507 | const suffix = options.suffix || ""; 508 | while (true) { 509 | const rand = Math.random() * 100000; 510 | const ret = path.join(dir, `${prefix}${rand}${suffix}`); 511 | if (!fs.existsSync(ret)) { 512 | mkdirSync(ret); 513 | return ret; 514 | } 515 | } 516 | } 517 | } 518 | 519 | /** makeTempDir creates a new temporary directory in the directory `dir`, its 520 | * name beginning with `prefix` and ending with `suffix`. 521 | * It returns the full path to the newly created directory. 522 | * If `dir` is unspecified, tempDir uses the default directory for temporary 523 | * files. Multiple programs calling tempDir simultaneously will not choose the 524 | * same directory. It is the caller's responsibility to remove the directory 525 | * when no longer needed. 526 | * 527 | * const tempDirName0 = await Deno.makeTempDir(); 528 | * const tempDirName1 = await Deno.makeTempDir({ prefix: 'my_temp' }); 529 | */ 530 | export async function makeTempDir( 531 | options?: MakeTempDirOptions 532 | ): Promise { 533 | if (!options) { 534 | return fs.promises.mkdtemp(""); 535 | } else { 536 | let dir = options.dir || os.tmpdir(); 537 | const prefix = options.prefix || ""; 538 | const suffix = options.suffix || ""; 539 | const day = Date.now(); 540 | const rand = Math.random() * 100000; 541 | const ret = path.join(dir, `${prefix}${day}-${rand}${suffix}`); 542 | await mkdir(ret, true); 543 | return ret; 544 | } 545 | } 546 | 547 | // @url js/chmod.d.ts 548 | 549 | /** Changes the permission of a specific file/directory of specified path 550 | * synchronously. 551 | * 552 | * Deno.chmodSync("/path/to/file", 0o666); 553 | */ 554 | export function chmodSync(path: string, mode: number): void { 555 | fs.chmodSync(path, mode); 556 | } 557 | 558 | /** Changes the permission of a specific file/directory of specified path. 559 | * 560 | * await Deno.chmod("/path/to/file", 0o666); 561 | */ 562 | export function chmod(path: string, mode: number): Promise { 563 | return fs.promises.chmod(path, mode); 564 | } 565 | 566 | // @url js/chown.d.ts 567 | 568 | /** 569 | * Change owner of a regular file or directory synchronously. Unix only at the moment. 570 | * @param path path to the file 571 | * @param uid user id of the new owner 572 | * @param gid group id of the new owner 573 | */ 574 | export function chownSync(path: string, uid: number, gid: number): void { 575 | fs.chownSync(path, uid, gid); 576 | } 577 | 578 | /** 579 | * Change owner of a regular file or directory asynchronously. Unix only at the moment. 580 | * @param path path to the file 581 | * @param uid user id of the new owner 582 | * @param gid group id of the new owner 583 | */ 584 | export function chown(path: string, uid: number, gid: number): Promise { 585 | return fs.promises.chown(path, uid, gid); 586 | } 587 | 588 | // @url js/utime.d.ts 589 | 590 | /** Synchronously changes the access and modification times of a file system 591 | * object referenced by `filename`. Given times are either in seconds 592 | * (Unix epoch time) or as `Date` objects. 593 | * 594 | * Deno.utimeSync("myfile.txt", 1556495550, new Date()); 595 | */ 596 | export function utimeSync( 597 | filename: string, 598 | atime: number | Date, 599 | mtime: number | Date 600 | ): void { 601 | fs.utimesSync(filename, atime, mtime); 602 | } 603 | 604 | /** Changes the access and modification times of a file system object 605 | * referenced by `filename`. Given times are either in seconds 606 | * (Unix epoch time) or as `Date` objects. 607 | * 608 | * await Deno.utime("myfile.txt", 1556495550, new Date()); 609 | */ 610 | export function utime( 611 | filename: string, 612 | atime: number | Date, 613 | mtime: number | Date 614 | ): Promise { 615 | return fs.promises.utimes(filename, atime, mtime); 616 | } 617 | 618 | export interface RemoveOption { 619 | recursive?: boolean; 620 | } 621 | 622 | /** Removes the named file or directory synchronously. Would throw 623 | * error if permission denied, not found, or directory not empty if `recursive` 624 | * set to false. 625 | * `recursive` is set to false by default. 626 | * 627 | * Deno.removeSync("/path/to/dir/or/file", {recursive: false}); 628 | */ 629 | export function removeSync(path: string, options?: RemoveOption): void { 630 | // TODO: recursive 631 | const stats = fs.statSync(path); 632 | if (stats.isDirectory()) { 633 | fs.rmdirSync(path, { recursive: options.recursive }); 634 | } else { 635 | // TODO: recursive 636 | fs.unlinkSync(path); 637 | } 638 | } 639 | 640 | /** Removes the named file or directory. Would throw error if 641 | * permission denied, not found, or directory not empty if `recursive` set 642 | * to false. 643 | * `recursive` is set to false by default. 644 | * 645 | * await Deno.remove("/path/to/dir/or/file", {recursive: false}); 646 | */ 647 | export async function remove( 648 | path: string, 649 | options?: RemoveOption 650 | ): Promise { 651 | const stats = await fs.promises.stat(path); 652 | if (stats.isDirectory()) { 653 | await fs.promises.rmdir(path, options); 654 | } else { 655 | // TODO: recursive 656 | await fs.promises.unlink(path); 657 | } 658 | } 659 | 660 | // @url js/rename.d.ts 661 | 662 | /** Synchronously renames (moves) `oldpath` to `newpath`. If `newpath` already 663 | * exists and is not a directory, `renameSync()` replaces it. OS-specific 664 | * restrictions may apply when `oldpath` and `newpath` are in different 665 | * directories. 666 | * 667 | * Deno.renameSync("old/path", "new/path"); 668 | */ 669 | export function renameSync(oldpath: string, newpath: string): void { 670 | fs.renameSync(oldpath, newpath); 671 | } 672 | 673 | /** Renames (moves) `oldpath` to `newpath`. If `newpath` already exists and is 674 | * not a directory, `rename()` replaces it. OS-specific restrictions may apply 675 | * when `oldpath` and `newpath` are in different directories. 676 | * 677 | * await Deno.rename("old/path", "new/path"); 678 | */ 679 | export function rename(oldpath: string, newpath: string): Promise { 680 | return fs.promises.rename(oldpath, newpath); 681 | } 682 | 683 | // @url js/read_file.d.ts 684 | 685 | /** Read the entire contents of a file synchronously. 686 | * 687 | * const decoder = new TextDecoder("utf-8"); 688 | * const data = Deno.readFileSync("hello.txt"); 689 | * console.log(decoder.decode(data)); 690 | */ 691 | export function readFileSync(filename: string): Uint8Array { 692 | return fs.readFileSync(filename); 693 | } 694 | 695 | /** Read the entire contents of a file. 696 | * 697 | * const decoder = new TextDecoder("utf-8"); 698 | * const data = await Deno.readFile("hello.txt"); 699 | * console.log(decoder.decode(data)); 700 | */ 701 | export async function readFile(filename: string): Promise { 702 | return fs.promises.readFile(filename); 703 | } 704 | 705 | /** Synchronously reads and returns the entire contents of a file as utf8 encoded string 706 | * encoded string. Reading a directory returns an empty string. 707 | * 708 | * ```ts 709 | * const data = Deno.readTextFileSync("hello.txt"); 710 | * console.log(data); 711 | * ``` 712 | * 713 | * Requires `allow-read` permission. */ 714 | export function readTextFileSync(path: string): string { 715 | return fs.readFileSync(path, "utf8"); 716 | } 717 | 718 | /** Asynchronously reads and returns the entire contents of a file as a utf8 719 | * encoded string. Reading a directory returns an empty data array. 720 | * 721 | * ```ts 722 | * const data = await Deno.readTextFile("hello.txt"); 723 | * console.log(data); 724 | * ``` 725 | * 726 | * Requires `allow-read` permission. */ 727 | export function readTextFile(path: string): Promise { 728 | return fs.promises.readFile(path, "utf8"); 729 | } 730 | export interface FileInfo { 731 | /** The size of the file, in bytes. */ 732 | len: number; 733 | /** The last modification time of the file. This corresponds to the `mtime` 734 | * field from `stat` on Unix and `ftLastWriteTime` on Windows. This may not 735 | * be available on all platforms. 736 | */ 737 | modified: number | null; 738 | /** The last access time of the file. This corresponds to the `atime` 739 | * field from `stat` on Unix and `ftLastAccessTime` on Windows. This may not 740 | * be available on all platforms. 741 | */ 742 | accessed: number | null; 743 | /** The last access time of the file. This corresponds to the `birthtime` 744 | * field from `stat` on Unix and `ftCreationTime` on Windows. This may not 745 | * be available on all platforms. 746 | */ 747 | created: number | null; 748 | /** The underlying raw st_mode bits that contain the standard Unix permissions 749 | * for this file/directory. TODO Match behavior with Go on windows for mode. 750 | */ 751 | mode: number | null; 752 | /** The file or directory name. */ 753 | name: string | null; 754 | /** Returns whether this is info for a regular file. This result is mutually 755 | * exclusive to `FileInfo.isDirectory` and `FileInfo.isSymlink`. 756 | */ 757 | isFile(): boolean; 758 | /** Returns whether this is info for a regular directory. This result is 759 | * mutually exclusive to `FileInfo.isFile` and `FileInfo.isSymlink`. 760 | */ 761 | isDirectory(): boolean; 762 | /** Returns whether this is info for a symlink. This result is 763 | * mutually exclusive to `FileInfo.isFile` and `FileInfo.isDirectory`. 764 | */ 765 | isSymlink(): boolean; 766 | } 767 | 768 | // @url js/read_dir.d.ts 769 | 770 | /** Reads the directory given by path and returns a list of file info 771 | * synchronously. 772 | * 773 | * const files = Deno.readDirSync("/"); 774 | */ 775 | export function readDirSync(path: string): FileInfo[] { 776 | return fs.readdirSync(path).map(statSync); 777 | } 778 | 779 | /** Reads the directory given by path and returns a list of file info. 780 | * 781 | * const files = await Deno.readDir("/"); 782 | */ 783 | export async function readDir(path: string): Promise { 784 | const arr = await fs.promises.readdir(path); 785 | return Promise.all(arr.map(stat)); 786 | } 787 | 788 | // @url js/copy_file.d.ts 789 | 790 | /** Copies the contents of a file to another by name synchronously. 791 | * Creates a new file if target does not exists, and if target exists, 792 | * overwrites original content of the target file. 793 | * 794 | * It would also copy the permission of the original file 795 | * to the destination. 796 | * 797 | * Deno.copyFileSync("from.txt", "to.txt"); 798 | */ 799 | export function copyFileSync(from: string, to: string): void { 800 | fs.copyFileSync(from, to); 801 | } 802 | 803 | /** Copies the contents of a file to another by name. 804 | * 805 | * Creates a new file if target does not exists, and if target exists, 806 | * overwrites original content of the target file. 807 | * 808 | * It would also copy the permission of the original file 809 | * to the destination. 810 | * 811 | * await Deno.copyFile("from.txt", "to.txt"); 812 | */ 813 | export function copyFile(from: string, to: string): Promise { 814 | return fs.promises.copyFile(from, to); 815 | } 816 | 817 | // @url js/read_link.d.ts 818 | 819 | /** Returns the destination of the named symbolic link synchronously. 820 | * 821 | * const targetPath = Deno.readlinkSync("symlink/path"); 822 | */ 823 | export function readlinkSync(name: string): string { 824 | return fs.readlinkSync(name); 825 | } 826 | 827 | /** Returns the destination of the named symbolic link. 828 | * 829 | * const targetPath = await Deno.readlink("symlink/path"); 830 | */ 831 | export function readlink(name: string): Promise { 832 | return fs.promises.readlink(name); 833 | } 834 | 835 | function statToFileInfo(filename: string, stats: fs.Stats): FileInfo { 836 | return { 837 | accessed: stats.atimeMs, 838 | created: stats.ctimeMs, 839 | len: stats.size, 840 | mode: stats.mode, 841 | modified: stats.mtimeMs, 842 | name: filename, // basename? 843 | isDirectory(): boolean { 844 | return stats.isDirectory(); 845 | }, 846 | isFile(): boolean { 847 | return stats.isFile(); 848 | }, 849 | isSymlink(): boolean { 850 | return stats.isSymbolicLink(); 851 | } 852 | }; 853 | } 854 | 855 | /** Queries the file system for information on the path provided. If the given 856 | * path is a symlink information about the symlink will be returned. 857 | * 858 | * const fileInfo = await Deno.lstat("hello.txt"); 859 | * assert(fileInfo.isFile()); 860 | */ 861 | export async function lstat(filename: string): Promise { 862 | const stats = await fs.promises.lstat(filename); 863 | return statToFileInfo(filename, stats); 864 | } 865 | 866 | /** Queries the file system for information on the path provided synchronously. 867 | * If the given path is a symlink information about the symlink will be 868 | * returned. 869 | * 870 | * const fileInfo = Deno.lstatSync("hello.txt"); 871 | * assert(fileInfo.isFile()); 872 | */ 873 | export function lstatSync(filename: string): FileInfo { 874 | const stats = fs.lstatSync(filename); 875 | return statToFileInfo(filename, stats); 876 | } 877 | 878 | /** Queries the file system for information on the path provided. `stat` Will 879 | * always follow symlinks. 880 | * 881 | * const fileInfo = await Deno.stat("hello.txt"); 882 | * assert(fileInfo.isFile()); 883 | */ 884 | export async function stat(filename: string): Promise { 885 | const stats = await fs.promises.stat(filename); 886 | return statToFileInfo(filename, stats); 887 | } 888 | 889 | /** Queries the file system for information on the path provided synchronously. 890 | * `statSync` Will always follow symlinks. 891 | * 892 | * const fileInfo = Deno.statSync("hello.txt"); 893 | * assert(fileInfo.isFile()); 894 | */ 895 | export function statSync(filename: string): FileInfo { 896 | const stats = fs.statSync(filename); 897 | return statToFileInfo(filename, stats); 898 | } 899 | 900 | // @url js/link.d.ts 901 | 902 | /** Synchronously creates `newname` as a hard link to `oldname`. 903 | * 904 | * Deno.linkSync("old/name", "new/name"); 905 | */ 906 | export function linkSync(oldname: string, newname: string): void { 907 | fs.linkSync(oldname, newname); 908 | } 909 | 910 | /** Creates `newname` as a hard link to `oldname`. 911 | * 912 | * await Deno.link("old/name", "new/name"); 913 | */ 914 | export function link(oldname: string, newname: string): Promise { 915 | return fs.promises.link(oldname, newname); 916 | } 917 | 918 | // @url js/symlink.d.ts 919 | 920 | /** Synchronously creates `newname` as a symbolic link to `oldname`. The type 921 | * argument can be set to `dir` or `file` and is only available on Windows 922 | * (ignored on other platforms). 923 | * 924 | * Deno.symlinkSync("old/name", "new/name"); 925 | */ 926 | export function symlinkSync( 927 | oldname: string, 928 | newname: string, 929 | type?: "dir" | "file" 930 | ): void { 931 | fs.symlinkSync(oldname, newname, type); 932 | } 933 | 934 | /** Creates `newname` as a symbolic link to `oldname`. The type argument can be 935 | * set to `dir` or `file` and is only available on Windows (ignored on other 936 | * platforms). 937 | * 938 | * await Deno.symlink("old/name", "new/name"); 939 | */ 940 | export function symlink( 941 | oldname: string, 942 | newname: string, 943 | type?: "file" | "dir" 944 | ): Promise { 945 | return fs.promises.symlink(oldname, newname, type); 946 | } 947 | 948 | // @url js/write_file.d.ts 949 | 950 | /** Options for writing to a file. 951 | * `perm` would change the file's permission if set. 952 | * `create` decides if the file should be created if not exists (default: true) 953 | * `append` decides if the file should be appended (default: false) 954 | */ 955 | export interface WriteFileOptions { 956 | perm?: number; 957 | create?: boolean; 958 | append?: boolean; 959 | } 960 | 961 | /** Write a new file, with given filename and data synchronously. 962 | * 963 | * const encoder = new TextEncoder(); 964 | * const data = encoder.encode("Hello world\n"); 965 | * Deno.writeFileSync("hello.txt", data); 966 | */ 967 | export function writeFileSync( 968 | filename: string, 969 | data: Uint8Array, 970 | options: WriteFileOptions = { 971 | create: true, 972 | append: false 973 | } 974 | ): void { 975 | let flag = "w"; 976 | if (options?.create != null) { 977 | flag = options.create ? "w" : "wx"; 978 | } 979 | if (options.append != null) { 980 | flag = options.append ? "a" : "ax"; 981 | } 982 | fs.writeFileSync(filename, data, { 983 | flag, 984 | mode: options.perm 985 | }); 986 | } 987 | 988 | /** Write a new file, with given filename and data. 989 | * 990 | * const encoder = new TextEncoder(); 991 | * const data = encoder.encode("Hello world\n"); 992 | * await Deno.writeFile("hello.txt", data); 993 | */ 994 | export function writeFile( 995 | filename: string, 996 | data: Uint8Array, 997 | options: WriteFileOptions = { 998 | create: true, 999 | append: false 1000 | } 1001 | ): Promise { 1002 | let flag = "w"; 1003 | if (options.create != null) { 1004 | flag = options.create ? "w" : "wx"; 1005 | } 1006 | if (options.append != null) { 1007 | flag = options.append ? "a" : "ax"; 1008 | } 1009 | return fs.promises.writeFile(filename, data, { 1010 | flag, 1011 | mode: options.perm 1012 | }); 1013 | } 1014 | 1015 | /** Asynchronously write string `data` to the given `path`, by default creating a new file if needed, 1016 | * else overwriting. 1017 | * 1018 | * ```ts 1019 | * await Deno.writeTextFile("hello1.txt", "Hello world\n"); // overwrite "hello1.txt" or create it 1020 | * ``` 1021 | * 1022 | * Requires `allow-write` permission, and `allow-read` if `options.create` is `false`. 1023 | */ 1024 | 1025 | export function writeTextFile( 1026 | filename: string, 1027 | data: string, 1028 | options?: WriteFileOptions 1029 | ): Promise { 1030 | const encoder = new TextEncoder(); 1031 | const UTF8Data = encoder.encode(data); 1032 | return writeFile(filename, UTF8Data, options); 1033 | } 1034 | 1035 | /** Synchronously write string `data` to the given `path`, by default creating a new file if needed, 1036 | * else overwriting. 1037 | * 1038 | * ```ts 1039 | * await Deno.writeTextFileSync("hello1.txt", "Hello world\n"); // overwrite "hello1.txt" or create it 1040 | * ``` 1041 | * 1042 | * Requires `allow-write` permission, and `allow-read` if `options.create` is `false`. 1043 | */ 1044 | export function writeTextFileSync( 1045 | filename: string, 1046 | data: string, 1047 | options?: WriteFileOptions 1048 | ): void { 1049 | const encoder = new TextEncoder(); 1050 | const UTF8Data = encoder.encode(data); 1051 | return writeFileSync(filename, UTF8Data); 1052 | } 1053 | 1054 | // @url js/error_stack.d.ts 1055 | 1056 | interface Location { 1057 | /** The full url for the module, e.g. `file://some/file.ts` or 1058 | * `https://some/file.ts`. */ 1059 | filename: string; 1060 | /** The line number in the file. It is assumed to be 1-indexed. */ 1061 | line: number; 1062 | /** The column number in the file. It is assumed to be 1-indexed. */ 1063 | column: number; 1064 | } 1065 | 1066 | /** Given a current location in a module, lookup the source location and 1067 | * return it. 1068 | * 1069 | * When Deno transpiles code, it keep source maps of the transpiled code. This 1070 | * function can be used to lookup the original location. This is automatically 1071 | * done when accessing the `.stack` of an error, or when an uncaught error is 1072 | * logged. This function can be used to perform the lookup for creating better 1073 | * error handling. 1074 | * 1075 | * **Note:** `line` and `column` are 1 indexed, which matches display 1076 | * expectations, but is not typical of most index numbers in Deno. 1077 | * 1078 | * An example: 1079 | * 1080 | * const orig = Deno.applySourceMap({ 1081 | * location: "file://my/module.ts", 1082 | * line: 5, 1083 | * column: 15 1084 | * }); 1085 | * console.log(`${orig.filename}:${orig.line}:${orig.column}`); 1086 | * 1087 | */ 1088 | export function applySourceMap(location: Location): Location { 1089 | throw new Error("unsupported"); 1090 | } 1091 | 1092 | // @url js/errors.d.ts 1093 | export enum ErrorKind { 1094 | NoError = 0, 1095 | NotFound = 1, 1096 | PermissionDenied = 2, 1097 | ConnectionRefused = 3, 1098 | ConnectionReset = 4, 1099 | ConnectionAborted = 5, 1100 | NotConnected = 6, 1101 | AddrInUse = 7, 1102 | AddrNotAvailable = 8, 1103 | BrokenPipe = 9, 1104 | AlreadyExists = 10, 1105 | WouldBlock = 11, 1106 | InvalidInput = 12, 1107 | InvalidData = 13, 1108 | TimedOut = 14, 1109 | Interrupted = 15, 1110 | WriteZero = 16, 1111 | Other = 17, 1112 | UnexpectedEof = 18, 1113 | BadResource = 19, 1114 | CommandFailed = 20, 1115 | EmptyHost = 21, 1116 | IdnaError = 22, 1117 | InvalidPort = 23, 1118 | InvalidIpv4Address = 24, 1119 | InvalidIpv6Address = 25, 1120 | InvalidDomainCharacter = 26, 1121 | RelativeUrlWithoutBase = 27, 1122 | RelativeUrlWithCannotBeABaseBase = 28, 1123 | SetHostOnCannotBeABaseUrl = 29, 1124 | Overflow = 30, 1125 | HttpUser = 31, 1126 | HttpClosed = 32, 1127 | HttpCanceled = 33, 1128 | HttpParse = 34, 1129 | HttpOther = 35, 1130 | TooLarge = 36, 1131 | InvalidUri = 37, 1132 | InvalidSeekMode = 38, 1133 | OpNotAvailable = 39, 1134 | WorkerInitFailed = 40, 1135 | UnixError = 41, 1136 | NoAsyncSupport = 42, 1137 | NoSyncSupport = 43, 1138 | ImportMapError = 44, 1139 | InvalidPath = 45, 1140 | ImportPrefixMissing = 46, 1141 | UnsupportedFetchScheme = 47, 1142 | TooManyRedirects = 48, 1143 | Diagnostic = 49, 1144 | JSError = 50 1145 | } 1146 | 1147 | /** A Deno specific error. The `kind` property is set to a specific error code 1148 | * which can be used to in application logic. 1149 | * 1150 | * try { 1151 | * somethingThatMightThrow(); 1152 | * } catch (e) { 1153 | * if ( 1154 | * e instanceof Deno.DenoError && 1155 | * e.kind === Deno.ErrorKind.Overflow 1156 | * ) { 1157 | * console.error("Overflow error!"); 1158 | * } 1159 | * } 1160 | * 1161 | */ 1162 | export class DenoError extends Error { 1163 | readonly kind: T; 1164 | 1165 | constructor(kind: T, msg: string) { 1166 | super(msg); 1167 | this.kind = kind; 1168 | } 1169 | } 1170 | 1171 | interface RunPermissionDescriptor { 1172 | name: "run"; 1173 | } 1174 | 1175 | interface ReadWritePermissionDescriptor { 1176 | name: "read" | "write"; 1177 | path?: string; 1178 | } 1179 | 1180 | interface NetPermissionDescriptor { 1181 | name: "net"; 1182 | url?: string; 1183 | } 1184 | 1185 | interface EnvPermissionDescriptor { 1186 | name: "env"; 1187 | } 1188 | 1189 | interface HrtimePermissionDescriptor { 1190 | name: "hrtime"; 1191 | } 1192 | 1193 | /** Permissions as granted by the caller 1194 | * See: https://w3c.github.io/permissions/#permission-registry 1195 | */ 1196 | export type PermissionName = 1197 | | "run" 1198 | | "read" 1199 | | "write" 1200 | | "net" 1201 | | "env" 1202 | | "hrtime"; 1203 | /** https://w3c.github.io/permissions/#status-of-a-permission */ 1204 | export type PermissionState = "granted" | "denied" | "prompt"; 1205 | 1206 | /** See: https://w3c.github.io/permissions/#permission-descriptor */ 1207 | type PermissionDescriptor = 1208 | | RunPermissionDescriptor 1209 | | ReadWritePermissionDescriptor 1210 | | NetPermissionDescriptor 1211 | | EnvPermissionDescriptor 1212 | | HrtimePermissionDescriptor; 1213 | 1214 | export class Permissions { 1215 | /** Queries the permission. 1216 | * const status = await Deno.permissions.query({ name: "read", path: "/etc" }); 1217 | * if (status.state === "granted") { 1218 | * data = await Deno.readFile("/etc/passwd"); 1219 | * } 1220 | */ 1221 | async query(d: PermissionDescriptor): Promise { 1222 | return new PermissionStatus("granted"); 1223 | } 1224 | 1225 | /** Revokes the permission. 1226 | * const status = await Deno.permissions.revoke({ name: "run" }); 1227 | * assert(status.state !== "granted") 1228 | */ 1229 | async revoke(d: PermissionDescriptor): Promise { 1230 | return new PermissionStatus("granted"); 1231 | } 1232 | } 1233 | 1234 | export const permissions: Permissions = new Permissions(); 1235 | 1236 | /** https://w3c.github.io/permissions/#permissionstatus */ 1237 | export class PermissionStatus { 1238 | state: PermissionState; 1239 | 1240 | constructor(state: PermissionState) { 1241 | this.state = state; 1242 | } 1243 | } 1244 | 1245 | // @url js/truncate.d.ts 1246 | 1247 | /** Truncates or extends the specified file synchronously, updating the size of 1248 | * this file to become size. 1249 | * 1250 | * Deno.truncateSync("hello.txt", 10); 1251 | */ 1252 | export function truncateSync(name: string, len?: number): void { 1253 | fs.truncateSync(name, len); 1254 | } 1255 | 1256 | /** 1257 | * Truncates or extends the specified file, updating the size of this file to 1258 | * become size. 1259 | * 1260 | * await Deno.truncate("hello.txt", 10); 1261 | */ 1262 | export function truncate(name: string, len?: number): Promise { 1263 | return fs.promises.truncate(name, len); 1264 | } 1265 | 1266 | export interface Metrics { 1267 | opsDispatched: number; 1268 | opsCompleted: number; 1269 | bytesSentControl: number; 1270 | bytesSentData: number; 1271 | bytesReceived: number; 1272 | } 1273 | /** Receive metrics from the privileged side of Deno. 1274 | * 1275 | * > console.table(Deno.metrics()) 1276 | * ┌──────────────────┬────────┐ 1277 | * │ (index) │ Values │ 1278 | * ├──────────────────┼────────┤ 1279 | * │ opsDispatched │ 9 │ 1280 | * │ opsCompleted │ 9 │ 1281 | * │ bytesSentControl │ 504 │ 1282 | * │ bytesSentData │ 0 │ 1283 | * │ bytesReceived │ 856 │ 1284 | * └──────────────────┴────────┘ 1285 | */ 1286 | export function metrics(): Metrics { 1287 | return { 1288 | opsCompleted: 0, 1289 | opsDispatched: 0, 1290 | bytesReceived: 0, 1291 | bytesSentControl: 0, 1292 | bytesSentData: 0 1293 | }; 1294 | } 1295 | 1296 | // @url js/resources.d.ts 1297 | 1298 | export interface ResourceMap { 1299 | [rid: number]: string; 1300 | } 1301 | 1302 | /** Returns a map of open _file like_ resource ids along with their string 1303 | * representation. 1304 | */ 1305 | export function resources(): ResourceMap { 1306 | return ResourceTable.map(); 1307 | } 1308 | 1309 | type ProcessStdio = "inherit" | "piped" | "null"; 1310 | export interface RunOptions { 1311 | args: string[]; 1312 | cwd?: string; 1313 | env?: { 1314 | [key: string]: string; 1315 | }; 1316 | stdout?: ProcessStdio | number; 1317 | stderr?: ProcessStdio | number; 1318 | stdin?: ProcessStdio | number; 1319 | } 1320 | 1321 | /** Send a signal to process under given PID. Unix only at this moment. 1322 | * If pid is negative, the signal will be sent to the process group identified 1323 | * by -pid. 1324 | * Requires the `--allow-run` flag. 1325 | */ 1326 | export function kill(pid: number, signo: number): void { 1327 | process.kill(pid, signo); 1328 | } 1329 | 1330 | export interface DenoProcess { 1331 | readonly rid: number; 1332 | readonly pid: number; 1333 | readonly stdin?: WriteCloser; 1334 | readonly stdout?: ReadCloser; 1335 | readonly stderr?: ReadCloser; 1336 | status(): Promise; 1337 | 1338 | /** Buffer the stdout and return it as Uint8Array after EOF. 1339 | * You must set stdout to "piped" when creating the process. 1340 | * This calls close() on stdout after its done. 1341 | */ 1342 | output(): Promise; 1343 | 1344 | /** Buffer the stderr and return it as Uint8Array after EOF. 1345 | * You must set stderr to "piped" when creating the process. 1346 | * This calls close() on stderr after its done. 1347 | */ 1348 | stderrOutput(): Promise; 1349 | 1350 | close(): void; 1351 | 1352 | kill(signo: number): void; 1353 | } 1354 | 1355 | export { DenoProcessImpl as Process }; 1356 | 1357 | export interface ProcessStatus { 1358 | success: boolean; 1359 | code?: number; 1360 | signal?: number; 1361 | } 1362 | /** 1363 | * Spawns new subprocess. 1364 | * 1365 | * Subprocess uses same working directory as parent process unless `opt.cwd` 1366 | * is specified. 1367 | * 1368 | * Environmental variables for subprocess can be specified using `opt.env` 1369 | * mapping. 1370 | * 1371 | * By default subprocess inherits stdio of parent process. To change that 1372 | * `opt.stdout`, `opt.stderr` and `opt.stdin` can be specified independently - 1373 | * they can be set to either `ProcessStdio` or `rid` of open file. 1374 | */ 1375 | export function run(opt: RunOptions): DenoProcess { 1376 | const [cmd, ...args] = opt.args; 1377 | const p = cp.spawn(cmd, args, { 1378 | cwd: opt.cwd, 1379 | env: opt.env 1380 | }); 1381 | return ResourceTable.openProcess(p); 1382 | } 1383 | 1384 | enum LinuxSignal { 1385 | SIGHUP = 1, 1386 | SIGINT = 2, 1387 | SIGQUIT = 3, 1388 | SIGILL = 4, 1389 | SIGTRAP = 5, 1390 | SIGABRT = 6, 1391 | SIGBUS = 7, 1392 | SIGFPE = 8, 1393 | SIGKILL = 9, 1394 | SIGUSR1 = 10, 1395 | SIGSEGV = 11, 1396 | SIGUSR2 = 12, 1397 | SIGPIPE = 13, 1398 | SIGALRM = 14, 1399 | SIGTERM = 15, 1400 | SIGSTKFLT = 16, 1401 | SIGCHLD = 17, 1402 | SIGCONT = 18, 1403 | SIGSTOP = 19, 1404 | SIGTSTP = 20, 1405 | SIGTTIN = 21, 1406 | SIGTTOU = 22, 1407 | SIGURG = 23, 1408 | SIGXCPU = 24, 1409 | SIGXFSZ = 25, 1410 | SIGVTALRM = 26, 1411 | SIGPROF = 27, 1412 | SIGWINCH = 28, 1413 | SIGIO = 29, 1414 | SIGPWR = 30, 1415 | SIGSYS = 31 1416 | } 1417 | 1418 | enum MacOSSignal { 1419 | SIGHUP = 1, 1420 | SIGINT = 2, 1421 | SIGQUIT = 3, 1422 | SIGILL = 4, 1423 | SIGTRAP = 5, 1424 | SIGABRT = 6, 1425 | SIGEMT = 7, 1426 | SIGFPE = 8, 1427 | SIGKILL = 9, 1428 | SIGBUS = 10, 1429 | SIGSEGV = 11, 1430 | SIGSYS = 12, 1431 | SIGPIPE = 13, 1432 | SIGALRM = 14, 1433 | SIGTERM = 15, 1434 | SIGURG = 16, 1435 | SIGSTOP = 17, 1436 | SIGTSTP = 18, 1437 | SIGCONT = 19, 1438 | SIGCHLD = 20, 1439 | SIGTTIN = 21, 1440 | SIGTTOU = 22, 1441 | SIGIO = 23, 1442 | SIGXCPU = 24, 1443 | SIGXFSZ = 25, 1444 | SIGVTALRM = 26, 1445 | SIGPROF = 27, 1446 | SIGWINCH = 28, 1447 | SIGINFO = 29, 1448 | SIGUSR1 = 30, 1449 | SIGUSR2 = 31 1450 | } 1451 | 1452 | /** Signals numbers. This is platform dependent. 1453 | */ 1454 | export const Signal: typeof MacOSSignal | typeof LinuxSignal = 1455 | os.platform() === "darwin" ? MacOSSignal : LinuxSignal; 1456 | // export {}; 1457 | 1458 | // @url js/console.d.ts 1459 | 1460 | type ConsoleOptions = Partial<{ 1461 | showHidden: boolean; 1462 | depth: number; 1463 | colors: boolean; 1464 | indentLevel: number; 1465 | }>; 1466 | /** A symbol which can be used as a key for a custom method which will be called 1467 | * when `Deno.inspect()` is called, or when the object is logged to the console. 1468 | */ 1469 | export const customInspect: unique symbol = Symbol("customInspect"); 1470 | 1471 | /** 1472 | * `inspect()` converts input into string that has the same format 1473 | * as printed by `console.log(...)`; 1474 | */ 1475 | export function inspect(value: unknown, options?: ConsoleOptions): string { 1476 | return util.inspect(value, options); 1477 | } 1478 | // export type OperatingSystem = "mac" | "win" | "linux"; 1479 | //'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos', and 'win32'. 1480 | export type OperatingSystem = string; 1481 | // export type Arch = "x64" | "arm64"; 1482 | //'arm', 'arm64', 'ia32', 'mips', 'mipsel', 'ppc', 'ppc64', 's390', 's390x', 'x32', and 'x64'. 1483 | export type Arch = string; 1484 | /** Build related information */ 1485 | interface BuildInfo { 1486 | /** The CPU architecture. */ 1487 | arch: Arch; 1488 | /** The operating system. */ 1489 | os: OperatingSystem; 1490 | } 1491 | 1492 | export const build: BuildInfo = { 1493 | arch: os.arch(), 1494 | os: os.platform() 1495 | }; 1496 | 1497 | // @url js/version.d.ts 1498 | 1499 | interface Version { 1500 | deno: string; 1501 | v8: string; 1502 | typescript: string; 1503 | } 1504 | 1505 | export const version: Version = { 1506 | deno: "0.23.0", 1507 | v8: "7.9.317.12", 1508 | typescript: "3.6.3" 1509 | }; 1510 | 1511 | // @url js/deno.d.ts 1512 | 1513 | export const args: string[] = [...process.argv]; 1514 | 1515 | export * from "./buffer"; 1516 | export * from "./net"; 1517 | -------------------------------------------------------------------------------- /src/encoding.ts: -------------------------------------------------------------------------------- 1 | export class TextEncoder { 2 | encode(s: string): Uint8Array { 3 | return Buffer.from(s); 4 | } 5 | } 6 | export class TextDecoder { 7 | decode(u: Uint8Array): string { 8 | return Buffer.from(u).toString(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/file.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import { ResourceTable } from "./resources"; 3 | import { DenoFile, EOF, SeekMode } from "./deno"; 4 | 5 | export class DenoFileImpl implements DenoFile { 6 | private loc = 0; 7 | 8 | constructor(readonly rid: number, readonly handle: fs.promises.FileHandle) {} 9 | 10 | async write(p: Uint8Array): Promise { 11 | const result = await this.handle.write(p, 0, p.byteLength, this.loc); 12 | this.loc += result.bytesWritten; 13 | return result.bytesWritten; 14 | } 15 | 16 | writeSync(p: Uint8Array): number { 17 | const written = fs.writeSync(this.handle.fd, p); 18 | this.loc += written; 19 | return written; 20 | } 21 | 22 | async read(p: Uint8Array): Promise { 23 | const result = await this.handle.read(p, 0, p.byteLength, this.loc); 24 | this.loc += result.bytesRead; 25 | return result.bytesRead === 0 ? EOF : result.bytesRead; 26 | } 27 | 28 | readSync(p: Uint8Array): number | EOF { 29 | const result = fs.readSync(this.handle.fd, p, 0, p.byteLength, this.loc); 30 | this.loc += result; 31 | return result === 0 ? EOF : result; 32 | } 33 | 34 | async seek(offset: number, whence: SeekMode): Promise { 35 | if (whence === SeekMode.SEEK_START) { 36 | this.loc = offset; 37 | } else if (whence === SeekMode.SEEK_CURRENT) { 38 | this.loc += offset; 39 | } else if (whence === SeekMode.SEEK_END) { 40 | const stats = await this.handle.stat(); 41 | this.loc = stats.size - offset; 42 | } 43 | } 44 | 45 | seekSync(offset: number, whence: SeekMode): void { 46 | if (whence === SeekMode.SEEK_START) { 47 | this.loc = offset; 48 | } else if (whence === SeekMode.SEEK_CURRENT) { 49 | this.loc += offset; 50 | } else if (whence === SeekMode.SEEK_END) { 51 | const stats = fs.fstatSync(this.handle.fd); 52 | this.loc = stats.size - offset; 53 | } 54 | } 55 | 56 | close(): void { 57 | try { 58 | fs.closeSync(this.handle.fd); 59 | } finally { 60 | ResourceTable.delete(this.rid); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/net.ts: -------------------------------------------------------------------------------- 1 | import { Closer, Reader, Writer } from "./deno"; 2 | 3 | type Transport = "tcp"; 4 | interface Addr { 5 | transport: Transport; 6 | address: string; 7 | } 8 | 9 | /** A Listener is a generic network listener for stream-oriented protocols. */ 10 | export interface Listener extends AsyncIterator { 11 | /** Waits for and resolves to the next connection to the `Listener`. */ 12 | accept(): Promise; 13 | /** Close closes the listener. Any pending accept promises will be rejected 14 | * with errors. 15 | */ 16 | close(): void; 17 | /** Return the address of the `Listener`. */ 18 | addr(): Addr; 19 | [Symbol.asyncIterator](): AsyncIterator; 20 | } 21 | 22 | export interface Conn extends Reader, Writer, Closer { 23 | /** The local address of the connection. */ 24 | localAddr: string; 25 | /** The remote address of the connection. */ 26 | remoteAddr: string; 27 | /** The resource ID of the connection. */ 28 | rid: number; 29 | /** Shuts down (`shutdown(2)`) the reading side of the TCP connection. Most 30 | * callers should just use `close()`. 31 | */ 32 | closeRead(): void; 33 | /** Shuts down (`shutdown(2)`) the writing side of the TCP connection. Most 34 | * callers should just use `close()`. 35 | */ 36 | closeWrite(): void; 37 | } 38 | 39 | export interface ListenOptions { 40 | port: number; 41 | hostname?: string; 42 | transport?: Transport; 43 | } 44 | 45 | /** Listen announces on the local transport address. 46 | * 47 | * @param options 48 | * @param options.port The port to connect to. (Required.) 49 | * @param options.hostname A literal IP address or host name that can be 50 | * resolved to an IP address. If not specified, defaults to 0.0.0.0 51 | * @param options.transport Defaults to "tcp". Later we plan to add "tcp4", 52 | * "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6", "unix", "unixgram" and 53 | * "unixpacket". 54 | * 55 | * Examples: 56 | * 57 | * listen({ port: 80 }) 58 | * listen({ hostname: "192.0.2.1", port: 80 }) 59 | * listen({ hostname: "[2001:db8::1]", port: 80 }); 60 | * listen({ hostname: "golang.org", port: 80, transport: "tcp" }) 61 | */ 62 | export function listen(options: ListenOptions): Listener { 63 | // TODO 64 | throw new Error("unsupported"); 65 | } 66 | export interface ListenTLSOptions { 67 | port: number; 68 | hostname?: string; 69 | transport?: Transport; 70 | certFile: string; 71 | keyFile: string; 72 | } 73 | 74 | /** Listen announces on the local transport address over TLS (transport layer security). 75 | * 76 | * @param options 77 | * @param options.port The port to connect to. (Required.) 78 | * @param options.hostname A literal IP address or host name that can be 79 | * resolved to an IP address. If not specified, defaults to 0.0.0.0 80 | * @param options.certFile Server certificate file 81 | * @param options.keyFile Server public key file 82 | * 83 | * Examples: 84 | * 85 | * Deno.listenTLS({ port: 443, certFile: "./my_server.crt", keyFile: "./my_server.key" }) 86 | */ 87 | export function listenTLS(options: ListenTLSOptions): Listener { 88 | throw new Error("unsupported"); 89 | } 90 | 91 | export interface DialOptions { 92 | port: number; 93 | hostname?: string; 94 | transport?: Transport; 95 | } 96 | 97 | /** Dial connects to the address on the named transport. 98 | * 99 | * @param options 100 | * @param options.port The port to connect to. (Required.) 101 | * @param options.hostname A literal IP address or host name that can be 102 | * resolved to an IP address. If not specified, defaults to 127.0.0.1 103 | * @param options.transport Defaults to "tcp". Later we plan to add "tcp4", 104 | * "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6", "unix", "unixgram" and 105 | * "unixpacket". 106 | * 107 | * Examples: 108 | * 109 | * dial({ port: 80 }) 110 | * dial({ hostname: "192.0.2.1", port: 80 }) 111 | * dial({ hostname: "[2001:db8::1]", port: 80 }); 112 | * dial({ hostname: "golang.org", port: 80, transport: "tcp" }) 113 | */ 114 | export function dial(options: DialOptions): Promise { 115 | throw new Error("unsupported"); 116 | } 117 | 118 | export interface DialTLSOptions { 119 | port: number; 120 | hostname?: string; 121 | certFile?: string; 122 | } 123 | 124 | /** 125 | * dialTLS establishes a secure connection over TLS (transport layer security). 126 | */ 127 | export function dialTLS(options: DialTLSOptions): Promise { 128 | throw new Error("unsupported"); 129 | } 130 | -------------------------------------------------------------------------------- /src/polyfill.ts: -------------------------------------------------------------------------------- 1 | import { TextEncoder, TextDecoder } from "./encoding"; 2 | const _Deno = require("./deno"); 3 | const { Base64 } = require("js-base64"); 4 | const _fetch = require("node-fetch"); 5 | const _url = require("url"); 6 | global["fetch"] = _fetch; 7 | global["Headers"] = _fetch.Headers; 8 | global["Request"] = _fetch.Request; 9 | global["Response"] = _fetch.Response; 10 | global["URL"] = _url.URL; 11 | global["URLSearchParams"] = _url.URLSearchParams; 12 | global["atob"] = Base64.atob; 13 | global["btoa"] = Base64.btoa; 14 | global["Deno"] = _Deno; 15 | global["StringDecoder"] = TextDecoder; 16 | global["StringEncoder"] = TextEncoder; 17 | -------------------------------------------------------------------------------- /src/process.ts: -------------------------------------------------------------------------------- 1 | import { deferred, streamToReader, streamToWriter } from "./util"; 2 | import * as cp from "child_process"; 3 | import { readAll } from "./buffer"; 4 | import { 5 | DenoProcess, 6 | ProcessStatus, 7 | ReadCloser, 8 | Signal, 9 | WriteCloser 10 | } from "./deno"; 11 | import { ResourceTable } from "./resources"; 12 | 13 | export class DenoProcessImpl implements DenoProcess { 14 | readonly rid: number; 15 | readonly pid: number; 16 | readonly stdin?: WriteCloser; 17 | readonly stdout?: ReadCloser; 18 | readonly stderr?: ReadCloser; 19 | statusDeferred = deferred(); 20 | 21 | constructor(rid: number, readonly proc: cp.ChildProcess) { 22 | this.rid = rid; 23 | this.pid = proc.pid; 24 | if (proc.stdin) { 25 | const w = streamToWriter(proc.stdin); 26 | this.stdin = { 27 | ...w, 28 | close(): void {} 29 | }; 30 | } 31 | if (proc.stdout) { 32 | const r = streamToReader(proc.stdout); 33 | this.stdout = { 34 | ...r, 35 | close(): void {} 36 | }; 37 | } 38 | if (proc.stderr) { 39 | const r = streamToReader(proc.stderr); 40 | this.stderr = { 41 | ...r, 42 | close(): void {} 43 | }; 44 | } 45 | proc.on("exit", (code, sig) => { 46 | const status: ProcessStatus = { success: false }; 47 | if (code === 0) { 48 | status.success = true; 49 | } 50 | if (code != null) { 51 | status.code = code; 52 | } 53 | if (sig != null) { 54 | status.signal = Signal[sig]; 55 | } 56 | this.statusDeferred.resolve(status); 57 | }); 58 | proc.on("error", err => this.statusDeferred.reject(err)); 59 | } 60 | 61 | status(): Promise { 62 | return this.statusDeferred; 63 | } 64 | 65 | /** Buffer the stdout and return it as Uint8Array after EOF. 66 | * You must set stdout to "piped" when creating the process. 67 | * This calls close() on stdout after its done. 68 | */ 69 | output(): Promise { 70 | return readAll(this.stdout); 71 | } 72 | 73 | /** Buffer the stderr and return it as Uint8Array after EOF. 74 | * You must set stderr to "piped" when creating the process. 75 | * This calls close() on stderr after its done. 76 | */ 77 | stderrOutput(): Promise { 78 | return readAll(this.stderr); 79 | } 80 | 81 | close(): void { 82 | try { 83 | const st = this.statusDeferred.status(); 84 | if (!st) { 85 | process.kill(this.pid); 86 | } 87 | } finally { 88 | ResourceTable.delete(this.rid); 89 | } 90 | } 91 | 92 | kill(signo: number): void { 93 | try { 94 | process.kill(this.pid, signo); 95 | } finally { 96 | ResourceTable.delete(this.rid); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/resources.ts: -------------------------------------------------------------------------------- 1 | import { Conn } from "./net"; 2 | import { DenoFile, DenoProcess, ResourceMap } from "./deno"; 3 | import * as fs from "fs"; 4 | import * as cp from "child_process"; 5 | import { DenoProcessImpl } from "./process"; 6 | import { DenoFileImpl } from "./file"; 7 | export interface ResourceTable { 8 | openFile(file: fs.promises.FileHandle): DenoFile; 9 | openProcess(proc: cp.ChildProcess): DenoProcess; 10 | getFile(rid: number): DenoFile; 11 | getProcess(rid: number): DenoProcess; 12 | map(): ResourceMap; 13 | close(rid: number): void; 14 | delete(rid: number): void; 15 | } 16 | function resourceTable(): ResourceTable { 17 | const files: Map = new Map(); 18 | const processes: Map = new Map(); 19 | const conns: Map = new Map(); 20 | let resourceId = 3; 21 | function openFile(file: fs.promises.FileHandle): DenoFile { 22 | const rid = resourceId++; 23 | const ret = new DenoFileImpl(rid, file); 24 | files.set(rid, ret); 25 | return ret; 26 | } 27 | function openProcess(proc: cp.ChildProcess): DenoProcess { 28 | const rid = resourceId++; 29 | const ret = new DenoProcessImpl(rid, proc); 30 | processes.set(rid, ret); 31 | return ret; 32 | } 33 | function close(rid: number) { 34 | if (files.has(rid)) { 35 | const file = files.get(rid); 36 | file.close(); 37 | } else if (processes.has(rid)) { 38 | const proc = processes.get(rid); 39 | proc.close(); 40 | } else if (conns.has(rid)) { 41 | const conn = conns.get(rid); 42 | conn.close(); 43 | } 44 | } 45 | function del(rid: number) { 46 | if (files.has(rid)) { 47 | files.delete(rid); 48 | } else if (processes.has(rid)) { 49 | processes.delete(rid); 50 | } else if (conns.has(rid)) { 51 | processes.delete(rid); 52 | } 53 | } 54 | function getFile(rid: number): DenoFile { 55 | const file = files.get(rid); 56 | if (!file) { 57 | throw new Error("file not found: rid=" + rid); 58 | } 59 | return file; 60 | } 61 | function getProcess(rid: number): DenoProcess { 62 | const proc = processes.get(rid); 63 | if (!proc) { 64 | throw new Error("process not found: rid=" + rid); 65 | } 66 | return; 67 | } 68 | function map(): ResourceMap { 69 | return Object.fromEntries([ 70 | ...[...files.entries()].map(e => [e[0], "file"]), 71 | ...[...processes.entries()].map(e => [e[0], "process"]), 72 | ...[...conns.entries()].map(e => [e[0], "conn"]) 73 | ]); 74 | } 75 | return { 76 | getFile, 77 | getProcess, 78 | openFile, 79 | openProcess, 80 | close, 81 | delete: del, 82 | map 83 | }; 84 | } 85 | 86 | export const ResourceTable = resourceTable(); 87 | -------------------------------------------------------------------------------- /src/util.ts: -------------------------------------------------------------------------------- 1 | import { EOF, Reader, Writer } from "./deno"; 2 | import { TextDecoder, TextEncoder } from "./encoding"; 3 | 4 | interface Deferred extends Promise { 5 | status(): "resolved" | "rejected" | undefined; 6 | resolve(t: T); 7 | reject(e); 8 | } 9 | export function deferred(): Deferred { 10 | let resolve, reject; 11 | let st: "resolved" | "rejected" | undefined; 12 | const p = new Promise((a, b) => { 13 | resolve = (...args) => { 14 | try { 15 | a(...args); 16 | } finally { 17 | st = "resolved"; 18 | } 19 | }; 20 | reject = (...args) => { 21 | try { 22 | b(...args); 23 | } finally { 24 | st = "rejected"; 25 | } 26 | }; 27 | }); 28 | return Object.assign(p, { 29 | resolve, 30 | reject, 31 | status() { 32 | return st; 33 | } 34 | }); 35 | } 36 | 37 | export function concatBytes(...chunks: Uint8Array[]): Uint8Array { 38 | const total = chunks.reduce((sum, i) => sum + i.byteLength, 0); 39 | const ret = new Uint8Array(total); 40 | let done = 0; 41 | for (const chunk of chunks) { 42 | ret.set(chunk, done); 43 | done += chunk.byteLength; 44 | } 45 | return ret; 46 | } 47 | 48 | export function streamToReader(stream: NodeJS.ReadableStream): Reader { 49 | let ended = false; 50 | let err: any | undefined; 51 | let buf: Uint8Array = new Uint8Array(); 52 | let currDeferred = deferred(); 53 | stream 54 | .on("data", chunk => { 55 | buf = concatBytes(buf, chunk); 56 | currDeferred.resolve(); 57 | currDeferred = deferred(); 58 | }) 59 | .on("end", () => { 60 | ended = true; 61 | }) 62 | .on("error", e => { 63 | err = e; 64 | }); 65 | async function read(p: Uint8Array): Promise { 66 | if (ended) { 67 | return EOF; 68 | } else if (err) { 69 | throw err; 70 | } 71 | const rem = Math.min(p.byteLength, buf.byteLength); 72 | if (rem > 0) { 73 | p.set(buf.subarray(0, rem)); 74 | buf = buf.subarray(rem); 75 | return rem; 76 | } else { 77 | await currDeferred; 78 | return read(p); 79 | } 80 | } 81 | return { read }; 82 | } 83 | 84 | export function streamToWriter(stream: NodeJS.WritableStream): Writer { 85 | async function write(p: Uint8Array): Promise { 86 | return new Promise((resolve, reject) => { 87 | stream.write(p, err => { 88 | err ? reject(err) : resolve(p.byteLength); 89 | }); 90 | }); 91 | } 92 | return { write }; 93 | } 94 | 95 | const encoder = new TextEncoder(); 96 | export function encode(s: string): Uint8Array { 97 | return encoder.encode(s); 98 | } 99 | const decoder = new TextDecoder(); 100 | export function decode(p: Uint8Array): string { 101 | return decoder.decode(p); 102 | } 103 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "module": "commonjs", 5 | "lib": ["esnext"], 6 | "baseUrl": ".", 7 | "outDir": "dist", 8 | "paths": { 9 | } 10 | }, 11 | "include": [ 12 | "src/**/*.ts" 13 | ] 14 | } --------------------------------------------------------------------------------