@volter/tabnode 0.5.36 → 0.5.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__sw__.js +12 -5
- package/dist/assets/{runtime-worker-DEgP1CYS.js → runtime-worker-C4lPa6-H.js} +33 -12
- package/dist/index.mjs +34 -13
- package/dist/runtime.d.ts +4 -1
- package/package.json +1 -1
- package/src/node-lib/binding/buffer.ts +22 -1
- package/src/node-resolution.ts +7 -4
- package/src/runtime.ts +18 -7
- package/src/shims/crypto.ts +9 -0
package/dist/__sw__.js
CHANGED
|
@@ -578,7 +578,7 @@ async function virtualContext(event) {
|
|
|
578
578
|
// virtual request asks for its port, so a restart does not send the
|
|
579
579
|
// preview's own requests to the network.
|
|
580
580
|
if (hosts.size === 0 && ((client && client.frameType === 'nested') || (event.request.mode === 'navigate' && (event.request.destination === 'iframe' || event.request.destination === 'frame')))) {
|
|
581
|
-
await askForInit();
|
|
581
|
+
await askForInit(event.clientId);
|
|
582
582
|
}
|
|
583
583
|
const contextUrl = event.request.referrer || (client ? client.url : '');
|
|
584
584
|
if (contextUrl) {
|
|
@@ -607,9 +607,16 @@ function ownPath(pathname) {
|
|
|
607
607
|
return pathname.length > 1 && pathname.endsWith('/') ? pathname.slice(0, -1) : pathname;
|
|
608
608
|
}
|
|
609
609
|
|
|
610
|
-
/**
|
|
611
|
-
|
|
612
|
-
|
|
610
|
+
/**
|
|
611
|
+
* Asks every window for the page's registrations and waits for them, as a
|
|
612
|
+
* request waits for its port. Only another window can answer: a page's own
|
|
613
|
+
* document and scripts come before its `init`, and a frame being opened is no
|
|
614
|
+
* window yet, so with no other window each waited out the whole ask (a page
|
|
615
|
+
* opened on an origin whose worker had restarted took 5 s per request).
|
|
616
|
+
*/
|
|
617
|
+
async function askForInit(requesterId) {
|
|
618
|
+
const allClients = (await self.clients.matchAll({ type: 'window' })).filter((client) => client.id !== requesterId);
|
|
619
|
+
if (allClients.length === 0) return;
|
|
613
620
|
for (const client of allClients) client.postMessage({ type: 'sw-needs-init' });
|
|
614
621
|
await new Promise((resolve) => {
|
|
615
622
|
const check = setInterval(() => { if (hosts.size > 0) { clearInterval(check); resolve(); } }, 50);
|
|
@@ -739,7 +746,7 @@ async function withDocumentPrelude(event, response) {
|
|
|
739
746
|
*/
|
|
740
747
|
async function handleVirtualRequest(request, port, path, rooted = false) {
|
|
741
748
|
try {
|
|
742
|
-
if (hosts.size === 0) await askForInit();
|
|
749
|
+
if (hosts.size === 0) await askForInit(requestEvents.get(request)?.clientId);
|
|
743
750
|
const host = await hostForRequest(request, port);
|
|
744
751
|
const registration = host ? host.flowControlledPorts.get(port) : undefined;
|
|
745
752
|
// Build headers object
|
|
@@ -6235,7 +6235,11 @@ function hexSlice(start, end) {
|
|
|
6235
6235
|
}
|
|
6236
6236
|
return out;
|
|
6237
6237
|
}
|
|
6238
|
+
const nativeBase64 = typeof Uint8Array.prototype.toBase64 === "function";
|
|
6238
6239
|
function base64Text(bytes2, url2) {
|
|
6240
|
+
if (nativeBase64) {
|
|
6241
|
+
return bytes2.toBase64({ alphabet: url2 ? "base64url" : "base64", omitPadding: url2 });
|
|
6242
|
+
}
|
|
6239
6243
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
6240
6244
|
let out = "";
|
|
6241
6245
|
for (let index2 = 0; index2 < bytes2.length; index2 += 3) {
|
|
@@ -6259,7 +6263,20 @@ function base64urlSlice(start, end) {
|
|
|
6259
6263
|
return base64Text(this.subarray(from, to2), true);
|
|
6260
6264
|
}
|
|
6261
6265
|
function byteLengthUtf8(string) {
|
|
6262
|
-
|
|
6266
|
+
let length = 0;
|
|
6267
|
+
for (let index2 = 0; index2 < string.length; index2 += 1) {
|
|
6268
|
+
const code2 = string.charCodeAt(index2);
|
|
6269
|
+
if (code2 < 128) length += 1;
|
|
6270
|
+
else if (code2 < 2048) length += 2;
|
|
6271
|
+
else if (code2 >= 55296 && code2 < 56320 && index2 + 1 < string.length) {
|
|
6272
|
+
const next2 = string.charCodeAt(index2 + 1);
|
|
6273
|
+
if (next2 >= 56320 && next2 < 57344) {
|
|
6274
|
+
length += 4;
|
|
6275
|
+
index2 += 1;
|
|
6276
|
+
} else length += 3;
|
|
6277
|
+
} else length += 3;
|
|
6278
|
+
}
|
|
6279
|
+
return length;
|
|
6263
6280
|
}
|
|
6264
6281
|
function compare(a, b) {
|
|
6265
6282
|
return compareRanges(asBytes(a), 0, a.length, asBytes(b), 0, b.length);
|
|
@@ -23424,12 +23441,18 @@ function createCryptoModule(require2) {
|
|
|
23424
23441
|
function digestEngine(algorithm) {
|
|
23425
23442
|
return algorithm === "md5" ? md5.create() : SHA(algorithm);
|
|
23426
23443
|
}
|
|
23444
|
+
const utf8Encoder = new TextEncoder();
|
|
23427
23445
|
function cryptoBytes(value, encoding, allowArrayBuffer = false) {
|
|
23428
23446
|
if (typeof value === "string") {
|
|
23429
23447
|
if ((encoding == null ? void 0 : encoding.toLowerCase()) === "base64url") return buffer.Buffer.from(value, "base64");
|
|
23430
23448
|
if (encoding !== void 0 && !buffer.Buffer.isEncoding(encoding)) {
|
|
23431
23449
|
throw new TypeError(`Unknown encoding: ${encoding}`);
|
|
23432
23450
|
}
|
|
23451
|
+
const lower = encoding == null ? void 0 : encoding.toLowerCase();
|
|
23452
|
+
if (lower === void 0 || lower === "utf8" || lower === "utf-8") {
|
|
23453
|
+
const bytes2 = utf8Encoder.encode(value);
|
|
23454
|
+
return buffer.Buffer.from(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength);
|
|
23455
|
+
}
|
|
23433
23456
|
return buffer.Buffer.from(value, encoding);
|
|
23434
23457
|
}
|
|
23435
23458
|
if (ArrayBuffer.isView(value)) {
|
|
@@ -73561,10 +73584,7 @@ function createNodeResolver(options) {
|
|
|
73561
73584
|
const packageName = packageNameOf2(specifier);
|
|
73562
73585
|
const packageRoot = `${nodeModules}/${packageName}`;
|
|
73563
73586
|
const pkg = isDirectory(packageRoot) ? manifest(packageRoot) : null;
|
|
73564
|
-
if (pkg && pkg.exports !== void 0 && pkg.exports !== null)
|
|
73565
|
-
const found = loadPackageExports(packageRoot, pkg, specifier, packageName);
|
|
73566
|
-
if (found) return found;
|
|
73567
|
-
}
|
|
73587
|
+
if (pkg && pkg.exports !== void 0 && pkg.exports !== null) return loadPackageExports(packageRoot, pkg, specifier, packageName);
|
|
73568
73588
|
const path2 = `${nodeModules}/${specifier}`;
|
|
73569
73589
|
return loadAsFile(path2) ?? loadAsDirectory(path2);
|
|
73570
73590
|
};
|
|
@@ -78595,27 +78615,27 @@ function __substrateFollowAwaits(code2) {
|
|
|
78595
78615
|
};
|
|
78596
78616
|
const isFunction = (node) => node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
|
|
78597
78617
|
const visit = (node, framed, parent) => {
|
|
78618
|
+
const leading = [];
|
|
78598
78619
|
if (isFunction(node)) {
|
|
78599
78620
|
framed = node.async && node.body.type === "BlockStatement";
|
|
78600
78621
|
if (framed) {
|
|
78601
78622
|
const directives = node.body.body.filter((statement) => statement.directive !== void 0);
|
|
78602
|
-
|
|
78603
|
-
insert(at3, FOLLOW_TAKE);
|
|
78623
|
+
leading.push([directives.length ? directives[directives.length - 1].end : node.body.start + 1, FOLLOW_TAKE]);
|
|
78604
78624
|
}
|
|
78605
78625
|
} else if (node.type === "AwaitExpression") {
|
|
78606
78626
|
insert(node.start, framed ? FOLLOW_RESUME_FRAMED : FOLLOW_RESUME_TAKEN);
|
|
78607
78627
|
insert(node.end, `${FOLLOW_MARK})`);
|
|
78608
78628
|
} else if (framed && node.type === "CatchClause") {
|
|
78609
|
-
|
|
78629
|
+
leading.push([node.body.start + 1, FOLLOW_RESTORE]);
|
|
78610
78630
|
} else if (framed && node.type === "TryStatement" && node.finalizer) {
|
|
78611
|
-
|
|
78631
|
+
leading.push([node.finalizer.start + 1, FOLLOW_RESTORE]);
|
|
78612
78632
|
} else if (framed && node.type === "ForOfStatement" && node.await) {
|
|
78613
78633
|
const whole = (parent == null ? void 0 : parent.type) === "LabeledStatement" ? parent : node;
|
|
78614
78634
|
insert(whole.start, `{${FOLLOW_MARK}`);
|
|
78615
78635
|
insert(whole.end, `;${FOLLOW_RESTORE}${FOLLOW_MARK}}`);
|
|
78616
|
-
if (node.body.type === "BlockStatement")
|
|
78636
|
+
if (node.body.type === "BlockStatement") leading.push([node.body.start + 1, FOLLOW_RESTORE]);
|
|
78617
78637
|
else {
|
|
78618
|
-
|
|
78638
|
+
leading.push([node.body.start, `{${FOLLOW_MARK}${FOLLOW_RESTORE}`]);
|
|
78619
78639
|
insert(node.body.end, `${FOLLOW_MARK}}`);
|
|
78620
78640
|
}
|
|
78621
78641
|
}
|
|
@@ -78627,6 +78647,7 @@ function __substrateFollowAwaits(code2) {
|
|
|
78627
78647
|
for (const item of child) if (item && typeof item.type === "string") visit(item, framed, node);
|
|
78628
78648
|
} else if (typeof child.type === "string") visit(child, framed, node);
|
|
78629
78649
|
}
|
|
78650
|
+
for (const [at3, text] of leading) insert(at3, text);
|
|
78630
78651
|
};
|
|
78631
78652
|
visit(ast, false, void 0);
|
|
78632
78653
|
return edits.length ? applyReplacements(code2, edits) : code2;
|
|
@@ -78666,7 +78687,7 @@ function __substratePrepareBody(rawCode, resolvedPath, format2, process2) {
|
|
|
78666
78687
|
}
|
|
78667
78688
|
return __substrateFollowAwaits(code2);
|
|
78668
78689
|
}
|
|
78669
|
-
const PREPARED_MODULES_DIR = "/.tabnode/prepared";
|
|
78690
|
+
const PREPARED_MODULES_DIR = "/opt/.tabnode/prepared";
|
|
78670
78691
|
const PREPARED_MODULES_FORMAT = "tabnode-prepared-2";
|
|
78671
78692
|
function preparedModuleKey(rawCode, resolvedPath) {
|
|
78672
78693
|
var _a3;
|
package/dist/index.mjs
CHANGED
|
@@ -5946,7 +5946,11 @@ function hexSlice(start, end) {
|
|
|
5946
5946
|
}
|
|
5947
5947
|
return out;
|
|
5948
5948
|
}
|
|
5949
|
+
const nativeBase64 = typeof Uint8Array.prototype.toBase64 === "function";
|
|
5949
5950
|
function base64Text(bytes2, url2) {
|
|
5951
|
+
if (nativeBase64) {
|
|
5952
|
+
return bytes2.toBase64({ alphabet: url2 ? "base64url" : "base64", omitPadding: url2 });
|
|
5953
|
+
}
|
|
5950
5954
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
5951
5955
|
let out = "";
|
|
5952
5956
|
for (let index2 = 0; index2 < bytes2.length; index2 += 3) {
|
|
@@ -5970,7 +5974,20 @@ function base64urlSlice(start, end) {
|
|
|
5970
5974
|
return base64Text(this.subarray(from, to), true);
|
|
5971
5975
|
}
|
|
5972
5976
|
function byteLengthUtf8(string) {
|
|
5973
|
-
|
|
5977
|
+
let length = 0;
|
|
5978
|
+
for (let index2 = 0; index2 < string.length; index2 += 1) {
|
|
5979
|
+
const code2 = string.charCodeAt(index2);
|
|
5980
|
+
if (code2 < 128) length += 1;
|
|
5981
|
+
else if (code2 < 2048) length += 2;
|
|
5982
|
+
else if (code2 >= 55296 && code2 < 56320 && index2 + 1 < string.length) {
|
|
5983
|
+
const next = string.charCodeAt(index2 + 1);
|
|
5984
|
+
if (next >= 56320 && next < 57344) {
|
|
5985
|
+
length += 4;
|
|
5986
|
+
index2 += 1;
|
|
5987
|
+
} else length += 3;
|
|
5988
|
+
} else length += 3;
|
|
5989
|
+
}
|
|
5990
|
+
return length;
|
|
5974
5991
|
}
|
|
5975
5992
|
function compare(a, b) {
|
|
5976
5993
|
return compareRanges(asBytes(a), 0, a.length, asBytes(b), 0, b.length);
|
|
@@ -23572,12 +23589,18 @@ function createCryptoModule(require2) {
|
|
|
23572
23589
|
function digestEngine(algorithm) {
|
|
23573
23590
|
return algorithm === "md5" ? md5.create() : SHA(algorithm);
|
|
23574
23591
|
}
|
|
23592
|
+
const utf8Encoder = new TextEncoder();
|
|
23575
23593
|
function cryptoBytes(value, encoding, allowArrayBuffer = false) {
|
|
23576
23594
|
if (typeof value === "string") {
|
|
23577
23595
|
if ((encoding == null ? void 0 : encoding.toLowerCase()) === "base64url") return buffer.Buffer.from(value, "base64");
|
|
23578
23596
|
if (encoding !== void 0 && !buffer.Buffer.isEncoding(encoding)) {
|
|
23579
23597
|
throw new TypeError(`Unknown encoding: ${encoding}`);
|
|
23580
23598
|
}
|
|
23599
|
+
const lower = encoding == null ? void 0 : encoding.toLowerCase();
|
|
23600
|
+
if (lower === void 0 || lower === "utf8" || lower === "utf-8") {
|
|
23601
|
+
const bytes2 = utf8Encoder.encode(value);
|
|
23602
|
+
return buffer.Buffer.from(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength);
|
|
23603
|
+
}
|
|
23581
23604
|
return buffer.Buffer.from(value, encoding);
|
|
23582
23605
|
}
|
|
23583
23606
|
if (ArrayBuffer.isView(value)) {
|
|
@@ -33156,10 +33179,7 @@ function createNodeResolver(options) {
|
|
|
33156
33179
|
const packageName = packageNameOf2(specifier);
|
|
33157
33180
|
const packageRoot = `${nodeModules}/${packageName}`;
|
|
33158
33181
|
const pkg = isDirectory(packageRoot) ? manifest(packageRoot) : null;
|
|
33159
|
-
if (pkg && pkg.exports !== void 0 && pkg.exports !== null)
|
|
33160
|
-
const found = loadPackageExports(packageRoot, pkg, specifier, packageName);
|
|
33161
|
-
if (found) return found;
|
|
33162
|
-
}
|
|
33182
|
+
if (pkg && pkg.exports !== void 0 && pkg.exports !== null) return loadPackageExports(packageRoot, pkg, specifier, packageName);
|
|
33163
33183
|
const path2 = `${nodeModules}/${specifier}`;
|
|
33164
33184
|
return loadAsFile(path2) ?? loadAsDirectory(path2);
|
|
33165
33185
|
};
|
|
@@ -38253,27 +38273,27 @@ function __substrateFollowAwaits(code2) {
|
|
|
38253
38273
|
};
|
|
38254
38274
|
const isFunction = (node) => node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
|
|
38255
38275
|
const visit = (node, framed, parent) => {
|
|
38276
|
+
const leading = [];
|
|
38256
38277
|
if (isFunction(node)) {
|
|
38257
38278
|
framed = node.async && node.body.type === "BlockStatement";
|
|
38258
38279
|
if (framed) {
|
|
38259
38280
|
const directives = node.body.body.filter((statement) => statement.directive !== void 0);
|
|
38260
|
-
|
|
38261
|
-
insert(at2, FOLLOW_TAKE);
|
|
38281
|
+
leading.push([directives.length ? directives[directives.length - 1].end : node.body.start + 1, FOLLOW_TAKE]);
|
|
38262
38282
|
}
|
|
38263
38283
|
} else if (node.type === "AwaitExpression") {
|
|
38264
38284
|
insert(node.start, framed ? FOLLOW_RESUME_FRAMED : FOLLOW_RESUME_TAKEN);
|
|
38265
38285
|
insert(node.end, `${FOLLOW_MARK})`);
|
|
38266
38286
|
} else if (framed && node.type === "CatchClause") {
|
|
38267
|
-
|
|
38287
|
+
leading.push([node.body.start + 1, FOLLOW_RESTORE]);
|
|
38268
38288
|
} else if (framed && node.type === "TryStatement" && node.finalizer) {
|
|
38269
|
-
|
|
38289
|
+
leading.push([node.finalizer.start + 1, FOLLOW_RESTORE]);
|
|
38270
38290
|
} else if (framed && node.type === "ForOfStatement" && node.await) {
|
|
38271
38291
|
const whole = (parent == null ? void 0 : parent.type) === "LabeledStatement" ? parent : node;
|
|
38272
38292
|
insert(whole.start, `{${FOLLOW_MARK}`);
|
|
38273
38293
|
insert(whole.end, `;${FOLLOW_RESTORE}${FOLLOW_MARK}}`);
|
|
38274
|
-
if (node.body.type === "BlockStatement")
|
|
38294
|
+
if (node.body.type === "BlockStatement") leading.push([node.body.start + 1, FOLLOW_RESTORE]);
|
|
38275
38295
|
else {
|
|
38276
|
-
|
|
38296
|
+
leading.push([node.body.start, `{${FOLLOW_MARK}${FOLLOW_RESTORE}`]);
|
|
38277
38297
|
insert(node.body.end, `${FOLLOW_MARK}}`);
|
|
38278
38298
|
}
|
|
38279
38299
|
}
|
|
@@ -38285,6 +38305,7 @@ function __substrateFollowAwaits(code2) {
|
|
|
38285
38305
|
for (const item of child) if (item && typeof item.type === "string") visit(item, framed, node);
|
|
38286
38306
|
} else if (typeof child.type === "string") visit(child, framed, node);
|
|
38287
38307
|
}
|
|
38308
|
+
for (const [at2, text] of leading) insert(at2, text);
|
|
38288
38309
|
};
|
|
38289
38310
|
visit(ast, false, void 0);
|
|
38290
38311
|
return edits.length ? applyReplacements(code2, edits) : code2;
|
|
@@ -38324,7 +38345,7 @@ function __substratePrepareBody(rawCode, resolvedPath, format2, process2) {
|
|
|
38324
38345
|
}
|
|
38325
38346
|
return __substrateFollowAwaits(code2);
|
|
38326
38347
|
}
|
|
38327
|
-
const PREPARED_MODULES_DIR = "/.tabnode/prepared";
|
|
38348
|
+
const PREPARED_MODULES_DIR = "/opt/.tabnode/prepared";
|
|
38328
38349
|
const PREPARED_MODULES_FORMAT = "tabnode-prepared-2";
|
|
38329
38350
|
function preparedModuleKey(rawCode, resolvedPath) {
|
|
38330
38351
|
var _a2;
|
|
@@ -40293,7 +40314,7 @@ class WorkerRuntime {
|
|
|
40293
40314
|
this.worker = new Worker(
|
|
40294
40315
|
new URL(
|
|
40295
40316
|
/* @vite-ignore */
|
|
40296
|
-
"/assets/runtime-worker-
|
|
40317
|
+
"/assets/runtime-worker-C4lPa6-H.js",
|
|
40297
40318
|
import.meta.url
|
|
40298
40319
|
),
|
|
40299
40320
|
{ type: "module" }
|
package/dist/runtime.d.ts
CHANGED
|
@@ -16,8 +16,11 @@ export { pendingGuestTimers, stopGuestTimers } from './guest-timers';
|
|
|
16
16
|
* from, in this directory of the tab's filesystem, and the loader takes it in
|
|
17
17
|
* place of the passes when the file it read hashes to one. A body the loader
|
|
18
18
|
* prepares for a file the image has none for is kept there the same way.
|
|
19
|
+
* Under `/opt`, a root a tab's store keeps, so a host can link the image's
|
|
20
|
+
* bodies there once from a store they share instead of writing each into
|
|
21
|
+
* every process's memory.
|
|
19
22
|
*/
|
|
20
|
-
export declare const PREPARED_MODULES_DIR = "/.tabnode/prepared";
|
|
23
|
+
export declare const PREPARED_MODULES_DIR = "/opt/.tabnode/prepared";
|
|
21
24
|
/** The name a prepared body goes under: the hash of the file as read, and how it is compiled. Undefined for a file no body is prepared for. */
|
|
22
25
|
export declare function preparedModuleKey(rawCode: string, resolvedPath: string): string | undefined;
|
|
23
26
|
/** The body the loader would compile for this file, with no load hooks and no type stripping: what the image carries. */
|
package/package.json
CHANGED
|
@@ -205,7 +205,16 @@ export function hexSlice(this: Uint8Array, start?: number, end?: number): string
|
|
|
205
205
|
return out;
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
/** The engine's own encoder where it has one (`Uint8Array.prototype.toBase64`): one string, no garbage. */
|
|
209
|
+
const nativeBase64 = typeof (Uint8Array.prototype as { toBase64?: unknown }).toBase64 === 'function';
|
|
210
|
+
|
|
208
211
|
function base64Text(bytes: Uint8Array, url: boolean): string {
|
|
212
|
+
// Built a character at a time, a sourcemap's base64 was ropes of garbage:
|
|
213
|
+
// 600 MB of a Vite session's 1.4 GB allocated in its first 20 s in a tab.
|
|
214
|
+
if (nativeBase64) {
|
|
215
|
+
return (bytes as Uint8Array & { toBase64(options: { alphabet: string; omitPadding: boolean }): string })
|
|
216
|
+
.toBase64({ alphabet: url ? 'base64url' : 'base64', omitPadding: url });
|
|
217
|
+
}
|
|
209
218
|
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
210
219
|
let out = '';
|
|
211
220
|
for (let index = 0; index < bytes.length; index += 3) {
|
|
@@ -235,7 +244,19 @@ export function base64urlSlice(this: Uint8Array, start?: number, end?: number):
|
|
|
235
244
|
|
|
236
245
|
/** Node's `ByteLengthUtf8`. */
|
|
237
246
|
export function byteLengthUtf8(string: string): number {
|
|
238
|
-
|
|
247
|
+
// Counted, not encoded: encoding the whole string to read its length
|
|
248
|
+
// allocated every Buffer.from(string) twice.
|
|
249
|
+
let length = 0;
|
|
250
|
+
for (let index = 0; index < string.length; index += 1) {
|
|
251
|
+
const code = string.charCodeAt(index);
|
|
252
|
+
if (code < 0x80) length += 1;
|
|
253
|
+
else if (code < 0x800) length += 2;
|
|
254
|
+
else if (code >= 0xd800 && code < 0xdc00 && index + 1 < string.length) {
|
|
255
|
+
const next = string.charCodeAt(index + 1);
|
|
256
|
+
if (next >= 0xdc00 && next < 0xe000) { length += 4; index += 1; } else length += 3;
|
|
257
|
+
} else length += 3;
|
|
258
|
+
}
|
|
259
|
+
return length;
|
|
239
260
|
}
|
|
240
261
|
|
|
241
262
|
/** Node's `Compare`: two buffers whole, as `memcmp` orders them. */
|
package/src/node-resolution.ts
CHANGED
|
@@ -158,14 +158,17 @@ export function createNodeResolver(options: NodeResolverOptions): NodeResolver {
|
|
|
158
158
|
return parts[0]!.startsWith("@") && parts.length > 1 ? `${parts[0]}/${parts[1]}` : parts[0]!;
|
|
159
159
|
};
|
|
160
160
|
// LOAD_NODE_MODULES from one directory: exports, else the package's own entry or a file under it.
|
|
161
|
+
// A package with `exports` is answered by the map alone, as Node answers it:
|
|
162
|
+
// a subpath the map does not name, or names to a missing file, does not
|
|
163
|
+
// resolve. Falling through to the file under the package made
|
|
164
|
+
// `require.resolve("<pkg>/package.json")` succeed where Node throws, and a
|
|
165
|
+
// program that asks that question to decide what it does (Vite config that
|
|
166
|
+
// excludes a package it cannot resolve) decided differently in the tab.
|
|
161
167
|
const loadFromNodeModules = (nodeModules: string, specifier: string): string | null => {
|
|
162
168
|
const packageName = packageNameOf(specifier);
|
|
163
169
|
const packageRoot = `${nodeModules}/${packageName}`;
|
|
164
170
|
const pkg = isDirectory(packageRoot) ? manifest(packageRoot) : null;
|
|
165
|
-
if (pkg && pkg.exports !== undefined && pkg.exports !== null)
|
|
166
|
-
const found = loadPackageExports(packageRoot, pkg, specifier, packageName);
|
|
167
|
-
if (found) return found;
|
|
168
|
-
}
|
|
171
|
+
if (pkg && pkg.exports !== undefined && pkg.exports !== null) return loadPackageExports(packageRoot, pkg, specifier, packageName);
|
|
169
172
|
const path = `${nodeModules}/${specifier}`;
|
|
170
173
|
return loadAsFile(path) ?? loadAsDirectory(path);
|
|
171
174
|
};
|
package/src/runtime.ts
CHANGED
|
@@ -468,28 +468,35 @@ function __substrateFollowAwaits(code: string): string {
|
|
|
468
468
|
const isFunction = (node: any): boolean => node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression';
|
|
469
469
|
// `framed`: the nearest function is async and holds the frame in ASYNC_FRAME.
|
|
470
470
|
const visit = (node: any, framed: boolean, parent: any): void => {
|
|
471
|
+
// What opens a block (the frame's take in an async body, the restore
|
|
472
|
+
// at the start of a catch, a finally or a for-await body) goes before
|
|
473
|
+
// anything in it: where the block's first statement is an `await`
|
|
474
|
+
// (`async function f(){await g()}`, `finally{await h()}`, as minified code
|
|
475
|
+
// writes them), both share an offset, and edits at one offset land in
|
|
476
|
+
// reverse of the order they were made. So these are made after the
|
|
477
|
+
// block's own edits, and land first.
|
|
478
|
+
const leading: Array<[number, string]> = [];
|
|
471
479
|
if (isFunction(node)) {
|
|
472
480
|
framed = node.async && node.body.type === 'BlockStatement';
|
|
473
481
|
if (framed) {
|
|
474
482
|
const directives = node.body.body.filter((statement: any) => statement.directive !== undefined);
|
|
475
|
-
|
|
476
|
-
insert(at, FOLLOW_TAKE);
|
|
483
|
+
leading.push([directives.length ? directives[directives.length - 1].end : node.body.start + 1, FOLLOW_TAKE]);
|
|
477
484
|
}
|
|
478
485
|
} else if (node.type === 'AwaitExpression') {
|
|
479
486
|
insert(node.start, framed ? FOLLOW_RESUME_FRAMED : FOLLOW_RESUME_TAKEN);
|
|
480
487
|
insert(node.end, `${FOLLOW_MARK})`);
|
|
481
488
|
} else if (framed && node.type === 'CatchClause') {
|
|
482
|
-
|
|
489
|
+
leading.push([node.body.start + 1, FOLLOW_RESTORE]);
|
|
483
490
|
} else if (framed && node.type === 'TryStatement' && node.finalizer) {
|
|
484
|
-
|
|
491
|
+
leading.push([node.finalizer.start + 1, FOLLOW_RESTORE]);
|
|
485
492
|
} else if (framed && node.type === 'ForOfStatement' && node.await) {
|
|
486
493
|
// The loop's own wrap first: where its end is the body's, an insertion
|
|
487
494
|
// made later lands before it, so the body's brace closes inside.
|
|
488
495
|
const whole = parent?.type === 'LabeledStatement' ? parent : node;
|
|
489
496
|
insert(whole.start, `{${FOLLOW_MARK}`);
|
|
490
497
|
insert(whole.end, `;${FOLLOW_RESTORE}${FOLLOW_MARK}}`);
|
|
491
|
-
if (node.body.type === 'BlockStatement')
|
|
492
|
-
else {
|
|
498
|
+
if (node.body.type === 'BlockStatement') leading.push([node.body.start + 1, FOLLOW_RESTORE]);
|
|
499
|
+
else { leading.push([node.body.start, `{${FOLLOW_MARK}${FOLLOW_RESTORE}`]); insert(node.body.end, `${FOLLOW_MARK}}`); }
|
|
493
500
|
}
|
|
494
501
|
for (const key of Object.keys(node)) {
|
|
495
502
|
if (key === 'type' || key === 'start' || key === 'end' || key === 'loc' || key === 'range') continue;
|
|
@@ -499,6 +506,7 @@ function __substrateFollowAwaits(code: string): string {
|
|
|
499
506
|
for (const item of child) if (item && typeof item.type === 'string') visit(item, framed, node);
|
|
500
507
|
} else if (typeof child.type === 'string') visit(child, framed, node);
|
|
501
508
|
}
|
|
509
|
+
for (const [at, text] of leading) insert(at, text);
|
|
502
510
|
};
|
|
503
511
|
visit(ast, false, undefined);
|
|
504
512
|
return edits.length ? applyReplacements(code, edits) : code;
|
|
@@ -589,8 +597,11 @@ function __substratePrepareBody(rawCode: string, resolvedPath: string, format: s
|
|
|
589
597
|
* from, in this directory of the tab's filesystem, and the loader takes it in
|
|
590
598
|
* place of the passes when the file it read hashes to one. A body the loader
|
|
591
599
|
* prepares for a file the image has none for is kept there the same way.
|
|
600
|
+
* Under `/opt`, a root a tab's store keeps, so a host can link the image's
|
|
601
|
+
* bodies there once from a store they share instead of writing each into
|
|
602
|
+
* every process's memory.
|
|
592
603
|
*/
|
|
593
|
-
export const PREPARED_MODULES_DIR = '/.tabnode/prepared';
|
|
604
|
+
export const PREPARED_MODULES_DIR = '/opt/.tabnode/prepared';
|
|
594
605
|
const PREPARED_MODULES_FORMAT = 'tabnode-prepared-2';
|
|
595
606
|
/** The name a prepared body goes under: the hash of the file as read, and how it is compiled. Undefined for a file no body is prepared for. */
|
|
596
607
|
export function preparedModuleKey(rawCode: string, resolvedPath: string): string | undefined {
|
package/src/shims/crypto.ts
CHANGED
|
@@ -330,6 +330,7 @@ type HostBytes = InstanceType<typeof HostBuffer>;
|
|
|
330
330
|
* encodings the guest Buffer polyfill does not (utf16le, latin1) and views a
|
|
331
331
|
* caller's ArrayBuffer at its offset instead of copying the whole store.
|
|
332
332
|
*/
|
|
333
|
+
const utf8Encoder = new TextEncoder();
|
|
333
334
|
function cryptoBytes(value: unknown, encoding?: string, allowArrayBuffer = false): HostBytes {
|
|
334
335
|
if (typeof value === 'string') {
|
|
335
336
|
// `buffer` 6.0.3 predates base64url; the alphabet is a superset of base64's.
|
|
@@ -337,6 +338,14 @@ function cryptoBytes(value: unknown, encoding?: string, allowArrayBuffer = false
|
|
|
337
338
|
if (encoding !== undefined && !HostBuffer.isEncoding(encoding)) {
|
|
338
339
|
throw new TypeError(`Unknown encoding: ${encoding}`);
|
|
339
340
|
}
|
|
341
|
+
// UTF-8, the default, by the engine's encoder: `buffer`'s own builds an
|
|
342
|
+
// array of numbers per string, and a Vite session hashing every module it
|
|
343
|
+
// served made hundreds of MB of that garbage in its first seconds in a tab.
|
|
344
|
+
const lower = encoding?.toLowerCase();
|
|
345
|
+
if (lower === undefined || lower === 'utf8' || lower === 'utf-8') {
|
|
346
|
+
const bytes = utf8Encoder.encode(value);
|
|
347
|
+
return HostBuffer.from(bytes.buffer as ArrayBuffer, bytes.byteOffset, bytes.byteLength);
|
|
348
|
+
}
|
|
340
349
|
return HostBuffer.from(value, encoding);
|
|
341
350
|
}
|
|
342
351
|
if (ArrayBuffer.isView(value)) {
|