sandboxedjs 0.1.95 → 0.1.97
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/dist/index.cjs +44 -16
- package/dist/index.js +44 -16
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20958,7 +20958,7 @@ var wheels_default = {
|
|
|
20958
20958
|
|
|
20959
20959
|
// package.json
|
|
20960
20960
|
var package_default = {
|
|
20961
|
-
version: "0.1.
|
|
20961
|
+
version: "0.1.97"};
|
|
20962
20962
|
|
|
20963
20963
|
// src/python/extension-abi.ts
|
|
20964
20964
|
var EXTENSION_ABI = {
|
|
@@ -23933,9 +23933,7 @@ async function installRequirements(options) {
|
|
|
23933
23933
|
continue;
|
|
23934
23934
|
}
|
|
23935
23935
|
options.progress.downloading(distribution.name, distribution.version);
|
|
23936
|
-
const bytes2 = await options.client
|
|
23937
|
-
requireArchive(distribution, bytes2);
|
|
23938
|
-
verifyDigest(distribution, bytes2);
|
|
23936
|
+
const bytes2 = await download(options.client, distribution);
|
|
23939
23937
|
const files = stageWheel(readZip(bytes2));
|
|
23940
23938
|
staged.push(...distribution.kind === "substituted" ? substituteFiles(distribution.name, files, SITE_PACKAGES) : files);
|
|
23941
23939
|
installed3.push({ name: distribution.name, version: distribution.version });
|
|
@@ -23951,18 +23949,41 @@ function requireArchive(distribution, bytes2) {
|
|
|
23951
23949
|
`${distribution.filename} did not arrive as a wheel from ${distribution.url}: ` + (looksLikeMarkup ? "the server answered with an HTML page, which usually means the wheel is not published at that address and the server returned its index page instead" : `expected a zip archive, got ${bytes2.length} bytes beginning ${JSON.stringify(opening)}`)
|
|
23952
23950
|
);
|
|
23953
23951
|
}
|
|
23954
|
-
function
|
|
23952
|
+
async function download(client, distribution) {
|
|
23953
|
+
const bytes2 = await client.bytes(distribution.url, { timeoutMs: 12e4 });
|
|
23954
|
+
requireArchive(distribution, bytes2);
|
|
23955
|
+
const mismatch = digestMismatch(distribution, bytes2);
|
|
23956
|
+
if (!mismatch) return bytes2;
|
|
23957
|
+
const fresh = await refetch(client, distribution);
|
|
23958
|
+
if (fresh && !digestMismatch(distribution, fresh)) {
|
|
23959
|
+
requireArchive(distribution, fresh);
|
|
23960
|
+
return fresh;
|
|
23961
|
+
}
|
|
23962
|
+
throw new Error(
|
|
23963
|
+
`${mismatch} ${fresh ? "A retry past any cache returned the same bytes, so the index and the file it names disagree." : "A retry past any cache could not be made, so this may be a cached copy of an older build; clearing the cache, or asking the index's host to purge it, is worth trying before the index is blamed."}`
|
|
23964
|
+
);
|
|
23965
|
+
}
|
|
23966
|
+
async function refetch(client, distribution) {
|
|
23967
|
+
const separator = distribution.url.includes("?") ? "&" : "?";
|
|
23968
|
+
try {
|
|
23969
|
+
const bytes2 = await client.bytes(
|
|
23970
|
+
`${distribution.url}${separator}sha256=${distribution.sha256}`,
|
|
23971
|
+
{ timeoutMs: 6e4 }
|
|
23972
|
+
);
|
|
23973
|
+
return bytes2.length > 1 && bytes2[0] === 80 && bytes2[1] === 75 ? bytes2 : null;
|
|
23974
|
+
} catch {
|
|
23975
|
+
return null;
|
|
23976
|
+
}
|
|
23977
|
+
}
|
|
23978
|
+
function digestMismatch(distribution, bytes2) {
|
|
23955
23979
|
if (!distribution.sha256) {
|
|
23956
23980
|
throw new Error(
|
|
23957
23981
|
`${distribution.filename} was published without a sha256 digest, so it cannot be verified`
|
|
23958
23982
|
);
|
|
23959
23983
|
}
|
|
23960
23984
|
const actual = [...sha256.sha256(bytes2)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
23961
|
-
if (actual
|
|
23962
|
-
|
|
23963
|
-
`${distribution.filename} failed verification: the index published sha256 ${distribution.sha256} but the download hashes to ${actual}`
|
|
23964
|
-
);
|
|
23965
|
-
}
|
|
23985
|
+
if (actual === distribution.sha256) return null;
|
|
23986
|
+
return `${distribution.filename} failed verification: the index published sha256 ${distribution.sha256} but the download hashes to ${actual}.`;
|
|
23966
23987
|
}
|
|
23967
23988
|
function stageWheel(entries, resolved) {
|
|
23968
23989
|
const staged = [];
|
|
@@ -28043,12 +28064,19 @@ async function installRelease(ctx, index, release, seen, options) {
|
|
|
28043
28064
|
const base2 = registryBase(ctx).replace(/\/$/, "");
|
|
28044
28065
|
const url = `${base2}/${release.filename}`;
|
|
28045
28066
|
ctx.line(`Fetching ${release.name} ${release.version}`);
|
|
28046
|
-
|
|
28047
|
-
|
|
28067
|
+
let archive = await download2(url);
|
|
28068
|
+
let digest2 = await digestHex("sha256", archive);
|
|
28048
28069
|
if (digest2 !== release.sha256) {
|
|
28049
|
-
|
|
28050
|
-
|
|
28051
|
-
)
|
|
28070
|
+
const retried = await download2(`${url}${url.includes("?") ? "&" : "?"}sha256=${release.sha256}`).catch(() => null);
|
|
28071
|
+
const retriedDigest = retried && await digestHex("sha256", retried);
|
|
28072
|
+
if (retried && retriedDigest === release.sha256) {
|
|
28073
|
+
archive = retried;
|
|
28074
|
+
digest2 = retriedDigest;
|
|
28075
|
+
} else {
|
|
28076
|
+
throw new AppRegistryError(
|
|
28077
|
+
`${release.filename} failed verification: the registry publishes sha256 ${release.sha256} but the download hashes to ${digest2}. ` + (retried ? "A retry past any cache returned the same bytes, so the registry and the file it names disagree." : "A retry past any cache could not be made; a cached copy of an older build would look like this, so clearing the cache is worth trying before the registry is blamed.")
|
|
28078
|
+
);
|
|
28079
|
+
}
|
|
28052
28080
|
}
|
|
28053
28081
|
const verified = await verify(ctx, archive, release, options);
|
|
28054
28082
|
const root = `${APPS_ROOT}/${release.name}`;
|
|
@@ -28075,7 +28103,7 @@ async function installRelease(ctx, index, release, seen, options) {
|
|
|
28075
28103
|
}
|
|
28076
28104
|
if (manifest.docs) ctx.line(` docs: ${root}/${manifest.docs}`);
|
|
28077
28105
|
}
|
|
28078
|
-
async function
|
|
28106
|
+
async function download2(url) {
|
|
28079
28107
|
const response = await fetch(url);
|
|
28080
28108
|
if (!response.ok) {
|
|
28081
28109
|
throw new AppRegistryError(`${url} answered ${response.status} ${response.statusText}`);
|
package/dist/index.js
CHANGED
|
@@ -20941,7 +20941,7 @@ var wheels_default = {
|
|
|
20941
20941
|
|
|
20942
20942
|
// package.json
|
|
20943
20943
|
var package_default = {
|
|
20944
|
-
version: "0.1.
|
|
20944
|
+
version: "0.1.97"};
|
|
20945
20945
|
|
|
20946
20946
|
// src/python/extension-abi.ts
|
|
20947
20947
|
var EXTENSION_ABI = {
|
|
@@ -23916,9 +23916,7 @@ async function installRequirements(options) {
|
|
|
23916
23916
|
continue;
|
|
23917
23917
|
}
|
|
23918
23918
|
options.progress.downloading(distribution.name, distribution.version);
|
|
23919
|
-
const bytes2 = await options.client
|
|
23920
|
-
requireArchive(distribution, bytes2);
|
|
23921
|
-
verifyDigest(distribution, bytes2);
|
|
23919
|
+
const bytes2 = await download(options.client, distribution);
|
|
23922
23920
|
const files = stageWheel(readZip(bytes2));
|
|
23923
23921
|
staged.push(...distribution.kind === "substituted" ? substituteFiles(distribution.name, files, SITE_PACKAGES) : files);
|
|
23924
23922
|
installed3.push({ name: distribution.name, version: distribution.version });
|
|
@@ -23934,18 +23932,41 @@ function requireArchive(distribution, bytes2) {
|
|
|
23934
23932
|
`${distribution.filename} did not arrive as a wheel from ${distribution.url}: ` + (looksLikeMarkup ? "the server answered with an HTML page, which usually means the wheel is not published at that address and the server returned its index page instead" : `expected a zip archive, got ${bytes2.length} bytes beginning ${JSON.stringify(opening)}`)
|
|
23935
23933
|
);
|
|
23936
23934
|
}
|
|
23937
|
-
function
|
|
23935
|
+
async function download(client, distribution) {
|
|
23936
|
+
const bytes2 = await client.bytes(distribution.url, { timeoutMs: 12e4 });
|
|
23937
|
+
requireArchive(distribution, bytes2);
|
|
23938
|
+
const mismatch = digestMismatch(distribution, bytes2);
|
|
23939
|
+
if (!mismatch) return bytes2;
|
|
23940
|
+
const fresh = await refetch(client, distribution);
|
|
23941
|
+
if (fresh && !digestMismatch(distribution, fresh)) {
|
|
23942
|
+
requireArchive(distribution, fresh);
|
|
23943
|
+
return fresh;
|
|
23944
|
+
}
|
|
23945
|
+
throw new Error(
|
|
23946
|
+
`${mismatch} ${fresh ? "A retry past any cache returned the same bytes, so the index and the file it names disagree." : "A retry past any cache could not be made, so this may be a cached copy of an older build; clearing the cache, or asking the index's host to purge it, is worth trying before the index is blamed."}`
|
|
23947
|
+
);
|
|
23948
|
+
}
|
|
23949
|
+
async function refetch(client, distribution) {
|
|
23950
|
+
const separator = distribution.url.includes("?") ? "&" : "?";
|
|
23951
|
+
try {
|
|
23952
|
+
const bytes2 = await client.bytes(
|
|
23953
|
+
`${distribution.url}${separator}sha256=${distribution.sha256}`,
|
|
23954
|
+
{ timeoutMs: 6e4 }
|
|
23955
|
+
);
|
|
23956
|
+
return bytes2.length > 1 && bytes2[0] === 80 && bytes2[1] === 75 ? bytes2 : null;
|
|
23957
|
+
} catch {
|
|
23958
|
+
return null;
|
|
23959
|
+
}
|
|
23960
|
+
}
|
|
23961
|
+
function digestMismatch(distribution, bytes2) {
|
|
23938
23962
|
if (!distribution.sha256) {
|
|
23939
23963
|
throw new Error(
|
|
23940
23964
|
`${distribution.filename} was published without a sha256 digest, so it cannot be verified`
|
|
23941
23965
|
);
|
|
23942
23966
|
}
|
|
23943
23967
|
const actual = [...sha256(bytes2)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
23944
|
-
if (actual
|
|
23945
|
-
|
|
23946
|
-
`${distribution.filename} failed verification: the index published sha256 ${distribution.sha256} but the download hashes to ${actual}`
|
|
23947
|
-
);
|
|
23948
|
-
}
|
|
23968
|
+
if (actual === distribution.sha256) return null;
|
|
23969
|
+
return `${distribution.filename} failed verification: the index published sha256 ${distribution.sha256} but the download hashes to ${actual}.`;
|
|
23949
23970
|
}
|
|
23950
23971
|
function stageWheel(entries, resolved) {
|
|
23951
23972
|
const staged = [];
|
|
@@ -28026,12 +28047,19 @@ async function installRelease(ctx, index, release, seen, options) {
|
|
|
28026
28047
|
const base2 = registryBase(ctx).replace(/\/$/, "");
|
|
28027
28048
|
const url = `${base2}/${release.filename}`;
|
|
28028
28049
|
ctx.line(`Fetching ${release.name} ${release.version}`);
|
|
28029
|
-
|
|
28030
|
-
|
|
28050
|
+
let archive = await download2(url);
|
|
28051
|
+
let digest2 = await digestHex("sha256", archive);
|
|
28031
28052
|
if (digest2 !== release.sha256) {
|
|
28032
|
-
|
|
28033
|
-
|
|
28034
|
-
)
|
|
28053
|
+
const retried = await download2(`${url}${url.includes("?") ? "&" : "?"}sha256=${release.sha256}`).catch(() => null);
|
|
28054
|
+
const retriedDigest = retried && await digestHex("sha256", retried);
|
|
28055
|
+
if (retried && retriedDigest === release.sha256) {
|
|
28056
|
+
archive = retried;
|
|
28057
|
+
digest2 = retriedDigest;
|
|
28058
|
+
} else {
|
|
28059
|
+
throw new AppRegistryError(
|
|
28060
|
+
`${release.filename} failed verification: the registry publishes sha256 ${release.sha256} but the download hashes to ${digest2}. ` + (retried ? "A retry past any cache returned the same bytes, so the registry and the file it names disagree." : "A retry past any cache could not be made; a cached copy of an older build would look like this, so clearing the cache is worth trying before the registry is blamed.")
|
|
28061
|
+
);
|
|
28062
|
+
}
|
|
28035
28063
|
}
|
|
28036
28064
|
const verified = await verify(ctx, archive, release, options);
|
|
28037
28065
|
const root = `${APPS_ROOT}/${release.name}`;
|
|
@@ -28058,7 +28086,7 @@ async function installRelease(ctx, index, release, seen, options) {
|
|
|
28058
28086
|
}
|
|
28059
28087
|
if (manifest.docs) ctx.line(` docs: ${root}/${manifest.docs}`);
|
|
28060
28088
|
}
|
|
28061
|
-
async function
|
|
28089
|
+
async function download2(url) {
|
|
28062
28090
|
const response = await fetch(url);
|
|
28063
28091
|
if (!response.ok) {
|
|
28064
28092
|
throw new AppRegistryError(`${url} answered ${response.status} ${response.statusText}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sandboxedjs",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.97",
|
|
4
4
|
"description": "A Linux-like container that runs entirely inside Node.js — POSIX shell, ~140 coreutils, Node.js and Python runtimes, virtual filesystem and networking. No Docker, no VM, no native modules.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|