@php-wasm/web-service-worker 3.0.22 → 3.0.31

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/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("@php-wasm/scopes"),R=25e3;let g=0;function m(e,t,...s){const r=u();return e.postMessage({...t,requestId:r},...s),r}function u(){return++g}function h(e,t,s=R){return new Promise((r,c)=>{const o=a=>{a.data.type==="response"&&a.data.requestId===t&&(e.removeEventListener("message",o),clearTimeout(l),r(a.data.response))},l=setTimeout(()=>{c(new Error("Request timed out")),e.removeEventListener("message",o)},s);e.addEventListener("message",o)})}function w(e,t){return{type:"response",requestId:e,response:t}}async function E(e){let t=new URL(e.request.url);if(!d.isURLScoped(t))try{const n=new URL(e.request.referrer);t=d.setURLScope(t,d.getURLScope(n))}catch{}const s=e.request.headers.get("content-type"),r=e.request.method==="POST"?new Uint8Array(await e.request.clone().arrayBuffer()):void 0,c={};for(const n of e.request.headers.entries())c[n[0]]=n[1];let o;try{const n={method:"request",args:[{body:r,url:t.toString(),method:e.request.method,headers:{...c,Host:t.host,"User-agent":self.navigator.userAgent,"Content-type":s}}]},p=d.getURLScope(t);if(p===null)throw new Error(`The URL ${t.toString()} is not scoped. This should not happen.`);const f=await y(n,p);o=await h(self,f),delete o.headers["x-frame-options"]}catch(n){throw console.error(n,{url:t.toString()}),n}if(o.httpStatusCode>=300&&o.httpStatusCode<=399&&o.headers.location)return Response.redirect(new URL(o.headers.location[0],t.toString()),o.httpStatusCode);const a=[101,103,204,205,304].includes(o.httpStatusCode)?null:o.bytes;return new Response(a,{headers:o.headers,status:o.httpStatusCode})}async function y(e,t){const s=u();for(const r of await self.clients.matchAll({includeUncontrolled:!0}))r.postMessage({...e,scope:t,requestId:s});return s}async function i(e,t){const s=["GET","HEAD"].includes(e.method)||"body"in t?void 0:await e.blob();return new Request(t.url||e.url,{body:s,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,...t})}async function S(e){if(!e.body)return[e,e];const[t,s]=e.body.tee();return[await i(e,{body:t,duplex:"half"}),await i(e,{body:s,duplex:"half"})]}function b(e){const t={};return e.headers.forEach((s,r)=>{t[r]=s}),t}exports.awaitReply=h;exports.broadcastMessageExpectReply=y;exports.cloneRequest=i;exports.convertFetchEventToPHPRequest=E;exports.getNextRequestId=u;exports.getRequestHeaders=b;exports.postMessageExpectReply=m;exports.responseTo=w;exports.teeRequest=S;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("@php-wasm/scopes"),w=25e3;let S=0;function b(e,t,...s){const r=p();return e.postMessage({...t,requestId:r},...s),r}function p(){return++S}function f(e,t,s=w){return new Promise((r,i)=>{const o=c=>{c.data.type==="response"&&c.data.requestId===t&&(e.removeEventListener("message",o),clearTimeout(a),r(c.data.response))},a=setTimeout(()=>{i(new Error("Request timed out")),e.removeEventListener("message",o)},s);e.addEventListener("message",o)})}function E(e,t){return{type:"response",requestId:e,response:t}}async function C(e){let t=new URL(e.request.url);if(!d.isURLScoped(t))try{const n=new URL(e.request.referrer);t=d.setURLScope(t,d.getURLScope(n))}catch{}const s=e.request.headers.get("content-type"),r=e.request.method==="POST"?new Uint8Array(await e.request.clone().arrayBuffer()):void 0,i={};for(const n of e.request.headers.entries())i[n[0]]=n[1];let o;try{const n={method:"request",args:[{body:r,url:t.toString(),method:e.request.method,headers:{...i,Host:t.host,"User-agent":self.navigator.userAgent,"Content-type":s}}]},y=d.getURLScope(t);if(y===null)throw new Error(`The URL ${t.toString()} is not scoped. This should not happen.`);const R=await g(n,y);if(o=await f(self,R),delete o.headers["x-frame-options"],o.headers["content-security-policy"]){const h=o.headers["content-security-policy"].map(u=>m("frame-ancestors",u)).filter(u=>u.trim().length>0);h.length>0?o.headers["content-security-policy"]=h:delete o.headers["content-security-policy"]}}catch(n){throw console.error(n,{url:t.toString()}),n}if(o.httpStatusCode>=300&&o.httpStatusCode<=399&&o.headers.location)return Response.redirect(new URL(o.headers.location[0],t.toString()),o.httpStatusCode);const c=[101,103,204,205,304].includes(o.httpStatusCode)?null:o.bytes;return new Response(c,{headers:o.headers,status:o.httpStatusCode})}async function g(e,t){const s=p();for(const r of await self.clients.matchAll({includeUncontrolled:!0}))r.postMessage({...e,scope:t,requestId:s});return s}async function l(e,t){let s;return["GET","HEAD"].includes(e.method)||"body"in t?s=void 0:!e.bodyUsed&&e.body?s=e.body:s=await e.blob(),new Request(t.url||e.url,{body:s,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,...s&&{duplex:"half"},...t})}async function U(e){if(!e.body)return[e,e];const[t,s]=e.body.tee();return[await l(e,{body:t,duplex:"half"}),await l(e,{body:s,duplex:"half"})]}function L(e){const t={};return e.headers.forEach((s,r)=>{t[r]=s}),t}function m(e,t){const s=/^[\u{9}\u{A}\u{C}\u{D}\u{20}]+/u,r=/[\u{9}\u{A}\u{C}\u{D}\u{20}]+$/u,i=/[\u{9}\u{A}\u{C}\u{D}\u{20}]/u;return t.split(";").filter(o=>{const a=o.replace(s,"").replace(r,""),[c]=a.split(i,1);return c.toLowerCase()!==e.toLowerCase()}).join(";")}exports.awaitReply=f;exports.broadcastMessageExpectReply=g;exports.cloneRequest=l;exports.convertFetchEventToPHPRequest=C;exports.getNextRequestId=p;exports.getRequestHeaders=L;exports.postMessageExpectReply=b;exports.removeContentSecurityPolicyDirective=m;exports.responseTo=E;exports.teeRequest=U;
package/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { isURLScoped as f, setURLScope as y, getURLScope as l } from "@php-wasm/scopes";
2
- const m = 25e3;
3
- let R = 0;
4
- function S(e, t, ...r) {
5
- const s = p();
1
+ import { isURLScoped as m, setURLScope as g, getURLScope as p } from "@php-wasm/scopes";
2
+ const R = 25e3;
3
+ let w = 0;
4
+ function U(e, t, ...r) {
5
+ const s = y();
6
6
  return e.postMessage(
7
7
  {
8
8
  ...t,
@@ -11,32 +11,32 @@ function S(e, t, ...r) {
11
11
  ...r
12
12
  ), s;
13
13
  }
14
- function p() {
15
- return ++R;
14
+ function y() {
15
+ return ++w;
16
16
  }
17
- function g(e, t, r = m) {
17
+ function b(e, t, r = R) {
18
18
  return new Promise((s, c) => {
19
- const o = (a) => {
20
- a.data.type === "response" && a.data.requestId === t && (e.removeEventListener("message", o), clearTimeout(d), s(a.data.response));
21
- }, d = setTimeout(() => {
19
+ const o = (i) => {
20
+ i.data.type === "response" && i.data.requestId === t && (e.removeEventListener("message", o), clearTimeout(a), s(i.data.response));
21
+ }, a = setTimeout(() => {
22
22
  c(new Error("Request timed out")), e.removeEventListener("message", o);
23
23
  }, r);
24
24
  e.addEventListener("message", o);
25
25
  });
26
26
  }
27
- function b(e, t) {
27
+ function L(e, t) {
28
28
  return {
29
29
  type: "response",
30
30
  requestId: e,
31
31
  response: t
32
32
  };
33
33
  }
34
- async function U(e) {
34
+ async function A(e) {
35
35
  let t = new URL(e.request.url);
36
- if (!f(t))
36
+ if (!m(t))
37
37
  try {
38
38
  const n = new URL(e.request.referrer);
39
- t = y(t, l(n));
39
+ t = g(t, p(n));
40
40
  } catch {
41
41
  }
42
42
  const r = e.request.headers.get("content-type"), s = e.request.method === "POST" ? new Uint8Array(await e.request.clone().arrayBuffer()) : void 0, c = {};
@@ -61,13 +61,21 @@ async function U(e) {
61
61
  }
62
62
  }
63
63
  ]
64
- }, i = l(t);
65
- if (i === null)
64
+ }, u = p(t);
65
+ if (u === null)
66
66
  throw new Error(
67
67
  `The URL ${t.toString()} is not scoped. This should not happen.`
68
68
  );
69
- const h = await w(n, i);
70
- o = await g(self, h), delete o.headers["x-frame-options"];
69
+ const f = await S(n, u);
70
+ if (o = await b(self, f), delete o.headers["x-frame-options"], o.headers["content-security-policy"]) {
71
+ const l = o.headers["content-security-policy"].map(
72
+ (d) => C(
73
+ "frame-ancestors",
74
+ d
75
+ )
76
+ ).filter((d) => d.trim().length > 0);
77
+ l.length > 0 ? o.headers["content-security-policy"] = l : delete o.headers["content-security-policy"];
78
+ }
71
79
  } catch (n) {
72
80
  throw console.error(n, { url: t.toString() }), n;
73
81
  }
@@ -76,16 +84,16 @@ async function U(e) {
76
84
  new URL(o.headers.location[0], t.toString()),
77
85
  o.httpStatusCode
78
86
  );
79
- const a = [101, 103, 204, 205, 304].includes(
87
+ const i = [101, 103, 204, 205, 304].includes(
80
88
  o.httpStatusCode
81
89
  ) ? null : o.bytes;
82
- return new Response(a, {
90
+ return new Response(i, {
83
91
  headers: o.headers,
84
92
  status: o.httpStatusCode
85
93
  });
86
94
  }
87
- async function w(e, t) {
88
- const r = p();
95
+ async function S(e, t) {
96
+ const r = y();
89
97
  for (const s of await self.clients.matchAll({
90
98
  // Sometimes the client that triggered the current fetch()
91
99
  // event is considered uncontrolled in Google Chrome. This
@@ -107,9 +115,9 @@ async function w(e, t) {
107
115
  });
108
116
  return r;
109
117
  }
110
- async function u(e, t) {
111
- const r = ["GET", "HEAD"].includes(e.method) || "body" in t ? void 0 : await e.blob();
112
- return new Request(t.url || e.url, {
118
+ async function h(e, t) {
119
+ let r;
120
+ return ["GET", "HEAD"].includes(e.method) || "body" in t ? r = void 0 : !e.bodyUsed && e.body ? r = e.body : r = await e.blob(), new Request(t.url || e.url, {
113
121
  body: r,
114
122
  method: e.method,
115
123
  headers: e.headers,
@@ -120,32 +128,45 @@ async function u(e, t) {
120
128
  cache: e.cache,
121
129
  redirect: e.redirect,
122
130
  integrity: e.integrity,
131
+ ...r && { duplex: "half" },
123
132
  ...t
124
133
  });
125
134
  }
126
- async function L(e) {
135
+ async function T(e) {
127
136
  if (!e.body)
128
137
  return [e, e];
129
138
  const [t, r] = e.body.tee();
130
139
  return [
131
- await u(e, { body: t, duplex: "half" }),
132
- await u(e, { body: r, duplex: "half" })
140
+ await h(e, { body: t, duplex: "half" }),
141
+ await h(e, { body: r, duplex: "half" })
133
142
  ];
134
143
  }
135
- function T(e) {
144
+ function x(e) {
136
145
  const t = {};
137
146
  return e.headers.forEach((r, s) => {
138
147
  t[s] = r;
139
148
  }), t;
140
149
  }
150
+ function C(e, t) {
151
+ const r = /^[\u{9}\u{A}\u{C}\u{D}\u{20}]+/u, s = /[\u{9}\u{A}\u{C}\u{D}\u{20}]+$/u, c = /[\u{9}\u{A}\u{C}\u{D}\u{20}]/u;
152
+ return t.split(";").filter((o) => {
153
+ const a = o.replace(r, "").replace(s, ""), [i] = a.split(
154
+ c,
155
+ // The directive name is the first token.
156
+ 1
157
+ );
158
+ return i.toLowerCase() !== e.toLowerCase();
159
+ }).join(";");
160
+ }
141
161
  export {
142
- g as awaitReply,
143
- w as broadcastMessageExpectReply,
144
- u as cloneRequest,
145
- U as convertFetchEventToPHPRequest,
146
- p as getNextRequestId,
147
- T as getRequestHeaders,
148
- S as postMessageExpectReply,
149
- b as responseTo,
150
- L as teeRequest
162
+ b as awaitReply,
163
+ S as broadcastMessageExpectReply,
164
+ h as cloneRequest,
165
+ A as convertFetchEventToPHPRequest,
166
+ y as getNextRequestId,
167
+ x as getRequestHeaders,
168
+ U as postMessageExpectReply,
169
+ C as removeContentSecurityPolicyDirective,
170
+ L as responseTo,
171
+ T as teeRequest
151
172
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/web-service-worker",
3
- "version": "3.0.22",
3
+ "version": "3.0.31",
4
4
  "description": "PHP.wasm – service worker utils",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,7 +31,7 @@
31
31
  "main": "./index.cjs",
32
32
  "module": "./index.js",
33
33
  "license": "GPL-2.0-or-later",
34
- "gitHead": "a624d1a97dc639e152d335e6a801b2fad7f6b594",
34
+ "gitHead": "e28b6d2a2e663abc3cbb8fce9a3c5cc8abaa5bbe",
35
35
  "engines": {
36
36
  "node": ">=20.18.3",
37
37
  "npm": ">=10.1.0"
@@ -42,13 +42,13 @@
42
42
  "react": "18.3.1",
43
43
  "react-dom": "18.3.1",
44
44
  "typescript": "5.4.5",
45
- "@playwright/test": "1.47.1",
46
- "ws": "^8.18.0",
45
+ "@playwright/test": "1.55.1",
46
+ "ws": "8.18.3",
47
47
  "tmp": "0.2.5",
48
48
  "form-data": "^4.0.4"
49
49
  },
50
50
  "dependencies": {
51
- "@php-wasm/scopes": "3.0.22"
51
+ "@php-wasm/scopes": "3.0.31"
52
52
  },
53
53
  "optionalDependencies": {
54
54
  "fs-ext": "2.1.1"
package/utils.d.ts CHANGED
@@ -49,3 +49,11 @@ export declare function teeRequest(request: Request): Promise<[Request, Request]
49
49
  * @returns
50
50
  */
51
51
  export declare function getRequestHeaders(request: Request): Record<string, string>;
52
+ /**
53
+ * Removes the specified directive from the Content-Security-Policy header value.
54
+ *
55
+ * @param directiveToRemove The directive name to remove.
56
+ * @param cspHeader The Content-Security-Policy header value to filter.
57
+ * @returns The filtered Content-Security-Policy header value.
58
+ */
59
+ export declare function removeContentSecurityPolicyDirective(directiveToRemove: string, cspHeader: string): string;