hackmud-script-manager 0.20.4-7caccd9 → 0.20.4-8b994a4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/bin/hsm.js +302 -262
- package/env.d.ts +363 -289
- package/generateTypeDeclaration.js +2 -1
- package/index.d.ts +3 -0
- package/index.js +3 -1
- package/package.json +44 -39
- package/processScript/index.d.ts +2 -2
- package/processScript/index.js +14 -11
- package/processScript/minify.js +14 -19
- package/processScript/postprocess.d.ts +1 -1
- package/processScript/postprocess.js +3 -3
- package/processScript/preprocess.js +7 -5
- package/processScript/transform.d.ts +3 -0
- package/processScript/transform.js +118 -98
- package/push.d.ts +10 -1
- package/push.js +42 -18
- package/watch.d.ts +2 -1
- package/watch.js +32 -29
@@ -22,9 +22,8 @@ const { default: traverse } = babelTraverse,
|
|
22
22
|
"BigInt"
|
23
23
|
]
|
24
24
|
function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scriptName, seclevel = 4 }) {
|
25
|
-
const
|
26
|
-
|
27
|
-
liveExports = new Map()
|
25
|
+
const warnings = [],
|
26
|
+
topFunctionName = `_${uniqueId}_SCRIPT_`
|
28
27
|
let program
|
29
28
|
traverse(file, {
|
30
29
|
Program(path) {
|
@@ -46,9 +45,17 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
46
45
|
referencePath.replaceWith(t.identifier(`_${uniqueId}_SCRIPT_USER_`))
|
47
46
|
} else
|
48
47
|
referencePath.replaceWith(t.stringLiteral(1 == scriptUser ? `$${uniqueId}$SCRIPT_USER$` : scriptUser))
|
49
|
-
if (program.scope.hasGlobal("_SCRIPT_NAME"))
|
48
|
+
if (program.scope.hasGlobal("_SCRIPT_NAME")) {
|
49
|
+
warnings.push({
|
50
|
+
message:
|
51
|
+
"Global _SCRIPT_NAME is deprecated and will be removed in the next minor release of HSM, use _SCRIPT_SUBNAME instead"
|
52
|
+
})
|
50
53
|
for (const referencePath of getReferencePathsToGlobal("_SCRIPT_NAME", program))
|
51
54
|
referencePath.replaceWith(t.stringLiteral(1 == scriptName ? `$${uniqueId}$SCRIPT_NAME$` : scriptName))
|
55
|
+
}
|
56
|
+
if (program.scope.hasGlobal("_SCRIPT_SUBNAME"))
|
57
|
+
for (const referencePath of getReferencePathsToGlobal("_SCRIPT_SUBNAME", program))
|
58
|
+
referencePath.replaceWith(t.stringLiteral(1 == scriptName ? `$${uniqueId}$SCRIPT_NAME$` : scriptName))
|
52
59
|
if (program.scope.hasGlobal("_FULL_SCRIPT_NAME"))
|
53
60
|
for (const referencePath of getReferencePathsToGlobal("_FULL_SCRIPT_NAME", program))
|
54
61
|
if (1 == scriptUser || 1 == scriptName)
|
@@ -70,30 +77,30 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
70
77
|
const referencePath = FunctionReferencePaths[0]
|
71
78
|
assert(
|
72
79
|
"MemberExpression" == referencePath.parent.type,
|
73
|
-
"src/processScript/transform.ts:
|
80
|
+
"src/processScript/transform.ts:111:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
|
74
81
|
)
|
75
82
|
assert(
|
76
83
|
"Identifier" == referencePath.parent.property.type,
|
77
|
-
"src/processScript/transform.ts:
|
84
|
+
"src/processScript/transform.ts:116:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
|
78
85
|
)
|
79
86
|
assert(
|
80
87
|
"prototype" == referencePath.parent.property.name,
|
81
|
-
"src/processScript/transform.ts:
|
88
|
+
"src/processScript/transform.ts:121:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
|
82
89
|
)
|
83
90
|
referencePath.parentPath.replaceWith(createGetFunctionPrototypeNode())
|
84
91
|
} else {
|
85
92
|
for (const referencePath of FunctionReferencePaths) {
|
86
93
|
assert(
|
87
94
|
"MemberExpression" == referencePath.parent.type,
|
88
|
-
"src/processScript/transform.ts:
|
95
|
+
"src/processScript/transform.ts:129:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
|
89
96
|
)
|
90
97
|
assert(
|
91
98
|
"Identifier" == referencePath.parent.property.type,
|
92
|
-
"src/processScript/transform.ts:
|
99
|
+
"src/processScript/transform.ts:134:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
|
93
100
|
)
|
94
101
|
assert(
|
95
102
|
"prototype" == referencePath.parent.property.name,
|
96
|
-
"src/processScript/transform.ts:
|
103
|
+
"src/processScript/transform.ts:139:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
|
97
104
|
)
|
98
105
|
functionDotPrototypeIsReferencedMultipleTimes = !0
|
99
106
|
referencePath.parentPath.replaceWith(t.identifier(`_${uniqueId}_FUNCTION_DOT_PROTOTYPE_`))
|
@@ -101,40 +108,45 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
101
108
|
functionDotPrototypeIsReferencedMultipleTimes = !0
|
102
109
|
}
|
103
110
|
}
|
104
|
-
const neededSubscriptLets = new
|
111
|
+
const neededSubscriptLets = new Map()
|
105
112
|
let detectedSeclevel = 4
|
113
|
+
program.scope.hasGlobal("$s") &&
|
114
|
+
warnings.push({
|
115
|
+
message:
|
116
|
+
"Subscripts in the form of $s.foo.bar() and #s.foo.bar() are deprecated. Use explicit seclevels instead."
|
117
|
+
})
|
106
118
|
for (const fakeSubscriptObjectName of ["$fs", "$4s", "$s"])
|
107
|
-
program.scope.hasGlobal(fakeSubscriptObjectName) && processFakeSubscriptObject(fakeSubscriptObjectName)
|
119
|
+
program.scope.hasGlobal(fakeSubscriptObjectName) && processFakeSubscriptObject(fakeSubscriptObjectName, 4)
|
108
120
|
for (const fakeSubscriptObjectName of ["$hs", "$3s"])
|
109
121
|
if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
|
110
122
|
detectedSeclevel = 3
|
111
|
-
processFakeSubscriptObject(fakeSubscriptObjectName)
|
123
|
+
processFakeSubscriptObject(fakeSubscriptObjectName, 3)
|
112
124
|
}
|
113
125
|
for (const fakeSubscriptObjectName of ["$ms", "$2s"])
|
114
126
|
if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
|
115
127
|
detectedSeclevel = 2
|
116
|
-
processFakeSubscriptObject(fakeSubscriptObjectName)
|
128
|
+
processFakeSubscriptObject(fakeSubscriptObjectName, 2)
|
117
129
|
}
|
118
130
|
for (const fakeSubscriptObjectName of ["$ls", "$1s"])
|
119
131
|
if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
|
120
132
|
detectedSeclevel = 1
|
121
|
-
processFakeSubscriptObject(fakeSubscriptObjectName)
|
133
|
+
processFakeSubscriptObject(fakeSubscriptObjectName, 1)
|
122
134
|
}
|
123
135
|
for (const fakeSubscriptObjectName of ["$ns", "$0s"])
|
124
136
|
if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
|
125
137
|
detectedSeclevel = 0
|
126
|
-
processFakeSubscriptObject(fakeSubscriptObjectName)
|
138
|
+
processFakeSubscriptObject(fakeSubscriptObjectName, 0)
|
127
139
|
}
|
128
140
|
seclevel = Math.min(seclevel, detectedSeclevel)
|
129
141
|
const neededDbMethodLets = new Set()
|
130
142
|
if (program.scope.hasGlobal("$db"))
|
131
143
|
for (const referencePath of getReferencePathsToGlobal("$db", program)) {
|
132
|
-
assert("MemberExpression" == referencePath.parentPath.node.type, "src/processScript/transform.ts:
|
133
|
-
assert("Identifier" == referencePath.parentPath.node.property.type, "src/processScript/transform.ts:
|
144
|
+
assert("MemberExpression" == referencePath.parentPath.node.type, "src/processScript/transform.ts:199:69")
|
145
|
+
assert("Identifier" == referencePath.parentPath.node.property.type, "src/processScript/transform.ts:200:72")
|
134
146
|
const databaseOpMethodName = referencePath.parentPath.node.property.name
|
135
147
|
assert(
|
136
148
|
validDBMethods.includes(databaseOpMethodName),
|
137
|
-
`src/processScript/transform.ts:
|
149
|
+
`src/processScript/transform.ts:206:8 invalid db method "${databaseOpMethodName}", valid db methods are "${validDBMethods.join('", "')}"`
|
138
150
|
)
|
139
151
|
if ("CallExpression" == referencePath.parentPath.parentPath?.type)
|
140
152
|
referencePath.parentPath.replaceWith(t.identifier(`$${uniqueId}$DB$${databaseOpMethodName}$`))
|
@@ -157,27 +169,32 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
157
169
|
if (program.scope.hasGlobal("$FMCL"))
|
158
170
|
for (const referencePath of getReferencePathsToGlobal("$FMCL", program))
|
159
171
|
referencePath.replaceWith(t.identifier(`$${uniqueId}$FMCL$`))
|
160
|
-
|
172
|
+
let needG = program.scope.hasGlobal("$G")
|
173
|
+
if (needG)
|
161
174
|
for (const referencePath of getReferencePathsToGlobal("$G", program))
|
162
|
-
referencePath.replaceWith(t.identifier(
|
175
|
+
referencePath.replaceWith(t.identifier(`_${uniqueId}_G_`))
|
163
176
|
if (program.scope.hasGlobal("_SECLEVEL"))
|
164
177
|
for (const referencePath of getReferencePathsToGlobal("_SECLEVEL", program))
|
165
178
|
referencePath.replaceWith(t.numericLiteral(seclevel))
|
166
|
-
let needGetPrototypeOf = !1
|
179
|
+
let needGetPrototypeOf = !1,
|
180
|
+
needHasOwn = !1
|
167
181
|
if (program.scope.hasGlobal("Object"))
|
168
182
|
for (const referencePath of getReferencePathsToGlobal("Object", program))
|
169
183
|
if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
|
170
|
-
assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:
|
184
|
+
assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:256:64")
|
171
185
|
if ("getPrototypeOf" == referencePath.parent.property.name) {
|
172
186
|
referencePath.parentPath.replaceWith(t.identifier(`_${uniqueId}_GET_PROTOTYPE_OF_`))
|
173
187
|
needGetPrototypeOf = !0
|
188
|
+
} else if ("hasOwn" == referencePath.parent.property.name) {
|
189
|
+
referencePath.parentPath.replaceWith(t.identifier(`_${uniqueId}_HAS_OWN_`))
|
190
|
+
needHasOwn = !0
|
174
191
|
}
|
175
192
|
}
|
176
193
|
const consoleMethodsReferenced = new Set()
|
177
194
|
if (program.scope.hasGlobal("console"))
|
178
195
|
for (const referencePath of getReferencePathsToGlobal("console", program))
|
179
196
|
if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
|
180
|
-
assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:
|
197
|
+
assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:274:64")
|
181
198
|
referencePath.parentPath.replaceWith(
|
182
199
|
t.identifier(`_${uniqueId}_CONSOLE_METHOD_${referencePath.parent.property.name}_`)
|
183
200
|
)
|
@@ -185,19 +202,20 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
185
202
|
}
|
186
203
|
const lastStatement = program.node.body.at(-1)
|
187
204
|
let exportDefaultName
|
188
|
-
assert(lastStatement, "src/processScript/transform.ts:
|
205
|
+
assert(lastStatement, "src/processScript/transform.ts:288:27 program is empty")
|
189
206
|
if ("ExportNamedDeclaration" == lastStatement.type) {
|
190
207
|
program.node.body.pop()
|
191
208
|
for (const specifier of lastStatement.specifiers) {
|
192
209
|
assert(
|
193
210
|
"ExportSpecifier" == specifier.type,
|
194
|
-
`src/processScript/transform.ts:
|
211
|
+
`src/processScript/transform.ts:294:51 ${specifier.type} is currently unsupported`
|
212
|
+
)
|
213
|
+
if (
|
214
|
+
"default" !=
|
215
|
+
("Identifier" == specifier.exported.type ? specifier.exported.name : specifier.exported.value)
|
195
216
|
)
|
196
|
-
|
197
|
-
|
198
|
-
"default" == exportedName ?
|
199
|
-
(exportDefaultName = specifier.local.name)
|
200
|
-
: exports.set(specifier.local.name, exportedName)
|
217
|
+
throw Error("Only default exports are supported")
|
218
|
+
exportDefaultName = specifier.local.name
|
201
219
|
}
|
202
220
|
}
|
203
221
|
const globalBlock = t.blockStatement([])
|
@@ -223,10 +241,6 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
223
241
|
t.returnStatement(t.callExpression(t.identifier(exportDefaultName), []))
|
224
242
|
])
|
225
243
|
))
|
226
|
-
if ("const" != statement.kind && exports.has(identifierName)) {
|
227
|
-
liveExports.set(identifierName, exports.get(identifierName))
|
228
|
-
exports.delete(identifierName)
|
229
|
-
}
|
230
244
|
globalBlock.body.push(
|
231
245
|
t.variableDeclaration("let", [t.variableDeclarator(t.identifier(identifierName))])
|
232
246
|
)
|
@@ -291,34 +305,16 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
291
305
|
}
|
292
306
|
program.node.body = [mainFunction]
|
293
307
|
if (globalBlock.body.length) {
|
294
|
-
;(exports.size || liveExports.size) &&
|
295
|
-
mainFunction.body.body.push(
|
296
|
-
t.returnStatement(
|
297
|
-
t.objectExpression([
|
298
|
-
...[...exports].map(([local, exported]) =>
|
299
|
-
t.objectProperty(t.identifier(exported), t.identifier(local))
|
300
|
-
),
|
301
|
-
...[...liveExports].map(([local, exported]) =>
|
302
|
-
t.objectMethod(
|
303
|
-
"get",
|
304
|
-
t.identifier(exported),
|
305
|
-
[],
|
306
|
-
t.blockStatement([t.returnStatement(t.identifier(local))])
|
307
|
-
)
|
308
|
-
)
|
309
|
-
])
|
310
|
-
)
|
311
|
-
)
|
312
308
|
program.scope.crawl()
|
313
309
|
const globalBlockVariables = new Set()
|
314
310
|
let hoistedGlobalBlockFunctions = 0
|
315
311
|
for (const [globalBlockIndex, globalBlockStatement] of [...globalBlock.body.entries()].reverse())
|
316
312
|
if ("VariableDeclaration" == globalBlockStatement.type) {
|
317
|
-
assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:
|
313
|
+
assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:408:59")
|
318
314
|
const declarator = globalBlockStatement.declarations[0]
|
319
315
|
assert(
|
320
316
|
"Identifier" == declarator.id.type,
|
321
|
-
`src/processScript/transform.ts:
|
317
|
+
`src/processScript/transform.ts:412:51 declarator.id.type was "${declarator.id.type}"`
|
322
318
|
)
|
323
319
|
program.scope.crawl()
|
324
320
|
if (program.scope.hasGlobal(declarator.id.name)) {
|
@@ -333,15 +329,16 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
333
329
|
Object.keys(program.scope.globals).some(global => globalBlockVariables.has(global))
|
334
330
|
) {
|
335
331
|
const binding = program.scope.getBinding(declarator.id.name)
|
336
|
-
assert(binding, "src/processScript/transform.ts:
|
332
|
+
assert(binding, "src/processScript/transform.ts:431:23")
|
337
333
|
for (const referencePath of binding.referencePaths) {
|
338
|
-
assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:
|
334
|
+
assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:434:56")
|
339
335
|
referencePath.replaceWith(
|
340
336
|
t.memberExpression(
|
341
|
-
t.identifier(
|
337
|
+
t.identifier(`_${uniqueId}_G_`),
|
342
338
|
t.identifier(referencePath.node.name)
|
343
339
|
)
|
344
340
|
)
|
341
|
+
needG = !0
|
345
342
|
}
|
346
343
|
for (const referencePath of binding.constantViolations)
|
347
344
|
if ("AssignmentExpression" == referencePath.node.type)
|
@@ -350,12 +347,13 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
350
347
|
clearObject(node)
|
351
348
|
Object.assign(
|
352
349
|
node,
|
353
|
-
t.memberExpression(t.identifier(
|
350
|
+
t.memberExpression(t.identifier(`_${uniqueId}_G_`), t.identifier(name))
|
354
351
|
)
|
352
|
+
needG = !0
|
355
353
|
}
|
356
354
|
globalBlockPath.remove()
|
357
355
|
globalBlockStatementPath.remove()
|
358
|
-
declarator.init
|
356
|
+
if (declarator.init) {
|
359
357
|
globalBlock.body.splice(
|
360
358
|
globalBlockIndex,
|
361
359
|
0,
|
@@ -363,13 +361,15 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
363
361
|
t.assignmentExpression(
|
364
362
|
"=",
|
365
363
|
t.memberExpression(
|
366
|
-
t.identifier(
|
364
|
+
t.identifier(`_${uniqueId}_G_`),
|
367
365
|
t.identifier(declarator.id.name)
|
368
366
|
),
|
369
367
|
declarator.init
|
370
368
|
)
|
371
369
|
)
|
372
370
|
)
|
371
|
+
needG = !0
|
372
|
+
}
|
373
373
|
} else {
|
374
374
|
globalBlockPath.remove()
|
375
375
|
globalBlockStatementPath.remove()
|
@@ -379,22 +379,20 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
379
379
|
} else globalBlockVariables.add(declarator.id.name)
|
380
380
|
} else if ("ClassDeclaration" == globalBlockStatement.type) {
|
381
381
|
program.scope.crawl()
|
382
|
-
assert(globalBlockStatement.id, "src/processScript/transform.ts:
|
382
|
+
assert(globalBlockStatement.id, "src/processScript/transform.ts:491:37")
|
383
383
|
if (program.scope.hasGlobal(globalBlockStatement.id.name)) {
|
384
384
|
globalBlock.body.splice(globalBlockIndex, 1)
|
385
385
|
const [globalBlockPath] = program.unshiftContainer("body", globalBlock),
|
386
386
|
[globalBlockStatementPath] = program.unshiftContainer("body", globalBlockStatement)
|
387
387
|
program.scope.crawl()
|
388
388
|
const binding = program.scope.getBinding(globalBlockStatement.id.name)
|
389
|
-
assert(binding, "src/processScript/transform.ts:
|
389
|
+
assert(binding, "src/processScript/transform.ts:503:22")
|
390
390
|
for (const referencePath of binding.referencePaths) {
|
391
|
-
assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:
|
391
|
+
assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:506:55")
|
392
392
|
referencePath.replaceWith(
|
393
|
-
t.memberExpression(
|
394
|
-
t.identifier(`$${uniqueId}$GLOBAL$`),
|
395
|
-
t.identifier(referencePath.node.name)
|
396
|
-
)
|
393
|
+
t.memberExpression(t.identifier(`_${uniqueId}_G_`), t.identifier(referencePath.node.name))
|
397
394
|
)
|
395
|
+
needG = !0
|
398
396
|
}
|
399
397
|
globalBlockPath.remove()
|
400
398
|
globalBlockStatementPath.remove()
|
@@ -405,7 +403,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
405
403
|
t.assignmentExpression(
|
406
404
|
"=",
|
407
405
|
t.memberExpression(
|
408
|
-
t.identifier(
|
406
|
+
t.identifier(`_${uniqueId}_G_`),
|
409
407
|
t.identifier(globalBlockStatement.id.name)
|
410
408
|
),
|
411
409
|
t.classExpression(
|
@@ -417,13 +415,9 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
417
415
|
)
|
418
416
|
)
|
419
417
|
)
|
418
|
+
needG = !0
|
420
419
|
}
|
421
420
|
}
|
422
|
-
if (program.scope.hasGlobal("_EXPORTS"))
|
423
|
-
for (const referencePath of getReferencePathsToGlobal("_EXPORTS", program))
|
424
|
-
referencePath.replaceWith(
|
425
|
-
t.arrayExpression([...exports.keys(), ...liveExports.keys()].map(name => t.stringLiteral(name)))
|
426
|
-
)
|
427
421
|
globalBlock.body.length &&
|
428
422
|
mainFunction.body.body.splice(
|
429
423
|
hoistedGlobalBlockFunctions,
|
@@ -472,6 +466,31 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
472
466
|
)
|
473
467
|
])
|
474
468
|
)
|
469
|
+
needHasOwn &&
|
470
|
+
mainFunction.body.body.unshift(
|
471
|
+
t.variableDeclaration("let", [
|
472
|
+
t.variableDeclarator(
|
473
|
+
t.identifier(`_${uniqueId}_HAS_OWN_`),
|
474
|
+
t.callExpression(
|
475
|
+
t.memberExpression(
|
476
|
+
t.memberExpression(
|
477
|
+
t.identifier(
|
478
|
+
globalFunctionsUnder7Characters.find(name => !program.scope.hasOwnBinding(name))
|
479
|
+
),
|
480
|
+
t.identifier("call")
|
481
|
+
),
|
482
|
+
t.identifier("bind")
|
483
|
+
),
|
484
|
+
[
|
485
|
+
t.memberExpression(
|
486
|
+
t.memberExpression(t.identifier("Object"), t.identifier("prototype")),
|
487
|
+
t.identifier("hasOwnProperty")
|
488
|
+
)
|
489
|
+
]
|
490
|
+
)
|
491
|
+
)
|
492
|
+
])
|
493
|
+
)
|
475
494
|
consoleMethodsReferenced.size &&
|
476
495
|
mainFunction.body.body.unshift(
|
477
496
|
t.variableDeclaration(
|
@@ -522,12 +541,12 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
522
541
|
mainFunction.body.body.unshift(
|
523
542
|
t.variableDeclaration(
|
524
543
|
"let",
|
525
|
-
[...neededSubscriptLets].map(name =>
|
544
|
+
[...neededSubscriptLets].map(([name, seclevel]) =>
|
526
545
|
t.variableDeclarator(
|
527
546
|
t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`),
|
528
547
|
t.arrowFunctionExpression(
|
529
548
|
[t.restElement(t.identifier("args"))],
|
530
|
-
t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$${name}$`), [
|
549
|
+
t.callExpression(t.identifier(`$${uniqueId}$${seclevel}$SUBSCRIPT$${name}$`), [
|
531
550
|
t.spreadElement(t.identifier("args"))
|
532
551
|
])
|
533
552
|
)
|
@@ -535,6 +554,12 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
535
554
|
)
|
536
555
|
)
|
537
556
|
)
|
557
|
+
needG &&
|
558
|
+
mainFunction.body.body.unshift(
|
559
|
+
t.variableDeclaration("let", [
|
560
|
+
t.variableDeclarator(t.identifier(`_${uniqueId}_G_`), t.identifier(`$${uniqueId}$GLOBAL$`))
|
561
|
+
])
|
562
|
+
)
|
538
563
|
traverse(file, {
|
539
564
|
BlockStatement({ node: blockStatement }) {
|
540
565
|
for (const [index, functionDeclaration] of blockStatement.body.entries())
|
@@ -555,7 +580,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
555
580
|
}
|
556
581
|
},
|
557
582
|
ClassBody({ node: classBody, scope, parent }) {
|
558
|
-
assert(t.isClass(parent), "src/processScript/transform.ts:
|
583
|
+
assert(t.isClass(parent), "src/processScript/transform.ts:701:30")
|
559
584
|
let thisIsReferenced = !1
|
560
585
|
for (const classMethod of classBody.body) {
|
561
586
|
if ("ClassMethod" != classMethod.type) continue
|
@@ -631,7 +656,9 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
631
656
|
VariableDeclaration({ node: variableDeclaration }) {
|
632
657
|
"const" == variableDeclaration.kind && (variableDeclaration.kind = "let")
|
633
658
|
},
|
634
|
-
ThisExpression: path =>
|
659
|
+
ThisExpression: path => {
|
660
|
+
path.replaceWith(t.identifier("undefined"))
|
661
|
+
},
|
635
662
|
BigIntLiteral(path) {
|
636
663
|
const bigIntAsNumber = Number(path.node.value)
|
637
664
|
path.replaceWith(
|
@@ -643,52 +670,45 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
643
670
|
)
|
644
671
|
}
|
645
672
|
})
|
646
|
-
return { file, seclevel }
|
673
|
+
return { file, seclevel, warnings }
|
647
674
|
function createGetFunctionPrototypeNode() {
|
648
|
-
|
649
|
-
if (!program.scope.hasOwnBinding(globalFunction))
|
650
|
-
return t.memberExpression(
|
651
|
-
t.memberExpression(t.identifier(globalFunction), t.identifier("constructor")),
|
652
|
-
t.identifier("prototype")
|
653
|
-
)
|
675
|
+
const name = globalFunctionsUnder7Characters.find(name => !program.scope.hasOwnBinding(name))
|
654
676
|
return t.memberExpression(
|
655
|
-
t.
|
656
|
-
|
657
|
-
t.identifier("constructor")
|
658
|
-
),
|
659
|
-
t.identifier("prototype")
|
677
|
+
name ? t.identifier(name) : t.arrowFunctionExpression([t.identifier("_")], t.identifier("_")),
|
678
|
+
t.identifier("__proto__")
|
660
679
|
)
|
661
680
|
}
|
662
|
-
function processFakeSubscriptObject(fakeSubscriptObjectName) {
|
681
|
+
function processFakeSubscriptObject(fakeSubscriptObjectName, seclevel) {
|
663
682
|
for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
|
664
|
-
assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:
|
683
|
+
assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:807:60")
|
665
684
|
assert("Identifier" == referencePath.parent.property.type)
|
666
685
|
assert(
|
667
686
|
"MemberExpression" == referencePath.parentPath.parentPath?.node.type,
|
668
|
-
"src/processScript/transform.ts:
|
687
|
+
"src/processScript/transform.ts:809:81"
|
669
688
|
)
|
670
689
|
assert(
|
671
690
|
"Identifier" == referencePath.parentPath.parentPath.node.property.type,
|
672
|
-
"src/processScript/transform.ts:
|
691
|
+
"src/processScript/transform.ts:810:83"
|
673
692
|
)
|
674
693
|
assert(
|
675
694
|
/^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parent.property.name),
|
676
|
-
`src/processScript/transform.ts:
|
695
|
+
`src/processScript/transform.ts:814:8 invalid user "${referencePath.parent.property.name}" in subscript`
|
677
696
|
)
|
678
697
|
assert(
|
679
698
|
/^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parentPath.parentPath.node.property.name),
|
680
|
-
`src/processScript/transform.ts:
|
699
|
+
`src/processScript/transform.ts:819:8 invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
|
681
700
|
)
|
682
701
|
if ("CallExpression" == referencePath.parentPath.parentPath.parentPath?.type)
|
683
702
|
referencePath.parentPath.parentPath.replaceWith(
|
684
703
|
t.identifier(
|
685
|
-
`$${uniqueId}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
|
704
|
+
`$${uniqueId}$${seclevel}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
|
686
705
|
)
|
687
706
|
)
|
688
707
|
else {
|
689
708
|
const name = `${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}`
|
690
709
|
referencePath.parentPath.parentPath.replaceWith(t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`))
|
691
|
-
neededSubscriptLets.
|
710
|
+
const maxSecLevel = Math.max(neededSubscriptLets.get(name) || 0, seclevel)
|
711
|
+
neededSubscriptLets.set(name, maxSecLevel)
|
692
712
|
}
|
693
713
|
}
|
694
714
|
}
|
package/push.d.ts
CHANGED
@@ -17,7 +17,16 @@ export type PushOptions = LaxPartial<{
|
|
17
17
|
* when left unset or set to `undefined`, automatically uses or doesn't use quine cheats based on character count
|
18
18
|
*/
|
19
19
|
forceQuineCheats: boolean;
|
20
|
+
rootFolderPath: string;
|
20
21
|
}>;
|
22
|
+
export declare class MissingSourceFolderError extends Error {
|
23
|
+
}
|
24
|
+
export declare class MissingHackmudFolderError extends Error {
|
25
|
+
}
|
26
|
+
export declare class NoUsersError extends Error {
|
27
|
+
}
|
28
|
+
export declare class NoScriptsError extends Error {
|
29
|
+
}
|
21
30
|
/** Push scripts from a source directory to the hackmud directory.
|
22
31
|
*
|
23
32
|
* Pushes files directly in the source folder to all users
|
@@ -25,4 +34,4 @@ export type PushOptions = LaxPartial<{
|
|
25
34
|
* @param hackmudPath directory created by hackmud containing user data including scripts
|
26
35
|
* @param options {@link PushOptions details}
|
27
36
|
* @returns array of info on pushed scripts */
|
28
|
-
export declare function push(sourcePath: string, hackmudPath: string, { scripts, onPush, minify, mangleNames, forceQuineCheats }?: PushOptions): Promise<Info[]>;
|
37
|
+
export declare function push(sourcePath: string, hackmudPath: string, { scripts, onPush, minify, mangleNames, forceQuineCheats, rootFolderPath }?: PushOptions): Promise<MissingSourceFolderError | MissingHackmudFolderError | NoUsersError | NoScriptsError | Info[]>;
|
package/push.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { AutoMap } from "@samual/lib/AutoMap"
|
2
2
|
import { ensure, assert } from "@samual/lib/assert"
|
3
3
|
import { countHackmudCharacters } from "@samual/lib/countHackmudCharacters"
|
4
4
|
import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
|
@@ -25,6 +25,7 @@ import "@babel/plugin-transform-private-property-in-object"
|
|
25
25
|
import "@babel/plugin-transform-unicode-sets-regex"
|
26
26
|
import "@babel/traverse"
|
27
27
|
import "@babel/types"
|
28
|
+
import "@rollup/plugin-alias"
|
28
29
|
import "@rollup/plugin-babel"
|
29
30
|
import "@rollup/plugin-commonjs"
|
30
31
|
import "@rollup/plugin-json"
|
@@ -42,32 +43,54 @@ import "./processScript/preprocess.js"
|
|
42
43
|
import "import-meta-resolve"
|
43
44
|
import "./processScript/transform.js"
|
44
45
|
import "@samual/lib/clearObject"
|
46
|
+
class MissingSourceFolderError extends Error {}
|
47
|
+
Object.defineProperty(MissingSourceFolderError.prototype, "name", { value: "MissingSourceFolderError" })
|
48
|
+
class MissingHackmudFolderError extends Error {}
|
49
|
+
Object.defineProperty(MissingHackmudFolderError.prototype, "name", { value: "MissingHackmudFolderError" })
|
50
|
+
class NoUsersError extends Error {}
|
51
|
+
Object.defineProperty(NoUsersError.prototype, "name", { value: "NoUsersError" })
|
52
|
+
class NoScriptsError extends Error {}
|
53
|
+
Object.defineProperty(NoScriptsError.prototype, "name", { value: "NoScriptsError" })
|
45
54
|
async function push(
|
46
55
|
sourcePath,
|
47
56
|
hackmudPath,
|
48
|
-
{ scripts = ["*.*"], onPush = () => {}, minify = !0, mangleNames = !1, forceQuineCheats } = {}
|
57
|
+
{ scripts = ["*.*"], onPush = () => {}, minify = !0, mangleNames = !1, forceQuineCheats, rootFolderPath } = {}
|
49
58
|
) {
|
50
59
|
const [sourceFolder, hackmudFolder] = await Promise.all([
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
60
|
+
readDirectoryWithStats(sourcePath).catch(error => {
|
61
|
+
if (error && "ENOENT" == error.code)
|
62
|
+
return new MissingSourceFolderError("There is no folder at " + sourcePath)
|
63
|
+
throw error
|
64
|
+
}),
|
65
|
+
readDirectoryWithStats(hackmudPath).catch(error => {
|
66
|
+
if (error && "ENOENT" == error.code)
|
67
|
+
return new MissingHackmudFolderError("There is no folder at " + hackmudPath)
|
68
|
+
throw error
|
69
|
+
})
|
70
|
+
])
|
71
|
+
if (sourceFolder instanceof Error) return sourceFolder
|
72
|
+
if (hackmudFolder instanceof Error) return hackmudFolder
|
73
|
+
const sourceFolderFolders = sourceFolder.filter(({ stats }) => stats.isDirectory()),
|
55
74
|
allUsers = new Set([
|
56
75
|
...scripts
|
57
|
-
.map(scriptName => ensure(scriptName.split(".")[0], "src/push.ts:
|
76
|
+
.map(scriptName => ensure(scriptName.split(".")[0], "src/push.ts:85:65"))
|
58
77
|
.filter(name => "*" != name),
|
59
78
|
...sourceFolderFolders.map(({ name }) => name),
|
60
79
|
...hackmudFolder.filter(({ stats }) => stats.isDirectory()).map(({ name }) => name),
|
61
80
|
...hackmudFolder
|
62
81
|
.filter(({ stats, name }) => stats.isFile() && name.endsWith(".key"))
|
63
82
|
.map(({ name }) => name.slice(0, -4))
|
64
|
-
])
|
65
|
-
|
66
|
-
|
83
|
+
])
|
84
|
+
if (!allUsers.size)
|
85
|
+
return new NoUsersError(
|
86
|
+
"Could not find any users. Either provide the names of your users or log into a user in hackmud"
|
87
|
+
)
|
88
|
+
const usersToScriptsToPush = new AutoMap(_user => new Map()),
|
89
|
+
scriptNamesToUsers = new AutoMap(_scriptName => new Set())
|
67
90
|
for (const script of scripts) {
|
68
91
|
const [user, scriptName] = script.split(".")
|
69
|
-
assert(user, "src/push.ts:
|
70
|
-
assert(scriptName, "src/push.ts:
|
92
|
+
assert(user, "src/push.ts:108:16")
|
93
|
+
assert(scriptName, "src/push.ts:109:22")
|
71
94
|
"*" == user ? scriptNamesToUsers.set(scriptName, allUsers) : scriptNamesToUsers.get(scriptName).add(user)
|
72
95
|
}
|
73
96
|
const sourceFolderFiles = sourceFolder.filter(({ stats }) => stats.isFile()),
|
@@ -98,8 +121,8 @@ async function push(
|
|
98
121
|
for (const [scriptName, users] of scriptNamesToUsers)
|
99
122
|
for (const user of users)
|
100
123
|
if (!usersToScriptsToPush.get(user).has(scriptName))
|
101
|
-
|
102
|
-
const pathsToUsers = new
|
124
|
+
return new NoScriptsError(`Could not find script ${user}.${scriptName} to push`)
|
125
|
+
const pathsToUsers = new AutoMap(_path => new Set())
|
103
126
|
for (const [user, scriptsToPush] of usersToScriptsToPush)
|
104
127
|
for (const path of scriptsToPush.values()) pathsToUsers.get(path).add(user)
|
105
128
|
const allInfo = []
|
@@ -109,16 +132,17 @@ async function push(
|
|
109
132
|
uniqueId = Math.floor(Math.random() * 2 ** 52)
|
110
133
|
.toString(36)
|
111
134
|
.padStart(11, "0"),
|
112
|
-
{ script: minifiedCode } = await processScript(await readFile(path, { encoding: "utf8" }), {
|
135
|
+
{ script: minifiedCode, warnings } = await processScript(await readFile(path, { encoding: "utf8" }), {
|
113
136
|
minify,
|
114
137
|
scriptUser: !0,
|
115
138
|
scriptName,
|
116
139
|
uniqueId,
|
117
140
|
filePath: path,
|
118
141
|
mangleNames,
|
119
|
-
forceQuineCheats
|
142
|
+
forceQuineCheats,
|
143
|
+
rootFolderPath
|
120
144
|
}),
|
121
|
-
info = { path, users, characterCount: countHackmudCharacters(minifiedCode), error: void 0 }
|
145
|
+
info = { path, users, characterCount: countHackmudCharacters(minifiedCode), error: void 0, warnings }
|
122
146
|
await Promise.all(
|
123
147
|
users.map(user =>
|
124
148
|
writeFilePersistent(
|
@@ -135,4 +159,4 @@ async function push(
|
|
135
159
|
)
|
136
160
|
return allInfo
|
137
161
|
}
|
138
|
-
export { push }
|
162
|
+
export { MissingHackmudFolderError, MissingSourceFolderError, NoScriptsError, NoUsersError, push }
|
package/watch.d.ts
CHANGED
@@ -6,9 +6,10 @@ export type WatchOptions = PushOptions & LaxPartial<{
|
|
6
6
|
* writing the type declarations enables interscript type checking and autocompletetes for the args */
|
7
7
|
typeDeclarationPath: string;
|
8
8
|
onReady: () => void;
|
9
|
+
rootFolderPath: string;
|
9
10
|
}>;
|
10
11
|
/** Watches target file or folder for updates and builds and pushes updated file.
|
11
12
|
* @param sourceDirectory path to folder containing source files
|
12
13
|
* @param hackmudDirectory path to hackmud directory
|
13
14
|
* @param options {@link WatchOptions details} and {@link PushOptions more details} */
|
14
|
-
export declare function watch(sourceDirectory: string, hackmudDirectory: string, { scripts, onPush, minify, mangleNames, typeDeclarationPath: typeDeclarationPath_, onReady, forceQuineCheats }?: WatchOptions): Promise<void>;
|
15
|
+
export declare function watch(sourceDirectory: string, hackmudDirectory: string, { scripts, onPush, minify, mangleNames, typeDeclarationPath: typeDeclarationPath_, onReady, forceQuineCheats, rootFolderPath }?: WatchOptions): Promise<void>;
|