hackmud-script-manager 0.20.4-23a791c → 0.20.4-34a1e78

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.
@@ -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 topFunctionName = `_${uniqueId}_SCRIPT_`,
26
- exports = new Map(),
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:105:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
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:110:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
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:115:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
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:123:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
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:128:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
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:133:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
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,40 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
101
108
  functionDotPrototypeIsReferencedMultipleTimes = !0
102
109
  }
103
110
  }
104
- const neededSubscriptLets = new Set()
111
+ const neededSubscriptLets = new Map()
105
112
  let detectedSeclevel = 4
106
113
  for (const fakeSubscriptObjectName of ["$fs", "$4s", "$s"])
107
- program.scope.hasGlobal(fakeSubscriptObjectName) && processFakeSubscriptObject(fakeSubscriptObjectName)
114
+ program.scope.hasGlobal(fakeSubscriptObjectName) && processFakeSubscriptObject(fakeSubscriptObjectName, 4)
108
115
  for (const fakeSubscriptObjectName of ["$hs", "$3s"])
109
116
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
110
117
  detectedSeclevel = 3
111
- processFakeSubscriptObject(fakeSubscriptObjectName)
118
+ processFakeSubscriptObject(fakeSubscriptObjectName, 3)
112
119
  }
113
120
  for (const fakeSubscriptObjectName of ["$ms", "$2s"])
114
121
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
115
122
  detectedSeclevel = 2
116
- processFakeSubscriptObject(fakeSubscriptObjectName)
123
+ processFakeSubscriptObject(fakeSubscriptObjectName, 2)
117
124
  }
118
125
  for (const fakeSubscriptObjectName of ["$ls", "$1s"])
119
126
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
120
127
  detectedSeclevel = 1
121
- processFakeSubscriptObject(fakeSubscriptObjectName)
128
+ processFakeSubscriptObject(fakeSubscriptObjectName, 1)
122
129
  }
123
130
  for (const fakeSubscriptObjectName of ["$ns", "$0s"])
124
131
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
125
132
  detectedSeclevel = 0
126
- processFakeSubscriptObject(fakeSubscriptObjectName)
133
+ processFakeSubscriptObject(fakeSubscriptObjectName, 0)
127
134
  }
128
135
  seclevel = Math.min(seclevel, detectedSeclevel)
129
136
  const neededDbMethodLets = new Set()
130
137
  if (program.scope.hasGlobal("$db"))
131
138
  for (const referencePath of getReferencePathsToGlobal("$db", program)) {
132
- assert("MemberExpression" == referencePath.parentPath.node.type, "src/processScript/transform.ts:187:69")
133
- assert("Identifier" == referencePath.parentPath.node.property.type, "src/processScript/transform.ts:188:72")
139
+ assert("MemberExpression" == referencePath.parentPath.node.type, "src/processScript/transform.ts:193:69")
140
+ assert("Identifier" == referencePath.parentPath.node.property.type, "src/processScript/transform.ts:194:72")
134
141
  const databaseOpMethodName = referencePath.parentPath.node.property.name
135
142
  assert(
136
143
  validDBMethods.includes(databaseOpMethodName),
137
- `src/processScript/transform.ts:194:8 invalid db method "${databaseOpMethodName}", valid db methods are "${validDBMethods.join('", "')}"`
144
+ `src/processScript/transform.ts:200:8 invalid db method "${databaseOpMethodName}", valid db methods are "${validDBMethods.join('", "')}"`
138
145
  )
139
146
  if ("CallExpression" == referencePath.parentPath.parentPath?.type)
140
147
  referencePath.parentPath.replaceWith(t.identifier(`$${uniqueId}$DB$${databaseOpMethodName}$`))
@@ -157,27 +164,32 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
157
164
  if (program.scope.hasGlobal("$FMCL"))
158
165
  for (const referencePath of getReferencePathsToGlobal("$FMCL", program))
159
166
  referencePath.replaceWith(t.identifier(`$${uniqueId}$FMCL$`))
160
- if (program.scope.hasGlobal("$G"))
167
+ let needG = program.scope.hasGlobal("$G")
168
+ if (needG)
161
169
  for (const referencePath of getReferencePathsToGlobal("$G", program))
162
- referencePath.replaceWith(t.identifier(`$${uniqueId}$GLOBAL$`))
170
+ referencePath.replaceWith(t.identifier(`_${uniqueId}_G_`))
163
171
  if (program.scope.hasGlobal("_SECLEVEL"))
164
172
  for (const referencePath of getReferencePathsToGlobal("_SECLEVEL", program))
165
173
  referencePath.replaceWith(t.numericLiteral(seclevel))
166
- let needGetPrototypeOf = !1
174
+ let needGetPrototypeOf = !1,
175
+ needHasOwn = !1
167
176
  if (program.scope.hasGlobal("Object"))
168
177
  for (const referencePath of getReferencePathsToGlobal("Object", program))
169
178
  if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
170
- assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:241:64")
179
+ assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:250:64")
171
180
  if ("getPrototypeOf" == referencePath.parent.property.name) {
172
181
  referencePath.parentPath.replaceWith(t.identifier(`_${uniqueId}_GET_PROTOTYPE_OF_`))
173
182
  needGetPrototypeOf = !0
183
+ } else if ("hasOwn" == referencePath.parent.property.name) {
184
+ referencePath.parentPath.replaceWith(t.identifier(`_${uniqueId}_HAS_OWN_`))
185
+ needHasOwn = !0
174
186
  }
175
187
  }
