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(`
|
|
84
|
+
console.log(`Serverside reloading ${module.id}`);
|
|
85
85
|
isHotReloadingValue = true;
|
|
86
86
|
try {
|
|
87
87
|
module.loaded = false;
|
package/package.json
CHANGED
|
@@ -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 =
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
.replace(
|
|
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
|
|
353
|
-
|
|
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
|
|
package/require/require.html
CHANGED
|
@@ -1,11 +1,89 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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
|
-
|
|
92
|
-
|
|
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
|
-
|
|
99
|
-
|
|
196
|
+
g.require = rootRequire;
|
|
197
|
+
g.import = rootRequire;
|
|
100
198
|
|
|
101
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
299
|
+
let searchParams = new URLSearchParams(location.search);
|
|
300
|
+
if (searchParams.get("droppermissions") !== null) {
|
|
182
301
|
args.push(true);
|
|
183
302
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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 =
|
|
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:
|
|
387
|
+
)}KB, ${moduleCount} modules${dependenciesOnlyText} at ${(Date.now() - startTime).toFixed(0)}ms`,
|
|
388
|
+
"color: lightgreen"
|
|
232
389
|
);
|
|
233
390
|
|
|
234
|
-
|
|
391
|
+
|
|
235
392
|
|
|
236
393
|
if (alreadyHave?.requireSeqNumProcessId !== requireSeqNumProcessId) {
|
|
237
|
-
alreadyHave =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
448
|
-
module.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|
package/src/callHTTPHandler.ts
CHANGED
|
@@ -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}`);
|