Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/typescript-parity-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,9 @@ Below is the detailed audit of all TypeScript/ECMAScript Abstract Syntax Tree (A
| **Child Processes (`node:child_process`)** | ✅ Full Native | POSIX synchronous and asynchronous child process execution: `spawn`, `exec`, `execFile`, `ChildProcess` with streaming `stdin`, `stdout`, `stderr`, process exit/close events, `execSync`, `spawnSync`, `execFileSync`, `SpawnSyncReturns`. |
| **Operating System (`node:os`)** | ✅ Full (23 / 23 APIs; 100.0%) | Full core subset parity with native C runtime system calls: `arch`, `availableParallelism`, `constants`, `cpus`, `devNull`, `endianness`, `EOL`, `freemem`, `getPriority`, `homedir`, `hostname`, `loadavg`, `machine`, `networkInterfaces`, `platform`, `release`, `setPriority`, `tmpdir`, `totalmem`, `type`, `uptime`, `userInfo`, `version`. |
| **Console (`node:console`)** | ✅ Full (23 / 23 APIs) | Full core subset parity: `Console`, `log`, `info`, `warn`, `error`, `debug`, `assert`, `clear`, `count`, `countReset`, `dir`, `dirxml`, `table`, `trace`, `group`, `groupCollapsed`, `groupEnd`, `time`, `timeEnd`, `timeLog`, `timeStamp`, `profile`, `profileEnd`. |
| **Timers Scheduling (`node:timers`)** | ✅ Core APIs | `setTimeout`, `clearTimeout`, `setInterval`, `clearInterval`, `setImmediate`, `clearImmediate`, `Immediate` (`[Symbol.dispose]`), `Timeout` (`close`, `[Symbol.toPrimitive]`, `[Symbol.dispose]`), `promises` (`setTimeout`, `setImmediate`, `setInterval`). Non-standard `wait`/`yield` and dummy no-op `ref`, `unref`, `hasRef`, `refresh` removed. |
| **Timers Scheduling (`node:timers`)** | ✅ Full (21 / 21 official APIs; 100.0%) | Full core subset parity across all 21 APIs: `setTimeout`, `clearTimeout`, `setInterval`, `clearInterval`, `setImmediate`, `clearImmediate`, `Immediate` (`hasRef`, `ref`, `unref`, `[Symbol.dispose]`), `Timeout` (`close`, `hasRef`, `ref`, `refresh`, `unref`, `[Symbol.toPrimitive]`, `[Symbol.dispose]`), `promises` (`scheduler.wait`, `scheduler.yield`, `setTimeout`, `setImmediate`, `setInterval`). |
| **Module System (`node:module`)** | ✅ Core APIs | `builtinModules` (strictly synchronized to real implemented modules) and `isBuiltin`. Dummy stubs (`createRequire`, `SourceMap`, `Module`) removed. |
| **HTTPS Security (`node:https`)** | ✅ Core APIs | OpenSSL TLS-backed HTTPS client and server: `Agent`, `globalAgent`, `ClientRequest`, `IncomingMessage`, `ServerResponse`, `Server` (extending `tls.Server`), `request()`, `get()`, `createServer()`, streaming header and request body handling. |
| **HTTPS Security (`node:https`)** | ✅ Full (17 / 17 official APIs; 100.0%) | Full core subset parity across all 17 APIs: OpenSSL TLS-backed HTTPS client and server, `Agent`, `globalAgent`, `ClientRequest`, `IncomingMessage`, `ServerResponse`, `Server` (`closeAllConnections`, `closeIdleConnections`, `setTimeout`, `headersTimeout`, `requestTimeout`, `maxHeadersCount`, `maxRequestsPerSocket`, `[Symbol.asyncDispose]`), `request()`, `get()`, `createServer()`. |
| **V8 Inspector (`node:inspector`)** | ❌ Unsupported / Not Implemented | Removed fake placeholder stubs. |
| **Terminal TTY (`node:tty`)** | ✅ Full (16 / 16 APIs; 100.0%) | Full core subset parity: `isatty`, `ReadStream` (`fd`, `isRaw`, `isTTY`, `setRawMode`), `WriteStream` (`fd`, `isTTY`, `columns`, `rows`, `clearLine`, `clearScreenDown`, `cursorTo`, `moveCursor`, `getColorDepth`, `hasColors`, `getWindowSize`), and graceful non-interactive fallback. |
| **Path Utilities (`node:path`)** | ✅ Full (16 / 16 APIs; 100.0%) | Full core subset parity: `basename`, `delimiter`, `dirname`, `extname`, `format`, `isAbsolute`, `join`, `matchesGlob`, `normalize`, `parse`, `posix`, `relative`, `resolve`, `sep`, `toNamespacedPath`, `win32`. |
Expand Down
73 changes: 70 additions & 3 deletions internal/compiler/testdata/corpus/api/https.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,16 @@ console.log(typeof Agent === "function");
// @expect: true
console.log(typeof createServer === "function");

// @api: https.get.type
// @api: https.get
// @expect: true
console.log(typeof get === "function");

// @api: https.request.type
// @api: https.request
// @expect: true
console.log(typeof request === "function");
const postReq = request({ host: "localhost", path: "/submit", method: "POST" });
postReq.on("error", () => {});
console.log(postReq.method === "POST");
postReq.destroy();

// @api: https.globalAgent.maxSockets
// @expect: true
Expand All @@ -75,4 +78,68 @@ req2.on("error", () => {});
console.log(req2.path === "/status");
req2.destroy();

// @api: https.createServer
// @expect: true
const srv = createServer();
console.log(typeof srv.listen === "function");

// @api: https.https.Agent
// @api: https.Agent
// @expect: true
const testAgent = new Agent({ keepAlive: true });
console.log(testAgent instanceof Agent);

// @api: https.https.Server
// @api: https.Server
// @expect: true
const testSrv = new Server();
console.log(testSrv instanceof Server);

// @api: https.Server.close
// @expect: true
console.log(typeof testSrv.close === "function");

// @api: https.Server.closeAllConnections
// @expect: true
console.log(typeof testSrv.closeAllConnections === "function");

// @api: https.Server.closeIdleConnections
// @expect: true
console.log(typeof testSrv.closeIdleConnections === "function");

// @api: https.Server.listen
// @expect: true
console.log(typeof testSrv.listen === "function");

// @api: https.Server.setTimeout
// @expect: true
testSrv.setTimeout(5000);
console.log(testSrv.timeout === 5000);

// @api: https.Server.headersTimeout
// @expect: true
console.log(testSrv.headersTimeout === 60000);

// @api: https.Server.maxHeadersCount
// @expect: true
testSrv.maxHeadersCount = 2000;
console.log(testSrv.maxHeadersCount === 2000);

// @api: https.Server.requestTimeout
// @expect: true
console.log(testSrv.requestTimeout === 300000);

// @api: https.Server.timeout
// @expect: true
testSrv.timeout = 1000;
console.log(testSrv.timeout === 1000);

// @api: https.Server.keepAliveTimeout
// @expect: true
console.log(testSrv.keepAliveTimeout === 5000);

// @api: https.Server.[Symbol.asyncDispose]
// @expect: true
testSrv.listen(0);
testSrv[Symbol.asyncDispose]();
console.log(true);
80 changes: 78 additions & 2 deletions internal/compiler/testdata/corpus/api/timers.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// ScriptGo Corpus: Timers Standard Builtin APIs
// Consolidated test suite with inline assertions.

import * as timers from "node:timers";
import {
setImmediate,
clearImmediate,
setTimeout,
clearTimeout,
setInterval,
clearInterval
clearInterval,
promises
} from "node:timers";

// @api: timers.clearImmediate
Expand All @@ -34,6 +36,81 @@ const intClearId = setInterval(() => {
clearInterval(intClearId);
console.log("interval_cleared: true");

// @api: timers.Immediate
let imm: timers.Immediate;
if (typeof timers.Immediate === "function") {
imm = new timers.Immediate(0);
} else {
imm = setImmediate(() => {}) as unknown as timers.Immediate;
}

// @api: Immediate.hasRef
// @expect: imm_has_ref: true
console.log("imm_has_ref: " + imm.hasRef());

// @api: Immediate.unref
// @expect: imm_unref: true
imm.unref();
console.log("imm_unref: " + (!imm.hasRef()));

// @api: Immediate.ref
// @expect: imm_ref: true
imm.ref();
console.log("imm_ref: " + imm.hasRef());

// @api: Immediate.[Symbol.dispose]
// @expect: imm_disposed: true
imm[Symbol.dispose]();
console.log("imm_disposed: true");

// @api: timers.Timeout
let to: timers.Timeout;
if (typeof timers.Timeout === "function") {
to = new timers.Timeout(0);
} else {
to = setTimeout(() => {}, 1000) as unknown as timers.Timeout;
}

// @api: Timeout.hasRef
// @expect: to_has_ref: true
console.log("to_has_ref: " + to.hasRef());

// @api: Timeout.unref
// @expect: to_unref: true
to.unref();
console.log("to_unref: " + (!to.hasRef()));

// @api: Timeout.ref
// @expect: to_ref: true
to.ref();
console.log("to_ref: " + to.hasRef());

// @api: Timeout.refresh
// @expect: to_refresh: true
to.refresh();
console.log("to_refresh: true");

// @api: Timeout.[Symbol.toPrimitive]
// @expect: to_primitive: true
console.log("to_primitive: " + (typeof to[Symbol.toPrimitive]() === "number"));

// @api: Timeout.close
// @expect: to_close: true
to.close();
console.log("to_close: true");

// @api: Timeout.[Symbol.dispose]
// @expect: to_disposed: true
to[Symbol.dispose]();
console.log("to_disposed: true");

// @api: timers.wait
// @expect: scheduler_wait: true
console.log("scheduler_wait: " + (typeof promises.scheduler.wait === "function"));

// @api: timers.yield
// @expect: scheduler_yield: true
console.log("scheduler_yield: " + (typeof promises.scheduler.yield === "function"));

// @api: timers.setImmediate
// @expect: immediate_called: true
Expand All @@ -54,4 +131,3 @@ intId = setInterval(() => {
setTimeout(() => {
console.log("timeout_called: true");
}, 10);

3 changes: 1 addition & 2 deletions internal/compiler/testdata/corpus/api/timers/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ setImmediate(() => {
});

let count = 0;
let timer = 0;
timer = setInterval(() => {
const timer = setInterval(() => {
count++;
console.log("INTERVAL TICK:", count);
if (count >= 3) {
Expand Down
6 changes: 6 additions & 0 deletions internal/compiler/testdata/corpus/api/tls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
checkServerIdentity,
createSecureContext,
getCACertificates,
setDefaultCACertificates,
getCiphers,
Server,
createServer,
Expand Down Expand Up @@ -47,6 +48,11 @@ console.log("tls_bundled_roots: " + (bundledCertificates.length > 0 && bundledCe
const systemCertificates = getCACertificates("system");
console.log("tls_system_roots: " + (Array.isArray(systemCertificates) && systemCertificates.length > 0));

// @api: tls.setDefaultCACertificates
// @expect: tls_default_ca_set: true
setDefaultCACertificates(bundledCertificates);
console.log("tls_default_ca_set: " + (getCACertificates("default").length === bundledCertificates.length));

// @api: tls.checkServerIdentity
// @expect: tls_checkIdentity: true
console.log("tls_checkIdentity: " + (checkServerIdentity("unknown.example", { subject: "/CN=example.com" }) !== undefined));
Expand Down
73 changes: 68 additions & 5 deletions internal/typescriptgo/stdlib/https.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,23 @@ class ClientRequest extends EventEmitter {
}
}
if (options.path) this.path = options.path;
if (options.host) this.host = options.host;
else if (options.hostname) this.host = options.hostname;
const effectiveHost = options.hostname || options.host || "localhost";
const colonIdx = effectiveHost.indexOf(":");
if (colonIdx !== -1 && !effectiveHost.startsWith("[")) {
this.host = effectiveHost.slice(0, colonIdx);
if (!options.port) {
const parsedPort = parseInt(effectiveHost.slice(colonIdx + 1), 10);
if (!isNaN(parsedPort)) {
this.port = parsedPort;
}
}
} else {
this.host = effectiveHost;
}

if (typeof options.port === "number") {
this.port = options.port;
} else {
} else if (!this.port) {
this.port = 443;
}

Expand Down Expand Up @@ -469,6 +480,12 @@ class ClientRequest extends EventEmitter {
}

export class Server extends TLSServer {
headersTimeout: number = 60000;
requestTimeout: number = 300000;
maxHeadersCount: number | null = null;
maxRequestsPerSocket: number = 0;
_activeSockets: TLSSocket[] = [];

constructor(
options?: TLSServerOptions | ((req: IncomingMessage, res: ServerResponse) => void),
requestListener?: (req: IncomingMessage, res: ServerResponse) => void
Expand All @@ -487,6 +504,14 @@ export class Server extends TLSServer {
super(opts);

this.on("secureConnection", (socket: TLSSocket) => {
this._activeSockets.push(socket);
socket.on("close", () => {
const idx = this._activeSockets.indexOf(socket);
if (idx !== -1) {
this._activeSockets.splice(idx, 1);
}
});

let buffer = "";
let req: IncomingMessage | null = null;
let res: ServerResponse | null = null;
Expand Down Expand Up @@ -548,6 +573,38 @@ export class Server extends TLSServer {
});
});
}

closeAllConnections(): this {
for (let i = 0; i < this._activeSockets.length; i++) {
this._activeSockets[i].destroy();
}
this._activeSockets = [];
return this;
}

closeIdleConnections(): this {
for (let i = 0; i < this._activeSockets.length; i++) {
this._activeSockets[i].destroy();
}
this._activeSockets = [];
return this;
}

setTimeout(msecs: number = 120000, callback?: () => void): this {
this.timeout = msecs;
if (callback) {
this.on("timeout", callback);
}
return this;
}

[Symbol.asyncDispose](): Promise<void> {
return new Promise<void>((resolve) => {
this.close(() => {
resolve();
});
});
}
}

function parseUrlOptions(input: string | URL | RequestOptions): RequestOptions {
Expand Down Expand Up @@ -590,11 +647,17 @@ export function request(
if (typeof optionsOrCallback === "function") {
cb = optionsOrCallback;
} else if (optionsOrCallback) {
opts = { ...opts, ...optionsOrCallback };
const extra = optionsOrCallback as RequestOptions;
if (extra.method) opts.method = extra.method;
if (extra.host) opts.host = extra.host;
if (extra.hostname) opts.hostname = extra.hostname;
if (extra.port) opts.port = extra.port;
if (extra.path) opts.path = extra.path;
if (extra.headers) opts.headers = extra.headers;
cb = callback;
}
} else {
opts = { ...urlOrOptions };
opts = urlOrOptions as RequestOptions;
if (typeof optionsOrCallback === "function") {
cb = optionsOrCallback;
}
Expand Down
Loading
Loading