176
188
  const consoleMethodsReferenced = new Set()
177
189
  if (program.scope.hasGlobal("console"))
178
190
  for (const referencePath of getReferencePathsToGlobal("console", program))
179
191
  if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
180
- assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:256:64")
192
+ assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:268:64")
181
193
  referencePath.parentPath.replaceWith(
182
194
  t.identifier(`_${uniqueId}_CONSOLE_METHOD_${referencePath.parent.property.name}_`)
183
195
  )
@@ -185,19 +197,20 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
185
197
  }
186
198
  const lastStatement = program.node.body.at(-1)
187
199
  let exportDefaultName
188
- assert(lastStatement, "src/processScript/transform.ts:270:27 program is empty")
200
+ assert(lastStatement, "src/processScript/transform.ts:282:27 program is empty")
189
201
  if ("ExportNamedDeclaration" == lastStatement.type) {
190
202
  program.node.body.pop()
191
203
  for (const specifier of lastStatement.specifiers) {
192
204
  assert(
193
205
  "ExportSpecifier" == specifier.type,
194
- `src/processScript/transform.ts:276:51 ${specifier.type} is currently unsupported`
206
+ `src/processScript/transform.ts:288:51 ${specifier.type} is currently unsupported`
207
+ )
208
+ if (
209
+ "default" !=
210
+ ("Identifier" == specifier.exported.type ? specifier.exported.name : specifier.exported.value)
195
211
  )
196
- const exportedName =
197
- "Identifier" == specifier.exported.type ? specifier.exported.name : specifier.exported.value
198
- "default" == exportedName ?
199
- (exportDefaultName = specifier.local.name)
200
- : exports.set(specifier.local.name, exportedName)
212
+ throw Error("Only default exports are supported")
213
+ exportDefaultName = specifier.local.name
201
214
  }
202
215
  }
203
216
  const globalBlock = t.blockStatement([])
@@ -223,10 +236,6 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
223
236
  t.returnStatement(t.callExpression(t.identifier(exportDefaultName), []))
224
237
  ])
225
238
  ))
226
- if ("const" != statement.kind && exports.has(identifierName)) {
227
- liveExports.set(identifierName, exports.get(identifierName))
228
- exports.delete(identifierName)
229
- }
230
239
  globalBlock.body.push(
231
240
  t.variableDeclaration("let", [t.variableDeclarator(t.identifier(identifierName))])
232
241
  )
@@ -291,34 +300,16 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
291
300
  }
292
301
  program.node.body = [mainFunction]
293
302
  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
303
  program.scope.crawl()
313
304
  const globalBlockVariables = new Set()
314
305
  let hoistedGlobalBlockFunctions = 0
315
306
  for (const [globalBlockIndex, globalBlockStatement] of [...globalBlock.body.entries()].reverse())
