@wp-playground/client 0.1.49 → 0.1.56
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/blueprint-schema.json +4 -30
- package/index.cjs +23 -30
- package/index.d.ts +10 -20
- package/index.js +317 -341
- package/package.json +2 -2
package/blueprint-schema.json
CHANGED
|
@@ -244,37 +244,11 @@
|
|
|
244
244
|
"type": "object",
|
|
245
245
|
"additionalProperties": {},
|
|
246
246
|
"description": "The constants to define"
|
|
247
|
-
}
|
|
248
|
-
},
|
|
249
|
-
"required": [
|
|
250
|
-
"consts",
|
|
251
|
-
"step"
|
|
252
|
-
]
|
|
253
|
-
},
|
|
254
|
-
{
|
|
255
|
-
"type": "object",
|
|
256
|
-
"additionalProperties": false,
|
|
257
|
-
"properties": {
|
|
258
|
-
"progress": {
|
|
259
|
-
"type": "object",
|
|
260
|
-
"properties": {
|
|
261
|
-
"weight": {
|
|
262
|
-
"type": "number"
|
|
263
|
-
},
|
|
264
|
-
"caption": {
|
|
265
|
-
"type": "string"
|
|
266
|
-
}
|
|
267
|
-
},
|
|
268
|
-
"additionalProperties": false
|
|
269
247
|
},
|
|
270
|
-
"
|
|
271
|
-
"type": "
|
|
272
|
-
"
|
|
273
|
-
|
|
274
|
-
"consts": {
|
|
275
|
-
"type": "object",
|
|
276
|
-
"additionalProperties": {},
|
|
277
|
-
"description": "The constants to define"
|
|
248
|
+
"virtualize": {
|
|
249
|
+
"type": "boolean",
|
|
250
|
+
"description": "Enables the virtualization of wp-config.php and playground-consts.json files, leaving the local system files untouched. The variables defined in the /vfs-blueprints/playground-consts.json file are loaded via the auto_prepend_file directive in the php.ini file.",
|
|
251
|
+
"default": false
|
|
278
252
|
}
|
|
279
253
|
},
|
|
280
254
|
"required": [
|
package/index.cjs
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const fe=async(t,{pluginPath:e},r)=>{r?.tracker.setCaption(`Activating ${e}`);const s=[`${t.documentRoot}/wp-load.php`,`${t.documentRoot}/wp-admin/includes/plugin.php`];if(!s.every(i=>t.fileExists(i)))throw new Error(`Required WordPress files do not exist: ${s.join(", ")}`);await t.run({code:`<?php
|
|
2
2
|
${s.map(i=>`require_once( '${i}' );`).join(`
|
|
3
3
|
`)}
|
|
4
4
|
activate_plugin('${e}');
|
|
5
|
-
`})},
|
|
5
|
+
`})},me=async(t,{themeFolderName:e},r)=>{r?.tracker.setCaption(`Activating ${e}`);const s=`${t.documentRoot}/wp-load.php`;if(!t.fileExists(s))throw new Error(`Required WordPress file does not exist: ${s}`);await t.run({code:`<?php
|
|
6
6
|
require_once( '${s}' );
|
|
7
7
|
switch_theme( '${e}' );
|
|
8
|
-
`})};function F(t){return new DOMParser().parseFromString(t.text,"text/html")}function A(t){const e=t.split(".").shift().replace("-"," ");return e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()}async function
|
|
8
|
+
`})};function F(t){return new DOMParser().parseFromString(t.text,"text/html")}function A(t){const e=t.split(".").shift().replace("-"," ");return e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()}async function v(t,e,r){let s="";await t.fileExists(e)&&(s=await t.readFileAsText(e)),await t.writeFile(e,r(s))}async function st(t){return new Uint8Array(await t.arrayBuffer())}const we=async(t,e)=>{const r=new nt(t,e.siteUrl,e.wordpressPath||"/wordpress");e.patchSqlitePlugin!==!1&&await r.patchSqlitePlugin(),e.addPhpInfo!==!1&&await r.addPhpInfo(),e.patchSiteUrl!==!1&&await r.patchSiteUrl(),e.disableSiteHealth!==!1&&await r.disableSiteHealth(),e.disableWpNewBlogNotification!==!1&&await r.disableWpNewBlogNotification()};class nt{constructor(e,r,s){this.php=e,this.scopedSiteUrl=r,this.wordpressPath=s}async patchSqlitePlugin(){await v(this.php,`${this.wordpressPath}/wp-content/plugins/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php`,e=>e.replace("if ( false === strtotime( $value ) )",'if ( $value === "0000-00-00 00:00:00" || false === strtotime( $value ) )'))}async addPhpInfo(){await this.php.writeFile(`${this.wordpressPath}/phpinfo.php`,"<?php phpinfo(); ")}async patchSiteUrl(){await v(this.php,`${this.wordpressPath}/wp-config.php`,e=>`<?php
|
|
9
9
|
if(!defined('WP_HOME')) {
|
|
10
10
|
define('WP_HOME', "${this.scopedSiteUrl}");
|
|
11
11
|
define('WP_SITEURL', "${this.scopedSiteUrl}");
|
|
12
12
|
}
|
|
13
|
-
?>${e}`)}async disableSiteHealth(){await
|
|
14
|
-
$consts = json_decode(file_get_contents('
|
|
13
|
+
?>${e}`)}async disableSiteHealth(){await v(this.php,`${this.wordpressPath}/wp-includes/default-filters.php`,e=>e.replace(/add_filter[^;]+wp_maybe_grant_site_health_caps[^;]+;/i,""))}async disableWpNewBlogNotification(){await v(this.php,`${this.wordpressPath}/wp-config.php`,e=>`${e} function wp_new_blog_notification(...$args){} `)}}const ge=async(t,{code:e})=>await t.run({code:e}),ye=async(t,{options:e})=>await t.run(e),Pe=async(t,{key:e,value:r})=>{await t.setPhpIniEntry(e,r)},be=async(t,{request:e})=>await t.request(e),_e=async(t,{fromPath:e,toPath:r})=>{await t.writeFile(r,await t.readFileAsBuffer(e))},$e=async(t,{fromPath:e,toPath:r})=>{await t.mv(e,r)},Ee=async(t,{path:e})=>{await t.mkdir(e)},Se=async(t,{path:e})=>{await t.unlink(e)},ve=async(t,{path:e})=>{await t.rmdir(e)},Re=async(t,{path:e,data:r})=>{r instanceof File&&(r=await st(r)),await t.writeFile(e,r)},J="/vfs-blueprints",q=async(t,{consts:e,virtualize:r=!1})=>{const s=await t.documentRoot,n=r?J:s,i=`${n}/playground-consts.json`,o=`${n}/wp-config.php`;return r&&(t.mkdir(J),t.setPhpIniEntry("auto_prepend_file",o)),await v(t,i,a=>JSON.stringify({...JSON.parse(a||"{}"),...e})),await v(t,o,a=>a.includes("playground-consts.json")?a:`<?php
|
|
14
|
+
$consts = json_decode(file_get_contents('${i}'), true);
|
|
15
15
|
foreach ($consts as $const => $value) {
|
|
16
16
|
if (!defined($const)) {
|
|
17
17
|
define($const, $value);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
?>${
|
|
20
|
+
?>${a}`),o},xe=async(t,{siteUrl:e})=>await q(t,{consts:{WP_HOME:e,WP_SITEURL:e}});class Te{constructor({concurrency:e}){this._running=0,this.concurrency=e,this.queue=[]}get running(){return this._running}async acquire(){for(;;)if(this._running>=this.concurrency)await new Promise(e=>this.queue.push(e));else return this._running++,()=>{this._running--,this.queue.length>0&&this.queue.shift()()}}async run(e){const r=await this.acquire();try{return await e()}finally{r()}}}const it=Symbol("literal");function _(t){if(typeof t=="string")return t.startsWith("$")?t:JSON.stringify(t);if(typeof t=="number")return t.toString();if(Array.isArray(t))return`array(${t.map(_).join(", ")})`;if(t===null)return"null";if(typeof t=="object")return it in t?t.toString():`array(${Object.entries(t).map(([r,s])=>`${JSON.stringify(r)} => ${_(s)}`).join(", ")})`;if(typeof t=="function")return t();throw new Error(`Unsupported value: ${t}`)}function U(t){const e={};for(const r in t)e[r]=_(t[r]);return e}const K=`<?php
|
|
21
21
|
|
|
22
22
|
function zipDir($dir, $output, $additionalFiles = array())
|
|
23
23
|
{
|
|
@@ -79,39 +79,32 @@ function delTree($dir)
|
|
|
79
79
|
}
|
|
80
80
|
return rmdir($dir);
|
|
81
81
|
}
|
|
82
|
-
`;async function
|
|
82
|
+
`;async function Ce(t){const e="wordpress-playground.zip",r=`/${e}`,s=U({zipPath:r,documentRoot:await t.documentRoot});await Oe(t,`zipDir(${s.documentRoot}, ${s.zipPath});`);const n=await t.readFileAsBuffer(r);return t.unlink(r),new File([n],e)}const Fe=async(t,{fullSiteZip:e})=>{const r="/import.zip";await t.writeFile(r,new Uint8Array(await e.arrayBuffer()));const s=await t.absoluteUrl,n=await t.documentRoot;await t.rmdir(n),await z(t,{zipPath:r,extractToPath:"/"});const i=U({absoluteUrl:s});await at(t,`${n}/wp-config.php`,o=>`<?php
|
|
83
83
|
if(!defined('WP_HOME')) {
|
|
84
84
|
define('WP_HOME', ${i.absoluteUrl});
|
|
85
85
|
define('WP_SITEURL', ${i.absoluteUrl});
|
|
86
86
|
}
|
|
87
|
-
?>${o}`)},
|
|
87
|
+
?>${o}`)},z=async(t,{zipPath:e,extractToPath:r})=>{const s=U({zipPath:e,extractToPath:r});await Oe(t,`unzip(${s.zipPath}, ${s.extractToPath});`)},ke=async(t,{file:e})=>{const r=await t.request({url:"/wp-admin/admin.php?import=wordpress"}),s=Q(r).getElementById("import-upload-form")?.getAttribute("action"),n=await t.request({url:`/wp-admin/${s}`,method:"POST",files:{import:e}}),i=Q(n).querySelector("#wpbody-content form");if(!i)throw console.log(n.text),new Error("Could not find an importer form in response. See the response text above for details.");const o=ot(i);o.fetch_attachments="1";for(const a in o)if(a.startsWith("user_map[")){const l="user_new["+a.slice(9,-1)+"]";o[l]="1"}await t.request({url:i.action,method:"POST",formData:o})};function Q(t){return new DOMParser().parseFromString(t.text,"text/html")}function ot(t){return Object.fromEntries(new FormData(t).entries())}async function at(t,e,r){await t.writeFile(e,r(await t.readFileAsText(e)))}async function Oe(t,e){const r=await t.run({code:K+e});if(r.exitCode!==0)throw console.log(K+e),console.log(e+""),console.log(r.errors),r.errors;return r}const Le=async(t,{pluginZipFile:e,options:r={}},s)=>{s?.tracker.setCaption(`Installing the ${A(e?.name)} plugin`);try{const n="activate"in r?r.activate:!0,i=await t.request({url:"/wp-admin/plugin-install.php?tab=upload"}),o=F(i),a=new FormData(o.querySelector(".wp-upload-form")),{pluginzip:l,...c}=Object.fromEntries(a.entries()),u=await t.request({url:"/wp-admin/update.php?action=upload-plugin",method:"POST",formData:c,files:{pluginzip:e}});if(n){const p=F(u).querySelector("#wpbody-content .button.button-primary").attributes.getNamedItem("href").value,y=new URL(p,await t.pathToInternalUrl("/wp-admin/")).toString();await t.request({url:y})}await t.isDir("/wordpress/wp-content/plugins/gutenberg")&&!await t.fileExists("/wordpress/.gutenberg-patched")&&(await t.writeFile("/wordpress/.gutenberg-patched","1"),await X(t,"/wordpress/wp-content/plugins/gutenberg/build/block-editor/index.js",d=>d.replace(/srcDoc:("[^"]+"|[^,]+)/g,'src:"/wp-includes/empty.html"')),await X(t,"/wordpress/wp-content/plugins/gutenberg/build/block-editor/index.min.js",d=>d.replace(/srcDoc:("[^"]+"|[^,]+)/g,'src:"/wp-includes/empty.html"')))}catch(n){console.error(`Proceeding without the ${e.name} theme. Could not install it in wp-admin. The original error was: ${n}`),console.error(n)}};async function X(t,e,r){return await t.writeFile(e,r(await t.readFileAsText(e)))}const Ae=async(t,{themeZipFile:e,options:r={}},s)=>{s?.tracker.setCaption(`Installing the ${A(e.name)} theme`);try{const n="activate"in r?r.activate:!0,i=await t.request({url:"/wp-admin/theme-install.php"}),o=F(i),a=new FormData(o.querySelector(".wp-upload-form")),{themezip:l,...c}=Object.fromEntries(a.entries()),u=await t.request({url:"/wp-admin/update.php?action=upload-theme",method:"POST",formData:c,files:{themezip:e}});if(n){const d=F(u),p=d.querySelector("#wpbody-content > .wrap");if(p?.textContent?.includes("Theme installation failed.")){console.error(p?.textContent);return}const y=d.querySelector("#wpbody-content .activatelink, .update-from-upload-actions .button.button-primary");if(!y){console.error('The "activate" button was not found.');return}const tt=y.attributes.getNamedItem("href").value,rt=new URL(tt,await t.pathToInternalUrl("/wp-admin/")).toString();await t.request({url:rt})}}catch(n){console.error(`Proceeding without the ${e.name} theme. Could not install it in wp-admin. The original error was: ${n}`),console.error(n)}},Ue=async(t,{username:e="admin",password:r="password"}={},s)=>{s?.tracker.setCaption(s?.initialCaption||"Logging in"),await t.request({url:"/wp-login.php"}),await t.request({url:"/wp-login.php",method:"POST",formData:{log:e,pwd:r,rememberme:"forever"}})},He=async(t,{options:e})=>{await t.request({url:"/wp-admin/install.php?step=2",method:"POST",formData:{language:"en",prefix:"wp_",weblog_title:"My WordPress Website",user_name:e.adminPassword||"admin",admin_password:e.adminPassword||"password",admin_password2:e.adminPassword||"password",Submit:"Install WordPress",pw_weak:"1",admin_email:"admin@localhost.com"}})},Ie=async(t,{options:e})=>{const r=`<?php
|
|
88
88
|
include 'wordpress/wp-load.php';
|
|
89
|
-
$site_options = ${
|
|
89
|
+
$site_options = ${_(e)};
|
|
90
90
|
foreach($site_options as $name => $value) {
|
|
91
91
|
update_option($name, $value);
|
|
92
92
|
}
|
|
93
93
|
echo "Success";
|
|
94
|
-
`,s=await t.run({code:r});return Me(s),{code:r,result:s}},
|
|
94
|
+
`,s=await t.run({code:r});return Me(s),{code:r,result:s}},We=async(t,{meta:e,userId:r})=>{const s=`<?php
|
|
95
95
|
include 'wordpress/wp-load.php';
|
|
96
|
-
$meta = ${
|
|
96
|
+
$meta = ${_(e)};
|
|
97
97
|
foreach($meta as $name => $value) {
|
|
98
|
-
update_user_meta(${
|
|
98
|
+
update_user_meta(${_(r)}, $name, $value);
|
|
99
99
|
}
|
|
100
100
|
echo "Success";
|
|
101
|
-
`,n=await t.run({code:s});return Me(n),{code:s,result:n}};async function Me(t){if(t.text!=="Success")throw console.log(t),new Error(`Failed to run code: ${t.text} ${t.errors}`)}const
|
|
102
|
-
$consts = json_decode(file_get_contents('${r}'), true);
|
|
103
|
-
foreach ($consts as $const => $value) {
|
|
104
|
-
if (!defined($const)) {
|
|
105
|
-
define($const, $value);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
?>${s}`),K},ut=Object.freeze(Object.defineProperty({__proto__:null,activatePlugin:me,activateTheme:ge,applyWordPressPatches:we,cp:$e,defineSiteUrl:Te,defineVirtualWpConfigConsts:ze,defineWpConfigConsts:D,importFile:Oe,installPlugin:Ae,installTheme:Ue,login:He,mkdir:Se,mv:Ee,replaceSite:ke,request:_e,rm:ve,rmdir:Re,runPHP:ye,runPHPWithOptions:Pe,runWpInstallationWizard:Ie,setPhpIniEntry:be,setSiteOptions:We,unzip:q,updateUserMeta:Ne,writeFile:xe,zipEntireSite:Fe},Symbol.toStringTag,{value:"Module"})),ht=5*1024*1024;function dt(t,e){const r=t.headers.get("content-length")||"",s=parseInt(r,10)||ht;function n(i,o){e(new CustomEvent("progress",{detail:{loaded:i,total:o}}))}return new Response(new ReadableStream({async start(i){if(!t.body){i.close();return}const o=t.body.getReader();let a=0;for(;;)try{const{done:l,value:c}=await o.read();if(c&&(a+=c.byteLength),l){n(a,a),i.close();break}else n(a,s),i.enqueue(c)}catch(l){console.error({e:l}),i.error(l);break}}}),{status:t.status,statusText:t.statusText,headers:t.headers})}const W=1e-5;class H extends EventTarget{constructor({weight:e=1,caption:r="",fillTime:s=4}={}){super(),this._selfWeight=1,this._selfDone=!1,this._selfProgress=0,this._selfCaption="",this._isFilling=!1,this._subTrackers=[],this._weight=e,this._selfCaption=r,this._fillTime=s}stage(e,r=""){if(e||(e=this._selfWeight),this._selfWeight-e<-W)throw new Error(`Cannot add a stage with weight ${e} as the total weight of registered stages would exceed 1.`);this._selfWeight-=e;const s=new H({caption:r,weight:e,fillTime:this._fillTime});return this._subTrackers.push(s),s.addEventListener("progress",()=>this.notifyProgress()),s.addEventListener("done",()=>{this.done&&this.notifyDone()}),s}fillSlowly({stopBeforeFinishing:e=!0}={}){if(this._isFilling)return;this._isFilling=!0;const r=100,s=this._fillTime/r;this._fillInterval=setInterval(()=>{this.set(this._selfProgress+1),e&&this._selfProgress>=99&&clearInterval(this._fillInterval)},s)}set(e){this._selfProgress=Math.min(e,100),this.notifyProgress(),this._selfProgress+W>=100&&this.finish()}finish(){this._fillInterval&&clearInterval(this._fillInterval),this._selfDone=!0,this._selfProgress=100,this._isFilling=!1,this._fillInterval=void 0,this.notifyProgress(),this.notifyDone()}get caption(){for(let e=this._subTrackers.length-1;e>=0;e--)if(!this._subTrackers[e].done){const r=this._subTrackers[e].caption;if(r)return r}return this._selfCaption}setCaption(e){this._selfCaption=e,this.notifyProgress()}get done(){return this.progress+W>=100}get progress(){if(this._selfDone)return 100;const e=this._subTrackers.reduce((r,s)=>r+s.progress*s.weight,this._selfProgress*this._selfWeight);return Math.round(e*1e4)/1e4}get weight(){return this._weight}get observer(){return this._progressObserver||(this._progressObserver=e=>{this.set(e)}),this._progressObserver}get loadingListener(){return this._loadingListener||(this._loadingListener=e=>{this.set(e.detail.loaded/e.detail.total*100)}),this._loadingListener}pipe(e){e.setProgress({progress:this.progress,caption:this.caption}),this.addEventListener("progress",r=>{e.setProgress({progress:r.detail.progress,caption:r.detail.caption})}),this.addEventListener("done",()=>{e.setLoaded()})}addEventListener(e,r){super.addEventListener(e,r)}removeEventListener(e,r){super.removeEventListener(e,r)}notifyProgress(){const e=this;this.dispatchEvent(new CustomEvent("progress",{detail:{get progress(){return e.progress},get caption(){return e.caption}}}))}notifyDone(){this.dispatchEvent(new CustomEvent("done"))}}const ee=Symbol("error"),te=Symbol("message");class j extends Event{constructor(e,r={}){super(e),this[ee]=r.error===void 0?null:r.error,this[te]=r.message===void 0?"":r.message}get error(){return this[ee]}get message(){return this[te]}}Object.defineProperty(j.prototype,"error",{enumerable:!0});Object.defineProperty(j.prototype,"message",{enumerable:!0});const pt=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:j;class ft extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(e,r){++this.listenersCount,super.addEventListener(e,r)}removeEventListener(e,r){--this.listenersCount,super.removeEventListener(e,r)}hasListeners(){return this.listenersCount>0}}function mt(t){t.asm={...t.asm};const e=new ft;for(const r in t.asm)if(typeof t.asm[r]=="function"){const s=t.asm[r];t.asm[r]=function(...n){try{return s(...n)}catch(i){if(!(i instanceof Error))throw i;if("exitCode"in i&&i?.exitCode===0)return;const o=wt(i,t.lastAsyncifyStackSource?.stack);if(t.lastAsyncifyStackSource&&(i.cause=t.lastAsyncifyStackSource),!e.hasListeners())throw bt(o),i;e.dispatchEvent(new pt("error",{error:i,message:o}))}}}return e}let M=[];function gt(){return M}function wt(t,e){if(t.message==="unreachable"){let r=yt;e||(r+=`
|
|
101
|
+
`,n=await t.run({code:s});return Me(n),{code:s,result:n}};async function Me(t){if(t.text!=="Success")throw console.log(t),new Error(`Failed to run code: ${t.text} ${t.errors}`)}const ct=Object.freeze(Object.defineProperty({__proto__:null,activatePlugin:fe,activateTheme:me,applyWordPressPatches:we,cp:_e,defineSiteUrl:xe,defineWpConfigConsts:q,importFile:ke,installPlugin:Le,installTheme:Ae,login:Ue,mkdir:Ee,mv:$e,replaceSite:Fe,request:be,rm:Se,rmdir:ve,runPHP:ge,runPHPWithOptions:ye,runWpInstallationWizard:He,setPhpIniEntry:Pe,setSiteOptions:Ie,unzip:z,updateUserMeta:We,writeFile:Re,zipEntireSite:Ce},Symbol.toStringTag,{value:"Module"})),lt=5*1024*1024;function ut(t,e){const r=t.headers.get("content-length")||"",s=parseInt(r,10)||lt;function n(i,o){e(new CustomEvent("progress",{detail:{loaded:i,total:o}}))}return new Response(new ReadableStream({async start(i){if(!t.body){i.close();return}const o=t.body.getReader();let a=0;for(;;)try{const{done:l,value:c}=await o.read();if(c&&(a+=c.byteLength),l){n(a,a),i.close();break}else n(a,s),i.enqueue(c)}catch(l){console.error({e:l}),i.error(l);break}}}),{status:t.status,statusText:t.statusText,headers:t.headers})}const W=1e-5;class H extends EventTarget{constructor({weight:e=1,caption:r="",fillTime:s=4}={}){super(),this._selfWeight=1,this._selfDone=!1,this._selfProgress=0,this._selfCaption="",this._isFilling=!1,this._subTrackers=[],this._weight=e,this._selfCaption=r,this._fillTime=s}stage(e,r=""){if(e||(e=this._selfWeight),this._selfWeight-e<-W)throw new Error(`Cannot add a stage with weight ${e} as the total weight of registered stages would exceed 1.`);this._selfWeight-=e;const s=new H({caption:r,weight:e,fillTime:this._fillTime});return this._subTrackers.push(s),s.addEventListener("progress",()=>this.notifyProgress()),s.addEventListener("done",()=>{this.done&&this.notifyDone()}),s}fillSlowly({stopBeforeFinishing:e=!0}={}){if(this._isFilling)return;this._isFilling=!0;const r=100,s=this._fillTime/r;this._fillInterval=setInterval(()=>{this.set(this._selfProgress+1),e&&this._selfProgress>=99&&clearInterval(this._fillInterval)},s)}set(e){this._selfProgress=Math.min(e,100),this.notifyProgress(),this._selfProgress+W>=100&&this.finish()}finish(){this._fillInterval&&clearInterval(this._fillInterval),this._selfDone=!0,this._selfProgress=100,this._isFilling=!1,this._fillInterval=void 0,this.notifyProgress(),this.notifyDone()}get caption(){for(let e=this._subTrackers.length-1;e>=0;e--)if(!this._subTrackers[e].done){const r=this._subTrackers[e].caption;if(r)return r}return this._selfCaption}setCaption(e){this._selfCaption=e,this.notifyProgress()}get done(){return this.progress+W>=100}get progress(){if(this._selfDone)return 100;const e=this._subTrackers.reduce((r,s)=>r+s.progress*s.weight,this._selfProgress*this._selfWeight);return Math.round(e*1e4)/1e4}get weight(){return this._weight}get observer(){return this._progressObserver||(this._progressObserver=e=>{this.set(e)}),this._progressObserver}get loadingListener(){return this._loadingListener||(this._loadingListener=e=>{this.set(e.detail.loaded/e.detail.total*100)}),this._loadingListener}pipe(e){e.setProgress({progress:this.progress,caption:this.caption}),this.addEventListener("progress",r=>{e.setProgress({progress:r.detail.progress,caption:r.detail.caption})}),this.addEventListener("done",()=>{e.setLoaded()})}addEventListener(e,r){super.addEventListener(e,r)}removeEventListener(e,r){super.removeEventListener(e,r)}notifyProgress(){const e=this;this.dispatchEvent(new CustomEvent("progress",{detail:{get progress(){return e.progress},get caption(){return e.caption}}}))}notifyDone(){this.dispatchEvent(new CustomEvent("done"))}}const Z=Symbol("error"),ee=Symbol("message");class j extends Event{constructor(e,r={}){super(e),this[Z]=r.error===void 0?null:r.error,this[ee]=r.message===void 0?"":r.message}get error(){return this[Z]}get message(){return this[ee]}}Object.defineProperty(j.prototype,"error",{enumerable:!0});Object.defineProperty(j.prototype,"message",{enumerable:!0});const ht=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:j;class dt extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(e,r){++this.listenersCount,super.addEventListener(e,r)}removeEventListener(e,r){--this.listenersCount,super.removeEventListener(e,r)}hasListeners(){return this.listenersCount>0}}function pt(t){t.asm={...t.asm};const e=new dt;for(const r in t.asm)if(typeof t.asm[r]=="function"){const s=t.asm[r];t.asm[r]=function(...n){try{return s(...n)}catch(i){if(!(i instanceof Error))throw i;if("exitCode"in i&&i?.exitCode===0)return;const o=mt(i,t.lastAsyncifyStackSource?.stack);if(t.lastAsyncifyStackSource&&(i.cause=t.lastAsyncifyStackSource),!e.hasListeners())throw yt(o),i;e.dispatchEvent(new ht("error",{error:i,message:o}))}}}return e}let N=[];function ft(){return N}function mt(t,e){if(t.message==="unreachable"){let r=wt;e||(r+=`
|
|
109
102
|
|
|
110
103
|
This stack trace is lacking. For a better one initialize
|
|
111
104
|
the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
|
|
112
105
|
|
|
113
|
-
`),
|
|
114
|
-
`;return r}return t.message}const
|
|
106
|
+
`),N=Pt(e||t.stack||"");for(const s of N)r+=` * ${s}
|
|
107
|
+
`;return r}return t.message}const wt=`
|
|
115
108
|
"unreachable" WASM instruction executed.
|
|
116
109
|
|
|
117
110
|
The typical reason is a PHP function missing from the ASYNCIFY_ONLY
|
|
@@ -135,17 +128,17 @@ the Dockerfile, you'll need to trigger this error again with long stack
|
|
|
135
128
|
traces enabled. In node.js, you can do it using the --stack-trace-limit=100
|
|
136
129
|
CLI option:
|
|
137
130
|
|
|
138
|
-
`,
|
|
139
|
-
${
|
|
140
|
-
${
|
|
141
|
-
`))console.log(`${
|
|
142
|
-
`).slice(1).map(r=>{const s=r.trim().substring(3).split(" ");return{fn:s.length>=2?s[0]:"<unknown>",isWasm:r.includes("wasm://")}}).filter(({fn:r,isWasm:s})=>s&&!r.startsWith("dynCall_")&&!r.startsWith("invoke_")).map(({fn:r})=>r);return Array.from(new Set(e))}catch{return[]}}class
|
|
131
|
+
`,te="\x1B[41m",gt="\x1B[1m",re="\x1B[0m",se="\x1B[K";let ne=!1;function yt(t){if(!ne){ne=!0,console.log(`${te}
|
|
132
|
+
${se}
|
|
133
|
+
${gt} WASM ERROR${re}${te}`);for(const e of t.split(`
|
|
134
|
+
`))console.log(`${se} ${e} `);console.log(`${re}`)}}function Pt(t){try{const e=t.split(`
|
|
135
|
+
`).slice(1).map(r=>{const s=r.trim().substring(3).split(" ");return{fn:s.length>=2?s[0]:"<unknown>",isWasm:r.includes("wasm://")}}).filter(({fn:r,isWasm:s})=>s&&!r.startsWith("dynCall_")&&!r.startsWith("invoke_")).map(({fn:r})=>r);return Array.from(new Set(e))}catch{return[]}}class b{constructor(e,r,s,n="",i=0){this.httpStatusCode=e,this.headers=r,this.bytes=s,this.exitCode=i,this.errors=n}static fromRawData(e){return new b(e.httpStatusCode,e.headers,e.bytes,e.errors,e.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const I=["8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0","5.6"],Ne=I[0],bt=I;class _t{#e;#t;constructor(e,r={}){this.requestHandler=e,this.#e={},this.#t={handleRedirects:!1,maxRedirects:4,...r}}async request(e,r=0){const s=await this.requestHandler.request({...e,headers:{...e.headers,cookie:this.#r()}});if(s.headers["set-cookie"]&&this.#s(s.headers["set-cookie"]),this.#t.handleRedirects&&s.headers.location&&r<this.#t.maxRedirects){const n=new URL(s.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:n.toString(),method:"GET",headers:{}},r+1)}return s}pathToInternalUrl(e){return this.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.internalUrlToPath(e)}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}#s(e){for(const r of e)try{if(!r.includes("="))continue;const s=r.indexOf("="),n=r.substring(0,s),i=r.substring(s+1).split(";")[0];this.#e[n]=i}catch(s){console.error(s)}}#r(){const e=[];for(const r in this.#e)e.push(`${r}=${this.#e[r]}`);return e.join("; ")}}const $t="http://example.com";function ie(t){return t.toString().substring(t.origin.length)}function oe(t,e){return!e||!t.startsWith(e)?t:t.substring(e.length)}function Et(t,e){return!e||t.startsWith(e)?t:e+t}class St{#e;#t;#s;#r;#i;#n;#o;#a;#c;constructor(e,r={}){this.#a=new Te({concurrency:1});const{documentRoot:s="/www/",absoluteUrl:n=typeof location=="object"?location?.href:"",isStaticFilePath:i=()=>!1}=r;this.php=e,this.#e=s,this.#c=i;const o=new URL(n);this.#s=o.hostname,this.#r=o.port?Number(o.port):o.protocol==="https:"?443:80,this.#t=(o.protocol||"").replace(":","");const a=this.#r!==443&&this.#r!==80;this.#i=[this.#s,a?`:${this.#r}`:""].join(""),this.#n=o.pathname.replace(/\/+$/,""),this.#o=[`${this.#t}://`,this.#i,this.#n].join("")}pathToInternalUrl(e){return`${this.absoluteUrl}${e}`}internalUrlToPath(e){const r=new URL(e);return r.pathname.startsWith(this.#n)&&(r.pathname=r.pathname.slice(this.#n.length)),ie(r)}get isRequestRunning(){return this.#a.running>0}get absoluteUrl(){return this.#o}get documentRoot(){return this.#e}async request(e){const r=e.url.startsWith("http://")||e.url.startsWith("https://"),s=new URL(e.url,r?void 0:$t),n=oe(s.pathname,this.#n);return this.#c(n)?this.#l(n):await this.#u(e,s)}#l(e){const r=`${this.#e}${e}`;if(!this.php.fileExists(r))return new b(404,{},new TextEncoder().encode("404 File not found"));const s=this.php.readFileAsBuffer(r);return new b(200,{"content-length":[`${s.byteLength}`],"content-type":[Rt(r)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},s)}async#u(e,r){const s=await this.#a.acquire();try{this.php.addServerGlobalEntry("DOCUMENT_ROOT",this.#e),this.php.addServerGlobalEntry("HTTPS",this.#o.startsWith("https://")?"on":"");let n="GET";const i={host:this.#i,...De(e.headers||{})},o=[];if(e.files&&Object.keys(e.files).length){n="POST";for(const c in e.files){const u=e.files[c];o.push({key:c,name:u.name,type:u.type,data:new Uint8Array(await u.arrayBuffer())})}i["content-type"]?.startsWith("multipart/form-data")&&(e.formData=vt(e.body||""),i["content-type"]="application/x-www-form-urlencoded",delete e.body)}let a;e.formData!==void 0?(n="POST",i["content-type"]=i["content-type"]||"application/x-www-form-urlencoded",a=new URLSearchParams(e.formData).toString()):a=e.body;let l;try{l=this.#h(r.pathname)}catch{return new b(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:Et(ie(r),this.#n),protocol:this.#t,method:e.method||n,body:a,fileInfos:o,scriptPath:l,headers:i})}finally{s()}}#h(e){let r=oe(e,this.#n);r.includes(".php")?r=r.split(".php")[0]+".php":(r.endsWith("/")||(r+="/"),r.endsWith("index.php")||(r+="index.php"));const s=`${this.#e}${r}`;if(this.php.fileExists(s))return s;if(!this.php.fileExists(`${this.#e}/index.php`))throw new Error(`File not found: ${s}`);return`${this.#e}/index.php`}}function vt(t){const e={},r=t.match(/--(.*)\r\n/);if(!r)return e;const s=r[1],n=t.split(`--${s}`);return n.shift(),n.pop(),n.forEach(i=>{const o=i.indexOf(`\r
|
|
143
136
|
\r
|
|
144
|
-
`),a=i.substring(0,o).trim(),l=i.substring(o+4).trim(),c=a.match(/name="([^"]+)"/);if(c){const u=c[1];e[u]=l}}),e}function
|
|
137
|
+
`),a=i.substring(0,o).trim(),l=i.substring(o+4).trim(),c=a.match(/name="([^"]+)"/);if(c){const u=c[1];e[u]=l}}),e}function Rt(t){switch(t.split(".").pop()){case"css":return"text/css";case"js":return"application/javascript";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"gif":return"image/gif";case"svg":return"image/svg+xml";case"woff":return"font/woff";case"woff2":return"font/woff2";case"ttf":return"font/ttf";case"otf":return"font/otf";case"eot":return"font/eot";case"ico":return"image/x-icon";case"html":return"text/html";case"json":return"application/json";case"xml":return"application/xml";case"txt":case"md":return"text/plain";default:return"application-octet-stream"}}const ae={0:"No error occurred. System call completed successfully.",1:"Argument list too long.",2:"Permission denied.",3:"Address in use.",4:"Address not available.",5:"Address family not supported.",6:"Resource unavailable, or operation would block.",7:"Connection already in progress.",8:"Bad file descriptor.",9:"Bad message.",10:"Device or resource busy.",11:"Operation canceled.",12:"No child processes.",13:"Connection aborted.",14:"Connection refused.",15:"Connection reset.",16:"Resource deadlock would occur.",17:"Destination address required.",18:"Mathematics argument out of domain of function.",19:"Reserved.",20:"File exists.",21:"Bad address.",22:"File too large.",23:"Host is unreachable.",24:"Identifier removed.",25:"Illegal byte sequence.",26:"Operation in progress.",27:"Interrupted function.",28:"Invalid argument.",29:"I/O error.",30:"Socket is connected.",31:"There is a directory under that path.",32:"Too many levels of symbolic links.",33:"File descriptor value too large.",34:"Too many links.",35:"Message too large.",36:"Reserved.",37:"Filename too long.",38:"Network is down.",39:"Connection aborted by network.",40:"Network unreachable.",41:"Too many files open in system.",42:"No buffer space available.",43:"No such device.",44:"There is no such file or directory OR the parent directory does not exist.",45:"Executable file format error.",46:"No locks available.",47:"Reserved.",48:"Not enough space.",49:"No message of the desired type.",50:"Protocol not available.",51:"No space left on device.",52:"Function not supported.",53:"The socket is not connected.",54:"Not a directory or a symbolic link to a directory.",55:"Directory not empty.",56:"State not recoverable.",57:"Not a socket.",58:"Not supported, or operation not supported on socket.",59:"Inappropriate I/O control operation.",60:"No such device or address.",61:"Value too large to be stored in data type.",62:"Previous owner died.",63:"Operation not permitted.",64:"Broken pipe.",65:"Protocol error.",66:"Protocol not supported.",67:"Protocol wrong type for socket.",68:"Result too large.",69:"Read-only file system.",70:"Invalid seek.",71:"No such process.",72:"Reserved.",73:"Connection timed out.",74:"Text file busy.",75:"Cross-device link.",76:"Extension: Capabilities insufficient."};function m(t=""){return function(r,s,n){const i=n.value;n.value=function(...o){try{return i.apply(this,o)}catch(a){const l=typeof a=="object"?a?.errno:null;if(l in ae){const c=ae[l],u=typeof o[0]=="string"?o[0]:null,d=u!==null?t.replaceAll("{path}",u):t;throw new Error(`${d}: ${c}`,{cause:a})}throw a}}}}const xt=[];function Tt(t){return xt[t]}(function(){return typeof process<"u"&&process.release?.name==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"})();var Ct=Object.defineProperty,Ft=Object.getOwnPropertyDescriptor,w=(t,e,r,s)=>{for(var n=s>1?void 0:s?Ft(e,r):e,i=t.length-1,o;i>=0;i--)(o=t[i])&&(n=(s?o(e,r,n):o(n))||n);return s&&n&&Ct(e,r,n),n};const f="string",E="number",h=Symbol("__private__dont__use");class g{constructor(e,r){this.#e=[],this.#t=!1,this.#s=null,this.#r={},e!==void 0&&this.initializeRuntime(e),r&&(this.requestHandler=new _t(new St(this,r)))}#e;#t;#s;#r;get absoluteUrl(){return this.requestHandler.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.requestHandler.documentRoot}pathToInternalUrl(e){return this.requestHandler.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.requestHandler.internalUrlToPath(e)}initializeRuntime(e){if(this[h])throw new Error("PHP runtime already initialized.");const r=Tt(e);if(!r)throw new Error("Invalid PHP runtime id.");this[h]=r,this.#s=pt(r)}setPhpIniPath(e){if(this.#t)throw new Error("Cannot set PHP ini path after calling run().");this[h].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,r){if(this.#t)throw new Error("Cannot set PHP ini entries after calling run().");this.#e.push([e,r])}chdir(e){this[h].FS.chdir(e)}async request(e,r){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,r)}async run(e){this.#t||(this.#i(),this.#t=!0),this.#h(e.scriptPath||""),this.#o(e.relativeUri||""),this.#c(e.method||"GET");const{host:r,...s}={host:"example.com:443",...De(e.headers||{})};if(this.#a(r,e.protocol||"http"),this.#l(s),e.body&&this.#u(e.body),e.fileInfos)for(const n of e.fileInfos)this.#p(n);return e.code&&this.#f(" ?>"+e.code),this.#d(),await this.#m()}#i(){if(this.#e.length>0){const e=this.#e.map(([r,s])=>`${r}=${s}`).join(`
|
|
145
138
|
`)+`
|
|
146
139
|
|
|
147
|
-
`;this[h].ccall("wasm_set_phpini_entries",null,[f],[e])}this[h].ccall("php_wasm_init",null,[],[])}#n(){const e="/tmp/headers.json";if(!this.fileExists(e))throw new Error("SAPI Error: Could not find response headers file.");const r=JSON.parse(this.readFileAsText(e)),s={};for(const n of r.headers){if(!n.includes(": "))continue;const i=n.indexOf(": "),o=n.substring(0,i).toLowerCase(),a=n.substring(i+2);o in s||(s[o]=[]),s[o].push(a)}return{headers:s,httpStatusCode:r.status}}#o(e){if(this[h].ccall("wasm_set_request_uri",null,[f],[e]),e.includes("?")){const r=e.substring(e.indexOf("?")+1);this[h].ccall("wasm_set_query_string",null,[f],[r])}}#a(e,r){this[h].ccall("wasm_set_request_host",null,[f],[e]);let s;try{s=parseInt(new URL(e).port,10)}catch{}(!s||isNaN(s)||s===80)&&(s=r==="https"?443:80),this[h].ccall("wasm_set_request_port",null,[
|
|
140
|
+
`;this[h].ccall("wasm_set_phpini_entries",null,[f],[e])}this[h].ccall("php_wasm_init",null,[],[])}#n(){const e="/tmp/headers.json";if(!this.fileExists(e))throw new Error("SAPI Error: Could not find response headers file.");const r=JSON.parse(this.readFileAsText(e)),s={};for(const n of r.headers){if(!n.includes(": "))continue;const i=n.indexOf(": "),o=n.substring(0,i).toLowerCase(),a=n.substring(i+2);o in s||(s[o]=[]),s[o].push(a)}return{headers:s,httpStatusCode:r.status}}#o(e){if(this[h].ccall("wasm_set_request_uri",null,[f],[e]),e.includes("?")){const r=e.substring(e.indexOf("?")+1);this[h].ccall("wasm_set_query_string",null,[f],[r])}}#a(e,r){this[h].ccall("wasm_set_request_host",null,[f],[e]);let s;try{s=parseInt(new URL(e).port,10)}catch{}(!s||isNaN(s)||s===80)&&(s=r==="https"?443:80),this[h].ccall("wasm_set_request_port",null,[E],[s]),(r==="https"||!r&&s===443)&&this.addServerGlobalEntry("HTTPS","on")}#c(e){this[h].ccall("wasm_set_request_method",null,[f],[e])}#l(e){e.cookie&&this[h].ccall("wasm_set_cookies",null,[f],[e.cookie]),e["content-type"]&&this[h].ccall("wasm_set_content_type",null,[f],[e["content-type"]]),e["content-length"]&&this[h].ccall("wasm_set_content_length",null,[E],[parseInt(e["content-length"],10)]);for(const r in e)this.addServerGlobalEntry(`HTTP_${r.toUpperCase().replace(/-/g,"_")}`,e[r])}#u(e){this[h].ccall("wasm_set_request_body",null,[f],[e]),this[h].ccall("wasm_set_content_length",null,[E],[new TextEncoder().encode(e).length])}#h(e){this[h].ccall("wasm_set_path_translated",null,[f],[e])}addServerGlobalEntry(e,r){this.#r[e]=r}#d(){for(const e in this.#r)this[h].ccall("wasm_add_SERVER_entry",null,[f,f],[e,this.#r[e]])}#p(e){const{key:r,name:s,type:n,data:i}=e,o=`/tmp/${Math.random().toFixed(20)}`;this.writeFile(o,i);const a=0;this[h].ccall("wasm_add_uploaded_file",null,[f,f,f,f,E,E],[r,s,n,o,a,i.byteLength])}#f(e){this[h].ccall("wasm_set_php_code",null,[f],[e])}async#m(){let e,r;try{e=await new Promise((i,o)=>{r=l=>{const c=new Error("Rethrown");c.cause=l.error,c.betterMessage=l.message,o(c)},this.#s?.addEventListener("error",r);const a=this[h].ccall("wasm_sapi_handle_request",E,[],[]);return a instanceof Promise?a.then(i,o):i(a)})}catch(i){for(const c in this)typeof this[c]=="function"&&(this[c]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=ft();const o=i,a="betterMessage"in o?o.betterMessage:o.message,l=new Error(a);throw l.cause=o,l}finally{this.#s?.removeEventListener("error",r),this.#r={}}const{headers:s,httpStatusCode:n}=this.#n();return new b(n,s,this.readFileAsBuffer("/tmp/stdout"),this.readFileAsText("/tmp/stderr"),e)}mkdir(e){this[h].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[h].FS.readFile(e)}writeFile(e,r){this[h].FS.writeFile(e,r)}unlink(e){this[h].FS.unlink(e)}mv(e,r){this[h].FS.rename(e,r)}rmdir(e,r={recursive:!0}){r?.recursive&&this.listFiles(e).forEach(s=>{const n=`${e}/${s}`;this.isDir(n)?this.rmdir(n,r):this.unlink(n)}),this[h].FS.rmdir(e)}listFiles(e){if(!this.fileExists(e))return[];try{return this[h].FS.readdir(e).filter(r=>r!=="."&&r!=="..")}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[h].FS.isDir(this[h].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[h].FS.lookupPath(e),!0}catch{return!1}}}w([m('Could not create directory "{path}"')],g.prototype,"mkdir",1);w([m('Could not create directory "{path}"')],g.prototype,"mkdirTree",1);w([m('Could not read "{path}"')],g.prototype,"readFileAsText",1);w([m('Could not read "{path}"')],g.prototype,"readFileAsBuffer",1);w([m('Could not write to "{path}"')],g.prototype,"writeFile",1);w([m('Could not unlink "{path}"')],g.prototype,"unlink",1);w([m('Could not move "{path}"')],g.prototype,"mv",1);w([m('Could not remove directory "{path}"')],g.prototype,"rmdir",1);w([m('Could not list files in "{path}"')],g.prototype,"listFiles",1);w([m('Could not stat "{path}"')],g.prototype,"isDir",1);w([m('Could not stat "{path}"')],g.prototype,"fileExists",1);function De(t){const e={};for(const r in t)e[r.toLowerCase()]=t[r];return e}const kt=["vfs","literal","wordpress.org/themes","wordpress.org/plugins","url"];function Ot(t){return t&&typeof t=="object"&&typeof t.resource=="string"&&kt.includes(t.resource)}class ${static create(e,{semaphore:r,progress:s}){let n;switch(e.resource){case"vfs":n=new Lt(e,s);break;case"literal":n=new At(e,s);break;case"wordpress.org/themes":n=new Wt(e,s);break;case"wordpress.org/plugins":n=new Mt(e,s);break;case"url":n=new Ht(e,s);break;default:throw new Error(`Invalid resource: ${e}`)}return n=new Nt(n),r&&(n=new Dt(n,r)),n}setPlayground(e){this.playground=e}get isAsync(){return!1}}class Lt extends ${constructor(e,r){super(),this.resource=e,this.progress=r}async resolve(){const e=await this.playground.readFileAsBuffer(this.resource.path);return this.progress?.set(100),new File([e],this.name)}get name(){return this.resource.path}}class At extends ${constructor(e,r){super(),this.resource=e,this.progress=r}async resolve(){return this.progress?.set(100),new File([this.resource.contents],this.resource.name)}get name(){return this.resource.name}}class B extends ${constructor(e){super(),this.progress=e}async resolve(){this.progress?.setCaption(this.caption);const e=this.getURL();let r=await fetch(e);if(r=await ut(r,this.progress?.loadingListener??Ut),r.status!==200)throw new Error(`Could not download "${e}"`);return new File([await r.blob()],this.name)}get caption(){return`Downloading ${this.name}`}get name(){try{return new URL(this.getURL(),"http://example.com").pathname.split("/").pop()}catch{return this.getURL()}}get isAsync(){return!0}}const Ut=()=>{};class Ht extends B{constructor(e,r){super(r),this.resource=e}getURL(){return this.resource.url}get caption(){return this.resource.caption??super.caption}}let V="https://playground.wordpress.net/plugin-proxy";function It(t){V=t}class Wt extends B{constructor(e,r){super(r),this.resource=e}get name(){return A(this.resource.slug)}getURL(){const e=qe(this.resource.slug);return`${V}?theme=`+e}}class Mt extends B{constructor(e,r){super(r),this.resource=e}get name(){return A(this.resource.slug)}getURL(){const e=qe(this.resource.slug);return`${V}?plugin=`+e}}function qe(t){return!t||t.endsWith(".zip")?t:t+".latest-stable.zip"}class ze extends ${constructor(e){super(),this.resource=e}async resolve(){return this.resource.resolve()}async setPlayground(e){return this.resource.setPlayground(e)}get progress(){return this.resource.progress}set progress(e){this.resource.progress=e}get name(){return this.resource.name}get isAsync(){return this.resource.isAsync}}class Nt extends ze{async resolve(){return this.promise||(this.promise=super.resolve()),this.promise}}class Dt extends ze{constructor(e,r){super(e),this.semaphore=r}async resolve(){return this.isAsync?this.semaphore.run(()=>super.resolve()):super.resolve()}}const qt=["6.2","6.1","6.0","5.9"];function je(t,{progress:e=new H,semaphore:r=new Te({concurrency:3}),onStepCompleted:s=()=>{}}={}){const n=(t.steps||[]).filter(zt),i=n.reduce((a,l)=>a+(l.progress?.weight||1),0),o=n.map(a=>jt(a,{semaphore:r,rootProgressTracker:e,totalProgressWeight:i}));return{versions:{php:ce(t.preferredVersions?.php,I,Ne),wp:ce(t.preferredVersions?.wp,qt,"6.2")},run:async a=>{try{for(const{resources:l}of o)for(const c of l)c.setPlayground(a),c.isAsync&&c.resolve();for(const{run:l,step:c}of o){const u=await l(a);s(u,c)}try{await a.goTo(t.landingPage||"/")}catch{}}finally{e.finish()}}}}function ce(t,e,r){return t&&e.includes(t)?t:r}function zt(t){return!!(typeof t=="object"&&t)}function jt(t,{semaphore:e,rootProgressTracker:r,totalProgressWeight:s}){const n=r.stage((t.progress?.weight||1)/s),i={};for(const u of Object.keys(t)){let d=t[u];Ot(d)&&(d=$.create(d,{semaphore:e})),i[u]=d}const o=async u=>{try{return n.fillSlowly(),await ct[t.step](u,await Bt(i),{tracker:n,initialCaption:t.progress?.caption})}finally{n.finish()}},a=le(i),l=le(i).filter(u=>u.isAsync),c=1/(l.length+1);for(const u of l)u.progress=n.stage(c);return{run:o,step:t,resources:a}}function le(t){const e=[];for(const r in t){const s=t[r];s instanceof $&&e.push(s)}return e}async function Bt(t){const e={};for(const r in t){const s=t[r];s instanceof $?e[r]=await s.resolve():e[r]=s}return e}async function Be(t,e){await t.run(e)}/**
|
|
148
141
|
* @license
|
|
149
142
|
* Copyright 2019 Google LLC
|
|
150
143
|
* SPDX-License-Identifier: Apache-2.0
|
|
151
|
-
*/const
|
|
144
|
+
*/const Ve=Symbol("Comlink.proxy"),Vt=Symbol("Comlink.endpoint"),Gt=Symbol("Comlink.releaseProxy"),M=Symbol("Comlink.finalizer"),T=Symbol("Comlink.thrown"),Ge=t=>typeof t=="object"&&t!==null||typeof t=="function",Yt={canHandle:t=>Ge(t)&&t[Ve],serialize(t){const{port1:e,port2:r}=new MessageChannel;return G(t,e),[r,[r]]},deserialize(t){return t.start(),Y(t)}},Jt={canHandle:t=>Ge(t)&&T in t,serialize({value:t}){let e;return t instanceof Error?e={isError:!0,value:{message:t.message,name:t.name,stack:t.stack}}:e={isError:!1,value:t},[e,[]]},deserialize(t){throw t.isError?Object.assign(new Error(t.value.message),t.value):t.value}},R=new Map([["proxy",Yt],["throw",Jt]]);function Kt(t,e){for(const r of t)if(e===r||r==="*"||r instanceof RegExp&&r.test(e))return!0;return!1}function G(t,e=globalThis,r=["*"]){e.addEventListener("message",function s(n){if(!n||!n.data)return;if(!Kt(r,n.origin)){console.warn(`Invalid origin '${n.origin}' for comlink proxy`);return}const{id:i,type:o,path:a}=Object.assign({path:[]},n.data),l=(n.data.argumentList||[]).map(P);let c;try{const u=a.slice(0,-1).reduce((p,y)=>p[y],t),d=a.reduce((p,y)=>p[y],t);switch(o){case"GET":c=d;break;case"SET":u[a.slice(-1)[0]]=P(n.data.value),c=!0;break;case"APPLY":c=d.apply(u,l);break;case"CONSTRUCT":{const p=new d(...l);c=Qe(p)}break;case"ENDPOINT":{const{port1:p,port2:y}=new MessageChannel;G(t,y),c=tr(p,[p])}break;case"RELEASE":c=void 0;break;default:return}}catch(u){c={value:u,[T]:0}}Promise.resolve(c).catch(u=>({value:u,[T]:0})).then(u=>{const[d,p]=L(u);e.postMessage(Object.assign(Object.assign({},d),{id:i}),p),o==="RELEASE"&&(e.removeEventListener("message",s),Ye(e),M in t&&typeof t[M]=="function"&&t[M]())}).catch(u=>{const[d,p]=L({value:new TypeError("Unserializable return value"),[T]:0});e.postMessage(Object.assign(Object.assign({},d),{id:i}),p)})}),e.start&&e.start()}function Qt(t){return t.constructor.name==="MessagePort"}function Ye(t){Qt(t)&&t.close()}function Y(t,e){return D(t,[],e)}function x(t){if(t)throw new Error("Proxy has been released and is not useable")}function Je(t){return S(t,{type:"RELEASE"}).then(()=>{Ye(t)})}const k=new WeakMap,O="FinalizationRegistry"in globalThis&&new FinalizationRegistry(t=>{const e=(k.get(t)||0)-1;k.set(t,e),e===0&&Je(t)});function Xt(t,e){const r=(k.get(e)||0)+1;k.set(e,r),O&&O.register(t,e,t)}function Zt(t){O&&O.unregister(t)}function D(t,e=[],r=function(){}){let s=!1;const n=new Proxy(r,{get(i,o){if(x(s),o===Gt)return()=>{Zt(n),Je(t),s=!0};if(o==="then"){if(e.length===0)return{then:()=>n};const a=S(t,{type:"GET",path:e.map(l=>l.toString())}).then(P);return a.then.bind(a)}return D(t,[...e,o])},set(i,o,a){x(s);const[l,c]=L(a);return S(t,{type:"SET",path:[...e,o].map(u=>u.toString()),value:l},c).then(P)},apply(i,o,a){x(s);const l=e[e.length-1];if(l===Vt)return S(t,{type:"ENDPOINT"}).then(P);if(l==="bind")return D(t,e.slice(0,-1));const[c,u]=ue(a);return S(t,{type:"APPLY",path:e.map(d=>d.toString()),argumentList:c},u).then(P)},construct(i,o){x(s);const[a,l]=ue(o);return S(t,{type:"CONSTRUCT",path:e.map(c=>c.toString()),argumentList:a},l).then(P)}});return Xt(n,t),n}function er(t){return Array.prototype.concat.apply([],t)}function ue(t){const e=t.map(L);return[e.map(r=>r[0]),er(e.map(r=>r[1]))]}const Ke=new WeakMap;function tr(t,e){return Ke.set(t,e),t}function Qe(t){return Object.assign(t,{[Ve]:!0})}function rr(t,e=globalThis,r="*"){return{postMessage:(s,n)=>t.postMessage(s,r,n),addEventListener:e.addEventListener.bind(e),removeEventListener:e.removeEventListener.bind(e)}}function L(t){for(const[e,r]of R)if(r.canHandle(t)){const[s,n]=r.serialize(t);return[{type:"HANDLER",name:e,value:s},n]}return[{type:"RAW",value:t},Ke.get(t)||[]]}function P(t){switch(t.type){case"HANDLER":return R.get(t.name).deserialize(t.value);case"RAW":return t.value}}function S(t,e,r){return new Promise(s=>{const n=sr();t.addEventListener("message",function i(o){!o.data||!o.data.id||o.data.id!==n||(t.removeEventListener("message",i),s(o.data))}),t.start&&t.start(),t.postMessage(Object.assign({id:n},e),r)})}function sr(){return new Array(4).fill(0).map(()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16)).join("-")}function Xe(t){nr();const e=t instanceof Worker?t:rr(t),r=Y(e),s=Ze(r);return new Proxy(s,{get:(n,i)=>i==="isConnected"?()=>r.isConnected():r[i]})}let he=!1;function nr(){he||(he=!0,R.set("EVENT",{canHandle:t=>t instanceof CustomEvent,serialize:t=>[{detail:t.detail},[]],deserialize:t=>t}),R.set("FUNCTION",{canHandle:t=>typeof t=="function",serialize(t){console.debug("[Comlink][Performance] Proxying a function");const{port1:e,port2:r}=new MessageChannel;return G(t,e),[r,[r]]},deserialize(t){return t.start(),Y(t)}}),R.set("PHPResponse",{canHandle:t=>typeof t=="object"&&t!==null&&"headers"in t&&"bytes"in t&&"errors"in t&&"exitCode"in t&&"httpStatusCode"in t,serialize(t){return[t.toRawData(),[]]},deserialize(t){return b.fromRawData(t)}}))}function Ze(t){return new Proxy(t,{get(e,r){switch(typeof e[r]){case"function":return(...s)=>e[r](...s);case"object":return e[r]===null?e[r]:Ze(e[r]);case"undefined":case"number":case"string":return e[r];default:return Qe(e[r])}}})}(function(){return typeof navigator<"u"&&navigator?.userAgent?.toLowerCase().indexOf("firefox")>-1?"iframe":"webworker"})();async function et({iframe:t,blueprint:e,remoteUrl:r,progressTracker:s=new H,disableProgressBar:n,onBlueprintStepCompleted:i}){if(ir(r),r=pe(r,{progressbar:!n}),s.setCaption("Preparing WordPress"),!e)return de(t,r,s);const o=je(e,{progress:s.stage(.5),onStepCompleted:i}),a=await de(t,pe(r,{php:o.versions.php,wp:o.versions.wp}),s);return await Be(o,a),s.finish(),a}async function de(t,e,r){await new Promise(i=>{t.src=e,t.addEventListener("load",i,!1)});const s=Xe(t.contentWindow);await s.isConnected(),r.pipe(s);const n=r.stage();return await s.onDownloadProgress(n.loadingListener),await s.isReady(),n.finish(),s}const C="https://playground.wordpress.net";function ir(t){const e=new URL(t,C);if((e.origin===C||e.hostname==="localhost")&&e.pathname!=="/remote.html")throw new Error(`Invalid remote URL: ${e}. Expected origin to be ${C}/remote.html.`)}function pe(t,e){const r=new URL(t,C),s=new URLSearchParams(r.search);for(const[n,i]of Object.entries(e))i!=null&&i!==!1&&s.set(n,i.toString());return r.search=s.toString(),r.toString()}async function or(t,e){if(console.warn("`connectPlayground` is deprecated and will be removed. Use `startPlayground` instead."),e?.loadRemote)return et({iframe:t,remoteUrl:e.loadRemote});const r=Xe(t.contentWindow);return await r.isConnected(),r}exports.LatestSupportedPHPVersion=Ne;exports.SupportedPHPVersions=I;exports.SupportedPHPVersionsList=bt;exports.activatePlugin=fe;exports.activateTheme=me;exports.applyWordPressPatches=we;exports.compileBlueprint=je;exports.connectPlayground=or;exports.cp=_e;exports.defineSiteUrl=xe;exports.defineWpConfigConsts=q;exports.importFile=ke;exports.installPlugin=Le;exports.installTheme=Ae;exports.login=Ue;exports.mkdir=Ee;exports.mv=$e;exports.phpVar=_;exports.phpVars=U;exports.replaceSite=Fe;exports.request=be;exports.rm=Se;exports.rmdir=ve;exports.runBlueprintSteps=Be;exports.runPHP=ge;exports.runPHPWithOptions=ye;exports.runWpInstallationWizard=He;exports.setPhpIniEntry=Pe;exports.setPluginProxyURL=It;exports.setSiteOptions=Ie;exports.startPlaygroundWeb=et;exports.unzip=z;exports.updateUserMeta=We;exports.writeFile=Re;exports.zipEntireSite=Ce;
|
package/index.d.ts
CHANGED
|
@@ -1526,12 +1526,20 @@ export interface DefineWpConfigConstsStep {
|
|
|
1526
1526
|
step: "defineWpConfigConsts";
|
|
1527
1527
|
/** The constants to define */
|
|
1528
1528
|
consts: Record<string, unknown>;
|
|
1529
|
+
/**
|
|
1530
|
+
* Enables the virtualization of wp-config.php and playground-consts.json files, leaving the local system files untouched.
|
|
1531
|
+
* The variables defined in the /vfs-blueprints/playground-consts.json file are loaded via the auto_prepend_file directive in the php.ini file.
|
|
1532
|
+
* @default false
|
|
1533
|
+
* @see https://www.php.net/manual/en/ini.core.php#ini.auto-prepend-file
|
|
1534
|
+
*/
|
|
1535
|
+
virtualize?: boolean;
|
|
1529
1536
|
}
|
|
1530
1537
|
/**
|
|
1531
1538
|
* Sets site URL of the WordPress installation.
|
|
1532
1539
|
*
|
|
1533
1540
|
* @param playground The playground client.
|
|
1534
|
-
* @param wpConfigConst
|
|
1541
|
+
* @param wpConfigConst An object containing the constants to be defined and the optional virtual file system configuration file path.
|
|
1542
|
+
* @returns Returns the virtual file system configuration file path.
|
|
1535
1543
|
*/
|
|
1536
1544
|
export declare const defineWpConfigConsts: StepHandler<DefineWpConfigConstsStep>;
|
|
1537
1545
|
export interface ActivateThemeStep {
|
|
@@ -1545,24 +1553,6 @@ export interface ActivateThemeStep {
|
|
|
1545
1553
|
* @param themeFolderName The theme folder name.
|
|
1546
1554
|
*/
|
|
1547
1555
|
export declare const activateTheme: StepHandler<ActivateThemeStep>;
|
|
1548
|
-
/**
|
|
1549
|
-
* The step object for defining constants in the VFS_CONFIG_FILE_PATH php file and loaded using the auto_prepend_file php.ini directive.
|
|
1550
|
-
*/
|
|
1551
|
-
export interface DefineVirtualWpConfigConstsStep {
|
|
1552
|
-
step: "defineVirtualWpConfigConsts";
|
|
1553
|
-
/** The constants to define */
|
|
1554
|
-
consts: Record<string, unknown>;
|
|
1555
|
-
}
|
|
1556
|
-
/**
|
|
1557
|
-
* Function to define constants in the virtual VFS_CONFIG_FILE_PATH php file of a WordPress installation.
|
|
1558
|
-
* The file should be dynamically loaded using the auto_prepend_file php.ini directive after this step.
|
|
1559
|
-
*
|
|
1560
|
-
* @param playground The playground client.
|
|
1561
|
-
* @param wpConfigConst An object containing the constants to be defined and the optional virtual file system configuration file path.
|
|
1562
|
-
* @returns Returns the virtual file system configuration file path.
|
|
1563
|
-
* @see {@link https://www.php.net/manual/en/ini.core.php#ini.auto-prepend-file}
|
|
1564
|
-
*/
|
|
1565
|
-
export declare const defineVirtualWpConfigConsts: StepHandler<DefineVirtualWpConfigConstsStep>;
|
|
1566
1556
|
export type Step = GenericStep<FileReference>;
|
|
1567
1557
|
export type StepDefinition = Step & {
|
|
1568
1558
|
progress?: {
|
|
@@ -1574,7 +1564,7 @@ export type StepDefinition = Step & {
|
|
|
1574
1564
|
* If you add a step here, make sure to also
|
|
1575
1565
|
* add it to the exports below.
|
|
1576
1566
|
*/
|
|
1577
|
-
export type GenericStep<Resource> = ActivatePluginStep | ActivateThemeStep | ApplyWordPressPatchesStep | CpStep | DefineWpConfigConstsStep |
|
|
1567
|
+
export type GenericStep<Resource> = ActivatePluginStep | ActivateThemeStep | ApplyWordPressPatchesStep | CpStep | DefineWpConfigConstsStep | DefineSiteUrlStep | ImportFileStep<Resource> | InstallPluginStep<Resource> | InstallThemeStep<Resource> | LoginStep | MkdirStep | MvStep | RequestStep | ReplaceSiteStep<Resource> | RmStep | RmdirStep | RunPHPStep | RunPHPWithOptionsStep | RunWpInstallationWizardStep | SetPhpIniEntryStep | SetSiteOptionsStep | UnzipStep | UpdateUserMetaStep | WriteFileStep<Resource>;
|
|
1578
1568
|
export type StepHandler<S extends GenericStep<File>> = (
|
|
1579
1569
|
/**
|
|
1580
1570
|
* A PHP instance or Playground client.
|