mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-24 06:14:01 +08:00
createInterface accepts history, historySize, removeHistoryDuplicates, completer, tabSize and escapeCodeTimeout, as Node does for a non-terminal interface: tabSize, escapeCodeTimeout and historySize are checked in the constructor's order before the interface opens (ERR_OUT_OF_RANGE and ERR_INVALID_ARG_VALUE with Node's messages), a completer that is not a function throws ERR_INVALID_ARG_VALUE, and the values are kept on the interface. Options may be written as shorthand properties. rl.history answers the history option itself, or the interface's own empty array, and historySize, historyIndex, crlfDelay, tabSize, escapeCodeTimeout, line and terminal read as in Node. 'history' listeners can be registered; without terminal mode Node records no history, so they never fire.
50 lines
2.3 KiB
TypeScript
50 lines
2.3 KiB
TypeScript
/* The options-record stance's FENCE half (the accept-and-drop half is
|
|
* corpus 1750/1751): every key typechecks against the widened fallback
|
|
* declarations, and the option walks fence BY NAME — documented keys the
|
|
* compiler cannot honor, value shapes it cannot lower, and effectful
|
|
* values on keys Node would ignore but still evaluate. Never a generic
|
|
* excess-property error. */
|
|
import * as http from "node:http";
|
|
import * as tls from "node:tls";
|
|
import * as fs from "node:fs";
|
|
|
|
// The Agent lowers to a checked-dynamic handle now — but only from a
|
|
// LITERAL options object; a runtime options value cannot be walked.
|
|
const agentOpts: http.AgentOptions = { maxSockets: 1 };
|
|
const agent = new http.Agent(agentOpts);
|
|
http.get({ port: 80, agent }, () => {});
|
|
|
|
// agent: false needs a LITERAL headers object to inject Connection: close
|
|
// into; a record variable cannot be checked for a user connection header.
|
|
const dynHeaders: Record<string, string> = { "x-a": "1" };
|
|
http.get({ port: 80, agent: false, headers: dynHeaders }, () => {});
|
|
|
|
// Documented client options with no lowering fence by name.
|
|
http.get({ port: 80, socketPath: "/tmp/sock.s" }, () => {});
|
|
http.get({ port: 80, localAddress: "127.0.0.1" }, () => {});
|
|
|
|
// An UNDOCUMENTED key Node would ignore — but Node still evaluates the
|
|
// value, so an effectful one cannot silently drop.
|
|
function effect(): number {
|
|
console.log("observed");
|
|
return 1;
|
|
}
|
|
http.get({ port: 80, zorp: effect() }, () => {});
|
|
|
|
// Documented TLS server options with no lowering fence by name.
|
|
tls.createServer({ cert: "c", key: "k", ciphers: "TLS_AES_128_GCM_SHA256" }, () => {});
|
|
tls.createServer({ cert: "c", key: "k", ticketKeys: new Uint8Array(48) }, () => {});
|
|
|
|
// fs.watch: the options that would CHANGE behavior fence by name; the
|
|
// stated defaults are accepted (corpus 1751).
|
|
fs.watch("/tmp", { recursive: true }, () => {});
|
|
fs.watch("/tmp", { persistent: false }, () => {});
|
|
|
|
|
|
// A bare __proto__: value entry is not an ordinary undocumented key: it
|
|
// changes the options record's prototype, and Node reads inherited options.
|
|
// These must fence instead of dropping an inherited flag or mode without a diagnostic.
|
|
fs.writeFileSync("/tmp/proto-sync", "x", { __proto__: { flag: "a" } });
|
|
void fs.promises.writeFile("/tmp/proto-promise", "x", { __proto__: { mode: 0o600 } });
|
|
// Both calls must terminate in the explicit prototype-options fence.
|