316
307
  if ("VariableDeclaration" == globalBlockStatement.type) {
317
- assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:410:59")
308
+ assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:402:59")
318
309
  const declarator = globalBlockStatement.declarations[0]
319
310
  assert(
320
311
  "Identifier" == declarator.id.type,
321
- `src/processScript/transform.ts:414:51 declarator.id.type was "${declarator.id.type}"`
312
+ `src/processScript/transform.ts:406:51 declarator.id.type was "${declarator.id.type}"`
322
313
  )
323
314
  program.scope.crawl()
324
315
  if (program.scope.hasGlobal(declarator.id.name)) {
@@ -333,15 +324,16 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
333
324
  Object.keys(program.scope.globals).some(global => globalBlockVariables.has(global))
334
325
  ) {
335
326
  const binding = program.scope.getBinding(declarator.id.name)
336
- assert(binding, "src/processScript/transform.ts:433:23")
327
+ assert(binding, "src/processScript/transform.ts:425:23")
337
328
  for (const referencePath of binding.referencePaths) {
338
- assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:436:56")
329
+ assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:428:56")
339
330
  referencePath.replaceWith(
340
331
  t.memberExpression(
341
- t.identifier(`$${uniqueId}$GLOBAL$`),
332
+ t.identifier(`_${uniqueId}_G_`),
342
333
  t.identifier(referencePath.node.name)
343
334
  )
344
335
  )
336
+ needG = !0
345
337
  }
346
338
  for (const referencePath of binding.constantViolations)
347
339
  if ("AssignmentExpression" == referencePath.node.type)
@@ -350,12 +342,13 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
350
342
  clearObject(node)
351
343
  Object.assign(
352
344
  node,
353
- t.memberExpression(t.identifier(`$${uniqueId}$GLOBAL$`), t.identifier(name))
345
+ t.memberExpression(t.identifier(`_${uniqueId}_G_`), t.identifier(name))
354
346
  )
347
+ needG = !0
355
348
  }
356
349
  globalBlockPath.remove()
357
350
  globalBlockStatementPath.remove()
358
- declarator.init &&
351
+ if (declarator.init) {
359
352
  globalBlock.body.splice(
360
353
  globalBlockIndex,
361
354
  0,
@@ -363,13 +356,15 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
363
356
  t.assignmentExpression(
364
357
  "=",
365
358
  t.memberExpression(
366
- t.identifier(`$${uniqueId}$GLOBAL$`),
359
+ t.identifier(`_${uniqueId}_G_`),
367
360
  t.identifier(declarator.id.name)
368
361
  ),
369
362
  declarator.init
370
363
  )
371
364
  )
372
365
  )
366
+ needG = !0
367
+ }
373
368
  } else {
374
369
  globalBlockPath.remove()
375
370
  globalBlockStatementPath.remove()
@@ -379,22 +374,20 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
379
374
  } else globalBlockVariables.add(declarator.id.name)
380
375
  } else if ("ClassDeclaration" == globalBlockStatement.type) {
381
376
  program.scope.crawl()
382
- assert(globalBlockStatement.id, "src/processScript/transform.ts:487:37")
377
+ assert(globalBlockStatement.id, "src/processScript/transform.ts:485:37")
383
378
  if (program.scope.hasGlobal(globalBlockStatement.id.name)) {
384
379
  globalBlock.body.splice(globalBlockIndex, 1)
385
380
  const [globalBlockPath] = program.unshiftContainer("body", globalBlock),
386
381
  [globalBlockStatementPath] = program.unshiftContainer("body", globalBlockStatement)
387
382
  program.scope.crawl()
388
383
  const binding = program.scope.getBinding(globalBlockStatement.id.name)
389
- assert(binding, "src/processScript/transform.ts:499:22")
384
+ assert(binding, "src/processScript/transform.ts:497:22")
390
385
  for (const referencePath of binding.referencePaths) {
391
- assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:502:55")
386
+ assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:500:55")
392
387
  referencePath.replaceWith(
393
- t.memberExpression(
394
- t.identifier(`$${uniqueId}$GLOBAL$`),
395
- t.identifier(referencePath.node.name)
396
- )
388
+ t.memberExpression(t.identifier(`_${uniqueId}_G_`), t.identifier(referencePath.node.name))
397
389
  )
390
+ needG = !0
398
391
  }
399
392
  globalBlockPath.remove()
400
393
  globalBlockStatementPath.remove()
@@ -405,7 +398,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
405
398
  t.assignmentExpression(
406
399
  "=",
407
400
  t.memberExpression(
408
- t.identifier(`$${uniqueId}$GLOBAL$`),
401
+ t.identifier(`_${uniqueId}_G_`),
409
402
  t.identifier(globalBlockStatement.id.name)
410
403
  ),
411
404
  t.classExpression(
@@ -417,13 +410,9 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
417
410
  )
418
411
  )
419
412
  )
413
+ needG = !0
420
414
  }
421
415
  }
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
416
  globalBlock.body.length &&
