hackmud-script-manager 0.19.1-98e81f8 → 0.19.1-bf4dc4a

Sign up to get free protection for your applications and to get access to all the features.
@@ -111,39 +111,34 @@ const { default: traverse } = babelTraverse,
111
111
  }
112
112
  }
113
113
  let detectedSeclevel = 4
114
- const processFakeSubscriptObject = fakeSubscriptObjectName => {
115
- for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
116
- assert("MemberExpression" == referencePath.parent.type)
117
- assert("Identifier" == referencePath.parent.property.type)
118
- assert("MemberExpression" == referencePath.parentPath.parentPath?.node.type)
119
- assert("Identifier" == referencePath.parentPath.parentPath.node.property.type)
120
- assert(
121
- /^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parent.property.name),
122
- `invalid user "${referencePath.parent.property.name}" in subscript`
123
- )
124
- assert(
125
- /^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parentPath.parentPath.node.property.name),
126
- `invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
127
- )
128
- "CallExpression" == referencePath.parentPath.parentPath.parentPath?.type ?
129
- referencePath.parentPath.parentPath.replaceWith(
130
- t.identifier(
131
- `$${uniqueID}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
132
- )
114
+ const neededSubscriptLets = new Set(),
115
+ processFakeSubscriptObject = fakeSubscriptObjectName => {
116
+ for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
117
+ assert("MemberExpression" == referencePath.parent.type)
118
+ assert("Identifier" == referencePath.parent.property.type)
119
+ assert("MemberExpression" == referencePath.parentPath.parentPath?.node.type)
120
+ assert("Identifier" == referencePath.parentPath.parentPath.node.property.type)
121
+ assert(
122
+ /^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parent.property.name),
123
+ `invalid user "${referencePath.parent.property.name}" in subscript`
133
124
  )
