@volter/tabnode 0.5.29 → 0.5.30
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 +51 -3
- package/dist/index.mjs +4 -11
- package/package.json +1 -1
package/dist/__sw__.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Service Worker for Mini WebContainers
|
|
3
3
|
* Intercepts fetch requests and routes them to virtual servers
|
|
4
|
-
* Version:
|
|
4
|
+
* Version: 17 - a host's document prelude: its frames' documents start with it
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const DEBUG = false;
|
|
@@ -158,6 +158,9 @@ self.addEventListener('message', (event) => {
|
|
|
158
158
|
if (hosts.get(host.id) === host && host.port === initializedPort) handleMainMessage(host, message);
|
|
159
159
|
};
|
|
160
160
|
if (data && Array.isArray(data.ownDocuments)) host.ownDocuments = new Set(data.ownDocuments.map((path) => ownPath(String(path))));
|
|
161
|
+
// Markup a frame's document served from this host's servers starts with
|
|
162
|
+
// (after its doctype): the page's first script, before the document's own.
|
|
163
|
+
host.documentPrelude = data && typeof data.documentPrelude === 'string' && data.documentPrelude ? data.documentPrelude : null;
|
|
161
164
|
DEBUG && console.log('[SW] Initialized communication channel with transferred port');
|
|
162
165
|
// Re-claim clients so that pages opened after SW activation get controlled.
|
|
163
166
|
// Without this, controllerchange never fires for late-arriving pages.
|
|
@@ -664,7 +667,7 @@ self.addEventListener('fetch', (event) => {
|
|
|
664
667
|
const targetPath = url.pathname + url.search;
|
|
665
668
|
if (context.prefix === null) {
|
|
666
669
|
DEBUG && console.log('[SW] Answering a root request from the virtual server:', url.pathname);
|
|
667
|
-
return handleRootedRequest(event, context.port, targetPath);
|
|
670
|
+
return withDocumentPrelude(event, await handleRootedRequest(event, context.port, targetPath));
|
|
668
671
|
}
|
|
669
672
|
if (event.request.mode === 'navigate') {
|
|
670
673
|
DEBUG && console.log('[SW] Redirecting navigation from virtual context:', url.pathname);
|
|
@@ -683,9 +686,54 @@ self.addEventListener('fetch', (event) => {
|
|
|
683
686
|
const port = parseInt(match[1], 10);
|
|
684
687
|
const path = match[2] || '/';
|
|
685
688
|
|
|
686
|
-
event.respondWith(handleVirtualRequest(event.request, port, path + url.search));
|
|
689
|
+
event.respondWith(handleVirtualRequest(event.request, port, path + url.search).then((response) => withDocumentPrelude(event, response)));
|
|
687
690
|
});
|
|
688
691
|
|
|
692
|
+
/**
|
|
693
|
+
* A frame's HTML document from a host's servers, with the host's prelude
|
|
694
|
+
* first: after a leading doctype (so the document keeps its mode), else at
|
|
695
|
+
* the very start, where the parser puts a script into the head it makes.
|
|
696
|
+
*/
|
|
697
|
+
async function withDocumentPrelude(event, response) {
|
|
698
|
+
const request = event.request;
|
|
699
|
+
if (request.mode !== 'navigate' || (request.destination !== 'iframe' && request.destination !== 'frame')) return response;
|
|
700
|
+
if (!response.body || !/text\/html/i.test(response.headers.get('content-type') || '')) return response;
|
|
701
|
+
let host = null;
|
|
702
|
+
try { host = await hostForEvent(event); } catch (e) { /* no host */ }
|
|
703
|
+
const prelude = host && host.documentPrelude;
|
|
704
|
+
if (!prelude) return response;
|
|
705
|
+
const encoder = new TextEncoder();
|
|
706
|
+
const inserted = encoder.encode(prelude);
|
|
707
|
+
let pending = new Uint8Array(0);
|
|
708
|
+
let done = false;
|
|
709
|
+
const release = (controller, cut) => {
|
|
710
|
+
controller.enqueue(pending.subarray(0, cut));
|
|
711
|
+
controller.enqueue(inserted);
|
|
712
|
+
controller.enqueue(pending.subarray(cut));
|
|
713
|
+
pending = new Uint8Array(0);
|
|
714
|
+
done = true;
|
|
715
|
+
};
|
|
716
|
+
const body = response.body.pipeThrough(new TransformStream({
|
|
717
|
+
transform(chunk, controller) {
|
|
718
|
+
if (done) { controller.enqueue(chunk); return; }
|
|
719
|
+
const joined = new Uint8Array(pending.length + chunk.length);
|
|
720
|
+
joined.set(pending); joined.set(chunk, pending.length);
|
|
721
|
+
pending = joined;
|
|
722
|
+
const head = new TextDecoder().decode(pending.subarray(0, 2048));
|
|
723
|
+
const doctype = /^\uFEFF?\s*<!doctype[^>]*>/i.exec(head);
|
|
724
|
+
if (doctype) { release(controller, encoder.encode(doctype[0]).length); return; }
|
|
725
|
+
// A doctype still arriving waits for its end; anything else is no doctype.
|
|
726
|
+
const start = head.replace(/^\uFEFF?\s*/, '');
|
|
727
|
+
if (pending.length < 2048 && ('<!doctype'.startsWith(start.toLowerCase()) || /^<!doctype/i.test(start))) return;
|
|
728
|
+
release(controller, 0);
|
|
729
|
+
},
|
|
730
|
+
flush(controller) { if (!done) release(controller, 0); },
|
|
731
|
+
}));
|
|
732
|
+
const headers = new Headers(response.headers);
|
|
733
|
+
headers.delete('content-length');
|
|
734
|
+
return new Response(body, { status: response.status, statusText: response.statusText, headers });
|
|
735
|
+
}
|
|
736
|
+
|
|
689
737
|
/**
|
|
690
738
|
* Handle a request to a virtual server
|
|
691
739
|
*/
|
package/dist/index.mjs
CHANGED
|
@@ -21288,17 +21288,10 @@ var implementation$1 = function bind2(that) {
|
|
|
21288
21288
|
var implementation = implementation$1;
|
|
21289
21289
|
var functionBind = Function.prototype.bind || implementation;
|
|
21290
21290
|
var functionCall = Function.prototype.call;
|
|
21291
|
-
var functionApply;
|
|
21292
|
-
var hasRequiredFunctionApply;
|
|
21293
|
-
function requireFunctionApply() {
|
|
21294
|
-
if (hasRequiredFunctionApply) return functionApply;
|
|
21295
|
-
hasRequiredFunctionApply = 1;
|
|
21296
|
-
functionApply = Function.prototype.apply;
|
|
21297
|
-
return functionApply;
|
|
21298
|
-
}
|
|
21291
|
+
var functionApply = Function.prototype.apply;
|
|
21299
21292
|
var reflectApply = typeof Reflect !== "undefined" && Reflect && Reflect.apply;
|
|
21300
21293
|
var bind$2 = functionBind;
|
|
21301
|
-
var $apply$1 =
|
|
21294
|
+
var $apply$1 = functionApply;
|
|
21302
21295
|
var $call$2 = functionCall;
|
|
21303
21296
|
var $reflectApply = reflectApply;
|
|
21304
21297
|
var actualApply = $reflectApply || bind$2.call($call$2, $apply$1);
|
|
@@ -21418,7 +21411,7 @@ var hasSymbols = requireHasSymbols()();
|
|
|
21418
21411
|
var getProto = requireGetProto();
|
|
21419
21412
|
var $ObjectGPO = requireObject_getPrototypeOf();
|
|
21420
21413
|
var $ReflectGPO = requireReflect_getPrototypeOf();
|
|
21421
|
-
var $apply =
|
|
21414
|
+
var $apply = functionApply;
|
|
21422
21415
|
var $call = functionCall;
|
|
21423
21416
|
var needsEval = {};
|
|
21424
21417
|
var TypedArray = typeof Uint8Array === "undefined" || !getProto ? undefined$1 : getProto(Uint8Array);
|
|
@@ -22059,7 +22052,7 @@ function requireApplyBind() {
|
|
|
22059
22052
|
if (hasRequiredApplyBind) return applyBind;
|
|
22060
22053
|
hasRequiredApplyBind = 1;
|
|
22061
22054
|
var bind3 = functionBind;
|
|
22062
|
-
var $apply2 =
|
|
22055
|
+
var $apply2 = functionApply;
|
|
22063
22056
|
var actualApply$1 = actualApply;
|
|
22064
22057
|
applyBind = function applyBind2() {
|
|
22065
22058
|
return actualApply$1(bind3, $apply2, arguments);
|