From 7634a158c36a88a29785636dd6640c57b522a053 Mon Sep 17 00:00:00 2001 From: webreflection Date: Mon, 18 Dec 2023 11:25:10 +0100 Subject: [PATCH 1/2] Added MicroPython mip package manager --- .eslintrc.json | 2 +- docs/core.js | 4 +- docs/core.js.map | 2 +- esm/interpreter/micropython.js | 9 + esm/python/mip.js | 2 + package-lock.json | 128 ++++---- package.json | 8 +- python/mip.py | 287 ++++++++++++++++++ rollup/build_python.cjs | 21 ++ test/integration.html | 2 +- test/integration/_shared.js | 5 + .../interpreter/micropython/mip.html | 18 ++ test/integration/micropython.js | 2 + test/mip.html | 41 +++ test/mip.py | 22 ++ test/mip.toml | 1 + test/mocked/micropython.mjs | 20 ++ test/mocked/pyodide.mjs | 2 +- 18 files changed, 502 insertions(+), 74 deletions(-) create mode 100644 esm/python/mip.js create mode 100644 python/mip.py create mode 100644 rollup/build_python.cjs create mode 100644 test/integration/interpreter/micropython/mip.html create mode 100644 test/mip.html create mode 100644 test/mip.py create mode 100644 test/mip.toml diff --git a/.eslintrc.json b/.eslintrc.json index f664db1..4ebabc5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -8,7 +8,7 @@ "ecmaVersion": 12, "sourceType": "module" }, - "ignorePatterns": ["__template.js", "xworker.js"], + "ignorePatterns": ["__template.js", "xworker.js", "esm/python/*.js"], "rules": { "object-curly-spacing": ["error", "always"], "quotes": ["error", "single"] diff --git a/docs/core.js b/docs/core.js index 99d7e40..208d6c9 100644 --- a/docs/core.js +++ b/docs/core.js @@ -1,3 +1,3 @@ -const e=(e,t=document)=>[...t.querySelectorAll(e)],t=(e,t=document)=>{const r=(new XPathEvaluator).createExpression(e).evaluate(t,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE),n=[];for(let e=0,{snapshotLength:t}=r;e((e,t)=>{const n=(t,r)=>(e.set(r,t),t),s=o=>{if(e.has(o))return e.get(o);const[a,i]=t[o];switch(a){case 0:case-1:return n(i,o);case 1:{const e=n([],o);for(const t of i)e.push(s(t));return e}case 2:{const e=n({},o);for(const[t,r]of i)e[s(t)]=s(r);return e}case 3:return n(new Date(i),o);case 4:{const{source:e,flags:t}=i;return n(new RegExp(e,t),o)}case 5:{const e=n(new Map,o);for(const[t,r]of i)e.set(s(t),s(r));return e}case 6:{const e=n(new Set,o);for(const t of i)e.add(s(t));return e}case 7:{const{name:e,message:t}=i;return n(new r[e](t),o)}case 8:return n(BigInt(i),o);case"BigInt":return n(Object(BigInt(i)),o)}return n(new r[a](i),o)};return s})(new Map,e)(0),s="",{toString:o}={},{keys:a}=Object,i=e=>{const t=typeof e;if("object"!==t||!e)return[0,t];const r=o.call(e).slice(8,-1);switch(r){case"Array":return[1,s];case"Object":return[2,s];case"Date":return[3,s];case"RegExp":return[4,s];case"Map":return[5,s];case"Set":return[6,s]}return r.includes("Array")?[1,r]:r.includes("Error")?[7,r]:[2,r]},c=([e,t])=>0===e&&("function"===t||"symbol"===t),l=(e,{json:t,lossy:r}={})=>{const n=[];return((e,t,r,n)=>{const s=(e,t)=>{const s=n.push(e)-1;return r.set(t,s),s},o=n=>{if(r.has(n))return r.get(n);let[l,u]=i(n);switch(l){case 0:{let t=n;switch(u){case"bigint":l=8,t=n.toString();break;case"function":case"symbol":if(e)throw new TypeError("unable to serialize "+u);t=null;break;case"undefined":return s([-1],n)}return s([l,t],n)}case 1:{if(u)return s([u,[...n]],n);const e=[],t=s([l,e],n);for(const t of n)e.push(o(t));return t}case 2:{if(u)switch(u){case"BigInt":return s([u,n.toString()],n);case"Boolean":case"Number":case"String":return s([u,n.valueOf()],n)}if(t&&"toJSON"in n)return o(n.toJSON());const r=[],f=s([l,r],n);for(const t of a(n))!e&&c(i(n[t]))||r.push([o(t),o(n[t])]);return f}case 3:return s([l,n.toISOString()],n);case 4:{const{source:e,flags:t}=n;return s([l,{source:e,flags:t}],n)}case 5:{const t=[],r=s([l,t],n);for(const[r,s]of n)(e||!c(i(r))&&!c(i(s)))&&t.push([o(r),o(s)]);return r}case 6:{const t=[],r=s([l,t],n);for(const r of n)!e&&c(i(r))||t.push(o(r));return r}}const{message:f}=n;return s([l,{name:u,message:f}],n)};return o})(!(t||r),!!t,new Map,n)(e),n},{parse:u,stringify:f}=JSON,p={json:!0,lossy:!0};var d=Object.freeze({__proto__:null,parse:e=>n(u(e)),stringify:e=>f(l(e,p))});const h="ac6c1995-0675-46af-a99f-7fa298fa4e6d",y="M"+h,g="T"+h,w="array",m="function",b="null",v="number",$="object",S="string",E="symbol",k="undefined",P="apply",A="construct",j="defineProperty",x="deleteProperty",_="get",M="getOwnPropertyDescriptor",T="getPrototypeOf",O="has",W="isExtensible",R="ownKeys",J="preventExtensions",F="set",B="setPrototypeOf",I="delete";var L=e=>({value:new Promise((t=>{let r=new Worker("data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))");r.onmessage=t,r.postMessage(e)}))}) -/*! (c) Andrea Giammarchi - ISC */;const{Int32Array:N,Map:U,SharedArrayBuffer:C,Uint16Array:D}=globalThis,{BYTES_PER_ELEMENT:H}=N,{BYTES_PER_ELEMENT:q}=D,{isArray:z}=Array,{notify:X,wait:Y,waitAsync:K}=Atomics,G=new WeakSet,Q=new WeakMap,V={value:{then:e=>e()}};let Z=0;const ee=(e,{parse:t=JSON.parse,stringify:r=JSON.stringify,transform:n,interrupt:s}=JSON)=>{if(!Q.has(e)){const o=(t,...r)=>e.postMessage({[h]:r},{transfer:t}),a=typeof s===m?s:s?.handler,i=s?.delay||42,c=new TextDecoder("utf-16"),l=(e,t)=>e?(K||L)(t,0):(a?((e,t,r)=>{for(;"timed-out"===Y(e,0,0,t);)r()})(t,i,a):Y(t,0),V);let u=!1;Q.set(e,new Proxy(new U,{[O]:(e,t)=>"string"==typeof t&&!t.startsWith("_"),[_]:(r,s)=>"then"===s?null:(...r)=>{const a=Z++;let i=new N(new C(2*H)),f=[];G.has(r.at(-1)||f)&&G.delete(f=r.pop()),o(f,a,i,s,n?r.map(n):r);const p=e!==globalThis;let d=0;return u&&p&&(d=setTimeout(console.warn,1e3,`πŸ’€πŸ”’ - Possible deadlock if proxy.${s}(...args) is awaited`)),l(p,i).value.then((()=>{clearTimeout(d);const e=i[1];if(!e)return;const r=q*e;return i=new N(new C(r+r%H)),o([],a,i),l(p,i).value.then((()=>t(c.decode(new D(i.buffer).slice(0,e)))))}))},[F](t,s,o){const a=typeof o;if(a!==m)throw new Error(`Unable to assign ${s} as ${a}`);if(!t.size){const s=new U;e.addEventListener("message",(async e=>{const o=e.data?.[h];if(z(o)){e.stopImmediatePropagation();const[a,i,...c]=o;let l;if(c.length){const[e,o]=c;if(t.has(e)){u=!0;try{const c=await t.get(e)(...o);if(void 0!==c){const e=r(n?n(c):c);s.set(a,e),i[1]=e.length}}catch(e){l=e}finally{u=!1}}else l=new Error(`Unsupported action: ${e}`);i[0]=1}else{const e=s.get(a);s.delete(a);for(let t=new D(i.buffer),r=0;r(G.add(e),e);const{isArray:te}=Array,re=(e,t)=>t,ne=e=>typeof e===m?(e=>e())(e):e;function se(){return this}const oe=(e,t)=>e===w?[t]:{t:e,v:t},ae=(e,t=re)=>{let r=typeof e,n=e;return r===$&&(te(e)?(r=w,n=e.at(0)):({t:r,v:n}=e)),t(r,n)},ie=(e,t)=>e===m?t:oe(e,t),ce=(e,t=ie)=>{const r=null===e?b:typeof e;return t(r===$&&te(e)?w:r,e)},le=new FinalizationRegistry((([e,t,r])=>{r&&console.debug(`Held value ${String(t)} not relevant anymore`),e(t)})),ue=Object.create(null),fe=(e,t,{debug:r,return:n,token:s=e}=ue)=>{const o=n||new Proxy(e,ue),a=[o,[t,e,!!r]];return!1!==s&&a.push(s),le.register(...a),o},{defineProperty:pe,deleteProperty:de,getOwnPropertyDescriptor:he,getPrototypeOf:ye,isExtensible:ge,ownKeys:we,preventExtensions:me,set:be,setPrototypeOf:ve}=Reflect,{assign:$e,create:Se}=Object,Ee=ye(Int8Array),ke=(e,t)=>{const{get:r,set:n,value:s}=e;return r&&(e.get=t(r)),n&&(e.set=t(n)),s&&(e.value=t(s)),e},Pe=e=>t=>ce(t,((t,r)=>{switch(t){case b:return oe(b,r);case $:if(r===globalThis)return oe(t,null);case w:case m:return e(t,r);case"boolean":case v:case S:case k:case"bigint":return oe(t,r);case E:{if(Ae.has(r))return oe(t,Ae.get(r));let e=Symbol.keyFor(r);if(e)return oe(t,`.${e}`)}}throw new TypeError(`Unable to handle this ${t}: ${String(r)}`)})),Ae=new Map(we(Symbol).filter((e=>typeof Symbol[e]===E)).map((e=>[Symbol[e],e]))),je=e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,r]of Ae)if(r===e)return t},xe=e=>e;var _e=((e,t)=>{const r=t&&new WeakMap;if(t){const{addEventListener:e}=EventTarget.prototype;pe(EventTarget.prototype,"addEventListener",{value(t,n,...s){return s.at(0)?.invoke&&(r.has(this)||r.set(this,new Map),r.get(this).set(t,[].concat(s[0].invoke)),delete s[0].invoke),e.call(this,t,n,...s)}})}const n=t&&(e=>{const{currentTarget:t,target:n,type:s}=e;for(const o of r.get(t||n)?.get(s)||[])e[o]()});return function(r,s,o,...a){let i=0,c=this?.transform||xe;const l=new Map,u=new Map,{[o]:f}=r,p=a.length?$e(Se(globalThis),...a):globalThis,d=Pe(((e,t)=>{if(!l.has(t)){let r;for(;u.has(r=i++););l.set(t,r),u.set(r,e===m?t:c(t))}return oe(e,l.get(t))})),h=e=>{f(I,oe(S,e))},y=(e,r)=>{switch(e){case $:if(null==r)return p;case w:if(typeof r===v)return u.get(r);if(!(r instanceof Ee))for(const e in r)r[e]=g(r[e]);return r;case m:if(typeof r===S){if(!u.has(r)){const e=function(...e){return t&&e.at(0)instanceof Event&&n(...e),f(P,oe(m,r),d(this),e.map(d))};return u.set(r,new WeakRef(e)),fe(r,h,{return:e,token:!1})}return u.get(r).deref()}return u.get(r);case E:return je(r)}return r},g=e=>ae(e,y),b={[P]:(e,t,r)=>d(e.apply(t,r)),[A]:(e,t)=>d(new e(...t)),[j]:(e,t,r)=>d(pe(e,t,r)),[x]:(e,t)=>d(de(e,t)),[T]:e=>d(ye(e)),[_]:(e,t)=>d(e[t]),[M]:(e,t)=>{const r=he(e,t);return r?oe($,ke(r,d)):oe(k,r)},[O]:(e,t)=>d(t in e),[W]:e=>d(ge(e)),[R]:e=>oe(w,we(e).map(d)),[J]:e=>d(me(e)),[F]:(e,t,r)=>d(be(e,t,r)),[B]:(e,t)=>d(ve(e,t)),[I](e){l.delete(u.get(e)),u.delete(e)}};return r[s]=(e,t,...r)=>{switch(e){case P:r[0]=g(r[0]),r[1]=r[1].map(g);break;case A:r[0]=r[0].map(g);break;case j:{const[e,t]=r;r[0]=g(e);const{get:n,set:s,value:o}=t;n&&(t.get=g(n)),s&&(t.set=g(s)),o&&(t.value=g(o));break}default:r=r.map(g)}return b[e](g(t),...r)},{proxy:r,[e.toLowerCase()]:p,[`is${e}Proxy`]:()=>!1}}})("Window",!0),Me=(e=>{let t=0;const r=new Map,n=new Map,s=Symbol();return function(o,a,i){const c=this?.transform||xe,{[a]:l}=o,u=new Map,f=e=>{u.delete(e),l(I,p(e))},p=Pe(((e,o)=>{if(s in o)return ne(o[s]);if(e===m){if(o=c(o),!n.has(o)){let e;for(;n.has(e=String(t++)););r.set(o,e),n.set(e,o)}return oe(e,r.get(o))}if(!(o instanceof Ee)){o=c(o);for(const e in o)o[e]=p(o[e])}return oe(e,o)})),d=(e,t,r)=>{if(!u.has(r)){const n=t===m?(e=>se.bind(e))(e):e,s=new Proxy(n,g);return u.set(r,new WeakRef(s)),fe(r,f,{return:s,token:!1})}return u.get(r).deref()},h=e=>ae(e,((t,r)=>{switch(t){case $:if(null===r)return globalThis;case w:return typeof r===v?d(e,t,r):r;case m:return typeof r===S?n.get(r):d(e,t,r);case E:return je(r)}return r})),y=(e,t,...r)=>h(l(e,ne(t),...r)),g={[P]:(e,t,r)=>y(P,e,p(t),r.map(p)),[A]:(e,t)=>y(A,e,t.map(p)),[j]:(e,t,r)=>{const{get:n,set:s,value:o}=r;return typeof n===m&&(r.get=p(n)),typeof s===m&&(r.set=p(s)),typeof o===m&&(r.value=p(o)),y(j,e,p(t),r)},[x]:(e,t)=>y(x,e,p(t)),[T]:e=>y(T,e),[_]:(e,t)=>t===s?e:y(_,e,p(t)),[M]:(e,t)=>{const r=y(M,e,p(t));return r&&ke(r,h)},[O]:(e,t)=>t===s||y(O,e,p(t)),[W]:e=>y(W,e),[R]:e=>y(R,e).map(h),[J]:e=>y(J,e),[F]:(e,t,r)=>y(F,e,p(t),p(r)),[B]:(e,t)=>y(B,e,p(t))};o[i]=(e,t,s,o)=>{switch(e){case P:return h(t).apply(h(s),o.map(h));case I:{const e=h(t);r.delete(n.get(e)),n.delete(e)}}};const b=new Proxy(oe($,null),g);return{[e.toLowerCase()]:b,[`is${e}Proxy`]:e=>typeof e===$&&!!e&&s in e,proxy:o}}})("Window"),Te=typeof Worker===m?Worker:class{};const Oe=new WeakMap,We=(e,...t)=>{const r=ee(e,...t);if(!Oe.has(r)){const n=e instanceof Te?_e:Me;Oe.set(r,n.call(t.at(0),r,y,g))}return Oe.get(r)};We.transfer=ee.transfer;Promise.withResolvers||(Promise.withResolvers=function(){var e,t,r=new this((function(r,n){e=r,t=n}));return{resolve:e,reject:t,promise:r}});const Re=e=>e.arrayBuffer(),Je=e=>e.json(),Fe=e=>e.text();const Be={object(...e){return this.string(function(e){for(var t=e[0],r=1,n=arguments.length;r",">":">","'":"'","'":"'",""":'"',""":'"'},Ue=e=>Ne[e],Ce=(e,...t)=>Be[typeof e](e,...t),De=e=>Ie.call(e,Le,Ue),{isArray:He}=Array,{assign:qe,create:ze,defineProperties:Xe,defineProperty:Ye,entries:Ke}=Object,{all:Ge,resolve:Qe}=new Proxy(Promise,{get:(e,t)=>e[t].bind(e)}),Ve=(e,t=location.href)=>new URL(e,t.replace(/^blob:/,"")).href;let Ze=0;const et=(e,t)=>({id:e.id||(e.id=`${t}-w${Ze++}`),tag:e.tagName}),tt=(e,t,r,n=!1,s=CustomEvent)=>{e.dispatchEvent(new s(`${t}:${r}`,{bubbles:!0,detail:{worker:n}}))},rt=(e,t,r,n)=>({type:t,config:r,interpreter:n,io:ut.get(n),run:(t,...r)=>e.run(n,t,...r),runAsync:(t,...r)=>e.runAsync(n,t,...r),runEvent:(...t)=>e.runEvent(n,...t)}),nt=(e,t)=>(r,n)=>{const s=e[t].bind(e);e[t]=(e,t,...o)=>s(e,`${n?r:t}\n${n?t:r}`,...o)},st=Symbol.for("polyscript.js_modules"),ot=new Map;Ye(globalThis,st,{value:ot});const at=new Proxy(ot,{get:(e,t)=>e.get(t)}),it=(e,t)=>import(e).then((e=>{ot.set(t,{...e})})),ct=e=>new Promise(((t,r)=>{document.querySelector(`link[href="${e}"]`)&&t(),document.head.append(qe(document.createElement("link"),{rel:"stylesheet",href:e,onload:t,onerror:r}))})),lt=e=>/\.css/i.test(new URL(e).pathname),ut=new WeakMap,ft=e=>{const t=e||console,r={stderr:(t.stderr||console.error).bind(t),stdout:(t.stdout||console.log).bind(t)};return{stderr:(...e)=>r.stderr(...e),stdout:(...e)=>r.stdout(...e),async get(e){const t=await e;return ut.set(t,r),t}}},pt=({FS:e,PATH:t,PATH_FS:r},n,s)=>{const o=r.resolve(n);return e.mkdirTree(t.dirname(o)),e.writeFile(o,new Uint8Array(s),{canOwn:!0})},dt=e=>{const t=e.split("/");return t.pop(),t.join("/")},ht=(e,t)=>{const r=[];for(const n of t.split("/"))"."!==n&&(r.push(n),n&&e.mkdir(r.join("/")))},yt=(e,t)=>{const r=[];for(const e of t.split("/"))switch(e){case"":case".":break;case"..":r.pop();break;default:r.push(e)}return[e.cwd()].concat(r).join("/").replace(/^\/+/,"/")},gt=e=>{const t=e.map((e=>e.trim().replace(/(^[/]*|[/]*$)/g,""))).filter((e=>""!==e&&"."!==e)).join("/");return e[0].startsWith("/")?`/${t}`:t},wt=(e,t)=>fetch(Ve(t,mt.get(e))),mt=new WeakMap,bt=(e,t,r)=>Ge((e=>{for(const{files:t,to_file:r,from:n=""}of e){if(void 0!==t&&void 0!==r)throw new Error("Cannot use 'to_file' and 'files' parameters together!");if(void 0===t&&void 0===r&&n.endsWith("/"))throw new Error(`Couldn't determine the filename from the path ${n}, please supply 'to_file' parameter.`)}return e.flatMap((({from:e="",to_folder:t=".",to_file:r,files:n})=>{if(He(n))return n.map((r=>({url:gt([e,r]),path:gt([t,r])})));const s=r||e.slice(1+e.lastIndexOf("/"));return[{url:e,path:gt([t,s])}]}))})(r).map((({url:n,path:s})=>wt(r,n).then(Re).then((r=>e.writeFile(t,s,r)))))),vt=(e,t)=>t.endsWith("/")?`${t}${e.split("/").pop()}`:t,$t=(e,t)=>e.replace(/\{.+?\}/g,(e=>{if(!t.has(e))throw new SyntaxError(`Invalid template: ${e}`);return t.get(e)})),St=(e,t,r)=>Ge((e=>{const t=new Map,r=new Set,n=[];for(const[s,o]of Ke(e))if(/^\{.+\}$/.test(s)){if(t.has(s))throw new SyntaxError(`Duplicated template: ${s}`);t.set(s,$t(o,t))}else{const e=$t(s,t),a=vt(e,$t(o||"./",t));if(r.has(a))throw new SyntaxError(`Duplicated destination: ${a}`);r.add(a),n.push({url:e,path:a})}return n})(r).map((({url:n,path:s})=>wt(r,n).then(Re).then((r=>e.writeFile(t,s,r)))))),Et=typeof document===k,kt=({main:e,worker:t})=>{const r=[];if(t&&Et)for(let[e,n]of Ke(t))e=Ve(e,mt.get(t)),r.push(it(e,n));if(e&&!Et)for(let[t,n]of Ke(e))t=Ve(t,mt.get(e)),lt(t)?ct(t):r.push(it(t,n));return Ge(r)},Pt=(e,t,r)=>{e.registerJsModule(t,r)},At=(e,t,...r)=>{try{return e.runPython(Ce(t),...r)}catch(t){ut.get(e).stderr(t)}},jt=async(e,t,...r)=>{try{return await e.runPythonAsync(Ce(t),...r)}catch(t){ut.get(e).stderr(t)}},xt=async(e,t,r)=>{const[n,...s]=t.split(".");let o,a=e.globals.get(n);for(const e of s)[o,a]=[a,a[e]];try{await a.call(o,r)}catch(t){ut.get(e).stderr(t)}};var _t={type:"micropython",module:(e="1.21.0-278")=>`https://cdn.jsdelivr.net/npm/@micropython/micropython-webassembly-pyscript@${e}/micropython.mjs`,async engine({loadMicroPython:e},t,r){const{stderr:n,stdout:s,get:o}=ft();r=r.replace(/\.m?js$/,".wasm");const a=await o(e({stderr:n,stdout:s,url:r}));return t.files&&await St(this,a,t.files),t.fetch&&await bt(this,a,t.fetch),t.js_modules&&await kt(t.js_modules),a},registerJSModule:Pt,run:At,runAsync:jt,runEvent:xt,transform:(e,t)=>t instanceof e.PyProxy?e.PyProxy.toJs(t):t,writeFile:({FS:e,_module:{PATH:t,PATH_FS:r}},n,s)=>pt({FS:e,PATH:t,PATH_FS:r},n,s)};const Mt={dict_converter:Object.fromEntries};var Tt={type:"pyodide",module:(e="0.24.1")=>`https://cdn.jsdelivr.net/pyodide/v${e}/full/pyodide.mjs`,async engine({loadPyodide:e},t,r){const{stderr:n,stdout:s,get:o}=ft(),a=r.slice(0,r.lastIndexOf("/")),i=await o(e({stderr:n,stdout:s,indexURL:a}));if(t.files&&await St(this,i,t.files),t.fetch&&await bt(this,i,t.fetch),t.js_modules&&await kt(t.js_modules),t.packages){await i.loadPackage("micropip");const e=await i.pyimport("micropip");await e.install(t.packages,{keep_going:!0}),e.destroy()}return i},registerJSModule:Pt,run:At,runAsync:jt,runEvent:xt,transform:(e,t)=>t instanceof e.ffi.PyProxy?t.toJs(Mt):t,writeFile:({FS:e,PATH:t,_module:{PATH_FS:r}},n,s)=>pt({FS:e,PATH:t,PATH_FS:r},n,s)};const Ot="ruby-wasm-wasi",Wt=Ot.replace(/\W+/g,"_");var Rt={type:Ot,experimental:!0,module:(e="2.2.0")=>`https://cdn.jsdelivr.net/npm/ruby-3_2-wasm-wasi@${e}/dist/browser.esm.js`,async engine({DefaultRubyVM:e},t,r){const n=await fetch(`${r.slice(0,r.lastIndexOf("/"))}/ruby.wasm`),s=await WebAssembly.compile(await n.arrayBuffer()),{vm:o}=await e(s);return t.files&&await St(this,o,t.files),t.fetch&&await bt(this,o,t.fetch),t.js_modules&&await kt(t.js_modules),o},registerJSModule(e,t,r){const n=`__module_${Wt}_${t}`;globalThis[n]=r,this.run(e,`require "js";$${t}=JS.global[:${n}]`),delete globalThis[n]},run:(e,t,...r)=>e.eval(Ce(t),...r),runAsync:(e,t,...r)=>e.evalAsync(Ce(t),...r),async runEvent(e,t,r){if(/^xworker\.(on\w+)$/.test(t)){const{$1:t}=RegExp,n=`__module_${Wt}_event`;globalThis[n]=r,this.run(e,`require "js";$xworker.call("${t}",JS.global[:${n}])`),delete globalThis[n]}else{const n=this.run(e,`method(:${t})`);await n.call(t,e.wrap(r))}},transform:(e,t)=>t,writeFile:()=>{throw new Error(`writeFile is not supported in ${Ot}`)}};var Jt={type:"wasmoon",module:(e="1.16.0")=>`https://cdn.jsdelivr.net/npm/wasmoon@${e}/+esm`,async engine({LuaFactory:e,LuaLibraries:t},r){const{stderr:n,stdout:s,get:o}=ft(),a=await o((new e).createEngine());return a.global.getTable(t.Base,(e=>{a.global.setField(e,"print",s),a.global.setField(e,"printErr",n)})),r.files&&await St(this,a,r.files),r.fetch&&await bt(this,a,r.fetch),r.js_modules&&await kt(r.js_modules),a},registerJSModule:(e,t,r)=>{e.global.set(t,r)},run:(e,t,...r)=>{try{return e.doStringSync(Ce(t),...r)}catch(t){ut.get(e).stderr(t)}},runAsync:async(e,t,...r)=>{try{return await e.doString(Ce(t),...r)}catch(t){ut.get(e).stderr(t)}},runEvent:async(e,t,r)=>{const[n,...s]=t.split(".");let o,a=e.global.get(n);for(const e of s)[o,a]=[a,a[e]];try{await a.call(o,r)}catch(t){ut.get(e).stderr(t)}},transform:(e,t)=>t,writeFile:({cmodule:{module:{FS:e}}},t,r)=>((e,t,r)=>(ht(e,dt(t)),t=yt(e,t),e.writeFile(t,new Uint8Array(r),{canOwn:!0})))(e,t,r)};const Ft=new Map,Bt=new Map,It=[],Lt=[],Nt=new Proxy(new Map,{get(e,t){if(!e.has(t)){const[r,...n]=t.split("@"),s=Ft.get(r),o=/^(?:\.?\.?\/|https?:\/\/)/i.test(n)?n.join("@"):s.module(...n);e.set(t,{url:o,module:import(o),engine:s.engine.bind(s)})}const{url:r,module:n,engine:s}=e.get(t);return(e,o)=>n.then((n=>{Bt.set(t,e);for(const t of["files","fetch"]){const r=e?.[t];r&&mt.set(r,o)}for(const t of["main","worker"]){const r=e?.js_modules?.[t];r&&mt.set(r,o)}return s(n,e,r)}))}}),Ut=e=>{for(const t of[].concat(e.type))Ft.set(t,e),It.push(`script[type="${t}"]`),Lt.push(`${t}-`)};for(const e of[_t,Tt,Rt,Jt])Ut(e);const Ct=async e=>(await import("https://cdn.jsdelivr.net/npm/basic-toml@0.3.1/es.js")).parse(e),Dt=e=>{let t=typeof e;return"string"===t&&/\.(json|toml|txt)$/.test(e)?t=RegExp.$1:e="./config.txt",[Ve(e),t]},Ht=(e,t,r={})=>{if(t){const[e,n]=Dt(t);if("json"===n)r=fetch(e).then(Je);else if("toml"===n)r=fetch(e).then(Fe).then(Ct);else if("string"===n)try{r=JSON.parse(t)}catch(e){r=Ct(t)}else"object"===n&&t&&(r=t);t=e}return Qe(r).then((r=>Nt[e](r,t)))},qt=(e,t="")=>`${e}@${t}`.replace(/@$/,""),zt="BeforeRun",Xt="AfterRun",Yt=[`code${zt}`,`code${zt}Async`,`code${Xt}`,`code${Xt}Async`],Kt=["onWorker","onReady",`on${zt}`,`on${zt}Async`,`on${Xt}`,`on${Xt}Async`];function Gt(e,t){const{run:r,runAsync:n}=Ft.get(this.type);return{...e,run:r.bind(this,t),runAsync:n.bind(this,t)}}const Qt=(e,t,r,n,s,o)=>{if(s||o){const a=Gt.bind(e,t),i=n?"runAsync":"run",c=e[i];e[i]=n?async function(e,t,...n){s&&await s.call(this,a(e),r);const i=await c.call(this,e,t,...n);return o&&await o.call(this,a(e),r),i}:function(e,t,...n){s&&s.call(this,a(e),r);const i=c.call(this,e,t,...n);return o&&o.call(this,a(e),r),i}}};let Vt=class{constructor(e,t={}){const{main:r,worker:n}=t;this.interpreter=e,this.onWorker=r?.onWorker;for(const e of Kt.slice(1))this[e]=n?.[e];for(const e of Yt)this[e]=n?.[e]}toJSON(){const e={};for(const t of Kt.slice(1))this[t]&&(e[t]=String(this[t]));for(const t of Yt)this[t]&&(e[t]=Ce(this[t]()));return e}};var Zt=(...e)=>function(t,r){const n=new Worker(URL.createObjectURL(new Blob(['const e="object"==typeof self?self:globalThis,t=t=>((t,r)=>{const n=(e,r)=>(t.set(r,e),e),s=o=>{if(t.has(o))return t.get(o);const[a,i]=r[o];switch(a){case 0:case-1:return n(i,o);case 1:{const e=n([],o);for(const t of i)e.push(s(t));return e}case 2:{const e=n({},o);for(const[t,r]of i)e[s(t)]=s(r);return e}case 3:return n(new Date(i),o);case 4:{const{source:e,flags:t}=i;return n(new RegExp(e,t),o)}case 5:{const e=n(new Map,o);for(const[t,r]of i)e.set(s(t),s(r));return e}case 6:{const e=n(new Set,o);for(const t of i)e.add(s(t));return e}case 7:{const{name:t,message:r}=i;return n(new e[t](r),o)}case 8:return n(BigInt(i),o);case"BigInt":return n(Object(BigInt(i)),o)}return n(new e[a](i),o)};return s})(new Map,t)(0),r="",{toString:n}={},{keys:s}=Object,o=e=>{const t=typeof e;if("object"!==t||!e)return[0,t];const s=n.call(e).slice(8,-1);switch(s){case"Array":return[1,r];case"Object":return[2,r];case"Date":return[3,r];case"RegExp":return[4,r];case"Map":return[5,r];case"Set":return[6,r]}return s.includes("Array")?[1,s]:s.includes("Error")?[7,s]:[2,s]},a=([e,t])=>0===e&&("function"===t||"symbol"===t),i=(e,{json:t,lossy:r}={})=>{const n=[];return((e,t,r,n)=>{const i=(e,t)=>{const s=n.push(e)-1;return r.set(t,s),s},c=n=>{if(r.has(n))return r.get(n);let[l,u]=o(n);switch(l){case 0:{let t=n;switch(u){case"bigint":l=8,t=n.toString();break;case"function":case"symbol":if(e)throw new TypeError("unable to serialize "+u);t=null;break;case"undefined":return i([-1],n)}return i([l,t],n)}case 1:{if(u)return i([u,[...n]],n);const e=[],t=i([l,e],n);for(const t of n)e.push(c(t));return t}case 2:{if(u)switch(u){case"BigInt":return i([u,n.toString()],n);case"Boolean":case"Number":case"String":return i([u,n.valueOf()],n)}if(t&&"toJSON"in n)return c(n.toJSON());const r=[],f=i([l,r],n);for(const t of s(n))!e&&a(o(n[t]))||r.push([c(t),c(n[t])]);return f}case 3:return i([l,n.toISOString()],n);case 4:{const{source:e,flags:t}=n;return i([l,{source:e,flags:t}],n)}case 5:{const t=[],r=i([l,t],n);for(const[r,s]of n)(e||!a(o(r))&&!a(o(s)))&&t.push([c(r),c(s)]);return r}case 6:{const t=[],r=i([l,t],n);for(const r of n)!e&&a(o(r))||t.push(c(r));return r}}const{message:f}=n;return i([l,{name:u,message:f}],n)};return c})(!(t||r),!!t,new Map,n)(e),n},{parse:c,stringify:l}=JSON,u={json:!0,lossy:!0};var f=Object.freeze({__proto__:null,parse:e=>t(c(e)),stringify:e=>l(i(e,u))});const p="ac6c1995-0675-46af-a99f-7fa298fa4e6d",d="M"+p,y="T"+p,h="array",g="function",w="null",m="number",b="object",v="string",S="symbol",$="undefined",E="apply",P="construct",A="defineProperty",j="deleteProperty",_="get",k="getOwnPropertyDescriptor",x="getPrototypeOf",M="has",T="isExtensible",O="ownKeys",W="preventExtensions",F="set",R="setPrototypeOf",B="delete";var J=e=>({value:new Promise((t=>{let r=new Worker("data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))");r.onmessage=t,r.postMessage(e)}))})\n/*! (c) Andrea Giammarchi - ISC */;const{Int32Array:I,Map:L,SharedArrayBuffer:C,Uint16Array:D}=globalThis,{BYTES_PER_ELEMENT:H}=I,{BYTES_PER_ELEMENT:N}=D,{isArray:U}=Array,{notify:q,wait:z,waitAsync:K}=Atomics,Y=new WeakSet,G=new WeakMap,V={value:{then:e=>e()}};let Q=0;const X=(e,{parse:t=JSON.parse,stringify:r=JSON.stringify,transform:n,interrupt:s}=JSON)=>{if(!G.has(e)){const o=(t,...r)=>e.postMessage({[p]:r},{transfer:t}),a=typeof s===g?s:s?.handler,i=s?.delay||42,c=new TextDecoder("utf-16"),l=(e,t)=>e?(K||J)(t,0):(a?((e,t,r)=>{for(;"timed-out"===z(e,0,0,t);)r()})(t,i,a):z(t,0),V);let u=!1;G.set(e,new Proxy(new L,{[M]:(e,t)=>"string"==typeof t&&!t.startsWith("_"),[_]:(r,s)=>"then"===s?null:(...r)=>{const a=Q++;let i=new I(new C(2*H)),f=[];Y.has(r.at(-1)||f)&&Y.delete(f=r.pop()),o(f,a,i,s,n?r.map(n):r);const p=e!==globalThis;let d=0;return u&&p&&(d=setTimeout(console.warn,1e3,`πŸ’€πŸ”’ - Possible deadlock if proxy.${s}(...args) is awaited`)),l(p,i).value.then((()=>{clearTimeout(d);const e=i[1];if(!e)return;const r=N*e;return i=new I(new C(r+r%H)),o([],a,i),l(p,i).value.then((()=>t(c.decode(new D(i.buffer).slice(0,e)))))}))},[F](t,s,o){const a=typeof o;if(a!==g)throw new Error(`Unable to assign ${s} as ${a}`);if(!t.size){const s=new L;e.addEventListener("message",(async e=>{const o=e.data?.[p];if(U(o)){e.stopImmediatePropagation();const[a,i,...c]=o;let l;if(c.length){const[e,o]=c;if(t.has(e)){u=!0;try{const c=await t.get(e)(...o);if(void 0!==c){const e=r(n?n(c):c);s.set(a,e),i[1]=e.length}}catch(e){l=e}finally{u=!1}}else l=new Error(`Unsupported action: ${e}`);i[0]=1}else{const e=s.get(a);s.delete(a);for(let t=new D(i.buffer),r=0;r(Y.add(e),e);const{isArray:Z}=Array,ee=(e,t)=>t,te=e=>typeof e===g?(e=>e())(e):e;function re(){return this}const ne=(e,t)=>e===h?[t]:{t:e,v:t},se=(e,t=ee)=>{let r=typeof e,n=e;return r===b&&(Z(e)?(r=h,n=e.at(0)):({t:r,v:n}=e)),t(r,n)},oe=(e,t)=>e===g?t:ne(e,t),ae=(e,t=oe)=>{const r=null===e?w:typeof e;return t(r===b&&Z(e)?h:r,e)},ie=new FinalizationRegistry((([e,t,r])=>{r&&console.debug(`Held value ${String(t)} not relevant anymore`),e(t)})),ce=Object.create(null),le=(e,t,{debug:r,return:n,token:s=e}=ce)=>{const o=n||new Proxy(e,ce),a=[o,[t,e,!!r]];return!1!==s&&a.push(s),ie.register(...a),o},{defineProperty:ue,deleteProperty:fe,getOwnPropertyDescriptor:pe,getPrototypeOf:de,isExtensible:ye,ownKeys:he,preventExtensions:ge,set:we,setPrototypeOf:me}=Reflect,{assign:be,create:ve}=Object,Se=de(Int8Array),$e=(e,t)=>{const{get:r,set:n,value:s}=e;return r&&(e.get=t(r)),n&&(e.set=t(n)),s&&(e.value=t(s)),e},Ee=e=>t=>ae(t,((t,r)=>{switch(t){case w:return ne(w,r);case b:if(r===globalThis)return ne(t,null);case h:case g:return e(t,r);case"boolean":case m:case v:case $:case"bigint":return ne(t,r);case S:{if(Pe.has(r))return ne(t,Pe.get(r));let e=Symbol.keyFor(r);if(e)return ne(t,`.${e}`)}}throw new TypeError(`Unable to handle this ${t}: ${String(r)}`)})),Pe=new Map(he(Symbol).filter((e=>typeof Symbol[e]===S)).map((e=>[Symbol[e],e]))),Ae=e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,r]of Pe)if(r===e)return t},je=e=>e;var _e=((e,t)=>{const r=t&&new WeakMap;if(t){const{addEventListener:e}=EventTarget.prototype;ue(EventTarget.prototype,"addEventListener",{value(t,n,...s){return s.at(0)?.invoke&&(r.has(this)||r.set(this,new Map),r.get(this).set(t,[].concat(s[0].invoke)),delete s[0].invoke),e.call(this,t,n,...s)}})}const n=t&&(e=>{const{currentTarget:t,target:n,type:s}=e;for(const o of r.get(t||n)?.get(s)||[])e[o]()});return function(r,s,o,...a){let i=0,c=this?.transform||je;const l=new Map,u=new Map,{[o]:f}=r,p=a.length?be(ve(globalThis),...a):globalThis,d=Ee(((e,t)=>{if(!l.has(t)){let r;for(;u.has(r=i++););l.set(t,r),u.set(r,e===g?t:c(t))}return ne(e,l.get(t))})),y=e=>{f(B,ne(v,e))},w=(e,r)=>{switch(e){case b:if(null==r)return p;case h:if(typeof r===m)return u.get(r);if(!(r instanceof Se))for(const e in r)r[e]=J(r[e]);return r;case g:if(typeof r===v){if(!u.has(r)){const e=function(...e){return t&&e.at(0)instanceof Event&&n(...e),f(E,ne(g,r),d(this),e.map(d))};return u.set(r,new WeakRef(e)),le(r,y,{return:e,token:!1})}return u.get(r).deref()}return u.get(r);case S:return Ae(r)}return r},J=e=>se(e,w),I={[E]:(e,t,r)=>d(e.apply(t,r)),[P]:(e,t)=>d(new e(...t)),[A]:(e,t,r)=>d(ue(e,t,r)),[j]:(e,t)=>d(fe(e,t)),[x]:e=>d(de(e)),[_]:(e,t)=>d(e[t]),[k]:(e,t)=>{const r=pe(e,t);return r?ne(b,$e(r,d)):ne($,r)},[M]:(e,t)=>d(t in e),[T]:e=>d(ye(e)),[O]:e=>ne(h,he(e).map(d)),[W]:e=>d(ge(e)),[F]:(e,t,r)=>d(we(e,t,r)),[R]:(e,t)=>d(me(e,t)),[B](e){l.delete(u.get(e)),u.delete(e)}};return r[s]=(e,t,...r)=>{switch(e){case E:r[0]=J(r[0]),r[1]=r[1].map(J);break;case P:r[0]=r[0].map(J);break;case A:{const[e,t]=r;r[0]=J(e);const{get:n,set:s,value:o}=t;n&&(t.get=J(n)),s&&(t.set=J(s)),o&&(t.value=J(o));break}default:r=r.map(J)}return I[e](J(t),...r)},{proxy:r,[e.toLowerCase()]:p,[`is${e}Proxy`]:()=>!1}}})("Window",!0),ke=(e=>{let t=0;const r=new Map,n=new Map,s=Symbol();return function(o,a,i){const c=this?.transform||je,{[a]:l}=o,u=new Map,f=e=>{u.delete(e),l(B,p(e))},p=Ee(((e,o)=>{if(s in o)return te(o[s]);if(e===g){if(o=c(o),!n.has(o)){let e;for(;n.has(e=String(t++)););r.set(o,e),n.set(e,o)}return ne(e,r.get(o))}if(!(o instanceof Se)){o=c(o);for(const e in o)o[e]=p(o[e])}return ne(e,o)})),d=(e,t,r)=>{if(!u.has(r)){const n=t===g?(e=>re.bind(e))(e):e,s=new Proxy(n,$);return u.set(r,new WeakRef(s)),le(r,f,{return:s,token:!1})}return u.get(r).deref()},y=e=>se(e,((t,r)=>{switch(t){case b:if(null===r)return globalThis;case h:return typeof r===m?d(e,t,r):r;case g:return typeof r===v?n.get(r):d(e,t,r);case S:return Ae(r)}return r})),w=(e,t,...r)=>y(l(e,te(t),...r)),$={[E]:(e,t,r)=>w(E,e,p(t),r.map(p)),[P]:(e,t)=>w(P,e,t.map(p)),[A]:(e,t,r)=>{const{get:n,set:s,value:o}=r;return typeof n===g&&(r.get=p(n)),typeof s===g&&(r.set=p(s)),typeof o===g&&(r.value=p(o)),w(A,e,p(t),r)},[j]:(e,t)=>w(j,e,p(t)),[x]:e=>w(x,e),[_]:(e,t)=>t===s?e:w(_,e,p(t)),[k]:(e,t)=>{const r=w(k,e,p(t));return r&&$e(r,y)},[M]:(e,t)=>t===s||w(M,e,p(t)),[T]:e=>w(T,e),[O]:e=>w(O,e).map(y),[W]:e=>w(W,e),[F]:(e,t,r)=>w(F,e,p(t),p(r)),[R]:(e,t)=>w(R,e,p(t))};o[i]=(e,t,s,o)=>{switch(e){case E:return y(t).apply(y(s),o.map(y));case B:{const e=y(t);r.delete(n.get(e)),n.delete(e)}}};const J=new Proxy(ne(b,null),$);return{[e.toLowerCase()]:J,[`is${e}Proxy`]:e=>typeof e===b&&!!e&&s in e,proxy:o}}})("Window"),xe=typeof Worker===g?Worker:class{};const Me=new WeakMap,Te=(e,...t)=>{const r=X(e,...t);if(!Me.has(r)){const n=e instanceof xe?_e:ke;Me.set(r,n.call(t.at(0),r,d,y))}return Me.get(r)};Te.transfer=X.transfer;const Oe={object(...e){return this.string(function(e){for(var t=e[0],r=1,n=arguments.length;re.arrayBuffer(),Fe=e=>e.json(),Re=e=>e.text(),Be=new WeakMap,Je=e=>{const t=e||console,r={stderr:(t.stderr||console.error).bind(t),stdout:(t.stdout||console.log).bind(t)};return{stderr:(...e)=>r.stderr(...e),stdout:(...e)=>r.stdout(...e),async get(e){const t=await e;return Be.set(t,r),t}}},Ie=({FS:e,PATH:t,PATH_FS:r},n,s)=>{const o=r.resolve(n);return e.mkdirTree(t.dirname(o)),e.writeFile(o,new Uint8Array(s),{canOwn:!0})},Le=e=>{const t=e.split("/");return t.pop(),t.join("/")},Ce=(e,t)=>{const r=[];for(const n of t.split("/"))"."!==n&&(r.push(n),n&&e.mkdir(r.join("/")))},De=(e,t)=>{const r=[];for(const e of t.split("/"))switch(e){case"":case".":break;case"..":r.pop();break;default:r.push(e)}return[e.cwd()].concat(r).join("/").replace(/^\\/+/,"/")},He=e=>{const t=e.map((e=>e.trim().replace(/(^[/]*|[/]*$)/g,""))).filter((e=>""!==e&&"."!==e)).join("/");return e[0].startsWith("/")?`/${t}`:t},Ne=(e,t)=>fetch(at(t,Ue.get(e))),Ue=new WeakMap,qe=(e,t,r)=>st((e=>{for(const{files:t,to_file:r,from:n=""}of e){if(void 0!==t&&void 0!==r)throw new Error("Cannot use \'to_file\' and \'files\' parameters together!");if(void 0===t&&void 0===r&&n.endsWith("/"))throw new Error(`Couldn\'t determine the filename from the path ${n}, please supply \'to_file\' parameter.`)}return e.flatMap((({from:e="",to_folder:t=".",to_file:r,files:n})=>{if(Xe(n))return n.map((r=>({url:He([e,r]),path:He([t,r])})));const s=r||e.slice(1+e.lastIndexOf("/"));return[{url:e,path:He([t,s])}]}))})(r).map((({url:n,path:s})=>Ne(r,n).then(We).then((r=>e.writeFile(t,s,r)))))),ze=(e,t)=>t.endsWith("/")?`${t}${e.split("/").pop()}`:t,Ke=(e,t)=>e.replace(/\\{.+?\\}/g,(e=>{if(!t.has(e))throw new SyntaxError(`Invalid template: ${e}`);return t.get(e)})),Ye=(e,t,r)=>st((e=>{const t=new Map,r=new Set,n=[];for(const[s,o]of nt(e))if(/^\\{.+\\}$/.test(s)){if(t.has(s))throw new SyntaxError(`Duplicated template: ${s}`);t.set(s,Ke(o,t))}else{const e=Ke(s,t),a=ze(e,Ke(o||"./",t));if(r.has(a))throw new SyntaxError(`Duplicated destination: ${a}`);r.add(a),n.push({url:e,path:a})}return n})(r).map((({url:n,path:s})=>Ne(r,n).then(We).then((r=>e.writeFile(t,s,r)))))),Ge=typeof document===$,Ve=({main:e,worker:t})=>{const r=[];if(t&&Ge)for(let[e,n]of nt(t))e=at(e,Ue.get(t)),r.push(ft(e,n));if(e&&!Ge)for(let[t,n]of nt(e))t=at(t,Ue.get(e)),dt(t)?pt(t):r.push(ft(t,n));return st(r)},Qe=(e,...t)=>Oe[typeof e](e,...t),{isArray:Xe}=Array,{assign:Ze,create:et,defineProperties:tt,defineProperty:rt,entries:nt}=Object,{all:st,resolve:ot}=new Proxy(Promise,{get:(e,t)=>e[t].bind(e)}),at=(e,t=location.href)=>new URL(e,t.replace(/^blob:/,"")).href,it=(e,t,r,n=!1,s=CustomEvent)=>{e.dispatchEvent(new s(`${t}:${r}`,{bubbles:!0,detail:{worker:n}}))},ct=e=>Function(`\'use strict\';return (${e})`)(),lt=Symbol.for("polyscript.js_modules"),ut=new Map;rt(globalThis,lt,{value:ut}),new Proxy(ut,{get:(e,t)=>e.get(t)});const ft=(e,t)=>import(e).then((e=>{ut.set(t,{...e})})),pt=e=>new Promise(((t,r)=>{document.querySelector(`link[href="${e}"]`)&&t(),document.head.append(Ze(document.createElement("link"),{rel:"stylesheet",href:e,onload:t,onerror:r}))})),dt=e=>/\\.css/i.test(new URL(e).pathname),yt=(e,t,r)=>{e.registerJsModule(t,r)},ht=(e,t,...r)=>{try{return e.runPython(Qe(t),...r)}catch(t){Be.get(e).stderr(t)}},gt=async(e,t,...r)=>{try{return await e.runPythonAsync(Qe(t),...r)}catch(t){Be.get(e).stderr(t)}},wt=async(e,t,r)=>{const[n,...s]=t.split(".");let o,a=e.globals.get(n);for(const e of s)[o,a]=[a,a[e]];try{await a.call(o,r)}catch(t){Be.get(e).stderr(t)}};var mt={type:"micropython",module:(e="1.21.0-278")=>`https://cdn.jsdelivr.net/npm/@micropython/micropython-webassembly-pyscript@${e}/micropython.mjs`,async engine({loadMicroPython:e},t,r){const{stderr:n,stdout:s,get:o}=Je();r=r.replace(/\\.m?js$/,".wasm");const a=await o(e({stderr:n,stdout:s,url:r}));return t.files&&await Ye(this,a,t.files),t.fetch&&await qe(this,a,t.fetch),t.js_modules&&await Ve(t.js_modules),a},registerJSModule:yt,run:ht,runAsync:gt,runEvent:wt,transform:(e,t)=>t instanceof e.PyProxy?e.PyProxy.toJs(t):t,writeFile:({FS:e,_module:{PATH:t,PATH_FS:r}},n,s)=>Ie({FS:e,PATH:t,PATH_FS:r},n,s)};const bt={dict_converter:Object.fromEntries};var vt={type:"pyodide",module:(e="0.24.1")=>`https://cdn.jsdelivr.net/pyodide/v${e}/full/pyodide.mjs`,async engine({loadPyodide:e},t,r){const{stderr:n,stdout:s,get:o}=Je(),a=r.slice(0,r.lastIndexOf("/")),i=await o(e({stderr:n,stdout:s,indexURL:a}));if(t.files&&await Ye(this,i,t.files),t.fetch&&await qe(this,i,t.fetch),t.js_modules&&await Ve(t.js_modules),t.packages){await i.loadPackage("micropip");const e=await i.pyimport("micropip");await e.install(t.packages,{keep_going:!0}),e.destroy()}return i},registerJSModule:yt,run:ht,runAsync:gt,runEvent:wt,transform:(e,t)=>t instanceof e.ffi.PyProxy?t.toJs(bt):t,writeFile:({FS:e,PATH:t,_module:{PATH_FS:r}},n,s)=>Ie({FS:e,PATH:t,PATH_FS:r},n,s)};const St="ruby-wasm-wasi",$t=St.replace(/\\W+/g,"_");var Et={type:St,experimental:!0,module:(e="2.2.0")=>`https://cdn.jsdelivr.net/npm/ruby-3_2-wasm-wasi@${e}/dist/browser.esm.js`,async engine({DefaultRubyVM:e},t,r){const n=await fetch(`${r.slice(0,r.lastIndexOf("/"))}/ruby.wasm`),s=await WebAssembly.compile(await n.arrayBuffer()),{vm:o}=await e(s);return t.files&&await Ye(this,o,t.files),t.fetch&&await qe(this,o,t.fetch),t.js_modules&&await Ve(t.js_modules),o},registerJSModule(e,t,r){const n=`__module_${$t}_${t}`;globalThis[n]=r,this.run(e,`require "js";$${t}=JS.global[:${n}]`),delete globalThis[n]},run:(e,t,...r)=>e.eval(Qe(t),...r),runAsync:(e,t,...r)=>e.evalAsync(Qe(t),...r),async runEvent(e,t,r){if(/^xworker\\.(on\\w+)$/.test(t)){const{$1:t}=RegExp,n=`__module_${$t}_event`;globalThis[n]=r,this.run(e,`require "js";$xworker.call("${t}",JS.global[:${n}])`),delete globalThis[n]}else{const n=this.run(e,`method(:${t})`);await n.call(t,e.wrap(r))}},transform:(e,t)=>t,writeFile:()=>{throw new Error(`writeFile is not supported in ${St}`)}};var Pt={type:"wasmoon",module:(e="1.16.0")=>`https://cdn.jsdelivr.net/npm/wasmoon@${e}/+esm`,async engine({LuaFactory:e,LuaLibraries:t},r){const{stderr:n,stdout:s,get:o}=Je(),a=await o((new e).createEngine());return a.global.getTable(t.Base,(e=>{a.global.setField(e,"print",s),a.global.setField(e,"printErr",n)})),r.files&&await Ye(this,a,r.files),r.fetch&&await qe(this,a,r.fetch),r.js_modules&&await Ve(r.js_modules),a},registerJSModule:(e,t,r)=>{e.global.set(t,r)},run:(e,t,...r)=>{try{return e.doStringSync(Qe(t),...r)}catch(t){Be.get(e).stderr(t)}},runAsync:async(e,t,...r)=>{try{return await e.doString(Qe(t),...r)}catch(t){Be.get(e).stderr(t)}},runEvent:async(e,t,r)=>{const[n,...s]=t.split(".");let o,a=e.global.get(n);for(const e of s)[o,a]=[a,a[e]];try{await a.call(o,r)}catch(t){Be.get(e).stderr(t)}},transform:(e,t)=>t,writeFile:({cmodule:{module:{FS:e}}},t,r)=>((e,t,r)=>(Ce(e,Le(t)),t=De(e,t),e.writeFile(t,new Uint8Array(r),{canOwn:!0})))(e,t,r)};const At=new Map,jt=new Map,_t=new Proxy(new Map,{get(e,t){if(!e.has(t)){const[r,...n]=t.split("@"),s=At.get(r),o=/^(?:\\.?\\.?\\/|https?:\\/\\/)/i.test(n)?n.join("@"):s.module(...n);e.set(t,{url:o,module:import(o),engine:s.engine.bind(s)})}const{url:r,module:n,engine:s}=e.get(t);return(e,o)=>n.then((n=>{jt.set(t,e);for(const t of["files","fetch"]){const r=e?.[t];r&&Ue.set(r,o)}for(const t of["main","worker"]){const r=e?.js_modules?.[t];r&&Ue.set(r,o)}return s(n,e,r)}))}}),kt=e=>{for(const t of[].concat(e.type))At.set(t,e)};for(const e of[mt,vt,Et,Pt])kt(e);const xt=async e=>(await import("https://cdn.jsdelivr.net/npm/basic-toml@0.3.1/es.js")).parse(e),Mt=(e,t,r={})=>{if(t){const[e,n]=(e=>{let t=typeof e;return"string"===t&&/\\.(json|toml|txt)$/.test(e)?t=RegExp.$1:e="./config.txt",[at(e),t]})(t);if("json"===n)r=fetch(e).then(Fe);else if("toml"===n)r=fetch(e).then(Re).then(xt);else if("string"===n)try{r=JSON.parse(t)}catch(e){r=xt(t)}else"object"===n&&t&&(r=t);t=e}return ot(r).then((r=>_t[e](r,t)))},Tt="BeforeRun",Ot="AfterRun",Wt=[`code${Tt}`,`code${Tt}Async`,`code${Ot}`,`code${Ot}Async`],Ft=["onWorker","onReady",`on${Tt}`,`on${Tt}Async`,`on${Ot}`,`on${Ot}Async`];function Rt(e,t){const{run:r,runAsync:n}=At.get(this.type);return{...e,run:r.bind(this,t),runAsync:n.bind(this,t)}}const Bt=(e,t,r,n,s,o)=>{if(s||o){const a=Rt.bind(e,t),i=n?"runAsync":"run",c=e[i];e[i]=n?async function(e,t,...n){s&&await s.call(this,a(e),r);const i=await c.call(this,e,t,...n);return o&&await o.call(this,a(e),r),i}:function(e,t,...n){s&&s.call(this,a(e),r);const i=c.call(this,e,t,...n);return o&&o.call(this,a(e),r),i}}};try{new SharedArrayBuffer(4)}catch(e){throw new Error(["Unable to use SharedArrayBuffer due insecure environment.","Please read requirements in MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements"].join("\\n"))}let Jt,It,Lt;const Ct=(e,t)=>{addEventListener(e,t||(async t=>{try{await Jt,It(`xworker.on${e}`,t)}catch(e){postMessage(e)}}),!!t&&{once:!0})},{parse:Dt,stringify:Ht}=f,{proxy:Nt,window:Ut,isWindowProxy:qt}=Te(self,{parse:Dt,stringify:Ht,transform:e=>Lt?Lt(e):e}),zt={sync:Nt,window:Ut,isWindowProxy:qt,onmessage:console.info,onerror:console.error,onmessageerror:console.warn,postMessage:postMessage.bind(self)};Ct("message",(({data:{options:e,config:t,code:r,hooks:n}})=>{Jt=(async()=>{try{const{id:s,tag:o,type:a,custom:i,version:c,config:l,async:u}=e,f=((e,t="")=>`${e}@${t}`.replace(/@$/,""))(a,c),p=await Mt(f,t,l),d=jt.get(f).js_modules?.main,y=et(At.get(a)),h=((e,t,r,n)=>({type:t,config:r,interpreter:n,io:Be.get(n),run:(t,...r)=>e.run(n,t,...r),runAsync:(t,...r)=>e.runAsync(n,t,...r),runEvent:(...t)=>e.runEvent(n,...t)}))(y,i||a,l,p);let g="run";if(u&&(g+="Async"),n){const e=((e,t)=>(r,n)=>{const s=e[t].bind(e);e[t]=(e,t,...o)=>s(e,`${n?r:t}\\n${n?t:r}`,...o)})(y,g);let t,r,s="",o="";for(const e of Wt){const t=n[e];if(t){const r=e.endsWith("Async");(r&&u||!r&&!u)&&(e.startsWith("codeBefore")?s=t:o=t)}}o&&e(o,!1),s&&e(s,!0);for(const e of Ft.slice(2)){const s=n[e];if(s){const n=e.endsWith("Async");if(n&&u||!n&&!u){const n=ct(s);e.startsWith("onBefore")?t=n:r=n}}}Bt(y,h,zt,u,t,r)}const{CustomEvent:w,document:m}=Ut,b=s&&m.getElementById(s)||null,v=e=>it(b,i||a,e,!0,w);let S="";return y.registerJSModule(p,"polyscript",{xworker:zt,js_modules:new Proxy(globalThis[lt],{get(e,t){if(!e.has(t)&&d)for(let[r,n]of nt(d))n===t&&(r=at(r,Ue.get(d)),dt(r)?Nt.importCSS(r):(Nt.importJS(r,t),e.set(t,Ut[lt].get(t))));return e.get(t)}}),get target(){return!S&&b&&("SCRIPT"===o?b.after(Ze(m.createElement(`script-${i||a}`),{id:S=`${s}-target`})):(S=s,b.replaceChildren(),b.style.display="block")),S}}),It=y.runEvent.bind(y,p),Lt=y.transform.bind(y,p),b&&v("ready"),n?.onReady&&ct(n?.onReady).call(y,Rt.call(y,h,p),zt),await y[g](p,r),b&&v("done"),p}catch(e){postMessage(e)}})(),Ct("error"),Ct("message"),Ct("messageerror")}));\n'],{type:"application/javascript"})),{type:"module"}),{postMessage:s}=n,o=this instanceof Vt;if(e.length){const[t,n]=e;(r=qe({},r||{type:t,version:n})).type||(r.type=t)}const[a]=Dt(r.config),i=fetch(t).then(Fe).then((e=>{const t=o?this.toJSON():void 0;s.call(n,{options:r,config:a,code:e,hooks:t})})),c=qe(We(n,d).proxy,{importJS:it,importCSS:ct});return Xe(n,{sync:{value:c},postMessage:{value:(e,...t)=>i.then((()=>s.call(n,e,...t)))},onerror:{writable:!0,configurable:!0,value:console.error}}),n.addEventListener("message",(e=>{const{data:t}=e;t instanceof Error&&(e.stopImmediatePropagation(),n.onerror(ze(e,{type:{value:"error"},error:{value:t}})))})),o&&this.onWorker?.(this.interpreter,n),n};const er="Invalid content",tr="Invalid worker attribute",rr="Invalid worker attribute";var nr=e=>{const{src:t,worker:r}=e.attributes;if(r){let{value:n}=r;if(n)throw new SyntaxError(rr);if(n=t?.value,!n){if(t)throw new SyntaxError(tr);if(e.childElementCount){const{innerHTML:t,localName:r,type:s}=e,o=s||r.replace(/-script$/,"");n=De(t),console.warn(`Deprecated: use + + + + + diff --git a/test/integration/micropython.js b/test/integration/micropython.js index dfb12cd..cbf552a 100644 --- a/test/integration/micropython.js +++ b/test/integration/micropython.js @@ -39,4 +39,6 @@ module.exports = (playwright, baseURL) => { test('MicroPython ready-done events', python.waitForReadyDone(playwright, `${baseURL}/ready-done.html`)); test('MicroPython local intepreter', python.localInterpreter(playwright, baseURL)); + + test('MicroPython mip', python.waitForDone(playwright, `${baseURL}/mip.html`)); }; diff --git a/test/mip.html b/test/mip.html new file mode 100644 index 0000000..a180885 --- /dev/null +++ b/test/mip.html @@ -0,0 +1,41 @@ + + + + + + MicroPython mip + + + + + + + + + + + + + + diff --git a/test/mip.py b/test/mip.py new file mode 100644 index 0000000..15c7b9b --- /dev/null +++ b/test/mip.py @@ -0,0 +1,22 @@ +# Test a variety of ways that the mip tool can import content +# Based on documentation at https://docs.micropython.org/en/latest/reference/packages.html + +import mip + +# Install default version from micropython-lib +mip.install('keyword') +import keyword +print('The keyword list is', keyword.kwlist) + +# Install from raw URL +mip.install('https://raw.githubusercontent.com/micropython/micropython-lib/master/python-stdlib/bisect/bisect.py') +from bisect import insort_right +my_list = [1,2,4] +insort_right(my_list, 3) +print(f'My list with insertion is {my_list}') + +# Install from GitHub shortcut +mip.install("github:micropython/micropython-lib/python-stdlib/curses.ascii/curses/ascii.py") +import ascii +print(f'{ascii.isalpha("A")=}') +print(f'{ascii.ispunct("Q")=}') diff --git a/test/mip.toml b/test/mip.toml new file mode 100644 index 0000000..4d45707 --- /dev/null +++ b/test/mip.toml @@ -0,0 +1 @@ +packages = ['xmltok'] diff --git a/test/mocked/micropython.mjs b/test/mocked/micropython.mjs index 669cb95..f78be89 100644 --- a/test/mocked/micropython.mjs +++ b/test/mocked/micropython.mjs @@ -1,7 +1,17 @@ +import { dirname } from "node:path"; + export const python = { content: "", target: null }; export const loadMicroPython = () => ({ registerJsModule() { + }, + pyimport() { + return { + install(packages) { + python.packages = packages; + }, + destroy() {}, + }; }, runPython(content) { if (document.currentScript?.target) { @@ -17,4 +27,14 @@ export const loadMicroPython = () => ({ delete globalThis[name]; }, }, + FS: { + mkdirTree() {}, + writeFile() {}, + }, + _module: { + PATH: { dirname }, + PATH_FS: { + resolve: (path) => path, + }, + }, }); diff --git a/test/mocked/pyodide.mjs b/test/mocked/pyodide.mjs index 451a2e6..0feb17a 100644 --- a/test/mocked/pyodide.mjs +++ b/test/mocked/pyodide.mjs @@ -1,4 +1,4 @@ -import { basename, dirname } from "node:path"; +import { dirname } from "node:path"; let target; export const setTarget = (value) => { From 819d3f16bcf7543297146fd78069278559115c7c Mon Sep 17 00:00:00 2001 From: webreflection Date: Mon, 18 Dec 2023 11:52:31 +0100 Subject: [PATCH 2/2] Removed esm/python from the GitHub source --- .gitignore | 1 + esm/python/mip.js | 2 -- package.json | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 esm/python/mip.js diff --git a/.gitignore b/.gitignore index 9d31c52..9b8ceec 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ pyscript.js esm/worker/xworker.js esm/worker/__template.js types/ +esm/python/ diff --git a/esm/python/mip.js b/esm/python/mip.js deleted file mode 100644 index 0b03f3e..0000000 --- a/esm/python/mip.js +++ /dev/null @@ -1,2 +0,0 @@ -// ⚠️ DO NOT MODIFY - SOURCE FILE: "../../python/mip.py" -export default new TextEncoder().encode("from uio import StringIO\nimport sys\n\nclass Response:\n def __init__(self, f):\n self.raw = f\n self.encoding = \"utf-8\"\n self._cached = None\n\n def close(self):\n if self.raw:\n self.raw.close()\n self.raw = None\n self._cached = None\n\n @property\n def content(self):\n if self._cached is None:\n try:\n self._cached = self.raw.read()\n finally:\n self.raw.close()\n self.raw = None\n return self._cached\n\n @property\n def text(self):\n return str(self.content, self.encoding)\n\n def json(self):\n import ujson\n\n return ujson.loads(self.content)\n\n\n# TODO try to support streaming xhr requests, a-la pyodide-http\nHEADERS_TO_IGNORE = (\"user-agent\",)\n\n\ntry:\n import js\nexcept Exception as err:\n raise OSError(\"This version of urequests can only be used in the browser\")\n\n# TODO try to support streaming xhr requests, a-la pyodide-http\n\nHEADERS_TO_IGNORE = (\"user-agent\",)\n\n\ndef request(\n method,\n url,\n data=None,\n json=None,\n headers={},\n stream=None,\n auth=None,\n timeout=None,\n parse_headers=True,\n):\n from js import XMLHttpRequest\n\n xhr = XMLHttpRequest.new()\n xhr.withCredentials = False\n\n if auth is not None:\n import ubinascii\n\n username, password = auth\n xhr.open(method, url, False, username, password)\n else:\n xhr.open(method, url, False)\n\n for name, value in headers.items():\n if name.lower() not in HEADERS_TO_IGNORE:\n xhr.setRequestHeader(name, value)\n\n if timeout:\n xhr.timeout = int(timeout * 1000)\n\n if json is not None:\n assert data is None\n import ujson\n\n data = ujson.dumps(json)\n # s.write(b\"Content-Type: application/json\\r\\n\")\n xhr.setRequestHeader(\"Content-Type\", \"application/json\")\n\n xhr.send(data)\n\n # Emulates the construction process in the original urequests\n resp = Response(StringIO(xhr.responseText))\n resp.status_code = xhr.status\n resp.reason = xhr.statusText\n resp.headers = xhr.getAllResponseHeaders()\n\n return resp\n\n\n# Other methods - head, post, put, patch, delete - are not used by\n# mip and therefore not included\n\n\ndef get(url, **kw):\n return request(\"GET\", url, **kw)\n\n\n# Content below this line is from the Micropython MIP package and is covered\n# by the applicable MIT license:\n# \n# THE SOFTWARE IS PROVIDED β€œAS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n# DEALINGS IN THE SOFTWARE.\n\n# MicroPython package installer\n# MIT license; Copyright (c) 2022 Jim Mussared\n\n\n_PACKAGE_INDEX = const(\"https://micropython.org/pi/v2\")\n_CHUNK_SIZE = 128\n\n\n# This implements os.makedirs(os.dirname(path))\ndef _ensure_path_exists(path):\n import os\n\n split = path.split(\"/\")\n\n # Handle paths starting with \"/\".\n if not split[0]:\n split.pop(0)\n split[0] = \"/\" + split[0]\n\n prefix = \"\"\n for i in range(len(split) - 1):\n prefix += split[i]\n try:\n os.stat(prefix)\n except:\n os.mkdir(prefix)\n prefix += \"/\"\n\n\n# Copy from src (stream) to dest (function-taking-bytes)\ndef _chunk(src, dest):\n buf = memoryview(bytearray(_CHUNK_SIZE))\n while True:\n n = src.readinto(buf)\n if n == 0:\n break\n dest(buf if n == _CHUNK_SIZE else buf[:n])\n\n\n# Check if the specified path exists and matches the hash.\ndef _check_exists(path, short_hash):\n import os\n\n try:\n import binascii\n import hashlib\n\n with open(path, \"rb\") as f:\n hs256 = hashlib.sha256()\n _chunk(f, hs256.update)\n existing_hash = str(binascii.hexlify(hs256.digest())[: len(short_hash)], \"utf-8\")\n return existing_hash == short_hash\n except:\n return False\n\n\ndef _rewrite_url(url, branch=None):\n if not branch:\n branch = \"HEAD\"\n if url.startswith(\"github:\"):\n url = url[7:].split(\"/\")\n url = (\n \"https://raw.githubusercontent.com/\"\n + url[0]\n + \"/\"\n + url[1]\n + \"/\"\n + branch\n + \"/\"\n + \"/\".join(url[2:])\n )\n return url\n\n\ndef _download_file(url, dest):\n response = get(url)\n try:\n if response.status_code != 200:\n print(\"Error\", response.status_code, \"requesting\", url)\n return False\n\n print(\"Copying:\", dest)\n _ensure_path_exists(dest)\n with open(dest, \"wb\") as f:\n _chunk(response.raw, f.write)\n\n return True\n finally:\n response.close()\n\n\ndef _install_json(package_json_url, index, target, version, mpy):\n response = get(_rewrite_url(package_json_url, version))\n try:\n if response.status_code != 200:\n print(\"Package not found:\", package_json_url)\n return False\n\n package_json = response.json()\n finally:\n response.close()\n for target_path, short_hash in package_json.get(\"hashes\", ()):\n fs_target_path = target + \"/\" + target_path\n if _check_exists(fs_target_path, short_hash):\n print(\"Exists:\", fs_target_path)\n else:\n file_url = \"{}/file/{}/{}\".format(index, short_hash[:2], short_hash)\n if not _download_file(file_url, fs_target_path):\n print(\"File not found: {} {}\".format(target_path, short_hash))\n return False\n for target_path, url in package_json.get(\"urls\", ()):\n fs_target_path = target + \"/\" + target_path\n if not _download_file(_rewrite_url(url, version), fs_target_path):\n print(\"File not found: {} {}\".format(target_path, url))\n return False\n for dep, dep_version in package_json.get(\"deps\", ()):\n if not _install_package(dep, index, target, dep_version, mpy):\n return False\n return True\n\n\ndef _install_package(package, index, target, version, mpy):\n if (\n package.startswith(\"http://\")\n or package.startswith(\"https://\")\n or package.startswith(\"github:\")\n ):\n if package.endswith(\".py\") or package.endswith(\".mpy\"):\n print(\"Downloading {} to {}\".format(package, target))\n return _download_file(\n _rewrite_url(package, version), target + \"/\" + package.rsplit(\"/\")[-1]\n )\n else:\n if not package.endswith(\".json\"):\n if not package.endswith(\"/\"):\n package += \"/\"\n package += \"package.json\"\n print(\"Installing {} to {}\".format(package, target))\n else:\n if not version:\n version = \"latest\"\n print(\"Installing {} ({}) from {} to {}\".format(package, version, index, target))\n\n mpy_version = (\n sys.implementation._mpy & 0xFF if mpy and hasattr(sys.implementation, \"_mpy\") else \"py\"\n )\n\n package = \"{}/package/{}/{}/{}.json\".format(index, mpy_version, package, version)\n\n return _install_json(package, index, target, version, mpy)\n\n\ndef install(package, index=None, target=None, version=None, mpy=True):\n if not target:\n for p in sys.path:\n if p.endswith(\"/lib\"):\n target = p\n break\n else:\n print(\"Unable to find lib dir in sys.path\")\n return\n\n if not index:\n index = _PACKAGE_INDEX\n\n if _install_package(package, index.rstrip(\"/\"), target, version, mpy):\n print(\"Done\")\n else:\n print(\"Package may be partially installed\")\n"); \ No newline at end of file diff --git a/package.json b/package.json index 3df3022..a49e03b 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "types": "./types/polyscript/esm/index.d.ts", "scripts": { "server": "npx static-handler --coi .", - "build": "node rollup/build_python.cjs && npm run rollup:xworker && npm run rollup:core && eslint esm/ && npm run ts && npm run cjs && npm run rollup:integrations && cp core.* docs/", + "build": "mkdir -p esm/python && node rollup/build_python.cjs && npm run rollup:xworker && npm run rollup:core && eslint esm/ && npm run ts && npm run cjs && npm run rollup:integrations && cp core.* docs/", "cjs": "ascjs --no-default esm cjs", "dev": "node dev.cjs", "rollup:core": "rollup --config rollup/core.config.js",