@php-wasm/web-service-worker 3.1.19 → 3.1.21

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.
Files changed (4) hide show
  1. package/index.cjs +1 -1
  2. package/index.js +146 -131
  3. package/package.json +6 -5
  4. package/utils.d.ts +11 -5
package/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("@php-wasm/scopes"),q=require("@php-wasm/universal");var g=typeof document<"u"?document.currentScript:null;const I=25e3;let H=0;function v(e,t,...r){const n=S();return e.postMessage({...t,requestId:n},...r),n}function S(){return++H}function U(e,t,r=I){return new Promise((n,a)=>{const o=u=>{u.data.type==="response"&&u.data.requestId===t&&(e.removeEventListener("message",o),clearTimeout(s),n(u.data.response))},s=setTimeout(()=>{a(new Error("Request timed out")),e.removeEventListener("message",o)},r);e.addEventListener("message",o)})}function A(e,t){return{type:"response",requestId:e,response:t}}async function O(e){let t=new URL(e.request.url);if(!d.isURLScoped(t))try{const c=new URL(e.request.referrer);t=d.setURLScope(t,d.getURLScope(c))}catch{}const r=e.request.headers.get("content-type"),n=e.request.method==="POST"?new Uint8Array(await e.request.clone().arrayBuffer()):void 0,a={};for(const c of e.request.headers.entries())a[c[0]]=c[1];let o;try{const c={method:"request",args:[{body:n,url:t.toString(),method:e.request.method,headers:{...a,Host:t.host,"User-agent":self.navigator.userAgent,"Content-type":r}}]},i=d.getURLScope(t);if(i===null)throw new Error(`The URL ${t.toString()} is not scoped. This should not happen.`);const f=await b(c,i);if(o=await U(self,f),delete o.headers["x-frame-options"],o.headers["content-security-policy"]){const l=o.headers["content-security-policy"].map(p=>C("frame-ancestors",p)).filter(p=>p.trim().length>0);l.length>0?o.headers["content-security-policy"]=l:delete o.headers["content-security-policy"]}}catch(c){throw console.error(c,{url:t.toString()}),c}if(o.httpStatusCode>=300&&o.httpStatusCode<=399&&o.headers.location){const c=d.getURLScope(t);let i=new URL(o.headers.location[0],t.toString());return c&&!d.isURLScoped(i)&&(i=d.setURLScope(i,c)),Response.redirect(i.toString(),o.httpStatusCode)}const s=[101,103,204,205,304].includes(o.httpStatusCode);let u=null;return s||(o.bodyPort?u=q.portToStream(o.bodyPort):u=o.bytes),new Response(u,{headers:o.headers,status:o.httpStatusCode})}async function b(e,t){const r=S();for(const n of await self.clients.matchAll({includeUncontrolled:!0}))n.postMessage({...e,scope:t,requestId:r});return r}async function h(e,t){let r;return["GET","HEAD"].includes(e.method)?r=void 0:"body"in t?r=t.body:!e.bodyUsed&&e.body?r=e.body:r=await e.arrayBuffer(),new Request(t.url||e.url,{body:r,method:e.method,headers:e.headers,referrer:e.referrer,referrerPolicy:e.referrerPolicy,mode:e.mode==="navigate"?"same-origin":e.mode,credentials:e.credentials,cache:e.cache,redirect:e.redirect,integrity:e.integrity,...r instanceof ReadableStream&&{duplex:"half"},...t})}async function L(e){if(!e.body)return[e,e];const[t,r]=e.body.tee();return[await h(e,{body:t,duplex:"half"}),await h(e,{body:r,duplex:"half"})]}function D(e){const t={};return e.headers.forEach((r,n)=>{t[n]=r}),t}function C(e,t){const r=/^[\u{9}\u{A}\u{C}\u{D}\u{20}]+/u,n=/[\u{9}\u{A}\u{C}\u{D}\u{20}]+$/u,a=/[\u{9}\u{A}\u{C}\u{D}\u{20}]/u;return t.split(";").filter(o=>{const s=o.replace(r,"").replace(n,""),[u]=s.split(a,1);return u.toLowerCase()!==e.toLowerCase()}).join(";")}class T extends Error{constructor(t,r,n){super(`Could not fetch ${t} – your network appears to be blocking this request (HTTP ${r}). This often happens on school, university, or corporate networks. Try switching to a different network or using a VPN.`),this.name="FirewallInterferenceError",this.url=t,this.status=r,this.statusText=n}}const M="X-Playground-Cors-Proxy";async function j(e,t,r,n){var f;let a=typeof e=="string"?new Request(e,t):e;const o=n?new URL(n):null;let s=o?new URL(a.url,o):new URL(a.url);if(s.hostname==="localhost"||s.hostname==="127.0.0.1"||s.hostname==="[::1]"||s.hostname==="::1")return await fetch(a);if(s.protocol==="http:"){s.protocol="https:";const l=s.toString();a=await h(a,{url:l}),s=new URL(l)}if(!r)return await fetch(a);if(o&&s.protocol===o.protocol&&s.hostname===o.hostname&&s.port===o.port&&s.pathname.startsWith(o.pathname))return await fetch(a);const[c,i]=await L(a);try{return await fetch(c)}catch{const l=new Headers(i.headers),p=((f=l.get("x-cors-proxy-allowed-request-headers"))==null?void 0:f.split(","))||[],E=p.includes("authorization")||p.includes("cookie"),m=l.get("content-type");m&&m.toLowerCase().includes("multipart/form-data")&&(l.set("x-cors-proxy-content-type",m),l.set("content-type","application/octet-stream"));const y=new URL(typeof document>"u"?require("url").pathToFileURL(__filename).href:g&&g.tagName.toUpperCase()==="SCRIPT"&&g.src||new URL("index.cjs",document.baseURI).href);y.pathname="",y.search="",y.hash="";const P=new URL(r,y.toString());let w=i.body;w&&new URL(P).protocol==="http:"&&(w=await new Response(w).arrayBuffer());const x=await h(i,{url:`${r}${a.url}`,headers:l,body:w,...E&&{credentials:"include"}}),R=await fetch(x);if(!R.headers.has(M))throw new T(a.url,R.status,R.statusText);return R}}exports.FirewallInterferenceError=T;exports.awaitReply=U;exports.broadcastMessageExpectReply=b;exports.cloneRequest=h;exports.convertFetchEventToPHPRequest=O;exports.fetchWithCorsProxy=j;exports.getNextRequestId=S;exports.getRequestHeaders=D;exports.postMessageExpectReply=v;exports.removeContentSecurityPolicyDirective=C;exports.responseTo=A;exports.teeRequest=L;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("@php-wasm/scopes"),q=require("@php-wasm/universal");var R=typeof document<"u"?document.currentScript:null;const x=25e3;let v=0;function H(e,t,...o){const a=S();return e.postMessage({...t,requestId:a},...o),a}function S(){return++v}function U(e,t,o=x){return new Promise((a,s)=>{const r=i=>{i.data.type==="response"&&i.data.requestId===t&&(e.removeEventListener("message",r),clearTimeout(n),a(i.data.response))},n=setTimeout(()=>{s(new Error("Request timed out")),e.removeEventListener("message",r)},o);e.addEventListener("message",r)})}function I(e,t){return{type:"response",requestId:e,response:t}}async function A(e){let t=new URL(e.request.url);if(!d.isURLScoped(t))try{const c=new URL(e.request.referrer);t=d.setURLScope(t,d.getURLScope(c))}catch{}const o=e.request.headers.get("content-type"),a=e.request.method==="POST"?new Uint8Array(await e.request.clone().arrayBuffer()):void 0,s={};for(const c of e.request.headers.entries())s[c[0]]=c[1];let r;try{const c={method:"request",args:[{body:a,url:t.toString(),method:e.request.method,headers:{...s,Host:t.host,"User-agent":self.navigator.userAgent,"Content-type":o}}]},l=d.getURLScope(t);if(l===null)throw new Error(`The URL ${t.toString()} is not scoped. This should not happen.`);const u=await L(c,l);if(r=await U(self,u),delete r.headers["x-frame-options"],r.headers["content-security-policy"]){const f=r.headers["content-security-policy"].map(y=>C("frame-ancestors",y)).filter(y=>y.trim().length>0);f.length>0?r.headers["content-security-policy"]=f:delete r.headers["content-security-policy"]}}catch(c){throw console.error(c,{url:t.toString()}),c}if(r.httpStatusCode>=300&&r.httpStatusCode<=399&&r.headers.location){const c=d.getURLScope(t);let l=new URL(r.headers.location[0],t.toString());return c&&!d.isURLScoped(l)&&(l=d.setURLScope(l,c)),Response.redirect(l.toString(),r.httpStatusCode)}const n=[101,103,204,205,304].includes(r.httpStatusCode);let i=null;return n||(r.bodyPort?i=q.portToStream(r.bodyPort):i=r.bytes),new Response(i,{headers:r.headers,status:r.httpStatusCode})}async function L(e,t){const o=S();for(const a of await self.clients.matchAll({includeUncontrolled:!0}))a.postMessage({...e,scope:t,requestId:o});return o}async function g(e,t){let o;return["GET","HEAD"].includes(e.method)?o=void 0:"body"in t?o=t.body:!e.bodyUsed&&e.body?o=e.body:o=await e.arrayBuffer(),new Request(t.url||e.url,{body:o,method:e.method,headers:e.headers,referrer:e.referrer,referrerPolicy:e.referrerPolicy,mode:e.mode==="navigate"?"same-origin":e.mode,credentials:e.credentials,cache:e.cache,redirect:e.redirect,integrity:e.integrity,...o instanceof ReadableStream&&{duplex:"half"},...t})}let h;const O={resetStreamBodySupported(){h=void 0}};async function T(){if(h!==void 0)return h;try{const e=new ReadableStream({start(t){t.close()}});await fetch("data:,",{method:"POST",body:e,duplex:"half"}),h=!0}catch{h=!1}return h}function _(e){const t={};return e.headers.forEach((o,a)=>{t[a]=o}),t}function C(e,t){const o=/^[\u{9}\u{A}\u{C}\u{D}\u{20}]+/u,a=/[\u{9}\u{A}\u{C}\u{D}\u{20}]+$/u,s=/[\u{9}\u{A}\u{C}\u{D}\u{20}]/u;return t.split(";").filter(r=>{const n=r.replace(o,"").replace(a,""),[i]=n.split(s,1);return i.toLowerCase()!==e.toLowerCase()}).join(";")}class E extends Error{constructor(t,o,a){super(`Could not fetch ${t} – your network appears to be blocking this request (HTTP ${o}). This often happens on school, university, or corporate networks. Try switching to a different network or using a VPN.`),this.name="FirewallInterferenceError",this.url=t,this.status=o,this.statusText=a}}const B="X-Playground-Cors-Proxy";async function D(e,t,o,a){var l;let s=typeof e=="string"?new Request(e,t):e;const r=a?new URL(a):null;let n=r?new URL(s.url,r):new URL(s.url);if(n.hostname==="localhost"||n.hostname==="127.0.0.1"||n.hostname==="[::1]"||n.hostname==="::1")return await fetch(s);if(n.protocol==="http:"){n.protocol="https:";const u=n.toString();s=await g(s,{url:u}),n=new URL(u)}if(!o)return await fetch(s);if(r&&n.protocol===r.protocol&&n.hostname===r.hostname&&n.port===r.port&&n.pathname.startsWith(r.pathname))return await fetch(s);const c=s.clone();try{return await fetch(s)}catch{const u=new Headers(s.headers),f=((l=u.get("x-cors-proxy-allowed-request-headers"))==null?void 0:l.split(","))||[],y=f.includes("authorization")||f.includes("cookie"),w=u.get("content-type");w&&w.toLowerCase().includes("multipart/form-data")&&(u.set("x-cors-proxy-content-type",w),u.set("content-type","application/octet-stream"));let p=null;const b=s.method.toUpperCase();b!=="GET"&&b!=="HEAD"&&(await T()?p=c.body:p=await c.arrayBuffer()),p instanceof ReadableStream&&new URL(o,typeof document>"u"?require("url").pathToFileURL(__filename).href:R&&R.tagName.toUpperCase()==="SCRIPT"&&R.src||new URL("index.cjs",document.baseURI).href).protocol==="http:"&&(p=await new Response(p).arrayBuffer());const P=await g(s,{url:`${o}${s.url}`,headers:u,body:p,...y&&{credentials:"include"}}),m=await fetch(P);if(!m.headers.has(B))throw new E(s.url,m.status,m.statusText);return m}}exports.FirewallInterferenceError=E;exports.__testing=O;exports.awaitReply=U;exports.broadcastMessageExpectReply=L;exports.cloneRequest=g;exports.convertFetchEventToPHPRequest=A;exports.fetchWithCorsProxy=D;exports.getNextRequestId=S;exports.getRequestHeaders=_;exports.postMessageExpectReply=H;exports.removeContentSecurityPolicyDirective=C;exports.responseTo=I;exports.supportsReadableStreamBody=T;
package/index.js CHANGED
@@ -1,115 +1,115 @@
1
- import { isURLScoped as g, setURLScope as b, getURLScope as R } from "@php-wasm/scopes";
2
- import { portToStream as E } from "@php-wasm/universal";
3
- const T = 25e3;
4
- let x = 0;
5
- function j(e, t, ...r) {
6
- const n = L();
1
+ import { isURLScoped as g, setURLScope as S, getURLScope as w } from "@php-wasm/scopes";
2
+ import { portToStream as C } from "@php-wasm/universal";
3
+ const L = 25e3;
4
+ let U = 0;
5
+ function D(e, t, ...o) {
6
+ const a = E();
7
7
  return e.postMessage(
8
8
  {
9
9
  ...t,
10
- requestId: n
10
+ requestId: a
11
11
  },
12
- ...r
13
- ), n;
12
+ ...o
13
+ ), a;
14
14
  }
