rust-fetch 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -14
- package/node.js +252 -0
- package/package.json +2 -2
- package/rust_fetch.js +55 -5
- package/rust_fetch_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ const { body: user } = await api.get('/users/42');
|
|
|
43
43
|
- **Streaming** responses as a `ReadableStream`, and **download progress** callbacks.
|
|
44
44
|
- **Interceptors** for requests and responses, e.g. auth headers and token refresh.
|
|
45
45
|
- **TypeScript** definitions for the whole API.
|
|
46
|
-
- **Tested**: 100% line coverage of the Rust core, plus wasm tests and end-to-end tests of the packed npm package. See [Development](#development).
|
|
46
|
+
- **Tested**: 100% line coverage of the Rust core and of the Node.js transport, plus wasm tests and end-to-end tests of the packed npm package. See [Development](#development).
|
|
47
47
|
|
|
48
48
|
## Installation
|
|
49
49
|
|
|
@@ -105,7 +105,7 @@ await client.get('/search', { params: { q: 'rust wasm', page: 2, tag: ['a', 'b']
|
|
|
105
105
|
await client.fetch('/users/1', { method: 'DELETE', headers: { 'X-Reason': 'cleanup' } });
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
Relative URLs need a `baseUrl`. In a browser page without one, they resolve against the page URL. Absolute URLs always win over `baseUrl`. `TRACE` and `CONNECT` are rejected because `fetch()` forbids them.
|
|
108
|
+
Relative URLs need a `baseUrl`. In a browser page without one, they resolve against the page URL. Absolute URLs always win over `baseUrl`. `TRACE` and `CONNECT` are rejected, because browsers' `fetch()` forbids them.
|
|
109
109
|
|
|
110
110
|
#### Request options
|
|
111
111
|
|
|
@@ -223,7 +223,7 @@ controller.abort(); // rejects with a CancelledError
|
|
|
223
223
|
await client.get('/report', { signal: AbortSignal.timeout(5_000) }); // total deadline, including retries
|
|
224
224
|
```
|
|
225
225
|
|
|
226
|
-
Aborting cancels the
|
|
226
|
+
Aborting cancels the request in flight, any pending retry delay, and a body being streamed.
|
|
227
227
|
|
|
228
228
|
### Streaming
|
|
229
229
|
|
|
@@ -352,18 +352,20 @@ Request futures are `Send`, so you can `tokio::spawn` them. Progress callbacks (
|
|
|
352
352
|
|
|
353
353
|
## Performance
|
|
354
354
|
|
|
355
|
-
rust-fetch
|
|
355
|
+
**In Node.js, rust-fetch is as fast as or faster than the built-in `fetch()` for typical API traffic.** Node's `fetch()` implements browser semantics (WHATWG streams) on top of its sockets. rust-fetch uses its own lean transport on `node:http`/`node:https` with keep-alive. Retries, timeouts, validation and errors still come from the Rust core.
|
|
356
356
|
|
|
357
|
-
`npm run bench` (Node 22.13, Apple M1 Pro, local server):
|
|
357
|
+
`npm run bench` (Node 22.13, Apple M1 Pro, local server, median of 5 alternating rounds):
|
|
358
358
|
|
|
359
359
|
| Scenario | native `fetch` | rust-fetch | rust-fetch / native |
|
|
360
360
|
| --- | ---: | ---: | ---: |
|
|
361
|
-
| Small JSON, sequential |
|
|
362
|
-
| Small JSON, 50 concurrent |
|
|
363
|
-
| JSON 0.6 MB | 219 req/s |
|
|
364
|
-
| Binary 8 MB |
|
|
361
|
+
| Small JSON, sequential | 10,558 req/s | 10,634 req/s | **101%** |
|
|
362
|
+
| Small JSON, 50 concurrent | 13,401 req/s | 13,895 req/s | **104%** |
|
|
363
|
+
| JSON 0.6 MB | 219 req/s | 203 req/s | 92% |
|
|
364
|
+
| Binary 8 MB | 177 req/s | 181 req/s | **102%** |
|
|
365
365
|
|
|
366
|
-
|
|
366
|
+
Large JSON is dominated by `JSON.parse`, which both clients pay; the remaining gap is extra garbage collection from crossing into Wasm.
|
|
367
|
+
|
|
368
|
+
**In browsers**, `fetch()` is the only way to make requests, so rust-fetch uses it and can't be faster than it. The difference is a fraction of a millisecond per request, which matters little once a request crosses a real network.
|
|
367
369
|
|
|
368
370
|
## Roadmap
|
|
369
371
|
|
|
@@ -379,9 +381,9 @@ The overhead per request is a fraction of a millisecond, which matters little on
|
|
|
379
381
|
- [ ] Upload progress tracking: not possible on top of `fetch()`, which has no upload progress events
|
|
380
382
|
- [ ] WebSocket support
|
|
381
383
|
- Handled by the runtime, not by rust-fetch:
|
|
382
|
-
- **Connection pooling:** browsers
|
|
383
|
-
- **Proxies:**
|
|
384
|
-
- **HTTP/2:** browsers negotiate it automatically;
|
|
384
|
+
- **Connection pooling:** browsers pool connections for `fetch()`; in Node.js rust-fetch reuses connections through Node's default keep-alive agents.
|
|
385
|
+
- **Proxies:** in Node.js, install a proxy agent as `http.globalAgent` / `https.globalAgent` (for example from `https-proxy-agent`). In browsers, use the system settings.
|
|
386
|
+
- **HTTP/2:** browsers negotiate it automatically; the Node.js transport uses HTTP/1.1 with keep-alive.
|
|
385
387
|
|
|
386
388
|
## Upgrading to 2.0
|
|
387
389
|
|
|
@@ -420,6 +422,7 @@ npm run test:js # JS end-to-end tests against the built package (requires a b
|
|
|
420
422
|
npm run bench # rust-fetch vs native fetch (requires a build)
|
|
421
423
|
npm run size # size budget for the built package
|
|
422
424
|
npm run api:check # public TypeScript API vs the committed snapshot
|
|
425
|
+
npm run coverage:js # Node.js transport coverage (100% lines and functions)
|
|
423
426
|
|
|
424
427
|
cd wasm-module
|
|
425
428
|
wasm-pack test --node # wasm unit tests for the JS bindings
|
|
@@ -434,7 +437,7 @@ cargo llvm-cov --ignore-filename-regex 'src/(wasm/|http\.rs)|tests/' # coverag
|
|
|
434
437
|
| JS end-to-end tests | `wasm-module/js/test/client.test.mjs` | The built package against a local server |
|
|
435
438
|
| Package tests | `wasm-module/js/test/package.test.mjs` | Installs the packed tarball and uses it via `import`, `require`, the browser entry and its types |
|
|
436
439
|
|
|
437
|
-
CI runs the Rust suites with a coverage gate that fails if line or function coverage of the Rust core drops below 100%. It also runs the wasm and JS suites on Node 20, 22 and 24, and checks formatting, dependencies (security advisories and licenses), API compatibility and the size budget. See [CONTRIBUTING.md](CONTRIBUTING.md#pull-requests). The JS-only bindings in `src/wasm/` and `src/http.rs` need a JS engine, so they're covered by the wasm and JS suites instead.
|
|
440
|
+
CI runs the Rust suites with a coverage gate that fails if line or function coverage of the Rust core, or of the Node.js transport, drops below 100%. It also runs the wasm and JS suites on Node 20, 22 and 24, and checks formatting, dependencies (security advisories and licenses), API compatibility and the size budget. See [CONTRIBUTING.md](CONTRIBUTING.md#pull-requests). The JS-only bindings in `src/wasm/` and `src/http.rs` need a JS engine, so they're covered by the wasm and JS suites instead.
|
|
438
441
|
|
|
439
442
|
Releases are published by CI when a version tag is pushed. See [CONTRIBUTING.md](CONTRIBUTING.md#releasing).
|
|
440
443
|
|
package/node.js
CHANGED
|
@@ -4,10 +4,262 @@
|
|
|
4
4
|
// file: URLs. Here the module is compiled synchronously on import instead, so
|
|
5
5
|
// the API is ready to use immediately; calling `init()` is optional and
|
|
6
6
|
// returns the already-initialized module.
|
|
7
|
+
//
|
|
8
|
+
// It also registers a transport built on node:http/node:https. Node's global
|
|
9
|
+
// fetch() implements browser semantics (WHATWG streams) on top of the same
|
|
10
|
+
// sockets and is considerably slower; this transport only moves bytes.
|
|
11
|
+
// Retries, timeouts, validation and decoding stay in the Rust core.
|
|
7
12
|
import { readFileSync } from 'node:fs';
|
|
13
|
+
import http from 'node:http';
|
|
14
|
+
import https from 'node:https';
|
|
15
|
+
import zlib from 'node:zlib';
|
|
8
16
|
import { initSync } from './rust_fetch.js';
|
|
9
17
|
|
|
10
18
|
initSync({ module: readFileSync(new URL('./rust_fetch_bg.wasm', import.meta.url)) });
|
|
11
19
|
|
|
20
|
+
const MAX_REDIRECTS = 20;
|
|
21
|
+
const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
|
|
22
|
+
const ACCEPT_ENCODING = typeof zlib.zstdDecompressSync === 'function' ? 'gzip, deflate, br, zstd' : 'gzip, deflate, br';
|
|
23
|
+
|
|
24
|
+
const textDecoder = new TextDecoder();
|
|
25
|
+
// Response body types, numbered like `BodyType` in src/wasm/mod.rs
|
|
26
|
+
const AUTO = 0;
|
|
27
|
+
const JSON_BODY = 1;
|
|
28
|
+
const TEXT = 2;
|
|
29
|
+
const BINARY = 3;
|
|
30
|
+
|
|
31
|
+
// Same rules as is_json_content_type / is_text_content_type in src/types.rs
|
|
32
|
+
function mimeEssence(contentType) {
|
|
33
|
+
return (contentType ?? '').split(';')[0].trim().toLowerCase();
|
|
34
|
+
}
|
|
35
|
+
function isJsonType(essence) {
|
|
36
|
+
return essence === 'application/json' || essence.endsWith('+json');
|
|
37
|
+
}
|
|
38
|
+
function isTextType(essence) {
|
|
39
|
+
return (
|
|
40
|
+
essence.startsWith('text/') ||
|
|
41
|
+
essence.endsWith('+xml') ||
|
|
42
|
+
essence === 'application/xml' ||
|
|
43
|
+
essence === 'application/javascript' ||
|
|
44
|
+
essence === 'application/x-www-form-urlencoded'
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function coded(error, code) {
|
|
49
|
+
error.code = code;
|
|
50
|
+
return error;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Decode a body like `decode_body` in src/wasm/transport.rs, in JS so the
|
|
55
|
+
* text never crosses into wasm. TextDecoder replaces invalid UTF-8 and strips
|
|
56
|
+
* a BOM; the length is checked first, since a BOM-only body is not empty.
|
|
57
|
+
*/
|
|
58
|
+
function decodeBody(bytes, contentType, bodyType) {
|
|
59
|
+
if (bytes.length === 0) return bodyType === TEXT ? '' : bodyType === BINARY ? new Uint8Array(0) : null;
|
|
60
|
+
const essence = mimeEssence(contentType);
|
|
61
|
+
const json = bodyType === JSON_BODY || (bodyType === AUTO && isJsonType(essence));
|
|
62
|
+
const text = json || bodyType === TEXT || (bodyType === AUTO && isTextType(essence));
|
|
63
|
+
if (!text) return bytes;
|
|
64
|
+
const decoded = textDecoder.decode(bytes);
|
|
65
|
+
if (!json) return decoded;
|
|
66
|
+
try {
|
|
67
|
+
return JSON.parse(decoded);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (bodyType === AUTO) return decoded; // mislabelled responses fall back to text
|
|
70
|
+
throw coded(error, 'RUST_FETCH_PARSE');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Undo one Content-Encoding; unknown encodings are passed through, like fetch() */
|
|
75
|
+
function decode(body, encoding) {
|
|
76
|
+
switch (encoding) {
|
|
77
|
+
case 'gzip':
|
|
78
|
+
case 'x-gzip':
|
|
79
|
+
return zlib.gunzipSync(body, { finishFlush: zlib.constants.Z_SYNC_FLUSH });
|
|
80
|
+
case 'deflate':
|
|
81
|
+
// Servers send both zlib-wrapped and raw deflate under this name
|
|
82
|
+
return body[0] === 0x78 ? zlib.inflateSync(body) : zlib.inflateRawSync(body);
|
|
83
|
+
case 'br':
|
|
84
|
+
return zlib.brotliDecompressSync(body);
|
|
85
|
+
case 'zstd':
|
|
86
|
+
return typeof zlib.zstdDecompressSync === 'function' ? zlib.zstdDecompressSync(body) : body;
|
|
87
|
+
default:
|
|
88
|
+
return body;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function decompress(body, contentEncoding) {
|
|
93
|
+
if (!contentEncoding || body.length === 0) return body;
|
|
94
|
+
// Encodings are listed in the order they were applied
|
|
95
|
+
const encodings = contentEncoding.toLowerCase().split(',').map((e) => e.trim()).filter((e) => e && e !== 'identity');
|
|
96
|
+
for (let i = encodings.length - 1; i >= 0; i--) body = decode(body, encodings[i]);
|
|
97
|
+
return body;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Response headers as one string per name; repeated headers joined with ", " */
|
|
101
|
+
function flattenHeaders(raw) {
|
|
102
|
+
const headers = {};
|
|
103
|
+
for (const name in raw) {
|
|
104
|
+
const value = raw[name];
|
|
105
|
+
headers[name] = Array.isArray(value) ? value.join(', ') : value;
|
|
106
|
+
}
|
|
107
|
+
return headers;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* A plain Uint8Array that owns its memory. Small Node Buffers share a pooled
|
|
112
|
+
* ArrayBuffer, so those are copied; larger ones are wrapped without copying.
|
|
113
|
+
*/
|
|
114
|
+
function ownedBytes(bytes) {
|
|
115
|
+
return bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength
|
|
116
|
+
? new Uint8Array(bytes.buffer)
|
|
117
|
+
: new Uint8Array(bytes);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function withoutHeaders(headers, names) {
|
|
121
|
+
const copy = { ...headers };
|
|
122
|
+
for (const name of names) delete copy[name];
|
|
123
|
+
return copy;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function send(state, method, url, headers, body, redirects, resolve, reject) {
|
|
127
|
+
if (state.cancelled) return;
|
|
128
|
+
const transport = url.protocol === 'https:' ? https : http;
|
|
129
|
+
const request = transport.request(url, { method, headers }, (response) => {
|
|
130
|
+
const status = response.statusCode;
|
|
131
|
+
const location = response.headers.location;
|
|
132
|
+
|
|
133
|
+
if (REDIRECT_STATUSES.has(status) && location) {
|
|
134
|
+
response.resume();
|
|
135
|
+
if (redirects >= MAX_REDIRECTS) return reject(new TypeError(`Too many redirects (more than ${MAX_REDIRECTS})`));
|
|
136
|
+
let next;
|
|
137
|
+
try {
|
|
138
|
+
next = new URL(location, url);
|
|
139
|
+
} catch {
|
|
140
|
+
return reject(new TypeError(`Invalid redirect location: ${location}`));
|
|
141
|
+
}
|
|
142
|
+
if (next.protocol !== 'http:' && next.protocol !== 'https:') {
|
|
143
|
+
return reject(new TypeError(`Unsupported redirect to ${next.protocol}`));
|
|
144
|
+
}
|
|
145
|
+
// Same rules as fetch(): 303, and 301/302 after POST, become a bodiless GET
|
|
146
|
+
let nextMethod = method;
|
|
147
|
+
let nextBody = body;
|
|
148
|
+
let nextHeaders = headers;
|
|
149
|
+
if ((status === 303 && method !== 'GET' && method !== 'HEAD') || ((status === 301 || status === 302) && method === 'POST')) {
|
|
150
|
+
nextMethod = 'GET';
|
|
151
|
+
nextBody = undefined;
|
|
152
|
+
nextHeaders = withoutHeaders(nextHeaders, ['content-type', 'content-length', 'content-encoding', 'content-language', 'content-location']);
|
|
153
|
+
}
|
|
154
|
+
// Never forward credentials to another origin
|
|
155
|
+
if (next.origin !== url.origin) {
|
|
156
|
+
nextHeaders = withoutHeaders(nextHeaders, ['authorization', 'cookie', 'proxy-authorization']);
|
|
157
|
+
}
|
|
158
|
+
return send(state, nextMethod, next, nextHeaders, nextBody, redirects + 1, resolve, reject);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// With a Content-Length, fill one preallocated buffer (a single copy);
|
|
162
|
+
// otherwise collect chunks and join them at the end.
|
|
163
|
+
const expected = Number(response.headers['content-length']);
|
|
164
|
+
const preallocated = !response.headers['content-encoding'] && Number.isSafeInteger(expected) && expected > 0 && expected <= 512 * 1024 * 1024;
|
|
165
|
+
const buffer = preallocated ? new Uint8Array(expected) : undefined;
|
|
166
|
+
let received = 0;
|
|
167
|
+
const chunks = [];
|
|
168
|
+
response.on('data', (chunk) => {
|
|
169
|
+
if (buffer && received + chunk.length <= expected) buffer.set(chunk, received);
|
|
170
|
+
else chunks.push(chunk);
|
|
171
|
+
received += chunk.length;
|
|
172
|
+
});
|
|
173
|
+
response.on('error', reject);
|
|
174
|
+
// A socket closed mid-body may emit 'close' without 'end' (a settled promise ignores this)
|
|
175
|
+
response.on('close', () => {
|
|
176
|
+
if (!response.complete) reject(new TypeError('The connection closed before the response body was complete'));
|
|
177
|
+
});
|
|
178
|
+
response.on('end', () => {
|
|
179
|
+
if (!response.complete) return reject(new TypeError('The connection closed before the response body was complete'));
|
|
180
|
+
try {
|
|
181
|
+
let body;
|
|
182
|
+
if (buffer && received === expected && chunks.length === 0) {
|
|
183
|
+
body = buffer;
|
|
184
|
+
} else {
|
|
185
|
+
const raw = buffer ? Buffer.concat([buffer.subarray(0, Math.min(received, expected)), ...chunks]) : Buffer.concat(chunks);
|
|
186
|
+
body = ownedBytes(method === 'HEAD' ? raw : decompress(raw, response.headers['content-encoding']));
|
|
187
|
+
}
|
|
188
|
+
resolve({ status, url: url.href, headers: flattenHeaders(response.headers), body });
|
|
189
|
+
} catch (error) {
|
|
190
|
+
reject(error);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
request.on('error', reject);
|
|
195
|
+
request.end(body);
|
|
196
|
+
state.request = request;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* One attempt, called by the Rust core with
|
|
201
|
+
* `{ method, url, headers, body?, timeout?, bodyType }`. Resolves to the
|
|
202
|
+
* finished `{ status, statusText, ok, url, headers, body }` (the core fills
|
|
203
|
+
* in statusText). Rejects with code RUST_FETCH_TIMEOUT or RUST_FETCH_PARSE,
|
|
204
|
+
* or any other error for network failures.
|
|
205
|
+
*
|
|
206
|
+
* The promise has a `cancel()` method, which the core calls only when it
|
|
207
|
+
* abandons an attempt (e.g. AbortSignal); this is much cheaper than wiring an
|
|
208
|
+
* AbortSignal into every request.
|
|
209
|
+
*/
|
|
210
|
+
function nodeTransport(request) {
|
|
211
|
+
const state = { cancelled: false, request: undefined, bodyType: request.bodyType ?? AUTO };
|
|
212
|
+
let timer;
|
|
213
|
+
const promise = new Promise((resolve, reject) => {
|
|
214
|
+
if (request.timeout > 0) {
|
|
215
|
+
// Covers the whole attempt: connecting, redirects and reading the body
|
|
216
|
+
timer = setTimeout(() => {
|
|
217
|
+
cancel();
|
|
218
|
+
reject(coded(new Error(`Request timeout after ${request.timeout}ms`), 'RUST_FETCH_TIMEOUT'));
|
|
219
|
+
}, request.timeout);
|
|
220
|
+
}
|
|
221
|
+
let url;
|
|
222
|
+
try {
|
|
223
|
+
url = new URL(request.url);
|
|
224
|
+
} catch (error) {
|
|
225
|
+
clearTimeout(timer);
|
|
226
|
+
return reject(error);
|
|
227
|
+
}
|
|
228
|
+
const headers = { ...request.headers };
|
|
229
|
+
headers['accept'] ??= '*/*';
|
|
230
|
+
headers['accept-encoding'] ??= ACCEPT_ENCODING;
|
|
231
|
+
headers['user-agent'] ??= 'rust-fetch';
|
|
232
|
+
if (request.body) headers['content-length'] ??= String(request.body.length);
|
|
233
|
+
const settle = (fn) => (value) => {
|
|
234
|
+
clearTimeout(timer);
|
|
235
|
+
fn(value);
|
|
236
|
+
};
|
|
237
|
+
send(state, request.method, url, headers, request.body, 0, settle(resolve), settle(reject));
|
|
238
|
+
});
|
|
239
|
+
const cancel = () => {
|
|
240
|
+
state.cancelled = true;
|
|
241
|
+
state.request?.destroy();
|
|
242
|
+
};
|
|
243
|
+
// Decode only after the socket's event handlers have returned: decoding
|
|
244
|
+
// inside them keeps the raw chunks and stream state alive during
|
|
245
|
+
// JSON.parse, which costs several times more garbage collection.
|
|
246
|
+
const finished = promise.then((response) => finishResponse(response, state.bodyType));
|
|
247
|
+
finished.cancel = () => {
|
|
248
|
+
clearTimeout(timer);
|
|
249
|
+
cancel();
|
|
250
|
+
};
|
|
251
|
+
return finished;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** The response object handed to the Rust core (which fills in statusText) */
|
|
255
|
+
function finishResponse({ status, url, headers, body }, bodyType) {
|
|
256
|
+
const ok = status >= 200 && status < 300;
|
|
257
|
+
// Error statuses carry their body as text (for HttpError.body)
|
|
258
|
+
const decoded = ok ? decodeBody(body, headers['content-type'], bodyType) : decodeBody(body, '', TEXT);
|
|
259
|
+
return { status, statusText: '', ok, url, headers, body: decoded };
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
globalThis[Symbol.for('rust-fetch.transport')] = nodeTransport;
|
|
263
|
+
|
|
12
264
|
export { default } from './rust_fetch.js';
|
|
13
265
|
export * from './rust_fetch.js';
|
package/package.json
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
"collaborators": [
|
|
5
5
|
"Asem Qaffaf <asem@qaffaf.com>"
|
|
6
6
|
],
|
|
7
|
-
"description": "A
|
|
8
|
-
"version": "2.
|
|
7
|
+
"description": "A reliable HTTP client for JavaScript and TypeScript, written in Rust and compiled to WebAssembly: timeouts, retries, typed errors and interceptors, faster than fetch() in Node.js",
|
|
8
|
+
"version": "2.1.0",
|
|
9
9
|
"license": "MIT OR Apache-2.0",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
package/rust_fetch.js
CHANGED
|
@@ -513,6 +513,10 @@ function __wbg_get_imports() {
|
|
|
513
513
|
__wbg_append_1938ed58fb5613b8: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
|
514
514
|
arg0.append(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
|
|
515
515
|
}, arguments); },
|
|
516
|
+
__wbg_arrayBuffer_f07be74819944ea2: function() { return handleError(function (arg0) {
|
|
517
|
+
const ret = arg0.arrayBuffer();
|
|
518
|
+
return ret;
|
|
519
|
+
}, arguments); },
|
|
516
520
|
__wbg_body_4e088733babc630d: function(arg0) {
|
|
517
521
|
const ret = arg0.body;
|
|
518
522
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
|
@@ -525,6 +529,10 @@ function __wbg_get_imports() {
|
|
|
525
529
|
const ret = arg0.byobRequest;
|
|
526
530
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
|
527
531
|
},
|
|
532
|
+
__wbg_byteLength_27689b065d089962: function(arg0) {
|
|
533
|
+
const ret = arg0.byteLength;
|
|
534
|
+
return ret;
|
|
535
|
+
},
|
|
528
536
|
__wbg_byteLength_9f985b8373f1f3fe: function(arg0) {
|
|
529
537
|
const ret = arg0.byteLength;
|
|
530
538
|
return ret;
|
|
@@ -553,7 +561,7 @@ function __wbg_get_imports() {
|
|
|
553
561
|
const ret = clearTimeout(arg0);
|
|
554
562
|
return ret;
|
|
555
563
|
},
|
|
556
|
-
|
|
564
|
+
__wbg_clearTimeout_2d18004c33139d44: function(arg0) {
|
|
557
565
|
clearTimeout(arg0);
|
|
558
566
|
},
|
|
559
567
|
__wbg_close_185286988f30f252: function() { return handleError(function (arg0) {
|
|
@@ -562,6 +570,10 @@ function __wbg_get_imports() {
|
|
|
562
570
|
__wbg_close_748f26698dabe269: function() { return handleError(function (arg0) {
|
|
563
571
|
arg0.close();
|
|
564
572
|
}, arguments); },
|
|
573
|
+
__wbg_decode_0be77be735437c76: function() { return handleError(function (arg0, arg1) {
|
|
574
|
+
const ret = arg0.decode(arg1);
|
|
575
|
+
return ret;
|
|
576
|
+
}, arguments); },
|
|
565
577
|
__wbg_done_b41a1d26cdb37fb6: function(arg0) {
|
|
566
578
|
const ret = arg0.done;
|
|
567
579
|
return ret;
|
|
@@ -577,6 +589,10 @@ function __wbg_get_imports() {
|
|
|
577
589
|
const ret = Object.entries(arg0);
|
|
578
590
|
return ret;
|
|
579
591
|
},
|
|
592
|
+
__wbg_fetch_43bae44b7171a171: function() { return handleError(function (arg0) {
|
|
593
|
+
const ret = fetch(arg0);
|
|
594
|
+
return ret;
|
|
595
|
+
}, arguments); },
|
|
580
596
|
__wbg_fetch_7a37768ab67c5bd8: function(arg0) {
|
|
581
597
|
const ret = fetch(arg0);
|
|
582
598
|
return ret;
|
|
@@ -585,6 +601,14 @@ function __wbg_get_imports() {
|
|
|
585
601
|
const ret = arg0.fetch(arg1);
|
|
586
602
|
return ret;
|
|
587
603
|
},
|
|
604
|
+
__wbg_for_beb5dc4e908dd8b8: function(arg0, arg1) {
|
|
605
|
+
const ret = Symbol.for(getStringFromWasm0(arg0, arg1));
|
|
606
|
+
return ret;
|
|
607
|
+
},
|
|
608
|
+
__wbg_fromEntries_5159142be68954c3: function() { return handleError(function (arg0) {
|
|
609
|
+
const ret = Object.fromEntries(arg0);
|
|
610
|
+
return ret;
|
|
611
|
+
}, arguments); },
|
|
588
612
|
__wbg_from_296ca31f8d0f1c52: function(arg0) {
|
|
589
613
|
const ret = Array.from(arg0);
|
|
590
614
|
return ret;
|
|
@@ -609,6 +633,13 @@ function __wbg_get_imports() {
|
|
|
609
633
|
const ret = arg0.done;
|
|
610
634
|
return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
|
|
611
635
|
},
|
|
636
|
+
__wbg_get_f75619e20cb68514: function() { return handleError(function (arg0, arg1, arg2, arg3) {
|
|
637
|
+
const ret = arg1.get(getStringFromWasm0(arg2, arg3));
|
|
638
|
+
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
639
|
+
var len1 = WASM_VECTOR_LEN;
|
|
640
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
641
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
642
|
+
}, arguments); },
|
|
612
643
|
__wbg_get_unchecked_288889d017702237: function(arg0, arg1) {
|
|
613
644
|
const ret = arg0[arg1 >>> 0];
|
|
614
645
|
return ret;
|
|
@@ -707,6 +738,10 @@ function __wbg_get_imports() {
|
|
|
707
738
|
const ret = new Headers();
|
|
708
739
|
return ret;
|
|
709
740
|
}, arguments); },
|
|
741
|
+
__wbg_new_cdac6c2ae368ec54: function() {
|
|
742
|
+
const ret = new TextDecoder();
|
|
743
|
+
return ret;
|
|
744
|
+
},
|
|
710
745
|
__wbg_new_from_slice_9a868026ffa4208a: function(arg0, arg1) {
|
|
711
746
|
const ret = new Uint8Array(getArrayU8FromWasm0(arg0, arg1));
|
|
712
747
|
return ret;
|
|
@@ -753,13 +788,25 @@ function __wbg_get_imports() {
|
|
|
753
788
|
const ret = arg0.next();
|
|
754
789
|
return ret;
|
|
755
790
|
}, arguments); },
|
|
791
|
+
__wbg_of_20798cb14708764f: function(arg0, arg1) {
|
|
792
|
+
const ret = Array.of(arg0, arg1);
|
|
793
|
+
return ret;
|
|
794
|
+
},
|
|
756
795
|
__wbg_parse_0fc53dead14b3b42: function() { return handleError(function (arg0, arg1) {
|
|
757
796
|
const ret = JSON.parse(getStringFromWasm0(arg0, arg1));
|
|
758
797
|
return ret;
|
|
759
798
|
}, arguments); },
|
|
799
|
+
__wbg_parse_33ce4953982abfa3: function() { return handleError(function (arg0) {
|
|
800
|
+
const ret = JSON.parse(arg0);
|
|
801
|
+
return ret;
|
|
802
|
+
}, arguments); },
|
|
760
803
|
__wbg_prototypesetcall_bc27214492979395: function(arg0, arg1, arg2) {
|
|
761
804
|
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
|
|
762
805
|
},
|
|
806
|
+
__wbg_push_2baf45db356cf468: function(arg0, arg1) {
|
|
807
|
+
const ret = arg0.push(arg1);
|
|
808
|
+
return ret;
|
|
809
|
+
},
|
|
763
810
|
__wbg_queueMicrotask_9833f9a49df95a49: function(arg0) {
|
|
764
811
|
const ret = arg0.queueMicrotask;
|
|
765
812
|
return ret;
|
|
@@ -792,7 +839,7 @@ function __wbg_get_imports() {
|
|
|
792
839
|
__wbg_respond_c102fabcc79e5ef0: function() { return handleError(function (arg0, arg1) {
|
|
793
840
|
arg0.respond(arg1 >>> 0);
|
|
794
841
|
}, arguments); },
|
|
795
|
-
|
|
842
|
+
__wbg_setTimeout_61cdece84a7288cf: function(arg0, arg1) {
|
|
796
843
|
const ret = setTimeout(arg0, arg1);
|
|
797
844
|
return ret;
|
|
798
845
|
},
|
|
@@ -807,6 +854,9 @@ function __wbg_get_imports() {
|
|
|
807
854
|
__wbg_set_575d3ddb70fe831d: function(arg0, arg1, arg2) {
|
|
808
855
|
arg0.set(getArrayU8FromWasm0(arg1, arg2));
|
|
809
856
|
},
|
|
857
|
+
__wbg_set_af5932e3f78b5648: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
|
858
|
+
arg0.set(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
|
|
859
|
+
}, arguments); },
|
|
810
860
|
__wbg_set_body_1fb0f1008bfc7df6: function(arg0, arg1) {
|
|
811
861
|
arg0.body = arg1;
|
|
812
862
|
},
|
|
@@ -900,17 +950,17 @@ function __wbg_get_imports() {
|
|
|
900
950
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
|
901
951
|
},
|
|
902
952
|
__wbindgen_generic_0000000000000001: function(arg0, arg1) {
|
|
903
|
-
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx:
|
|
953
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 220, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
|
904
954
|
const ret = makeMutClosure(arg0, arg1, wasm_bindgen_6b82e471f4a4091b___convert__closures_____invoke___wasm_bindgen_6b82e471f4a4091b___JsValue______true_);
|
|
905
955
|
return ret;
|
|
906
956
|
},
|
|
907
957
|
__wbindgen_generic_0000000000000002: function(arg0, arg1) {
|
|
908
|
-
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx:
|
|
958
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 340, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
|
909
959
|
const ret = makeMutClosure(arg0, arg1, wasm_bindgen_6b82e471f4a4091b___convert__closures_____invoke___wasm_bindgen_6b82e471f4a4091b___JsValue__core_37ee0ce0c4cd57d5___result__Result_____wasm_bindgen_6b82e471f4a4091b___JsError___true_);
|
|
910
960
|
return ret;
|
|
911
961
|
},
|
|
912
962
|
__wbindgen_generic_0000000000000003: function(arg0, arg1) {
|
|
913
|
-
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx:
|
|
963
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 185, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
|
914
964
|
const ret = makeMutClosure(arg0, arg1, wasm_bindgen_6b82e471f4a4091b___convert__closures_____invoke_______true_);
|
|
915
965
|
return ret;
|
|
916
966
|
},
|
package/rust_fetch_bg.wasm
CHANGED
|
Binary file
|