socket-function 0.64.0 → 0.66.0

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.
@@ -81,7 +81,7 @@ const hotReloadModule = cache((module: NodeJS.Module) => {
81
81
  || module.moduleContents?.includes("\nmodule.hotreload = true;" + "\n")
82
82
  || module.moduleContents?.includes("\r\nmodule.hotreload = true;" + "\r\n")
83
83
  ) {
84
- console.log(`Reloading ${module.id}`);
84
+ console.log(`Serverside reloading ${module.id}`);
85
85
  isHotReloadingValue = true;
86
86
  try {
87
87
  module.loaded = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "socket-function",
3
- "version": "0.64.0",
3
+ "version": "0.66.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "dependencies": {
@@ -5,8 +5,9 @@ import { SocketFunction } from "../SocketFunction";
5
5
  import { getCurrentHTTPRequest, setHTTPResultHeaders } from "../src/callHTTPHandler";
6
6
  import { formatNumberSuffixed, isNode, isNodeTrue, sha256Hash, sha256HashPromise } from "../src/misc";
7
7
  import zlib from "zlib";
8
- import { cacheLimited } from "../src/caching";
8
+ import { cacheLimited, lazy } from "../src/caching";
9
9
  import { formatNumber } from "../src/formatting/format";
10
+ import { requireMain } from "./require";
10
11
 
11
12
  const COMPRESS_CACHE_SIZE = 1024 * 1024 * 128;
12
13
 
@@ -98,17 +99,21 @@ let nextModuleSeqNum = 1;
98
99
 
99
100
  const requireSeqNumProcessId = "requireSeqNumProcessId_" + Date.now() + "_" + Math.random();
100
101
 
101
- const htmlFile = isNodeTrue() && fs.readFileSync(__dirname + "/require.html").toString();
102
- const jsFile = isNodeTrue() && fs.readFileSync(__dirname + "/require.js").toString();
103
- const bufferShim = isNodeTrue() && fs.readFileSync(__dirname + "/buffer.js").toString();
104
102
  const BEFORE_ENTRY_TEMPLATE = "<!-- BEFORE_ENTRY_TEMPLATE -->";
105
103
  const ENTRY_TEMPLATE = "<!-- ENTRY_TEMPLATE -->";
106
104
 
107
- const resolvedHTMLFile = isNodeTrue() && (
108
- htmlFile
109
- .replace(`<script src="./buffer.js"></script>`, `<script>${bufferShim}</script>`)
110
- .replace(`<script src="./require.js"></script>`, `<script>${jsFile}</script>`)
111
- );
105
+ const resolvedHTMLFile = lazy(() => {
106
+ const bufferShim = fs.readFileSync(__dirname + "/buffer.js").toString();
107
+ return fs.readFileSync(__dirname + "/require.html").toString()
108
+ .replace(BEFORE_ENTRY_TEMPLATE,
109
+ `
110
+ <script>${bufferShim}</script>
111
+ <script>(${requireMain.toString()})()</script>
112
+
113
+ ${BEFORE_ENTRY_TEMPLATE}
114
+ `
115
+ );
116
+ });
112
117
 
113
118
  let beforeEntryText: (string | (() => Promise<string>))[] = [];
114
119
  function injectHTMLBeforeStartup(text: string | (() => Promise<string>)) {
@@ -116,7 +121,7 @@ function injectHTMLBeforeStartup(text: string | (() => Promise<string>)) {
116
121
  }
117
122
 
118
123
  type GetModulesResult = ReturnType<RequireControllerBase["getModules"]> extends Promise<infer T> ? T : never;
119
- type GetModulesArgs = Parameters<RequireControllerBase["getModules"]>;
124
+ export type GetModulesArgs = Parameters<RequireControllerBase["getModules"]>;
120
125
  let mapGetModules: {
121
126
  remap(result: GetModulesResult, args: GetModulesArgs): Promise<GetModulesResult>
122
127
  }[] = [];
@@ -131,7 +136,7 @@ class RequireControllerBase {
131
136
  requireCalls?: string[];
132
137
  }) {
133
138
  let { requireCalls } = config || {};
134
- let result = resolvedHTMLFile;
139
+ let result = resolvedHTMLFile();
135
140
  if (beforeEntryText.length > 0) {
136
141
  let resolved: string[] = [];
137
142
  for (let text of beforeEntryText) {
@@ -164,13 +169,6 @@ class RequireControllerBase {
164
169
  return setHTTPResultHeaders(Buffer.from(result), { "Content-Type": "text/html" });
165
170
  }
166
171
 
167
- public async bufferJS() {
168
- return setHTTPResultHeaders(Buffer.from(bufferShim), { "Content-Type": "text/javascript" });
169
- }
170
- public async requireJS() {
171
- return setHTTPResultHeaders(Buffer.from(jsFile), { "Content-Type": "text/javascript" });
172
- }
173
-
174
172
  public async getModules(
175
173
  pathRequests: string[],
176
174
  alreadyHave?: {
@@ -349,8 +347,14 @@ class RequireControllerBase {
349
347
  }]),
350
348
  };
351
349
  let key = sha256Hash(JSON.stringify(simplifiedResult));
352
- let buffer = await compressCached(key, () => Buffer.from(JSON.stringify(result)));
353
- setHTTPResultHeaders(buffer, { "Content-Type": "application/json", "Content-Encoding": "gzip" });
350
+ let uncompressedBuffer = Buffer.from(JSON.stringify(result));
351
+ let buffer = await compressCached(key, () => uncompressedBuffer);
352
+ setHTTPResultHeaders(buffer, {
353
+ "Content-Type": "application/json",
354
+ "Content-Encoding": "gzip",
355
+ "Content-Length": buffer.length.toString(),
356
+ "X-Uncompressed-Content-Length": uncompressedBuffer.length.toString(),
357
+ });
354
358
  return buffer as any;
355
359
  }
356
360
 
@@ -6,9 +6,6 @@
6
6
  <body>
7
7
  <div id="main"></div>
8
8
 
9
- <script src="./buffer.js"></script>
10
- <script src="./require.js"></script>
11
-
12
9
  <!-- BEFORE_ENTRY_TEMPLATE -->
13
10
  <!-- ENTRY_TEMPLATE -->
14
11
  </body>
@@ -1,11 +1,89 @@
1
- (function () {
2
- //# sourceURL=require.js
1
+ import { GetModulesArgs, SerializedModule } from "./RequireController";
3
2
 
3
+
4
+ declare global {
5
+ var onProgressHandler: undefined | ((progress: {
6
+ type: string;
7
+ addValue: number;
8
+ addMax: number;
9
+ }) => void);
10
+ var onErrorHandler: undefined | ((error: string) => void);
11
+
12
+
13
+ var BOOT_TIME: number;
14
+ var builtInModuleExports: {
15
+ [key: string]: unknown;
16
+ };
17
+ }
18
+
19
+ export function requireMain() {
20
+ async function requestText(endpoint: string, values: any) {
21
+ let url = new URL(endpoint);
22
+
23
+ let json = JSON.stringify(values);
24
+ let response: Response;
25
+ if (json.length < 6000) {
26
+ // NOTE: Try to use a GET, as GETs can be cached! However, if the data is too large,
27
+ // we have to use a post, or else the request url will be too large
28
+ for (let key in values) {
29
+ url.searchParams.set(key, JSON.stringify(values[key]));
30
+ }
31
+ response = await fetch(url.toString(), {
32
+ method: "GET",
33
+ credentials: "include",
34
+ });
35
+ } else {
36
+ response = await fetch(url.toString(), {
37
+ method: "POST",
38
+ body: json,
39
+ credentials: "include",
40
+ });
41
+ }
42
+
43
+ let compressionRatio = 1;
44
+ let uncompressedLength = response.headers.get("X-Uncompressed-Content-Length");
45
+ let compressedLength = response.headers.get("Content-Length");
46
+ if (uncompressedLength && compressedLength) {
47
+ compressionRatio = +uncompressedLength / +compressedLength;
48
+ }
49
+ let totalLength = +(uncompressedLength || compressedLength || 0);
50
+ if (totalLength) {
51
+ globalThis.onProgressHandler?.({
52
+ type: "Download",
53
+ addValue: 0,
54
+ addMax: Math.floor(totalLength / compressionRatio),
55
+ });
56
+ }
57
+
58
+ // If it's an error, set requestError
59
+ if (!response.ok) {
60
+ globalThis.onErrorHandler?.(response.statusText);
61
+ }
62
+
63
+ // Stream it, so we can get progrss
64
+ let reader = response.body!.getReader();
65
+ let result = "";
66
+ while (true) {
67
+ let { done, value } = await reader.read();
68
+ if (done) break;
69
+ result += new TextDecoder().decode(value);
70
+ let cur = (value?.length || 0) / compressionRatio;
71
+ globalThis.onProgressHandler?.({
72
+ type: "Download",
73
+ addValue: cur,
74
+ addMax: 0,
75
+ });
76
+ }
77
+
78
+ return result;
79
+ }
80
+
81
+ const g = globalThis as any;
4
82
  let startTime = Date.now();
5
83
  globalThis.BOOT_TIME = startTime;
6
84
 
7
- Symbol.dispose = Symbol.dispose || Symbol("dispose");
8
- Symbol.asyncDispose = Symbol.asyncDispose || Symbol("asyncDispose");
85
+ (Symbol as any).dispose = Symbol.dispose || Symbol("dispose");
86
+ (Symbol as any).asyncDispose = Symbol.asyncDispose || Symbol("asyncDispose");
9
87
 
10
88
  // Globals
11
89
  Object.assign(window, {
@@ -17,11 +95,11 @@
17
95
  },
18
96
  versions: {},
19
97
  },
20
- setImmediate(callback) {
98
+ setImmediate(callback: () => void) {
21
99
  setTimeout(callback, 0);
22
100
  },
23
101
  // Ignore flags for now, even though they should work fine if we just hardcoded compileFlags.ts here.
24
- setFlag() {},
102
+ setFlag() { },
25
103
  global: window,
26
104
  });
27
105
 
@@ -32,7 +110,7 @@
32
110
  },
33
111
  util: {
34
112
  // https://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor
35
- inherits(constructor, superConstructor) {
113
+ inherits(constructor: any, superConstructor: any) {
36
114
  Object.setPrototypeOf(constructor.prototype, superConstructor.prototype);
37
115
  },
38
116
  TextDecoder: TextDecoder,
@@ -41,8 +119,8 @@
41
119
  buffer: { Buffer },
42
120
  stream: {
43
121
  // HACK: Needed to get SAX JS to work correctly.
44
- Stream: function () {},
45
- Transform: function () {},
122
+ Stream: function () { },
123
+ Transform: function () { },
46
124
  },
47
125
  timers: {
48
126
  // TODO: Add all members of timers
@@ -51,7 +129,8 @@
51
129
  child_process: {},
52
130
  events: {},
53
131
  };
54
- global.builtInModuleExports = builtInModuleExports;
132
+ globalThis.builtInModuleExports = globalThis.builtInModuleExports || {};
133
+ Object.assign(globalThis.builtInModuleExports, builtInModuleExports);
55
134
 
56
135
  let lastTime = 0;
57
136
  function nextTime() {
@@ -88,23 +167,42 @@
88
167
  }} */
89
168
  let serializedModules = Object.create(null);
90
169
 
91
- let moduleCache = Object.create(null);
92
- let alreadyHave = undefined;
170
+ type ModuleType = {
171
+ id: string;
172
+ filename: string;
173
+ exports: unknown;
174
+ children: ModuleType[];
175
+ flags: { [key: string]: boolean };
176
+ load: () => void;
177
+ loaded: boolean;
178
+ isPreloading: boolean;
179
+ evalStartTime: number;
180
+ evalEndTime: number;
181
+ source: string;
182
+ allowclient: boolean;
183
+ size: number;
184
+ };
185
+
186
+ let moduleCache: { [id: string]: ModuleType } = Object.create(null);
187
+ let alreadyHave: {
188
+ requireSeqNumProcessId: string;
189
+ seqNums: { [seqNum: string]: true | 1 | 0 | undefined };
190
+ } | undefined;
93
191
 
94
192
  let rootResolveCache = Object.create(null);
95
193
 
96
194
  rootRequire.cache = moduleCache;
97
195
  // Expose require for debugging, not so it can be called
98
- window.require = rootRequire;
99
- window.import = rootRequire;
196
+ g.require = rootRequire;
197
+ g.import = rootRequire;
100
198
 
101
- window.r = function r(text) {
199
+ g.r = function r(text: string) {
102
200
  text = text.toLowerCase();
103
201
  return Object.values(moduleCache).filter((x) => x.filename.toLowerCase().includes(text))[0].exports;
104
202
  };
105
203
 
106
- let requireBatch;
107
- function rootRequire(request, batch) {
204
+ let requireBatch: { [request: string]: (() => void)[] } | undefined;
205
+ function rootRequire(request: string, batch?: boolean): unknown {
108
206
  if (!batch) {
109
207
  if (request in rootResolveCache) {
110
208
  let resolvedRequest = rootResolveCache[request];
@@ -119,16 +217,16 @@
119
217
  }
120
218
 
121
219
  if (request in builtInModuleExports) {
122
- return builtInModuleExports[request];
220
+ return builtInModuleExports[request as keyof typeof builtInModuleExports];
123
221
  }
124
222
  if (batch) {
125
223
  if (!requireBatch) {
126
- requireBatch = requireBatch || {};
127
224
  setTimeout(() => {
225
+ requireBatch = requireBatch || {};
128
226
  let requests = Object.keys(requireBatch);
129
227
  let callbacks = Object.values(requireBatch).reduce((a, b) => a.concat(b), []);
130
228
  requireBatch = undefined;
131
- void rootRequireMultiple(requests, true).then(
229
+ void rootRequireMultiple(requests).then(
132
230
  () => {
133
231
  for (let callback of callbacks) {
134
232
  callback();
@@ -140,7 +238,8 @@
140
238
  );
141
239
  }, 0);
142
240
  }
143
- return new Promise((resolve) => {
241
+ return new Promise<void>((resolve) => {
242
+ if (!requireBatch) throw new Error("Impossible");
144
243
  requireBatch[request] = requireBatch[request] || [];
145
244
  requireBatch[request].push(resolve);
146
245
  });
@@ -148,7 +247,7 @@
148
247
  return rootRequireMultiple([request]).then((x) => x[0].exports);
149
248
  }
150
249
  }
151
- async function rootRequireMultiple(requests) {
250
+ async function rootRequireMultiple(requests: string[]) {
152
251
  console.log(`%cimport(${requests.join(", ")}) at ${Date.now() - startTime}ms`, "color: orange");
153
252
 
154
253
  let time = Date.now();
@@ -157,7 +256,7 @@
157
256
  if (alreadyHave) {
158
257
  let seqNums = Object.keys(alreadyHave.seqNums).map((x) => +x);
159
258
  seqNums.sort((a, b) => a - b);
160
- let seqNumRanges = [];
259
+ let seqNumRanges: { s: number; e?: number }[] = [];
161
260
  alreadyHaveRanges = { requireSeqNumProcessId: alreadyHave.requireSeqNumProcessId, seqNumRanges };
162
261
  for (let seqNum of seqNums) {
163
262
  let prev = seqNumRanges[seqNumRanges.length - 1];
@@ -174,17 +273,40 @@
174
273
  }
175
274
  }
176
275
 
177
- let args = [requests, alreadyHaveRanges];
276
+ let domainOrigin = "";
277
+ let originalRequests = requests;
278
+ if (requests.some(x => x.startsWith("https://"))) {
279
+ requests = requests.map((request) => {
280
+ if (!request.startsWith("https://")) {
281
+ throw new Error(`Mixed domains with non-domain requests is not supported presently. Requests: ${requests.join(" | ")}`);
282
+ }
283
+ let url = new URL(request);
284
+ if (domainOrigin && domainOrigin !== url.origin) {
285
+ // TODO: If this happens, we can probably just split the call up into multiple calls?
286
+ throw new Error(`Mixed domains in require call is not supported presently. Requests: ${requests.join(" | ")}`);
287
+ }
288
+ domainOrigin = url.origin + "/";
289
+ // By stripping by length, we can turn https://example.com/./test => "./test"
290
+ // (where as if we used pathname, it would turn into "/test"
291
+ return request.slice(domainOrigin.length);
292
+ });
293
+ }
294
+
295
+ let args: GetModulesArgs = [requests, alreadyHaveRanges];
178
296
  // We have to add hardcoded support for droppermissions, because... this call
179
297
  // doesn't have the conventional persisted code sending code, because... it's
180
298
  // all on its own.
181
- if (new URL(location).searchParams.get("droppermissions") !== null) {
299
+ let searchParams = new URLSearchParams(location.search);
300
+ if (searchParams.get("droppermissions") !== null) {
182
301
  args.push(true);
183
302
  }
184
- let requestUrl =
185
- location.origin +
186
- location.pathname +
187
- `?classGuid=RequireController-e2f811f3-14b8-4759-b0d6-73f14516cf1d&functionName=getModules`;
303
+
304
+ let requestUrlBase = location.origin + location.pathname;
305
+ if (domainOrigin) {
306
+ requestUrlBase = domainOrigin;
307
+ }
308
+ let requestUrl = requestUrlBase + `?classGuid=RequireController-e2f811f3-14b8-4759-b0d6-73f14516cf1d&functionName=getModules`;
309
+
188
310
  let remapImportRequestsClientside = globalThis.remapImportRequestsClientside;
189
311
  if (remapImportRequestsClientside) {
190
312
  for (let fnc of remapImportRequestsClientside) {
@@ -192,7 +314,12 @@
192
314
  }
193
315
  }
194
316
  let rawText = await requestText(requestUrl, { args });
195
- let resultObj;
317
+ let resultObj: {
318
+ modules: { [id: string]: SerializedModule };
319
+ requestsResolvedPaths: string[];
320
+ requireSeqNumProcessId: string;
321
+ error?: string;
322
+ };
196
323
  try {
197
324
  resultObj = JSON.parse(rawText);
198
325
  } catch (e) {
@@ -207,13 +334,43 @@
207
334
  throw errorObj;
208
335
  }
209
336
 
337
+
338
+ if (Object.keys(modules).length === 1 && "" in modules) {
339
+ eval(modules[""].source || "");
340
+ throw new Error(`Failed to find modules for ${originalRequests.join(", ")} (mapped to ${requests.join(", ")})`);
341
+ }
342
+
343
+
344
+ if (domainOrigin) {
345
+ function fixDomain(request: string) {
346
+ if (!request) return request;
347
+ return domainOrigin + request;
348
+ }
349
+ requests = requests.map(fixDomain);
350
+ for (let [id, module] of Object.entries(modules)) {
351
+ delete modules[id];
352
+ modules[fixDomain(id)] = module;
353
+ module.filename = fixDomain(module.filename);
354
+ module.requests = Object.fromEntries(Object.entries(module.requests).map(([k, v]) => [k, fixDomain(v)]));
355
+ module.originalId = fixDomain(module.originalId);
356
+ }
357
+ requestsResolvedPaths = requestsResolvedPaths.map(fixDomain);
358
+ }
359
+
360
+
210
361
  for (let i = 0; i < requests.length; i++) {
211
362
  rootResolveCache[requests[i]] = requestsResolvedPaths[i];
212
363
  }
213
364
 
365
+ globalThis.onProgressHandler?.({
366
+ type: "Compile",
367
+ addValue: 0,
368
+ addMax: Object.keys(modules).length,
369
+ });
370
+
214
371
  // Store the function, so we only call it if it exists BEFORE we import
215
372
  // (which means we already have something loading, so this is likely hot reloading...)
216
- let observerOnHotReload = global.observerOnHotReload;
373
+ let observerOnHotReload = g.observerOnHotReload;
217
374
  setTimeout(() => {
218
375
  if (observerOnHotReload) {
219
376
  observerOnHotReload();
@@ -225,17 +382,18 @@
225
382
  let requireModuleCount = Object.values(modules).filter((x) => !x.source).length;
226
383
  let dependenciesOnlyText = requireModuleCount ? ` (+${requireModuleCount} dependencies only)` : "";
227
384
  console.log(
228
- `%cimport(${requests.join(", ")}) finished download ${time}ms, ${Math.ceil(
385
+ `%cimport(${requests.join(", ")}) finished download ${time.toFixed(0)}ms, ${Math.ceil(
229
386
  rawText.length / 1024
230
- )}KB, ${moduleCount} modules${dependenciesOnlyText} at ${Date.now() - startTime}ms`,
231
- "color: green"
387
+ )}KB, ${moduleCount} modules${dependenciesOnlyText} at ${(Date.now() - startTime).toFixed(0)}ms`,
388
+ "color: lightgreen"
232
389
  );
233
390
 
234
- time = Date.now();
391
+
235
392
 
236
393
  if (alreadyHave?.requireSeqNumProcessId !== requireSeqNumProcessId) {
237
- alreadyHave = { requireSeqNumProcessId, seqNums: {} };
394
+ alreadyHave = undefined;
238
395
  }
396
+ alreadyHave = alreadyHave || { requireSeqNumProcessId, seqNums: {} };
239
397
 
240
398
  for (let id in modules) {
241
399
  let module = modules[id];
@@ -243,28 +401,51 @@
243
401
  serializedModules[id] = module;
244
402
  }
245
403
 
404
+ time = Date.now();
405
+ let lastWaitTime = time;
406
+ for (let key of Object.keys(modules)) {
407
+ getModule(key, "preload");
408
+ // Wait, so we can render progress (and in generals, so the UI remains somewhat responsive)
409
+ if (Date.now() - lastWaitTime > 10) {
410
+ await new Promise(resolve => setTimeout(resolve, 0));
411
+ lastWaitTime = Date.now();
412
+ }
413
+ }
414
+
415
+ time = Date.now() - time;
416
+ console.log(
417
+ `%cimport(${requests.join(", ")}) finished compile ${time.toFixed(0)}ms (${moduleCount} modules) at ${(Date.now() - startTime).toFixed(0)}ms`,
418
+ "color: hotpink"
419
+ );
420
+
421
+
422
+ globalThis.onProgressHandler?.({
423
+ type: "Evaluate",
424
+ addValue: 0,
425
+ addMax: Object.keys(modules).length,
426
+ });
427
+
428
+ time = Date.now();
246
429
  try {
247
430
  return requestsResolvedPaths.map((x) => getModule(x));
248
431
  } finally {
249
432
  time = Date.now() - time;
250
433
  console.log(
251
- `%cimport(${requests.join(", ")}) finished evaluate ${time}ms (${moduleCount} modules) at ${
252
- Date.now() - startTime
253
- }ms`,
434
+ `%cimport(${requests.join(", ")}) finished evaluate ${time.toFixed(0)}ms (${moduleCount} modules) at ${(Date.now() - startTime).toFixed(0)}ms`,
254
435
  "color: lightblue"
255
436
  );
256
437
  }
257
438
  }
258
439
 
259
- function createRequire(module, serializedModule, asyncIsFineOuter) {
440
+ function createRequire(module: ModuleType, serializedModule: SerializedModule, asyncIsFineOuter?: boolean) {
260
441
  require.cache = moduleCache;
261
- require.resolve = function (request) {
442
+ require.resolve = function (request: string) {
262
443
  // TODO: Maybe do a request, making this async, if it isn't found?
263
444
  return serializedModule.requests[request];
264
445
  };
265
446
  let moduleFolder = module.filename.replace(/\\/g, "/").split("/").slice(0, -1).join("/") + "/";
266
447
  return require;
267
- function require(request, asyncIsFine) {
448
+ function require(request: string, asyncIsFine?: boolean) {
268
449
  if (asyncIsFineOuter) {
269
450
  asyncIsFine = true;
270
451
  }
@@ -275,7 +456,7 @@
275
456
  asyncIsFine = true;
276
457
  }
277
458
  if (request in builtInModuleExports) {
278
- return builtInModuleExports[request];
459
+ return builtInModuleExports[request as keyof typeof builtInModuleExports];
279
460
  }
280
461
 
281
462
  let resolvedPath;
@@ -317,12 +498,11 @@
317
498
  "color: red",
318
499
  "color: unset"
319
500
  );
320
- debugger;
321
501
  }
322
502
  return rootRequire(resolvedPath);
323
503
  }
324
504
 
325
- let exportsOverride = undefined;
505
+ let exportsOverride: unknown | undefined;
326
506
  if (resolvedPath === "NOTALLOWEDCLIENTSIDE" || !serializedModules[resolvedPath].allowclient) {
327
507
  let childId = resolvedPath === "NOTALLOWEDCLIENTSIDE" ? request : resolvedPath;
328
508
  if (serializedModules[resolvedPath]?.serveronly) {
@@ -336,7 +516,7 @@
336
516
  if (property === "default") return exportsOverride;
337
517
 
338
518
  throw new Error(
339
- `Module ${childId} is serverside only. Tried to access ${property} from ${module.id}`
519
+ `Module ${childId} is serverside only. Tried to access ${String(property)} from ${module.id}`
340
520
  );
341
521
  },
342
522
  }
@@ -354,8 +534,7 @@
354
534
  console.warn(
355
535
  `Accessed non-whitelisted module %c${childId}%c, specifically property %c${String(
356
536
  property
357
- )}%c.\n\tAdd %cmodule.allowclient = true%c to the file to allow access.\n\t(IF it is a 3rd party library, use the global "setFlag" helper (in the file you imported the module) to set properties on other modules (it can even recursively set properties)).\n\n\tFrom ${
358
- module.id
537
+ )}%c.\n\tAdd %cmodule.allowclient = true%c to the file to allow access.\n\t(IF it is a 3rd party library, use the global "setFlag" helper (in the file you imported the module) to set properties on other modules (it can even recursively set properties)).\n\n\tFrom ${module.id
359
538
  }`,
360
539
  "color: red",
361
540
  "color: unset",
@@ -395,10 +574,10 @@
395
574
  * and has code equal to contents.
396
575
  * - filename is just for debugging / stack traces
397
576
  */
398
- function wrapSafe(filename, contents) {
577
+ function wrapSafe(filename: string, contents: string) {
399
578
  // TODO: Have the serverside inform us of the correct loader, or... have it actually emit a .json loader.
400
579
  if (filename.endsWith(".json")) {
401
- return (exports, require, module) => (module.exports = contents && JSON.parse(contents));
580
+ return (exports: unknown, require: unknown, module: ModuleType) => (module.exports = contents && JSON.parse(contents));
402
581
  }
403
582
 
404
583
  // NOTE: debugName only matters during module evaluation. After that the sourcemap should work.
@@ -419,14 +598,19 @@
419
598
 
420
599
  const unloadedModule = Symbol("unloadedModule");
421
600
 
422
- let currentModuleEvaluationStack = [];
601
+ let currentModuleEvaluationStack: string[] = [];
423
602
  // See https://nodejs.org/api/modules.html
424
- function getModule(resolvedId) {
603
+ function getModule(resolvedId: string, preload?: "preload") {
425
604
  if (resolvedId === "") {
426
605
  return {};
427
606
  }
428
607
  if (resolvedId in moduleCache) {
429
- return moduleCache[resolvedId];
608
+ let module = moduleCache[resolvedId];
609
+ if (!preload && !module.loaded) {
610
+ module.loaded = true;
611
+ module.load();
612
+ }
613
+ return module;
430
614
  }
431
615
 
432
616
  let serializedModule = serializedModules[resolvedId];
@@ -439,15 +623,27 @@
439
623
  module.exports.default = module.exports;
440
624
  module.children = [];
441
625
  for (let key in serializedModule.flags || {}) {
626
+ if (key === "loaded") continue;
442
627
  module[key] = true;
443
628
  }
444
629
 
445
630
  module.load = load;
446
631
 
447
- module.loaded = true;
448
- module.load();
632
+ let originalSource = serializedModule.source;
633
+ let moduleFnc = wrapSafe(module.id, originalSource);
634
+
635
+ globalThis.onProgressHandler?.({
636
+ type: "Compile",
637
+ addValue: 1,
638
+ addMax: 0,
639
+ });
449
640
 
450
- function load(filename) {
641
+ if (!preload) {
642
+ module.loaded = true;
643
+ module.load();
644
+ }
645
+
646
+ function load() {
451
647
  let serializedModule = serializedModules[resolvedId];
452
648
  if (!module.loaded) {
453
649
  if (alreadyHave) {
@@ -486,7 +682,10 @@
486
682
  module.size = source.length;
487
683
  module.source = source;
488
684
 
489
- let moduleFnc = wrapSafe(module.id, source);
685
+ if (source !== originalSource) {
686
+ originalSource = source;
687
+ moduleFnc = wrapSafe(module.id, originalSource);
688
+ }
490
689
 
491
690
  let dirname = module.filename.replace(/\\/g, "/").split("/").slice(0, -1).join("/");
492
691
 
@@ -500,11 +699,11 @@
500
699
  {
501
700
  // NOTE: Adding __importStar to the module causes typescript to use our implementation,
502
701
  // which checks for unloadedModule and returns undefined in that case.
503
- __importStar(mod) {
702
+ __importStar(mod: any) {
504
703
  if (mod[unloadedModule]) return undefined;
505
704
  return mod;
506
705
  },
507
- __importDefault(mod) {
706
+ __importDefault(mod: any) {
508
707
  return mod.default ? mod : { default: mod };
509
708
  },
510
709
  },
@@ -523,34 +722,15 @@
523
722
  } finally {
524
723
  module.isPreloading = false;
525
724
  currentModuleEvaluationStack.pop();
725
+
726
+ globalThis.onProgressHandler?.({
727
+ type: "Evaluate",
728
+ addValue: 1,
729
+ addMax: 0,
730
+ });
526
731
  }
527
732
  }
528
733
 
529
734
  return module;
530
735
  }
531
-
532
- async function requestText(endpoint, values) {
533
- let url = new URL(endpoint);
534
-
535
- let json = JSON.stringify(values);
536
- if (json.length < 6000) {
537
- // NOTE: Try to use a GET, as GETs can be cached! However, if the data is too large,
538
- // we have to use a post, or else the request url will be too large
539
- for (let key in values) {
540
- url.searchParams.set(key, JSON.stringify(values[key]));
541
- }
542
- let response = await fetch(url.toString(), {
543
- method: "GET",
544
- credentials: "include",
545
- });
546
- return await response.text();
547
- } else {
548
- let response = await fetch(url.toString(), {
549
- method: "POST",
550
- body: json,
551
- credentials: "include",
552
- });
553
- return await response.text();
554
- }
555
- }
556
- })();
736
+ }
@@ -189,6 +189,7 @@ export async function httpCallHandler(request: http.IncomingMessage, response: h
189
189
  return;
190
190
  }
191
191
  }
192
+ let uncompressedLength = resultBuffer.length;
192
193
  if (SocketFunction.HTTP_COMPRESS && request.headers["accept-encoding"]?.includes("gzip") && !headers?.["Content-Encoding"]) {
193
194
  // NOTE: This is a BIT slow. To speed it up, functions can use an internal cache, according to their function,
194
195
  // and return a Buffer (which they can as any cast to make the returned type allowed, as returned Buffers will
@@ -205,6 +206,10 @@ export async function httpCallHandler(request: http.IncomingMessage, response: h
205
206
  });
206
207
  });
207
208
  }
209
+ response.setHeader("Content-Length", resultBuffer.length.toString());
210
+ if (!response.getHeader("X-Uncompressed-Content-Length")) {
211
+ response.setHeader("X-Uncompressed-Content-Length", uncompressedLength.toString());
212
+ }
208
213
  response.write(resultBuffer);
209
214
  if (SocketFunction.logMessages) {
210
215
  console.log(`HTTP response ${formatNumberSuffixed(resultBuffer.length)}B (${request.method}) ${url}`);