134
- : referencePath.parentPath.parentPath.replaceWith(
135
- t.arrowFunctionExpression(
136
- [t.restElement(t.identifier("args"))],
137
- t.callExpression(
138
- t.identifier(
139
- `$${uniqueID}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
140
- ),
141
- [t.spreadElement(t.identifier("args"))]
125
+ assert(
126
+ /^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parentPath.parentPath.node.property.name),
127
+ `invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
128
+ )
129
+ if ("CallExpression" == referencePath.parentPath.parentPath.parentPath?.type)
130
+ referencePath.parentPath.parentPath.replaceWith(
131
+ t.identifier(
132
+ `$${uniqueID}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
142
133
  )
143
134
  )
144
- )
135
+ else {
136
+ const name = `${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}`
137
+ referencePath.parentPath.parentPath.replaceWith(t.identifier(`_${uniqueID}_SUBSCRIPT_${name}_`))
138
+ neededSubscriptLets.add(name)
139
+ }
140
+ }
145
141
  }
146
- }
147
142
  for (const fakeSubscriptObjectName of ["$fs", "$4s", "$s"])
148
143
  program.scope.hasGlobal(fakeSubscriptObjectName) && processFakeSubscriptObject(fakeSubscriptObjectName)
149
144
  for (const fakeSubscriptObjectName of ["$hs", "$3s"])
@@ -167,6 +162,7 @@ const { default: traverse } = babelTraverse,
167
162
  processFakeSubscriptObject(fakeSubscriptObjectName)
168
163
  }
169
164
  seclevel = Math.min(seclevel, detectedSeclevel)
165
+ const neededDbMethodLets = new Set()
170
166
  if (program.scope.hasGlobal("$db"))
171
167
  for (const referencePath of getReferencePathsToGlobal("$db", program)) {
172
168
  assert("MemberExpression" == referencePath.parentPath.node.type)
@@ -176,44 +172,24 @@ const { default: traverse } = babelTraverse,
176
172
  validDBMethods.includes(databaseOpMethodName),
177
173
  `invalid db method "${databaseOpMethodName}", valid db methods are "${validDBMethods.join('", "')}"`
178
174
  )
179
- "CallExpression" == referencePath.parentPath.parentPath?.type ?
175
+ if ("CallExpression" == referencePath.parentPath.parentPath?.type)
180
176
  referencePath.parentPath.replaceWith(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`))
181
- : "ObjectId" == databaseOpMethodName ?
182
- referencePath.parentPath.replaceWith(
183
- t.arrowFunctionExpression(
184
- [],
185
- t.callExpression(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`), [])
186
- )
187
- )
188
- : "i" == databaseOpMethodName || "r" == databaseOpMethodName ?
177
+ else {
189
178
  referencePath.parentPath.replaceWith(
190
- t.arrowFunctionExpression(
191
- [t.identifier("a")],
192
- t.callExpression(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`), [
193
- t.identifier("a")
194
- ])
195
- )
196
- )
197
- : referencePath.parentPath.replaceWith(
198
- t.arrowFunctionExpression(
199
- [t.identifier("a"), t.identifier("b")],
200
- t.callExpression(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`), [
201
- t.identifier("a"),
202
- t.identifier("b")
203
- ])
204
- )
179
+ t.identifier(`_${uniqueID}_CONSOLE_METHOD_${databaseOpMethodName}_`)
205
180
  )
181
+ neededDbMethodLets.add(databaseOpMethodName)
182
+ }
206
183
  }
184
+ let needDebugLet = !1
207
185
  if (program.scope.hasGlobal("$D"))
208
186
  for (const referencePath of getReferencePathsToGlobal("$D", program))
209
- "CallExpression" == referencePath.parentPath.type ?
187
+ if ("CallExpression" == referencePath.parentPath.type)
210
188
  referencePath.replaceWith(t.identifier(`$${uniqueID}$DEBUG$`))
211
- : referencePath.replaceWith(
212
- t.arrowFunctionExpression(
213
- [t.identifier("a")],
214
- t.callExpression(t.identifier(`$${uniqueID}$DEBUG$`), [t.identifier("a")])
215
- )
216
- )
189
+ else {
190
+ referencePath.replaceWith(t.identifier(`_${uniqueID}_DEBUG_`))
191
+ needDebugLet = !0
192
+ }
217
193
  if (program.scope.hasGlobal("$FMCL"))
218
194
  for (const referencePath of getReferencePathsToGlobal("$FMCL", program))
219
195
  referencePath.replaceWith(t.identifier(`$${uniqueID}$FMCL$`))
@@ -223,8 +199,7 @@ const { default: traverse } = babelTraverse,
223
199
  if (program.scope.hasGlobal("_SECLEVEL"))
224
200
  for (const referencePath of getReferencePathsToGlobal("_SECLEVEL", program))
225
201
  referencePath.replaceWith(t.numericLiteral(seclevel))
226
- let needGetPrototypeOf = !1,
227
- needSetPrototypeOf = !1
202
+ let needGetPrototypeOf = !1
228
203
  if (program.scope.hasGlobal("Object"))
229
204
  for (const referencePath of getReferencePathsToGlobal("Object", program))
230
205
  if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
@@ -232,11 +207,18 @@ const { default: traverse } = babelTraverse,
232
207
  if ("getPrototypeOf" == referencePath.parent.property.name) {
233
208
  referencePath.parentPath.replaceWith(t.identifier(`_${uniqueID}_GET_PROTOTYPE_OF_`))
234
209
  needGetPrototypeOf = !0
235
- } else if ("setPrototypeOf" == referencePath.parent.property.name) {
236
- referencePath.parentPath.replaceWith(t.identifier(`_${uniqueID}_SET_PROTOTYPE_OF_`))
237
- needSetPrototypeOf = !0
238
210
  }
239
211
  }
212
+ const consoleMethodsReferenced = new Set()
213
+ if (program.scope.hasGlobal("console"))
214
+ for (const referencePath of getReferencePathsToGlobal("console", program))
215
+ if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
216
+ assert("Identifier" == referencePath.parent.property.type)
217
+ referencePath.parentPath.replaceWith(
218
+ t.identifier(`_${uniqueID}_CONSOLE_METHOD_${referencePath.parent.property.name}_`)
219
+ )
220
+ consoleMethodsReferenced.add(referencePath.parent.property.name)
221
+ }
240
222
  const lastStatement = program.node.body.at(-1)
241
223
  let exportDefaultName
242
224
  assert(lastStatement, "program is empty")
@@ -410,7 +392,7 @@ const { default: traverse } = babelTraverse,
410
392
  } else globalBlockVariables.add(declarator.id.name)
411
393
  } else if ("ClassDeclaration" == globalBlockStatement.type) {
412
394
  program.scope.crawl()
413
- assert(globalBlockStatement.id, "src/processScript/transform.ts:564:37")
395
+ assert(globalBlockStatement.id, "src/processScript/transform.ts:544:37")
414
396
  if (program.scope.hasGlobal(globalBlockStatement.id.name)) {
415
397
  globalBlock.body.splice(globalBlockIndex, 1)
416
398
  const [globalBlockPath] = program.unshiftContainer("body", globalBlock),
@@ -471,29 +453,31 @@ const { default: traverse } = babelTraverse,
471
453
  )
472
454
  ])
473
455
  )
474
- needSetPrototypeOf &&
456
+ needGetPrototypeOf &&
475
457
  mainFunction.body.body.unshift(
476
458
  t.variableDeclaration("let", [
477
459
  t.variableDeclarator(
478
- t.identifier(`_${uniqueID}_SET_PROTOTYPE_OF_`),
460
+ t.objectPattern([
461
+ t.objectProperty(t.identifier("get"), t.identifier(`_${uniqueID}_DUNDER_PROTO_GETTER_`))
462
+ ]),
479
463
  t.callExpression(
480
- t.memberExpression(
481
- t.memberExpression(t.identifier("Object"), t.identifier("call")),
482
- t.identifier("bind")
483
- ),
484
- [t.identifier(`_${uniqueID}_DUNDER_PROTO_SETTER_`)]
464
+ t.memberExpression(t.identifier("Object"), t.identifier("getOwnPropertyDescriptor")),
465
+ [
466
+ t.memberExpression(t.identifier("Object"), t.identifier("prototype")),
467
+ t.stringLiteral("__proto__")
468
+ ]
485
469
  )
486
- )
487
- ])
488
- )
489
- needGetPrototypeOf &&
490
- mainFunction.body.body.unshift(
491
- t.variableDeclaration("let", [
470
+ ),
492
471
  t.variableDeclarator(
493
472
  t.identifier(`_${uniqueID}_GET_PROTOTYPE_OF_`),
494
473
  t.callExpression(
495
474
  t.memberExpression(
496
- t.memberExpression(t.identifier("Object"), t.identifier("call")),
475
+ t.memberExpression(
476
+ t.identifier(
477
+ globalFunctionsUnder7Characters.find(name => !program.scope.hasOwnBinding(name))
478
+ ),
479
+ t.identifier("call")
480
+ ),
497
481
  t.identifier("bind")
498
482
  ),
499
483
  [t.identifier(`_${uniqueID}_DUNDER_PROTO_GETTER_`)]
@@ -501,41 +485,69 @@ const { default: traverse } = babelTraverse,
501
485
  )
502
486
  ])
503
487
  )
504
- ;(needGetPrototypeOf || needSetPrototypeOf) &&
488
+ consoleMethodsReferenced.size &&
489
+ mainFunction.body.body.unshift(
490
+ t.variableDeclaration(
491
+ "let",
492
+ [...consoleMethodsReferenced].map(name =>
493
+ t.variableDeclarator(
494
+ t.identifier(`_${uniqueID}_CONSOLE_METHOD_${name}_`),
495
+ t.arrowFunctionExpression(
496
+ [t.restElement(t.identifier("args"))],
497
+ t.unaryExpression(
498
+ "void",
499
+ t.callExpression(t.identifier(`$${uniqueID}$DEBUG$`), [t.identifier("args")])
500
+ )
501
+ )
502
+ )
503
+ )
504
+ )
505
+ )
506
+ neededDbMethodLets.size &&
507
+ mainFunction.body.body.unshift(
508
+ t.variableDeclaration(
509
+ "let",
510
+ [...neededDbMethodLets].map(name => {
511
+ const getArgs = () =>
512
+ "ObjectId" == name ? []
513
+ : "i" == name || "r" == name ? [t.identifier("a")]
514
+ : [t.identifier("a"), t.identifier("b")]
515
+ return t.variableDeclarator(
516
+ t.identifier(`_${uniqueID}_CONSOLE_METHOD_${name}_`),
517
+ t.arrowFunctionExpression(
518
+ getArgs(),
519
+ t.callExpression(t.identifier(`$${uniqueID}$DB$${name}$`), getArgs())
520
+ )
521
+ )
522
+ })
523
+ )
524
+ )
525
+ needDebugLet &&
505
526
  mainFunction.body.body.unshift(
506
527
  t.variableDeclaration("let", [
507
528
  t.variableDeclarator(
508
- t.objectPattern(
509
- needGetPrototypeOf ?
510
- needSetPrototypeOf ?
511
- [
512
- t.objectProperty(
513
- t.identifier("get"),
514
- t.identifier(`_${uniqueID}_DUNDER_PROTO_GETTER_`)
515
- ),
516
- t.objectProperty(
517
- t.identifier("set"),
518
- t.identifier(`_${uniqueID}_DUNDER_PROTO_SETTER_`)
519
- )
520
- ]
521
- : [
522
- t.objectProperty(
523
- t.identifier("get"),
524
- t.identifier(`_${uniqueID}_DUNDER_PROTO_GETTER_`)
525
- )
526
- ]
527
- : [t.objectProperty(t.identifier("set"), t.identifier(`_${uniqueID}_DUNDER_PROTO_SETTER_`))]
528
- ),
529
- t.callExpression(
530
- t.memberExpression(t.identifier("Object"), t.identifier("getOwnPropertyDescriptor")),
531
- [
532
- t.memberExpression(t.identifier("Object"), t.identifier("prototype")),
533
- t.stringLiteral("__proto__")
534
- ]
535
- )
529
+ t.identifier(`_${uniqueID}_DEBUG_`),
530
+ t.callExpression(t.identifier(`$${uniqueID}$DEBUG$`), [t.identifier("a")])
536
531
  )
537
532
  ])
538
533
  )
534
+ neededSubscriptLets.size &&
535
+ mainFunction.body.body.unshift(
536
+ t.variableDeclaration(
537
+ "let",
538
+ [...neededSubscriptLets].map(name =>
539
+ t.variableDeclarator(
540
+ t.identifier(`_${uniqueID}_SUBSCRIPT_${name}_`),
541
+ t.arrowFunctionExpression(
542
+ [t.restElement(t.identifier("args"))],
543
+ t.callExpression(t.identifier(`$${uniqueID}$SUBSCRIPT$${name}$`), [
544
+ t.spreadElement(t.identifier("args"))
545
+ ])
546
+ )
547
+ )
548
+ )
549
+ )
550
+ )
539
551
  traverse(file, {
540
552
  BlockStatement({ node: blockStatement }) {
541
553
  for (const [index, functionDeclaration] of blockStatement.body.entries())
package/push.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { Cache } from "@samual/lib/Cache"
2
2
  import { countHackmudCharacters } from "@samual/lib/countHackmudCharacters"
3
+ import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
3
4
  import { writeFilePersistent } from "@samual/lib/writeFilePersistent"
4
- import { readdir, readFile } from "fs/promises"
5
- import { resolve, extname, basename } from "path"
5
+ import { readFile } from "fs/promises"
6
+ import { basename, resolve, extname } from "path"
6
7
  import { supportedExtensions } from "./constants.js"
7
8
  import { processScript } from "./processScript/index.js"
8
9
  import "@babel/generator"
@@ -64,18 +65,20 @@ const push = async (
64
65
  scriptNamesAlreadyPushedByUser = new Cache(_user => new Set())
65
66
  let sourceDirectoryDirents
66
67
  if (wildUserScripts.size || pushEverything) {
67
- const hackmudDirectoryDirents = await readdir(resolve(hackmudDirectory), { withFileTypes: !0 }),
68
- allUsers = new Set([
69
- ...(sourceDirectoryDirents = await readdir(resolve(sourceDirectory), { withFileTypes: !0 }))
70
- .filter(dirent => dirent.isDirectory())
71
- .map(dirent => dirent.name),
72
- ...hackmudDirectoryDirents.filter(dirent => dirent.isDirectory()).map(dirent => dirent.name),
73
- ...hackmudDirectoryDirents
74
- .filter(dirent => dirent.isFile() && dirent.name.endsWith(".key"))
75
- .map(dirent => dirent.name.slice(0, -4)),
76
- ...scriptNamesByUser.keys(),
77
- ...wildScriptUsers
78
- ])
68
+ let hackmudDirectoryEntries
69
+ ;[hackmudDirectoryEntries, sourceDirectoryDirents] = await Promise.all([
70
+ readDirectoryWithStats(hackmudDirectory),
71
+ readDirectoryWithStats(sourceDirectory)
72
+ ])
73
+ const allUsers = new Set([
74
+ ...sourceDirectoryDirents.filter(({ stats }) => stats.isDirectory()).map(({ path }) => basename(path)),
75
+ ...hackmudDirectoryEntries.filter(({ stats }) => stats.isDirectory()).map(({ name }) => name),
76
+ ...hackmudDirectoryEntries
77
+ .filter(({ name, stats }) => stats.isFile() && name.endsWith(".key"))
78
+ .map(({ name }) => name.slice(0, -4)),
79
+ ...scriptNamesByUser.keys(),
80
+ ...wildScriptUsers
81
+ ])
79
82
  if (pushEverything) for (const user of allUsers) wildScriptUsers.add(user)
80
83
  else
81
84
  for (const user of allUsers) {
@@ -85,28 +88,27 @@ const push = async (
85
88
  }
86
89
  await Promise.all(
87
90
  [...wildScriptUsers].map(async user => {
88
- await readdir(resolve(sourceDirectory, user), { withFileTypes: !0 }).then(
89
- async dirents => {
91
+ await readDirectoryWithStats(resolve(sourceDirectory, user)).then(
92
+ async entries => {
90
93
  await Promise.all(
91
- dirents.map(async dirent => {
92
- if (dirent.name.endsWith(".d.ts")) return
93
- const extension = extname(dirent.name)
94
- if (dirent.isFile() && supportedExtensions.includes(extension)) {
95
- const scriptName = basename(dirent.name, extension),
96
- filePath = resolve(sourceDirectory, user, dirent.name),
94
+ entries.map(async ({ stats, name, path }) => {
95
+ if (name.endsWith(".d.ts")) return
96
+ const extension = extname(name)
97
+ if (stats.isFile() && supportedExtensions.includes(extension)) {
98
+ const scriptName = basename(name, extension),
97
99
  { script: minifiedCode } = await processScript(
98
- await readFile(filePath, { encoding: "utf-8" }),
100
+ await readFile(path, { encoding: "utf-8" }),
99
101
  {
100
102
  minify,
101
103
  scriptUser: user,
102
104
  scriptName,
103
- filePath,
105
+ filePath: path,
104
106
  mangleNames,
105
107
  forceQuineCheats
106
108
  }
107
109
  ),
108
110
  info = {
109
- file: `${user}/${dirent.name}`,
111
+ file: `${user}/${name}`,
110
112
  users: [user],
111
113
  minLength: countHackmudCharacters(minifiedCode),
112
114
  error: void 0
@@ -170,12 +172,12 @@ const push = async (
170
172
  )
171
173
  await (wildScriptUsers.size ?
172
174
  Promise.all(
173
- (sourceDirectoryDirents || (await readdir(resolve(sourceDirectory), { withFileTypes: !0 }))).map(
174
- async dirent => {
175
- if (dirent.name.endsWith(".d.ts")) return
176
- const extension = extname(dirent.name)
177
- if (!dirent.isFile() || !supportedExtensions.includes(extension)) return
178
- const scriptName = basename(dirent.name, extension),
175
+ (sourceDirectoryDirents || (await readDirectoryWithStats(sourceDirectory))).map(
176
+ async ({ path, stats, name }) => {
177
+ if (name.endsWith(".d.ts")) return
178
+ const extension = extname(name)
179
+ if (!stats.isFile() || !supportedExtensions.includes(extension)) return
180
+ const scriptName = basename(name, extension),
179
181
  usersToPushTo = [...wildScriptUsers, ...usersByGlobalScriptsToPush.get(scriptName)].filter(
180
182
  user => !scriptNamesAlreadyPushedByUser.get(user).has(scriptName)
181
183
  )
@@ -183,13 +185,17 @@ const push = async (
183
185
  const uniqueID = Math.floor(Math.random() * 2 ** 52)
184
186
  .toString(36)
185
187
  .padStart(11, "0"),
186
- filePath = resolve(sourceDirectory, dirent.name),
187
- { script: minifiedCode } = await processScript(
188
- await readFile(filePath, { encoding: "utf-8" }),
189
- { minify, scriptUser: !0, scriptName, uniqueID, filePath, mangleNames, forceQuineCheats }
190
- ),
188
+ { script: minifiedCode } = await processScript(await readFile(path, { encoding: "utf-8" }), {
189
+ minify,
190
+ scriptUser: !0,
191
+ scriptName,
192
+ uniqueID,
193
+ filePath: path,
194
+ mangleNames,
195
+ forceQuineCheats
196
+ }),
191
197
  info = {
192
- file: dirent.name,
198
+ file: name,
193
199
  users: usersToPushTo,
194
200
  minLength: countHackmudCharacters(minifiedCode),
195
201
  error: void 0
package/syncMacros.js CHANGED
@@ -1,12 +1,13 @@
1
- import { readdir, readFile, stat, writeFile } from "fs/promises"
1
+ import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
2
+ import { readFile, stat, writeFile } from "fs/promises"
2
3
  import { extname, basename, resolve } from "path"
3
4
  const syncMacros = async hackmudPath => {
4
- const files = await readdir(hackmudPath, { withFileTypes: !0 }),
5
+ const files = await readDirectoryWithStats(hackmudPath),
5
6
  macros = new Map(),
6
7
  users = []
7
8
  await Promise.all(
8
9
  files.map(async file => {
9
- if (file.isFile())
10
+ if (file.stats.isFile())
10
11
  switch (extname(file.name)) {
11
12
  case ".macros":
12
13
  {