Skip to content

Commit fadf074

Browse files
committed
wip
1 parent 19e123e commit fadf074

File tree

6 files changed

+132
-8
lines changed

6 files changed

+132
-8
lines changed

examples/fetch.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const foo = async () => {
2+
const res = await fetch("https://developer.mozilla.org");
3+
console.log(res);
4+
};
5+
6+
foo();

runtime/src/ext/fetch/fetch/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
use andromeda_core::Extension;
6+
7+
#[derive(Default)]
8+
pub struct FetchExt;
9+
10+
impl FetchExt {
11+
pub fn new_extension() -> Extension {
12+
Extension {
13+
name: "fetch",
14+
ops: vec![],
15+
storage: None,
16+
files: vec![include_str!("./mod.ts")],
17+
}
18+
}
19+
}

runtime/src/ext/fetch/fetch/mod.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
/**
6+
* Implementation of the fetch API for Andromeda
7+
* Based on: https://developer.mozilla.org/ja/docs/Web/API/Window/fetch
8+
* Spec: https://fetch.spec.whatwg.org/#fetch-method/
9+
*/
10+
11+
type RequestInfo = Request | URL;
12+
13+
/** The fetch(input, init) method steps are: */
14+
const fetch = (input: RequestInfo, init = undefined) => {
15+
// 1. Let p be a new promise.
16+
let p = createDeferredPromise();
17+
18+
// 2. Let requestObject be the result of invoking the initial value
19+
// of Request as constructor with input and init as arguments.
20+
// If this throws an exception, reject p with it and return p.
21+
let request: any;
22+
23+
try {
24+
// 3. Let request be requestObject’s request.
25+
// @ts-ignore deno lint stuff
26+
request = new Request(input, init);
27+
} catch (e) {
28+
p.reject(e);
29+
return p.promise;
30+
}
31+
32+
// 4. If requestObject’s signal is aborted, then:
33+
if (request.signal.aborted) {
34+
// 1. Abort the fetch() call with p, request, null, and
35+
// requestObject’s signal’s abort reason.
36+
//
37+
// TODO: abortFetch
38+
//
39+
// 2. Return p.
40+
return p.promise;
41+
}
42+
43+
// 5. Let globalObject be request’s client’s global object.
44+
const globalObject = request.client.globalObject;
45+
46+
// 6. If globalObject is a ServiceWorkerGlobalScope object,
47+
// then set request’s service-workers mode to "none".
48+
if (globalObject?.constructor?.name === "ServiceWorkerGlobalScope") {
49+
request.serviceWorkers = "none";
50+
}
51+
52+
// 7. Let responseObject be null.
53+
let responseObject = null;
54+
55+
// 8. Let relevantRealm be this’s relevant realm.
56+
// 9. Let locallyAborted be false.
57+
// NOTE: This lets us reject promises with predictable timing,
58+
// when the request to abort comes from the same thread as
59+
// the call to fetch.
60+
let locallyAborted = false;
61+
62+
// 10. Let controller be null.
63+
let controller = null;
64+
65+
// TODO: abort controller
66+
// 11. Add the following abort steps to requestObject’s signal:
67+
// 1. Set locallyAborted to true.
68+
// 2. Assert: controller is non-null.
69+
// 3. Abort controller with requestObject’s signal’s abort reason.
70+
// 4. Abort the fetch() call with p, request, responseObject,
71+
// and requestObject’s signal’s abort reason.
72+
73+
// 12. Set controller to the result of calling fetch given request
74+
// and processResponse given response being these steps:
75+
// 1. If locallyAborted is true, then abort these steps.
76+
// 2. If response’s aborted flag is set, then:
77+
// 1. Let deserializedError be the result of deserialize a serialized abort reason given controller’s serialized abort reason and relevantRealm.
78+
// 2. Abort the fetch() call with p, request, responseObject, and deserializedError.
79+
// 3. Abort these steps.
80+
// 3. If response is a network error, then reject p with a TypeError and abort these steps.
81+
// 4. Set responseObject to the result of creating a Response object, given response, "immutable", and relevantRealm.
82+
// 5. Resolve p with responseObject.
83+
84+
// 13. Return p.
85+
return p;
86+
};
87+
88+
(globalThis as unknown as { fetch: typeof fetch }).fetch = fetch;
89+
90+
function createDeferredPromise() {
91+
let res: any;
92+
let rej: any;
93+
const promise = new Promise((resolve, reject) => {
94+
res = resolve;
95+
rej = reject;
96+
});
97+
98+
return { promise, resolve: res, reject: rej };
99+
}

runtime/src/ext/fetch/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5+
mod fetch;
56
mod headers;
67
mod request;
78
mod response;
89

10+
pub use fetch::*;
911
pub use headers::*;
1012
pub use request::*;
1113
pub use response::*;

runtime/src/ext/fetch/request/mod.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@ class Request {
103103
[bodySymbol]: any = null;
104104

105105
/** https://fetch.spec.whatwg.org/#request-class */
106-
constructor(input: RequestInfo, init: RequestInit = { __proto__: null } as any) {
106+
constructor(
107+
input: RequestInfo,
108+
init: RequestInit = { __proto__: null } as any,
109+
) {
107110
// 1. Let request be null.
108111
let request: any = null;
109112

@@ -396,13 +399,6 @@ class Request {
396399
// 42. Set this’s request’s body to finalBody.
397400
request.body = finalBody;
398401

399-
const url = request.url;
400-
console.log("url", url);
401-
const method = request.method;
402-
console.log("method", method);
403-
const credentials = request.credentials;
404-
console.log("credentials", credentials);
405-
406402
this[requestSymbol] = request;
407403
}
408404

runtime/src/recommended.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use nova_vm::ecmascript::execution::agent::{GcAgent, RealmRoot};
88
use crate::{
99
//BroadcastChannelExt,
1010
ConsoleExt,
11+
FetchExt,
1112
FsExt,
1213
HeadersExt,
1314
ProcessExt,
@@ -31,6 +32,7 @@ pub fn recommended_extensions() -> Vec<Extension> {
3132
// BroadcastChannelExt::new_extension(),
3233
RequestExt::new_extension(),
3334
ResponseExt::new_extension(),
35+
FetchExt::new_extension(),
3436
#[cfg(feature = "canvas")]
3537
crate::CanvasExt::new_extension(),
3638
#[cfg(feature = "crypto")]

0 commit comments

Comments
 (0)