sandboxedjs 0.1.1 → 0.1.2
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/README.md +5 -3
- package/dist/index.cjs +236 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +236 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -591,9 +591,11 @@ a tested claim.
|
|
|
591
591
|
|
|
592
592
|
Honest list of what does not work:
|
|
593
593
|
|
|
594
|
-
- **Vite's dev server**
|
|
595
|
-
|
|
596
|
-
|
|
594
|
+
- **Vite's dev server** loads and reads its config, then stops when esbuild starts: Nodepod
|
|
595
|
+
initialises esbuild by importing it from a CDN over `https:`, which the Node ESM loader
|
|
596
|
+
refuses. Anything that needs esbuild — Vite, and tools built on it — is therefore unavailable
|
|
597
|
+
under Node. Express, Koa, Fastify-style apps and plain `http` servers work. See
|
|
598
|
+
`examples/react-app` for a React setup that runs.
|
|
597
599
|
- **Python is MicroPython**, so C extensions (`numpy`, `pandas`, `cryptography`) are unavailable.
|
|
598
600
|
- **No real sockets.** HTTP servers work through the request proxy; raw TCP/UDP does not.
|
|
599
601
|
- **No real processes.** Processes are cooperative async tasks: `kill -9` cannot interrupt a
|
package/dist/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var headless = require('@scelar/nodepod/headless');
|
|
6
|
+
var acorn = require('acorn');
|
|
6
7
|
|
|
7
8
|
var __defProp = Object.defineProperty;
|
|
8
9
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -17951,6 +17952,226 @@ async function readZip(data) {
|
|
|
17951
17952
|
function pythonCommands() {
|
|
17952
17953
|
return [python, pip];
|
|
17953
17954
|
}
|
|
17955
|
+
var DECLARES_EXPORTS = /(?:^|[\s;{)])(?:var|let|const|function|class)\s+exports\b/;
|
|
17956
|
+
var NAME = "exports";
|
|
17957
|
+
function renameShadowedExports(source) {
|
|
17958
|
+
if (!DECLARES_EXPORTS.test(source)) return null;
|
|
17959
|
+
let ast;
|
|
17960
|
+
try {
|
|
17961
|
+
ast = acorn.parse(source, {
|
|
17962
|
+
ecmaVersion: "latest",
|
|
17963
|
+
sourceType: "module",
|
|
17964
|
+
allowAwaitOutsideFunction: true,
|
|
17965
|
+
allowHashBang: true
|
|
17966
|
+
});
|
|
17967
|
+
} catch {
|
|
17968
|
+
return null;
|
|
17969
|
+
}
|
|
17970
|
+
const body = ast.body;
|
|
17971
|
+
const isModule = body.some(
|
|
17972
|
+
(node2) => node2.type.startsWith("Import") || node2.type.startsWith("Export")
|
|
17973
|
+
);
|
|
17974
|
+
if (!isModule) return null;
|
|
17975
|
+
const programScope = { bindsExports: hoistedNames(body).has(NAME), parent: null };
|
|
17976
|
+
if (!programScope.bindsExports) return null;
|
|
17977
|
+
const targets = [];
|
|
17978
|
+
let bail = false;
|
|
17979
|
+
visit(ast, programScope);
|
|
17980
|
+
if (bail || targets.length === 0) return null;
|
|
17981
|
+
const replacement = freshName(source);
|
|
17982
|
+
let out = source;
|
|
17983
|
+
for (const target of [...targets].sort((a, b) => b.start - a.start)) {
|
|
17984
|
+
const text = target.shorthand ? `${NAME}: ${replacement}` : replacement;
|
|
17985
|
+
out = out.slice(0, target.start) + text + out.slice(target.end);
|
|
17986
|
+
}
|
|
17987
|
+
return out;
|
|
17988
|
+
function visit(node2, scope) {
|
|
17989
|
+
if (bail) return;
|
|
17990
|
+
let childScope = scope;
|
|
17991
|
+
let skip = NOTHING;
|
|
17992
|
+
switch (node2.type) {
|
|
17993
|
+
case "FunctionDeclaration":
|
|
17994
|
+
case "FunctionExpression":
|
|
17995
|
+
case "ArrowFunctionExpression": {
|
|
17996
|
+
const names = /* @__PURE__ */ new Set();
|
|
17997
|
+
for (const param of node2.params ?? []) collectPattern(param, names);
|
|
17998
|
+
if (isExports(node2.id) && node2.type === "FunctionExpression") names.add(NAME);
|
|
17999
|
+
const fnBody = node2.body;
|
|
18000
|
+
if (fnBody?.type === "BlockStatement") {
|
|
18001
|
+
for (const name of hoistedNames(fnBody.body)) names.add(name);
|
|
18002
|
+
}
|
|
18003
|
+
childScope = { bindsExports: names.has(NAME), parent: scope };
|
|
18004
|
+
break;
|
|
18005
|
+
}
|
|
18006
|
+
case "CatchClause": {
|
|
18007
|
+
const names = /* @__PURE__ */ new Set();
|
|
18008
|
+
if (node2.param) collectPattern(node2.param, names);
|
|
18009
|
+
childScope = { bindsExports: names.has(NAME), parent: scope };
|
|
18010
|
+
break;
|
|
18011
|
+
}
|
|
18012
|
+
case "ClassDeclaration":
|
|
18013
|
+
case "ClassExpression":
|
|
18014
|
+
if (isExports(node2.id) && node2.type === "ClassExpression") {
|
|
18015
|
+
childScope = { bindsExports: true, parent: scope };
|
|
18016
|
+
}
|
|
18017
|
+
break;
|
|
18018
|
+
case "BlockStatement":
|
|
18019
|
+
case "StaticBlock":
|
|
18020
|
+
if (node2 !== ast.body) {
|
|
18021
|
+
childScope = {
|
|
18022
|
+
bindsExports: blockNames(node2.body).has(NAME),
|
|
18023
|
+
parent: scope
|
|
18024
|
+
};
|
|
18025
|
+
}
|
|
18026
|
+
break;
|
|
18027
|
+
case "ForStatement":
|
|
18028
|
+
case "ForInStatement":
|
|
18029
|
+
case "ForOfStatement": {
|
|
18030
|
+
const head2 = node2.init ?? node2.left;
|
|
18031
|
+
if (head2?.type === "VariableDeclaration" && head2.kind !== "var") {
|
|
18032
|
+
const names = /* @__PURE__ */ new Set();
|
|
18033
|
+
for (const declarator of head2.declarations) {
|
|
18034
|
+
collectPattern(declarator.id, names);
|
|
18035
|
+
}
|
|
18036
|
+
childScope = { bindsExports: names.has(NAME), parent: scope };
|
|
18037
|
+
}
|
|
18038
|
+
break;
|
|
18039
|
+
}
|
|
18040
|
+
/* `export { exports }` would have to become `exports as exports`, and
|
|
18041
|
+
* `import { exports as x }` names someone else's binding. Neither is
|
|
18042
|
+
* worth handling; refuse rather than rewrite them wrongly. */
|
|
18043
|
+
case "ExportSpecifier":
|
|
18044
|
+
case "ImportSpecifier":
|
|
18045
|
+
if (isExports(node2.local) || isExports(node2.exported) || isExports(node2.imported)) {
|
|
18046
|
+
bail = true;
|
|
18047
|
+
}
|
|
18048
|
+
return;
|
|
18049
|
+
case "Identifier":
|
|
18050
|
+
if (node2.name === NAME && resolvesToProgram(scope)) {
|
|
18051
|
+
targets.push({ start: node2.start, end: node2.end, shorthand: false });
|
|
18052
|
+
}
|
|
18053
|
+
return;
|
|
18054
|
+
// Property positions are names, not references to the binding.
|
|
18055
|
+
case "MemberExpression":
|
|
18056
|
+
case "MethodDefinition":
|
|
18057
|
+
case "PropertyDefinition":
|
|
18058
|
+
skip = node2.computed ? NOTHING : PROPERTY;
|
|
18059
|
+
break;
|
|
18060
|
+
case "Property":
|
|
18061
|
+
if (node2.computed) break;
|
|
18062
|
+
if (node2.shorthand) {
|
|
18063
|
+
const value = node2.value;
|
|
18064
|
+
if (isExports(value) && resolvesToProgram(scope)) {
|
|
18065
|
+
targets.push({ start: value.start, end: value.end, shorthand: true });
|
|
18066
|
+
}
|
|
18067
|
+
return;
|
|
18068
|
+
}
|
|
18069
|
+
skip = PROPERTY;
|
|
18070
|
+
break;
|
|
18071
|
+
case "LabeledStatement":
|
|
18072
|
+
case "BreakStatement":
|
|
18073
|
+
case "ContinueStatement":
|
|
18074
|
+
skip = LABEL;
|
|
18075
|
+
break;
|
|
18076
|
+
}
|
|
18077
|
+
for (const [key, value] of Object.entries(node2)) {
|
|
18078
|
+
if (key === "type" || key === "start" || key === "end" || skip.includes(key)) continue;
|
|
18079
|
+
if (Array.isArray(value)) {
|
|
18080
|
+
for (const item of value) if (isNode2(item)) visit(item, childScope);
|
|
18081
|
+
} else if (isNode2(value)) {
|
|
18082
|
+
visit(value, childScope);
|
|
18083
|
+
}
|
|
18084
|
+
}
|
|
18085
|
+
}
|
|
18086
|
+
}
|
|
18087
|
+
function resolvesToProgram(scope) {
|
|
18088
|
+
for (let current = scope; current; current = current.parent) {
|
|
18089
|
+
if (current.bindsExports) return current.parent === null;
|
|
18090
|
+
}
|
|
18091
|
+
return false;
|
|
18092
|
+
}
|
|
18093
|
+
function hoistedNames(body) {
|
|
18094
|
+
const names = blockNames(body);
|
|
18095
|
+
collectVars(body, names);
|
|
18096
|
+
return names;
|
|
18097
|
+
}
|
|
18098
|
+
function blockNames(body) {
|
|
18099
|
+
const names = /* @__PURE__ */ new Set();
|
|
18100
|
+
for (const node2 of body ?? []) {
|
|
18101
|
+
if (node2.type === "VariableDeclaration" && node2.kind !== "var") {
|
|
18102
|
+
for (const declarator of node2.declarations) {
|
|
18103
|
+
collectPattern(declarator.id, names);
|
|
18104
|
+
}
|
|
18105
|
+
} else if (node2.type === "ClassDeclaration" && isNode2(node2.id)) {
|
|
18106
|
+
names.add(node2.id.name);
|
|
18107
|
+
} else if (node2.type === "FunctionDeclaration" && isNode2(node2.id)) {
|
|
18108
|
+
names.add(node2.id.name);
|
|
18109
|
+
}
|
|
18110
|
+
}
|
|
18111
|
+
return names;
|
|
18112
|
+
}
|
|
18113
|
+
function collectVars(nodes, names) {
|
|
18114
|
+
if (Array.isArray(nodes)) {
|
|
18115
|
+
for (const item of nodes) collectVars(item, names);
|
|
18116
|
+
return;
|
|
18117
|
+
}
|
|
18118
|
+
if (!isNode2(nodes)) return;
|
|
18119
|
+
const node2 = nodes;
|
|
18120
|
+
if (node2.type === "FunctionDeclaration" || node2.type === "FunctionExpression" || node2.type === "ArrowFunctionExpression") {
|
|
18121
|
+
if (isNode2(node2.id)) names.add(node2.id.name);
|
|
18122
|
+
return;
|
|
18123
|
+
}
|
|
18124
|
+
if (node2.type === "VariableDeclaration" && node2.kind === "var") {
|
|
18125
|
+
for (const declarator of node2.declarations) {
|
|
18126
|
+
collectPattern(declarator.id, names);
|
|
18127
|
+
}
|
|
18128
|
+
}
|
|
18129
|
+
for (const [key, value] of Object.entries(node2)) {
|
|
18130
|
+
if (key === "type" || key === "start" || key === "end") continue;
|
|
18131
|
+
collectVars(value, names);
|
|
18132
|
+
}
|
|
18133
|
+
}
|
|
18134
|
+
function collectPattern(node2, names) {
|
|
18135
|
+
if (!isNode2(node2)) return;
|
|
18136
|
+
switch (node2.type) {
|
|
18137
|
+
case "Identifier":
|
|
18138
|
+
names.add(node2.name);
|
|
18139
|
+
return;
|
|
18140
|
+
case "ObjectPattern":
|
|
18141
|
+
for (const property of node2.properties) {
|
|
18142
|
+
collectPattern(property.value ?? property.argument, names);
|
|
18143
|
+
}
|
|
18144
|
+
return;
|
|
18145
|
+
case "ArrayPattern":
|
|
18146
|
+
for (const element of node2.elements) collectPattern(element, names);
|
|
18147
|
+
return;
|
|
18148
|
+
case "AssignmentPattern":
|
|
18149
|
+
collectPattern(node2.left, names);
|
|
18150
|
+
return;
|
|
18151
|
+
case "RestElement":
|
|
18152
|
+
collectPattern(node2.argument, names);
|
|
18153
|
+
return;
|
|
18154
|
+
default:
|
|
18155
|
+
return;
|
|
18156
|
+
}
|
|
18157
|
+
}
|
|
18158
|
+
function isExports(value) {
|
|
18159
|
+
return isNode2(value) && value.type === "Identifier" && value.name === NAME;
|
|
18160
|
+
}
|
|
18161
|
+
function freshName(source) {
|
|
18162
|
+
let name = "__sandboxedjs_exports";
|
|
18163
|
+
let suffix = 0;
|
|
18164
|
+
while (source.includes(name)) name = `__sandboxedjs_exports${++suffix}`;
|
|
18165
|
+
return name;
|
|
18166
|
+
}
|
|
18167
|
+
function isNode2(value) {
|
|
18168
|
+
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
18169
|
+
}
|
|
18170
|
+
var NOTHING = [];
|
|
18171
|
+
var PROPERTY = ["property", "key"];
|
|
18172
|
+
var LABEL = ["label"];
|
|
18173
|
+
|
|
18174
|
+
// src/pkg/index.ts
|
|
17954
18175
|
init_path();
|
|
17955
18176
|
var NPM_VERSION = "10.9.0";
|
|
17956
18177
|
function readManifest(ctx, dir3) {
|
|
@@ -18012,6 +18233,7 @@ async function installPackages(ctx, specs, opts) {
|
|
|
18012
18233
|
}
|
|
18013
18234
|
}
|
|
18014
18235
|
normalizeBinDirectories(ctx, opts.cwd);
|
|
18236
|
+
normalizeEsmExports(ctx, opts.cwd);
|
|
18015
18237
|
return 0;
|
|
18016
18238
|
} catch (e) {
|
|
18017
18239
|
ctx.warn(`npm error ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -18235,6 +18457,20 @@ function normalizeBinDirectories(ctx, root) {
|
|
|
18235
18457
|
if (basename(path) === ".bin" && path !== join(modules, ".bin")) visit(path);
|
|
18236
18458
|
}
|
|
18237
18459
|
}
|
|
18460
|
+
function normalizeEsmExports(ctx, root) {
|
|
18461
|
+
const modules = join(root, "node_modules");
|
|
18462
|
+
if (!ctx.vfs.lexists(modules)) return;
|
|
18463
|
+
for (const path of ctx.vfs.walk(modules, { cred: ctx.cred })) {
|
|
18464
|
+
if (!/\.(?:js|mjs)$/.test(path)) continue;
|
|
18465
|
+
try {
|
|
18466
|
+
if (!ctx.vfs.lstat(path).isFile()) continue;
|
|
18467
|
+
const source = ctx.vfs.readText(path, ctx.cred);
|
|
18468
|
+
const repaired = renameShadowedExports(source);
|
|
18469
|
+
if (repaired !== null) ctx.vfs.writeFile(path, repaired, { privileged: true });
|
|
18470
|
+
} catch {
|
|
18471
|
+
}
|
|
18472
|
+
}
|
|
18473
|
+
}
|
|
18238
18474
|
function printNpmHelp(ctx) {
|
|
18239
18475
|
ctx.line(`npm <command>`);
|
|
18240
18476
|
ctx.line("");
|