├── .gitignore
├── LICENSE
├── README.md
├── crypt.ts
├── deno.d.ts
├── errors.ts
├── example
└── main.ts
├── ioutil.ts
├── tsconfig.json
├── ws.ts
└── ws_test.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 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 | deno-ws
2 | ===
3 | An experimental websocket implementation for deno.ts
4 |
5 | NOTE: 2019/01/08
6 |
7 | 🎉deno-ws has been merged into https://github.com/denoland/deno_std
8 | Please use https://deno.land/x/net/ws.ts instead of this repository. This repository will be archived soon.
9 |
10 | ## Author
11 |
12 | [keroxp](https://github.com/keroxp)
13 |
14 | ## License
15 |
16 | MIT
17 |
--------------------------------------------------------------------------------
/crypt.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * [js-sha1]{@link https://github.com/emn178/js-sha1}
3 | *
4 | * @version 0.6.0
5 | * @author Chen, Yi-Cyuan [emn178@gmail.com]
6 | * @copyright Chen, Yi-Cyuan 2014-2017
7 | * @license MIT
8 | */
9 | /*jslint bitwise: true */
10 |
11 | const HEX_CHARS = '0123456789abcdef'.split('');
12 | const EXTRA = [-2147483648, 8388608, 32768, 128];
13 | const SHIFT = [24, 16, 8, 0];
14 |
15 | const blocks = [];
16 |
17 | export class Sha1 {
18 | blocks;
19 | block;
20 | start;
21 | bytes;
22 | hBytes;
23 | finalized;
24 | hashed;
25 | first;
26 |
27 | h0 = 0x67452301;
28 | h1 = 0xEFCDAB89;
29 | h2 = 0x98BADCFE;
30 | h3 = 0x10325476;
31 | h4 = 0xC3D2E1F0;
32 | lastByteIndex = 0;
33 |
34 | constructor(sharedMemory: boolean = false) {
35 | if (sharedMemory) {
36 | blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =
37 | blocks[4] = blocks[5] = blocks[6] = blocks[7] =
38 | blocks[8] = blocks[9] = blocks[10] = blocks[11] =
39 | blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
40 | this.blocks = blocks;
41 | } else {
42 | this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
43 | }
44 |
45 | this.h0 = 0x67452301;
46 | this.h1 = 0xEFCDAB89;
47 | this.h2 = 0x98BADCFE;
48 | this.h3 = 0x10325476;
49 | this.h4 = 0xC3D2E1F0;
50 |
51 | this.block = this.start = this.bytes = this.hBytes = 0;
52 | this.finalized = this.hashed = false;
53 | this.first = true;
54 | }
55 |
56 | update(data: string | ArrayBuffer) {
57 | if (this.finalized) {
58 | return;
59 | }
60 | let message;
61 | let notString = typeof(data) !== 'string';
62 | if (notString && data instanceof ArrayBuffer) {
63 | message = new Uint8Array(data);
64 | } else {
65 | message = data;
66 | }
67 | let code, index = 0, i, length = message.length || 0, blocks = this.blocks;
68 |
69 | while (index < length) {
70 | if (this.hashed) {
71 | this.hashed = false;
72 | blocks[0] = this.block;
73 | blocks[16] = blocks[1] = blocks[2] = blocks[3] =
74 | blocks[4] = blocks[5] = blocks[6] = blocks[7] =
75 | blocks[8] = blocks[9] = blocks[10] = blocks[11] =
76 | blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
77 | }
78 |
79 | if (notString) {
80 | for (i = this.start; index < length && i < 64; ++index) {
81 | blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
82 | }
83 | } else {
84 | for (i = this.start; index < length && i < 64; ++index) {
85 | code = message.charCodeAt(index);
86 | if (code < 0x80) {
87 | blocks[i >> 2] |= code << SHIFT[i++ & 3];
88 | } else if (code < 0x800) {
89 | blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
90 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
91 | } else if (code < 0xd800 || code >= 0xe000) {
92 | blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
93 | blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
94 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
95 | } else {
96 | code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
97 | blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
98 | blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
99 | blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
100 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
101 | }
102 | }
103 | }
104 |
105 | this.lastByteIndex = i;
106 | this.bytes += i - this.start;
107 | if (i >= 64) {
108 | this.block = blocks[16];
109 | this.start = i - 64;
110 | this.hash();
111 | this.hashed = true;
112 | } else {
113 | this.start = i;
114 | }
115 | }
116 | if (this.bytes > 4294967295) {
117 | this.hBytes += this.bytes / 4294967296 << 0;
118 | this.bytes = this.bytes % 4294967296;
119 | }
120 | return this;
121 | };
122 |
123 | finalize() {
124 | if (this.finalized) {
125 | return;
126 | }
127 | this.finalized = true;
128 | let blocks = this.blocks, i = this.lastByteIndex;
129 | blocks[16] = this.block;
130 | blocks[i >> 2] |= EXTRA[i & 3];
131 | this.block = blocks[16];
132 | if (i >= 56) {
133 | if (!this.hashed) {
134 | this.hash();
135 | }
136 | blocks[0] = this.block;
137 | blocks[16] = blocks[1] = blocks[2] = blocks[3] =
138 | blocks[4] = blocks[5] = blocks[6] = blocks[7] =
139 | blocks[8] = blocks[9] = blocks[10] = blocks[11] =
140 | blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
141 | }
142 | blocks[14] = this.hBytes << 3 | this.bytes >>> 29;
143 | blocks[15] = this.bytes << 3;
144 | this.hash();
145 | };
146 |
147 | hash() {
148 | let a = this.h0, b = this.h1, c = this.h2, d = this.h3, e = this.h4;
149 | let f, j, t, blocks = this.blocks;
150 |
151 | for (j = 16; j < 80; ++j) {
152 | t = blocks[j - 3] ^ blocks[j - 8] ^ blocks[j - 14] ^ blocks[j - 16];
153 | blocks[j] = (t << 1) | (t >>> 31);
154 | }
155 |
156 | for (j = 0; j < 20; j += 5) {
157 | f = (b & c) | ((~b) & d);
158 | t = (a << 5) | (a >>> 27);
159 | e = t + f + e + 1518500249 + blocks[j] << 0;
160 | b = (b << 30) | (b >>> 2);
161 |
162 | f = (a & b) | ((~a) & c);
163 | t = (e << 5) | (e >>> 27);
164 | d = t + f + d + 1518500249 + blocks[j + 1] << 0;
165 | a = (a << 30) | (a >>> 2);
166 |
167 | f = (e & a) | ((~e) & b);
168 | t = (d << 5) | (d >>> 27);
169 | c = t + f + c + 1518500249 + blocks[j + 2] << 0;
170 | e = (e << 30) | (e >>> 2);
171 |
172 | f = (d & e) | ((~d) & a);
173 | t = (c << 5) | (c >>> 27);
174 | b = t + f + b + 1518500249 + blocks[j + 3] << 0;
175 | d = (d << 30) | (d >>> 2);
176 |
177 | f = (c & d) | ((~c) & e);
178 | t = (b << 5) | (b >>> 27);
179 | a = t + f + a + 1518500249 + blocks[j + 4] << 0;
180 | c = (c << 30) | (c >>> 2);
181 | }
182 |
183 | for (; j < 40; j += 5) {
184 | f = b ^ c ^ d;
185 | t = (a << 5) | (a >>> 27);
186 | e = t + f + e + 1859775393 + blocks[j] << 0;
187 | b = (b << 30) | (b >>> 2);
188 |
189 | f = a ^ b ^ c;
190 | t = (e << 5) | (e >>> 27);
191 | d = t + f + d + 1859775393 + blocks[j + 1] << 0;
192 | a = (a << 30) | (a >>> 2);
193 |
194 | f = e ^ a ^ b;
195 | t = (d << 5) | (d >>> 27);
196 | c = t + f + c + 1859775393 + blocks[j + 2] << 0;
197 | e = (e << 30) | (e >>> 2);
198 |
199 | f = d ^ e ^ a;
200 | t = (c << 5) | (c >>> 27);
201 | b = t + f + b + 1859775393 + blocks[j + 3] << 0;
202 | d = (d << 30) | (d >>> 2);
203 |
204 | f = c ^ d ^ e;
205 | t = (b << 5) | (b >>> 27);
206 | a = t + f + a + 1859775393 + blocks[j + 4] << 0;
207 | c = (c << 30) | (c >>> 2);
208 | }
209 |
210 | for (; j < 60; j += 5) {
211 | f = (b & c) | (b & d) | (c & d);
212 | t = (a << 5) | (a >>> 27);
213 | e = t + f + e - 1894007588 + blocks[j] << 0;
214 | b = (b << 30) | (b >>> 2);
215 |
216 | f = (a & b) | (a & c) | (b & c);
217 | t = (e << 5) | (e >>> 27);
218 | d = t + f + d - 1894007588 + blocks[j + 1] << 0;
219 | a = (a << 30) | (a >>> 2);
220 |
221 | f = (e & a) | (e & b) | (a & b);
222 | t = (d << 5) | (d >>> 27);
223 | c = t + f + c - 1894007588 + blocks[j + 2] << 0;
224 | e = (e << 30) | (e >>> 2);
225 |
226 | f = (d & e) | (d & a) | (e & a);
227 | t = (c << 5) | (c >>> 27);
228 | b = t + f + b - 1894007588 + blocks[j + 3] << 0;
229 | d = (d << 30) | (d >>> 2);
230 |
231 | f = (c & d) | (c & e) | (d & e);
232 | t = (b << 5) | (b >>> 27);
233 | a = t + f + a - 1894007588 + blocks[j + 4] << 0;
234 | c = (c << 30) | (c >>> 2);
235 | }
236 |
237 | for (; j < 80; j += 5) {
238 | f = b ^ c ^ d;
239 | t = (a << 5) | (a >>> 27);
240 | e = t + f + e - 899497514 + blocks[j] << 0;
241 | b = (b << 30) | (b >>> 2);
242 |
243 | f = a ^ b ^ c;
244 | t = (e << 5) | (e >>> 27);
245 | d = t + f + d - 899497514 + blocks[j + 1] << 0;
246 | a = (a << 30) | (a >>> 2);
247 |
248 | f = e ^ a ^ b;
249 | t = (d << 5) | (d >>> 27);
250 | c = t + f + c - 899497514 + blocks[j + 2] << 0;
251 | e = (e << 30) | (e >>> 2);
252 |
253 | f = d ^ e ^ a;
254 | t = (c << 5) | (c >>> 27);
255 | b = t + f + b - 899497514 + blocks[j + 3] << 0;
256 | d = (d << 30) | (d >>> 2);
257 |
258 | f = c ^ d ^ e;
259 | t = (b << 5) | (b >>> 27);
260 | a = t + f + a - 899497514 + blocks[j + 4] << 0;
261 | c = (c << 30) | (c >>> 2);
262 | }
263 |
264 | this.h0 = this.h0 + a << 0;
265 | this.h1 = this.h1 + b << 0;
266 | this.h2 = this.h2 + c << 0;
267 | this.h3 = this.h3 + d << 0;
268 | this.h4 = this.h4 + e << 0;
269 | };
270 |
271 | hex() {
272 | this.finalize();
273 |
274 | let h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4;
275 |
276 | return HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +
277 | HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +
278 | HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +
279 | HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +
280 | HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +
281 | HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +
282 | HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +
283 | HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +
284 | HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +
285 | HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +
286 | HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +
287 | HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +
288 | HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F] +
289 | HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +
290 | HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +
291 | HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +
292 | HEX_CHARS[(h4 >> 28) & 0x0F] + HEX_CHARS[(h4 >> 24) & 0x0F] +
293 | HEX_CHARS[(h4 >> 20) & 0x0F] + HEX_CHARS[(h4 >> 16) & 0x0F] +
294 | HEX_CHARS[(h4 >> 12) & 0x0F] + HEX_CHARS[(h4 >> 8) & 0x0F] +
295 | HEX_CHARS[(h4 >> 4) & 0x0F] + HEX_CHARS[h4 & 0x0F];
296 | };
297 |
298 | toString() {
299 | return this.hex();
300 | };
301 |
302 | digest() {
303 | this.finalize();
304 |
305 | let h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4;
306 |
307 | return [
308 | (h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, h0 & 0xFF,
309 | (h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, h1 & 0xFF,
310 | (h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, h2 & 0xFF,
311 | (h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, h3 & 0xFF,
312 | (h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, h4 & 0xFF
313 | ];
314 | };
315 |
316 | array() {
317 | return this.digest();
318 | };
319 |
320 | arrayBuffer() {
321 | this.finalize();
322 |
323 | let buffer = new ArrayBuffer(20);
324 | let dataView = new DataView(buffer);
325 | dataView.setUint32(0, this.h0);
326 | dataView.setUint32(4, this.h1);
327 | dataView.setUint32(8, this.h2);
328 | dataView.setUint32(12, this.h3);
329 | dataView.setUint32(16, this.h4);
330 | return buffer;
331 | }
332 | }
333 |
--------------------------------------------------------------------------------
/deno.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2018 the Deno authors. All rights reserved. MIT license.
2 |
3 | ///
4 | ///
5 |
6 | declare module "deno" {
7 | /** Exit the Deno process with optional exit code. */
8 | export function exit(exitCode?: number): never;
9 | /** Returns a snapshot of the environment variables at invocation. Mutating a
10 | * property in the object will set that variable in the environment for
11 | * the process. The environment object will only accept `string`s or `number`s
12 | * as values.
13 | *
14 | * import { env } from "deno";
15 | *
16 | * const myEnv = env();
17 | * console.log(myEnv.SHELL);
18 | * myEnv.TEST_VAR = "HELLO";
19 | * const newEnv = env();
20 | * console.log(myEnv.TEST_VAR == newEnv.TEST_VAR);
21 | */
22 | export function env(): {
23 | [index: string]: string;
24 | };
25 | /**
26 | * cwd() Return a string representing the current working directory.
27 | * If the current directory can be reached via multiple paths
28 | * (due to symbolic links), cwd() may return
29 | * any one of them.
30 | * throws NotFound exception if directory not available
31 | */
32 | export function cwd(): string;
33 | /**
34 | * chdir() Change the current working directory to path.
35 | * throws NotFound exception if directory not available
36 | */
37 | export function chdir(directory: string): void;
38 | export interface ReadResult {
39 | nread: number;
40 | eof: boolean;
41 | }
42 | export interface Reader {
43 | /** Reads up to p.byteLength bytes into `p`. It resolves to the number
44 | * of bytes read (`0` <= `n` <= `p.byteLength`) and any error encountered.
45 | * Even if `read()` returns `n` < `p.byteLength`, it may use all of `p` as
46 | * scratch space during the call. If some data is available but not
47 | * `p.byteLength` bytes, `read()` conventionally returns what is available
48 | * instead of waiting for more.
49 | *
50 | * When `read()` encounters an error or end-of-file condition after
51 | * successfully reading `n` > `0` bytes, it returns the number of bytes read.
52 | * It may return the (non-nil) error from the same call or return the error
53 | * (and `n` == `0`) from a subsequent call. An instance of this general case
54 | * is that a `Reader` returning a non-zero number of bytes at the end of the
55 | * input stream may return either `err` == `EOF` or `err` == `null`. The next
56 | * `read()` should return `0`, `EOF`.
57 | *
58 | * Callers should always process the `n` > `0` bytes returned before
59 | * considering the `EOF`. Doing so correctly handles I/O errors that happen
60 | * after reading some bytes and also both of the allowed `EOF` behaviors.
61 | *
62 | * Implementations of `read()` are discouraged from returning a zero byte
63 | * count with a `null` error, except when `p.byteLength` == `0`. Callers
64 | * should treat a return of `0` and `null` as indicating that nothing
65 | * happened; in particular it does not indicate `EOF`.
66 | *
67 | * Implementations must not retain `p`.
68 | */
69 | read(p: Uint8Array): Promise;
70 | }
71 | export interface Writer {
72 | /** Writes `p.byteLength` bytes from `p` to the underlying data
73 | * stream. It resolves to the number of bytes written from `p` (`0` <= `n` <=
74 | * `p.byteLength`) and any error encountered that caused the write to stop
75 | * early. `write()` must return a non-null error if it returns `n` <
76 | * `p.byteLength`. write() must not modify the slice data, even temporarily.
77 | *
78 | * Implementations must not retain `p`.
79 | */
80 | write(p: Uint8Array): Promise;
81 | }
82 | export interface Closer {
83 | close(): void;
84 | }
85 | export interface Seeker {
86 | /** Seek sets the offset for the next `read()` or `write()` to offset,
87 | * interpreted according to `whence`: `SeekStart` means relative to the start
88 | * of the file, `SeekCurrent` means relative to the current offset, and
89 | * `SeekEnd` means relative to the end. Seek returns the new offset relative
90 | * to the start of the file and an error, if any.
91 | *
92 | * Seeking to an offset before the start of the file is an error. Seeking to
93 | * any positive offset is legal, but the behavior of subsequent I/O operations
94 | * on the underlying object is implementation-dependent.
95 | */
96 | seek(offset: number, whence: number): Promise;
97 | }
98 | export interface ReadCloser extends Reader, Closer {}
99 | export interface WriteCloser extends Writer, Closer {}
100 | export interface ReadSeeker extends Reader, Seeker {}
101 | export interface WriteSeeker extends Writer, Seeker {}
102 | export interface ReadWriteCloser extends Reader, Writer, Closer {}
103 | export interface ReadWriteSeeker extends Reader, Writer, Seeker {}
104 | /** Copies from `src` to `dst` until either `EOF` is reached on `src`
105 | * or an error occurs. It returns the number of bytes copied and the first
106 | * error encountered while copying, if any.
107 | *
108 | * Because `copy()` is defined to read from `src` until `EOF`, it does not
109 | * treat an `EOF` from `read()` as an error to be reported.
110 | */
111 | export function copy(dst: Writer, src: Reader): Promise;
112 | /** Turns `r` into async iterator.
113 | *
114 | * for await (const chunk of readerIterator(reader)) {
115 | * console.log(chunk)
116 | * }
117 | */
118 | export function toAsyncIterator(r: Reader): AsyncIterableIterator;
119 | /** The Deno abstraction for reading and writing files. */
120 | export class File implements Reader, Writer, Closer {
121 | readonly rid: number;
122 | constructor(rid: number);
123 | write(p: Uint8Array): Promise;
124 | read(p: Uint8Array): Promise;
125 | close(): void;
126 | }
127 | /** An instance of `File` for stdin. */
128 | export const stdin: File;
129 | /** An instance of `File` for stdout. */
130 | export const stdout: File;
131 | /** An instance of `File` for stderr. */
132 | export const stderr: File;
133 | export type OpenMode =
134 | | "r"
135 | /** Read-write. Start at beginning of file. */
136 | | "r+"
137 | /** Write-only. Opens and truncates existing file or creates new one for
138 | * writing only.
139 | */
140 | | "w"
141 | /** Read-write. Opens and truncates existing file or creates new one for
142 | * writing and reading.
143 | */
144 | | "w+"
145 | /** Write-only. Opens existing file or creates new one. Each write appends
146 | * content to the end of file.
147 | */
148 | | "a"
149 | /** Read-write. Behaves like "a" and allows to read from file. */
150 | | "a+"
151 | /** Write-only. Exclusive create - creates new file only if one doesn't exist
152 | * already.
153 | */
154 | | "x"
155 | /** Read-write. Behaves like `x` and allows to read from file. */
156 | | "x+";
157 | /** A factory function for creating instances of `File` associated with the
158 | * supplied file name.
159 | */
160 | function create(filename: string): Promise;
161 | /** Open a file and return an instance of the `File` object.
162 | *
163 | * import * as deno from "deno";
164 | * (async () => {
165 | * const file = await deno.open("/foo/bar.txt");
166 | * })();
167 | */
168 | export function open(filename: string, mode?: OpenMode): Promise;
169 | /** Read from a file ID into an array buffer.
170 | *
171 | * Resolves with the `ReadResult` for the operation.
172 | */
173 | export function read(rid: number, p: Uint8Array): Promise;
174 | /** Write to the file ID the contents of the array buffer.
175 | *
176 | * Resolves with the number of bytes written.
177 | */
178 | export function write(rid: number, p: Uint8Array): Promise;
179 | /** Close the file ID. */
180 | export function close(rid: number): void;
181 | /** A Buffer is a variable-sized buffer of bytes with read() and write()
182 | * methods. Based on https://golang.org/pkg/bytes/#Buffer
183 | */
184 | export class Buffer implements Reader, Writer {
185 | private buf;
186 | private off;
187 | constructor(ab?: ArrayBuffer);
188 | /** bytes() returns a slice holding the unread portion of the buffer.
189 | * The slice is valid for use only until the next buffer modification (that
190 | * is, only until the next call to a method like read(), write(), reset(), or
191 | * truncate()). The slice aliases the buffer content at least until the next
192 | * buffer modification, so immediate changes to the slice will affect the
193 | * result of future reads.
194 | */
195 | bytes(): Uint8Array;
196 | /** toString() returns the contents of the unread portion of the buffer
197 | * as a string. Warning - if multibyte characters are present when data is
198 | * flowing through the buffer, this method may result in incorrect strings
199 | * due to a character being split.
200 | */
201 | toString(): string;
202 | /** empty() returns whether the unread portion of the buffer is empty. */
203 | empty(): boolean;
204 | /** length is a getter that returns the number of bytes of the unread
205 | * portion of the buffer
206 | */
207 | readonly length: number;
208 | /** Returns the capacity of the buffer's underlying byte slice, that is,
209 | * the total space allocated for the buffer's data.
210 | */
211 | readonly capacity: number;
212 | /** truncate() discards all but the first n unread bytes from the buffer but
213 | * continues to use the same allocated storage. It throws if n is negative or
214 | * greater than the length of the buffer.
215 | */
216 | truncate(n: number): void;
217 | /** reset() resets the buffer to be empty, but it retains the underlying
218 | * storage for use by future writes. reset() is the same as truncate(0)
219 | */
220 | reset(): void;
221 | /** _tryGrowByReslice() is a version of grow for the fast-case
222 | * where the internal buffer only needs to be resliced. It returns the index
223 | * where bytes should be written and whether it succeeded.
224 | * It returns -1 if a reslice was not needed.
225 | */
226 | private _tryGrowByReslice;
227 | private _reslice;
228 | /** read() reads the next len(p) bytes from the buffer or until the buffer
229 | * is drained. The return value n is the number of bytes read. If the
230 | * buffer has no data to return, eof in the response will be true.
231 | */
232 | read(p: Uint8Array): Promise;
233 | write(p: Uint8Array): Promise;
234 | /** _grow() grows the buffer to guarantee space for n more bytes.
235 | * It returns the index where bytes should be written.
236 | * If the buffer can't grow it will throw with ErrTooLarge.
237 | */
238 | private _grow;
239 | /** grow() grows the buffer's capacity, if necessary, to guarantee space for
240 | * another n bytes. After grow(n), at least n bytes can be written to the
241 | * buffer without another allocation. If n is negative, grow() will panic. If
242 | * the buffer can't grow it will throw ErrTooLarge.
243 | * Based on https://golang.org/pkg/bytes/#Buffer.Grow
244 | */
245 | grow(n: number): void;
246 | /** readFrom() reads data from r until EOF and appends it to the buffer,
247 | * growing the buffer as needed. It returns the number of bytes read. If the
248 | * buffer becomes too large, readFrom will panic with ErrTooLarge.
249 | * Based on https://golang.org/pkg/bytes/#Buffer.ReadFrom
250 | */
251 | readFrom(r: Reader): Promise;
252 | }
253 | /** Read `r` until EOF and return the content as `Uint8Array`.
254 | */
255 | export function readAll(r: Reader): Promise;
256 | /** Creates a new directory with the specified path and permission
257 | * synchronously.
258 | *
259 | * import { mkdirSync } from "deno";
260 | * mkdirSync("new_dir");
261 | */
262 | export function mkdirSync(path: string, mode?: number): void;
263 | /** Creates a new directory with the specified path and permission.
264 | *
265 | * import { mkdir } from "deno";
266 | * await mkdir("new_dir");
267 | */
268 | export function mkdir(path: string, mode?: number): Promise;
269 | interface MakeTempDirOptions {
270 | dir?: string;
271 | prefix?: string;
272 | suffix?: string;
273 | }
274 | /** makeTempDirSync is the synchronous version of `makeTempDir`.
275 | *
276 | * import { makeTempDirSync } from "deno";
277 | * const tempDirName0 = makeTempDirSync();
278 | * const tempDirName1 = makeTempDirSync({ prefix: 'my_temp' });
279 | */
280 | export function makeTempDirSync(options?: MakeTempDirOptions): string;
281 | /** makeTempDir creates a new temporary directory in the directory `dir`, its
282 | * name beginning with `prefix` and ending with `suffix`.
283 | * It returns the full path to the newly created directory.
284 | * If `dir` is unspecified, tempDir uses the default directory for temporary
285 | * files. Multiple programs calling tempDir simultaneously will not choose the
286 | * same directory. It is the caller's responsibility to remove the directory
287 | * when no longer needed.
288 | *
289 | * import { makeTempDir } from "deno";
290 | * const tempDirName0 = await makeTempDir();
291 | * const tempDirName1 = await makeTempDir({ prefix: 'my_temp' });
292 | */
293 | export function makeTempDir(options?: MakeTempDirOptions): Promise;
294 | /** Changes the permission of a specific file/directory of specified path
295 | * synchronously.
296 | *
297 | * import { chmodSync } from "deno";
298 | * chmodSync("/path/to/file", 0o666);
299 | */
300 | export function chmodSync(path: string, mode: number): void;
301 | /** Changes the permission of a specific file/directory of specified path.
302 | *
303 | * import { chmod } from "deno";
304 | * await chmod("/path/to/file", 0o666);
305 | */
306 | export function chmod(path: string, mode: number): Promise;
307 | /** Removes the named file or (empty) directory synchronously. Would throw
308 | * error if permission denied, not found, or directory not empty.
309 | *
310 | * import { removeSync } from "deno";
311 | * removeSync("/path/to/empty_dir/or/file");
312 | */
313 | export function removeSync(path: string): void;
314 | /** Removes the named file or (empty) directory. Would throw error if
315 | * permission denied, not found, or directory not empty.
316 | *
317 | * import { remove } from "deno";
318 | * await remove("/path/to/empty_dir/or/file");
319 | */
320 | export function remove(path: string): Promise;
321 | /** Recursively removes the named file or directory synchronously. Would throw
322 | * error if permission denied or not found.
323 | *
324 | * import { removeAllSync } from "deno";
325 | * removeAllSync("/path/to/dir/or/file");
326 | */
327 | export function removeAllSync(path: string): void;
328 | /** Recursively removes the named file or directory. Would throw error if
329 | * permission denied or not found.
330 | *
331 | * import { removeAll } from "deno";
332 | * await removeAll("/path/to/dir/or/file");
333 | */
334 | export function removeAll(path: string): Promise;
335 | /** Synchronously renames (moves) `oldpath` to `newpath`. If `newpath` already
336 | * exists and is not a directory, `renameSync()` replaces it. OS-specific
337 | * restrictions may apply when `oldpath` and `newpath` are in different
338 | * directories.
339 | *
340 | * import { renameSync } from "deno";
341 | * renameSync("old/path", "new/path");
342 | */
343 | export function renameSync(oldpath: string, newpath: string): void;
344 | /** Renames (moves) `oldpath` to `newpath`. If `newpath` already exists and is
345 | * not a directory, `rename()` replaces it. OS-specific restrictions may apply
346 | * when `oldpath` and `newpath` are in different directories.
347 | *
348 | * import { rename } from "deno";
349 | * await rename("old/path", "new/path");
350 | */
351 | export function rename(oldpath: string, newpath: string): Promise;
352 | /** Read the entire contents of a file synchronously.
353 | *
354 | * import { readFileSync } from "deno";
355 | * const decoder = new TextDecoder("utf-8");
356 | * const data = readFileSync("hello.txt");
357 | * console.log(decoder.decode(data));
358 | */
359 | export function readFileSync(filename: string): Uint8Array;
360 | /** Read the entire contents of a file.
361 | *
362 | * import { readFile } from "deno";
363 | * const decoder = new TextDecoder("utf-8");
364 | * const data = await readFile("hello.txt");
365 | * console.log(decoder.decode(data));
366 | */
367 | export function readFile(filename: string): Promise;
368 | /** A FileInfo describes a file and is returned by `stat`, `lstat`,
369 | * `statSync`, `lstatSync`.
370 | */
371 | export interface FileInfo {
372 | /** The size of the file, in bytes. */
373 | len: number;
374 | /** The last modification time of the file. This corresponds to the `mtime`
375 | * field from `stat` on Unix and `ftLastWriteTime` on Windows. This may not
376 | * be available on all platforms.
377 | */
378 | modified: number | null;
379 | /** The last access time of the file. This corresponds to the `atime`
380 | * field from `stat` on Unix and `ftLastAccessTime` on Windows. This may not
381 | * be available on all platforms.
382 | */
383 | accessed: number | null;
384 | /** The last access time of the file. This corresponds to the `birthtime`
385 | * field from `stat` on Unix and `ftCreationTime` on Windows. This may not
386 | * be available on all platforms.
387 | */
388 | created: number | null;
389 | /** The underlying raw st_mode bits that contain the standard Unix permissions
390 | * for this file/directory. TODO Match behavior with Go on windows for mode.
391 | */
392 | mode: number | null;
393 | /** Returns the file or directory name. */
394 | name: string | null;
395 | /** Returns the file or directory path. */
396 | path: string | null;
397 | /** Returns whether this is info for a regular file. This result is mutually
398 | * exclusive to `FileInfo.isDirectory` and `FileInfo.isSymlink`.
399 | */
400 | isFile(): boolean;
401 | /** Returns whether this is info for a regular directory. This result is
402 | * mutually exclusive to `FileInfo.isFile` and `FileInfo.isSymlink`.
403 | */
404 | isDirectory(): boolean;
405 | /** Returns whether this is info for a symlink. This result is
406 | * mutually exclusive to `FileInfo.isFile` and `FileInfo.isDirectory`.
407 | */
408 | isSymlink(): boolean;
409 | }
410 | /** Reads the directory given by path and returns a list of file info
411 | * synchronously.
412 | *
413 | * import { readDirSync } from "deno";
414 | * const files = readDirSync("/");
415 | */
416 | export function readDirSync(path: string): FileInfo[];
417 | /** Reads the directory given by path and returns a list of file info.
418 | *
419 | * import { readDir } from "deno";
420 | * const files = await readDir("/");
421 | */
422 | export function readDir(path: string): Promise;
423 | /** Copies the contents of a file to another by name synchronously.
424 | * Creates a new file if target does not exists, and if target exists,
425 | * overwrites original content of the target file.
426 | *
427 | * It would also copy the permission of the original file
428 | * to the destination.
429 | *
430 | * import { copyFileSync } from "deno";
431 | * copyFileSync("from.txt", "to.txt");
432 | */
433 | export function copyFileSync(from: string, to: string): void;
434 | /** Copies the contents of a file to another by name.
435 | *
436 | * Creates a new file if target does not exists, and if target exists,
437 | * overwrites original content of the target file.
438 | *
439 | * It would also copy the permission of the original file
440 | * to the destination.
441 | *
442 | * import { copyFile } from "deno";
443 | * await copyFile("from.txt", "to.txt");
444 | */
445 | export function copyFile(from: string, to: string): Promise;
446 | /** Returns the destination of the named symbolic link synchronously.
447 | *
448 | * import { readlinkSync } from "deno";
449 | * const targetPath = readlinkSync("symlink/path");
450 | */
451 | export function readlinkSync(name: string): string;
452 | /** Returns the destination of the named symbolic link.
453 | *
454 | * import { readlink } from "deno";
455 | * const targetPath = await readlink("symlink/path");
456 | */
457 | export function readlink(name: string): Promise;
458 | /** Queries the file system for information on the path provided. If the given
459 | * path is a symlink information about the symlink will be returned.
460 | *
461 | * import { lstat } from "deno";
462 | * const fileInfo = await lstat("hello.txt");
463 | * assert(fileInfo.isFile());
464 | */
465 | export function lstat(filename: string): Promise;
466 | /** Queries the file system for information on the path provided synchronously.
467 | * If the given path is a symlink information about the symlink will be
468 | * returned.
469 | *
470 | * import { lstatSync } from "deno";
471 | * const fileInfo = lstatSync("hello.txt");
472 | * assert(fileInfo.isFile());
473 | */
474 | export function lstatSync(filename: string): FileInfo;
475 | /** Queries the file system for information on the path provided. `stat` Will
476 | * always follow symlinks.
477 | *
478 | * import { stat } from "deno";
479 | * const fileInfo = await stat("hello.txt");
480 | * assert(fileInfo.isFile());
481 | */
482 | export function stat(filename: string): Promise;
483 | /** Queries the file system for information on the path provided synchronously.
484 | * `statSync` Will always follow symlinks.
485 | *
486 | * import { statSync } from "deno";
487 | * const fileInfo = statSync("hello.txt");
488 | * assert(fileInfo.isFile());
489 | */
490 | export function statSync(filename: string): FileInfo;
491 | /** Synchronously creates `newname` as a symbolic link to `oldname`. The type
492 | * argument can be set to `dir` or `file` and is only available on Windows
493 | * (ignored on other platforms).
494 | *
495 | * import { symlinkSync } from "deno";
496 | * symlinkSync("old/name", "new/name");
497 | */
498 | export function symlinkSync(
499 | oldname: string,
500 | newname: string,
501 | type?: string
502 | ): void;
503 | /** Creates `newname` as a symbolic link to `oldname`. The type argument can be
504 | * set to `dir` or `file` and is only available on Windows (ignored on other
505 | * platforms).
506 | *
507 | * import { symlink } from "deno";
508 | * await symlink("old/name", "new/name");
509 | */
510 | export function symlink(
511 | oldname: string,
512 | newname: string,
513 | type?: string
514 | ): Promise;
515 | /** Write a new file, with given filename and data synchronously.
516 | *
517 | * import { writeFileSync } from "deno";
518 | *
519 | * const encoder = new TextEncoder("utf-8");
520 | * const data = encoder.encode("Hello world\n");
521 | * writeFileSync("hello.txt", data);
522 | */
523 | export function writeFileSync(
524 | filename: string,
525 | data: Uint8Array,
526 | perm?: number
527 | ): void;
528 | /** Write a new file, with given filename and data.
529 | *
530 | * import { writeFile } from "deno";
531 | *
532 | * const encoder = new TextEncoder("utf-8");
533 | * const data = encoder.encode("Hello world\n");
534 | * await writeFile("hello.txt", data);
535 | */
536 | export function writeFile(
537 | filename: string,
538 | data: Uint8Array,
539 | perm?: number
540 | ): Promise;
541 | export enum ErrorKind {
542 | NoError = 0,
543 | NotFound = 1,
544 | PermissionDenied = 2,
545 | ConnectionRefused = 3,
546 | ConnectionReset = 4,
547 | ConnectionAborted = 5,
548 | NotConnected = 6,
549 | AddrInUse = 7,
550 | AddrNotAvailable = 8,
551 | BrokenPipe = 9,
552 | AlreadyExists = 10,
553 | WouldBlock = 11,
554 | InvalidInput = 12,
555 | InvalidData = 13,
556 | TimedOut = 14,
557 | Interrupted = 15,
558 | WriteZero = 16,
559 | Other = 17,
560 | UnexpectedEof = 18,
561 | BadResource = 19,
562 | CommandFailed = 20,
563 | EmptyHost = 21,
564 | IdnaError = 22,
565 | InvalidPort = 23,
566 | InvalidIpv4Address = 24,
567 | InvalidIpv6Address = 25,
568 | InvalidDomainCharacter = 26,
569 | RelativeUrlWithoutBase = 27,
570 | RelativeUrlWithCannotBeABaseBase = 28,
571 | SetHostOnCannotBeABaseUrl = 29,
572 | Overflow = 30,
573 | HttpUser = 31,
574 | HttpClosed = 32,
575 | HttpCanceled = 33,
576 | HttpParse = 34,
577 | HttpOther = 35,
578 | TooLarge = 36,
579 | InvalidUri = 37
580 | }
581 | /** A Deno specific error. The `kind` property is set to a specific error code
582 | * which can be used to in application logic.
583 | *
584 | * import { DenoError, ErrorKind } from "deno";
585 | * try {
586 | * somethingThatMightThrow();
587 | * } catch (e) {
588 | * if (e instanceof DenoError && e.kind === ErrorKind.Overflow) {
589 | * console.error("Overflow error!");
590 | * }
591 | * }
592 | */
593 | export class DenoError extends Error {
594 | readonly kind: T;
595 | constructor(kind: T, msg: string);
596 | }
597 | type MessageCallback = (msg: Uint8Array) => void;
598 | type PromiseRejectEvent =
599 | | "RejectWithNoHandler"
600 | | "HandlerAddedAfterReject"
601 | | "ResolveAfterResolved"
602 | | "RejectAfterResolved";
603 | interface Libdeno {
604 | recv(cb: MessageCallback): void;
605 | send(control: ArrayBufferView, data?: ArrayBufferView): null | Uint8Array;
606 | print(x: string, isErr?: boolean): void;
607 | shared: ArrayBuffer;
608 | setGlobalErrorHandler: (
609 | handler: (
610 | message: string,
611 | source: string,
612 | line: number,
613 | col: number,
614 | error: Error
615 | ) => void
616 | ) => void;
617 | setPromiseRejectHandler: (
618 | handler: (
619 | error: Error | string,
620 | event: PromiseRejectEvent,
621 | promise: Promise
622 | ) => void
623 | ) => void;
624 | setPromiseErrorExaminer: (handler: () => boolean) => void;
625 | }
626 | export const libdeno: Libdeno;
627 | export {};
628 | interface Platform {
629 | /** The operating system CPU architecture. */
630 | arch: "x64";
631 | /** The operating system platform. */
632 | os: "mac" | "win" | "linux";
633 | }
634 | export const platform: Platform;
635 | /** Truncates or extends the specified file synchronously, updating the size of
636 | * this file to become size.
637 | *
638 | * import { truncateSync } from "deno";
639 | *
640 | * truncateSync("hello.txt", 10);
641 | */
642 | export function truncateSync(name: string, len?: number): void;
643 | /**
644 | * Truncates or extends the specified file, updating the size of this file to
645 | * become size.
646 | *
647 | * import { truncate } from "deno";
648 | *
649 | * await truncate("hello.txt", 10);
650 | */
651 | export function truncate(name: string, len?: number): Promise;
652 | type Network = "tcp";
653 | type Addr = string;
654 | /** A Listener is a generic network listener for stream-oriented protocols. */
655 | export interface Listener {
656 | /** Waits for and resolves to the next connection to the `Listener`. */
657 | accept(): Promise;
658 | /** Close closes the listener. Any pending accept promises will be rejected
659 | * with errors.
660 | */
661 | close(): void;
662 | /** Return the address of the `Listener`. */
663 | addr(): Addr;
664 | }
665 | export interface Conn extends Reader, Writer, Closer {
666 | /** The local address of the connection. */
667 | localAddr: string;
668 | /** The remote address of the connection. */
669 | remoteAddr: string;
670 | /** Shuts down (`shutdown(2)`) the reading side of the TCP connection. Most
671 | * callers should just use `close()`.
672 | */
673 | closeRead(): void;
674 | /** Shuts down (`shutdown(2)`) the writing side of the TCP connection. Most
675 | * callers should just use `close()`.
676 | */
677 | closeWrite(): void;
678 | }
679 | /** Listen announces on the local network address.
680 | *
681 | * The network must be `tcp`, `tcp4`, `tcp6`, `unix` or `unixpacket`.
682 | *
683 | * For TCP networks, if the host in the address parameter is empty or a literal
684 | * unspecified IP address, `listen()` listens on all available unicast and
685 | * anycast IP addresses of the local system. To only use IPv4, use network
686 | * `tcp4`. The address can use a host name, but this is not recommended,
687 | * because it will create a listener for at most one of the host's IP
688 | * addresses. If the port in the address parameter is empty or `0`, as in
689 | * `127.0.0.1:` or `[::1]:0`, a port number is automatically chosen. The
690 | * `addr()` method of `Listener` can be used to discover the chosen port.
691 | *
692 | * See `dial()` for a description of the network and address parameters.
693 | */
694 | export function listen(network: Network, address: string): Listener;
695 | /** Dial connects to the address on the named network.
696 | *
697 | * Supported networks are only `tcp` currently.
698 | *
699 | * TODO: `tcp4` (IPv4-only), `tcp6` (IPv6-only), `udp`, `udp4` (IPv4-only),
700 | * `udp6` (IPv6-only), `ip`, `ip4` (IPv4-only), `ip6` (IPv6-only), `unix`,
701 | * `unixgram` and `unixpacket`.
702 | *
703 | * For TCP and UDP networks, the address has the form `host:port`. The host must
704 | * be a literal IP address, or a host name that can be resolved to IP addresses.
705 | * The port must be a literal port number or a service name. If the host is a
706 | * literal IPv6 address it must be enclosed in square brackets, as in
707 | * `[2001:db8::1]:80` or `[fe80::1%zone]:80`. The zone specifies the scope of
708 | * the literal IPv6 address as defined in RFC 4007. The functions JoinHostPort
709 | * and SplitHostPort manipulate a pair of host and port in this form. When using
710 | * TCP, and the host resolves to multiple IP addresses, Dial will try each IP
711 | * address in order until one succeeds.
712 | *
713 | * Examples:
714 | *
715 | * dial("tcp", "golang.org:http")
716 | * dial("tcp", "192.0.2.1:http")
717 | * dial("tcp", "198.51.100.1:80")
718 | * dial("udp", "[2001:db8::1]:domain")
719 | * dial("udp", "[fe80::1%lo0]:53")
720 | * dial("tcp", ":80")
721 | */
722 | export function dial(network: Network, address: string): Promise;
723 | /** **RESERVED** */
724 | export function connect(network: Network, address: string): Promise;
725 | interface Metrics {
726 | opsDispatched: number;
727 | opsCompleted: number;
728 | bytesSentControl: number;
729 | bytesSentData: number;
730 | bytesReceived: number;
731 | }
732 | /** Receive metrics from the privileged side of Deno. */
733 | export function metrics(): Metrics;
734 | export {};
735 | type ResourceMap = {
736 | [rid: number]: string;
737 | };
738 | /** Returns a map of open _file like_ resource ids along with their string
739 | * representation.
740 | */
741 | export function resources(): ResourceMap;
742 | /** How to handle subsubprocess stdio.
743 | *
744 | * "inherit" The default if unspecified. The child inherits from the
745 | * corresponding parent descriptor.
746 | *
747 | * "piped" A new pipe should be arranged to connect the parent and child
748 | * subprocesses.
749 | *
750 | * "null" This stream will be ignored. This is the equivalent of attaching the
751 | * stream to /dev/null.
752 | */
753 | type ProcessStdio = "inherit" | "piped" | "null";
754 | export interface RunOptions {
755 | args: string[];
756 | cwd?: string;
757 | stdout?: ProcessStdio;
758 | stderr?: ProcessStdio;
759 | stdin?: ProcessStdio;
760 | }
761 | export class Process {
762 | readonly rid: number;
763 | readonly pid: number;
764 | readonly stdin?: WriteCloser;
765 | readonly stdout?: ReadCloser;
766 | readonly stderr?: ReadCloser;
767 | status(): Promise;
768 | /** Buffer the stdout and return it as Uint8Array after EOF.
769 | * You must have set stdout to "piped" in when creating the process.
770 | * This calls close() on stdout after its done.
771 | */
772 | output(): Promise;
773 | close(): void;
774 | }
775 | export interface ProcessStatus {
776 | success: boolean;
777 | code?: number;
778 | signal?: number;
779 | }
780 | export function run(opt: RunOptions): Process;
781 | type ConsoleOptions = Partial<{
782 | showHidden: boolean;
783 | depth: number;
784 | colors: boolean;
785 | }>;
786 | /** TODO Do not expose this from "deno" namespace. */
787 | export function stringifyArgs(args: any[], options?: ConsoleOptions): string;
788 | type PrintFunc = (x: string, isErr?: boolean) => void;
789 | /** TODO Do not expose this from "deno". */
790 | export class Console {
791 | private printFunc;
792 | constructor(printFunc: PrintFunc);
793 | /** Writes the arguments to stdout */
794 | log: (...args: any[]) => void;
795 | /** Writes the arguments to stdout */
796 | debug: (...args: any[]) => void;
797 | /** Writes the arguments to stdout */
798 | info: (...args: any[]) => void;
799 | /** Writes the properties of the supplied `obj` to stdout */
800 | dir: (
801 | obj: any,
802 | options?: Partial<{
803 | showHidden: boolean;
804 | depth: number;
805 | colors: boolean;
806 | }>
807 | ) => void;
808 | /** Writes the arguments to stdout */
809 | warn: (...args: any[]) => void;
810 | /** Writes the arguments to stdout */
811 | error: (...args: any[]) => void;
812 | /** Writes an error message to stdout if the assertion is `false`. If the
813 | * assertion is `true`, nothing happens.
814 | *
815 | * ref: https://console.spec.whatwg.org/#assert
816 | */
817 | assert: (condition?: boolean, ...args: any[]) => void;
818 | count: (label?: string) => void;
819 | countReset: (label?: string) => void;
820 | time: (label?: string) => void;
821 | timeLog: (label?: string, ...args: any[]) => void;
822 | timeEnd: (label?: string) => void;
823 | }
824 | /**
825 | * inspect() converts input into string that has the same format
826 | * as printed by console.log(...);
827 | */
828 | export function inspect(
829 | value: any, // tslint:disable-line:no-any
830 | options?: ConsoleOptions
831 | ): string;
832 | export {};
833 | /*! ****************************************************************************
834 | Copyright (c) Microsoft Corporation. All rights reserved.
835 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
836 | this file except in compliance with the License. You may obtain a copy of the
837 | License at http://www.apache.org/licenses/LICENSE-2.0
838 |
839 | THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
840 | ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
841 | WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
842 | MERCHANTABLITY OR NON-INFRINGEMENT.
843 |
844 | See the Apache Version 2.0 License for specific language governing permissions
845 | and limitations under the License.
846 | *******************************************************************************/
847 | type BufferSource = ArrayBufferView | ArrayBuffer;
848 | type HeadersInit = Headers | Array<[string, string]> | Record;
849 | type URLSearchParamsInit = string | string[][] | Record;
850 | type BodyInit =
851 | | Blob
852 | | BufferSource
853 | | FormData
854 | | URLSearchParams
855 | | ReadableStream
856 | | string;
857 | type RequestInfo = Request | string;
858 | type ReferrerPolicy =
859 | | ""
860 | | "no-referrer"
861 | | "no-referrer-when-downgrade"
862 | | "origin-only"
863 | | "origin-when-cross-origin"
864 | | "unsafe-url";
865 | type BlobPart = BufferSource | Blob | string;
866 | type FormDataEntryValue = DomFile | string;
867 | type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
868 | interface DomIterable {
869 | keys(): IterableIterator;
870 | values(): IterableIterator;
871 | entries(): IterableIterator<[K, V]>;
872 | [Symbol.iterator](): IterableIterator<[K, V]>;
873 | forEach(
874 | callback: (value: V, key: K, parent: this) => void,
875 | thisArg?: any
876 | ): void;
877 | }
878 | interface Element {}
879 | interface HTMLFormElement {}
880 | type EndingType = "transparent" | "native";
881 | interface BlobPropertyBag {
882 | type?: string;
883 | ending?: EndingType;
884 | }
885 | interface AbortSignalEventMap {
886 | abort: ProgressEvent;
887 | }
888 | interface EventTarget {
889 | addEventListener(
890 | type: string,
891 | listener: EventListenerOrEventListenerObject | null,
892 | options?: boolean | AddEventListenerOptions
893 | ): void;
894 | dispatchEvent(evt: Event): boolean;
895 | removeEventListener(
896 | type: string,
897 | listener?: EventListenerOrEventListenerObject | null,
898 | options?: EventListenerOptions | boolean
899 | ): void;
900 | }
901 | interface ProgressEventInit extends EventInit {
902 | lengthComputable?: boolean;
903 | loaded?: number;
904 | total?: number;
905 | }
906 | interface URLSearchParams {
907 | /**
908 | * Appends a specified key/value pair as a new search parameter.
909 | */
910 | append(name: string, value: string): void;
911 | /**
912 | * Deletes the given search parameter, and its associated value,
913 | * from the list of all search parameters.
914 | */
915 | delete(name: string): void;
916 | /**
917 | * Returns the first value associated to the given search parameter.
918 | */
919 | get(name: string): string | null;
920 | /**
921 | * Returns all the values association with a given search parameter.
922 | */
923 | getAll(name: string): string[];
924 | /**
925 | * Returns a Boolean indicating if such a search parameter exists.
926 | */
927 | has(name: string): boolean;
928 | /**
929 | * Sets the value associated to a given search parameter to the given value.
930 | * If there were several values, delete the others.
931 | */
932 | set(name: string, value: string): void;
933 | /**
934 | * Sort all key/value pairs contained in this object in place
935 | * and return undefined. The sort order is according to Unicode
936 | * code points of the keys.
937 | */
938 | sort(): void;
939 | /**
940 | * Returns a query string suitable for use in a URL.
941 | */
942 | toString(): string;
943 | /**
944 | * Iterates over each name-value pair in the query
945 | * and invokes the given function.
946 | */
947 | forEach(
948 | callbackfn: (value: string, key: string, parent: URLSearchParams) => void,
949 | thisArg?: any
950 | ): void;
951 | }
952 | interface EventListener {
953 | (evt: Event): void;
954 | }
955 | interface EventInit {
956 | bubbles?: boolean;
957 | cancelable?: boolean;
958 | composed?: boolean;
959 | }
960 | interface Event {
961 | readonly bubbles: boolean;
962 | cancelBubble: boolean;
963 | readonly cancelable: boolean;
964 | readonly composed: boolean;
965 | readonly currentTarget: EventTarget | null;
966 | readonly defaultPrevented: boolean;
967 | readonly eventPhase: number;
968 | readonly isTrusted: boolean;
969 | returnValue: boolean;
970 | readonly srcElement: Element | null;
971 | readonly target: EventTarget | null;
972 | readonly timeStamp: number;
973 | readonly type: string;
974 | deepPath(): EventTarget[];
975 | initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void;
976 | preventDefault(): void;
977 | stopImmediatePropagation(): void;
978 | stopPropagation(): void;
979 | readonly AT_TARGET: number;
980 | readonly BUBBLING_PHASE: number;
981 | readonly CAPTURING_PHASE: number;
982 | readonly NONE: number;
983 | }
984 | interface DomFile extends Blob {
985 | readonly lastModified: number;
986 | readonly name: string;
987 | }
988 | interface FilePropertyBag extends BlobPropertyBag {
989 | lastModified?: number;
990 | }
991 | interface ProgressEvent extends Event {
992 | readonly lengthComputable: boolean;
993 | readonly loaded: number;
994 | readonly total: number;
995 | }
996 | interface EventListenerOptions {
997 | capture?: boolean;
998 | }
999 | interface AddEventListenerOptions extends EventListenerOptions {
1000 | once?: boolean;
1001 | passive?: boolean;
1002 | }
1003 | interface AbortSignal extends EventTarget {
1004 | readonly aborted: boolean;
1005 | onabort: ((this: AbortSignal, ev: ProgressEvent) => any) | null;
1006 | addEventListener(
1007 | type: K,
1008 | listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any,
1009 | options?: boolean | AddEventListenerOptions
1010 | ): void;
1011 | addEventListener(
1012 | type: string,
1013 | listener: EventListenerOrEventListenerObject,
1014 | options?: boolean | AddEventListenerOptions
1015 | ): void;
1016 | removeEventListener(
1017 | type: K,
1018 | listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any,
1019 | options?: boolean | EventListenerOptions
1020 | ): void;
1021 | removeEventListener(
1022 | type: string,
1023 | listener: EventListenerOrEventListenerObject,
1024 | options?: boolean | EventListenerOptions
1025 | ): void;
1026 | }
1027 | interface ReadableStream {
1028 | readonly locked: boolean;
1029 | cancel(): Promise;
1030 | getReader(): ReadableStreamReader;
1031 | }
1032 | interface EventListenerObject {
1033 | handleEvent(evt: Event): void;
1034 | }
1035 | interface ReadableStreamReader {
1036 | cancel(): Promise;
1037 | read(): Promise;
1038 | releaseLock(): void;
1039 | }
1040 | interface FormData extends DomIterable {
1041 | append(name: string, value: string | Blob, fileName?: string): void;
1042 | delete(name: string): void;
1043 | get(name: string): FormDataEntryValue | null;
1044 | getAll(name: string): FormDataEntryValue[];
1045 | has(name: string): boolean;
1046 | set(name: string, value: string | Blob, fileName?: string): void;
1047 | }
1048 | interface FormDataConstructor {
1049 | new (): FormData;
1050 | prototype: FormData;
1051 | }
1052 | /** A blob object represents a file-like object of immutable, raw data. */
1053 | interface Blob {
1054 | /** The size, in bytes, of the data contained in the `Blob` object. */
1055 | readonly size: number;
1056 | /** A string indicating the media type of the data contained in the `Blob`.
1057 | * If the type is unknown, this string is empty.
1058 | */
1059 | readonly type: string;
1060 | /** Returns a new `Blob` object containing the data in the specified range of
1061 | * bytes of the source `Blob`.
1062 | */
1063 | slice(start?: number, end?: number, contentType?: string): Blob;
1064 | }
1065 | interface Body {
1066 | /** A simple getter used to expose a `ReadableStream` of the body contents. */
1067 | readonly body: ReadableStream | null;
1068 | /** Stores a `Boolean` that declares whether the body has been used in a
1069 | * response yet.
1070 | */
1071 | readonly bodyUsed: boolean;
1072 | /** Takes a `Response` stream and reads it to completion. It returns a promise
1073 | * that resolves with an `ArrayBuffer`.
1074 | */
1075 | arrayBuffer(): Promise;
1076 | /** Takes a `Response` stream and reads it to completion. It returns a promise
1077 | * that resolves with a `Blob`.
1078 | */
1079 | blob(): Promise;
1080 | /** Takes a `Response` stream and reads it to completion. It returns a promise
1081 | * that resolves with a `FormData` object.
1082 | */
1083 | formData(): Promise;
1084 | /** Takes a `Response` stream and reads it to completion. It returns a promise
1085 | * that resolves with the result of parsing the body text as JSON.
1086 | */
1087 | json(): Promise;
1088 | /** Takes a `Response` stream and reads it to completion. It returns a promise
1089 | * that resolves with a `USVString` (text).
1090 | */
1091 | text(): Promise;
1092 | }
1093 | interface Headers extends DomIterable {
1094 | /** Appends a new value onto an existing header inside a `Headers` object, or
1095 | * adds the header if it does not already exist.
1096 | */
1097 | append(name: string, value: string): void;
1098 | /** Deletes a header from a `Headers` object. */
1099 | delete(name: string): void;
1100 | /** Returns an iterator allowing to go through all key/value pairs
1101 | * contained in this Headers object. The both the key and value of each pairs
1102 | * are ByteString objects.
1103 | */
1104 | entries(): IterableIterator<[string, string]>;
1105 | /** Returns a `ByteString` sequence of all the values of a header within a
1106 | * `Headers` object with a given name.
1107 | */
1108 | get(name: string): string | null;
1109 | /** Returns a boolean stating whether a `Headers` object contains a certain
1110 | * header.
1111 | */
1112 | has(name: string): boolean;
1113 | /** Returns an iterator allowing to go through all keys contained in
1114 | * this Headers object. The keys are ByteString objects.
1115 | */
1116 | keys(): IterableIterator;
1117 | /** Sets a new value for an existing header inside a Headers object, or adds
1118 | * the header if it does not already exist.
1119 | */
1120 | set(name: string, value: string): void;
1121 | /** Returns an iterator allowing to go through all values contained in
1122 | * this Headers object. The values are ByteString objects.
1123 | */
1124 | values(): IterableIterator;
1125 | forEach(
1126 | callbackfn: (value: string, key: string, parent: this) => void,
1127 | thisArg?: any
1128 | ): void;
1129 | /** The Symbol.iterator well-known symbol specifies the default
1130 | * iterator for this Headers object
1131 | */
1132 | [Symbol.iterator](): IterableIterator<[string, string]>;
1133 | }
1134 | interface HeadersConstructor {
1135 | new (init?: HeadersInit): Headers;
1136 | prototype: Headers;
1137 | }
1138 | type RequestCache =
1139 | | "default"
1140 | | "no-store"
1141 | | "reload"
1142 | | "no-cache"
1143 | | "force-cache"
1144 | | "only-if-cached";
1145 | type RequestCredentials = "omit" | "same-origin" | "include";
1146 | type RequestDestination =
1147 | | ""
1148 | | "audio"
1149 | | "audioworklet"
1150 | | "document"
1151 | | "embed"
1152 | | "font"
1153 | | "image"
1154 | | "manifest"
1155 | | "object"
1156 | | "paintworklet"
1157 | | "report"
1158 | | "script"
1159 | | "sharedworker"
1160 | | "style"
1161 | | "track"
1162 | | "video"
1163 | | "worker"
1164 | | "xslt";
1165 | type RequestMode = "navigate" | "same-origin" | "no-cors" | "cors";
1166 | type RequestRedirect = "follow" | "error" | "manual";
1167 | type ResponseType =
1168 | | "basic"
1169 | | "cors"
1170 | | "default"
1171 | | "error"
1172 | | "opaque"
1173 | | "opaqueredirect";
1174 | interface RequestInit {
1175 | body?: BodyInit | null;
1176 | cache?: RequestCache;
1177 | credentials?: RequestCredentials;
1178 | headers?: HeadersInit;
1179 | integrity?: string;
1180 | keepalive?: boolean;
1181 | method?: string;
1182 | mode?: RequestMode;
1183 | redirect?: RequestRedirect;
1184 | referrer?: string;
1185 | referrerPolicy?: ReferrerPolicy;
1186 | signal?: AbortSignal | null;
1187 | window?: any;
1188 | }
1189 | interface ResponseInit {
1190 | headers?: HeadersInit;
1191 | status?: number;
1192 | statusText?: string;
1193 | }
1194 | interface Request extends Body {
1195 | /** Returns the cache mode associated with request, which is a string
1196 | * indicating how the the request will interact with the browser's cache when
1197 | * fetching.
1198 | */
1199 | readonly cache: RequestCache;
1200 | /** Returns the credentials mode associated with request, which is a string
1201 | * indicating whether credentials will be sent with the request always, never,
1202 | * or only when sent to a same-origin URL.
1203 | */
1204 | readonly credentials: RequestCredentials;
1205 | /** Returns the kind of resource requested by request, (e.g., `document` or
1206 | * `script`).
1207 | */
1208 | readonly destination: RequestDestination;
1209 | /** Returns a Headers object consisting of the headers associated with
1210 | * request.
1211 | *
1212 | * Note that headers added in the network layer by the user agent
1213 | * will not be accounted for in this object, (e.g., the `Host` header).
1214 | */
1215 | readonly headers: Headers;
1216 | /** Returns request's subresource integrity metadata, which is a cryptographic
1217 | * hash of the resource being fetched. Its value consists of multiple hashes
1218 | * separated by whitespace. [SRI]
1219 | */
1220 | readonly integrity: string;
1221 | /** Returns a boolean indicating whether or not request is for a history
1222 | * navigation (a.k.a. back-forward navigation).
1223 | */
1224 | readonly isHistoryNavigation: boolean;
1225 | /** Returns a boolean indicating whether or not request is for a reload
1226 | * navigation.
1227 | */
1228 | readonly isReloadNavigation: boolean;
1229 | /** Returns a boolean indicating whether or not request can outlive the global
1230 | * in which it was created.
1231 | */
1232 | readonly keepalive: boolean;
1233 | /** Returns request's HTTP method, which is `GET` by default. */
1234 | readonly method: string;
1235 | /** Returns the mode associated with request, which is a string indicating
1236 | * whether the request will use CORS, or will be restricted to same-origin
1237 | * URLs.
1238 | */
1239 | readonly mode: RequestMode;
1240 | /** Returns the redirect mode associated with request, which is a string
1241 | * indicating how redirects for the request will be handled during fetching.
1242 | *
1243 | * A request will follow redirects by default.
1244 | */
1245 | readonly redirect: RequestRedirect;
1246 | /** Returns the referrer of request. Its value can be a same-origin URL if
1247 | * explicitly set in init, the empty string to indicate no referrer, and
1248 | * `about:client` when defaulting to the global's default.
1249 | *
1250 | * This is used during fetching to determine the value of the `Referer`
1251 | * header of the request being made.
1252 | */
1253 | readonly referrer: string;
1254 | /** Returns the referrer policy associated with request. This is used during
1255 | * fetching to compute the value of the request's referrer.
1256 | */
1257 | readonly referrerPolicy: ReferrerPolicy;
1258 | /** Returns the signal associated with request, which is an AbortSignal object
1259 | * indicating whether or not request has been aborted, and its abort event
1260 | * handler.
1261 | */
1262 | readonly signal: AbortSignal;
1263 | /** Returns the URL of request as a string. */
1264 | readonly url: string;
1265 | clone(): Request;
1266 | }
1267 | interface Response extends Body {
1268 | /** Contains the `Headers` object associated with the response. */
1269 | readonly headers: Headers;
1270 | /** Contains a boolean stating whether the response was successful (status in
1271 | * the range 200-299) or not.
1272 | */
1273 | readonly ok: boolean;
1274 | /** Indicates whether or not the response is the result of a redirect; that
1275 | * is, its URL list has more than one entry.
1276 | */
1277 | readonly redirected: boolean;
1278 | /** Contains the status code of the response (e.g., `200` for a success). */
1279 | readonly status: number;
1280 | /** Contains the status message corresponding to the status code (e.g., `OK`
1281 | * for `200`).
1282 | */
1283 | readonly statusText: string;
1284 | readonly trailer: Promise;
1285 | /** Contains the type of the response (e.g., `basic`, `cors`). */
1286 | readonly type: ResponseType;
1287 | /** Contains the URL of the response. */
1288 | readonly url: string;
1289 | /** Creates a clone of a `Response` object. */
1290 | clone(): Response;
1291 | }
1292 | export {};
1293 | type Constructor = new (...args: any[]) => T;
1294 | /** Mixes in a DOM iterable methods into a base class, assumes that there is
1295 | * a private data iterable that is part of the base class, located at
1296 | * `[dataSymbol]`.
1297 | * TODO Don't expose DomIterableMixin from "deno" namespace.
1298 | */
1299 | export function DomIterableMixin(
1300 | Base: TBase,
1301 | dataSymbol: symbol
1302 | ): TBase & Constructor>;
1303 | export {};
1304 | type TypedArray = Uint8Array | Float32Array | Int32Array;
1305 | interface CallSite {
1306 | /** Value of `this` */
1307 | getThis(): any;
1308 | /** Type of `this` as a string.
1309 | *
1310 | * This is the name of the function stored in the constructor field of
1311 | * `this`, if available. Otherwise the object's `[[Class]]` internal
1312 | * property.
1313 | */
1314 | getTypeName(): string | null;
1315 | /** Current function. */
1316 | getFunction(): Function | undefined;
1317 | /** Name of the current function, typically its name property.
1318 | *
1319 | * If a name property is not available an attempt will be made to try
1320 | * to infer a name from the function's context.
1321 | */
1322 | getFunctionName(): string | null;
1323 | /** Name of the property (of `this` or one of its prototypes) that holds
1324 | * the current function.
1325 | */
1326 | getMethodName(): string | null;
1327 | /** Name of the script (if this function was defined in a script). */
1328 | getFileName(): string | null;
1329 | /** Get the script name or source URL for the source map. */
1330 | getScriptNameOrSourceURL(): string;
1331 | /** Current line number (if this function was defined in a script). */
1332 | getLineNumber(): number | null;
1333 | /** Current column number (if this function was defined in a script). */
1334 | getColumnNumber(): number | null;
1335 | /** A call site object representing the location where eval was called (if
1336 | * this function was created using a call to `eval`)
1337 | */
1338 | getEvalOrigin(): string | undefined;
1339 | /** Is this a top level invocation, that is, is `this` the global object? */
1340 | isToplevel(): boolean;
1341 | /** Does this call take place in code defined by a call to `eval`? */
1342 | isEval(): boolean;
1343 | /** Is this call in native V8 code? */
1344 | isNative(): boolean;
1345 | /** Is this a constructor call? */
1346 | isConstructor(): boolean;
1347 | }
1348 | interface StartOfSourceMap {
1349 | file?: string;
1350 | sourceRoot?: string;
1351 | }
1352 | interface RawSourceMap extends StartOfSourceMap {
1353 | version: string;
1354 | sources: string[];
1355 | names: string[];
1356 | sourcesContent?: string[];
1357 | mappings: string;
1358 | }
1359 | global {
1360 | interface ErrorConstructor {
1361 | /** Create `.stack` property on a target object */
1362 | captureStackTrace(targetObject: object, constructorOpt?: Function): void;
1363 | /**
1364 | * Optional override for formatting stack traces
1365 | *
1366 | * @see https://github.com/v8/v8/wiki/Stack%20Trace%20API#customizing-stack-traces
1367 | */
1368 | prepareStackTrace?: (err: Error, stackTraces: CallSite[]) => any;
1369 | stackTraceLimit: number;
1370 | }
1371 | }
1372 | interface Deferred {
1373 | promise: Promise;
1374 | resolve: Function;
1375 | reject: Function;
1376 | }
1377 | /** Create a wrapper around a promise that could be resolved externally.
1378 | * TODO Do not expose this from "deno" namespace.
1379 | */
1380 | export function deferred(): Deferred;
1381 | function isTypedArray(x: unknown): x is TypedArray;
1382 | export const args: string[];
1383 | }
1384 |
1385 | declare interface Window {
1386 | window: Window;
1387 | atob: typeof textEncoding.atob;
1388 | btoa: typeof textEncoding.btoa;
1389 | fetch: typeof fetchTypes.fetch;
1390 | clearTimeout: typeof timers.clearTimer;
1391 | clearInterval: typeof timers.clearTimer;
1392 | console: consoleTypes.Console;
1393 | setTimeout: typeof timers.setTimeout;
1394 | setInterval: typeof timers.setInterval;
1395 | Blob: typeof blob.DenoBlob;
1396 | URL: typeof url.URL;
1397 | URLSearchParams: typeof urlSearchParams.URLSearchParams;
1398 | Headers: domTypes.HeadersConstructor;
1399 | FormData: domTypes.FormDataConstructor;
1400 | TextEncoder: typeof textEncoding.TextEncoder;
1401 | TextDecoder: typeof textEncoding.TextDecoder;
1402 | }
1403 |
1404 | declare const window: Window;
1405 | declare const atob: typeof textEncoding.atob;
1406 | declare const btoa: typeof textEncoding.btoa;
1407 | declare const fetch: typeof fetchTypes.fetch;
1408 | declare const clearTimeout: typeof timers.clearTimer;
1409 | declare const clearInterval: typeof timers.clearTimer;
1410 | declare const console: consoleTypes.Console;
1411 | declare const setTimeout: typeof timers.setTimeout;
1412 | declare const setInterval: typeof timers.setInterval;
1413 | declare const Blob: typeof blob.DenoBlob;
1414 | declare const URL: typeof url.URL;
1415 | declare const URLSearchParams: typeof urlSearchParams.URLSearchParams;
1416 | declare const Headers: domTypes.HeadersConstructor;
1417 | declare const FormData: domTypes.FormDataConstructor;
1418 | declare const TextEncoder: typeof textEncoding.TextEncoder;
1419 | declare const TextDecoder: typeof textEncoding.TextDecoder;
1420 |
1421 | declare type Blob = blob.DenoBlob;
1422 | declare type URL = url.URL;
1423 | declare type URLSearchParams = urlSearchParams.URLSearchParams;
1424 | declare type Headers = domTypes.Headers;
1425 | declare type FormData = domTypes.FormData;
1426 | declare type TextEncoder = textEncoding.TextEncoder;
1427 | declare type TextDecoder = textEncoding.TextDecoder;
1428 |
1429 | declare namespace domTypes {
1430 | type BufferSource = ArrayBufferView | ArrayBuffer;
1431 | type HeadersInit = Headers | Array<[string, string]> | Record;
1432 | type URLSearchParamsInit = string | string[][] | Record;
1433 | type BodyInit =
1434 | | Blob
1435 | | BufferSource
1436 | | FormData
1437 | | URLSearchParams
1438 | | ReadableStream
1439 | | string;
1440 | type RequestInfo = Request | string;
1441 | type ReferrerPolicy =
1442 | | ""
1443 | | "no-referrer"
1444 | | "no-referrer-when-downgrade"
1445 | | "origin-only"
1446 | | "origin-when-cross-origin"
1447 | | "unsafe-url";
1448 | type BlobPart = BufferSource | Blob | string;
1449 | type FormDataEntryValue = DomFile | string;
1450 | type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
1451 | interface DomIterable {
1452 | keys(): IterableIterator;
1453 | values(): IterableIterator;
1454 | entries(): IterableIterator<[K, V]>;
1455 | [Symbol.iterator](): IterableIterator<[K, V]>;
1456 | forEach(
1457 | callback: (value: V, key: K, parent: this) => void,
1458 | thisArg?: any
1459 | ): void;
1460 | }
1461 | interface Element {}
1462 | interface HTMLFormElement {}
1463 | type EndingType = "transparent" | "native";
1464 | interface BlobPropertyBag {
1465 | type?: string;
1466 | ending?: EndingType;
1467 | }
1468 | interface AbortSignalEventMap {
1469 | abort: ProgressEvent;
1470 | }
1471 | interface EventTarget {
1472 | addEventListener(
1473 | type: string,
1474 | listener: EventListenerOrEventListenerObject | null,
1475 | options?: boolean | AddEventListenerOptions
1476 | ): void;
1477 | dispatchEvent(evt: Event): boolean;
1478 | removeEventListener(
1479 | type: string,
1480 | listener?: EventListenerOrEventListenerObject | null,
1481 | options?: EventListenerOptions | boolean
1482 | ): void;
1483 | }
1484 | interface ProgressEventInit extends EventInit {
1485 | lengthComputable?: boolean;
1486 | loaded?: number;
1487 | total?: number;
1488 | }
1489 | interface URLSearchParams {
1490 | /**
1491 | * Appends a specified key/value pair as a new search parameter.
1492 | */
1493 | append(name: string, value: string): void;
1494 | /**
1495 | * Deletes the given search parameter, and its associated value,
1496 | * from the list of all search parameters.
1497 | */
1498 | delete(name: string): void;
1499 | /**
1500 | * Returns the first value associated to the given search parameter.
1501 | */
1502 | get(name: string): string | null;
1503 | /**
1504 | * Returns all the values association with a given search parameter.
1505 | */
1506 | getAll(name: string): string[];
1507 | /**
1508 | * Returns a Boolean indicating if such a search parameter exists.
1509 | */
1510 | has(name: string): boolean;
1511 | /**
1512 | * Sets the value associated to a given search parameter to the given value.
1513 | * If there were several values, delete the others.
1514 | */
1515 | set(name: string, value: string): void;
1516 | /**
1517 | * Sort all key/value pairs contained in this object in place
1518 | * and return undefined. The sort order is according to Unicode
1519 | * code points of the keys.
1520 | */
1521 | sort(): void;
1522 | /**
1523 | * Returns a query string suitable for use in a URL.
1524 | */
1525 | toString(): string;
1526 | /**
1527 | * Iterates over each name-value pair in the query
1528 | * and invokes the given function.
1529 | */
1530 | forEach(
1531 | callbackfn: (value: string, key: string, parent: URLSearchParams) => void,
1532 | thisArg?: any
1533 | ): void;
1534 | }
1535 | interface EventListener {
1536 | (evt: Event): void;
1537 | }
1538 | interface EventInit {
1539 | bubbles?: boolean;
1540 | cancelable?: boolean;
1541 | composed?: boolean;
1542 | }
1543 | interface Event {
1544 | readonly bubbles: boolean;
1545 | cancelBubble: boolean;
1546 | readonly cancelable: boolean;
1547 | readonly composed: boolean;
1548 | readonly currentTarget: EventTarget | null;
1549 | readonly defaultPrevented: boolean;
1550 | readonly eventPhase: number;
1551 | readonly isTrusted: boolean;
1552 | returnValue: boolean;
1553 | readonly srcElement: Element | null;
1554 | readonly target: EventTarget | null;
1555 | readonly timeStamp: number;
1556 | readonly type: string;
1557 | deepPath(): EventTarget[];
1558 | initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void;
1559 | preventDefault(): void;
1560 | stopImmediatePropagation(): void;
1561 | stopPropagation(): void;
1562 | readonly AT_TARGET: number;
1563 | readonly BUBBLING_PHASE: number;
1564 | readonly CAPTURING_PHASE: number;
1565 | readonly NONE: number;
1566 | }
1567 | interface DomFile extends Blob {
1568 | readonly lastModified: number;
1569 | readonly name: string;
1570 | }
1571 | interface FilePropertyBag extends BlobPropertyBag {
1572 | lastModified?: number;
1573 | }
1574 | interface ProgressEvent extends Event {
1575 | readonly lengthComputable: boolean;
1576 | readonly loaded: number;
1577 | readonly total: number;
1578 | }
1579 | interface EventListenerOptions {
1580 | capture?: boolean;
1581 | }
1582 | interface AddEventListenerOptions extends EventListenerOptions {
1583 | once?: boolean;
1584 | passive?: boolean;
1585 | }
1586 | interface AbortSignal extends EventTarget {
1587 | readonly aborted: boolean;
1588 | onabort: ((this: AbortSignal, ev: ProgressEvent) => any) | null;
1589 | addEventListener(
1590 | type: K,
1591 | listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any,
1592 | options?: boolean | AddEventListenerOptions
1593 | ): void;
1594 | addEventListener(
1595 | type: string,
1596 | listener: EventListenerOrEventListenerObject,
1597 | options?: boolean | AddEventListenerOptions
1598 | ): void;
1599 | removeEventListener(
1600 | type: K,
1601 | listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any,
1602 | options?: boolean | EventListenerOptions
1603 | ): void;
1604 | removeEventListener(
1605 | type: string,
1606 | listener: EventListenerOrEventListenerObject,
1607 | options?: boolean | EventListenerOptions
1608 | ): void;
1609 | }
1610 | interface ReadableStream {
1611 | readonly locked: boolean;
1612 | cancel(): Promise;
1613 | getReader(): ReadableStreamReader;
1614 | }
1615 | interface EventListenerObject {
1616 | handleEvent(evt: Event): void;
1617 | }
1618 | interface ReadableStreamReader {
1619 | cancel(): Promise;
1620 | read(): Promise;
1621 | releaseLock(): void;
1622 | }
1623 | interface FormData extends DomIterable {
1624 | append(name: string, value: string | Blob, fileName?: string): void;
1625 | delete(name: string): void;
1626 | get(name: string): FormDataEntryValue | null;
1627 | getAll(name: string): FormDataEntryValue[];
1628 | has(name: string): boolean;
1629 | set(name: string, value: string | Blob, fileName?: string): void;
1630 | }
1631 | interface FormDataConstructor {
1632 | new (): FormData;
1633 | prototype: FormData;
1634 | }
1635 | /** A blob object represents a file-like object of immutable, raw data. */
1636 | interface Blob {
1637 | /** The size, in bytes, of the data contained in the `Blob` object. */
1638 | readonly size: number;
1639 | /** A string indicating the media type of the data contained in the `Blob`.
1640 | * If the type is unknown, this string is empty.
1641 | */
1642 | readonly type: string;
1643 | /** Returns a new `Blob` object containing the data in the specified range of
1644 | * bytes of the source `Blob`.
1645 | */
1646 | slice(start?: number, end?: number, contentType?: string): Blob;
1647 | }
1648 | interface Body {
1649 | /** A simple getter used to expose a `ReadableStream` of the body contents. */
1650 | readonly body: ReadableStream | null;
1651 | /** Stores a `Boolean` that declares whether the body has been used in a
1652 | * response yet.
1653 | */
1654 | readonly bodyUsed: boolean;
1655 | /** Takes a `Response` stream and reads it to completion. It returns a promise
1656 | * that resolves with an `ArrayBuffer`.
1657 | */
1658 | arrayBuffer(): Promise;
1659 | /** Takes a `Response` stream and reads it to completion. It returns a promise
1660 | * that resolves with a `Blob`.
1661 | */
1662 | blob(): Promise;
1663 | /** Takes a `Response` stream and reads it to completion. It returns a promise
1664 | * that resolves with a `FormData` object.
1665 | */
1666 | formData(): Promise;
1667 | /** Takes a `Response` stream and reads it to completion. It returns a promise
1668 | * that resolves with the result of parsing the body text as JSON.
1669 | */
1670 | json(): Promise;
1671 | /** Takes a `Response` stream and reads it to completion. It returns a promise
1672 | * that resolves with a `USVString` (text).
1673 | */
1674 | text(): Promise;
1675 | }
1676 | interface Headers extends DomIterable {
1677 | /** Appends a new value onto an existing header inside a `Headers` object, or
1678 | * adds the header if it does not already exist.
1679 | */
1680 | append(name: string, value: string): void;
1681 | /** Deletes a header from a `Headers` object. */
1682 | delete(name: string): void;
1683 | /** Returns an iterator allowing to go through all key/value pairs
1684 | * contained in this Headers object. The both the key and value of each pairs
1685 | * are ByteString objects.
1686 | */
1687 | entries(): IterableIterator<[string, string]>;
1688 | /** Returns a `ByteString` sequence of all the values of a header within a
1689 | * `Headers` object with a given name.
1690 | */
1691 | get(name: string): string | null;
1692 | /** Returns a boolean stating whether a `Headers` object contains a certain
1693 | * header.
1694 | */
1695 | has(name: string): boolean;
1696 | /** Returns an iterator allowing to go through all keys contained in
1697 | * this Headers object. The keys are ByteString objects.
1698 | */
1699 | keys(): IterableIterator;
1700 | /** Sets a new value for an existing header inside a Headers object, or adds
1701 | * the header if it does not already exist.
1702 | */
1703 | set(name: string, value: string): void;
1704 | /** Returns an iterator allowing to go through all values contained in
1705 | * this Headers object. The values are ByteString objects.
1706 | */
1707 | values(): IterableIterator;
1708 | forEach(
1709 | callbackfn: (value: string, key: string, parent: this) => void,
1710 | thisArg?: any
1711 | ): void;
1712 | /** The Symbol.iterator well-known symbol specifies the default
1713 | * iterator for this Headers object
1714 | */
1715 | [Symbol.iterator](): IterableIterator<[string, string]>;
1716 | }
1717 | interface HeadersConstructor {
1718 | new (init?: HeadersInit): Headers;
1719 | prototype: Headers;
1720 | }
1721 | type RequestCache =
1722 | | "default"
1723 | | "no-store"
1724 | | "reload"
1725 | | "no-cache"
1726 | | "force-cache"
1727 | | "only-if-cached";
1728 | type RequestCredentials = "omit" | "same-origin" | "include";
1729 | type RequestDestination =
1730 | | ""
1731 | | "audio"
1732 | | "audioworklet"
1733 | | "document"
1734 | | "embed"
1735 | | "font"
1736 | | "image"
1737 | | "manifest"
1738 | | "object"
1739 | | "paintworklet"
1740 | | "report"
1741 | | "script"
1742 | | "sharedworker"
1743 | | "style"
1744 | | "track"
1745 | | "video"
1746 | | "worker"
1747 | | "xslt";
1748 | type RequestMode = "navigate" | "same-origin" | "no-cors" | "cors";
1749 | type RequestRedirect = "follow" | "error" | "manual";
1750 | type ResponseType =
1751 | | "basic"
1752 | | "cors"
1753 | | "default"
1754 | | "error"
1755 | | "opaque"
1756 | | "opaqueredirect";
1757 | interface RequestInit {
1758 | body?: BodyInit | null;
1759 | cache?: RequestCache;
1760 | credentials?: RequestCredentials;
1761 | headers?: HeadersInit;
1762 | integrity?: string;
1763 | keepalive?: boolean;
1764 | method?: string;
1765 | mode?: RequestMode;
1766 | redirect?: RequestRedirect;
1767 | referrer?: string;
1768 | referrerPolicy?: ReferrerPolicy;
1769 | signal?: AbortSignal | null;
1770 | window?: any;
1771 | }
1772 | interface ResponseInit {
1773 | headers?: HeadersInit;
1774 | status?: number;
1775 | statusText?: string;
1776 | }
1777 | interface Request extends Body {
1778 | /** Returns the cache mode associated with request, which is a string
1779 | * indicating how the the request will interact with the browser's cache when
1780 | * fetching.
1781 | */
1782 | readonly cache: RequestCache;
1783 | /** Returns the credentials mode associated with request, which is a string
1784 | * indicating whether credentials will be sent with the request always, never,
1785 | * or only when sent to a same-origin URL.
1786 | */
1787 | readonly credentials: RequestCredentials;
1788 | /** Returns the kind of resource requested by request, (e.g., `document` or
1789 | * `script`).
1790 | */
1791 | readonly destination: RequestDestination;
1792 | /** Returns a Headers object consisting of the headers associated with
1793 | * request.
1794 | *
1795 | * Note that headers added in the network layer by the user agent
1796 | * will not be accounted for in this object, (e.g., the `Host` header).
1797 | */
1798 | readonly headers: Headers;
1799 | /** Returns request's subresource integrity metadata, which is a cryptographic
1800 | * hash of the resource being fetched. Its value consists of multiple hashes
1801 | * separated by whitespace. [SRI]
1802 | */
1803 | readonly integrity: string;
1804 | /** Returns a boolean indicating whether or not request is for a history
1805 | * navigation (a.k.a. back-forward navigation).
1806 | */
1807 | readonly isHistoryNavigation: boolean;
1808 | /** Returns a boolean indicating whether or not request is for a reload
1809 | * navigation.
1810 | */
1811 | readonly isReloadNavigation: boolean;
1812 | /** Returns a boolean indicating whether or not request can outlive the global
1813 | * in which it was created.
1814 | */
1815 | readonly keepalive: boolean;
1816 | /** Returns request's HTTP method, which is `GET` by default. */
1817 | readonly method: string;
1818 | /** Returns the mode associated with request, which is a string indicating
1819 | * whether the request will use CORS, or will be restricted to same-origin
1820 | * URLs.
1821 | */
1822 | readonly mode: RequestMode;
1823 | /** Returns the redirect mode associated with request, which is a string
1824 | * indicating how redirects for the request will be handled during fetching.
1825 | *
1826 | * A request will follow redirects by default.
1827 | */
1828 | readonly redirect: RequestRedirect;
1829 | /** Returns the referrer of request. Its value can be a same-origin URL if
1830 | * explicitly set in init, the empty string to indicate no referrer, and
1831 | * `about:client` when defaulting to the global's default.
1832 | *
1833 | * This is used during fetching to determine the value of the `Referer`
1834 | * header of the request being made.
1835 | */
1836 | readonly referrer: string;
1837 | /** Returns the referrer policy associated with request. This is used during
1838 | * fetching to compute the value of the request's referrer.
1839 | */
1840 | readonly referrerPolicy: ReferrerPolicy;
1841 | /** Returns the signal associated with request, which is an AbortSignal object
1842 | * indicating whether or not request has been aborted, and its abort event
1843 | * handler.
1844 | */
1845 | readonly signal: AbortSignal;
1846 | /** Returns the URL of request as a string. */
1847 | readonly url: string;
1848 | clone(): Request;
1849 | }
1850 | interface Response extends Body {
1851 | /** Contains the `Headers` object associated with the response. */
1852 | readonly headers: Headers;
1853 | /** Contains a boolean stating whether the response was successful (status in
1854 | * the range 200-299) or not.
1855 | */
1856 | readonly ok: boolean;
1857 | /** Indicates whether or not the response is the result of a redirect; that
1858 | * is, its URL list has more than one entry.
1859 | */
1860 | readonly redirected: boolean;
1861 | /** Contains the status code of the response (e.g., `200` for a success). */
1862 | readonly status: number;
1863 | /** Contains the status message corresponding to the status code (e.g., `OK`
1864 | * for `200`).
1865 | */
1866 | readonly statusText: string;
1867 | readonly trailer: Promise;
1868 | /** Contains the type of the response (e.g., `basic`, `cors`). */
1869 | readonly type: ResponseType;
1870 | /** Contains the URL of the response. */
1871 | readonly url: string;
1872 | /** Creates a clone of a `Response` object. */
1873 | clone(): Response;
1874 | }
1875 | }
1876 |
1877 | declare namespace blob {
1878 | const bytesSymbol: unique symbol;
1879 | export class DenoBlob implements domTypes.Blob {
1880 | private readonly [bytesSymbol];
1881 | readonly size: number;
1882 | readonly type: string;
1883 | /** A blob object represents a file-like object of immutable, raw data. */
1884 | constructor(
1885 | blobParts?: domTypes.BlobPart[],
1886 | options?: domTypes.BlobPropertyBag
1887 | );
1888 | slice(start?: number, end?: number, contentType?: string): DenoBlob;
1889 | }
1890 | }
1891 |
1892 | declare namespace consoleTypes {
1893 | type ConsoleOptions = Partial<{
1894 | showHidden: boolean;
1895 | depth: number;
1896 | colors: boolean;
1897 | }>;
1898 | /** TODO Do not expose this from "deno" namespace. */
1899 | export function stringifyArgs(args: any[], options?: ConsoleOptions): string;
1900 | type PrintFunc = (x: string, isErr?: boolean) => void;
1901 | /** TODO Do not expose this from "deno". */
1902 | export class Console {
1903 | private printFunc;
1904 | constructor(printFunc: PrintFunc);
1905 | /** Writes the arguments to stdout */
1906 | log: (...args: any[]) => void;
1907 | /** Writes the arguments to stdout */
1908 | debug: (...args: any[]) => void;
1909 | /** Writes the arguments to stdout */
1910 | info: (...args: any[]) => void;
1911 | /** Writes the properties of the supplied `obj` to stdout */
1912 | dir: (
1913 | obj: any,
1914 | options?: Partial<{
1915 | showHidden: boolean;
1916 | depth: number;
1917 | colors: boolean;
1918 | }>
1919 | ) => void;
1920 | /** Writes the arguments to stdout */
1921 | warn: (...args: any[]) => void;
1922 | /** Writes the arguments to stdout */
1923 | error: (...args: any[]) => void;
1924 | /** Writes an error message to stdout if the assertion is `false`. If the
1925 | * assertion is `true`, nothing happens.
1926 | *
1927 | * ref: https://console.spec.whatwg.org/#assert
1928 | */
1929 | assert: (condition?: boolean, ...args: any[]) => void;
1930 | count: (label?: string) => void;
1931 | countReset: (label?: string) => void;
1932 | time: (label?: string) => void;
1933 | timeLog: (label?: string, ...args: any[]) => void;
1934 | timeEnd: (label?: string) => void;
1935 | }
1936 | /**
1937 | * inspect() converts input into string that has the same format
1938 | * as printed by console.log(...);
1939 | */
1940 | export function inspect(
1941 | value: any, // tslint:disable-line:no-any
1942 | options?: ConsoleOptions
1943 | ): string;
1944 | }
1945 |
1946 | declare namespace io {
1947 | export interface ReadResult {
1948 | nread: number;
1949 | eof: boolean;
1950 | }
1951 | export interface Reader {
1952 | /** Reads up to p.byteLength bytes into `p`. It resolves to the number
1953 | * of bytes read (`0` <= `n` <= `p.byteLength`) and any error encountered.
1954 | * Even if `read()` returns `n` < `p.byteLength`, it may use all of `p` as
1955 | * scratch space during the call. If some data is available but not
1956 | * `p.byteLength` bytes, `read()` conventionally returns what is available
1957 | * instead of waiting for more.
1958 | *
1959 | * When `read()` encounters an error or end-of-file condition after
1960 | * successfully reading `n` > `0` bytes, it returns the number of bytes read.
1961 | * It may return the (non-nil) error from the same call or return the error
1962 | * (and `n` == `0`) from a subsequent call. An instance of this general case
1963 | * is that a `Reader` returning a non-zero number of bytes at the end of the
1964 | * input stream may return either `err` == `EOF` or `err` == `null`. The next
1965 | * `read()` should return `0`, `EOF`.
1966 | *
1967 | * Callers should always process the `n` > `0` bytes returned before
1968 | * considering the `EOF`. Doing so correctly handles I/O errors that happen
1969 | * after reading some bytes and also both of the allowed `EOF` behaviors.
1970 | *
1971 | * Implementations of `read()` are discouraged from returning a zero byte
1972 | * count with a `null` error, except when `p.byteLength` == `0`. Callers
1973 | * should treat a return of `0` and `null` as indicating that nothing
1974 | * happened; in particular it does not indicate `EOF`.
1975 | *
1976 | * Implementations must not retain `p`.
1977 | */
1978 | read(p: Uint8Array): Promise;
1979 | }
1980 | export interface Writer {
1981 | /** Writes `p.byteLength` bytes from `p` to the underlying data
1982 | * stream. It resolves to the number of bytes written from `p` (`0` <= `n` <=
1983 | * `p.byteLength`) and any error encountered that caused the write to stop
1984 | * early. `write()` must return a non-null error if it returns `n` <
1985 | * `p.byteLength`. write() must not modify the slice data, even temporarily.
1986 | *
1987 | * Implementations must not retain `p`.
1988 | */
1989 | write(p: Uint8Array): Promise;
1990 | }
1991 | export interface Closer {
1992 | close(): void;
1993 | }
1994 | export interface Seeker {
1995 | /** Seek sets the offset for the next `read()` or `write()` to offset,
1996 | * interpreted according to `whence`: `SeekStart` means relative to the start
1997 | * of the file, `SeekCurrent` means relative to the current offset, and
1998 | * `SeekEnd` means relative to the end. Seek returns the new offset relative
1999 | * to the start of the file and an error, if any.
2000 | *
2001 | * Seeking to an offset before the start of the file is an error. Seeking to
2002 | * any positive offset is legal, but the behavior of subsequent I/O operations
2003 | * on the underlying object is implementation-dependent.
2004 | */
2005 | seek(offset: number, whence: number): Promise;
2006 | }
2007 | export interface ReadCloser extends Reader, Closer {}
2008 | export interface WriteCloser extends Writer, Closer {}
2009 | export interface ReadSeeker extends Reader, Seeker {}
2010 | export interface WriteSeeker extends Writer, Seeker {}
2011 | export interface ReadWriteCloser extends Reader, Writer, Closer {}
2012 | export interface ReadWriteSeeker extends Reader, Writer, Seeker {}
2013 | /** Copies from `src` to `dst` until either `EOF` is reached on `src`
2014 | * or an error occurs. It returns the number of bytes copied and the first
2015 | * error encountered while copying, if any.
2016 | *
2017 | * Because `copy()` is defined to read from `src` until `EOF`, it does not
2018 | * treat an `EOF` from `read()` as an error to be reported.
2019 | */
2020 | export function copy(dst: Writer, src: Reader): Promise;
2021 | /** Turns `r` into async iterator.
2022 | *
2023 | * for await (const chunk of readerIterator(reader)) {
2024 | * console.log(chunk)
2025 | * }
2026 | */
2027 | export function toAsyncIterator(r: Reader): AsyncIterableIterator;
2028 | }
2029 |
2030 | declare namespace fetchTypes {
2031 | class Body implements domTypes.Body, domTypes.ReadableStream, io.ReadCloser {
2032 | private rid;
2033 | readonly contentType: string;
2034 | bodyUsed: boolean;
2035 | private _bodyPromise;
2036 | private _data;
2037 | readonly locked: boolean;
2038 | readonly body: null | Body;
2039 | constructor(rid: number, contentType: string);
2040 | private _bodyBuffer;
2041 | arrayBuffer(): Promise;
2042 | blob(): Promise;
2043 | formData(): Promise;
2044 | json(): Promise;
2045 | text(): Promise;
2046 | read(p: Uint8Array): Promise;
2047 | close(): void;
2048 | cancel(): Promise;
2049 | getReader(): domTypes.ReadableStreamReader;
2050 | }
2051 | class Response implements domTypes.Response {
2052 | readonly status: number;
2053 | readonly url: string;
2054 | statusText: string;
2055 | readonly type = "basic";
2056 | redirected: boolean;
2057 | headers: domTypes.Headers;
2058 | readonly trailer: Promise;
2059 | bodyUsed: boolean;
2060 | readonly body: Body;
2061 | constructor(
2062 | status: number,
2063 | headersList: Array<[string, string]>,
2064 | rid: number,
2065 | body_?: null | Body
2066 | );
2067 | arrayBuffer(): Promise;
2068 | blob(): Promise;
2069 | formData(): Promise;
2070 | json(): Promise;
2071 | text(): Promise;
2072 | readonly ok: boolean;
2073 | clone(): domTypes.Response;
2074 | }
2075 | /** Fetch a resource from the network. */
2076 | export function fetch(
2077 | input: domTypes.Request | string,
2078 | init?: domTypes.RequestInit
2079 | ): Promise;
2080 | }
2081 |
2082 | declare namespace textEncoding {
2083 | export function atob(s: string): string;
2084 | /** Creates a base-64 ASCII string from the input string. */
2085 | export function btoa(s: string): string;
2086 | export interface TextDecodeOptions {
2087 | stream?: false;
2088 | }
2089 | export interface TextDecoderOptions {
2090 | fatal?: boolean;
2091 | ignoreBOM?: false;
2092 | }
2093 | export class TextDecoder {
2094 | private _encoding;
2095 | /** Returns encoding's name, lowercased. */
2096 | readonly encoding: string;
2097 | /** Returns `true` if error mode is "fatal", and `false` otherwise. */
2098 | readonly fatal: boolean;
2099 | /** Returns `true` if ignore BOM flag is set, and `false` otherwise. */
2100 | readonly ignoreBOM = false;
2101 | constructor(label?: string, options?: TextDecoderOptions);
2102 | /** Returns the result of running encoding's decoder. */
2103 | decode(input?: domTypes.BufferSource, options?: TextDecodeOptions): string;
2104 | }
2105 | export class TextEncoder {
2106 | /** Returns "utf-8". */
2107 | readonly encoding = "utf-8";
2108 | /** Returns the result of running UTF-8's encoder. */
2109 | encode(input?: string): Uint8Array;
2110 | }
2111 | }
2112 |
2113 | declare namespace timers {
2114 | export type Args = any[];
2115 | /** Sets a timer which executes a function once after the timer expires. */
2116 | export function setTimeout(
2117 | cb: (...args: Args) => void,
2118 | delay: number,
2119 | ...args: Args
2120 | ): number;
2121 | /** Repeatedly calls a function , with a fixed time delay between each call. */
2122 | export function setInterval(
2123 | cb: (...args: Args) => void,
2124 | delay: number,
2125 | ...args: Args
2126 | ): number;
2127 | /** Clears a previously set timer by id. */
2128 | export function clearTimer(id: number): void;
2129 | }
2130 |
2131 | declare namespace urlSearchParams {
2132 | export class URLSearchParams {
2133 | private params;
2134 | constructor(init?: string | string[][] | Record);
2135 | /** Appends a specified key/value pair as a new search parameter.
2136 | *
2137 | * searchParams.append('name', 'first');
2138 | * searchParams.append('name', 'second');
2139 | */
2140 | append(name: string, value: string): void;
2141 | /** Deletes the given search parameter and its associated value,
2142 | * from the list of all search parameters.
2143 | *
2144 | * searchParams.delete('name');
2145 | */
2146 | delete(name: string): void;
2147 | /** Returns all the values associated with a given search parameter
2148 | * as an array.
2149 | *
2150 | * searchParams.getAll('name');
2151 | */
2152 | getAll(name: string): string[];
2153 | /** Returns the first value associated to the given search parameter.
2154 | *
2155 | * searchParams.get('name');
2156 | */
2157 | get(name: string): string | null;
2158 | /** Returns a Boolean that indicates whether a parameter with the
2159 | * specified name exists.
2160 | *
2161 | * searchParams.has('name');
2162 | */
2163 | has(name: string): boolean;
2164 | /** Sets the value associated with a given search parameter to the
2165 | * given value. If there were several matching values, this method
2166 | * deletes the others. If the search parameter doesn't exist, this
2167 | * method creates it.
2168 | *
2169 | * searchParams.set('name', 'value');
2170 | */
2171 | set(name: string, value: string): void;
2172 | /** Sort all key/value pairs contained in this object in place and
2173 | * return undefined. The sort order is according to Unicode code
2174 | * points of the keys.
2175 | *
2176 | * searchParams.sort();
2177 | */
2178 | sort(): void;
2179 | /** Calls a function for each element contained in this object in
2180 | * place and return undefined. Optionally accepts an object to use
2181 | * as this when executing callback as second argument.
2182 | *
2183 | * searchParams.forEach((value, key, parent) => {
2184 | * console.log(value, key, parent);
2185 | * });
2186 | *
2187 | */
2188 | forEach(
2189 | callbackfn: (value: string, key: string, parent: URLSearchParams) => void,
2190 | thisArg?: any
2191 | ): void;
2192 | /** Returns an iterator allowing to go through all keys contained
2193 | * in this object.
2194 | *
2195 | * for (const key of searchParams.keys()) {
2196 | * console.log(key);
2197 | * }
2198 | */
2199 | keys(): Iterable;
2200 | /** Returns an iterator allowing to go through all values contained
2201 | * in this object.
2202 | *
2203 | * for (const value of searchParams.values()) {
2204 | * console.log(value);
2205 | * }
2206 | */
2207 | values(): Iterable;
2208 | /** Returns an iterator allowing to go through all key/value
2209 | * pairs contained in this object.
2210 | *
2211 | * for (const [key, value] of searchParams.entries()) {
2212 | * console.log(key, value);
2213 | * }
2214 | */
2215 | entries(): Iterable<[string, string]>;
2216 | /** Returns an iterator allowing to go through all key/value
2217 | * pairs contained in this object.
2218 | *
2219 | * for (const [key, value] of searchParams[Symbol.iterator]()) {
2220 | * console.log(key, value);
2221 | * }
2222 | */
2223 | [Symbol.iterator](): Iterable<[string, string]>;
2224 | /** Returns a query string suitable for use in a URL.
2225 | *
2226 | * searchParams.toString();
2227 | */
2228 | toString(): string;
2229 | }
2230 | }
2231 |
2232 | declare namespace url {
2233 | export class URL {
2234 | private _parts;
2235 | private _searchParams;
2236 | private _updateSearchParams;
2237 | hash: string;
2238 | host: string;
2239 | hostname: string;
2240 | href: string;
2241 | readonly origin: string;
2242 | password: string;
2243 | pathname: string;
2244 | port: string;
2245 | protocol: string;
2246 | search: string;
2247 | username: string;
2248 | readonly searchParams: urlSearchParams.URLSearchParams;
2249 | constructor(url: string, base?: string | URL);
2250 | toString(): string;
2251 | toJSON(): string;
2252 | }
2253 | }
2254 |
2255 |
--------------------------------------------------------------------------------
/errors.ts:
--------------------------------------------------------------------------------
1 | export class SocketClosedError extends Error {}
--------------------------------------------------------------------------------
/example/main.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Yusuke Sakurai. All rights reserved. MIT license.
2 | import {serve} from "https://deno.land/x/net/http.ts";
3 | import {acceptWebSocket, isWebSocketCloseEvent, isWebSocketPingEvent} from "../ws.ts";
4 |
5 | async function main() {
6 | console.log("websocket server is running on 0.0.0.0:8080");
7 | for await (const req of serve("0.0.0.0:8080")) {
8 | if (req.url === "/ws") {
9 | (async () => {
10 | const sock = await acceptWebSocket(req);
11 | console.log("socket connected!");
12 | for await (const ev of sock.receive()) {
13 | if (typeof ev === "string") {
14 | // text message
15 | console.log("ws:Text", ev);
16 | await sock.send(ev);
17 | } else if (ev instanceof Uint8Array) {
18 | // binary message
19 | console.log("ws:Binary", ev);
20 | } else if (isWebSocketPingEvent(ev)) {
21 | const [_, body] = ev;
22 | // ping
23 | console.log("ws:Ping", body);
24 | } else if (isWebSocketCloseEvent(ev)) {
25 | // close
26 | const {code, reason} = ev;
27 | console.log("ws:Close", code, reason);
28 | }
29 | }
30 | })();
31 | }
32 | }
33 | }
34 |
35 | main();
--------------------------------------------------------------------------------
/ioutil.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Yusuke Sakurai. All rights reserved. MIT license.
2 | import {BufReader} from "https://deno.land/x/net/bufio.ts";
3 |
4 | export async function readShort(buf: BufReader) {
5 | const [high, low] = [
6 | await buf.readByte(),
7 | await buf.readByte()
8 | ];
9 | return (high << 8) | low;
10 | }
11 |
12 | export async function readInt(buf: BufReader) {
13 | const [high, low] = [
14 | await readShort(buf),
15 | await readShort(buf)
16 | ];
17 | return (high << 16) | low
18 | }
19 |
20 | export async function readLong(buf: BufReader) {
21 | const [high, low] = [
22 | await readInt(buf),
23 | await readInt(buf)
24 | ];
25 | return (high << 32) | low
26 | }
27 |
28 | export function sliceLongToBytes(d: number, dest = new Array(8)): number[] {
29 | let mask = 0xff;
30 | let shift = 58;
31 | for (let i = 0; i < 8; i++) {
32 | dest[i] = (d >>> shift) & mask;
33 | shift -= 8;
34 | mask >>>= 8;
35 | }
36 | return dest;
37 | }
38 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2018",
4 | "baseUrl": ".",
5 | "paths": {
6 | "deno": ["./deno.d.ts"],
7 | "http://*": [
8 | "../../.deno/deps/https/*"
9 | ],
10 | "https://*": [
11 | "../../.deno/deps/https/*"
12 | ]
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/ws.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Yusuke Sakurai. All rights reserved. MIT license.
2 | import {Buffer, Writer, Conn} from "deno"
3 | import {ServerRequest} from "https://deno.land/x/net/http.ts";
4 | import {BufReader, BufWriter} from "https://deno.land/x/net/bufio.ts";
5 | import {readLong, readShort, sliceLongToBytes} from "./ioutil.ts";
6 | import {Sha1} from "./crypt.ts";
7 | import {SocketClosedError} from "./errors.ts";
8 |
9 | export const OpCodeContinue = 0x0;
10 | export const OpCodeTextFrame = 0x1;
11 | export const OpCodeBinaryFrame = 0x2;
12 | export const OpCodeClose = 0x8;
13 | export const OpcodePing = 0x9;
14 | export const OpcodePong = 0xA;
15 |
16 |
17 | export type WebSocketEvent = string | Uint8Array | WebSocketCloseEvent | WebSocketPingEvent | WebSocketPongEvent;
18 |
19 | export type WebSocketCloseEvent = {
20 | code: number
21 | reason?: string
22 | };
23 |
24 | export function isWebSocketCloseEvent(a): a is WebSocketCloseEvent {
25 | return a && typeof a["code"] === "number"
26 | }
27 |
28 | export type WebSocketPingEvent = ["ping", Uint8Array]
29 |
30 | export function isWebSocketPingEvent(a): a is WebSocketPingEvent {
31 | return Array.isArray(a) && a[0] === "ping" && a[1] instanceof Uint8Array;
32 | }
33 |
34 | export type WebSocketPongEvent = ["pong", Uint8Array]
35 |
36 | export function isWebSocketPongEvent(a): a is WebSocketPongEvent {
37 | return Array.isArray(a) && a[0] === "pong" && a[1] instanceof Uint8Array;
38 | }
39 |
40 | export type WebSocketFrame = {
41 | isLastFrame: boolean,
42 | opcode: number,
43 | mask?: Uint8Array,
44 | payload: Uint8Array
45 | }
46 |
47 | export type WebSocket = {
48 | readonly isClosed: boolean
49 | receive(): AsyncIterableIterator
50 | send(data: string | Uint8Array): Promise
51 | ping(data?: string | Uint8Array): Promise
52 | close(code: number, reason?: string): Promise
53 | }
54 |
55 | class WebSocketImpl implements WebSocket {
56 | encoder = new TextEncoder();
57 | constructor(private conn: Conn, private mask?: Uint8Array) {
58 | }
59 |
60 | async* receive(): AsyncIterableIterator {
61 | let frames: WebSocketFrame[] = [];
62 | let payloadsLength = 0;
63 | for await (const frame of receiveFrame(this.conn)) {
64 | unmask(frame.payload, frame.mask);
65 | switch (frame.opcode) {
66 | case OpCodeTextFrame:
67 | case OpCodeBinaryFrame:
68 | case OpCodeContinue:
69 | frames.push(frame);
70 | payloadsLength += frame.payload.length;
71 | if (frame.isLastFrame) {
72 | const concat = new Uint8Array(payloadsLength);
73 | let offs = 0;
74 | for (const frame of frames) {
75 | concat.set(frame.payload, offs);
76 | offs += frame.payload.length;
77 | }
78 | if (frames[0].opcode === OpCodeTextFrame) {
79 | // text
80 | yield new Buffer(concat).toString()
81 | } else {
82 | // binary
83 | yield concat
84 | }
85 | frames = [];
86 | payloadsLength = 0;
87 | }
88 | break;
89 | case OpCodeClose:
90 | const code = (frame.payload[0] << 16) | frame.payload[1];
91 | const reason = new Buffer(frame.payload.subarray(2, frame.payload.length)).toString();
92 | this._isClosed = true;
93 | yield {code, reason};
94 | return;
95 | case OpcodePing:
96 | yield ["ping", frame.payload] as WebSocketPingEvent;
97 | break;
98 | case OpcodePong:
99 | yield ["pong", frame.payload] as WebSocketPongEvent;
100 | break;
101 | }
102 | }
103 | }
104 |
105 | async send(data: string | Uint8Array): Promise {
106 | if (this.isClosed) {
107 | throw new SocketClosedError("socket has been closed")
108 | }
109 | const opcode = typeof data === "string" ? OpCodeTextFrame : OpCodeBinaryFrame;
110 | const payload = typeof data === "string" ? this.encoder.encode(data) : data;
111 | const isLastFrame = true;
112 | await writeFrame({
113 | isLastFrame,
114 | opcode,
115 | payload,
116 | mask: this.mask,
117 | }, this.conn);
118 | }
119 |
120 | async ping(data: string | Uint8Array): Promise {
121 | const payload = typeof data === "string" ? this.encoder.encode(data) : data;
122 | await writeFrame({
123 | isLastFrame: true,
124 | opcode: OpCodeClose,
125 | mask: this.mask,
126 | payload
127 | }, this.conn)
128 | }
129 |
130 | private _isClosed = false;
131 | get isClosed() {
132 | return this._isClosed;
133 | }
134 |
135 | async close(code: number, reason?: string): Promise {
136 | try {
137 | const header = [
138 | (code >>> 8), (code & 0x00ff)
139 | ];
140 | let payload: Uint8Array;
141 | if (reason) {
142 | const reasonBytes = this.encoder.encode(reason);
143 | payload = new Uint8Array(2 + reasonBytes.byteLength);
144 | payload.set(header);
145 | payload.set(reasonBytes, 2);
146 | } else {
147 | payload = new Uint8Array(header);
148 | }
149 | await writeFrame({
150 | isLastFrame: true,
151 | opcode: OpCodeClose,
152 | mask: this.mask,
153 | payload
154 | }, this.conn);
155 | } catch (e) {
156 | throw e;
157 | } finally {
158 | this.ensureSocketClosed();
159 | }
160 | }
161 |
162 | private ensureSocketClosed(): Error {
163 | if (this.isClosed) return;
164 | try {
165 | this.conn.close()
166 | } catch (e) {
167 | console.error(e);
168 | } finally {
169 | this._isClosed = true;
170 | }
171 | }
172 | }
173 |
174 |
175 | export async function* receiveFrame(conn: Conn): AsyncIterableIterator {
176 | let receiving = true;
177 | const reader = new BufReader(conn);
178 | while (receiving) {
179 | const frame = await readFrame(reader);
180 | switch (frame.opcode) {
181 | case OpCodeTextFrame:
182 | case OpCodeBinaryFrame:
183 | case OpCodeContinue:
184 | yield frame;
185 | break;
186 | case OpCodeClose:
187 | await writeFrame({
188 | isLastFrame: true,
189 | opcode: OpCodeClose,
190 | payload: frame.payload,
191 | }, conn);
192 | conn.close();
193 | yield frame;
194 | receiving = false;
195 | break;
196 | case OpcodePing:
197 | await writeFrame({
198 | isLastFrame: true,
199 | opcode: OpcodePong,
200 | payload: frame.payload
201 | }, conn);
202 | yield frame;
203 | break;
204 | case OpcodePong:
205 | yield frame;
206 | break;
207 | }
208 | }
209 | }
210 |
211 | export async function writeFrame(frame: WebSocketFrame, writer: Writer) {
212 | let payloadLength = frame.payload.byteLength;
213 | let header: Uint8Array;
214 | const hasMask = (frame.mask ? 1 : 0) << 7;
215 | if (payloadLength < 126) {
216 | header = new Uint8Array([
217 | (0b1000 << 4) | frame.opcode,
218 | (hasMask | payloadLength)
219 | ]);
220 | } else if (payloadLength < 0xffff) {
221 | header = new Uint8Array([
222 | (0b1000 << 4) | frame.opcode,
223 | (hasMask | 0b01111110),
224 | payloadLength >>> 8,
225 | (payloadLength & 0x00ff)
226 | ]);
227 | } else {
228 | header = new Uint8Array([
229 | (0b1000 << 4) | frame.opcode,
230 | (hasMask | 0b01111111),
231 | ...sliceLongToBytes(payloadLength)
232 | ]);
233 | }
234 | if (frame.mask) {
235 | unmask(frame.payload, frame.mask);
236 | }
237 | const bytes = new Uint8Array(header.length + payloadLength);
238 | bytes.set(header, 0);
239 | bytes.set(frame.payload, header.length);
240 | const w = new BufWriter(writer);
241 | await w.write(bytes);
242 | await w.flush();
243 | }
244 |
245 | export function unmask(payload: Uint8Array, mask: Uint8Array) {
246 | if (mask) {
247 | for (let i = 0; i < payload.length; i++) {
248 | payload[i] ^= mask[i % 4];
249 | }
250 | }
251 | }
252 |
253 | export function acceptable(req: ServerRequest): boolean {
254 | return req.headers.get("upgrade") === "websocket"
255 | && req.headers.has("sec-websocket-key")
256 | }
257 |
258 | export async function acceptWebSocket(req: ServerRequest): Promise {
259 | if (acceptable(req)) {
260 | const sock = new WebSocketImpl(req.conn);
261 | const secKey = req.headers.get("sec-websocket-key");
262 | const secAccept = createSecAccept(secKey);
263 | await req.respond({
264 | status: 101,
265 | headers: new Headers({
266 | "Upgrade": "websocket",
267 | "Connection": "Upgrade",
268 | "Sec-WebSocket-Accept": secAccept,
269 | })
270 | });
271 | return sock;
272 | }
273 | throw new Error("request is not acceptable");
274 | }
275 |
276 | const kGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
277 |
278 | export function createSecAccept(nonce: string) {
279 | const sha1 = new Sha1();
280 | sha1.update(nonce + kGUID);
281 | const bytes = sha1.digest();
282 | const hash = bytes.reduce((data, byte) => data + String.fromCharCode(byte), "");
283 | return btoa(hash);
284 | }
285 |
286 | export async function readFrame(buf: BufReader): Promise {
287 | let b = await buf.readByte();
288 | let isLastFrame = false;
289 | switch (b >>> 4) {
290 | case 0b1000:
291 | isLastFrame = true;
292 | break;
293 | case 0b0000:
294 | isLastFrame = false;
295 | break;
296 | default:
297 | throw new Error("invalid signature");
298 | }
299 | const opcode = b & 0x0f;
300 | // has_mask & payload
301 | b = await buf.readByte();
302 | const hasMask = b >>> 7;
303 | let payloadLength = b & 0b01111111;
304 | if (payloadLength === 126) {
305 | payloadLength = await readShort(buf);
306 | } else if (payloadLength === 127) {
307 | payloadLength = await readLong(buf);
308 | }
309 | // mask
310 | let mask;
311 | if (hasMask) {
312 | mask = new Uint8Array(4);
313 | await buf.readFull(mask);
314 | }
315 | // payload
316 | const payload = new Uint8Array(payloadLength);
317 | await buf.readFull(payload);
318 | return {
319 | isLastFrame, opcode, mask, payload
320 | }
321 | }
322 |
--------------------------------------------------------------------------------
/ws_test.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2018 Yusuke Sakurai. All rights reserved. MIT license.
2 | import {Buffer} from "deno";
3 | import {BufReader} from "https://deno.land/x/net/bufio.ts"
4 | import {
5 | test,
6 | assert,
7 | assertEqual
8 | } from "https://deno.land/x/testing/testing.ts";
9 | import {
10 | createSecAccept,
11 | OpCodeBinaryFrame,
12 | OpCodeContinue,
13 | OpcodePing,
14 | OpcodePong,
15 | OpCodeTextFrame,
16 | readFrame,
17 | unmask
18 | } from "./ws.ts";
19 |
20 | test(async function testReadFrame() {
21 | // unmasked single text frame with payload "Hello"
22 | const buf = new BufReader(new Buffer(new Uint8Array([
23 | 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f
24 | ])));
25 | const frame = await readFrame(buf);
26 | assertEqual(frame.opcode, OpCodeTextFrame);
27 | assertEqual(frame.mask, undefined);
28 | assertEqual(new Buffer(frame.payload).toString(), "Hello");
29 | assertEqual(frame.isLastFrame, true);
30 | });
31 |
32 | test(async function testReadFrame2() {
33 | //a masked single text frame with payload "Hello"
34 | const buf = new BufReader(new Buffer(new Uint8Array([
35 | 0x81, 0x85, 0x37, 0xfa, 0x21, 0x3d, 0x7f, 0x9f, 0x4d, 0x51, 0x58
36 | ])));
37 | const frame = await readFrame(buf);
38 | console.dir(frame);
39 | assertEqual(frame.opcode, OpCodeTextFrame);
40 | unmask(frame.payload, frame.mask);
41 | assertEqual(new Buffer(frame.payload).toString(), "Hello");
42 | assertEqual(frame.isLastFrame, true);
43 | });
44 |
45 | test(async function f() {
46 | const buf1 = new BufReader(new Buffer(new Uint8Array([
47 | 0x01, 0x03, 0x48, 0x65, 0x6c
48 | ])));
49 | const buf2 = new BufReader(new Buffer(new Uint8Array([
50 | 0x80, 0x02, 0x6c, 0x6f
51 | ])));
52 | const [f1, f2] = await Promise.all([
53 | readFrame(buf1), readFrame(buf2)
54 | ]);
55 | assertEqual(f1.isLastFrame, false);
56 | assertEqual(f1.mask, undefined);
57 | assertEqual(f1.opcode, OpCodeTextFrame);
58 | assertEqual(new Buffer(f1.payload).toString(), "Hel");
59 |
60 | assertEqual(f2.isLastFrame, true);
61 | assertEqual(f2.mask, undefined);
62 | assertEqual(f2.opcode, OpCodeContinue);
63 | assertEqual(new Buffer(f2.payload).toString(), "lo")
64 | });
65 |
66 | test(async function f2() {
67 | // unmasked ping with payload "Hello"
68 | const buf = new BufReader(new Buffer(new Uint8Array([
69 | 0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f,
70 | ])));
71 | const ping = await readFrame(buf);
72 | assertEqual(ping.opcode, OpcodePing);
73 | assertEqual(new Buffer(ping.payload).toString(), "Hello")
74 |
75 | const buf2 = new BufReader(new Buffer(new Uint8Array([
76 | 0x8a, 0x85, 0x37, 0xfa, 0x21, 0x3d, 0x7f, 0x9f, 0x4d, 0x51, 0x58
77 | ])));
78 | const pong = await readFrame(buf2);
79 | assertEqual(pong.opcode, OpcodePong);
80 | assert(pong.mask !== undefined);
81 | unmask(pong.payload, pong.mask);
82 | assertEqual(new Buffer(pong.payload).toString(), "Hello")
83 | });
84 |
85 | test(async function f3() {
86 | let a = [0x82, 0x7E, 0x01, 0x00];
87 | for (let i = 0; i < 256; i++) {
88 | a.push(i);
89 | }
90 | const buf = new BufReader(new Buffer(new Uint8Array(a)));
91 | const bin = await readFrame(buf);
92 | assertEqual(bin.opcode, OpCodeBinaryFrame);
93 | assertEqual(bin.isLastFrame, true);
94 | assertEqual(bin.mask, undefined);
95 | assertEqual(bin.payload.length, 256);
96 | });
97 |
98 | test(async function f4() {
99 | let a = [0x82, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00];
100 | for (let i = 0; i < 0xffff; i++) {
101 | a.push(i);
102 | }
103 | const buf = new BufReader(new Buffer(new Uint8Array(a)));
104 | const bin = await readFrame(buf);
105 | assertEqual(bin.opcode, OpCodeBinaryFrame);
106 | assertEqual(bin.isLastFrame, true);
107 | assertEqual(bin.mask, undefined);
108 | assertEqual(bin.payload.length, 0xffff + 1);
109 | });
110 |
111 | test(async function testCreateSecAccept() {
112 | const nonce = "dGhlIHNhbXBsZSBub25jZQ==";
113 | const d = createSecAccept(nonce);
114 | assertEqual(d, "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=");
115 | });
--------------------------------------------------------------------------------