428
417
  mainFunction.body.body.splice(
429
418
  hoistedGlobalBlockFunctions,
@@ -472,6 +461,31 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
472
461
  )
473
462
  ])
474
463
  )
464
+ needHasOwn &&
465
+ mainFunction.body.body.unshift(
466
+ t.variableDeclaration("let", [
467
+ t.variableDeclarator(
468
+ t.identifier(`_${uniqueId}_HAS_OWN_`),
469
+ t.callExpression(
470
+ t.memberExpression(
471
+ t.memberExpression(
472
+ t.identifier(
473
+ globalFunctionsUnder7Characters.find(name => !program.scope.hasOwnBinding(name))
474
+ ),
475
+ t.identifier("call")
476
+ ),
477
+ t.identifier("bind")
478
+ ),
479
+ [
480
+ t.memberExpression(
481
+ t.memberExpression(t.identifier("Object"), t.identifier("prototype")),
482
+ t.identifier("hasOwnProperty")
483
+ )
484
+ ]
485
+ )
486
+ )
487
+ ])
488
+ )
475
489
  consoleMethodsReferenced.size &&
476
490
  mainFunction.body.body.unshift(
477
491
  t.variableDeclaration(
@@ -522,12 +536,12 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
522
536
  mainFunction.body.body.unshift(
523
537
  t.variableDeclaration(
524
538
  "let",
525
- [...neededSubscriptLets].map(name =>
539
+ [...neededSubscriptLets].map(([name, seclevel]) =>
526
540
  t.variableDeclarator(
527
541
  t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`),
528
542
  t.arrowFunctionExpression(
529
543
  [t.restElement(t.identifier("args"))],
530
- t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$${name}$`), [
544
+ t.callExpression(t.identifier(`$${uniqueId}$${seclevel}$SUBSCRIPT$${name}$`), [
531
545
  t.spreadElement(t.identifier("args"))
532
546
  ])
533
547
  )
@@ -535,6 +549,12 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
535
549
  )
536
550
  )
537
551
  )
552
+ needG &&
553
+ mainFunction.body.body.unshift(
554
+ t.variableDeclaration("let", [
555
+ t.variableDeclarator(t.identifier(`_${uniqueId}_G_`), t.identifier(`$${uniqueId}$GLOBAL$`))
556
+ ])
557
+ )
538
558
  traverse(file, {
539
559
  BlockStatement({ node: blockStatement }) {
540
560
  for (const [index, functionDeclaration] of blockStatement.body.entries())
@@ -555,7 +575,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
555
575
  }
556
576
  },
557
577
  ClassBody({ node: classBody, scope, parent }) {
558
- assert(t.isClass(parent), "src/processScript/transform.ts:669:30")
578
+ assert(t.isClass(parent), "src/processScript/transform.ts:695:30")
559
579
  let thisIsReferenced = !1
560
580
  for (const classMethod of classBody.body) {
561
581
  if ("ClassMethod" != classMethod.type) continue
@@ -645,52 +665,45 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
645
665
  )
646
666
  }
647
667
  })
648
- return { file, seclevel }
668
+ return { file, seclevel, warnings }
649
669
  function createGetFunctionPrototypeNode() {
650
- for (const globalFunction of globalFunctionsUnder7Characters)
651
- if (!program.scope.hasOwnBinding(globalFunction))
652
- return t.memberExpression(
653
- t.memberExpression(t.identifier(globalFunction), t.identifier("constructor")),
654
- t.identifier("prototype")
655
- )
670
+ const name = globalFunctionsUnder7Characters.find(name => !program.scope.hasOwnBinding(name))
656
671
  return t.memberExpression(
657
- t.memberExpression(
658
- t.arrowFunctionExpression([t.identifier("_")], t.identifier("_")),
659
- t.identifier("constructor")
660
- ),
661
- t.identifier("prototype")
672
+ name ? t.identifier(name) : t.arrowFunctionExpression([t.identifier("_")], t.identifier("_")),
673
+ t.identifier("__proto__")
662
674
  )
663
675
  }
664
- function processFakeSubscriptObject(fakeSubscriptObjectName) {
676
+ function processFakeSubscriptObject(fakeSubscriptObjectName, seclevel) {
665
677
  for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
666
- assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:785:60")
678
+ assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:801:60")
667
679
  assert("Identifier" == referencePath.parent.property.type)
668
680
  assert(
669
681
  "MemberExpression" == referencePath.parentPath.parentPath?.node.type,
670
- "src/processScript/transform.ts:787:81"
682
+ "src/processScript/transform.ts:803:81"
671
683
  )
672
684
  assert(
673
685
  "Identifier" == referencePath.parentPath.parentPath.node.property.type,
674
- "src/processScript/transform.ts:788:83"
686
+ "src/processScript/transform.ts:804:83"
675
687
  )
676
688
  assert(
677
689
  /^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parent.property.name),
678
- `src/processScript/transform.ts:792:8 invalid user "${referencePath.parent.property.name}" in subscript`
690
+ `src/processScript/transform.ts:808:8 invalid user "${referencePath.parent.property.name}" in subscript`
679
691
  )
680
692
  assert(
681
693
  /^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parentPath.parentPath.node.property.name),
682
- `src/processScript/transform.ts:797:8 invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
694
+ `src/processScript/transform.ts:813:8 invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
683
695
  )
684
696
  if ("CallExpression" == referencePath.parentPath.parentPath.parentPath?.type)
685
697
  referencePath.parentPath.parentPath.replaceWith(
686
698
  t.identifier(
687
- `$${uniqueId}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
699
+ `$${uniqueId}$${seclevel}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
688
700
  )
689
701
  )
690
702
  else {
691
703
  const name = `${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}`
692
704
  referencePath.parentPath.parentPath.replaceWith(t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`))
693
- neededSubscriptLets.add(name)
705
+ const maxSecLevel = Math.max(neededSubscriptLets.get(name) || 0, seclevel)
706
+ neededSubscriptLets.set(name, maxSecLevel)
694
707
  }
695
708
  }
696
709
  }
package/push.d.ts CHANGED
@@ -18,6 +18,14 @@ export type PushOptions = LaxPartial<{
18
18
  */
19
19
  forceQuineCheats: boolean;
20
20
  }>;
21
+ export declare class MissingSourceFolderError extends Error {
22
+ }
23
+ export declare class MissingHackmudFolderError extends Error {
24
+ }
25
+ export declare class NoUsersError extends Error {
26
+ }
27
+ export declare class NoScriptsError extends Error {
28
+ }
21
29
  /** Push scripts from a source directory to the hackmud directory.
22
30
  *
23
31
  * Pushes files directly in the source folder to all users
@@ -25,4 +33,4 @@ export type PushOptions = LaxPartial<{
25
33
  * @param hackmudPath directory created by hackmud containing user data including scripts
26
34
  * @param options {@link PushOptions details}
27
35
  * @returns array of info on pushed scripts */
28
- export declare function push(sourcePath: string, hackmudPath: string, { scripts, onPush, minify, mangleNames, forceQuineCheats }?: PushOptions): Promise<Info[]>;
36
+ export declare function push(sourcePath: string, hackmudPath: string, { scripts, onPush, minify, mangleNames, forceQuineCheats }?: PushOptions): Promise<MissingSourceFolderError | MissingHackmudFolderError | NoUsersError | NoScriptsError | Info[]>;
package/push.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Cache } from "@samual/lib/Cache"
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"
@@ -42,32 +42,54 @@ import "./processScript/preprocess.js"
42
42
  import "import-meta-resolve"
43
43
  import "./processScript/transform.js"
44
44
  import "@samual/lib/clearObject"
45
+ class MissingSourceFolderError extends Error {}
46
+ Object.defineProperty(MissingSourceFolderError.prototype, "name", { value: "MissingSourceFolderError" })
47
+ class MissingHackmudFolderError extends Error {}
48
+ Object.defineProperty(MissingHackmudFolderError.prototype, "name", { value: "MissingHackmudFolderError" })
49
+ class NoUsersError extends Error {}
50
+ Object.defineProperty(NoUsersError.prototype, "name", { value: "NoUsersError" })
51
+ class NoScriptsError extends Error {}
52
+ Object.defineProperty(NoScriptsError.prototype, "name", { value: "NoScriptsError" })
45
53
  async function push(
46
54
  sourcePath,
47
55
  hackmudPath,
48
56
  { scripts = ["*.*"], onPush = () => {}, minify = !0, mangleNames = !1, forceQuineCheats } = {}
49
57
  ) {
50
58
  const [sourceFolder, hackmudFolder] = await Promise.all([
51
- readDirectoryWithStats(sourcePath),
52
- readDirectoryWithStats(hackmudPath)
53
- ]),
54
- sourceFolderFolders = sourceFolder.filter(({ stats }) => stats.isDirectory()),
59
+ readDirectoryWithStats(sourcePath).catch(error => {
60
+ if (error && "ENOENT" == error.code)
61
+ return new MissingSourceFolderError("There is no folder at " + sourcePath)
62
+ throw error
63
+ }),
64
+ readDirectoryWithStats(hackmudPath).catch(error => {
65
+ if (error && "ENOENT" == error.code)
66
+ return new MissingHackmudFolderError("There is no folder at " + hackmudPath)
67
+ throw error
68
+ })
69
+ ])
70
+ if (sourceFolder instanceof Error) return sourceFolder
71
+ if (hackmudFolder instanceof Error) return hackmudFolder
72
+ const sourceFolderFolders = sourceFolder.filter(({ stats }) => stats.isDirectory()),
55
73
  allUsers = new Set([
56
74
  ...scripts
57
- .map(scriptName => ensure(scriptName.split(".")[0], "src/push.ts:52:65"))
75
+ .map(scriptName => ensure(scriptName.split(".")[0], "src/push.ts:82:65"))
58
76
  .filter(name => "*" != name),
59
77
  ...sourceFolderFolders.map(({ name }) => name),
60
78
  ...hackmudFolder.filter(({ stats }) => stats.isDirectory()).map(({ name }) => name),
61
79
  ...hackmudFolder
62
80
  .filter(({ stats, name }) => stats.isFile() && name.endsWith(".key"))
63
81
  .map(({ name }) => name.slice(0, -4))
64
- ]),
65
- usersToScriptsToPush = new Cache(_user => new Map()),
66
- scriptNamesToUsers = new Cache(_scriptName => new Set())
82
+ ])
83
+ if (!allUsers.size)
84
+ return new NoUsersError(
85
+ "Could not find any users. Either provide the names of your users or log into a user in hackmud"
86
+ )
87
+ const usersToScriptsToPush = new AutoMap(_user => new Map()),
88
+ scriptNamesToUsers = new AutoMap(_scriptName => new Set())
67
89
  for (const script of scripts) {
68
90
  const [user, scriptName] = script.split(".")
69
- assert(user, "src/push.ts:69:16")
70
- assert(scriptName, "src/push.ts:70:22")
91
+ assert(user, "src/push.ts:105:16")
92
+ assert(scriptName, "src/push.ts:106:22")
71
93
  "*" == user ? scriptNamesToUsers.set(scriptName, allUsers) : scriptNamesToUsers.get(scriptName).add(user)
72
94
  }
73
95
  const sourceFolderFiles = sourceFolder.filter(({ stats }) => stats.isFile()),
@@ -98,8 +120,8 @@ async function push(
98
120
  for (const [scriptName, users] of scriptNamesToUsers)
99
121
  for (const user of users)
100
122
  if (!usersToScriptsToPush.get(user).has(scriptName))
101
- throw Error(`Could not find script ${user}.${scriptName} to push`)
102
- const pathsToUsers = new Cache(_path => new Set())
123
+ return new NoScriptsError(`Could not find script ${user}.${scriptName} to push`)
124
+ const pathsToUsers = new AutoMap(_path => new Set())
103
125
  for (const [user, scriptsToPush] of usersToScriptsToPush)
104
126
  for (const path of scriptsToPush.values()) pathsToUsers.get(path).add(user)
105
127
  const allInfo = []
@@ -109,7 +131,7 @@ async function push(
109
131
  uniqueId = Math.floor(Math.random() * 2 ** 52)
110
132
  .toString(36)
111
133
  .padStart(11, "0"),
112
- { script: minifiedCode } = await processScript(await readFile(path, { encoding: "utf8" }), {
134
+ { script: minifiedCode, warnings } = await processScript(await readFile(path, { encoding: "utf8" }), {
113
135
  minify,
114
136
  scriptUser: !0,
115
137
  scriptName,
@@ -118,7 +140,7 @@ async function push(
118
140
  mangleNames,
119
141
  forceQuineCheats
120
142
  }),
121
- info = { path, users, characterCount: countHackmudCharacters(minifiedCode), error: void 0 }
143
+ info = { path, users, characterCount: countHackmudCharacters(minifiedCode), error: void 0, warnings }
122
144
  await Promise.all(
123
145
  users.map(user =>
124
146
  writeFilePersistent(
@@ -135,4 +157,4 @@ async function push(
135
157
  )
136
158
  return allInfo
137
159
  }
138
- export { push }
160
+ export { MissingHackmudFolderError, MissingSourceFolderError, NoScriptsError, NoUsersError, push }