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/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Nodepod, DependencyInstaller } from '@scelar/nodepod/headless';
|
|
2
|
+
import { parse as parse$1 } from 'acorn';
|
|
2
3
|
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -17947,6 +17948,226 @@ async function readZip(data) {
|
|
|
17947
17948
|
function pythonCommands() {
|
|
17948
17949
|
return [python, pip];
|
|
17949
17950
|
}
|
|
17951
|
+
var DECLARES_EXPORTS = /(?:^|[\s;{)])(?:var|let|const|function|class)\s+exports\b/;
|
|
17952
|
+
var NAME = "exports";
|
|
17953
|
+
function renameShadowedExports(source) {
|
|
17954
|
+
if (!DECLARES_EXPORTS.test(source)) return null;
|
|
17955
|
+
let ast;
|
|
17956
|
+
try {
|
|
17957
|
+
ast = parse$1(source, {
|
|
17958
|
+
ecmaVersion: "latest",
|
|
17959
|
+
sourceType: "module",
|
|
17960
|
+
allowAwaitOutsideFunction: true,
|
|
17961
|
+
allowHashBang: true
|
|
17962
|
+
});
|
|
17963
|
+
} catch {
|
|
17964
|
+
return null;
|
|
17965
|
+
}
|
|
17966
|
+
const body = ast.body;
|
|
17967
|
+
const isModule = body.some(
|
|
17968
|
+
(node2) => node2.type.startsWith("Import") || node2.type.startsWith("Export")
|
|
17969
|
+
);
|
|
17970
|
+
if (!isModule) return null;
|
|
17971
|
+
const programScope = { bindsExports: hoistedNames(body).has(NAME), parent: null };
|
|
17972
|
+
if (!programScope.bindsExports) return null;
|
|
17973
|
+
const targets = [];
|
|
17974
|
+
let bail = false;
|
|
17975
|
+
visit(ast, programScope);
|
|
17976
|
+
if (bail || targets.length === 0) return null;
|
|
17977
|
+
const replacement = freshName(source);
|
|
17978
|
+
let out = source;
|
|
17979
|
+
for (const target of [...targets].sort((a, b) => b.start - a.start)) {
|
|
17980
|
+
const text = target.shorthand ? `${NAME}: ${replacement}` : replacement;
|
|
17981
|
+
out = out.slice(0, target.start) + text + out.slice(target.end);
|
|
17982
|
+
}
|
|
17983
|
+
return out;
|
|
17984
|
+
function visit(node2, scope) {
|
|
17985
|
+
if (bail) return;
|
|
17986
|
+
let childScope = scope;
|
|
17987
|
+
let skip = NOTHING;
|
|
17988
|
+
switch (node2.type) {
|
|
17989
|
+
case "FunctionDeclaration":
|
|
17990
|
+
case "FunctionExpression":
|
|
17991
|
+
case "ArrowFunctionExpression": {
|
|
17992
|
+
const names = /* @__PURE__ */ new Set();
|
|
17993
|
+
for (const param of node2.params ?? []) collectPattern(param, names);
|
|
17994
|
+
if (isExports(node2.id) && node2.type === "FunctionExpression") names.add(NAME);
|
|
17995
|
+
const fnBody = node2.body;
|
|
17996
|
+
if (fnBody?.type === "BlockStatement") {
|
|
17997
|
+
for (const name of hoistedNames(fnBody.body)) names.add(name);
|
|
17998
|
+
}
|
|
17999
|
+
childScope = { bindsExports: names.has(NAME), parent: scope };
|
|
18000
|
+
break;
|
|
18001
|
+
}
|
|
18002
|
+
case "CatchClause": {
|
|
18003
|
+
const names = /* @__PURE__ */ new Set();
|
|
18004
|
+
if (node2.param) collectPattern(node2.param, names);
|
|
18005
|
+
childScope = { bindsExports: names.has(NAME), parent: scope };
|
|
18006
|
+
break;
|
|
18007
|
+
}
|
|
18008
|
+
case "ClassDeclaration":
|
|
18009
|
+
case "ClassExpression":
|
|
18010
|
+
if (isExports(node2.id) && node2.type === "ClassExpression") {
|
|
18011
|
+
childScope = { bindsExports: true, parent: scope };
|
|
18012
|
+
}
|
|
18013
|
+
break;
|
|
18014
|
+
case "BlockStatement":
|
|
18015
|
+
case "StaticBlock":
|
|
18016
|
+
if (node2 !== ast.body) {
|
|
18017
|
+
childScope = {
|
|
18018
|
+
bindsExports: blockNames(node2.body).has(NAME),
|
|
18019
|
+
parent: scope
|
|
18020
|
+
};
|
|
18021
|
+
}
|
|
18022
|
+
break;
|
|
18023
|
+
case "ForStatement":
|
|
18024
|
+
case "ForInStatement":
|
|
18025
|
+
case "ForOfStatement": {
|
|
18026
|
+
const head2 = node2.init ?? node2.left;
|
|
18027
|
+
if (head2?.type === "VariableDeclaration" && head2.kind !== "var") {
|
|
18028
|
+
const names = /* @__PURE__ */ new Set();
|
|
18029
|
+
for (const declarator of head2.declarations) {
|
|
18030
|
+
collectPattern(declarator.id, names);
|
|
18031
|
+
}
|
|
18032
|
+
childScope = { bindsExports: names.has(NAME), parent: scope };
|
|
18033
|
+
}
|
|
18034
|
+
break;
|
|
18035
|
+
}
|
|
18036
|
+
/* `export { exports }` would have to become `exports as exports`, and
|
|
18037
|
+
* `import { exports as x }` names someone else's binding. Neither is
|
|
18038
|
+
* worth handling; refuse rather than rewrite them wrongly. */
|
|
18039
|
+
case "ExportSpecifier":
|
|
18040
|
+
case "ImportSpecifier":
|
|
18041
|
+
if (isExports(node2.local) || isExports(node2.exported) || isExports(node2.imported)) {
|
|
18042
|
+
bail = true;
|
|
18043
|
+
}
|
|
18044
|
+
return;
|
|
18045
|
+
case "Identifier":
|
|
18046
|
+
if (node2.name === NAME && resolvesToProgram(scope)) {
|
|
18047
|
+
targets.push({ start: node2.start, end: node2.end, shorthand: false });
|
|
18048
|
+
}
|
|
18049
|
+
return;
|
|
18050
|
+
// Property positions are names, not references to the binding.
|
|
18051
|
+
case "MemberExpression":
|
|
18052
|
+
case "MethodDefinition":
|
|
18053
|
+
case "PropertyDefinition":
|
|
18054
|
+
skip = node2.computed ? NOTHING : PROPERTY;
|
|
18055
|
+
break;
|
|
18056
|
+
case "Property":
|
|
18057
|
+
if (node2.computed) break;
|
|
18058
|
+
if (node2.shorthand) {
|
|
18059
|
+
const value = node2.value;
|
|
18060
|
+
if (isExports(value) && resolvesToProgram(scope)) {
|
|
18061
|
+
targets.push({ start: value.start, end: value.end, shorthand: true });
|
|
18062
|
+
}
|
|
18063
|
+
return;
|
|
18064
|
+
}
|
|
18065
|
+
skip = PROPERTY;
|
|
18066
|
+
break;
|
|
18067
|
+
case "LabeledStatement":
|
|
18068
|
+
case "BreakStatement":
|
|
18069
|
+
case "ContinueStatement":
|
|
18070
|
+
skip = LABEL;
|
|
18071
|
+
break;
|
|
18072
|
+
}
|
|
18073
|
+
for (const [key, value] of Object.entries(node2)) {
|
|
18074
|
+
if (key === "type" || key === "start" || key === "end" || skip.includes(key)) continue;
|
|
18075
|
+
if (Array.isArray(value)) {
|
|
18076
|
+
for (const item of value) if (isNode2(item)) visit(item, childScope);
|
|
18077
|
+
} else if (isNode2(value)) {
|
|
18078
|
+
visit(value, childScope);
|
|
18079
|
+
}
|
|
18080
|
+
}
|
|
18081
|
+
}
|
|
18082
|
+
}
|
|
18083
|
+
function resolvesToProgram(scope) {
|
|
18084
|
+
for (let current = scope; current; current = current.parent) {
|
|
18085
|
+
if (current.bindsExports) return current.parent === null;
|
|
18086
|
+
}
|
|
18087
|
+
return false;
|
|
18088
|
+
}
|
|
18089
|
+
function hoistedNames(body) {
|
|
18090
|
+
const names = blockNames(body);
|
|
18091
|
+
collectVars(body, names);
|
|
18092
|
+
return names;
|
|
18093
|
+
}
|
|
18094
|
+
function blockNames(body) {
|
|
18095
|
+
const names = /* @__PURE__ */ new Set();
|
|
18096
|
+
for (const node2 of body ?? []) {
|
|
18097
|
+
if (node2.type === "VariableDeclaration" && node2.kind !== "var") {
|
|
18098
|
+
for (const declarator of node2.declarations) {
|
|
18099
|
+
collectPattern(declarator.id, names);
|
|
18100
|
+
}
|
|
18101
|
+
} else if (node2.type === "ClassDeclaration" && isNode2(node2.id)) {
|
|
18102
|
+
names.add(node2.id.name);
|
|
18103
|
+
} else if (node2.type === "FunctionDeclaration" && isNode2(node2.id)) {
|
|
18104
|
+
names.add(node2.id.name);
|
|
18105
|
+
}
|
|
18106
|
+
}
|
|
18107
|
+
return names;
|
|
18108
|
+
}
|
|
18109
|
+
function collectVars(nodes, names) {
|
|
18110
|
+
if (Array.isArray(nodes)) {
|
|
18111
|
+
for (const item of nodes) collectVars(item, names);
|
|
18112
|
+
return;
|
|
18113
|
+
}
|
|
18114
|
+
if (!isNode2(nodes)) return;
|
|
18115
|
+
const node2 = nodes;
|
|
18116
|
+
if (node2.type === "FunctionDeclaration" || node2.type === "FunctionExpression" || node2.type === "ArrowFunctionExpression") {
|
|
18117
|
+
if (isNode2(node2.id)) names.add(node2.id.name);
|
|
18118
|
+
return;
|
|
18119
|
+
}
|
|
18120
|
+
if (node2.type === "VariableDeclaration" && node2.kind === "var") {
|
|
18121
|
+
for (const declarator of node2.declarations) {
|
|
18122
|
+
collectPattern(declarator.id, names);
|
|
18123
|
+
}
|
|
18124
|
+
}
|
|
18125
|
+
for (const [key, value] of Object.entries(node2)) {
|
|
18126
|
+
if (key === "type" || key === "start" || key === "end") continue;
|
|
18127
|
+
collectVars(value, names);
|
|
18128
|
+
}
|
|
18129
|
+
}
|
|
18130
|
+
function collectPattern(node2, names) {
|
|
18131
|
+
if (!isNode2(node2)) return;
|
|
18132
|
+
switch (node2.type) {
|
|
18133
|
+
case "Identifier":
|
|
18134
|
+
names.add(node2.name);
|
|
18135
|
+
return;
|
|
18136
|
+
case "ObjectPattern":
|
|
18137
|
+
for (const property of node2.properties) {
|
|
18138
|
+
collectPattern(property.value ?? property.argument, names);
|
|
18139
|
+
}
|
|
18140
|
+
return;
|
|
18141
|
+
case "ArrayPattern":
|
|
18142
|
+
for (const element of node2.elements) collectPattern(element, names);
|
|
18143
|
+
return;
|
|
18144
|
+
case "AssignmentPattern":
|
|
18145
|
+
collectPattern(node2.left, names);
|
|
18146
|
+
return;
|
|
18147
|
+
case "RestElement":
|
|
18148
|
+
collectPattern(node2.argument, names);
|
|
18149
|
+
return;
|
|
18150
|
+
default:
|
|
18151
|
+
return;
|
|
18152
|
+
}
|
|
18153
|
+
}
|
|
18154
|
+
function isExports(value) {
|
|
18155
|
+
return isNode2(value) && value.type === "Identifier" && value.name === NAME;
|
|
18156
|
+
}
|
|
18157
|
+
function freshName(source) {
|
|
18158
|
+
let name = "__sandboxedjs_exports";
|
|
18159
|
+
let suffix = 0;
|
|
18160
|
+
while (source.includes(name)) name = `__sandboxedjs_exports${++suffix}`;
|
|
18161
|
+
return name;
|
|
18162
|
+
}
|
|
18163
|
+
function isNode2(value) {
|
|
18164
|
+
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
18165
|
+
}
|
|
18166
|
+
var NOTHING = [];
|
|
18167
|
+
var PROPERTY = ["property", "key"];
|
|
18168
|
+
var LABEL = ["label"];
|
|
18169
|
+
|
|
18170
|
+
// src/pkg/index.ts
|
|
17950
18171
|
init_path();
|
|
17951
18172
|
var NPM_VERSION = "10.9.0";
|
|
17952
18173
|
function readManifest(ctx, dir3) {
|
|
@@ -18008,6 +18229,7 @@ async function installPackages(ctx, specs, opts) {
|
|
|
18008
18229
|
}
|
|
18009
18230
|
}
|
|
18010
18231
|
normalizeBinDirectories(ctx, opts.cwd);
|
|
18232
|
+
normalizeEsmExports(ctx, opts.cwd);
|
|
18011
18233
|
return 0;
|
|
18012
18234
|
} catch (e) {
|
|
18013
18235
|
ctx.warn(`npm error ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -18231,6 +18453,20 @@ function normalizeBinDirectories(ctx, root) {
|
|
|
18231
18453
|
if (basename(path) === ".bin" && path !== join(modules, ".bin")) visit(path);
|
|
18232
18454
|
}
|
|
18233
18455
|
}
|
|
18456
|
+
function normalizeEsmExports(ctx, root) {
|
|
18457
|
+
const modules = join(root, "node_modules");
|
|
18458
|
+
if (!ctx.vfs.lexists(modules)) return;
|
|
18459
|
+
for (const path of ctx.vfs.walk(modules, { cred: ctx.cred })) {
|
|
18460
|
+
if (!/\.(?:js|mjs)$/.test(path)) continue;
|
|
18461
|
+
try {
|
|
18462
|
+
if (!ctx.vfs.lstat(path).isFile()) continue;
|
|
18463
|
+
const source = ctx.vfs.readText(path, ctx.cred);
|
|
18464
|
+
const repaired = renameShadowedExports(source);
|
|
18465
|
+
if (repaired !== null) ctx.vfs.writeFile(path, repaired, { privileged: true });
|
|
18466
|
+
} catch {
|
|
18467
|
+
}
|
|
18468
|
+
}
|
|
18469
|
+
}
|
|
18234
18470
|
function printNpmHelp(ctx) {
|
|
18235
18471
|
ctx.line(`npm <command>`);
|
|
18236
18472
|
ctx.line("");
|