@fedify/vocab-runtime 2.3.11-dev.2280 → 2.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deno.json +2 -2
- package/dist/mod.cjs +91 -4
- package/dist/mod.d.cts +30 -2
- package/dist/mod.d.ts +30 -2
- package/dist/mod.js +91 -5
- package/dist/tests/{body-Bkseh1QO.mjs → body-Cfk4XwBC.mjs} +1 -1
- package/dist/tests/{body-DuDpNk3l.cjs → body-kujxx7yw.cjs} +1 -1
- package/dist/tests/body.test.cjs +1 -1
- package/dist/tests/body.test.mjs +1 -1
- package/dist/tests/decimal.test.cjs +3 -2
- package/dist/tests/decimal.test.mjs +3 -2
- package/dist/tests/{docloader-BHCG9eDn.mjs → docloader-BeuDl5a0.mjs} +43 -3
- package/dist/tests/{docloader-56AWfLMh.cjs → docloader-Bx_LR9xG.cjs} +43 -3
- package/dist/tests/docloader.test.cjs +168 -43
- package/dist/tests/docloader.test.mjs +158 -34
- package/dist/tests/{langstr-DDLc4833.mjs → langstr-ABdAOKlF.mjs} +5 -2
- package/dist/tests/{langstr-BOQHfJDr.cjs → langstr-BsqFJupv.cjs} +5 -2
- package/dist/tests/langstr.test.cjs +8 -1
- package/dist/tests/langstr.test.mjs +9 -2
- package/dist/tests/langtag-DgySESmk.cjs +50 -0
- package/dist/tests/langtag-LDBqlxHv.mjs +45 -0
- package/dist/tests/langtag.test.cjs +46 -0
- package/dist/tests/langtag.test.d.cts +1 -0
- package/dist/tests/langtag.test.d.mts +1 -0
- package/dist/tests/langtag.test.mjs +46 -0
- package/dist/tests/multibase/multibase.test.cjs +7 -7
- package/dist/tests/multibase/multibase.test.mjs +5 -5
- package/dist/tests/{request-DWyJcJ_e.mjs → request-D6bjY2cF.mjs} +1 -1
- package/dist/tests/{request-CVg2A6dZ.cjs → request-DPh7-Q1i.cjs} +1 -1
- package/dist/tests/request.test.cjs +1 -1
- package/dist/tests/request.test.mjs +1 -1
- package/package.json +6 -3
- package/scripts/test-bun.mjs +18 -0
- package/src/contexts/fep-22cd.json +14 -0
- package/src/contexts/fep-6757.json +12 -0
- package/src/contexts/joinmastodon.json +1 -1
- package/src/contexts.ts +16 -0
- package/src/docloader.test.ts +222 -67
- package/src/docloader.ts +2 -0
- package/src/langstr.test.ts +18 -1
- package/src/langstr.ts +6 -2
- package/src/langtag.test.ts +53 -0
- package/src/langtag.ts +76 -0
- package/src/mod.ts +1 -0
- package/src/multibase/multibase.test.ts +5 -5
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-C2EiDwsr.cjs");
|
|
2
|
-
const require_request = require("./request-
|
|
3
|
-
const require_docloader = require("./docloader-
|
|
2
|
+
const require_request = require("./request-DPh7-Q1i.cjs");
|
|
3
|
+
const require_docloader = require("./docloader-Bx_LR9xG.cjs");
|
|
4
4
|
const require_url = require("./url-4PAkYhZC.cjs");
|
|
5
|
-
let node_test = require("node:test");
|
|
6
5
|
let node_zlib = require("node:zlib");
|
|
7
6
|
let _logtape_logtape = require("@logtape/logtape");
|
|
8
7
|
let node_assert = require("node:assert");
|
|
9
8
|
let node_dns_promises = require("node:dns/promises");
|
|
10
9
|
node_dns_promises = require_chunk.__toESM(node_dns_promises, 1);
|
|
10
|
+
let _fedify_fixture = require("@fedify/fixture");
|
|
11
11
|
let node_http = require("node:http");
|
|
12
|
+
let jsonld_dist_jsonld_esm_js = require("jsonld/dist/jsonld.esm.js");
|
|
13
|
+
jsonld_dist_jsonld_esm_js = require_chunk.__toESM(jsonld_dist_jsonld_esm_js, 1);
|
|
12
14
|
//#region ../../node_modules/.pnpm/glob-to-regexp@0.4.1/node_modules/glob-to-regexp/index.js
|
|
13
15
|
var require_glob_to_regexp = /* @__PURE__ */ require_chunk.__commonJSMin(((exports, module) => {
|
|
14
16
|
module.exports = function(glob, opts) {
|
|
@@ -1210,8 +1212,11 @@ var esm_default = new class FetchMock {
|
|
|
1210
1212
|
}
|
|
1211
1213
|
}({ ...defaultFetchMockConfig });
|
|
1212
1214
|
//#endregion
|
|
1215
|
+
//#region src/jsonld.ts
|
|
1216
|
+
var jsonld_default = jsonld_dist_jsonld_esm_js.default;
|
|
1217
|
+
//#endregion
|
|
1213
1218
|
//#region src/docloader.test.ts
|
|
1214
|
-
(0,
|
|
1219
|
+
(0, _fedify_fixture.test)("new FetchError()", () => {
|
|
1215
1220
|
const e = new require_request.FetchError("https://example.com/", "An error message.");
|
|
1216
1221
|
(0, node_assert.deepStrictEqual)(e.name, "FetchError");
|
|
1217
1222
|
(0, node_assert.deepStrictEqual)(e.url, new URL("https://example.com/"));
|
|
@@ -1224,7 +1229,7 @@ var esm_default = new class FetchMock {
|
|
|
1224
1229
|
(0, node_assert.ok)(e2.response != null);
|
|
1225
1230
|
(0, node_assert.deepStrictEqual)(e2.response.status, 410);
|
|
1226
1231
|
});
|
|
1227
|
-
(0,
|
|
1232
|
+
(0, _fedify_fixture.test)("getDocumentLoader()", async (t) => {
|
|
1228
1233
|
const fetchDocumentLoader = require_docloader.getDocumentLoader();
|
|
1229
1234
|
esm_default.spyGlobal();
|
|
1230
1235
|
esm_default.get("https://example.com/object", { body: {
|
|
@@ -1233,7 +1238,7 @@ var esm_default = new class FetchMock {
|
|
|
1233
1238
|
name: "Fetched object",
|
|
1234
1239
|
type: "Object"
|
|
1235
1240
|
} });
|
|
1236
|
-
await t.
|
|
1241
|
+
await t.step("ok", async () => {
|
|
1237
1242
|
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader("https://example.com/object"), {
|
|
1238
1243
|
contextUrl: null,
|
|
1239
1244
|
documentUrl: "https://example.com/object",
|
|
@@ -1276,7 +1281,7 @@ var esm_default = new class FetchMock {
|
|
|
1276
1281
|
Link: "<https://example.com/object>; rel=\"alternate\"; type=\"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"\""
|
|
1277
1282
|
}
|
|
1278
1283
|
});
|
|
1279
|
-
await t.
|
|
1284
|
+
await t.step("Link header", async () => {
|
|
1280
1285
|
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader("https://example.com/link-ctx"), {
|
|
1281
1286
|
contextUrl: "https://www.w3.org/ns/activitystreams",
|
|
1282
1287
|
documentUrl: "https://example.com/link-ctx",
|
|
@@ -1297,7 +1302,7 @@ var esm_default = new class FetchMock {
|
|
|
1297
1302
|
}
|
|
1298
1303
|
});
|
|
1299
1304
|
});
|
|
1300
|
-
await t.
|
|
1305
|
+
await t.step("Link header relative url", async () => {
|
|
1301
1306
|
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader("https://example.com/link-ctx"), {
|
|
1302
1307
|
contextUrl: "https://www.w3.org/ns/activitystreams",
|
|
1303
1308
|
documentUrl: "https://example.com/link-ctx",
|
|
@@ -1318,7 +1323,7 @@ var esm_default = new class FetchMock {
|
|
|
1318
1323
|
}
|
|
1319
1324
|
});
|
|
1320
1325
|
});
|
|
1321
|
-
await t.
|
|
1326
|
+
await t.step("wrong Link header syntax", async () => {
|
|
1322
1327
|
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader("https://example.com/obj-w-wrong-link"), {
|
|
1323
1328
|
contextUrl: null,
|
|
1324
1329
|
documentUrl: "https://example.com/obj-w-wrong-link",
|
|
@@ -1342,7 +1347,7 @@ var esm_default = new class FetchMock {
|
|
|
1342
1347
|
</html>`,
|
|
1343
1348
|
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
1344
1349
|
});
|
|
1345
|
-
await t.
|
|
1350
|
+
await t.step("HTML <link>", async () => {
|
|
1346
1351
|
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader("https://example.com/html-link"), {
|
|
1347
1352
|
contextUrl: null,
|
|
1348
1353
|
documentUrl: "https://example.com/object",
|
|
@@ -1366,7 +1371,7 @@ var esm_default = new class FetchMock {
|
|
|
1366
1371
|
</html>`,
|
|
1367
1372
|
headers: { "Content-Type": "application/xhtml+xml; charset=utf-8" }
|
|
1368
1373
|
});
|
|
1369
|
-
await t.
|
|
1374
|
+
await t.step("XHTML <link>", async () => {
|
|
1370
1375
|
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader("https://example.com/xhtml-link"), {
|
|
1371
1376
|
contextUrl: null,
|
|
1372
1377
|
documentUrl: "https://example.com/object",
|
|
@@ -1392,7 +1397,7 @@ var esm_default = new class FetchMock {
|
|
|
1392
1397
|
</html>`,
|
|
1393
1398
|
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
1394
1399
|
});
|
|
1395
|
-
await t.
|
|
1400
|
+
await t.step("HTML <a>", async () => {
|
|
1396
1401
|
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader("https://example.com/html-a"), {
|
|
1397
1402
|
contextUrl: null,
|
|
1398
1403
|
documentUrl: "https://example.com/object",
|
|
@@ -1413,7 +1418,7 @@ var esm_default = new class FetchMock {
|
|
|
1413
1418
|
},
|
|
1414
1419
|
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
1415
1420
|
});
|
|
1416
|
-
await t.
|
|
1421
|
+
await t.step("Wrong Content-Type", async () => {
|
|
1417
1422
|
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader("https://example.com/wrong-content-type"), {
|
|
1418
1423
|
contextUrl: null,
|
|
1419
1424
|
documentUrl: "https://example.com/wrong-content-type",
|
|
@@ -1426,18 +1431,33 @@ var esm_default = new class FetchMock {
|
|
|
1426
1431
|
});
|
|
1427
1432
|
});
|
|
1428
1433
|
esm_default.get("https://example.com/404", { status: 404 });
|
|
1429
|
-
await t.
|
|
1434
|
+
await t.step("not ok", async () => {
|
|
1430
1435
|
await (0, node_assert.rejects)(() => fetchDocumentLoader("https://example.com/404"), require_request.FetchError, "HTTP 404: https://example.com/404");
|
|
1431
1436
|
});
|
|
1432
|
-
await t.
|
|
1437
|
+
await t.step("preloaded contexts", async () => {
|
|
1433
1438
|
for (const [url, document] of Object.entries(require_docloader.preloadedContexts)) (0, node_assert.deepStrictEqual)(await fetchDocumentLoader(url), {
|
|
1434
1439
|
contextUrl: null,
|
|
1435
1440
|
documentUrl: url,
|
|
1436
1441
|
document
|
|
1437
1442
|
});
|
|
1438
1443
|
});
|
|
1444
|
+
await t.step("preloaded Mastodon attribution domains", async () => {
|
|
1445
|
+
const context = ["https://www.w3.org/ns/activitystreams", "http://joinmastodon.org/ns"];
|
|
1446
|
+
const expanded = await jsonld_default.expand({
|
|
1447
|
+
"@context": context,
|
|
1448
|
+
id: "https://social.example/users/alice",
|
|
1449
|
+
type: "Person",
|
|
1450
|
+
attributionDomains: ["blog.example"]
|
|
1451
|
+
}, { documentLoader: fetchDocumentLoader });
|
|
1452
|
+
(0, node_assert.deepStrictEqual)(expanded, [{
|
|
1453
|
+
"@id": "https://social.example/users/alice",
|
|
1454
|
+
"@type": ["https://www.w3.org/ns/activitystreams#Person"],
|
|
1455
|
+
"http://joinmastodon.org/ns#attributionDomains": [{ "@value": "blog.example" }]
|
|
1456
|
+
}]);
|
|
1457
|
+
(0, node_assert.deepStrictEqual)((await jsonld_default.compact(expanded, context, { documentLoader: fetchDocumentLoader })).attributionDomains, ["blog.example"]);
|
|
1458
|
+
});
|
|
1439
1459
|
esm_default.get("https://www.w3.org/ns/cid/v1", { status: 503 });
|
|
1440
|
-
await t.
|
|
1460
|
+
await t.step("preloaded CID v1 context", async () => {
|
|
1441
1461
|
const url = "https://www.w3.org/ns/cid/v1";
|
|
1442
1462
|
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader(url), {
|
|
1443
1463
|
contextUrl: null,
|
|
@@ -1445,7 +1465,7 @@ var esm_default = new class FetchMock {
|
|
|
1445
1465
|
document: require_docloader.cid_v1_default
|
|
1446
1466
|
});
|
|
1447
1467
|
});
|
|
1448
|
-
await t.
|
|
1468
|
+
await t.step("preloaded FEP-ef61 context", async () => {
|
|
1449
1469
|
const url = "https://w3id.org/fep/ef61";
|
|
1450
1470
|
(0, node_assert.ok)(url in require_docloader.preloadedContexts);
|
|
1451
1471
|
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader(url), {
|
|
@@ -1462,7 +1482,7 @@ var esm_default = new class FetchMock {
|
|
|
1462
1482
|
});
|
|
1463
1483
|
});
|
|
1464
1484
|
esm_default.get("https://w3id.org/fep/7aa9", { status: 502 });
|
|
1465
|
-
await t.
|
|
1485
|
+
await t.step("preloaded FEP-7aa9 context", async () => {
|
|
1466
1486
|
const url = "https://w3id.org/fep/7aa9";
|
|
1467
1487
|
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader(url), {
|
|
1468
1488
|
contextUrl: null,
|
|
@@ -1492,7 +1512,115 @@ var esm_default = new class FetchMock {
|
|
|
1492
1512
|
});
|
|
1493
1513
|
(0, node_assert.deepStrictEqual)(esm_default.callHistory.calls(url).length, 0);
|
|
1494
1514
|
});
|
|
1495
|
-
|
|
1515
|
+
esm_default.get("https://w3id.org/fep/6757", { status: 502 });
|
|
1516
|
+
await t.step("preloaded FEP-6757 context", async () => {
|
|
1517
|
+
const url = "https://w3id.org/fep/6757";
|
|
1518
|
+
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader(url), {
|
|
1519
|
+
contextUrl: null,
|
|
1520
|
+
documentUrl: url,
|
|
1521
|
+
document: { "@context": {
|
|
1522
|
+
license: {
|
|
1523
|
+
"@id": "http://purl.org/dc/terms/license",
|
|
1524
|
+
"@type": "@id"
|
|
1525
|
+
},
|
|
1526
|
+
preferredLicense: {
|
|
1527
|
+
"@id": "https://w3id.org/fep/6757#preferredLicense",
|
|
1528
|
+
"@type": "@id"
|
|
1529
|
+
}
|
|
1530
|
+
} }
|
|
1531
|
+
});
|
|
1532
|
+
(0, node_assert.deepStrictEqual)(await jsonld_default.expand({
|
|
1533
|
+
"@context": ["https://www.w3.org/ns/activitystreams", url],
|
|
1534
|
+
type: "Person",
|
|
1535
|
+
license: "https://creativecommons.org/licenses/by/4.0/",
|
|
1536
|
+
preferredLicense: "https://creativecommons.org/licenses/by-nc/4.0/"
|
|
1537
|
+
}, { documentLoader: fetchDocumentLoader }), [{
|
|
1538
|
+
"@type": ["https://www.w3.org/ns/activitystreams#Person"],
|
|
1539
|
+
"http://purl.org/dc/terms/license": [{ "@id": "https://creativecommons.org/licenses/by/4.0/" }],
|
|
1540
|
+
"https://w3id.org/fep/6757#preferredLicense": [{ "@id": "https://creativecommons.org/licenses/by-nc/4.0/" }]
|
|
1541
|
+
}]);
|
|
1542
|
+
(0, node_assert.deepStrictEqual)(esm_default.callHistory.calls(url).length, 0);
|
|
1543
|
+
});
|
|
1544
|
+
esm_default.get("https://w3id.org/fep/22cd", { status: 502 });
|
|
1545
|
+
await t.step("preloaded FEP-22cd context", async () => {
|
|
1546
|
+
const url = "https://w3id.org/fep/22cd";
|
|
1547
|
+
const articleId = "https://example.com/articles/1";
|
|
1548
|
+
const translatorId = "https://example.com/users/alice";
|
|
1549
|
+
const revisionId = "https://example.com/articles/1/revisions/1";
|
|
1550
|
+
(0, node_assert.deepStrictEqual)(await fetchDocumentLoader(url), {
|
|
1551
|
+
contextUrl: null,
|
|
1552
|
+
documentUrl: url,
|
|
1553
|
+
document: { "@context": {
|
|
1554
|
+
"fep-22cd": "https://w3id.org/fep/22cd#",
|
|
1555
|
+
schema: "https://schema.org/",
|
|
1556
|
+
xsd: "http://www.w3.org/2001/XMLSchema#",
|
|
1557
|
+
translations: {
|
|
1558
|
+
"@id": "fep-22cd:translations",
|
|
1559
|
+
"@container": "@set"
|
|
1560
|
+
},
|
|
1561
|
+
Translation: "fep-22cd:Translation",
|
|
1562
|
+
sourceUpdated: {
|
|
1563
|
+
"@id": "fep-22cd:sourceUpdated",
|
|
1564
|
+
"@type": "xsd:dateTime"
|
|
1565
|
+
},
|
|
1566
|
+
translator: {
|
|
1567
|
+
"@id": "schema:translator",
|
|
1568
|
+
"@type": "@id",
|
|
1569
|
+
"@container": "@set"
|
|
1570
|
+
},
|
|
1571
|
+
inLanguage: "schema:inLanguage",
|
|
1572
|
+
translationOfWork: {
|
|
1573
|
+
"@id": "schema:translationOfWork",
|
|
1574
|
+
"@type": "@id"
|
|
1575
|
+
},
|
|
1576
|
+
isBasedOn: {
|
|
1577
|
+
"@id": "schema:isBasedOn",
|
|
1578
|
+
"@type": "@id"
|
|
1579
|
+
}
|
|
1580
|
+
} }
|
|
1581
|
+
});
|
|
1582
|
+
(0, node_assert.deepStrictEqual)(await jsonld_default.expand({
|
|
1583
|
+
"@context": ["https://www.w3.org/ns/activitystreams", url],
|
|
1584
|
+
id: articleId,
|
|
1585
|
+
type: "Article",
|
|
1586
|
+
contentMap: {
|
|
1587
|
+
en: "Original",
|
|
1588
|
+
ko: "Translation"
|
|
1589
|
+
},
|
|
1590
|
+
translations: [{
|
|
1591
|
+
type: "Translation",
|
|
1592
|
+
inLanguage: "ko",
|
|
1593
|
+
translator: [translatorId],
|
|
1594
|
+
translationOfWork: articleId,
|
|
1595
|
+
sourceUpdated: "2026-09-01T00:00:00Z",
|
|
1596
|
+
isBasedOn: revisionId
|
|
1597
|
+
}]
|
|
1598
|
+
}, { documentLoader: fetchDocumentLoader }), [{
|
|
1599
|
+
"@id": articleId,
|
|
1600
|
+
"@type": ["https://www.w3.org/ns/activitystreams#Article"],
|
|
1601
|
+
"https://www.w3.org/ns/activitystreams#content": [{
|
|
1602
|
+
"@language": "en",
|
|
1603
|
+
"@value": "Original"
|
|
1604
|
+
}, {
|
|
1605
|
+
"@language": "ko",
|
|
1606
|
+
"@value": "Translation"
|
|
1607
|
+
}],
|
|
1608
|
+
"https://w3id.org/fep/22cd#translations": [{
|
|
1609
|
+
"@type": ["https://w3id.org/fep/22cd#Translation"],
|
|
1610
|
+
"https://schema.org/inLanguage": [{ "@value": "ko" }],
|
|
1611
|
+
"https://schema.org/translator": [{ "@id": translatorId }],
|
|
1612
|
+
"https://schema.org/translationOfWork": [{ "@id": articleId }],
|
|
1613
|
+
"https://w3id.org/fep/22cd#sourceUpdated": [{
|
|
1614
|
+
"@type": "http://www.w3.org/2001/XMLSchema#dateTime",
|
|
1615
|
+
"@value": "2026-09-01T00:00:00Z"
|
|
1616
|
+
}],
|
|
1617
|
+
"https://schema.org/isBasedOn": [{ "@id": revisionId }]
|
|
1618
|
+
}]
|
|
1619
|
+
}]);
|
|
1620
|
+
(0, node_assert.deepStrictEqual)(esm_default.callHistory.calls(url).length, 0);
|
|
1621
|
+
(0, node_assert.deepStrictEqual)(esm_default.callHistory.calls("https://www.w3.org/ns/activitystreams").length, 0);
|
|
1622
|
+
});
|
|
1623
|
+
await t.step("deny non-HTTP/HTTPS", async () => {
|
|
1496
1624
|
await (0, node_assert.rejects)(() => fetchDocumentLoader("ftp://localhost"), require_url.UrlError);
|
|
1497
1625
|
});
|
|
1498
1626
|
esm_default.get("https://example.com/localhost-redirect", {
|
|
@@ -1517,13 +1645,13 @@ var esm_default = new class FetchMock {
|
|
|
1517
1645
|
name: "Fetched object",
|
|
1518
1646
|
type: "Object"
|
|
1519
1647
|
} });
|
|
1520
|
-
await t.
|
|
1648
|
+
await t.step("allowPrivateAddress: false", async () => {
|
|
1521
1649
|
await (0, node_assert.rejects)(() => fetchDocumentLoader("https://localhost/object"), require_url.UrlError);
|
|
1522
1650
|
await (0, node_assert.rejects)(() => fetchDocumentLoader("https://example.com/localhost-redirect"), require_url.UrlError);
|
|
1523
1651
|
await (0, node_assert.rejects)(() => fetchDocumentLoader("https://example.com/localhost-link"), require_url.UrlError);
|
|
1524
1652
|
});
|
|
1525
1653
|
const fetchDocumentLoader2 = require_docloader.getDocumentLoader({ allowPrivateAddress: true });
|
|
1526
|
-
await t.
|
|
1654
|
+
await t.step("allowPrivateAddress: true", async () => {
|
|
1527
1655
|
const expected = {
|
|
1528
1656
|
contextUrl: null,
|
|
1529
1657
|
documentUrl: "https://localhost/object",
|
|
@@ -1546,12 +1674,12 @@ var esm_default = new class FetchMock {
|
|
|
1546
1674
|
headers: { Location: `https://example.com/too-many-redirects/${Number(cl.url.split("/").at(-1)) + 1}` }
|
|
1547
1675
|
};
|
|
1548
1676
|
});
|
|
1549
|
-
await t.
|
|
1677
|
+
await t.step("too many redirects", async () => {
|
|
1550
1678
|
redirectAttempts = 0;
|
|
1551
1679
|
await (0, node_assert.rejects)(() => fetchDocumentLoader("https://example.com/too-many-redirects/0"), require_request.FetchError, "Too many redirections");
|
|
1552
1680
|
(0, node_assert.deepStrictEqual)(redirectAttempts, 21);
|
|
1553
1681
|
});
|
|
1554
|
-
await t.
|
|
1682
|
+
await t.step("custom max redirection", async () => {
|
|
1555
1683
|
redirectAttempts = 0;
|
|
1556
1684
|
const loader = require_docloader.getDocumentLoader({ maxRedirection: 1 });
|
|
1557
1685
|
await (0, node_assert.rejects)(() => loader("https://example.com/too-many-redirects/0"), require_request.FetchError, "Too many redirections");
|
|
@@ -1572,7 +1700,7 @@ var esm_default = new class FetchMock {
|
|
|
1572
1700
|
headers: { Location: "https://example.com/redirect-loop-a" }
|
|
1573
1701
|
};
|
|
1574
1702
|
});
|
|
1575
|
-
await t.
|
|
1703
|
+
await t.step("redirect loop", async () => {
|
|
1576
1704
|
loopAttempts = 0;
|
|
1577
1705
|
await (0, node_assert.rejects)(() => fetchDocumentLoader("https://example.com/redirect-loop-a"), require_request.FetchError, "Redirect loop detected");
|
|
1578
1706
|
(0, node_assert.deepStrictEqual)(loopAttempts, 2);
|
|
@@ -1585,7 +1713,7 @@ var esm_default = new class FetchMock {
|
|
|
1585
1713
|
headers: { Location: "/redirect-loop-relative" }
|
|
1586
1714
|
};
|
|
1587
1715
|
});
|
|
1588
|
-
await t.
|
|
1716
|
+
await t.step("redirect loop with relative location", async () => {
|
|
1589
1717
|
relativeLoopAttempts = 0;
|
|
1590
1718
|
await (0, node_assert.rejects)(() => fetchDocumentLoader("https://example.com/redirect-loop-relative"), require_request.FetchError, "Redirect loop detected");
|
|
1591
1719
|
(0, node_assert.deepStrictEqual)(relativeLoopAttempts, 1);
|
|
@@ -1595,7 +1723,7 @@ var esm_default = new class FetchMock {
|
|
|
1595
1723
|
body: maliciousPayload,
|
|
1596
1724
|
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
1597
1725
|
});
|
|
1598
|
-
await t.
|
|
1726
|
+
await t.step("ReDoS resistance (CVE-2025-68475)", async () => {
|
|
1599
1727
|
const start = performance.now();
|
|
1600
1728
|
await (0, node_assert.rejects)(() => fetchDocumentLoader("https://example.com/redos"), SyntaxError);
|
|
1601
1729
|
const elapsed = performance.now() - start;
|
|
@@ -1603,7 +1731,7 @@ var esm_default = new class FetchMock {
|
|
|
1603
1731
|
});
|
|
1604
1732
|
esm_default.hardReset();
|
|
1605
1733
|
});
|
|
1606
|
-
(0,
|
|
1734
|
+
(0, _fedify_fixture.test)("getDocumentLoader() bounds JSON, HTML, and alternate documents", async () => {
|
|
1607
1735
|
const url = "https://example.com/bounded";
|
|
1608
1736
|
esm_default.mockGlobal();
|
|
1609
1737
|
let oversized = true;
|
|
@@ -1633,7 +1761,7 @@ var esm_default = new class FetchMock {
|
|
|
1633
1761
|
esm_default.hardReset();
|
|
1634
1762
|
}
|
|
1635
1763
|
});
|
|
1636
|
-
(0,
|
|
1764
|
+
(0, _fedify_fixture.test)("getDocumentLoader() rejects oversized gzip responses from fetch", async () => {
|
|
1637
1765
|
const document = { name: "a".repeat(16 * 1024 * 1024) };
|
|
1638
1766
|
const compressed = (0, node_zlib.gzipSync)(JSON.stringify(document));
|
|
1639
1767
|
(0, node_assert.ok)(compressed.byteLength < 64 * 1024);
|
|
@@ -1663,7 +1791,7 @@ var esm_default = new class FetchMock {
|
|
|
1663
1791
|
});
|
|
1664
1792
|
}
|
|
1665
1793
|
});
|
|
1666
|
-
(0,
|
|
1794
|
+
(0, _fedify_fixture.test)("getRemoteDocument() bounds JSON by default", async () => {
|
|
1667
1795
|
let canceled = false;
|
|
1668
1796
|
let pulls = 0;
|
|
1669
1797
|
await (0, node_assert.rejects)(require_docloader.getRemoteDocument("https://example.com/document", new Response(new ReadableStream({
|
|
@@ -1680,17 +1808,14 @@ var esm_default = new class FetchMock {
|
|
|
1680
1808
|
(0, node_assert.deepStrictEqual)(canceled, true);
|
|
1681
1809
|
(0, node_assert.deepStrictEqual)(pulls, 257);
|
|
1682
1810
|
});
|
|
1683
|
-
(0,
|
|
1684
|
-
if ("Deno" in globalThis && (await Deno.permissions.query({ name: "net" })).state !== "granted")
|
|
1685
|
-
t.skip("requires the net permission");
|
|
1686
|
-
return;
|
|
1687
|
-
}
|
|
1811
|
+
(0, _fedify_fixture.test)("getDocumentLoader() logs DNS failures as such", async (t) => {
|
|
1812
|
+
if ("Deno" in globalThis && (await Deno.permissions.query({ name: "net" })).state !== "granted") throw new Error("This DNS test requires Deno network permission (--allow-net).");
|
|
1688
1813
|
const loader = require_docloader.getDocumentLoader();
|
|
1689
1814
|
for (const result of [
|
|
1690
1815
|
"throws",
|
|
1691
1816
|
"empty",
|
|
1692
1817
|
"private"
|
|
1693
|
-
]) await t.
|
|
1818
|
+
]) await t.step(result, async () => {
|
|
1694
1819
|
const originalLookup = node_dns_promises.default.lookup;
|
|
1695
1820
|
node_dns_promises.default.lookup = (() => result === "throws" ? Promise.reject(/* @__PURE__ */ new Error("Resolver unavailable")) : Promise.resolve(result === "empty" ? [] : [{
|
|
1696
1821
|
address: "127.0.0.1",
|
|
@@ -1738,14 +1863,14 @@ var esm_default = new class FetchMock {
|
|
|
1738
1863
|
}
|
|
1739
1864
|
});
|
|
1740
1865
|
});
|
|
1741
|
-
(0,
|
|
1866
|
+
(0, _fedify_fixture.test)("getDocumentLoader() bounds alternate document chains", async (t) => {
|
|
1742
1867
|
const base = "https://example.com/alternate-chain/";
|
|
1743
1868
|
const loader = require_docloader.getDocumentLoader({ allowPrivateAddress: true });
|
|
1744
1869
|
for (const mode of [
|
|
1745
1870
|
"header",
|
|
1746
1871
|
"html",
|
|
1747
1872
|
"mixed"
|
|
1748
|
-
]) for (const hops of [20, 21]) await t.
|
|
1873
|
+
]) for (const hops of [20, 21]) await t.step(`${mode}: ${hops} hops`, async () => {
|
|
1749
1874
|
esm_default.mockGlobal();
|
|
1750
1875
|
let requests = 0;
|
|
1751
1876
|
esm_default.get(`begin:${base}`, ({ url }) => {
|
|
@@ -1774,7 +1899,7 @@ var esm_default = new class FetchMock {
|
|
|
1774
1899
|
"alternate-redirect",
|
|
1775
1900
|
"redirect-alternate",
|
|
1776
1901
|
"redirect-intermediate"
|
|
1777
|
-
]) await t.
|
|
1902
|
+
]) await t.step(`${mode}: cycle`, async () => {
|
|
1778
1903
|
esm_default.mockGlobal();
|
|
1779
1904
|
let requests = 0;
|
|
1780
1905
|
esm_default.get(`begin:${base}`, ({ url }) => {
|
|
@@ -1796,7 +1921,7 @@ var esm_default = new class FetchMock {
|
|
|
1796
1921
|
esm_default.hardReset();
|
|
1797
1922
|
}
|
|
1798
1923
|
});
|
|
1799
|
-
await t.
|
|
1924
|
+
await t.step("alternate followed by 20 redirects shares the limit", async () => {
|
|
1800
1925
|
esm_default.mockGlobal();
|
|
1801
1926
|
let requests = 0;
|
|
1802
1927
|
esm_default.get(`begin:${base}`, ({ url }) => {
|
|
@@ -1816,7 +1941,7 @@ var esm_default = new class FetchMock {
|
|
|
1816
1941
|
esm_default.hardReset();
|
|
1817
1942
|
}
|
|
1818
1943
|
});
|
|
1819
|
-
await t.
|
|
1944
|
+
await t.step("relative alternate after redirect and isolated calls", async () => {
|
|
1820
1945
|
esm_default.mockGlobal();
|
|
1821
1946
|
esm_default.get(`${base}start`, Response.redirect(`${base}html`, 302));
|
|
1822
1947
|
esm_default.get(`${base}html`, alternate("./document", true));
|
|
@@ -1840,10 +1965,10 @@ var esm_default = new class FetchMock {
|
|
|
1840
1965
|
} });
|
|
1841
1966
|
}
|
|
1842
1967
|
});
|
|
1843
|
-
(0,
|
|
1968
|
+
(0, _fedify_fixture.test)("getDocumentLoader() preserves cancellation across alternates", async (t) => {
|
|
1844
1969
|
const base = "https://example.com/alternate-abort/";
|
|
1845
1970
|
const loader = require_docloader.getDocumentLoader({ allowPrivateAddress: true });
|
|
1846
|
-
for (const html of [false, true]) await t.
|
|
1971
|
+
for (const html of [false, true]) await t.step(html ? "HTML" : "Link header", async () => {
|
|
1847
1972
|
esm_default.mockGlobal();
|
|
1848
1973
|
const controller = new AbortController();
|
|
1849
1974
|
let requests = 0;
|
|
@@ -1866,7 +1991,7 @@ var esm_default = new class FetchMock {
|
|
|
1866
1991
|
}
|
|
1867
1992
|
});
|
|
1868
1993
|
});
|
|
1869
|
-
(0,
|
|
1994
|
+
(0, _fedify_fixture.test)("getDocumentLoader() rejects cancellation before fetching", async () => {
|
|
1870
1995
|
esm_default.mockGlobal();
|
|
1871
1996
|
let requests = 0;
|
|
1872
1997
|
const url = "https://example.com/pre-aborted-alternate";
|