hackmud-script-manager 0.19.0-43367ba → 0.19.0-c12fd7c

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.
@@ -1 +1,394 @@
1
- import e from"@babel/traverse";import t from"@babel/types";import{v as i}from"../constants-9bb78688.js";import{getReferencePathsToGlobal as r}from"./shared.js";import{a as n}from"../assert-22a7ef8a.js";function clearObject(e,t){for(const t of Object.getOwnPropertyNames(e))delete e[t];for(const t of Object.getOwnPropertySymbols(e))delete e[t];void 0!==t&&Object.setPrototypeOf(e,t)}const{default:o}=e,a=["Map","Set","Date","JSON","Math","Array","Error","isNaN","Number","Object","RegExp","String","Symbol","BigInt"],transform=(e,s,{uniqueID:p="00000000000",scriptUser:l="UNKNOWN",scriptName:c="UNKNOWN",seclevel:d=4}={})=>{const f=`_${p}_SCRIPT_`,b=new Map,y=new Map;let $;if(o(e,{Program(e){$=e,e.skip()}}),$.scope.hasGlobal("_SOURCE"))for(const e of r("_SOURCE",$))e.replaceWith(t.stringLiteral(s));if($.scope.hasGlobal("_BUILD_DATE"))for(const e of r("_BUILD_DATE",$))e.replaceWith(t.numericLiteral(Date.now()));if($.scope.hasGlobal("_SCRIPT_USER"))for(const e of r("_SCRIPT_USER",$))1==l?e.replaceWith(t.stringLiteral(`$${p}$SCRIPT_USER$`)):e.replaceWith(t.stringLiteral(l));if($.scope.hasGlobal("_SCRIPT_NAME"))for(const e of r("_SCRIPT_NAME",$))1==c?e.replaceWith(t.stringLiteral(`$${p}$SCRIPT_NAME$`)):e.replaceWith(t.stringLiteral(c));if($.scope.hasGlobal("_FULL_SCRIPT_NAME"))for(const e of r("_FULL_SCRIPT_NAME",$))1==l||1==c?e.replaceWith(t.stringLiteral(`$${p}$FULL_SCRIPT_NAME$`)):e.replaceWith(t.stringLiteral(`${l}.${c}`));let m=!1;const createGetFunctionPrototypeNode=()=>{for(const e of a)if(!$.scope.hasOwnBinding(e))return t.memberExpression(t.memberExpression(t.identifier(e),t.identifier("constructor")),t.identifier("prototype"));return t.memberExpression(t.memberExpression(t.arrowFunctionExpression([t.identifier("_")],t.identifier("_")),t.identifier("constructor")),t.identifier("prototype"))};if($.scope.hasGlobal("Function")){const e=r("Function",$);if(1==e.length){const t=e[0];n("MemberExpression"==t.parent.type,"`Function` isn't available in hackmud, only `Function.prototype` is accessible"),n("Identifier"==t.parent.property.type,"`Function` isn't available in hackmud, only `Function.prototype` is accessible"),n("prototype"==t.parent.property.name,"`Function` isn't available in hackmud, only `Function.prototype` is accessible"),t.parentPath.replaceWith(createGetFunctionPrototypeNode())}else{for(const i of e)n("MemberExpression"==i.parent.type,"`Function` isn't available in hackmud, only `Function.prototype` is accessible"),n("Identifier"==i.parent.property.type,"`Function` isn't available in hackmud, only `Function.prototype` is accessible"),n("prototype"==i.parent.property.name,"`Function` isn't available in hackmud, only `Function.prototype` is accessible"),m=!0,i.parentPath.replaceWith(t.identifier(`_${p}_FUNCTION_DOT_PROTOTYPE_`));m=!0}}let h=4;const processFakeSubscriptObject=e=>{for(const a of r(e,$)){var i,o;n("MemberExpression"==a.parent.type),n("Identifier"==a.parent.property.type),n("MemberExpression"==(null===(i=a.parentPath.parentPath)||void 0===i?void 0:i.node.type)),n("Identifier"==a.parentPath.parentPath.node.property.type),n(/^[_a-z][\d_a-z]{0,24}$/.test(a.parent.property.name),`invalid user "${a.parent.property.name}" in subscript`),n(/^[_a-z][\d_a-z]{0,24}$/.test(a.parentPath.parentPath.node.property.name),`invalid script name "${a.parentPath.parentPath.node.property.name}" in subscript`),"CallExpression"==(null===(o=a.parentPath.parentPath.parentPath)||void 0===o?void 0:o.type)?a.parentPath.parentPath.replaceWith(t.identifier(`$${p}$SUBSCRIPT$${a.parent.property.name}$${a.parentPath.parentPath.node.property.name}$`)):a.parentPath.parentPath.replaceWith(t.arrowFunctionExpression([t.restElement(t.identifier("args"))],t.callExpression(t.identifier(`$${p}$SUBSCRIPT$${a.parent.property.name}$${a.parentPath.parentPath.node.property.name}$`),[t.spreadElement(t.identifier("args"))])))}};for(const e of["$fs","$4s","$s"])$.scope.hasGlobal(e)&&processFakeSubscriptObject(e);for(const e of["$hs","$3s"])$.scope.hasGlobal(e)&&(h=3,processFakeSubscriptObject(e));for(const e of["$ms","$2s"])$.scope.hasGlobal(e)&&(h=2,processFakeSubscriptObject(e));for(const e of["$ls","$1s"])$.scope.hasGlobal(e)&&(h=1,processFakeSubscriptObject(e));for(const e of["$ns","$0s"])$.scope.hasGlobal(e)&&(h=0,processFakeSubscriptObject(e));if(d=Math.min(d,h),$.scope.hasGlobal("$db"))for(const e of r("$db",$)){var E;n("MemberExpression"==e.parentPath.node.type),n("Identifier"==e.parentPath.node.property.type);const r=e.parentPath.node.property.name;n(i.includes(r),`invalid db method "${r}", valid db methods are "${i.join('", "')}"`),"CallExpression"==(null===(E=e.parentPath.parentPath)||void 0===E?void 0:E.type)?e.parentPath.replaceWith(t.identifier(`$${p}$DB$${r}$`)):"ObjectId"==r?e.parentPath.replaceWith(t.arrowFunctionExpression([],t.callExpression(t.identifier(`$${p}$DB$${r}$`),[]))):"i"==r||"r"==r?e.parentPath.replaceWith(t.arrowFunctionExpression([t.identifier("a")],t.callExpression(t.identifier(`$${p}$DB$${r}$`),[t.identifier("a")]))):e.parentPath.replaceWith(t.arrowFunctionExpression([t.identifier("a"),t.identifier("b")],t.callExpression(t.identifier(`$${p}$DB$${r}$`),[t.identifier("a"),t.identifier("b")])))}if($.scope.hasGlobal("$D"))for(const e of r("$D",$))"CallExpression"==e.parentPath.type?e.replaceWith(t.identifier(`$${p}$DEBUG$`)):e.replaceWith(t.arrowFunctionExpression([t.identifier("a")],t.callExpression(t.identifier(`$${p}$DEBUG$`),[t.identifier("a")])));if($.scope.hasGlobal("$FMCL"))for(const e of r("$FMCL",$))e.replaceWith(t.identifier(`$${p}$FMCL$`));if($.scope.hasGlobal("$G"))for(const e of r("$G",$))e.replaceWith(t.identifier(`$${p}$GLOBAL$`));if($.scope.hasGlobal("_SECLEVEL"))for(const e of r("_SECLEVEL",$))e.replaceWith(t.numericLiteral(d));let _=!1,u=!1;if($.scope.hasGlobal("Object"))for(const e of r("Object",$))"MemberExpression"!=e.parent.type||e.parent.computed||(n("Identifier"==e.parent.property.type),"getPrototypeOf"==e.parent.property.name?(e.parentPath.replaceWith(t.identifier(`_${p}_GET_PROTOTYPE_OF_`)),_=!0):"setPrototypeOf"==e.parent.property.name&&(e.parentPath.replaceWith(t.identifier(`_${p}_SET_PROTOTYPE_OF_`)),u=!0));const P=$.node.body[$.node.body.length-1];let x;if(n(P,"program is empty"),"ExportNamedDeclaration"==P.type){$.node.body.pop();for(const e of P.specifiers){n("ExportSpecifier"==e.type,`${e.type} is currently unsupported`);const t="Identifier"==e.exported.type?e.exported.name:e.exported.value;"default"==t?x=e.local.name:b.set(e.local.name,t)}}const O=t.blockStatement([]);let D;for(const e of $.node.body)if("VariableDeclaration"==e.type)for(const i of e.declarations)if("Identifier"!=i.id.type||i.id.name!=x||!i.init||"FunctionExpression"!=i.init.type&&"ArrowFunctionExpression"!=i.init.type||i.init.async||i.init.generator){for(const r in t.getBindingIdentifiers(i.id))r==x&&(D=t.functionDeclaration(t.identifier(f),[t.identifier("context"),t.identifier("args")],t.blockStatement([t.returnStatement(t.callExpression(t.identifier(x),[]))]))),"const"!=e.kind&&b.has(r)&&(y.set(r,b.get(r)),b.delete(r)),O.body.push(t.variableDeclaration("let",[t.variableDeclarator(t.identifier(r))]));i.init&&O.body.push(t.expressionStatement(t.assignmentExpression("=",i.id,i.init)))}else D=t.functionDeclaration(t.identifier(f),i.init.params,"BlockStatement"==i.init.body.type?i.init.body:t.blockStatement([t.returnStatement(i.init.body)]));else"FunctionDeclaration"==e.type?e.id.name==x?D=e:O.body.push(t.variableDeclaration("let",[t.variableDeclarator(e.id,t.functionExpression(void 0,e.params,e.body,e.generator,e.async))])):O.body.push(e);if(D||(D=t.functionDeclaration(t.identifier(f),[t.identifier("context"),t.identifier("args")],t.blockStatement([]))),$.node.body=[D],O.body.length){(b.size||y.size)&&D.body.body.push(t.returnStatement(t.objectExpression([...[...b].map((([e,i])=>t.objectProperty(t.identifier(i),t.identifier(e)))),...[...y].map((([e,i])=>t.objectMethod("get",t.identifier(i),[],t.blockStatement([t.returnStatement(t.identifier(e))]))))]))),$.scope.crawl();const e=new Set;let i=0;for(const[r,o]of[...O.body.entries()].reverse())if("VariableDeclaration"==o.type){n(1==o.declarations.length);const a=o.declarations[0];if(n("Identifier"==a.id.type,`declarator.id.type was "${a.id.type}"`),$.scope.crawl(),$.scope.hasGlobal(a.id.name)){O.body.splice(r,1);const[s]=$.unshiftContainer("body",O),[l]=$.unshiftContainer("body",o);if($.scope.crawl(),!a.init||"FunctionExpression"!=a.init.type&&"ArrowFunctionExpression"!=a.init.type||Object.keys($.scope.globals).some((t=>e.has(t)))){const e=$.scope.getBinding(a.id.name);n(e);for(const i of e.referencePaths)n("Identifier"==i.node.type),i.replaceWith(t.memberExpression(t.identifier(`$${p}$GLOBAL$`),t.identifier(i.node.name)));for(const i of e.constantViolations)if("AssignmentExpression"==i.node.type)for(const[e,r]of Object.entries(t.getBindingIdentifiers(i.node)))e==a.id.name&&(clearObject(r),Object.assign(r,t.memberExpression(t.identifier(`$${p}$GLOBAL$`),t.identifier(e))));s.remove(),l.remove(),a.init&&O.body.splice(r,0,t.expressionStatement(t.assignmentExpression("=",t.memberExpression(t.identifier(`$${p}$GLOBAL$`),t.identifier(a.id.name)),a.init)))}else s.remove(),l.remove(),D.body.body.unshift(o),i++}else e.add(a.id.name)}else if("ClassDeclaration"==o.type&&($.scope.crawl(),$.scope.hasGlobal(o.id.name))){O.body.splice(r,1);const[e]=$.unshiftContainer("body",O),[i]=$.unshiftContainer("body",o);$.scope.crawl();const a=$.scope.getBinding(o.id.name);n(a);for(const e of a.referencePaths)n("Identifier"==e.node.type),e.replaceWith(t.memberExpression(t.identifier(`$${p}$GLOBAL$`),t.identifier(e.node.name)));e.remove(),i.remove(),O.body.splice(r,0,t.expressionStatement(t.assignmentExpression("=",t.memberExpression(t.identifier(`$${p}$GLOBAL$`),t.identifier(o.id.name)),t.classExpression(void 0,o.superClass,o.body,o.decorators))))}if($.scope.hasGlobal("_EXPORTS"))for(const e of r("_EXPORTS",$))e.replaceWith(t.arrayExpression([...b.keys(),...y.keys()].map((e=>t.stringLiteral(e)))));O.body.length&&D.body.body.splice(i,0,t.ifStatement(t.unaryExpression("!",t.identifier(`$${p}$FMCL$`)),O))}return m&&D.body.body.unshift(t.variableDeclaration("let",[t.variableDeclarator(t.identifier(`_${p}_FUNCTION_DOT_PROTOTYPE_`),createGetFunctionPrototypeNode())])),u&&D.body.body.unshift(t.variableDeclaration("let",[t.variableDeclarator(t.identifier(`_${p}_SET_PROTOTYPE_OF_`),t.callExpression(t.memberExpression(t.memberExpression(t.identifier("Object"),t.identifier("call")),t.identifier("bind")),[t.identifier(`_${p}_DUNDER_PROTO_SETTER_`)]))])),_&&D.body.body.unshift(t.variableDeclaration("let",[t.variableDeclarator(t.identifier(`_${p}_GET_PROTOTYPE_OF_`),t.callExpression(t.memberExpression(t.memberExpression(t.identifier("Object"),t.identifier("call")),t.identifier("bind")),[t.identifier(`_${p}_DUNDER_PROTO_GETTER_`)]))])),(_||u)&&D.body.body.unshift(t.variableDeclaration("let",[t.variableDeclarator(t.objectPattern(_?u?[t.objectProperty(t.identifier("get"),t.identifier(`_${p}_DUNDER_PROTO_GETTER_`)),t.objectProperty(t.identifier("set"),t.identifier(`_${p}_DUNDER_PROTO_SETTER_`))]:[t.objectProperty(t.identifier("get"),t.identifier(`_${p}_DUNDER_PROTO_GETTER_`))]:[t.objectProperty(t.identifier("set"),t.identifier(`_${p}_DUNDER_PROTO_SETTER_`))]),t.callExpression(t.memberExpression(t.identifier("Object"),t.identifier("getOwnPropertyDescriptor")),[t.memberExpression(t.identifier("Object"),t.identifier("prototype")),t.stringLiteral("__proto__")]))])),o(e,{BlockStatement({node:e}){for(const[i,r]of e.body.entries())"FunctionDeclaration"!=r.type||r.generator||(e.body.splice(i,1),e.body.unshift(t.variableDeclaration("let",[t.variableDeclarator(r.id,t.arrowFunctionExpression(r.params,r.body,r.async))])))},ClassBody({node:e,scope:i,parent:r}){n(t.isClass(r));let a=!1;for(const r of e.body){if("ClassMethod"!=r.type)continue;let e=!1;if(o(r.body,{ThisExpression(i){e=!0,a=!0,i.replaceWith(t.identifier(`_${p}_THIS_`))},Function(e){e.skip()}},i),e)if("constructor"!=r.kind)r.body.body.unshift(t.variableDeclaration("let",[t.variableDeclarator(t.identifier(`_${p}_THIS_`),t.callExpression(t.memberExpression(t.super(),t.identifier("valueOf")),[]))]));else{const e=[];if(o(r.body,{CallExpression(t){"Super"==t.node.callee.type&&e.push(t)}},i),e.length)if(1==e.length&&"ExpressionStatement"==e[0].parent.type&&e[0].parentPath.parentPath.parent==r)e[0].parentPath.replaceWith(t.variableDeclaration("let",[t.variableDeclarator(t.identifier(`_${p}_THIS_`),e[0].node)]));else{for(const i of e)i.replaceWith(t.assignmentExpression("=",t.identifier(`_${p}_THIS_`),i.node));r.body.body.unshift(t.variableDeclaration("let",[t.variableDeclarator(t.identifier(`_${p}_THIS_`))]))}else r.body.body.unshift(t.variableDeclaration("let",[t.variableDeclarator(t.identifier(`_${p}_THIS_`),t.callExpression(t.super(),[]))]))}}!r.superClass&&a&&(r.superClass=t.identifier("Object"))},VariableDeclaration({node:e}){"const"==e.kind&&(e.kind="let")},ThisExpression(e){e.replaceWith(t.identifier("undefined"))},BigIntLiteral(e){const i=Number(e.node.value);BigInt(i)==BigInt(e.node.value)?e.replaceWith(t.callExpression(t.identifier("BigInt"),[t.numericLiteral(i)])):e.replaceWith(t.callExpression(t.identifier("BigInt"),[t.stringLiteral(e.node.value)]))}}),{file:e,seclevel:d}};export{transform as default,transform};
1
+ import babelTraverse from '@babel/traverse';
2
+ import t from '@babel/types';
3
+ import { assert } from '@samual/lib/assert';
4
+ import { clearObject } from '@samual/lib/clearObject';
5
+ import { validDBMethods } from '../constants.js';
6
+ import { getReferencePathsToGlobal } from './shared.js';
7
+
8
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
9
+ const {
10
+ default: traverse
11
+ } = babelTraverse;
12
+ const globalFunctionsUnder7Characters = [`Map`, `Set`, `Date`, `JSON`, `Math`, `Array`, `Error`, `isNaN`, `Number`, `Object`, `RegExp`, `String`, `Symbol`, `BigInt`];
13
+
14
+ /**
15
+ * transform a given babel `File` to be hackmud compatible
16
+ *
17
+ * (returned File will need `postprocess()`ing)
18
+ *
19
+ * @param file babel ast node representing a file containing preprocessed code
20
+ * @param sourceCode the original untouched source code
21
+ * @param options {@link TransformOptions details}
22
+ */
23
+ const transform = (file, sourceCode, {
24
+ uniqueID = `00000000000`,
25
+ scriptUser = `UNKNOWN`,
26
+ scriptName = `UNKNOWN`,
27
+ seclevel = 4
28
+ } = {}) => {
29
+ const topFunctionName = `_${uniqueID}_SCRIPT_`;
30
+ const exports = new Map();
31
+ const liveExports = new Map();
32
+ let program;
33
+ traverse(file, {
34
+ Program(path) {
35
+ program = path;
36
+ path.skip();
37
+ }
38
+ });
39
+ if (program.scope.hasGlobal(`_SOURCE`)) {
40
+ for (const referencePath of getReferencePathsToGlobal(`_SOURCE`, program)) referencePath.replaceWith(t.stringLiteral(sourceCode));
41
+ }
42
+ if (program.scope.hasGlobal(`_BUILD_DATE`)) {
43
+ for (const referencePath of getReferencePathsToGlobal(`_BUILD_DATE`, program)) referencePath.replaceWith(t.numericLiteral(Date.now()));
44
+ }
45
+ if (program.scope.hasGlobal(`_SCRIPT_USER`)) {
46
+ for (const referencePath of getReferencePathsToGlobal(`_SCRIPT_USER`, program)) {
47
+ if (scriptUser == true) referencePath.replaceWith(t.stringLiteral(`$${uniqueID}$SCRIPT_USER$`));else referencePath.replaceWith(t.stringLiteral(scriptUser));
48
+ }
49
+ }
50
+ if (program.scope.hasGlobal(`_SCRIPT_NAME`)) {
51
+ for (const referencePath of getReferencePathsToGlobal(`_SCRIPT_NAME`, program)) {
52
+ if (scriptName == true) referencePath.replaceWith(t.stringLiteral(`$${uniqueID}$SCRIPT_NAME$`));else referencePath.replaceWith(t.stringLiteral(scriptName));
53
+ }
54
+ }
55
+ if (program.scope.hasGlobal(`_FULL_SCRIPT_NAME`)) {
56
+ for (const referencePath of getReferencePathsToGlobal(`_FULL_SCRIPT_NAME`, program)) {
57
+ if (scriptUser == true || scriptName == true) referencePath.replaceWith(t.stringLiteral(`$${uniqueID}$FULL_SCRIPT_NAME$`));else referencePath.replaceWith(t.stringLiteral(`${scriptUser}.${scriptName}`));
58
+ }
59
+ }
60
+ let functionDotPrototypeIsReferencedMultipleTimes = false;
61
+ const createGetFunctionPrototypeNode = () => {
62
+ for (const globalFunction of globalFunctionsUnder7Characters) {
63
+ if (program.scope.hasOwnBinding(globalFunction)) continue;
64
+ return t.memberExpression(t.memberExpression(t.identifier(globalFunction), t.identifier(`constructor`)), t.identifier(`prototype`));
65
+ }
66
+ return t.memberExpression(t.memberExpression(t.arrowFunctionExpression([t.identifier(`_`)], t.identifier(`_`)), t.identifier(`constructor`)), t.identifier(`prototype`));
67
+ };
68
+ if (program.scope.hasGlobal(`Function`)) {
69
+ const FunctionReferencePaths = getReferencePathsToGlobal(`Function`, program);
70
+ if (FunctionReferencePaths.length == 1) {
71
+ const referencePath = FunctionReferencePaths[0];
72
+ assert(referencePath.parent.type == `MemberExpression`, `\`Function\` isn't available in hackmud, only \`Function.prototype\` is accessible`);
73
+ assert(referencePath.parent.property.type == `Identifier`, `\`Function\` isn't available in hackmud, only \`Function.prototype\` is accessible`);
74
+ assert(referencePath.parent.property.name == `prototype`, `\`Function\` isn't available in hackmud, only \`Function.prototype\` is accessible`);
75
+ referencePath.parentPath.replaceWith(createGetFunctionPrototypeNode());
76
+ } else {
77
+ for (const referencePath of FunctionReferencePaths) {
78
+ assert(referencePath.parent.type == `MemberExpression`, `\`Function\` isn't available in hackmud, only \`Function.prototype\` is accessible`);
79
+ assert(referencePath.parent.property.type == `Identifier`, `\`Function\` isn't available in hackmud, only \`Function.prototype\` is accessible`);
80
+ assert(referencePath.parent.property.name == `prototype`, `\`Function\` isn't available in hackmud, only \`Function.prototype\` is accessible`);
81
+ functionDotPrototypeIsReferencedMultipleTimes = true;
82
+ referencePath.parentPath.replaceWith(t.identifier(`_${uniqueID}_FUNCTION_DOT_PROTOTYPE_`));
83
+ }
84
+ functionDotPrototypeIsReferencedMultipleTimes = true;
85
+ }
86
+ }
87
+ let detectedSeclevel = 4;
88
+ const processFakeSubscriptObject = fakeSubscriptObjectName => {
89
+ for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
90
+ var _referencePath$parent, _referencePath$parent2;
91
+ assert(referencePath.parent.type == `MemberExpression`);
92
+ assert(referencePath.parent.property.type == `Identifier`);
93
+ assert(((_referencePath$parent = referencePath.parentPath.parentPath) === null || _referencePath$parent === void 0 ? void 0 : _referencePath$parent.node.type) == `MemberExpression`);
94
+ assert(referencePath.parentPath.parentPath.node.property.type == `Identifier`);
95
+ assert(/^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parent.property.name), `invalid user "${referencePath.parent.property.name}" in subscript`);
96
+ assert(/^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parentPath.parentPath.node.property.name), `invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`);
97
+ if (((_referencePath$parent2 = referencePath.parentPath.parentPath.parentPath) === null || _referencePath$parent2 === void 0 ? void 0 : _referencePath$parent2.type) == `CallExpression`) {
98
+ // BUG this is causing typescript to be slow
99
+ referencePath.parentPath.parentPath.replaceWith(t.identifier(`$${uniqueID}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`));
100
+ } else {
101
+ // BUG this is causing typescript to be slow
102
+ referencePath.parentPath.parentPath.replaceWith(t.arrowFunctionExpression([t.restElement(t.identifier(`args`))], t.callExpression(t.identifier(`$${uniqueID}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`), [t.spreadElement(t.identifier(`args`))])));
103
+ }
104
+ }
105
+ };
106
+ for (const fakeSubscriptObjectName of [`$fs`, `$4s`, `$s`]) {
107
+ if (program.scope.hasGlobal(fakeSubscriptObjectName)) processFakeSubscriptObject(fakeSubscriptObjectName);
108
+ }
109
+ for (const fakeSubscriptObjectName of [`$hs`, `$3s`]) {
110
+ if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
111
+ detectedSeclevel = 3;
112
+ processFakeSubscriptObject(fakeSubscriptObjectName);
113
+ }
114
+ }
115
+ for (const fakeSubscriptObjectName of [`$ms`, `$2s`]) {
116
+ if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
117
+ detectedSeclevel = 2;
118
+ processFakeSubscriptObject(fakeSubscriptObjectName);
119
+ }
120
+ }
121
+ for (const fakeSubscriptObjectName of [`$ls`, `$1s`]) {
122
+ if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
123
+ detectedSeclevel = 1;
124
+ processFakeSubscriptObject(fakeSubscriptObjectName);
125
+ }
126
+ }
127
+ for (const fakeSubscriptObjectName of [`$ns`, `$0s`]) {
128
+ if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
129
+ detectedSeclevel = 0;
130
+ processFakeSubscriptObject(fakeSubscriptObjectName);
131
+ }
132
+ }
133
+ seclevel = Math.min(seclevel, detectedSeclevel);
134
+ if (program.scope.hasGlobal(`$db`)) {
135
+ for (const referencePath of getReferencePathsToGlobal(`$db`, program)) {
136
+ var _referencePath$parent3;
137
+ assert(referencePath.parentPath.node.type == `MemberExpression`);
138
+ assert(referencePath.parentPath.node.property.type == `Identifier`);
139
+ const databaseOpMethodName = referencePath.parentPath.node.property.name;
140
+ assert(validDBMethods.includes(databaseOpMethodName), `invalid db method "${databaseOpMethodName}", valid db methods are "${validDBMethods.join(`", "`)}"`);
141
+ if (((_referencePath$parent3 = referencePath.parentPath.parentPath) === null || _referencePath$parent3 === void 0 ? void 0 : _referencePath$parent3.type) == `CallExpression`) referencePath.parentPath.replaceWith(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`));else if (databaseOpMethodName == `ObjectId`) {
142
+ referencePath.parentPath.replaceWith(t.arrowFunctionExpression([], t.callExpression(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`), [])));
143
+ } else if (databaseOpMethodName == `i` || databaseOpMethodName == `r`) {
144
+ referencePath.parentPath.replaceWith(t.arrowFunctionExpression([t.identifier(`a`)], t.callExpression(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`), [t.identifier(`a`)])));
145
+ } else {
146
+ referencePath.parentPath.replaceWith(t.arrowFunctionExpression([t.identifier(`a`), t.identifier(`b`)], t.callExpression(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`), [t.identifier(`a`), t.identifier(`b`)])));
147
+ }
148
+ }
149
+ }
150
+ if (program.scope.hasGlobal(`$D`)) {
151
+ for (const referencePath of getReferencePathsToGlobal(`$D`, program)) {
152
+ if (referencePath.parentPath.type == `CallExpression`) referencePath.replaceWith(t.identifier(`$${uniqueID}$DEBUG$`));else {
153
+ referencePath.replaceWith(t.arrowFunctionExpression([t.identifier(`a`)], t.callExpression(t.identifier(`$${uniqueID}$DEBUG$`), [t.identifier(`a`)])));
154
+ }
155
+ }
156
+ }
157
+ if (program.scope.hasGlobal(`$FMCL`)) {
158
+ for (const referencePath of getReferencePathsToGlobal(`$FMCL`, program)) referencePath.replaceWith(t.identifier(`$${uniqueID}$FMCL$`));
159
+ }
160
+ if (program.scope.hasGlobal(`$G`)) {
161
+ for (const referencePath of getReferencePathsToGlobal(`$G`, program)) referencePath.replaceWith(t.identifier(`$${uniqueID}$GLOBAL$`));
162
+ }
163
+ if (program.scope.hasGlobal(`_SECLEVEL`)) {
164
+ for (const referencePath of getReferencePathsToGlobal(`_SECLEVEL`, program)) referencePath.replaceWith(t.numericLiteral(seclevel));
165
+ }
166
+ let needGetPrototypeOf = false;
167
+ let needSetPrototypeOf = false;
168
+ if (program.scope.hasGlobal(`Object`)) {
169
+ for (const referencePath of getReferencePathsToGlobal(`Object`, program)) {
170
+ if (referencePath.parent.type != `MemberExpression` || referencePath.parent.computed) continue;
171
+ assert(referencePath.parent.property.type == `Identifier`);
172
+ if (referencePath.parent.property.name == `getPrototypeOf`) {
173
+ referencePath.parentPath.replaceWith(t.identifier(`_${uniqueID}_GET_PROTOTYPE_OF_`));
174
+ needGetPrototypeOf = true;
175
+ } else if (referencePath.parent.property.name == `setPrototypeOf`) {
176
+ referencePath.parentPath.replaceWith(t.identifier(`_${uniqueID}_SET_PROTOTYPE_OF_`));
177
+ needSetPrototypeOf = true;
178
+ }
179
+ }
180
+ }
181
+
182
+ // rollup removes all the inline exports and places a statement at the end instead
183
+ const lastStatement = program.node.body.at(-1);
184
+ let exportDefaultName;
185
+ assert(lastStatement, `program is empty`);
186
+ if (lastStatement.type == `ExportNamedDeclaration`) {
187
+ program.node.body.pop();
188
+ for (const specifier of lastStatement.specifiers) {
189
+ assert(specifier.type == `ExportSpecifier`, `${specifier.type} is currently unsupported`);
190
+ const exportedName = specifier.exported.type == `Identifier` ? specifier.exported.name : specifier.exported.value;
191
+ if (exportedName == `default`) exportDefaultName = specifier.local.name;else exports.set(specifier.local.name, exportedName);
192
+ }
193
+ }
194
+ const globalBlock = t.blockStatement([]);
195
+ let mainFunction;
196
+ for (const statement of program.node.body) {
197
+ if (statement.type == `VariableDeclaration`) {
198
+ for (const declarator of statement.declarations) {
199
+ if (declarator.id.type == `Identifier` && declarator.id.name == exportDefaultName && declarator.init && (declarator.init.type == `FunctionExpression` || declarator.init.type == `ArrowFunctionExpression`) && !declarator.init.async && !declarator.init.generator) {
200
+ mainFunction = t.functionDeclaration(t.identifier(topFunctionName), declarator.init.params, declarator.init.body.type == `BlockStatement` ? declarator.init.body : t.blockStatement([t.returnStatement(declarator.init.body)]));
201
+ continue;
202
+ }
203
+ for (const identifierName in t.getBindingIdentifiers(declarator.id)) {
204
+ if (identifierName == exportDefaultName) {
205
+ mainFunction = t.functionDeclaration(t.identifier(topFunctionName), [t.identifier(`context`), t.identifier(`args`)], t.blockStatement([t.returnStatement(t.callExpression(t.identifier(exportDefaultName), []))]));
206
+ }
207
+ if (statement.kind != `const` && exports.has(identifierName)) {
208
+ liveExports.set(identifierName, exports.get(identifierName));
209
+ exports.delete(identifierName);
210
+ }
211
+ globalBlock.body.push(t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(identifierName))]));
212
+ }
213
+ if (declarator.init) {
214
+ globalBlock.body.push(t.expressionStatement(t.assignmentExpression(`=`, declarator.id, declarator.init)));
215
+ }
216
+ }
217
+ } else if (statement.type == `FunctionDeclaration`) {
218
+ if (statement.id.name == exportDefaultName) mainFunction = statement;else {
219
+ globalBlock.body.push(t.variableDeclaration(`let`, [t.variableDeclarator(statement.id, t.functionExpression(undefined, statement.params, statement.body, statement.generator, statement.async))]));
220
+ }
221
+ } else globalBlock.body.push(statement);
222
+ }
223
+ mainFunction || (mainFunction = t.functionDeclaration(t.identifier(topFunctionName), [t.identifier(`context`), t.identifier(`args`)], t.blockStatement([])));
224
+ program.node.body = [mainFunction];
225
+ if (globalBlock.body.length) {
226
+ if (exports.size || liveExports.size) {
227
+ mainFunction.body.body.push(t.returnStatement(t.objectExpression([...[...exports].map(([local, exported]) => t.objectProperty(t.identifier(exported), t.identifier(local))), ...[...liveExports].map(([local, exported]) => t.objectMethod(`get`, t.identifier(exported), [], t.blockStatement([t.returnStatement(t.identifier(local))])))])));
228
+ }
229
+ program.scope.crawl();
230
+ const globalBlockVariables = new Set();
231
+ let hoistedGlobalBlockFunctions = 0;
232
+ for (const [globalBlockIndex, globalBlockStatement] of [...globalBlock.body.entries()].reverse()) {
233
+ if (globalBlockStatement.type == `VariableDeclaration`) {
234
+ assert(globalBlockStatement.declarations.length == 1);
235
+ const declarator = globalBlockStatement.declarations[0];
236
+ assert(declarator.id.type == `Identifier`, `declarator.id.type was "${declarator.id.type}"`);
237
+ program.scope.crawl();
238
+ if (program.scope.hasGlobal(declarator.id.name)) {
239
+ globalBlock.body.splice(globalBlockIndex, 1);
240
+ const [globalBlockPath] = program.unshiftContainer(`body`, globalBlock);
241
+ const [globalBlockStatementPath] = program.unshiftContainer(`body`, globalBlockStatement);
242
+ program.scope.crawl();
243
+ if (!declarator.init || declarator.init.type != `FunctionExpression` && declarator.init.type != `ArrowFunctionExpression` || Object.keys(program.scope.globals).some(global => globalBlockVariables.has(global))) {
244
+ const binding = program.scope.getBinding(declarator.id.name);
245
+ assert(binding);
246
+ for (const referencePath of binding.referencePaths) {
247
+ assert(referencePath.node.type == `Identifier`);
248
+ referencePath.replaceWith(t.memberExpression(t.identifier(`$${uniqueID}$GLOBAL$`), t.identifier(referencePath.node.name)));
249
+ }
250
+ for (const referencePath of binding.constantViolations) {
251
+ if (referencePath.node.type != `AssignmentExpression`) continue;
252
+ for (const [name, node] of Object.entries(t.getBindingIdentifiers(referencePath.node))) {
253
+ if (name == declarator.id.name) {
254
+ clearObject(node);
255
+ Object.assign(node, t.memberExpression(t.identifier(`$${uniqueID}$GLOBAL$`), t.identifier(name)));
256
+ }
257
+ }
258
+ }
259
+ globalBlockPath.remove();
260
+ globalBlockStatementPath.remove();
261
+ if (declarator.init) {
262
+ globalBlock.body.splice(globalBlockIndex, 0, t.expressionStatement(t.assignmentExpression(`=`, t.memberExpression(t.identifier(`$${uniqueID}$GLOBAL$`), t.identifier(declarator.id.name)), declarator.init)));
263
+ }
264
+ } else {
265
+ globalBlockPath.remove();
266
+ globalBlockStatementPath.remove();
267
+ mainFunction.body.body.unshift(globalBlockStatement);
268
+ hoistedGlobalBlockFunctions++;
269
+ }
270
+ } else globalBlockVariables.add(declarator.id.name);
271
+ } else if (globalBlockStatement.type == `ClassDeclaration`) {
272
+ program.scope.crawl();
273
+ if (program.scope.hasGlobal(globalBlockStatement.id.name)) {
274
+ globalBlock.body.splice(globalBlockIndex, 1);
275
+ const [globalBlockPath] = program.unshiftContainer(`body`, globalBlock);
276
+ const [globalBlockStatementPath] = program.unshiftContainer(`body`, globalBlockStatement);
277
+ program.scope.crawl();
278
+ const binding = program.scope.getBinding(globalBlockStatement.id.name);
279
+ assert(binding);
280
+ for (const referencePath of binding.referencePaths) {
281
+ assert(referencePath.node.type == `Identifier`);
282
+ referencePath.replaceWith(t.memberExpression(t.identifier(`$${uniqueID}$GLOBAL$`), t.identifier(referencePath.node.name)));
283
+ }
284
+ globalBlockPath.remove();
285
+ globalBlockStatementPath.remove();
286
+ globalBlock.body.splice(globalBlockIndex, 0, t.expressionStatement(t.assignmentExpression(`=`, t.memberExpression(t.identifier(`$${uniqueID}$GLOBAL$`), t.identifier(globalBlockStatement.id.name)), t.classExpression(undefined, globalBlockStatement.superClass, globalBlockStatement.body, globalBlockStatement.decorators))));
287
+ }
288
+ }
289
+ }
290
+ if (program.scope.hasGlobal(`_EXPORTS`)) {
291
+ for (const referencePath of getReferencePathsToGlobal(`_EXPORTS`, program)) {
292
+ referencePath.replaceWith(t.arrayExpression([...exports.keys(), ...liveExports.keys()].map(name => t.stringLiteral(name))));
293
+ }
294
+ }
295
+ if (globalBlock.body.length) {
296
+ mainFunction.body.body.splice(hoistedGlobalBlockFunctions, 0, t.ifStatement(t.unaryExpression(`!`, t.identifier(`$${uniqueID}$FMCL$`)), globalBlock));
297
+ }
298
+ }
299
+ if (functionDotPrototypeIsReferencedMultipleTimes) {
300
+ mainFunction.body.body.unshift(t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_FUNCTION_DOT_PROTOTYPE_`), createGetFunctionPrototypeNode())]));
301
+ }
302
+ if (needSetPrototypeOf) {
303
+ mainFunction.body.body.unshift(t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_SET_PROTOTYPE_OF_`), t.callExpression(t.memberExpression(t.memberExpression(t.identifier(`Object`), t.identifier(`call`)), t.identifier(`bind`)), [t.identifier(`_${uniqueID}_DUNDER_PROTO_SETTER_`)]))]));
304
+ }
305
+ if (needGetPrototypeOf) {
306
+ mainFunction.body.body.unshift(t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_GET_PROTOTYPE_OF_`), t.callExpression(t.memberExpression(t.memberExpression(t.identifier(`Object`), t.identifier(`call`)), t.identifier(`bind`)), [t.identifier(`_${uniqueID}_DUNDER_PROTO_GETTER_`)]))]));
307
+ }
308
+ if (needGetPrototypeOf || needSetPrototypeOf) {
309
+ mainFunction.body.body.unshift(t.variableDeclaration(`let`, [t.variableDeclarator(t.objectPattern(needGetPrototypeOf ? needSetPrototypeOf ? [t.objectProperty(t.identifier(`get`), t.identifier(`_${uniqueID}_DUNDER_PROTO_GETTER_`)), t.objectProperty(t.identifier(`set`), t.identifier(`_${uniqueID}_DUNDER_PROTO_SETTER_`))] : [t.objectProperty(t.identifier(`get`), t.identifier(`_${uniqueID}_DUNDER_PROTO_GETTER_`))] : [t.objectProperty(t.identifier(`set`), t.identifier(`_${uniqueID}_DUNDER_PROTO_SETTER_`))]), t.callExpression(t.memberExpression(t.identifier(`Object`), t.identifier(`getOwnPropertyDescriptor`)), [t.memberExpression(t.identifier(`Object`), t.identifier(`prototype`)), t.stringLiteral(`__proto__`)]))]));
310
+ }
311
+ traverse(file, {
312
+ BlockStatement({
313
+ node: blockStatement
314
+ }) {
315
+ for (const [index, functionDeclaration] of blockStatement.body.entries()) {
316
+ if (functionDeclaration.type != `FunctionDeclaration` || functionDeclaration.generator) continue;
317
+ blockStatement.body.splice(index, 1);
318
+ blockStatement.body.unshift(t.variableDeclaration(`let`, [t.variableDeclarator(functionDeclaration.id, t.arrowFunctionExpression(functionDeclaration.params, functionDeclaration.body, functionDeclaration.async))]));
319
+ }
320
+ },
321
+ ClassBody({
322
+ node: classBody,
323
+ scope,
324
+ parent
325
+ }) {
326
+ assert(t.isClass(parent));
327
+ let thisIsReferenced = false;
328
+ for (const classMethod of classBody.body) {
329
+ if (classMethod.type != `ClassMethod`) continue;
330
+ let methodReferencesThis = false;
331
+ traverse(classMethod.body, {
332
+ ThisExpression(path) {
333
+ methodReferencesThis = true;
334
+ thisIsReferenced = true;
335
+ path.replaceWith(t.identifier(`_${uniqueID}_THIS_`));
336
+ },
337
+ Function(path) {
338
+ path.skip();
339
+ }
340
+ }, scope);
341
+ if (!methodReferencesThis) continue;
342
+ if (classMethod.kind == `constructor`) {
343
+ const superCalls = [];
344
+ traverse(classMethod.body, {
345
+ CallExpression(path) {
346
+ if (path.node.callee.type == `Super`) superCalls.push(path);
347
+ }
348
+ }, scope);
349
+ if (!superCalls.length) {
350
+ classMethod.body.body.unshift(t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_THIS_`), t.callExpression(t.super(), []))]));
351
+ } else if (superCalls.length == 1 && superCalls[0].parent.type == `ExpressionStatement` && superCalls[0].parentPath.parentPath.parent == classMethod) {
352
+ superCalls[0].parentPath.replaceWith(t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_THIS_`), superCalls[0].node)]));
353
+ } else {
354
+ for (const path of superCalls) {
355
+ path.replaceWith(t.assignmentExpression(`=`, t.identifier(`_${uniqueID}_THIS_`), path.node));
356
+ }
357
+ classMethod.body.body.unshift(t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_THIS_`))]));
358
+ }
359
+ continue;
360
+ }
361
+
362
+ // BUG if the class or a super class overwrites `valueOf()` (or `Object.prototype` isn't even in the chain), this breaks
363
+ // TODO track whether the class is extending a class that at some point extends from `Object` (if unsure, assume no)
364
+ // TODO track whether any class in the chain overwrites `valueOf()` (if unsure, assume yes)
365
+ // TODO for classes that need it, create a super class for this one to extend from with `valueOf()` assigned to an unused name
366
+
367
+ classMethod.body.body.unshift(t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_THIS_`), t.callExpression(t.memberExpression(t.super(), t.identifier(`valueOf`)), []))]));
368
+ }
369
+ if (!parent.superClass && thisIsReferenced) parent.superClass = t.identifier(`Object`);
370
+ },
371
+ VariableDeclaration({
372
+ node: variableDeclaration
373
+ }) {
374
+ if (variableDeclaration.kind == `const`) variableDeclaration.kind = `let`;
375
+ },
376
+ ThisExpression(path) {
377
+ path.replaceWith(t.identifier(`undefined`));
378
+ },
379
+ BigIntLiteral(path) {
380
+ const bigIntAsNumber = Number(path.node.value);
381
+ if (BigInt(bigIntAsNumber) == BigInt(path.node.value)) {
382
+ path.replaceWith(t.callExpression(t.identifier(`BigInt`), [t.numericLiteral(bigIntAsNumber)]));
383
+ } else {
384
+ path.replaceWith(t.callExpression(t.identifier(`BigInt`), [t.stringLiteral(path.node.value)]));
385
+ }
386
+ }
387
+ });
388
+ return {
389
+ file,
390
+ seclevel
391
+ };
392
+ };
393
+
394
+ export { transform as default, transform };
package/pull.js CHANGED
@@ -1 +1,17 @@
1
- import{dirname as t,resolve as r}from"path";import s from"fs";const{mkdir:i,copyFile:o}=s.promises;const pull=async(s,e,a)=>{const[c,n]=a.split(".");if(!c||!n)throw new Error('`script` argument must be in "user.name" format');await function copyFilePersistent(r,s,e){return o(r,s,e).catch((async a=>{if("ENOENT"!=a.code)throw a;await i(t(s),{recursive:!0}),await o(r,s,e)}))}(r(e,c,"scripts",`${n}.js`),r(s,c,`${n}.js`))};export{pull as default,pull};
1
+ import { copyFilePersistent } from '@samual/lib/copyFilePersistent';
2
+ import { resolve } from 'path';
3
+
4
+ /**
5
+ * Copies script from hackmud to local source folder.
6
+ *
7
+ * @param sourceFolderPath path to folder containing source files
8
+ * @param hackmudPath path to hackmud directory
9
+ * @param script to pull in `user.name` format
10
+ */
11
+ const pull = async (sourceFolderPath, hackmudPath, script) => {
12
+ const [user, name] = script.split(`.`);
13
+ if (!user || !name) throw new Error(`\`script\` argument must be in "user.name" format`);
14
+ await copyFilePersistent(resolve(hackmudPath, user, `scripts`, `${name}.js`), resolve(sourceFolderPath, user, `${name}.js`));
15
+ };
16
+
17
+ export { pull as default, pull };
package/push.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { LaxPartial } from "@samual/lib";
2
- import { Info } from ".";
3
- export declare type PushOptions = {
1
+ import type { LaxPartial } from "@samual/lib";
2
+ import type { Info } from ".";
3
+ export type PushOptions = {
4
4
  /** whether to do the minify step (defaults to `true`) */
5
5
  minify: boolean;
6
6
  /** whether to mangle function and class names (defaults to `false`) */