mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-02 00:25:34 +08:00
fix: support static URL port and hash getters (#383)
- Lower URL.port and URL.hash through both native backends with Node-compatible values. - Add differential and typed-project coverage, and update compatibility evidence and docs. Fixes #372 Co-authored-by: Hagege Ruben <20857346+HagegeR@users.noreply.github.com>
This commit is contained in:
co-authored by
Hagege Ruben
parent
72ebac8659
commit
e12856c1b4
@@ -36,7 +36,7 @@ const results = await Promise.all(jobs); // number[] — compiles
|
||||
- CommonJS module metadata (`module.id`, `filename`, `path`, `paths`, `loaded`, `isPreloading`, `parent`, `children`, `require.main`, and read-only `require.cache` lookup/enumeration) compiles natively. A compiled binary has a fixed module graph, so cache deletion/reloading, metadata writes, `module.paths` mutation, and `require.extensions` remain explicit refusals.
|
||||
- The type checker sees the full standard library; only the supported surface compiles. Reaching declared-but-unlowered surface is SC2020 with the supported alternatives in the hint — e.g. parts of the regex API (`re.exec`), `Symbol`, `globalThis`, array/Map/Set methods beyond the lowered sets.
|
||||
- `Date` values support zero-argument construction, one number/string argument, storage and passing, `getTime`/`valueOf`, `toISOString`, the local and UTC calendar getters, and `getTimezoneOffset`. `Date.parse(dateString)` accepts one string using the same bounded parser as `new Date(dateString).getTime()`. Date-armed unions, the year/month field constructor, setters, identity comparisons, throwing `Date` values, and locale/string formatters remain fenced; the supported string grammar is described below.
|
||||
- `URL` supports construction from one absolute string and read-only `protocol`, `origin`, `username`, `pathname`, `href`, `host`, `hostname`, and `search` getters. `searchParams` remains a live view. Relative inputs with a base argument and setters remain fenced.
|
||||
- `URL` supports construction from one absolute string and read-only `protocol`, `origin`, `username`, `pathname`, `href`, `host`, `hostname`, `port`, `search`, and `hash` getters. `searchParams` remains a live view. Relative inputs with a base argument and setters remain fenced.
|
||||
- Numeric `process.exitCode = value` writes in statement position set the implicit exit status; `process.exit()` with no argument uses that status. Reading or resetting `process.exitCode`, and assignments used as values, remain fenced.
|
||||
- Map keys and Set elements are strings and numbers; other key types are fenced.
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"schemaVersion": 3,
|
||||
"nodeVersion": "24.15.0",
|
||||
"nodeCommit": "848430679556aed0bd073f2bc263331ad84fa119",
|
||||
"artifactVersion": "55356b7c091f54d5fd72",
|
||||
"artifactVersion": "bbbe77bce52b68292e6d",
|
||||
"rowCount": 3662
|
||||
}
|
||||
|
||||
@@ -1178,9 +1178,9 @@
|
||||
"apiEntries": 62,
|
||||
"static": {
|
||||
"supported": 0,
|
||||
"partial": 3,
|
||||
"partial": 5,
|
||||
"refused": 0,
|
||||
"not-implemented": 59,
|
||||
"not-implemented": 57,
|
||||
"by-design": 0,
|
||||
"unreviewed": 0,
|
||||
"not-applicable": 0
|
||||
@@ -82518,9 +82518,9 @@
|
||||
"inherited": true
|
||||
},
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"detail": "No static compiler lowering is registered for this API yet.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented scriptc module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
@@ -82714,9 +82714,9 @@
|
||||
"inherited": true
|
||||
},
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"detail": "No static compiler lowering is registered for this API yet.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented scriptc module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
"tiers": {
|
||||
"static": {
|
||||
"replace-refusal": 46,
|
||||
"verify-gap": 2705,
|
||||
"audit-partial": 461,
|
||||
"verify-gap": 2703,
|
||||
"audit-partial": 463,
|
||||
"classify": 2,
|
||||
"implement": 81
|
||||
},
|
||||
@@ -90987,12 +90987,14 @@
|
||||
"priority": "high",
|
||||
"tiers": {
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "compiler-unmatched:url",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "compiler-feature:url.hash",
|
||||
"tests": [
|
||||
"tests/corpus/2946-url-port-hash.ts"
|
||||
]
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
@@ -91218,12 +91220,14 @@
|
||||
"priority": "high",
|
||||
"tiers": {
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "compiler-unmatched:url",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "compiler-feature:url.port",
|
||||
"tests": [
|
||||
"tests/corpus/2946-url-port-hash.ts"
|
||||
]
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
|
||||
@@ -1299,9 +1299,9 @@
|
||||
"apiEntries": 62,
|
||||
"static": {
|
||||
"supported": 0,
|
||||
"partial": 3,
|
||||
"partial": 5,
|
||||
"refused": 0,
|
||||
"not-implemented": 59,
|
||||
"not-implemented": 57,
|
||||
"by-design": 0,
|
||||
"unreviewed": 0,
|
||||
"not-applicable": 0
|
||||
@@ -107770,7 +107770,8 @@
|
||||
"status": "partial",
|
||||
"evidence": "derived:descendants",
|
||||
"tests": [
|
||||
"tests/corpus/1794-searchparams-url-live.ts"
|
||||
"tests/corpus/1794-searchparams-url-live.ts",
|
||||
"tests/corpus/2946-url-port-hash.ts"
|
||||
]
|
||||
},
|
||||
"dynamic": {
|
||||
@@ -108091,8 +108092,11 @@
|
||||
"inherited": true
|
||||
},
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "compiler-unmatched:url"
|
||||
"status": "partial",
|
||||
"evidence": "compiler-feature:url.hash",
|
||||
"tests": [
|
||||
"tests/corpus/2946-url-port-hash.ts"
|
||||
]
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
@@ -108280,8 +108284,11 @@
|
||||
"inherited": true
|
||||
},
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "compiler-unmatched:url"
|
||||
"status": "partial",
|
||||
"evidence": "compiler-feature:url.port",
|
||||
"tests": [
|
||||
"tests/corpus/2946-url-port-hash.ts"
|
||||
]
|
||||
},
|
||||
"dynamic": {
|
||||
"status": "not-implemented",
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
{ "chapter": "stream", "signatures": ["`writable` Type: {boolean}"], "status": "partial", "evidence": ["tests/corpus/2893-child-stdin-duplex.ts", "tests/corpus/2895-child-stdin-write-after-end.ts"] },
|
||||
{ "chapter": "stream", "signatures": ["Event: `'drain'`"], "status": "partial", "evidence": ["tests/corpus/2894-child-stdin-backpressure.ts"] },
|
||||
{ "chapter": "webstreams", "signatures": ["`readableStream.values([options])`"], "status": "partial", "evidence": ["tests/corpus/2862-web-readable-async-iteration.ts"] },
|
||||
{ "chapter": "url", "signatures": ["`hash` Type: {string}", "`port` Type: {string}"], "status": "partial", "evidence": ["tests/corpus/2946-url-port-hash.ts"] },
|
||||
{ "chapter": "util", "signatures": ["`util.promisify(original)`"], "status": "partial", "evidence": ["tests/corpus/1473-promisify-execfile.ts", "tests/corpus/1573-promisify-execfile-env-spread.ts", "tests/corpus/2912-promisify-fs-readfile.ts"] },
|
||||
{ "chapter": "typescript", "symbols": ["type"], "status": "supported", "evidence": ["tests/corpus/2702-type-import-link-static/main.ts", "tests/corpus/2703-type-import-link-static-reexport/main.ts", "tests/corpus/2704-type-import-link-static-success/main.ts", "tests/corpus/2707-type-import-link-static-default-reexport/main.ts", "tests/harness/errors.test.ts"] }
|
||||
],
|
||||
|
||||
+3
-1
@@ -1370,7 +1370,7 @@ declare module "node:os" {
|
||||
/* The WHATWG URL class (a Node global; the es2023 lib doesn't declare it),
|
||||
* typed as exactly the supported surface: construction from ONE absolute-
|
||||
* URL string (invalid input throws a catchable TypeError, like Node), the
|
||||
* protocol/origin/username/pathname/href/host/hostname/search getters, searchParams (the
|
||||
* protocol/origin/username/pathname/href/host/hostname/port/search/hash getters, searchParams (the
|
||||
* LIVE query view — mutations through it re-serialize into the URL, so
|
||||
* href reflects immediately; every read answers the same object, Node's
|
||||
* caching), and toString() (the href serialization).
|
||||
@@ -1388,7 +1388,9 @@ interface URL {
|
||||
readonly href: string;
|
||||
readonly host: string;
|
||||
readonly hostname: string;
|
||||
readonly port: string;
|
||||
readonly search: string;
|
||||
readonly hash: string;
|
||||
readonly searchParams: URLSearchParams;
|
||||
toString(): string;
|
||||
}
|
||||
|
||||
@@ -4958,6 +4958,8 @@ function emitPathUrlLibCall(state: LibCallState): Temp {
|
||||
return finish(`scr_url_host(${arg(0)})`);
|
||||
case "url.hostname":
|
||||
return finish(`scr_url_hostname(${arg(0)})`);
|
||||
case "url.port":
|
||||
return finish(`scr_url_port(${arg(0)})`);
|
||||
case "url.pathname":
|
||||
return finish(`scr_url_pathname(${arg(0)})`);
|
||||
case "url.href":
|
||||
@@ -4991,6 +4993,8 @@ function emitPathUrlLibCall(state: LibCallState): Temp {
|
||||
return finish(`scr_url_search_params(${arg(0)})`);
|
||||
case "url.search":
|
||||
return finish(`scr_url_search(${arg(0)})`);
|
||||
case "url.hash":
|
||||
return finish(`scr_url_hash(${arg(0)})`);
|
||||
case "sp.get": {
|
||||
// `string | null` — the sym.desc pattern with a null arm: the
|
||||
// runtime answers a +1 string or NULL.
|
||||
|
||||
@@ -328,9 +328,11 @@ export const LIB_FN_SYMS: Record<string, string> = {
|
||||
"url.username": "scr_url_username",
|
||||
"url.host": "scr_url_host",
|
||||
"url.hostname": "scr_url_hostname",
|
||||
"url.port": "scr_url_port",
|
||||
"url.pathname": "scr_url_pathname",
|
||||
"url.href": "scr_url_href",
|
||||
"url.search": "scr_url_search",
|
||||
"url.hash": "scr_url_hash",
|
||||
"url.searchParams": "scr_url_search_params",
|
||||
"url.fileURLToPathUrl": "scr_url_to_path",
|
||||
"url.fileURLToPathStr": "scr_url_str_to_path",
|
||||
|
||||
@@ -3431,7 +3431,7 @@ function lowerPromiseThenPresence(
|
||||
// a non-default port is present (scr_url_host — Node-exact,
|
||||
// opaque-path URLs answer ""); `hostname` is the stored port-less
|
||||
// host field verbatim, including IPv6 brackets.
|
||||
if (name === "protocol" || name === "origin" || name === "username" || name === "pathname" || name === "href" || name === "host" || name === "hostname" || name === "search") {
|
||||
if (name === "protocol" || name === "origin" || name === "username" || name === "pathname" || name === "href" || name === "host" || name === "hostname" || name === "port" || name === "search" || name === "hash") {
|
||||
const receiver = lowerer.lowerExpr(expr.expression);
|
||||
const fn =
|
||||
name === "protocol"
|
||||
@@ -3446,8 +3446,12 @@ function lowerPromiseThenPresence(
|
||||
? "url.host"
|
||||
: name === "hostname"
|
||||
? "url.hostname"
|
||||
: name === "port"
|
||||
? "url.port"
|
||||
: name === "search"
|
||||
? "url.search"
|
||||
: name === "hash"
|
||||
? "url.hash"
|
||||
: "url.href";
|
||||
return { kind: "libCall", fn, args: [receiver], type: STRING, loc: locOf(expr) };
|
||||
}
|
||||
@@ -3464,7 +3468,7 @@ function lowerPromiseThenPresence(
|
||||
lowerer.noLowering(
|
||||
`URL.${name}`,
|
||||
expr,
|
||||
"protocol, origin, username, pathname, href, host, hostname, search, searchParams, and toString() are the supported URL members",
|
||||
"protocol, origin, username, pathname, href, host, hostname, port, search, hash, searchParams, and toString() are the supported URL members",
|
||||
lowerer.checker.getSymbolAtLocation(expr.name),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2259,6 +2259,7 @@ export type IrLibFn =
|
||||
| "url.username"
|
||||
| "url.host"
|
||||
| "url.hostname"
|
||||
| "url.port"
|
||||
| "url.pathname"
|
||||
| "url.href"
|
||||
| "url.fileURLToPathUrl"
|
||||
@@ -2293,6 +2294,7 @@ export type IrLibFn =
|
||||
| "sp.with"
|
||||
| "url.searchParams"
|
||||
| "url.search"
|
||||
| "url.hash"
|
||||
| "sp.get"
|
||||
| "sp.getAll"
|
||||
| "sp.append"
|
||||
|
||||
@@ -294,6 +294,7 @@ export const LIB_FN_SIGS: Record<IrLibFn, { argTypes: (IrType | null)[]; result:
|
||||
"url.username": { argTypes: [URL_T], result: STRING },
|
||||
"url.host": { argTypes: [URL_T], result: STRING },
|
||||
"url.hostname": { argTypes: [URL_T], result: STRING },
|
||||
"url.port": { argTypes: [URL_T], result: STRING },
|
||||
"url.pathname": { argTypes: [URL_T], result: STRING },
|
||||
"url.href": { argTypes: [URL_T], result: STRING },
|
||||
"url.fileURLToPathUrl": { argTypes: [URL_T], result: STRING },
|
||||
@@ -309,6 +310,7 @@ export const LIB_FN_SIGS: Record<IrLibFn, { argTypes: (IrType | null)[]; result:
|
||||
"sp.with": { argTypes: [SEARCH_PARAMS_T, STRING, STRING], result: SEARCH_PARAMS_T },
|
||||
"url.searchParams": { argTypes: [URL_T], result: SEARCH_PARAMS_T },
|
||||
"url.search": { argTypes: [URL_T], result: STRING },
|
||||
"url.hash": { argTypes: [URL_T], result: STRING },
|
||||
// Result is the interned `string | null` union — the libCall case
|
||||
// checks the arms (the spawnRes.signal pattern).
|
||||
"sp.get": { argTypes: [SEARCH_PARAMS_T, STRING], result: VOID },
|
||||
|
||||
@@ -6504,6 +6504,12 @@
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/2946-url-port-hash.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/2946-url-port-hash.ts"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/300-if-else.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/300-if-else.ts"
|
||||
@@ -9311,6 +9317,12 @@
|
||||
"<repo>/tests/fixtures/node-types/stream-capture.ts"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/fixtures/node-types/url-getters.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/node-types/url-getters.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2932,6 +2932,7 @@ ScrStr *scr_url_origin(ScrUrl *u); /* +1 "https://host" or "null" */
|
||||
ScrStr *scr_url_username(ScrUrl *u); /* +1 encoded username, possibly empty */
|
||||
ScrStr *scr_url_host(ScrUrl *u); /* +1 "host[:port]" (defaults stripped) */
|
||||
ScrStr *scr_url_hostname(ScrUrl *u); /* +1 port-less host ("" when none) */
|
||||
ScrStr *scr_url_port(ScrUrl *u); /* +1 "" or normalized non-default port */
|
||||
ScrStr *scr_url_pathname(ScrUrl *u); /* +1 */
|
||||
ScrStr *scr_url_href(ScrUrl *u); /* +1; also toString() */
|
||||
ScrStr *scr_url_to_path(ScrUrl *u); /* +1, or throws */
|
||||
@@ -2971,6 +2972,7 @@ void *scr_sp_retain_v(void *p);
|
||||
void scr_sp_release_v(void *p);
|
||||
ScrSearchParams *scr_url_search_params(ScrUrl *u); /* +1 live cached view */
|
||||
ScrStr *scr_url_search(ScrUrl *u); /* +1 "?..." or "" */
|
||||
ScrStr *scr_url_hash(ScrUrl *u); /* +1 "#..." or "" */
|
||||
void scr_sp_append(ScrSearchParams *sp, ScrStr *name, ScrStr *value);
|
||||
void scr_sp_set(ScrSearchParams *sp, ScrStr *name, ScrStr *value);
|
||||
void scr_sp_delete(ScrSearchParams *sp, ScrStr *name);
|
||||
|
||||
@@ -653,6 +653,8 @@ ScrStr *scr_url_host(ScrUrl *u) {
|
||||
* authority-less URLs); IPv6 literals retain their brackets. */
|
||||
ScrStr *scr_url_hostname(ScrUrl *u) { return scr_str_retain(u->host); }
|
||||
|
||||
ScrStr *scr_url_port(ScrUrl *u) { return scr_str_retain(u->port); }
|
||||
|
||||
/* WHATWG origin is opaque for file and non-special schemes. A blob URL
|
||||
* inherits the origin of an embedded http(s) URL when its path parses. */
|
||||
ScrStr *scr_url_origin(ScrUrl *u) {
|
||||
@@ -1032,3 +1034,9 @@ ScrStr *scr_url_search(ScrUrl *u) {
|
||||
if (u->query->len <= 1) return scr_str_new("", 0);
|
||||
return scr_str_retain(u->query);
|
||||
}
|
||||
|
||||
/* A bare '#' remains in href but its hash getter is empty, like Node. */
|
||||
ScrStr *scr_url_hash(ScrUrl *u) {
|
||||
if (u->fragment->len <= 1) return scr_str_new("", 0);
|
||||
return scr_str_retain(u->fragment);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
const cases = [
|
||||
"https://example.com:443/path#",
|
||||
"https://example.com:8443/path#frag",
|
||||
"http://example.com:00080/path",
|
||||
"http://example.com:00081/a#x y",
|
||||
"ws://example.com:80/path#x",
|
||||
"wss://example.com:443/path#",
|
||||
"ftp://example.com:21/file#f",
|
||||
"file:///tmp/a#",
|
||||
"data:text/plain,hi#a#b",
|
||||
"foo://host:00042/p#%41",
|
||||
"https://[::1]:8080/a#é",
|
||||
];
|
||||
for (const source of cases) {
|
||||
const url = new URL(source);
|
||||
console.log(`<${url.port}>`, `<${url.hash}>`, url.host, url.href);
|
||||
}
|
||||
|
||||
const live = new URL("https://host.test:8443/path?q=1#frag");
|
||||
live.searchParams.set("q", "2");
|
||||
console.log(live.port, live.hash, live.search, live.href);
|
||||
Vendored
+4
-4
@@ -39,12 +39,12 @@ import { win32 } from "path";
|
||||
watchFile("x", () => {});
|
||||
console.log(cpus().length);
|
||||
console.log(win32.sep);
|
||||
/* URL members beyond the supported getters (protocol/pathname/href/
|
||||
* host/hostname/search/searchParams) fence member-qualified, with the
|
||||
* supported list; searchParams and its method surface LOWER under
|
||||
/* URL getters including port/hash lower under @types/node, but
|
||||
* unimplemented members still fence by member name with the
|
||||
* supported list; searchParams and its method surface lower under
|
||||
* @types/node's declarations (provenance-mapped like URL itself). */
|
||||
const u = new URL("https://example.com/x?a=1");
|
||||
console.log(u.hash);
|
||||
console.log(u.password);
|
||||
u.searchParams.get("a");
|
||||
/* The one-shot zlib/raw/gzip codecs lower for strings and Buffers;
|
||||
* explicit options remain fenced, while Brotli remains a member-qualified
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
const nonDefault = new URL("https://example.com:8443/path#frag");
|
||||
const defaultPort = new URL("https://example.com:443/path#");
|
||||
console.log(nonDefault.port, nonDefault.hash);
|
||||
console.log(`<${defaultPort.port}>`, `<${defaultPort.hash}>`, defaultPort.href);
|
||||
@@ -75,18 +75,18 @@ fenced.ts:41:13 - error SC2020: 'PlatformPath.sep' is typed by @types/node but h
|
||||
40 | console.log(cpus().length);
|
||||
41 | console.log(win32.sep);
|
||||
| ^~~~~~~~~
|
||||
42 | /* URL members beyond the supported getters (protocol/pathname/href/
|
||||
42 | /* URL getters including port/hash lower under @types/node, but
|
||||
|
||||
hint: the type checker sees everything @types/node declares, but only the supported surface compiles (https://scriptc.dev/limitations)
|
||||
|
||||
fenced.ts:47:13 - error SC2020: 'URL.hash' is typed by @types/node but has no scriptc lowering yet
|
||||
fenced.ts:47:13 - error SC2020: 'URL.password' is typed by @types/node but has no scriptc lowering yet
|
||||
|
||||
46 | const u = new URL("https://example.com/x?a=1");
|
||||
47 | console.log(u.hash);
|
||||
| ^~~~~~
|
||||
47 | console.log(u.password);
|
||||
| ^~~~~~~~~~
|
||||
48 | u.searchParams.get("a");
|
||||
|
||||
hint: protocol, origin, username, pathname, href, host, hostname, search, searchParams, and toString() are the supported URL members
|
||||
hint: protocol, origin, username, pathname, href, host, hostname, port, search, hash, searchParams, and toString() are the supported URL members
|
||||
|
||||
fenced.ts:53:21 - error SC2020: 'deflateSync with explicit options' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
|
||||
@@ -88,6 +88,24 @@ test("node-types: the supported process surface lowers statically under @types/n
|
||||
expect(stdout).toBe("2\nalpha\nbeta\nhi from env\nwritten without newline <- flushed in order\n");
|
||||
});
|
||||
|
||||
test("node-types: URL port and hash getters lower statically under @types/node", async () => {
|
||||
const outDir = outDirFor("node-url-getters");
|
||||
const entry = join(nodeTypesDir, "url-getters.ts");
|
||||
const result = await compile(entry, {
|
||||
outPath: join(outDir, "url-getters"),
|
||||
outDir,
|
||||
sanitize,
|
||||
});
|
||||
expect(result.ok, !result.ok ? JSON.stringify(result.diagnostics, null, 2) : "").toBe(true);
|
||||
if (!result.ok) return;
|
||||
const [native, node] = await Promise.all([
|
||||
execFileAsync(result.binaryPath),
|
||||
execFileAsync(process.execPath, [entry]),
|
||||
]);
|
||||
expect(native.stdout).toBe(node.stdout);
|
||||
expect(native.stderr).toBe(node.stderr);
|
||||
});
|
||||
|
||||
test("node-types: captured NodeJS.WritableStream values write through the procStream scalar", async () => {
|
||||
const outDir = outDirFor("node-stream-capture");
|
||||
const result = await compile(join(nodeTypesDir, "stream-capture.ts"), {
|
||||
|
||||
Reference in New Issue
Block a user