15
- function L() {
16
- return ++x;
15
+ function E() {
16
+ return ++U;
17
17
  }
18
- function P(e, t, r = T) {
19
- return new Promise((n, a) => {
20
- const o = (u) => {
21
- u.data.type === "response" && u.data.requestId === t && (e.removeEventListener("message", o), clearTimeout(s), n(u.data.response));
22
- }, s = setTimeout(() => {
23
- a(new Error("Request timed out")), e.removeEventListener("message", o);
24
- }, r);
25
- e.addEventListener("message", o);
18
+ function P(e, t, o = L) {
19
+ return new Promise((a, s) => {
20
+ const r = (c) => {
21
+ c.data.type === "response" && c.data.requestId === t && (e.removeEventListener("message", r), clearTimeout(n), a(c.data.response));
22
+ }, n = setTimeout(() => {
23
+ s(new Error("Request timed out")), e.removeEventListener("message", r);
24
+ }, o);
25
+ e.addEventListener("message", r);
26
26
  });
27
27
  }
28
- function k(e, t) {
28
+ function v(e, t) {
29
29
  return {
30
30
  type: "response",
31
31
  requestId: e,
32
32
  response: t
33
33
  };
34
34
  }
35
- async function v(e) {
35
+ async function _(e) {
36
36
  let t = new URL(e.request.url);
37
37
  if (!g(t))
38
38
  try {
39
- const c = new URL(e.request.referrer);
40
- t = b(t, R(c));
39
+ const i = new URL(e.request.referrer);
40
+ t = S(t, w(i));
41
41
  } catch {
42
42
  }
43
- const r = e.request.headers.get("content-type"), n = e.request.method === "POST" ? new Uint8Array(await e.request.clone().arrayBuffer()) : void 0, a = {};
44
- for (const c of e.request.headers.entries())
45
- a[c[0]] = c[1];
46
- let o;
43
+ const o = e.request.headers.get("content-type"), a = e.request.method === "POST" ? new Uint8Array(await e.request.clone().arrayBuffer()) : void 0, s = {};
44
+ for (const i of e.request.headers.entries())
45
+ s[i[0]] = i[1];
46
+ let r;
47
47
  try {
48
- const c = {
48
+ const i = {
49
49
  method: "request",
50
50
  args: [
51
51
  {
52
- body: n,
52
+ body: a,
53
53
  url: t.toString(),
54
54
  method: e.request.method,
55
55
  headers: {
56
- ...a,
56
+ ...s,
57
57
  Host: t.host,
58
58
  // Safari and Firefox don't make the User-Agent header
59
59
  // available in the fetch event. Let's add it manually:
60
60
  "User-agent": self.navigator.userAgent,
61
- "Content-type": r
61
+ "Content-type": o
62
62
  }
63
63
  }
64
64
  ]
65
- }, i = R(t);
66
- if (i === null)
65
+ }, l = w(t);
66
+ if (l === null)
67
67
  throw new Error(
68
68
  `The URL ${t.toString()} is not scoped. This should not happen.`
69
69
  );
70
- const h = await A(c, i);
71
- if (o = await P(self, h), delete o.headers["x-frame-options"], o.headers["content-security-policy"]) {
72
- const l = o.headers["content-security-policy"].map(
73
- (d) => q(
70
+ const u = await x(i, l);
71
+ if (r = await P(self, u), delete r.headers["x-frame-options"], r.headers["content-security-policy"]) {
72
+ const h = r.headers["content-security-policy"].map(
73
+ (f) => A(
74
74
  "frame-ancestors",
75
- d
75
+ f
76
76
  )
77
- ).filter((d) => d.trim().length > 0);
78
- l.length > 0 ? o.headers["content-security-policy"] = l : delete o.headers["content-security-policy"];
77
+ ).filter((f) => f.trim().length > 0);
78
+ h.length > 0 ? r.headers["content-security-policy"] = h : delete r.headers["content-security-policy"];
79
79
  }
80
- } catch (c) {
81
- throw console.error(c, { url: t.toString() }), c;
80
+ } catch (i) {
81
+ throw console.error(i, { url: t.toString() }), i;
82
82
  }
83
- if (o.httpStatusCode >= 300 && o.httpStatusCode <= 399 && o.headers.location) {
84
- const c = R(t);
85
- let i = new URL(
86
- o.headers.location[0],
83
+ if (r.httpStatusCode >= 300 && r.httpStatusCode <= 399 && r.headers.location) {
84
+ const i = w(t);
85
+ let l = new URL(
86
+ r.headers.location[0],
87
87
  t.toString()
88
88
  );
89
- return c && !g(i) && (i = b(i, c)), Response.redirect(
90
- i.toString(),
91
- o.httpStatusCode
89
+ return i && !g(l) && (l = S(l, i)), Response.redirect(
90
+ l.toString(),
91
+ r.httpStatusCode
92
92
  );
93
93
  }
94
- const s = [101, 103, 204, 205, 304].includes(
95
- o.httpStatusCode
94
+ const n = [101, 103, 204, 205, 304].includes(
95
+ r.httpStatusCode
96
96
  );
97
- let u = null;
98
- return s || (o.bodyPort ? u = E(o.bodyPort) : u = o.bytes), new Response(u, {
99
- headers: o.headers,
100
- status: o.httpStatusCode
97
+ let c = null;
98
+ return n || (r.bodyPort ? c = C(r.bodyPort) : c = r.bytes), new Response(c, {
99
+ headers: r.headers,
100
+ status: r.httpStatusCode
101
101
  });
102
102
  }
103
- async function A(e, t) {
104
- const r = L();
105
- for (const n of await self.clients.matchAll({
103
+ async function x(e, t) {
104
+ const o = E();
105
+ for (const a of await self.clients.matchAll({
106
106
  // Sometimes the client that triggered the current fetch()
107
107
  // event is considered uncontrolled in Google Chrome. This
108
108
  // only happens on the first few fetches() after the initial
109
109
  // registration of the service worker.
110
110
  includeUncontrolled: !0
111
111
  }))
112
- n.postMessage({
112
+ a.postMessage({
113
113
  ...e,
114
114
  /**
115
115
  * Attach the scope with a URL starting with `/scope:` to this message.
@@ -119,14 +119,14 @@ async function A(e, t) {
119
119
  * helps WASM workers ignore requests meant for other WASM workers.
120
120
  */
121
121
  scope: t,
122
- requestId: r
122
+ requestId: o
123
123
  });
124
- return r;
124
+ return o;
125
125
  }
126
- async function w(e, t) {
127
- let r;
128
- return ["GET", "HEAD"].includes(e.method) ? r = void 0 : "body" in t ? r = t.body : !e.bodyUsed && e.body ? r = e.body : r = await e.arrayBuffer(), new Request(t.url || e.url, {
129
- body: r,
126
+ async function b(e, t) {
127
+ let o;
128
+ return ["GET", "HEAD"].includes(e.method) ? o = void 0 : "body" in t ? o = t.body : !e.bodyUsed && e.body ? o = e.body : o = await e.arrayBuffer(), new Request(t.url || e.url, {
129
+ body: o,
130
130
  method: e.method,
131
131
  headers: e.headers,
132
132
  referrer: e.referrer,
@@ -148,80 +148,94 @@ async function w(e, t) {
148
148
  *
149
149
  * See MDN: https://developer.mozilla.org/en-US/docs/Web/API/Request/duplex
150
150
  */
151
- ...r instanceof ReadableStream && { duplex: "half" },
151
+ ...o instanceof ReadableStream && { duplex: "half" },
152
152
  ...t
153
153
  });
154
154
  }
155
- async function H(e) {
156
- if (!e.body)
157
- return [e, e];
158
- const [t, r] = e.body.tee();
159
- return [
160
- await w(e, { body: t, duplex: "half" }),
161
- await w(e, { body: r, duplex: "half" })
162
- ];
155
+ let p;
156
+ const $ = {
157
+ resetStreamBodySupported() {
158
+ p = void 0;
159
+ }
160
+ };
161
+ async function q() {
162
+ if (p !== void 0)
163
+ return p;
164
+ try {
165
+ const e = new ReadableStream({
166
+ start(t) {
167
+ t.close();
168
+ }
169
+ });
170
+ await fetch("data:,", {
171
+ method: "POST",
172
+ body: e,
173
+ duplex: "half"
174
+ }), p = !0;
175
+ } catch {
176
+ p = !1;
177
+ }
178
+ return p;
163
179
  }
164
- function B(e) {
180
+ function k(e) {
165
181
  const t = {};
166
- return e.headers.forEach((r, n) => {
167
- t[n] = r;
182
+ return e.headers.forEach((o, a) => {
183
+ t[a] = o;
168
184
  }), t;
169
185
  }
170
- function q(e, t) {
171
- const r = /^[\u{9}\u{A}\u{C}\u{D}\u{20}]+/u, n = /[\u{9}\u{A}\u{C}\u{D}\u{20}]+$/u, a = /[\u{9}\u{A}\u{C}\u{D}\u{20}]/u;
172
- return t.split(";").filter((o) => {
173
- const s = o.replace(r, "").replace(n, ""), [u] = s.split(
174
- a,
186
+ function A(e, t) {
187
+ const o = /^[\u{9}\u{A}\u{C}\u{D}\u{20}]+/u, a = /[\u{9}\u{A}\u{C}\u{D}\u{20}]+$/u, s = /[\u{9}\u{A}\u{C}\u{D}\u{20}]/u;
188
+ return t.split(";").filter((r) => {
189
+ const n = r.replace(o, "").replace(a, ""), [c] = n.split(
190
+ s,
175
191
  // The directive name is the first token.
176
192
  1
177
193
  );
178
- return u.toLowerCase() !== e.toLowerCase();
194
+ return c.toLowerCase() !== e.toLowerCase();
179
195
  }).join(";");
180
196
  }
181
- class I extends Error {
182
- constructor(t, r, n) {
197
+ class H extends Error {
198
+ constructor(t, o, a) {
183
199
  super(
184
- `Could not fetch ${t} – your network appears to be blocking this request (HTTP ${r}). This often happens on school, university, or corporate networks. Try switching to a different network or using a VPN.`
185
- ), this.name = "FirewallInterferenceError", this.url = t, this.status = r, this.statusText = n;
200
+ `Could not fetch ${t} – your network appears to be blocking this request (HTTP ${o}). This often happens on school, university, or corporate networks. Try switching to a different network or using a VPN.`
201
+ ), this.name = "FirewallInterferenceError", this.url = t, this.status = o, this.statusText = a;
186
202
  }
187
203
  }
188
- const O = "X-Playground-Cors-Proxy";
189
- async function M(e, t, r, n) {
190
- var h;
191
- let a = typeof e == "string" ? new Request(e, t) : e;
192
- const o = n ? new URL(n) : null;
193
- let s = o ? new URL(a.url, o) : new URL(a.url);
194
- if (s.hostname === "localhost" || s.hostname === "127.0.0.1" || s.hostname === "[::1]" || s.hostname === "::1")
195
- return await fetch(a);
196
- if (s.protocol === "http:") {
197
- s.protocol = "https:";
198
- const l = s.toString();
199
- a = await w(a, { url: l }), s = new URL(l);
204
+ const I = "X-Playground-Cors-Proxy";
205
+ async function M(e, t, o, a) {
206
+ var l;
207
+ let s = typeof e == "string" ? new Request(e, t) : e;
208
+ const r = a ? new URL(a) : null;
209
+ let n = r ? new URL(s.url, r) : new URL(s.url);
210
+ if (n.hostname === "localhost" || n.hostname === "127.0.0.1" || n.hostname === "[::1]" || n.hostname === "::1")
211
+ return await fetch(s);
212
+ if (n.protocol === "http:") {
213
+ n.protocol = "https:";
214
+ const u = n.toString();
215
+ s = await b(s, { url: u }), n = new URL(u);
200
216
  }
201
- if (!r)
202
- return await fetch(a);
203
- if (o && s.protocol === o.protocol && s.hostname === o.hostname && s.port === o.port && s.pathname.startsWith(o.pathname))
204
- return await fetch(a);
205
- const [c, i] = await H(a);
217
+ if (!o)
218
+ return await fetch(s);
219
+ if (r && n.protocol === r.protocol && n.hostname === r.hostname && n.port === r.port && n.pathname.startsWith(r.pathname))
220
+ return await fetch(s);
221
+ const i = s.clone();
206
222
  try {
207
- return await fetch(c);
223
+ return await fetch(s);
208
224
  } catch {
209
- const l = new Headers(i.headers), d = ((h = l.get("x-cors-proxy-allowed-request-headers")) == null ? void 0 : h.split(",")) || [], U = d.includes("authorization") || d.includes("cookie"), m = l.get("content-type");
210
- m && m.toLowerCase().includes("multipart/form-data") && (l.set("x-cors-proxy-content-type", m), l.set("content-type", "application/octet-stream"));
211
- const p = new URL(import.meta.url);
212
- p.pathname = "", p.search = "", p.hash = "";
213
- const S = new URL(r, p.toString());
214
- let f = i.body;
215
- f && new URL(S).protocol === "http:" && (f = await new Response(f).arrayBuffer());
216
- const C = await w(i, {
217
- url: `${r}${a.url}`,
218
- headers: l,
219
- body: f,
220
- ...U && { credentials: "include" }
221
- }), y = await fetch(C);
222
- if (!y.headers.has(O))
223
- throw new I(
224
- a.url,
225
+ const u = new Headers(s.headers), h = ((l = u.get("x-cors-proxy-allowed-request-headers")) == null ? void 0 : l.split(",")) || [], f = h.includes("authorization") || h.includes("cookie"), m = u.get("content-type");
226
+ m && m.toLowerCase().includes("multipart/form-data") && (u.set("x-cors-proxy-content-type", m), u.set("content-type", "application/octet-stream"));
227
+ let d = null;
228
+ const R = s.method.toUpperCase();
229
+ R !== "GET" && R !== "HEAD" && (await q() ? d = i.body : d = await i.arrayBuffer()), d instanceof ReadableStream && new URL(o, import.meta.url).protocol === "http:" && (d = await new Response(d).arrayBuffer());
230
+ const T = await b(s, {
231
+ url: `${o}${s.url}`,
232
+ headers: u,
233
+ body: d,
234
+ ...f && { credentials: "include" }
235
+ }), y = await fetch(T);
236
+ if (!y.headers.has(I))
237
+ throw new H(
238
+ s.url,
225
239
  y.status,
226
240
  y.statusText
227
241
  );
@@ -229,16 +243,17 @@ async function M(e, t, r, n) {
229
243
  }
230
244
  }
231
245
  export {
232
- I as FirewallInterferenceError,
246
+ H as FirewallInterferenceError,
247
+ $ as __testing,
233
248
  P as awaitReply,
234
- A as broadcastMessageExpectReply,
235
- w as cloneRequest,
236
- v as convertFetchEventToPHPRequest,
249
+ x as broadcastMessageExpectReply,
250
+ b as cloneRequest,
251
+ _ as convertFetchEventToPHPRequest,
237
252
  M as fetchWithCorsProxy,
238
- L as getNextRequestId,
239
- B as getRequestHeaders,
240
- j as postMessageExpectReply,
241
- q as removeContentSecurityPolicyDirective,
242
- k as responseTo,
243
- H as teeRequest
253
+ E as getNextRequestId,
254
+ k as getRequestHeaders,
255
+ D as postMessageExpectReply,
256
+ A as removeContentSecurityPolicyDirective,
257
+ v as responseTo,
258
+ q as supportsReadableStreamBody
244
259
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/web-service-worker",
3
- "version": "3.1.19",
3
+ "version": "3.1.21",
4
4
  "description": "PHP.wasm – service worker utils",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,15 +31,15 @@
31
31
  "main": "./index.cjs",
32
32
  "module": "./index.js",
33
33
  "license": "GPL-2.0-or-later",
34
- "gitHead": "be542ee28a5966eeb28154cd8e3723db5ff9df07",
34
+ "gitHead": "5864051cbf4c2a55656112d99a3f1b076bcd67cd",
35
35
  "engines": {
36
36
  "node": ">=20.10.0",
37
37
  "npm": ">=10.2.3"
38
38
  },
39
39
  "dependencies": {
40
40
  "ini": "4.1.2",
41
- "@php-wasm/scopes": "3.1.19",
42
- "@php-wasm/universal": "3.1.19"
41
+ "@php-wasm/scopes": "3.1.21",
42
+ "@php-wasm/universal": "3.1.21"
43
43
  },
44
44
  "packageManager": "npm@10.9.2",
45
45
  "overrides": {
@@ -51,6 +51,7 @@
51
51
  "tmp": "0.2.5",
52
52
  "form-data": "^4.0.4",
53
53
  "lodash": "^4.17.23",
54
- "glob": "^9.3.0"
54
+ "glob": "^9.3.0",
55
+ "webpackbar": "^7.0.0"
55
56
  }
56
57
  }
package/utils.d.ts CHANGED
@@ -34,14 +34,20 @@ export declare function broadcastMessageExpectReply(message: any, scope: string)
34
34
  * @returns The new request.
35
35
  */
36
36
  export declare function cloneRequest(request: Request, overrides: Record<string, any>): Promise<Request>;
37
+ /** @internal Test-only utilities — not part of the public API. */
38
+ export declare const __testing: {
39
+ resetStreamBodySupported(): void;
40
+ };
37
41
  /**
38
- * Tee a request to ensure the body stream is not consumed
39
- * when executing or cloning the request.
42
+ * Detects whether the browser supports passing a ReadableStream as the body
43
+ * of a fetch() request. The result is probed once (via a `data:` URL) and
44
+ * cached for the lifetime of the page.
40
45
  *
41
- * @param request
42
- * @returns
46
+ * - Chrome: supported (with `duplex: 'half'`).
47
+ * - Safari: throws `NotSupportedError: ReadableStream uploading is not supported`.
48
+ * - Firefox: the probe fetch itself may fail; `request.body` is not even exposed.
43
49
  */
44
- export declare function teeRequest(request: Request): Promise<[Request, Request]>;
50
+ export declare function supportsReadableStreamBody(): Promise<boolean>;
45
51
  /**
46
52
  * Extracts headers from a Request as a plain key->value JS object.
47
53
  *