hackmud-script-manager 0.19.0-50a29ed → 0.19.0-cd5548c

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1,310 @@
1
- import e from"@babel/generator";import{parse as o}from"@babel/parser";import r from"@babel/plugin-proposal-class-properties";import t from"@babel/plugin-proposal-class-static-block";import a from"@babel/plugin-proposal-decorators";import p from"@babel/plugin-proposal-json-strings";import s from"@babel/plugin-proposal-logical-assignment-operators";import l from"@babel/plugin-proposal-nullish-coalescing-operator";import i from"@babel/plugin-proposal-numeric-separator";import n from"@babel/plugin-proposal-object-rest-spread";import m from"@babel/plugin-proposal-optional-catch-binding";import c from"@babel/plugin-proposal-optional-chaining";import u from"@babel/plugin-proposal-private-property-in-object";import f from"@babel/plugin-transform-exponentiation-operator";import d from"@babel/traverse";import b from"@babel/types";import g from"@rollup/plugin-babel";import h from"@rollup/plugin-commonjs";import y from"@rollup/plugin-json";import w from"@rollup/plugin-node-resolve";import{resolve as k}from"path";import x from"prettier";import{rollup as j}from"rollup";import{s as v}from"../constants-9bb78688.js";import{minify as C}from"./minify.js";export{minify}from"./minify.js";import{postprocess as E}from"./postprocess.js";export{postprocess}from"./postprocess.js";import{preprocess as S}from"./preprocess.js";export{preprocess}from"./preprocess.js";import{includesIllegalString as L,replaceUnsafeStrings as $}from"./shared.js";import{transform as N}from"./transform.js";export{transform}from"./transform.js";import{a as I}from"../assert-22a7ef8a.js";import"acorn";import"terser";import"../spliceString-0e6b5d6d.js";import"../countHackmudCharacters-a08a265f.js";import"import-meta-resolve";const{default:P}=g,{format:D}=x,{default:_}=e,{default:M}=d,processScript=async(e,{minify:d=!0,uniqueID:g=Math.floor(Math.random()*2**52).toString(36).padStart(11,"0"),scriptUser:x="UNKNOWN",scriptName:O="UNKNOWN",filePath:T,mangleNames:U=!1,forceQuineCheats:W}={})=>{I(/^\w{11}$/.exec(g));const q=e;let F,H;const z=/^function\s*\(.+\/\/(?<autocomplete>.+)/.exec(e);if(z)e=`export default ${e}`,({autocomplete:F}=z.groups);else for(const o of e.split("\n")){const e=/^\s*\/\/(?<commentContent>.+)/.exec(o);if(!e)break;const r=e.groups.commentContent.trim();if(r.startsWith("@autocomplete "))F=r.slice(14).trimStart();else if(r.startsWith("@seclevel ")){const e=r.slice(10).trimStart().toLowerCase();switch(e){case"fullsec":case"full":case"fs":case"4s":case"f":case"4":H=4;break;case"highsec":case"high":case"hs":case"3s":case"h":case"3":H=3;break;case"midsec":case"mid":case"ms":case"2s":case"m":case"2":H=2;break;case"lowsec":case"low":case"ls":case"1s":case"l":case"1":H=1;break;case"nullsec":case"null":case"ns":case"0s":case"n":case"0":H=0;break;default:throw new Error(`unrecognised seclevel "${e}"`)}}}I(/^\w{11}$/.exec(g));const K=[[a.default,{decoratorsBeforeExport:!0}],[r.default],[t.default],[u.default],[s.default],[i.default],[l.default],[c.default],[m.default],[p.default],[n.default],[f.default]];let Q;if(T)if(Q=k(T),T.endsWith(".ts"))K.push([(await import("@babel/plugin-transform-typescript")).default,{allowDeclareFields:!0,optimizeConstEnums:!0}]);else{const[e,o,r,t,a,p,s]=await Promise.all([import("@babel/plugin-proposal-do-expressions"),import("@babel/plugin-proposal-function-bind"),import("@babel/plugin-proposal-function-sent"),import("@babel/plugin-proposal-partial-application"),import("@babel/plugin-proposal-pipeline-operator"),import("@babel/plugin-proposal-throw-expressions"),import("@babel/plugin-proposal-record-and-tuple")]);K.push([e.default],[o.default],[r.default],[t.default],[a.default,{proposal:"hack",topicToken:"%"}],[p.default],[s.default,{syntaxType:"hash",importPolyfill:!0}])}else{Q=`${g}.ts`;const[e,o,r,t,a,p,s,l]=await Promise.all([import("@babel/plugin-transform-typescript"),import("@babel/plugin-proposal-do-expressions"),import("@babel/plugin-proposal-function-bind"),import("@babel/plugin-proposal-function-sent"),import("@babel/plugin-proposal-partial-application"),import("@babel/plugin-proposal-pipeline-operator"),import("@babel/plugin-proposal-throw-expressions"),import("@babel/plugin-proposal-record-and-tuple")]);K.push([e.default,{allowDeclareFields:!0,optimizeConstEnums:!0}],[o.default],[r.default],[t.default],[a.default],[p.default,{proposal:"hack",topicToken:"%"}],[s.default],[l.default,{syntaxType:"hash",importPolyfill:!0}])}const V=await j({input:Q,plugins:[{name:"hackmud-script-manager",transform:async e=>(await S(e,{uniqueID:g})).code},P({babelHelpers:"bundled",plugins:K,configFile:!1,extensions:v}),h(),w({extensions:v}),y()],treeshake:{moduleSideEffects:!1}}),A=["NULLSEC","LOWSEC","MIDSEC","HIGHSEC","FULLSEC"];e=(await V.generate({})).output[0].code;const{file:B,seclevel:G}=N(o(e,{sourceType:"module"}),q,{uniqueID:g,scriptUser:x,scriptName:O});if(null!=H&&G<H)throw new Error(`detected seclevel ${A[G]} is lower than stated seclevel ${A[H]}`);if(e=_(B).code,d?e=await C(B,{uniqueID:g,mangleNames:U,forceQuineCheats:W,autocomplete:F}):(M(B,{MemberExpression({node:e}){e.computed||(I("Identifier"==e.property.type),"prototype"==e.property.name?(e.computed=!0,e.property=b.stringLiteral("prototype")):"__proto__"==e.property.name?(e.computed=!0,e.property=b.stringLiteral("__proto__")):L(e.property.name)&&(e.computed=!0,e.property=b.stringLiteral($(g,e.property.name))))},VariableDeclarator(e){const renameVariables=o=>{switch(o.type){case"Identifier":L(o.name)&&e.scope.rename(o.name,`$${Math.floor(Math.random()*2**52).toString(36).padStart(11,"0")}`);break;case"ObjectPattern":for(const e of o.properties)I("ObjectProperty"==e.type),renameVariables(e.value);break;case"ArrayPattern":for(const e of o.elements)e&&renameVariables(e);break;default:throw new Error(`unknown lValue type "${o.type}"`)}};renameVariables(e.node.id)},ObjectProperty({node:e}){"Identifier"==e.key.type&&L(e.key.name)&&(e.key=b.stringLiteral($(g,e.key.name)),e.shorthand=!1)},StringLiteral({node:e}){e.value=$(g,e.value)},TemplateLiteral({node:e}){for(const o of e.quasis)o.value.cooked?(o.value.cooked=$(g,o.value.cooked),o.value.raw=o.value.cooked.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"$\\{")):o.value.raw=$(g,o.value.raw)},RegExpLiteral(e){e.node.pattern=$(g,e.node.pattern),delete e.node.extra}}),e=D(_(B,{comments:!1}).code,{parser:"babel",arrowParens:"avoid",semi:!1,trailingComma:"none"})),e=E(e,G,g),L(e))throw new Error('you found a weird edge case where I wasn\'t able to replace illegal strings like "SC$", please report thx');return{script:e,warnings:[]}};export{processScript as default,processScript};
1
+ import babelGenerator from '@babel/generator';
2
+ import { parse } from '@babel/parser';
3
+ import babelPluginProposalClassProperties from '@babel/plugin-proposal-class-properties';
4
+ import babelPluginProposalClassStaticBlock from '@babel/plugin-proposal-class-static-block';
5
+ import babelPluginProposalDecorators from '@babel/plugin-proposal-decorators';
6
+ import babelPluginProposalJSONStrings from '@babel/plugin-proposal-json-strings';
7
+ import babelPluginProposalLogicalAssignmentOperators from '@babel/plugin-proposal-logical-assignment-operators';
8
+ import babelPluginProposalNullishCoalescingOperator from '@babel/plugin-proposal-nullish-coalescing-operator';
9
+ import babelPluginProposalNumericSeparator from '@babel/plugin-proposal-numeric-separator';
10
+ import babelPluginProposalObjectRestSpread from '@babel/plugin-proposal-object-rest-spread';
11
+ import babelPluginProposalOptionalCatchBinding from '@babel/plugin-proposal-optional-catch-binding';
12
+ import babelPluginProposalOptionalChaining from '@babel/plugin-proposal-optional-chaining';
13
+ import babelPluginProposalPrivatePropertyInObject from '@babel/plugin-proposal-private-property-in-object';
14
+ import babelPluginTransformExponentiationOperator from '@babel/plugin-transform-exponentiation-operator';
15
+ import babelTraverse from '@babel/traverse';
16
+ import t from '@babel/types';
17
+ import { babel } from '@rollup/plugin-babel';
18
+ import rollupPluginCommonJS from '@rollup/plugin-commonjs';
19
+ import rollupPluginJSON from '@rollup/plugin-json';
20
+ import rollupPluginNodeResolve from '@rollup/plugin-node-resolve';
21
+ import { assert } from '@samual/lib/assert';
22
+ import { resolve } from 'path';
23
+ import prettier from 'prettier';
24
+ import { rollup } from 'rollup';
25
+ import { supportedExtensions } from '../constants.js';
26
+ import { minify } from './minify.js';
27
+ import { postprocess } from './postprocess.js';
28
+ import { preprocess } from './preprocess.js';
29
+ import { includesIllegalString, replaceUnsafeStrings } from './shared.js';
30
+ import { transform } from './transform.js';
31
+ import '@samual/lib/countHackmudCharacters';
32
+ import '@samual/lib/spliceString';
33
+ import 'acorn';
34
+ import 'terser';
35
+ import 'import-meta-resolve';
36
+ import '@samual/lib/clearObject';
37
+
38
+ const {
39
+ format
40
+ } = prettier;
41
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
42
+ const {
43
+ default: generate
44
+ } = babelGenerator;
45
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
46
+ const {
47
+ default: traverse
48
+ } = babelTraverse;
49
+ /**
50
+ * Minifies a given script
51
+ *
52
+ * @param code JavaScript or TypeScript code
53
+ * @param options {@link ProcessOptions details}
54
+ */
55
+ const processScript = async (code, {
56
+ minify: shouldMinify = true,
57
+ uniqueID = Math.floor(Math.random() * 2 ** 52).toString(36).padStart(11, `0`),
58
+ scriptUser = `UNKNOWN`,
59
+ scriptName = `UNKNOWN`,
60
+ filePath,
61
+ mangleNames = false,
62
+ forceQuineCheats
63
+ } = {}) => {
64
+ assert(/^\w{11}$/.exec(uniqueID));
65
+ const sourceCode = code;
66
+ let autocomplete;
67
+ let statedSeclevel;
68
+
69
+ // TODO do seclevel detection and verification per module
70
+
71
+ const autocompleteMatch = /^function\s*\(.+\/\/(?<autocomplete>.+)/.exec(code);
72
+ if (autocompleteMatch) {
73
+ code = `export default ${code}`;
74
+ ({
75
+ autocomplete
76
+ } = autocompleteMatch.groups);
77
+ } else {
78
+ for (const line of code.split(`\n`)) {
79
+ const comment = /^\s*\/\/(?<commentContent>.+)/.exec(line);
80
+ if (!comment) break;
81
+ const commentContent = comment.groups.commentContent.trim();
82
+ if (commentContent.startsWith(`@autocomplete `)) autocomplete = commentContent.slice(14).trimStart();else if (commentContent.startsWith(`@seclevel `)) {
83
+ const seclevelString = commentContent.slice(10).trimStart().toLowerCase();
84
+ switch (seclevelString) {
85
+ case `fullsec`:
86
+ case `full`:
87
+ case `fs`:
88
+ case `4s`:
89
+ case `f`:
90
+ case `4`:
91
+ {
92
+ statedSeclevel = 4;
93
+ }
94
+ break;
95
+ case `highsec`:
96
+ case `high`:
97
+ case `hs`:
98
+ case `3s`:
99
+ case `h`:
100
+ case `3`:
101
+ {
102
+ statedSeclevel = 3;
103
+ }
104
+ break;
105
+ case `midsec`:
106
+ case `mid`:
107
+ case `ms`:
108
+ case `2s`:
109
+ case `m`:
110
+ case `2`:
111
+ {
112
+ statedSeclevel = 2;
113
+ }
114
+ break;
115
+ case `lowsec`:
116
+ case `low`:
117
+ case `ls`:
118
+ case `1s`:
119
+ case `l`:
120
+ case `1`:
121
+ {
122
+ statedSeclevel = 1;
123
+ }
124
+ break;
125
+ case `nullsec`:
126
+ case `null`:
127
+ case `ns`:
128
+ case `0s`:
129
+ case `n`:
130
+ case `0`:
131
+ {
132
+ statedSeclevel = 0;
133
+ }
134
+ break;
135
+ default:
136
+ // TODO turn into warninig when I get round to those
137
+ throw new Error(`unrecognised seclevel "${seclevelString}"`);
138
+ }
139
+ }
140
+ }
141
+ }
142
+ assert(/^\w{11}$/.exec(uniqueID));
143
+ const plugins = [[babelPluginProposalDecorators.default, {
144
+ decoratorsBeforeExport: true
145
+ }], [babelPluginProposalClassProperties.default], [babelPluginProposalClassStaticBlock.default], [babelPluginProposalPrivatePropertyInObject.default], [babelPluginProposalLogicalAssignmentOperators.default], [babelPluginProposalNumericSeparator.default], [babelPluginProposalNullishCoalescingOperator.default], [babelPluginProposalOptionalChaining.default], [babelPluginProposalOptionalCatchBinding.default], [babelPluginProposalJSONStrings.default], [babelPluginProposalObjectRestSpread.default], [babelPluginTransformExponentiationOperator.default]];
146
+ let filePathResolved;
147
+ if (filePath) {
148
+ filePathResolved = resolve(filePath);
149
+ if (filePath.endsWith(`.ts`)) plugins.push([(await import('@babel/plugin-transform-typescript')).default, {
150
+ allowDeclareFields: true,
151
+ optimizeConstEnums: true
152
+ }]);else {
153
+ const [babelPluginProposalDoExpressions, babelPluginProposalFunctionBind, babelPluginProposalFunctionSent, babelPluginProposalPartialApplication, babelPluginProposalPipelineOperator, babelPluginProposalThrowExpressions, babelPluginProposalRecordAndTuple] = await Promise.all([import('@babel/plugin-proposal-do-expressions'), import('@babel/plugin-proposal-function-bind'), import('@babel/plugin-proposal-function-sent'), import('@babel/plugin-proposal-partial-application'), import('@babel/plugin-proposal-pipeline-operator'), import('@babel/plugin-proposal-throw-expressions'), import('@babel/plugin-proposal-record-and-tuple')]);
154
+ plugins.push([babelPluginProposalDoExpressions.default], [babelPluginProposalFunctionBind.default], [babelPluginProposalFunctionSent.default], [babelPluginProposalPartialApplication.default], [babelPluginProposalPipelineOperator.default, {
155
+ proposal: `hack`,
156
+ topicToken: `%`
157
+ }], [babelPluginProposalThrowExpressions.default], [babelPluginProposalRecordAndTuple.default, {
158
+ syntaxType: `hash`,
159
+ importPolyfill: true
160
+ }]);
161
+ }
162
+ } else {
163
+ filePathResolved = `${uniqueID}.ts`;
164
+ const [babelPluginTransformTypescript, babelPluginProposalDoExpressions, babelPluginProposalFunctionBind, babelPluginProposalFunctionSent, babelPluginProposalPartialApplication, babelPluginProposalPipelineOperator, babelPluginProposalThrowExpressions, babelPluginProposalRecordAndTuple] = await Promise.all([import('@babel/plugin-transform-typescript'), import('@babel/plugin-proposal-do-expressions'), import('@babel/plugin-proposal-function-bind'), import('@babel/plugin-proposal-function-sent'), import('@babel/plugin-proposal-partial-application'), import('@babel/plugin-proposal-pipeline-operator'), import('@babel/plugin-proposal-throw-expressions'), import('@babel/plugin-proposal-record-and-tuple')]);
165
+ plugins.push([babelPluginTransformTypescript.default, {
166
+ allowDeclareFields: true,
167
+ optimizeConstEnums: true
168
+ }], [babelPluginProposalDoExpressions.default], [babelPluginProposalFunctionBind.default], [babelPluginProposalFunctionSent.default], [babelPluginProposalPartialApplication.default], [babelPluginProposalPipelineOperator.default, {
169
+ proposal: `hack`,
170
+ topicToken: `%`
171
+ }], [babelPluginProposalThrowExpressions.default], [babelPluginProposalRecordAndTuple.default, {
172
+ syntaxType: `hash`,
173
+ importPolyfill: true
174
+ }]);
175
+ }
176
+ const bundle = await rollup({
177
+ input: filePathResolved,
178
+ plugins: [{
179
+ name: `hackmud-script-manager`,
180
+ transform: async code => (await preprocess(code, {
181
+ uniqueID
182
+ })).code
183
+ }, babel({
184
+ babelHelpers: `bundled`,
185
+ plugins,
186
+ configFile: false,
187
+ extensions: supportedExtensions
188
+ }), rollupPluginCommonJS(), rollupPluginNodeResolve({
189
+ extensions: supportedExtensions
190
+ }), rollupPluginJSON()],
191
+ treeshake: {
192
+ moduleSideEffects: false
193
+ }
194
+ });
195
+ const seclevelNames = [`NULLSEC`, `LOWSEC`, `MIDSEC`, `HIGHSEC`, `FULLSEC`];
196
+ code = (await bundle.generate({})).output[0].code;
197
+ const {
198
+ file,
199
+ seclevel
200
+ } = transform(parse(code, {
201
+ sourceType: `module`
202
+ }), sourceCode, {
203
+ uniqueID,
204
+ scriptUser,
205
+ scriptName
206
+ });
207
+ if (statedSeclevel != undefined && seclevel < statedSeclevel)
208
+ // TODO replace with a warning and build script anyway
209
+ throw new Error(`detected seclevel ${seclevelNames[seclevel]} is lower than stated seclevel ${seclevelNames[statedSeclevel]}`);
210
+ code = generate(file).code;
211
+ if (shouldMinify) code = await minify(file, {
212
+ uniqueID,
213
+ mangleNames,
214
+ forceQuineCheats,
215
+ autocomplete
216
+ });else {
217
+ traverse(file, {
218
+ MemberExpression({
219
+ node: memberExpression
220
+ }) {
221
+ if (memberExpression.computed) return;
222
+ assert(memberExpression.property.type == `Identifier`);
223
+ if (memberExpression.property.name == `prototype`) {
224
+ memberExpression.computed = true;
225
+ memberExpression.property = t.stringLiteral(`prototype`);
226
+ } else if (memberExpression.property.name == `__proto__`) {
227
+ memberExpression.computed = true;
228
+ memberExpression.property = t.stringLiteral(`__proto__`);
229
+ } else if (includesIllegalString(memberExpression.property.name)) {
230
+ memberExpression.computed = true;
231
+ memberExpression.property = t.stringLiteral(replaceUnsafeStrings(uniqueID, memberExpression.property.name));
232
+ }
233
+ },
234
+ VariableDeclarator(path) {
235
+ const renameVariables = lValue => {
236
+ switch (lValue.type) {
237
+ case `Identifier`:
238
+ {
239
+ if (includesIllegalString(lValue.name)) path.scope.rename(lValue.name, `$${Math.floor(Math.random() * 2 ** 52).toString(36).padStart(11, `0`)}`);
240
+ }
241
+ break;
242
+ case `ObjectPattern`:
243
+ {
244
+ for (const property of lValue.properties) {
245
+ assert(property.type == `ObjectProperty`);
246
+ renameVariables(property.value);
247
+ }
248
+ }
249
+ break;
250
+ case `ArrayPattern`:
251
+ {
252
+ for (const element of lValue.elements) {
253
+ if (element) renameVariables(element);
254
+ }
255
+ }
256
+ break;
257
+ default:
258
+ throw new Error(`unknown lValue type "${lValue.type}"`);
259
+ }
260
+ };
261
+ renameVariables(path.node.id);
262
+ },
263
+ ObjectProperty({
264
+ node: objectProperty
265
+ }) {
266
+ if (objectProperty.key.type == `Identifier` && includesIllegalString(objectProperty.key.name)) {
267
+ objectProperty.key = t.stringLiteral(replaceUnsafeStrings(uniqueID, objectProperty.key.name));
268
+ objectProperty.shorthand = false;
269
+ }
270
+ },
271
+ StringLiteral({
272
+ node
273
+ }) {
274
+ node.value = replaceUnsafeStrings(uniqueID, node.value);
275
+ },
276
+ TemplateLiteral({
277
+ node
278
+ }) {
279
+ for (const templateElement of node.quasis) {
280
+ if (templateElement.value.cooked) {
281
+ templateElement.value.cooked = replaceUnsafeStrings(uniqueID, templateElement.value.cooked);
282
+ templateElement.value.raw = templateElement.value.cooked.replaceAll(`\\`, `\\\\`).replaceAll(`\``, `\\\``).replaceAll(`\${`, `$\\{`);
283
+ } else templateElement.value.raw = replaceUnsafeStrings(uniqueID, templateElement.value.raw);
284
+ }
285
+ },
286
+ RegExpLiteral(path) {
287
+ path.node.pattern = replaceUnsafeStrings(uniqueID, path.node.pattern);
288
+ delete path.node.extra;
289
+ }
290
+ });
291
+
292
+ // we can't have comments because they may contain illegal strings
293
+ code = await format(generate(file, {
294
+ comments: false
295
+ }).code, {
296
+ parser: `babel`,
297
+ arrowParens: `avoid`,
298
+ semi: false,
299
+ trailingComma: `none`
300
+ });
301
+ }
302
+ code = postprocess(code, seclevel, uniqueID);
303
+ if (includesIllegalString(code)) throw new Error(`you found a weird edge case where I wasn't able to replace illegal strings like "SC$", please report thx`);
304
+ return {
305
+ script: code,
306
+ warnings: []
307
+ };
308
+ };
309
+
310
+ export { processScript as default, minify, postprocess, preprocess, processScript, transform };
@@ -1,6 +1,6 @@
1
- import { File } from "@babel/types";
2
- import { LaxPartial } from "@samual/lib";
3
- declare type MinifyOptions = {
1
+ import type { File } from "@babel/types";
2
+ import type { LaxPartial } from "@samual/lib";
3
+ type MinifyOptions = {
4
4
  /** 11 a-z 0-9 characters */
5
5
  uniqueID: string;
6
6
  /** whether to mangle function and class names (defaults to `false`) */