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,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`) */
@@ -1 +1,376 @@
1
- import e from"@babel/generator";import t from"@babel/traverse";import r from"@babel/types";import{tokenizer as i,tokTypes as n}from"acorn";import*as a from"terser";import{getReferencePathsToGlobal as o,includesIllegalString as s,replaceUnsafeStrings as l}from"./shared.js";import{a as p}from"../assert-22a7ef8a.js";import{s as u}from"../spliceString-0e6b5d6d.js";import{c}from"../countHackmudCharacters-a08a265f.js";const{default:d}=e,{default:f}=t,minify=async(e,{uniqueID:t="00000000000",mangleNames:i=!1,forceQuineCheats:n,autocomplete:m}={})=>{let _;if(p(/^\w{11}$/.exec(t)),f(e,{Program(e){_=e,e.skip()}}),_.scope.hasGlobal("_START"))for(const e of o("_START",_))e.replaceWith(r.identifier("_ST"));if(_.scope.hasGlobal("_TIMEOUT"))for(const e of o("_TIMEOUT",_))e.replaceWith(r.identifier("_TO"));const y=_.get("body.0");for(const e of[...y.node.params].reverse()){if("Identifier"==e.type){if(!y.scope.getBinding(e.name).referenced){y.node.params.pop();continue}}break}for(const e in _.scope.globals){if("arguments"==e||e.startsWith(`$${t}$`))continue;const i=o(e,_);if(!(5+e.length+i.length>=e.length*i.length)){for(const n of i)n.replaceWith(r.identifier(`_${t}_GLOBAL_${e}_`));y.node.body.body.unshift(r.variableDeclaration("let",[r.variableDeclarator(r.identifier(`_${t}_GLOBAL_${e}_`),r.identifier(e))]))}}const $=o(`$${t}$GLOBAL$`,_);if($.length>3){for(const e of $)e.replaceWith(r.identifier(`_${t}_G_`));y.node.body.body.unshift(r.variableDeclaration("let",[r.variableDeclarator(r.identifier(`_${t}_G_`),r.identifier(`$${t}$GLOBAL$`))]))}const g=[];let E,b,v=!1;if(1!=n){const o=r.cloneNode(e);if(f(o,{MemberExpression({node:e}){e.computed||(p("Identifier"==e.property.type),"prototype"==e.property.name?(e.computed=!0,e.property=r.identifier(`_${t}_PROTOTYPE_PROPERTY_`)):"__proto__"==e.property.name?(e.computed=!0,e.property=r.identifier(`_${t}_PROTO_PROPERTY_`)):s(e.property.name)&&(e.computed=!0,e.property=r.stringLiteral(l(t,e.property.name))))},ObjectProperty({node:e}){"Identifier"==e.key.type&&s(e.key.name)&&(e.key=r.stringLiteral(l(t,e.key.name)),e.shorthand=!1)},StringLiteral({node:e}){e.value=l(t,e.value)},TemplateLiteral({node:e}){for(const r of e.quasis)r.value.cooked?(r.value.cooked=l(t,r.value.cooked),r.value.raw=r.value.cooked.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"$\\{")):r.value.raw=l(t,r.value.raw)},RegExpLiteral(e){e.node.pattern=l(t,e.node.pattern),delete e.node.extra}}),E=(await a.minify(d(o).code,{ecma:2015,compress:{passes:1/0,unsafe:!0,unsafe_arrows:!0,unsafe_comps:!0,unsafe_symbols:!0,unsafe_methods:!0,unsafe_proto:!0,unsafe_regexp:!0,unsafe_undefined:!0,sequences:!1},format:{semicolons:!1},keep_classnames:!i,keep_fnames:!i})).code.replace(new RegExp(`_${t}_PROTOTYPE_PROPERTY_`,"g"),'"prototype"').replace(new RegExp(`_${t}_PROTO_PROPERTY_`,"g"),'"__proto__"'),m&&(E=u(E,`//${m}\n`,getFunctionBodyStart(E)+1)),0==n)return E}let h,k=!1;{const i=[];f(e,{FunctionDeclaration(e){e.traverse({Function(e){"CallExpression"!=e.parent.type&&"callee"!=e.parentKey&&e.skip()},Loop(e){e.skip()},ObjectExpression(e){const i={};parseObjectExpression(e.node,i)&&e.replaceWith(r.identifier(`_${t}_JSON_VALUE_${g.push(i)-1}_`))},ArrayExpression(e){const i=[];parseArrayExpression(e.node,i)&&e.replaceWith(r.identifier(`_${t}_JSON_VALUE_${g.push(i)-1}_`))}}),e.traverse({TemplateLiteral(e){if("TaggedTemplateExpression"==e.parent.type)return;const t=e.node;let i=r.stringLiteral(t.quasis[0].value.cooked);for(let e=0;e<t.expressions.length;e++){const n=t.expressions[e],a=t.quasis[e+1];i=r.binaryExpression("+",i,n),a.value.cooked&&(i=r.binaryExpression("+",i,r.stringLiteral(a.value.cooked)))}e.replaceWith(i)},MemberExpression({node:e}){e.computed||(p("Identifier"==e.property.type),e.property.name.length<3||(e.computed=!0,e.property=r.stringLiteral(e.property.name)))},UnaryExpression(e){if("void"==e.node.operator)"NumericLiteral"!=e.node.argument.type||e.node.argument.value||(e.replaceWith(r.identifier(`_${t}_UNDEFINED_`)),v=!0);else if("-"==e.node.operator&&"NumericLiteral"==e.node.argument.type){const n=-e.node.argument.value;i.push((async()=>{if((await minifyNumber(n)).length<=3)return;"key"==e.parentKey&&"ObjectProperty"==e.parent.type&&(e.parent.computed=!0);let i=g.indexOf(n);-1==i&&(i+=g.push(n)),e.replaceWith(r.identifier(`_${t}_JSON_VALUE_${i}_`))})()),e.skip()}},NullLiteral(e){let i=g.indexOf(null);-1==i&&(i+=g.push(null)),e.replaceWith(r.identifier(`_${t}_JSON_VALUE_${i}_`))},NumericLiteral(e){i.push((async()=>{if((await minifyNumber(e.node.value)).length<=3)return;"key"==e.parentKey&&"ObjectProperty"==e.parent.type&&(e.parent.computed=!0);let i=g.indexOf(e.node.value);-1==i&&(i+=g.push(e.node.value)),e.replaceWith(r.identifier(`_${t}_JSON_VALUE_${i}_`))})())},StringLiteral(e){if(e.node.value=l(t,e.node.value),JSON.stringify(e.node.value).includes("\\u00")||e.toString().length<4)return;"key"==e.parentKey&&"ObjectProperty"==e.parent.type&&(e.parent.computed=!0);let i=g.indexOf(e.node.value);-1==i&&(i+=g.push(e.node.value)),e.replaceWith(r.identifier(`_${t}_JSON_VALUE_${i}_`))},ObjectProperty({node:e}){if(e.computed||"Identifier"!=e.key.type||e.key.name.length<4)return;let i=g.indexOf(e.key.name);-1==i&&(i+=g.push(e.key.name)),e.computed=!0,e.key=r.identifier(`_${t}_JSON_VALUE_${i}_`)},RegExpLiteral(e){e.node.pattern=l(t,e.node.pattern),delete e.node.extra}}),e.skip()}}),await Promise.all(i);const n=e.program.body[0];if(p("FunctionDeclaration"==n.type),g.length)if(k=!0,1==g.length)if("string"!=typeof g[0]||g[0].includes("\n")||g[0].includes("\t")){const e=r.variableDeclaration("let",[r.variableDeclarator(r.identifier(`_${t}_JSON_VALUE_0_`),r.callExpression(r.memberExpression(r.identifier("JSON"),r.identifier("parse")),[r.memberExpression(r.taggedTemplateExpression(r.memberExpression(r.callExpression(r.identifier(`$${t}$SUBSCRIPT$scripts$quine$`),[]),r.identifier("split")),r.templateLiteral([r.templateElement({raw:"\t",cooked:"\t"},!0)],[])),r.identifier(`$${t}$SPLIT_INDEX$`),!0)]))]);v&&e.declarations.push(r.variableDeclarator(r.identifier(`_${t}_UNDEFINED_`))),n.body.body.unshift(e),b=JSON.stringify(g[0])}else{const e=r.variableDeclaration("let",[r.variableDeclarator(r.identifier(`_${t}_JSON_VALUE_0_`),r.memberExpression(r.taggedTemplateExpression(r.memberExpression(r.callExpression(r.identifier(`$${t}$SUBSCRIPT$scripts$quine$`),[]),r.identifier("split")),r.templateLiteral([r.templateElement({raw:"\t",cooked:"\t"},!0)],[])),r.identifier(`$${t}$SPLIT_INDEX$`),!0))]);v&&e.declarations.push(r.variableDeclarator(r.identifier(`_${t}_UNDEFINED_`))),n.body.body.unshift(e),b=g[0]}else{const e=r.variableDeclaration("let",[r.variableDeclarator(r.arrayPattern(g.map(((e,i)=>r.identifier(`_${t}_JSON_VALUE_${i}_`)))),r.callExpression(r.memberExpression(r.identifier("JSON"),r.identifier("parse")),[r.memberExpression(r.taggedTemplateExpression(r.memberExpression(r.callExpression(r.identifier(`$${t}$SUBSCRIPT$scripts$quine$`),[]),r.identifier("split")),r.templateLiteral([r.templateElement({raw:"\t",cooked:"\t"},!0)],[])),r.identifier(`$${t}$SPLIT_INDEX$`),!0)]))]);v&&e.declarations.push(r.variableDeclarator(r.identifier(`_${t}_UNDEFINED_`))),n.body.body.unshift(e),b=JSON.stringify(g)}else v&&n.body.body.unshift(r.variableDeclaration("let",[r.variableDeclarator(r.identifier(`_${t}_UNDEFINED_`))]));h=d(e).code}return h=(await a.minify(h,{ecma:2015,compress:{passes:1/0,unsafe:!0,unsafe_arrows:!0,unsafe_comps:!0,unsafe_symbols:!0,unsafe_methods:!0,unsafe_proto:!0,unsafe_regexp:!0,unsafe_undefined:!0,sequences:!1},format:{semicolons:!1},keep_classnames:!i,keep_fnames:!i})).code||"",null!=b&&(h=u(h,`${m?`//${m}\n`:""}\n//\t${b}\t\n`,getFunctionBodyStart(h)+1),h=h.replace(`$${t}$SPLIT_INDEX$`,await minifyNumber(h.split("\t").findIndex((e=>e==b))))),1==n?h:(p(E),c(E)<=c(h)+Number(k)?E:h)},parseObjectExpression=(e,t)=>{if(!e.properties.length)return!1;for(const r of e.properties){if("ObjectProperty"!=r.type||r.computed)return!1;if(p("Identifier"==r.key.type||"NumericLiteral"==r.key.type||"StringLiteral"==r.key.type),"ArrayExpression"==r.value.type){const e=[];if(!parseArrayExpression(r.value,e))return!1;t["Identifier"==r.key.type?r.key.name:r.key.value]=e}else if("ObjectExpression"==r.value.type){const e={};if(!parseObjectExpression(r.value,e))return!1;t["Identifier"==r.key.type?r.key.name:r.key.value]=e}else if("NullLiteral"==r.value.type)t["Identifier"==r.key.type?r.key.name:r.key.value]=null;else if("BooleanLiteral"==r.value.type||"NumericLiteral"==r.value.type||"StringLiteral"==r.value.type)t["Identifier"==r.key.type?r.key.name:r.key.value]=r.value.value;else{if("TemplateLiteral"!=r.value.type||r.value.expressions.length)return!1;t["Identifier"==r.key.type?r.key.name:r.key.value]=r.value.quasis[0].value.cooked}}return!0},parseArrayExpression=(e,t)=>{if(!e.elements.length)return!1;for(const r of e.elements){if(!r)return!1;if("ArrayExpression"==r.type){const e=[];if(!parseArrayExpression(r,e))return!1;e.push(e)}else if("ObjectExpression"==r.type){const e={};if(!parseObjectExpression(r,e))return!1;t.push(e)}else if("NullLiteral"==r.type)t.push(null);else if("BooleanLiteral"==r.type||"NumericLiteral"==r.type||"StringLiteral"==r.type)t.push(r.value);else{if("TemplateLiteral"!=r.type||r.expressions.length)return!1;t.push(r.quasis[0].value.cooked)}}return!0},minifyNumber=async e=>/\$\((?<number>.+)\)/.exec((await a.minify(`$(${e})`,{ecma:2015})).code).groups.number,getFunctionBodyStart=e=>{const t=i(e,{ecmaVersion:2015});t.getToken(),t.getToken(),t.getToken();let r=1;for(;r;){const e=t.getToken();e.type==n.parenL?r++:e.type==n.parenR&&r--}return t.getToken().start};export{minify as default,minify};
1
+ import babelGenerator from '@babel/generator';
2
+ import babelTraverse from '@babel/traverse';
3
+ import t from '@babel/types';
4
+ import { assert } from '@samual/lib/assert';
5
+ import { countHackmudCharacters } from '@samual/lib/countHackmudCharacters';
6
+ import { spliceString } from '@samual/lib/spliceString';
7
+ import { tokenizer, tokTypes } from 'acorn';
8
+ import * as terser from 'terser';
9
+ import { getReferencePathsToGlobal, includesIllegalString, replaceUnsafeStrings } from './shared.js';
10
+
11
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
12
+ const {
13
+ default: generate
14
+ } = babelGenerator;
15
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
16
+ const {
17
+ default: traverse
18
+ } = babelTraverse;
19
+ // TODO move autocomplete code outside this function
20
+ // TODO replace references to `arguments`
21
+ /**
22
+ * @param file babel ast node representing a file containing transformed code
23
+ * @param options {@link MinifyOptions details}
24
+ */
25
+ const minify = async (file, {
26
+ uniqueID = `00000000000`,
27
+ mangleNames = false,
28
+ forceQuineCheats,
29
+ autocomplete
30
+ } = {}) => {
31
+ assert(/^\w{11}$/.exec(uniqueID));
32
+ let program;
33
+ traverse(file, {
34
+ Program(path) {
35
+ program = path;
36
+ path.skip();
37
+ }
38
+ });
39
+ if (program.scope.hasGlobal(`_START`)) {
40
+ for (const referencePath of getReferencePathsToGlobal(`_START`, program)) referencePath.replaceWith(t.identifier(`_ST`));
41
+ }
42
+ if (program.scope.hasGlobal(`_TIMEOUT`)) {
43
+ for (const referencePath of getReferencePathsToGlobal(`_TIMEOUT`, program)) referencePath.replaceWith(t.identifier(`_TO`));
44
+ }
45
+
46
+ // typescript does not like NodePath#get() and becomes slow so I have to dance around it
47
+ const mainFunctionPath = program.get(`body.0`);
48
+ for (const parameter of [...mainFunctionPath.node.params].reverse()) {
49
+ if (parameter.type == `Identifier`) {
50
+ const binding = mainFunctionPath.scope.getBinding(parameter.name);
51
+ if (!binding.referenced) {
52
+ mainFunctionPath.node.params.pop();
53
+ continue;
54
+ }
55
+ }
56
+ break;
57
+ }
58
+ for (const global in program.scope.globals) {
59
+ if (global == `arguments` || global.startsWith(`$${uniqueID}$`)) continue;
60
+ const referencePaths = getReferencePathsToGlobal(global, program);
61
+ if (5 + global.length + referencePaths.length >= global.length * referencePaths.length) continue;
62
+ for (const path of referencePaths) path.replaceWith(t.identifier(`_${uniqueID}_GLOBAL_${global}_`));
63
+ mainFunctionPath.node.body.body.unshift(t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_GLOBAL_${global}_`), t.identifier(global))]));
64
+ }
65
+ const hashGReferencePaths = getReferencePathsToGlobal(`$${uniqueID}$GLOBAL$`, program);
66
+ if (hashGReferencePaths.length > 3) {
67
+ for (const path of hashGReferencePaths) path.replaceWith(t.identifier(`_${uniqueID}_G_`));
68
+ mainFunctionPath.node.body.body.unshift(t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_G_`), t.identifier(`$${uniqueID}$GLOBAL$`))]));
69
+ }
70
+ const jsonValues = [];
71
+ // this needs `as boolean` because typescript is dumb
72
+ let undefinedIsReferenced = false;
73
+ let scriptBeforeJSONValueReplacement;
74
+ if (forceQuineCheats != true) {
75
+ const fileBeforeJSONValueReplacement = t.cloneNode(file);
76
+ traverse(fileBeforeJSONValueReplacement, {
77
+ MemberExpression({
78
+ node: memberExpression
79
+ }) {
80
+ if (memberExpression.computed) return;
81
+ assert(memberExpression.property.type == `Identifier`);
82
+ if (memberExpression.property.name == `prototype`) {
83
+ memberExpression.computed = true;
84
+ memberExpression.property = t.identifier(`_${uniqueID}_PROTOTYPE_PROPERTY_`);
85
+ } else if (memberExpression.property.name == `__proto__`) {
86
+ memberExpression.computed = true;
87
+ memberExpression.property = t.identifier(`_${uniqueID}_PROTO_PROPERTY_`);
88
+ } else if (includesIllegalString(memberExpression.property.name)) {
89
+ memberExpression.computed = true;
90
+ memberExpression.property = t.stringLiteral(replaceUnsafeStrings(uniqueID, memberExpression.property.name));
91
+ }
92
+ },
93
+ ObjectProperty({
94
+ node: objectProperty
95
+ }) {
96
+ if (objectProperty.key.type == `Identifier` && includesIllegalString(objectProperty.key.name)) {
97
+ objectProperty.key = t.stringLiteral(replaceUnsafeStrings(uniqueID, objectProperty.key.name));
98
+ objectProperty.shorthand = false;
99
+ }
100
+ },
101
+ StringLiteral({
102
+ node
103
+ }) {
104
+ node.value = replaceUnsafeStrings(uniqueID, node.value);
105
+ },
106
+ TemplateLiteral({
107
+ node
108
+ }) {
109
+ for (const templateElement of node.quasis) {
110
+ if (templateElement.value.cooked) {
111
+ templateElement.value.cooked = replaceUnsafeStrings(uniqueID, templateElement.value.cooked);
112
+ templateElement.value.raw = templateElement.value.cooked.replaceAll(`\\`, `\\\\`).replaceAll(`\``, `\\\``).replaceAll(`\${`, `$\\{`);
113
+ } else templateElement.value.raw = replaceUnsafeStrings(uniqueID, templateElement.value.raw);
114
+ }
115
+ },
116
+ RegExpLiteral(path) {
117
+ path.node.pattern = replaceUnsafeStrings(uniqueID, path.node.pattern);
118
+ delete path.node.extra;
119
+ }
120
+ });
121
+ scriptBeforeJSONValueReplacement = (await terser.minify(generate(fileBeforeJSONValueReplacement).code, {
122
+ ecma: 2015,
123
+ compress: {
124
+ passes: Infinity,
125
+ unsafe: true,
126
+ unsafe_arrows: true,
127
+ unsafe_comps: true,
128
+ unsafe_symbols: true,
129
+ unsafe_methods: true,
130
+ unsafe_proto: true,
131
+ unsafe_regexp: true,
132
+ unsafe_undefined: true,
133
+ sequences: false
134
+ },
135
+ format: {
136
+ semicolons: false
137
+ },
138
+ keep_classnames: !mangleNames,
139
+ keep_fnames: !mangleNames
140
+ })).code.replace(new RegExp(`_${uniqueID}_PROTOTYPE_PROPERTY_`, `g`), `"prototype"`).replace(new RegExp(`_${uniqueID}_PROTO_PROPERTY_`, `g`), `"__proto__"`);
141
+ if (autocomplete) scriptBeforeJSONValueReplacement = spliceString(scriptBeforeJSONValueReplacement, `//${autocomplete}\n`, getFunctionBodyStart(scriptBeforeJSONValueReplacement) + 1);
142
+ if (forceQuineCheats == false) return scriptBeforeJSONValueReplacement;
143
+ }
144
+ let comment;
145
+ let hasComment = false;
146
+ let code;
147
+ {
148
+ const promises = [];
149
+ traverse(file, {
150
+ FunctionDeclaration(path) {
151
+ path.traverse({
152
+ Function(path) {
153
+ if (path.parent.type != `CallExpression` && path.parentKey != `callee`) path.skip();
154
+ },
155
+ Loop(path) {
156
+ path.skip();
157
+ },
158
+ ObjectExpression(path) {
159
+ const o = {};
160
+ if (parseObjectExpression(path.node, o)) path.replaceWith(t.identifier(`_${uniqueID}_JSON_VALUE_${jsonValues.push(o) - 1}_`));
161
+ },
162
+ ArrayExpression(path) {
163
+ const o = [];
164
+ if (parseArrayExpression(path.node, o)) path.replaceWith(t.identifier(`_${uniqueID}_JSON_VALUE_${jsonValues.push(o) - 1}_`));
165
+ }
166
+ });
167
+ path.traverse({
168
+ TemplateLiteral(path) {
169
+ if (path.parent.type == `TaggedTemplateExpression`) return;
170
+ const templateLiteral = path.node;
171
+ let replacement = t.stringLiteral(templateLiteral.quasis[0].value.cooked);
172
+ for (let index = 0; index < templateLiteral.expressions.length; index++) {
173
+ const expression = templateLiteral.expressions[index];
174
+ const templateElement = templateLiteral.quasis[index + 1];
175
+ replacement = t.binaryExpression(`+`, replacement, expression);
176
+ if (!templateElement.value.cooked) continue;
177
+ replacement = t.binaryExpression(`+`, replacement, t.stringLiteral(templateElement.value.cooked));
178
+ }
179
+ path.replaceWith(replacement);
180
+ },
181
+ MemberExpression({
182
+ node: memberExpression
183
+ }) {
184
+ if (memberExpression.computed) return;
185
+ assert(memberExpression.property.type == `Identifier`);
186
+ if (memberExpression.property.name.length < 3) return;
187
+ memberExpression.computed = true;
188
+ memberExpression.property = t.stringLiteral(memberExpression.property.name);
189
+ },
190
+ UnaryExpression(path) {
191
+ if (path.node.operator == `void`) {
192
+ if (path.node.argument.type == `NumericLiteral` && !path.node.argument.value) {
193
+ path.replaceWith(t.identifier(`_${uniqueID}_UNDEFINED_`));
194
+ undefinedIsReferenced = true;
195
+ }
196
+ } else if (path.node.operator == `-` && path.node.argument.type == `NumericLiteral`) {
197
+ const value = -path.node.argument.value;
198
+ promises.push((async () => {
199
+ if ((await minifyNumber(value)).length <= 3) return;
200
+ if (path.parentKey == `key` && path.parent.type == `ObjectProperty`) path.parent.computed = true;
201
+ let jsonValueIndex = jsonValues.indexOf(value);
202
+ if (jsonValueIndex == -1) jsonValueIndex += jsonValues.push(value);
203
+ path.replaceWith(t.identifier(`_${uniqueID}_JSON_VALUE_${jsonValueIndex}_`));
204
+ })());
205
+ path.skip();
206
+ }
207
+ },
208
+ NullLiteral(path) {
209
+ /* eslint-disable unicorn/no-null */
210
+ let jsonValueIndex = jsonValues.indexOf(null);
211
+ if (jsonValueIndex == -1) jsonValueIndex += jsonValues.push(null);
212
+ path.replaceWith(t.identifier(`_${uniqueID}_JSON_VALUE_${jsonValueIndex}_`));
213
+ /* eslint-enable unicorn/no-null */
214
+ },
215
+
216
+ NumericLiteral(path) {
217
+ promises.push((async () => {
218
+ if ((await minifyNumber(path.node.value)).length <= 3) return;
219
+ if (path.parentKey == `key` && path.parent.type == `ObjectProperty`) path.parent.computed = true;
220
+ let jsonValueIndex = jsonValues.indexOf(path.node.value);
221
+ if (jsonValueIndex == -1) jsonValueIndex += jsonValues.push(path.node.value);
222
+ path.replaceWith(t.identifier(`_${uniqueID}_JSON_VALUE_${jsonValueIndex}_`));
223
+ })());
224
+ },
225
+ StringLiteral(path) {
226
+ path.node.value = replaceUnsafeStrings(uniqueID, path.node.value);
227
+
228
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string -- the `NodePath`'s `.toString()` method compiles and returns the contained `Node`
229
+ if (JSON.stringify(path.node.value).includes(`\\u00`) || path.toString().length < 4) return;
230
+ if (path.parentKey == `key` && path.parent.type == `ObjectProperty`) path.parent.computed = true;
231
+ let jsonValueIndex = jsonValues.indexOf(path.node.value);
232
+ if (jsonValueIndex == -1) jsonValueIndex += jsonValues.push(path.node.value);
233
+ path.replaceWith(t.identifier(`_${uniqueID}_JSON_VALUE_${jsonValueIndex}_`));
234
+ },
235
+ ObjectProperty({
236
+ node
237
+ }) {
238
+ if (node.computed || node.key.type != `Identifier` || node.key.name.length < 4) return;
239
+ let jsonValueIndex = jsonValues.indexOf(node.key.name);
240
+ if (jsonValueIndex == -1) jsonValueIndex += jsonValues.push(node.key.name);
241
+ node.computed = true;
242
+ node.key = t.identifier(`_${uniqueID}_JSON_VALUE_${jsonValueIndex}_`);
243
+ },
244
+ RegExpLiteral(path) {
245
+ path.node.pattern = replaceUnsafeStrings(uniqueID, path.node.pattern);
246
+ delete path.node.extra;
247
+ }
248
+ });
249
+ path.skip();
250
+ }
251
+ });
252
+ await Promise.all(promises);
253
+ const functionDeclaration = file.program.body[0];
254
+ assert(functionDeclaration.type == `FunctionDeclaration`);
255
+ if (jsonValues.length) {
256
+ hasComment = true;
257
+ if (jsonValues.length == 1) {
258
+ if (typeof jsonValues[0] == `string` && !jsonValues[0].includes(`\n`) && !jsonValues[0].includes(`\t`)) {
259
+ const variableDeclaration = t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_JSON_VALUE_0_`), t.memberExpression(t.taggedTemplateExpression(t.memberExpression(t.callExpression(t.identifier(`$${uniqueID}$SUBSCRIPT$scripts$quine$`), []), t.identifier(`split`)), t.templateLiteral([t.templateElement({
260
+ raw: `\t`,
261
+ cooked: `\t`
262
+ }, true)], [])), t.identifier(`$${uniqueID}$SPLIT_INDEX$`), true))]);
263
+ if (undefinedIsReferenced) variableDeclaration.declarations.push(t.variableDeclarator(t.identifier(`_${uniqueID}_UNDEFINED_`)));
264
+ functionDeclaration.body.body.unshift(variableDeclaration);
265
+ comment = jsonValues[0];
266
+ } else {
267
+ const variableDeclaration = t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_JSON_VALUE_0_`), t.callExpression(t.memberExpression(t.identifier(`JSON`), t.identifier(`parse`)), [t.memberExpression(t.taggedTemplateExpression(t.memberExpression(t.callExpression(t.identifier(`$${uniqueID}$SUBSCRIPT$scripts$quine$`), []), t.identifier(`split`)), t.templateLiteral([t.templateElement({
268
+ raw: `\t`,
269
+ cooked: `\t`
270
+ }, true)], [])), t.identifier(`$${uniqueID}$SPLIT_INDEX$`), true)]))]);
271
+ if (undefinedIsReferenced) variableDeclaration.declarations.push(t.variableDeclarator(t.identifier(`_${uniqueID}_UNDEFINED_`)));
272
+ functionDeclaration.body.body.unshift(variableDeclaration);
273
+ comment = JSON.stringify(jsonValues[0]);
274
+ }
275
+ } else {
276
+ const variableDeclaration = t.variableDeclaration(`let`, [t.variableDeclarator(t.arrayPattern(jsonValues.map((_, index) => t.identifier(`_${uniqueID}_JSON_VALUE_${index}_`))), t.callExpression(t.memberExpression(t.identifier(`JSON`), t.identifier(`parse`)), [t.memberExpression(t.taggedTemplateExpression(t.memberExpression(t.callExpression(t.identifier(`$${uniqueID}$SUBSCRIPT$scripts$quine$`), []), t.identifier(`split`)), t.templateLiteral([t.templateElement({
277
+ raw: `\t`,
278
+ cooked: `\t`
279
+ }, true)], [])), t.identifier(`$${uniqueID}$SPLIT_INDEX$`), true)]))]);
280
+ if (undefinedIsReferenced) variableDeclaration.declarations.push(t.variableDeclarator(t.identifier(`_${uniqueID}_UNDEFINED_`)));
281
+ functionDeclaration.body.body.unshift(variableDeclaration);
282
+ comment = JSON.stringify(jsonValues);
283
+ }
284
+ } else if (undefinedIsReferenced) {
285
+ functionDeclaration.body.body.unshift(t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(`_${uniqueID}_UNDEFINED_`))]));
286
+ }
287
+ code = generate(file).code;
288
+ }
289
+ code = (await terser.minify(code, {
290
+ ecma: 2015,
291
+ compress: {
292
+ passes: Infinity,
293
+ unsafe: true,
294
+ unsafe_arrows: true,
295
+ unsafe_comps: true,
296
+ unsafe_symbols: true,
297
+ unsafe_methods: true,
298
+ unsafe_proto: true,
299
+ unsafe_regexp: true,
300
+ unsafe_undefined: true,
301
+ sequences: false
302
+ },
303
+ format: {
304
+ semicolons: false
305
+ },
306
+ keep_classnames: !mangleNames,
307
+ keep_fnames: !mangleNames
308
+ })).code || ``;
309
+
310
+ // this step affects the character count and can't happen after the count comparison
311
+ if (comment != undefined) {
312
+ code = spliceString(code, `${autocomplete ? `//${autocomplete}\n` : ``}\n//\t${comment}\t\n`, getFunctionBodyStart(code) + 1);
313
+ code = code.replace(`$${uniqueID}$SPLIT_INDEX$`, await minifyNumber(code.split(`\t`).findIndex(part => part == comment)));
314
+ }
315
+ if (forceQuineCheats == true) return code;
316
+ assert(scriptBeforeJSONValueReplacement);
317
+
318
+ // if the script has a comment, it's gonna contain `SC$scripts$quine()`
319
+ // which is gonna compile to `#fs.scripts.quine()` which contains
320
+ // an extra character so we have to account for that
321
+ if (countHackmudCharacters(scriptBeforeJSONValueReplacement) <= countHackmudCharacters(code) + Number(hasComment)) return scriptBeforeJSONValueReplacement;
322
+ return code;
323
+ };
324
+ const parseObjectExpression = (node, o) => {
325
+ if (!node.properties.length) return false;
326
+ for (const property of node.properties) {
327
+ if (property.type != `ObjectProperty` || property.computed) return false;
328
+ assert(property.key.type == `Identifier` || property.key.type == `NumericLiteral` || property.key.type == `StringLiteral`);
329
+ if (property.value.type == `ArrayExpression`) {
330
+ const childArray = [];
331
+ if (parseArrayExpression(property.value, childArray)) o[property.key.type == `Identifier` ? property.key.name : property.key.value] = childArray;else return false;
332
+ } else if (property.value.type == `ObjectExpression`) {
333
+ const childObject = {};
334
+ if (parseObjectExpression(property.value, childObject)) o[property.key.type == `Identifier` ? property.key.name : property.key.value] = childObject;else return false;
335
+ } else if (property.value.type == `NullLiteral`)
336
+ // eslint-disable-next-line unicorn/no-null
337
+ o[property.key.type == `Identifier` ? property.key.name : property.key.value] = null;else if (property.value.type == `BooleanLiteral` || property.value.type == `NumericLiteral` || property.value.type == `StringLiteral`) o[property.key.type == `Identifier` ? property.key.name : property.key.value] = property.value.value;else if (property.value.type == `TemplateLiteral` && !property.value.expressions.length) o[property.key.type == `Identifier` ? property.key.name : property.key.value] = property.value.quasis[0].value.cooked;else return false;
338
+ }
339
+ return true;
340
+ };
341
+ const parseArrayExpression = (node, o) => {
342
+ if (!node.elements.length) return false;
343
+ for (const element of node.elements) {
344
+ if (!element) return false;
345
+ if (element.type == `ArrayExpression`) {
346
+ const childArray = [];
347
+ if (parseArrayExpression(element, childArray)) childArray.push(childArray);else return false;
348
+ } else if (element.type == `ObjectExpression`) {
349
+ const childObject = {};
350
+ if (parseObjectExpression(element, childObject)) o.push(childObject);else return false;
351
+ } else if (element.type == `NullLiteral`)
352
+ // eslint-disable-next-line unicorn/no-null
353
+ o.push(null);else if (element.type == `BooleanLiteral` || element.type == `NumericLiteral` || element.type == `StringLiteral`) o.push(element.value);else if (element.type == `TemplateLiteral` && !element.expressions.length) o.push(element.quasis[0].value.cooked);else return false;
354
+ }
355
+ return true;
356
+ };
357
+ const minifyNumber = async number => /\$\((?<number>.+)\)/.exec((await terser.minify(`$(${number})`, {
358
+ ecma: 2015
359
+ })).code).groups.number;
360
+ const getFunctionBodyStart = code => {
361
+ const tokens = tokenizer(code, {
362
+ ecmaVersion: 2015
363
+ });
364
+ tokens.getToken(); // function
365
+ tokens.getToken(); // name
366
+ tokens.getToken(); // (
367
+
368
+ let nests = 1;
369
+ while (nests) {
370
+ const token = tokens.getToken();
371
+ if (token.type == tokTypes.parenL) nests++;else if (token.type == tokTypes.parenR) nests--;
372
+ }
373
+ return tokens.getToken().start; // {
374
+ };
375
+
376
+ export { minify as default, minify };
@@ -1 +1,5 @@
1
- const postprocess=($,e,p)=>$.replace(/^function\s*\w+\(/,"function(").replace(new RegExp(`\\$${p}\\$\\\\(?:\\\\)?\\$SC_DOLLAR\\$`,"g"),"S\\C$").replace(new RegExp(`\\$${p}\\$\\\\(?:\\\\)?\\$DB_DOLLAR\\$`,"g"),"D\\B$").replace(new RegExp(`\\$${p}\\$\\\\(?:\\\\)?\\$D\\$`,"g"),"_\\_D_S").replace(new RegExp(`\\$${p}\\$\\\\(?:\\\\)?\\$FMCL\\$`,"g"),"_\\_FMCL_").replace(new RegExp(`\\$${p}\\$\\\\(?:\\\\)?\\$G\\$`,"g"),"_\\_G_").replace(new RegExp(`\\$${p}\\$SUBSCRIPT\\$(\\w+)\\$(\\w+)\\$`,"g"),`#${"nlmhf"[e]}s.$1.$2`).replace(new RegExp(`\\$${p}\\$DEBUG\\$`,"g"),"#D").replace(new RegExp(`\\$${p}\\$FMCL\\$`,"g"),"#FMCL").replace(new RegExp(`\\$${p}\\$GLOBAL\\$`,"g"),"#G").replace(new RegExp(`\\$${p}\\$DB\\$(\\w+)\\$`,"g"),"#db.$1").replace(new RegExp(`\\$${p}\\$SLASH_SLASH\\$`,"g"),"/\\/").replace(new RegExp(`\\$${p}\\$NOT_A_SUBSCRIPT\\$(#[\\w\\.]+)\\(\\$`,"g"),"$1\\(").replace(new RegExp(`\\$${p}\\$NOT_A_DB_CALL\\$(\\w+)\\$`,"g"),"#db.$1\\(").replace(new RegExp(`\\$${p}\\$NOT_A_DEBUG_CALL\\$`,"g"),"#D\\(").replace(new RegExp(`\\$${p}\\$NOT_FMCL\\$`,"g"),"#\\FMCL").replace(new RegExp(`\\$${p}\\$NOT_G\\$`,"g"),"#\\G");export{postprocess as default,postprocess};
1
+ const postprocess = (code, seclevel, uniqueID) => {
2
+ return code.replace(/^function\s*\w+\(/, `function(`).replace(new RegExp(`\\$${uniqueID}\\$\\\\(?:\\\\)?\\$SC_DOLLAR\\$`, `g`), `S\\C$`).replace(new RegExp(`\\$${uniqueID}\\$\\\\(?:\\\\)?\\$DB_DOLLAR\\$`, `g`), `D\\B$`).replace(new RegExp(`\\$${uniqueID}\\$\\\\(?:\\\\)?\\$D\\$`, `g`), `_\\_D_S`).replace(new RegExp(`\\$${uniqueID}\\$\\\\(?:\\\\)?\\$FMCL\\$`, `g`), `_\\_FMCL_`).replace(new RegExp(`\\$${uniqueID}\\$\\\\(?:\\\\)?\\$G\\$`, `g`), `_\\_G_`).replace(new RegExp(`\\$${uniqueID}\\$SUBSCRIPT\\$(\\w+)\\$(\\w+)\\$`, `g`), `#${`nlmhf`[seclevel]}s.$1.$2`).replace(new RegExp(`\\$${uniqueID}\\$DEBUG\\$`, `g`), `#D`).replace(new RegExp(`\\$${uniqueID}\\$FMCL\\$`, `g`), `#FMCL`).replace(new RegExp(`\\$${uniqueID}\\$GLOBAL\\$`, `g`), `#G`).replace(new RegExp(`\\$${uniqueID}\\$DB\\$(\\w+)\\$`, `g`), `#db.$1`).replace(new RegExp(`\\$${uniqueID}\\$SLASH_SLASH\\$`, `g`), `/\\/`).replace(new RegExp(`\\$${uniqueID}\\$NOT_A_SUBSCRIPT\\$(#[\\w\\.]+)\\(\\$`, `g`), `$1\\(`).replace(new RegExp(`\\$${uniqueID}\\$NOT_A_DB_CALL\\$(\\w+)\\$`, `g`), `#db.$1\\(`).replace(new RegExp(`\\$${uniqueID}\\$NOT_A_DEBUG_CALL\\$`, `g`), `#D\\(`).replace(new RegExp(`\\$${uniqueID}\\$NOT_FMCL\\$`, `g`), `#\\FMCL`).replace(new RegExp(`\\$${uniqueID}\\$NOT_G\\$`, `g`), `#\\G`);
3
+ };
4
+
5
+ export { postprocess as default, postprocess };
@@ -1,4 +1,4 @@
1
- export declare type PreprocessOptions = {
1
+ export type PreprocessOptions = {
2
2
  /** 11 a-z 0-9 characters */
3
3
  uniqueID: string;
4
4
  };
@@ -1 +1,84 @@
1
- import e from"@babel/generator";import{parse as o}from"@babel/parser";import r from"@babel/traverse";import i from"@babel/types";import{resolve as t}from"import-meta-resolve";import{a as s}from"../assert-22a7ef8a.js";import{s as p}from"../spliceString-0e6b5d6d.js";const{default:l}=r,{default:a}=e,preprocess=async(e,{uniqueID:r="00000000000"}={})=>{s(/^\w{11}$/.test(r));const n=e;let c,d,f;do{c=e.length,e=e.replace(/^\s+/,"").replace(/^\/\/.*/,"").replace(/^\/\*[\s\S]*?\*\//,"")}while(e.length!=c);for(e=e.replace(/^function\s*\(/,"export default function (");;){let i;try{d=o(e,{plugins:["typescript",["decorators",{decoratorsBeforeExport:!0}],"doExpressions","functionBind","functionSent","partialApplication",["pipelineOperator",{proposal:"hack",topicToken:"%"}],"throwExpressions",["recordAndTuple",{syntaxType:"hash"}],"classProperties","classPrivateProperties","classPrivateMethods","logicalAssignment","numericSeparator","nullishCoalescingOperator","optionalChaining","optionalCatchBinding","objectRestSpread"],sourceType:"module"});break}catch(e){s(e instanceof SyntaxError),i=e}var m;if("BABEL_PARSER_SYNTAX_ERROR"!=i.code||"PrivateInExpectedIn"!=i.reasonCode)throw console.log(null===(m=/.+/.exec(e.slice(i.pos)))||void 0===m?void 0:m[0]),i;const t=e.slice(i.pos);let l;if(l=/^#[0-4fhmln]s\.scripts\.quine\(\)/.exec(t))e=p(e,JSON.stringify(n),i.pos,l[0].length);else if(l=/^#[0-4fhmln]?s\./.exec(t))e=p(e,"$",i.pos,1);else if(l=/^#D[^\w$]/.exec(t))e=p(e,"$",i.pos,1);else if(l=/^#FMCL/.exec(t))e=p(e,`$${r}$FMCL$`,i.pos,l[0].length);else if(l=/^#G/.exec(t))e=p(e,`$${r}$GLOBAL$`,i.pos,l[0].length);else{if(!(l=/^#db\./.exec(t)))throw i;e=p(e,"$",i.pos,1)}}l(d,{Program(e){f=e,e.skip()}});const u=f.scope.hasGlobal("Record"),h=f.scope.hasGlobal("Tuple");return(u||h)&&d.program.body.unshift(i.importDeclaration(u?h?[i.importSpecifier(i.identifier("Record"),i.identifier("Record")),i.importSpecifier(i.identifier("Tuple"),i.identifier("Tuple"))]:[i.importSpecifier(i.identifier("Record"),i.identifier("Record"))]:[i.importSpecifier(i.identifier("Tuple"),i.identifier("Tuple"))],i.stringLiteral("@bloomberg/record-tuple-polyfill"))),f.scope.hasGlobal("Proxy")&&d.program.body.unshift(i.importDeclaration([i.importDefaultSpecifier(i.identifier("Proxy"))],i.stringLiteral((await t("proxy-polyfill/src/proxy.js",import.meta.url)).slice(7)))),1==f.node.body.length&&"FunctionDeclaration"==f.node.body[0].type?{code:`export default ${a(d).code}`}:{code:a(d).code}};export{preprocess as default,preprocess};
1
+ import babelGenerator from '@babel/generator';
2
+ import { parse } from '@babel/parser';
3
+ import babelTraverse from '@babel/traverse';
4
+ import t from '@babel/types';
5
+ import { assert } from '@samual/lib/assert';
6
+ import { spliceString } from '@samual/lib/spliceString';
7
+ import { resolve } from 'import-meta-resolve';
8
+
9
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
10
+ const {
11
+ default: traverse
12
+ } = babelTraverse;
13
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
14
+ const {
15
+ default: generate
16
+ } = babelGenerator;
17
+ /**
18
+ * @param code source code for preprocessing
19
+ * @param options {@link PreprocessOptions details}
20
+ */
21
+ const preprocess = async (code, {
22
+ uniqueID = `00000000000`
23
+ } = {}) => {
24
+ assert(/^\w{11}$/.test(uniqueID));
25
+ const sourceCode = code;
26
+ let lengthBefore;
27
+ do {
28
+ lengthBefore = code.length;
29
+ code = code.replace(/^\s+/, ``).replace(/^\/\/.*/, ``).replace(/^\/\*[\s\S]*?\*\//, ``);
30
+ } while (code.length != lengthBefore);
31
+ code = code.replace(/^function\s*\(/, `export default function (`);
32
+ let file;
33
+ while (true) {
34
+ let error;
35
+ try {
36
+ file = parse(code, {
37
+ plugins: [`typescript`, [`decorators`, {
38
+ decoratorsBeforeExport: true
39
+ }], `doExpressions`, `functionBind`, `functionSent`, `partialApplication`, [`pipelineOperator`, {
40
+ proposal: `hack`,
41
+ topicToken: `%`
42
+ }], `throwExpressions`, [`recordAndTuple`, {
43
+ syntaxType: `hash`
44
+ }], `classProperties`, `classPrivateProperties`, `classPrivateMethods`, `logicalAssignment`, `numericSeparator`, `nullishCoalescingOperator`, `optionalChaining`, `optionalCatchBinding`, `objectRestSpread`],
45
+ sourceType: `module`
46
+ });
47
+ break;
48
+ } catch (error_) {
49
+ assert(error_ instanceof SyntaxError);
50
+ error = error_;
51
+ }
52
+ if (error.code != `BABEL_PARSER_SYNTAX_ERROR` || error.reasonCode != `PrivateInExpectedIn`) {
53
+ var _exec;
54
+ console.log((_exec = /.+/.exec(code.slice(error.pos))) === null || _exec === void 0 ? void 0 : _exec[0]);
55
+ throw error;
56
+ }
57
+ const codeSlice = code.slice(error.pos);
58
+ let match;
59
+ if (match = /^#[0-4fhmln]s\.scripts\.quine\(\)/.exec(codeSlice)) code = spliceString(code, JSON.stringify(sourceCode), error.pos, match[0].length);else if (match = /^#[0-4fhmln]?s\./.exec(codeSlice)) code = spliceString(code, `$`, error.pos, 1);else if (match = /^#D[^\w$]/.exec(codeSlice)) code = spliceString(code, `$`, error.pos, 1);else if (match = /^#FMCL/.exec(codeSlice)) code = spliceString(code, `$${uniqueID}$FMCL$`, error.pos, match[0].length);else if (match = /^#G/.exec(codeSlice)) code = spliceString(code, `$${uniqueID}$GLOBAL$`, error.pos, match[0].length);else if (match = /^#db\./.exec(codeSlice)) code = spliceString(code, `$`, error.pos, 1);else throw error;
60
+ }
61
+ let program;
62
+ traverse(file, {
63
+ Program(path) {
64
+ program = path;
65
+ path.skip();
66
+ }
67
+ });
68
+ const needRecord = program.scope.hasGlobal(`Record`);
69
+ const needTuple = program.scope.hasGlobal(`Tuple`);
70
+ if (needRecord || needTuple) {
71
+ file.program.body.unshift(t.importDeclaration(needRecord ? needTuple ? [t.importSpecifier(t.identifier(`Record`), t.identifier(`Record`)), t.importSpecifier(t.identifier(`Tuple`), t.identifier(`Tuple`))] : [t.importSpecifier(t.identifier(`Record`), t.identifier(`Record`))] : [t.importSpecifier(t.identifier(`Tuple`), t.identifier(`Tuple`))], t.stringLiteral(`@bloomberg/record-tuple-polyfill`)));
72
+ }
73
+ if (program.scope.hasGlobal(`Proxy`)) {
74
+ file.program.body.unshift(t.importDeclaration([t.importDefaultSpecifier(t.identifier(`Proxy`))], t.stringLiteral((await resolve(`proxy-polyfill/src/proxy.js`, import.meta.url)).slice(7))));
75
+ }
76
+ if (program.node.body.length == 1 && program.node.body[0].type == `FunctionDeclaration`) return {
77
+ code: `export default ${generate(file).code}`
78
+ };
79
+ return {
80
+ code: generate(file).code
81
+ };
82
+ };
83
+
84
+ export { preprocess as default, preprocess };
@@ -1,5 +1,5 @@
1
- import { NodePath } from "@babel/traverse";
2
- import t, { Program } from "@babel/types";
3
- export declare const getReferencePathsToGlobal: (name: string, program: NodePath<Program>) => NodePath<t.Identifier>[];
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type { Identifier, Program } from "@babel/types";
3
+ export declare const getReferencePathsToGlobal: (name: string, program: NodePath<Program>) => NodePath<Identifier>[];
4
4
  export declare const includesIllegalString: (toCheck: string) => boolean;
5
5
  export declare const replaceUnsafeStrings: (uniqueID: string, toReplace: string) => string;
@@ -1 +1,18 @@
1
- import $ from"@babel/types";import{e}from"../assert-22a7ef8a.js";const getReferencePathsToGlobal=(_,r)=>{const[a]=r.unshiftContainer("body",$.variableDeclaration("let",[$.variableDeclarator($.identifier(_))]));r.scope.crawl();const c=e(r.scope.getBinding(_));return a.remove(),c.referencePaths},includesIllegalString=$=>$.includes("SC$")||$.includes("DB$")||$.includes("__D_S")||$.includes("__FMCL_")||$.includes("__G_"),replaceUnsafeStrings=($,e)=>e.replace(/SC\$/g,`$${$}$\\$SC_DOLLAR$`).replace(/DB\$/g,`$${$}$\\$DB_DOLLAR$`).replace(/__D_S/g,`$${$}$\\$D$`).replace(/__FMCL_/g,`$${$}$\\$FMCL$`).replace(/__G_/g,`$${$}$\\$G$`).replace(/\/\//g,`$${$}$SLASH_SLASH$`).replace(/#[0-4fhmln]?s(?:\.[_a-z][\d_a-z]{0,24}){2}\(/g,`$${$}$NOT_A_SUBSCRIPT$$$&$`).replace(/#db\.(?<methodName>[irfu]|u1|us|ObjectId)\(/g,`$${$}$NOT_A_DB_CALL$$$1$`).replace(/#D\(/g,`$${$}$NOT_A_DEBUG_CALL$`).replace(/#FMCL/g,`$${$}$NOT_FMCL$`).replace(/#G/g,`$${$}$NOT_G$`);export{getReferencePathsToGlobal,includesIllegalString,replaceUnsafeStrings};
1
+ import t from '@babel/types';
2
+ import { ensure } from '@samual/lib/assert';
3
+
4
+ const getReferencePathsToGlobal = (name, program) => {
5
+ const [variableDeclaration] = program.unshiftContainer(`body`, t.variableDeclaration(`let`, [t.variableDeclarator(t.identifier(name))]));
6
+ program.scope.crawl();
7
+ const binding = ensure(program.scope.getBinding(name));
8
+ variableDeclaration.remove();
9
+ return binding.referencePaths;
10
+ };
11
+ const includesIllegalString = toCheck => {
12
+ return toCheck.includes(`SC$`) || toCheck.includes(`DB$`) || toCheck.includes(`__D_S`) || toCheck.includes(`__FMCL_`) || toCheck.includes(`__G_`);
13
+ };
14
+ const replaceUnsafeStrings = (uniqueID, toReplace) => {
15
+ return toReplace.replaceAll(`SC$`, `$${uniqueID}$\\$SC_DOLLAR$`).replaceAll(`DB$`, `$${uniqueID}$\\$DB_DOLLAR$`).replaceAll(`__D_S`, `$${uniqueID}$\\$D$`).replaceAll(`__FMCL_`, `$${uniqueID}$\\$FMCL$`).replaceAll(`__G_`, `$${uniqueID}$\\$G$`).replaceAll(`//`, `$${uniqueID}$SLASH_SLASH$`).replaceAll(/#[0-4fhmln]?s(?:\.[_a-z][\d_a-z]{0,24}){2}\(/g, `$${uniqueID}$NOT_A_SUBSCRIPT$$$&$`).replaceAll(/#db\.(?<methodName>[irfu]|u1|us|ObjectId)\(/g, `$${uniqueID}$NOT_A_DB_CALL$$$1$`).replaceAll(`#D(`, `$${uniqueID}$NOT_A_DEBUG_CALL$`).replaceAll(`#FMCL`, `$${uniqueID}$NOT_FMCL$`).replaceAll(`#G`, `$${uniqueID}$NOT_G$`);
16
+ };
17
+
18
+ export { getReferencePathsToGlobal, includesIllegalString, replaceUnsafeStrings };
@@ -1,5 +1,5 @@
1
- import t, { File } from "@babel/types";
2
- export declare type TransformOptions = {
1
+ import type { File } from "@babel/types";
2
+ export type TransformOptions = {
3
3
  /** 11 a-z 0-9 characters */
4
4
  uniqueID: string;
5
5
  /** the user going to be hosting this script (or set to `true` if not yet known) */
@@ -18,7 +18,7 @@ export declare type TransformOptions = {
18
18
  * @param options {@link TransformOptions details}
19
19
  */
20
20
  export declare const transform: (file: File, sourceCode: string, { uniqueID, scriptUser, scriptName, seclevel }?: Partial<TransformOptions>) => {
21
- file: t.File;
21
+ file: File;
22
22
  seclevel: number;
23
23
  };
24
24
  export default transform;