A minimal, synchronous HTTP client built into the default library, modeled after the
web-standard fetch() API.
function fetch(url: string, init?: {
method?: string,
headers?: [string, string][],
body?: string
}): Response;
class Headers {
constructor(init?: [string, string][]);
static parse(rawHeaders: string): Headers;
append(name: string, value: string): void;
set(name: string, value: string): void;
get(name: string): string;
has(name: string): boolean;
delete(name: string): void;
toRawString(): string;
}
class Response {
status: int;
headers: Headers;
get ok(): boolean; // true for 2xx status codes
text(): string;
json(): any; // TODO: parses nothing yet, returns the raw body
}const response = fetch("http://example.com/");
if (response.ok) {
console.log(response.text());
}
const posted = fetch("http://example.com/api", {
method: "POST",
headers: [["Content-Type", "application/json"]],
body: '{"hello":"world"}'
});- Synchronous, not
async.fetchis a plain function, notasync function fetch(): Response. The compiler's async lowering currently fails (failed to legalize operation 'async.runtime.load') when anasync functionreturns a class-typed value, soawait fetch(...)isn't usable yet. Revisit once that compiler limitation is fixed. Headersstores entries as two parallel arrays (names/values), not aMap. AMap<string, string>field triggered an unrelated linker issue (duplicateHeaders..sizeCOMDAT symbols) when a program usingHeaderswas compiled and linked against the static default lib. Parallel arrays sidestep it; header lists are always small, so the O(n) lookup cost is negligible.json()doesn't parse JSON yet — there's noJSON.parsein the default lib. It currently just returns the raw body text.
Native networking lives in src/wrappers/:
- Windows (
http.cpp): uses WinHTTP. Strings are converted UTF-8 ↔ UTF-16 at the WinHTTP boundary only; everywhere else in the runtime, strings are narrow/UTF-8 (seelib.win32.ts's CRT bindings for the established convention). - Linux (
http_linux.cpp): uses libcurl (-lcurl).
Both expose the same extern "C" surface (declared in src/native/lib.native.d.ts):
http_request, http_response_success, http_response_error_code,
http_response_status, http_response_headers_length /
http_response_headers_copy_to, http_response_body_length /
http_response_body_copy_to, http_response_free. fetch() in src/lib.ts wraps
these into the Headers/Response classes.
Building the default lib in release mode initially crashed Headers.parse() with a
segfault on realistic multi-header input, while the identical code worked in debug
builds. Root cause: MLIR's generic CSE pass ran on the ts dialect before allocation
calls were lowered, and ts.Cast (the op that materializes a fresh heap allocation
when casting an empty-array literal to a heap-backed array type) was incorrectly
marked Pure. Two structurally-identical casts — one per class field initialized to
[] in a constructor — got merged into one, aliasing the two fields' backing arrays.
Fixed upstream in TypeScriptCompiler (commit 795fbe0e, "Fix root cause of
GC_malloc CSE bug: CastOp was incorrectly marked Pure"), with a regression test at
tslang/test/tester/tests/gc_malloc_cse_o3.ts.