hackmud-script-manager 0.20.5-97101bc → 0.21.1-0b2f476
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 +7 -6
- package/bin/hsm.js +302 -262
- package/env.d.ts +364 -275
- package/generateTypeDeclaration.js +2 -1
- package/index.d.ts +3 -0
- package/index.js +3 -1
- package/package.json +39 -38
- package/processScript/index.d.ts +2 -2
- package/processScript/index.js +14 -11
- package/processScript/minify.js +11 -17
- 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 +115 -97
- package/push.d.ts +10 -1
- package/push.js +40 -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
|
@@ -645,52 +670,45 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
|
|
645
670
|
)
|
646
671
|
}
|
647
672
|
})
|
648
|
-
return { file, seclevel }
|
673
|
+
return { file, seclevel, warnings }
|
649
674
|
function createGetFunctionPrototypeNode() {
|
650
|
-
|
651
|
-
if (!program.scope.hasOwnBinding(globalFunction))
|
652
|
-
return t.memberExpression(
|
653
|
-
t.memberExpression(t.identifier(globalFunction), t.identifier("constructor")),
|
654
|
-
t.identifier("prototype")
|
655
|
-
)
|
675
|
+
const name = globalFunctionsUnder7Characters.find(name => !program.scope.hasOwnBinding(name))
|
656
676
|
return t.memberExpression(
|
657
|
-
t.
|
658
|
-
|
659
|
-
t.identifier("constructor")
|
660
|
-
),
|
661
|
-
t.identifier("prototype")
|
677
|
+
name ? t.identifier(name) : t.arrowFunctionExpression([t.identifier("_")], t.identifier("_")),
|
678
|
+
t.identifier("__proto__")
|
662
679
|
)
|
663
680
|
}
|
664
|
-
function processFakeSubscriptObject(fakeSubscriptObjectName) {
|
681
|
+
function processFakeSubscriptObject(fakeSubscriptObjectName, seclevel) {
|
665
682
|
for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
|
666
|
-
assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:
|
683
|
+
assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:807:60")
|
667
684
|
assert("Identifier" == referencePath.parent.property.type)
|
668
685
|
assert(
|
669
686
|
"MemberExpression" == referencePath.parentPath.parentPath?.node.type,
|
670
|
-
"src/processScript/transform.ts:
|
687
|
+
"src/processScript/transform.ts:809:81"
|
671
688
|
)
|
672
689
|
assert(
|
673
690
|
"Identifier" == referencePath.parentPath.parentPath.node.property.type,
|
674
|
-
"src/processScript/transform.ts:
|
691
|
+
"src/processScript/transform.ts:810:83"
|
675
692
|
)
|
676
693
|
assert(
|
677
694
|
/^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parent.property.name),
|
678
|
-
`src/processScript/transform.ts:
|
695
|
+
`src/processScript/transform.ts:814:8 invalid user "${referencePath.parent.property.name}" in subscript`
|
679
696
|
)
|
680
697
|
assert(
|
681
698
|
/^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parentPath.parentPath.node.property.name),
|
682
|
-
`src/processScript/transform.ts:
|
699
|
+
`src/processScript/transform.ts:819:8 invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
|
683
700
|
)
|
684
701
|
if ("CallExpression" == referencePath.parentPath.parentPath.parentPath?.type)
|
685
702
|
referencePath.parentPath.parentPath.replaceWith(
|
686
703
|
t.identifier(
|
687
|
-
`$${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}$`
|
688
705
|
)
|
689
706
|
)
|
690
707
|
else {
|
691
708
|
const name = `${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}`
|
692
709
|
referencePath.parentPath.parentPath.replaceWith(t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`))
|
693
|
-
neededSubscriptLets.
|
710
|
+
const maxSecLevel = Math.max(neededSubscriptLets.get(name) || 0, seclevel)
|
711
|
+
neededSubscriptLets.set(name, maxSecLevel)
|
694
712
|
}
|
695
713
|
}
|
696
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,19 +43,37 @@ 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),
|
@@ -63,13 +82,15 @@ async function push(
|
|
63
82
|
.map(({ name }) => name.slice(0, -4))
|
64
83
|
])
|
65
84
|
if (!allUsers.size)
|
66
|
-
|
67
|
-
|
68
|
-
|
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())
|
69
90
|
for (const script of scripts) {
|
70
91
|
const [user, scriptName] = script.split(".")
|
71
|
-
assert(user, "src/push.ts:
|
72
|
-
assert(scriptName, "src/push.ts:
|
92
|
+
assert(user, "src/push.ts:108:16")
|
93
|
+
assert(scriptName, "src/push.ts:109:22")
|
73
94
|
"*" == user ? scriptNamesToUsers.set(scriptName, allUsers) : scriptNamesToUsers.get(scriptName).add(user)
|
74
95
|
}
|
75
96
|
const sourceFolderFiles = sourceFolder.filter(({ stats }) => stats.isFile()),
|
@@ -100,8 +121,8 @@ async function push(
|
|
100
121
|
for (const [scriptName, users] of scriptNamesToUsers)
|
101
122
|
for (const user of users)
|
102
123
|
if (!usersToScriptsToPush.get(user).has(scriptName))
|
103
|
-
|
104
|
-
const pathsToUsers = new
|
124
|
+
return new NoScriptsError(`Could not find script ${user}.${scriptName} to push`)
|
125
|
+
const pathsToUsers = new AutoMap(_path => new Set())
|
105
126
|
for (const [user, scriptsToPush] of usersToScriptsToPush)
|
106
127
|
for (const path of scriptsToPush.values()) pathsToUsers.get(path).add(user)
|
107
128
|
const allInfo = []
|
@@ -111,16 +132,17 @@ async function push(
|
|
111
132
|
uniqueId = Math.floor(Math.random() * 2 ** 52)
|
112
133
|
.toString(36)
|
113
134
|
.padStart(11, "0"),
|
114
|
-
{ script: minifiedCode } = await processScript(await readFile(path, { encoding: "utf8" }), {
|
135
|
+
{ script: minifiedCode, warnings } = await processScript(await readFile(path, { encoding: "utf8" }), {
|
115
136
|
minify,
|
116
137
|
scriptUser: !0,
|
117
138
|
scriptName,
|
118
139
|
uniqueId,
|
119
140
|
filePath: path,
|
120
141
|
mangleNames,
|
121
|
-
forceQuineCheats
|
142
|
+
forceQuineCheats,
|
143
|
+
rootFolderPath
|
122
144
|
}),
|
123
|
-
info = { path, users, characterCount: countHackmudCharacters(minifiedCode), error: void 0 }
|
145
|
+
info = { path, users, characterCount: countHackmudCharacters(minifiedCode), error: void 0, warnings }
|
124
146
|
await Promise.all(
|
125
147
|
users.map(user =>
|
126
148
|
writeFilePersistent(
|
@@ -137,4 +159,4 @@ async function push(
|
|
137
159
|
)
|
138
160
|
return allInfo
|
139
161
|
}
|
140
|
-
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>;
|