diff --git a/asset-manifest.json b/asset-manifest.json index 6f533e6..b3d9e7b 100644 --- a/asset-manifest.json +++ b/asset-manifest.json @@ -1,15 +1,15 @@ { "files": { "main.css": "/static/css/main.8a09dddb.chunk.css", - "main.js": "/static/js/main.4cb4b833.chunk.js", - "main.js.map": "/static/js/main.4cb4b833.chunk.js.map", + "main.js": "/static/js/main.bd7fc67a.chunk.js", + "main.js.map": "/static/js/main.bd7fc67a.chunk.js.map", "runtime-main.js": "/static/js/runtime-main.a136100e.js", "runtime-main.js.map": "/static/js/runtime-main.a136100e.js.map", "static/css/2.6b709c6b.chunk.css": "/static/css/2.6b709c6b.chunk.css", "static/js/2.e4620b26.chunk.js": "/static/js/2.e4620b26.chunk.js", "static/js/2.e4620b26.chunk.js.map": "/static/js/2.e4620b26.chunk.js.map", "index.html": "/index.html", - "precache-manifest.8763ac274428afd69a1081b0563ce2ff.js": "/precache-manifest.8763ac274428afd69a1081b0563ce2ff.js", + "precache-manifest.2939d20d8316e754b820be6e160cfa00.js": "/precache-manifest.2939d20d8316e754b820be6e160cfa00.js", "service-worker.js": "/service-worker.js", "static/css/2.6b709c6b.chunk.css.map": "/static/css/2.6b709c6b.chunk.css.map", "static/css/main.8a09dddb.chunk.css.map": "/static/css/main.8a09dddb.chunk.css.map", @@ -24,6 +24,6 @@ "static/css/2.6b709c6b.chunk.css", "static/js/2.e4620b26.chunk.js", "static/css/main.8a09dddb.chunk.css", - "static/js/main.4cb4b833.chunk.js" + "static/js/main.bd7fc67a.chunk.js" ] } \ No newline at end of file diff --git a/index.html b/index.html index 32d356f..9a66926 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ -jsGist
\ No newline at end of file +jsGist
\ No newline at end of file diff --git a/precache-manifest.8763ac274428afd69a1081b0563ce2ff.js b/precache-manifest.2939d20d8316e754b820be6e160cfa00.js similarity index 85% rename from precache-manifest.8763ac274428afd69a1081b0563ce2ff.js rename to precache-manifest.2939d20d8316e754b820be6e160cfa00.js index e93ad05..7a7eead 100644 --- a/precache-manifest.8763ac274428afd69a1081b0563ce2ff.js +++ b/precache-manifest.2939d20d8316e754b820be6e160cfa00.js @@ -1,6 +1,6 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([ { - "revision": "245c5521d574975fad63b3ce8e4c764b", + "revision": "516021b88bcf1b8f1ce9b9cdcd262cd0", "url": "/index.html" }, { @@ -8,7 +8,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([ "url": "/static/css/2.6b709c6b.chunk.css" }, { - "revision": "cc3b53031edeb4d8c0db", + "revision": "582a79a9e29c91c3c4a9", "url": "/static/css/main.8a09dddb.chunk.css" }, { @@ -20,8 +20,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([ "url": "/static/js/2.e4620b26.chunk.js.LICENSE.txt" }, { - "revision": "cc3b53031edeb4d8c0db", - "url": "/static/js/main.4cb4b833.chunk.js" + "revision": "582a79a9e29c91c3c4a9", + "url": "/static/js/main.bd7fc67a.chunk.js" }, { "revision": "21d734a13edf31307f64", diff --git a/service-worker.js b/service-worker.js index 2e5cf5d..7962c14 100644 --- a/service-worker.js +++ b/service-worker.js @@ -14,7 +14,7 @@ importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); importScripts( - "/precache-manifest.8763ac274428afd69a1081b0563ce2ff.js" + "/precache-manifest.2939d20d8316e754b820be6e160cfa00.js" ); self.addEventListener('message', (event) => { diff --git a/static/js/main.4cb4b833.chunk.js b/static/js/main.4cb4b833.chunk.js deleted file mode 100644 index 682ec19..0000000 --- a/static/js/main.4cb4b833.chunk.js +++ /dev/null @@ -1,2 +0,0 @@ -(this.webpackJsonpjsgist=this.webpackJsonpjsgist||[]).push([[0],{177:function(e,t,n){},178:function(e,t,n){"use strict";n.r(t);var a=n(0),r=n.n(a),i=n(76),o=n.n(i),s=n(3),c=n(5),l=n(16),u=function(){function e(){Object(s.a)(this,e),this.itemToSubscriptionMap=void 0,this.itemToSubscriptionMap=new Map}return Object(c.a)(e,[{key:"subscribe",value:function(e,t){this.unsubscribe(e,t);var n=this.itemToSubscriptionMap.get(e);n||(n=[],this.itemToSubscriptionMap.set(e,n)),n.push(t)}},{key:"unsubscribe",value:function(e,t){var n=this.itemToSubscriptionMap.get(e);if(n){var a=n.indexOf(t);a>=0&&(n.splice(a,1),0===n.length&&this.itemToSubscriptionMap.delete(e))}}},{key:"notify",value:function(e){var t=this.itemToSubscriptionMap.get(e);if(t){var n,a=Object(l.a)(t.slice());try{for(a.s();!(n=a.n()).done;){(0,n.value)()}}catch(r){a.e(r)}finally{a.f()}}}}]),e}();var d=new(function(){function e(t){var n=this;Object(s.a)(this,e),this.prefix=void 0,this.subscriptionManager=void 0,this._handleNewValue=function(e){var t=e.key;if(t&&t.startsWith(n.prefix)){var a=t.substr(n.prefix.length);n.subscriptionManager.notify(a)}},this.prefix="".concat(t,"-"),this.subscriptionManager=new u,window.addEventListener("storage",this._handleNewValue)}return Object(c.a)(e,[{key:"_addPrefix",value:function(e){return"".concat(this.prefix).concat(e)}},{key:"subscribe",value:function(e,t){this.subscriptionManager.subscribe(e,t)}},{key:"unsubscribe",value:function(e,t){this.subscriptionManager.unsubscribe(e,t)}},{key:"get",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this._addPrefix(e);if(t){var a=sessionStorage.getItem(n);if(a)return a}return localStorage.getItem(n)}},{key:"set",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],a=this._addPrefix(e);n&&sessionStorage.setItem(a,t),localStorage.setItem(a,t),this.subscriptionManager.notify(e)}},{key:"delete",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this._addPrefix(e);t&&sessionStorage.removeItem(n),localStorage.removeItem(n),this.subscriptionManager.notify(e)}},{key:"cleanup",value:function(){window.removeEventListener("storage",this._handleNewValue)}}]),e}())("jsgist"),h=(n(93),n(94),document.createElement("div"));h.setAttribute("style","width:30px;height:30px;"),h.classList.add("scrollbar-test");var m=document.createElement("div");m.setAttribute("style","width:100%;height:40px"),h.appendChild(m),document.body.appendChild(h),30-h.firstChild.clientWidth&&document.body.classList.add("layout-scrollbar-obtrusive"),document.body.removeChild(h);var p=n(1),g=n.n(p),f=n(8),v=n(42),b=n(6),y=n(7);function E(e){return r.a.createElement("input",{type:"text",onChange:function(t){e.onChange(t.target.value)},placeholder:e.placeholder,value:e.value})}var k=n(20),w=n(4),S=n(11),j=n(53),O="/*bug-in-github-api-content-can-not-be-empty*/";function x(e){return e.content.startsWith(O)?e.content.substr(O.length):e.content}function C(e){var t=JSON.parse(e.files["jsGist.json"].content);return t.filenames?t.files=t.filenames.map((function(t){return{name:t,content:x(e.files[t])}})):t.files=Object.entries(e.files).filter((function(e){return"jsGist.json"!==Object(S.a)(e,1)[0]})).map((function(e){var t=Object(S.a)(e,2);return{name:t[0],content:x(t[1])}})).concat(t.files||[]),t}function M(e,t,n){var a=e.files.reduce((function(e,t){return e[t.name]={content:t.content.trim()?t.content:"".concat(O).concat(t.content)},e}),{}),r=Object(w.a)({},e),i={};if(a["jsGist.json"]=i,Object.keys(a).length===e.files.length+1?(delete r.files,r.filenames=e.files.map((function(e){return e.name}))):a={"jsGist.json":i},i.content=JSON.stringify(r),n){var o=Object.keys(a).map((function(e){return e.toLowerCase()}));if(!(o.includes("readme.md")||o.includes("readme.txt")||o.includes("readme"))){var s="## ".concat(e.name,"\n\n[view on jsgist](").concat(window.location.origin,"?src=").concat(n,")");a["README.md"]={content:s}}for(var c=0,l=Object.entries(a);c1&&void 0!==i[1]&&i[1],a=M(t,n),e.next=4,this.authorizedOctokit.gists.create(a);case 4:return r=e.sent,this._updateUserData(r.data),e.next=8,this.updateGist(r.data.id,t);case 8:return e.abrupt("return",e.sent);case 9:case"end":return e.stop()}}),e,this)})));return function(t){return e.apply(this,arguments)}}()},{key:"updateGist",value:function(){var e=Object(f.a)(g.a.mark((function e(t,n){var a,r;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a=M(n,!1,t),e.next=3,this.authorizedOctokit.gists.update(a);case 3:return r=e.sent,e.abrupt("return",{id:r.data.id,name:r.data.description,date:r.data.updated_at,public:r.data.public});case 5:case"end":return e.stop()}}),e,this)})));return function(t,n){return e.apply(this,arguments)}}()},{key:"forkGist",value:function(){var e=Object(f.a)(g.a.mark((function e(t){var n;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this.authorizedOctokit.gists.fork({gist_id:t});case 2:return n=e.sent,e.abrupt("return",{id:n.data.id});case 4:case"end":return e.stop()}}),e,this)})));return function(t){return e.apply(this,arguments)}}()},{key:"deleteGist",value:function(){var e=Object(f.a)(g.a.mark((function e(t){var n;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this.authorizedOctokit.gists.delete({gist_id:t});case 2:return n=e.sent,e.abrupt("return",n);case 4:case"end":return e.stop()}}),e,this)})));return function(t){return e.apply(this,arguments)}}()},{key:"createGistComment",value:function(){var e=Object(f.a)(g.a.mark((function e(t,n){var a;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this.authorizedOctokit.gists.createComment({gist_id:t,body:n});case 2:if(!((a=e.sent).status<200||a.status>=300)){e.next=5;break}throw new Error(a.message);case 5:return e.abrupt("return",a.data);case 6:case"end":return e.stop()}}),e,this)})));return function(t,n){return e.apply(this,arguments)}}()},{key:"octokit",get:function(){return this.authorizedOctokit||this.unAuthorizedOctokit}}]),n}(Object(k.a)(EventTarget));function N(){return r.a.createElement("div",{className:"head"},r.a.createElement("div",null,r.a.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:window.location.origin},r.a.createElement("img",{src:"/resources/images/logo-small.svg",alt:"logo"}),window.location.hostname)),r.a.createElement("div",{className:"fix-help-contribute"},r.a.createElement("div",{className:"octocat"},r.a.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/greggman/jsgist/"},r.a.createElement("img",{alt:"github",src:"/resources/images/octocat-icon.svg"})))))}var L=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(){var e;Object(s.a)(this,n);for(var a=arguments.length,r=new Array(a),i=0;i--"),"."),r.a.createElement("p",null,"Example: ",r.a.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://jsgist.org/?src=f793cb359f2571409983351a6099d5d1"},"https://jsgist.org/?src=f793cb359f2571409983351a6099d5d1"))),r.a.createElement("li",null,"Save it manually somewhere else.",r.a.createElement("p",null,"If there's some other service that will provide a string via http get then copy and save the JSON there then create a URL in the form of ",r.a.createElement("code",null,"https://jsgist.org/?src="),". Note: you may have to escape the URL.")),r.a.createElement("li",null,"Save it as a bookmark or link",r.a.createElement("p",null,"In the SaveAs dialog there's a link that contains all the data for your benchmark.")))))}var U=n(15),_=n.n(U),T=n(14),A=n.n(T),D=n(18),P=/([a-z])([A-Z])/g,R=function(e,t,n){return"".concat(t,"-").concat(n)},G=function(e){return e.replace(P,R).toLowerCase()};function K(){for(var e=[],t=arguments.length,n=new Array(t),a=0;a=0?e.substr(t+1):e}(t.url||""),":",t.lineNo)))}))))}}]),n}(r.a.Component);function W(e,t){for(var n=new URL(e),a=new URLSearchParams(n.search),r=0,i=Object.entries(t);r=0&&r.splice(i,1),0===r.length&&(a.delete(e),0===a.size&&t&&q.delete(t))}}}function $(e,t,n){var a=e.get(t);if(a){var r,i=Object(l.a)(a);try{for(i.s();!(r=i.n()).done;){(0,r.value)(n)}}catch(o){i.e(o)}finally{i.f()}return!0}return!1}window.addEventListener("message",(function(e){var t=e.data,n=t.type,a=t.data,r=q.get(e.source);r&&$(r,n,a)||$(H,n,a)}));var X=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(e){var a;return Object(s.a)(this,n),(a=t.call(this,e)).handleJSLog=function(e){a.context.logManager.addMsg(e)},a.handleJSError=function(e){a.context.logManager.addMsg(Object(w.a)(Object(w.a)({},e),{},{type:"error",showStack:!0}))},a.handleJSUnhandledRejection=function(e){a.context.logManager.addMsg(Object(w.a)(Object(w.a)({},e),{},{type:"error",showStack:!0}))},a.handleInfoMessages=function(e){a.context.logManager.addMsgs(e)},a.handleGimmeDaCodez=function(){a.iframe.contentWindow.postMessage({type:"run",data:a.data},"*")},a.handleMessage=function(e){var t=e.data,n=t.type,r=t.data,i=a.handlers[n];i&&i(r)},a.runnerRef=r.a.createRef(),a}return Object(c.a)(n,[{key:"componentDidMount",value:function(){var e=this,t=this.props.registerAPI,n=Object.fromEntries(new URLSearchParams(window.location.search).entries()).debug,a=Object(w.a)({},n&&{debug:n});t({run:function(t,n){e.data=t,e.removeIFrame();var r=document.createElement("iframe");e.iframe=r,r.src=W("https://jsgistrunner.devcomments.org/runner-03.html",Object(w.a)({url:"https://jsgist.org/jsgist-runner.js"},a)),n&&(r.style.background="none"),e.runnerRef.current.appendChild(r)}}),B("gimmeDaCodez",null,this.handleGimmeDaCodez),B("jsLog",null,this.handleJSLog),B("jsError",null,this.handleJSError),B("jsUnhandledRejection",null,this.handleJSUnhandledRejection),B("infoMessages",null,this.handleInfoMessages)}},{key:"removeIFrame",value:function(){this.iframe&&(this.iframe.remove(),this.iframe.src="about:blank",this.iframe=void 0)}},{key:"componentWillUnmount",value:function(){this.removeIFrame(),Y("gimmeDaCodez",null,this.handleGimmeDaCodez),Y("jsLog",null,this.handleJSLog),Y("jsError",null,this.handleJSError),Y("jsUnhandledRejection",null,this.handleJSUnhandledRejection),Y("infoMessages",null,this.handleInfoMessages)}},{key:"render",value:function(){return r.a.createElement("div",{className:"runner",ref:this.runnerRef})}}]),n}(r.a.Component);X.contextType=F;var Z=n(79),Q=(new _.a).compile(Z),ee={};function te(e){var t=ee[e]||{subscriptions:new Set};return ee[e]=t,t}function ne(e,t){var n=te(e);return void 0!==t&&(n.value=t),n}function ae(e){return ee[e].value}function re(e,t){var n=ee[e];if(!n)throw new Error("no such track value: ".concat(e));n.value=t;var a,r=Object(v.a)(n.subscriptions.keys()),i=Object(l.a)(r);try{for(i.s();!(a=i.n()).done;){(0,a.value)(t,e)}}catch(o){i.e(o)}finally{i.f()}}function ie(e,t){te(e).subscriptions.add(t)}function oe(e,t){te(e).subscriptions.delete(t)}var se,ce={name:"My jsGist",settings:{},files:[{name:"index.html",content:""},{name:"index.css",content:""},{name:"index.js",content:""}]};function le(){var e="".concat(window.location.origin,"/resources/images/logo.svg");return JSON.parse(JSON.stringify({name:"jsGist",settings:{},files:[{name:"index.html",content:""},{name:"index.css",content:"\n html, body {\n margin: 0;\n width: 100%;\n height: 100%;\n background-image: url(".concat(e,");\n background-size: contain contain;\n background-position: center center;\n background-repeat: no-repeat no-repeat;\n }\n @media (prefers-color-scheme: dark) {\n html {\n background: #222;\n }\n }\n ")},{name:"index.js",content:""}]}))}function ue(){return se}ne("dataVersion",0),ne("updateVersion",0),ne("filesVersion",0);var de=function(e){return re(e,ae(e)+1)},he=function(e){return de("dataVersion")},me=function(e){return de("filesVersion")};function pe(e,t){se.files[e].name=t,he()}function ge(e,t){se.files[e].content=t,he()}function fe(e){!function(e){if(!Q(e))throw new Error("data not valid:\n".concat(Q.errors.map((function(e){return"".concat(e.message,": ").concat(e.dataPath)}))))}(e),se=e,de("updateVersion"),he(),me()}fe(JSON.parse(JSON.stringify(ce)));var ve,be=Object.fromEntries(new URLSearchParams(window.location.search).entries()),ye=!be.codeMirror&&!/webOS|iPhone|iPad|Android/.test(navigator.userAgent),Ee=!1,ke={layout:window.screen.width<540||window.screen.height<540?3:0,editor:ye?"monaco":"codemirror",lineNumbers:!0,tabs:!1,showWhitespace:!1};function we(e,t){ve[e]=t;var n=JSON.stringify(ve);d.set("ui-settings",n,!0),re("settings",ve)}function Se(){return function(){if(!Ee){Ee=!0;try{if(!(ve=JSON.parse(d.get("ui-settings",!0))))throw new Error("no settings")}catch(i){ve=Object(w.a)({},ke)}for(var e=0,t=Object.entries(ke);e=0&&(u.matchTags=!0),r.a.createElement(Ne.Controlled,{value:c,options:u,onBeforeChange:function(t,n,a){e.setState({value:a})},onChange:function(e,t,n){o(n)},editorDidMount:this.registerEditor})}}],[{key:"getDerivedStateFromProps",value:function(e,t){return t.hackKey!==e.hackKey?{hackKey:e.hackKey,value:e.value}:null}}]),n}(r.a.Component),_e=n(87),Te=window.matchMedia?window.matchMedia("(prefers-color-scheme: dark)"):{},Ae=function(){};var De=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(e){var a;Object(s.a)(this,n),(a=t.call(this,e)).handleEditorDidMount=function(e,t){a.editor=e,e.getModel().updateOptions({tabSize:2});var n=a.props.registerAPI;n&&n({goToLine:function(e,t){a.editor.focus(),a.editor.setPosition({lineNumber:e,column:t}),a.editor.revealPosition({lineNumber:e,column:t})},refresh:function(e){},focus:function(e){a.editor.focus()}})},a.registerEditor=function(e){a.editor=e};var r=e.value,i=e.hackKey;return a.state={value:r,hackKey:i},a}return Object(c.a)(n,[{key:"render",value:function(){var e=this.props,t=e.options,n=void 0===t?{}:t,a=e.onValueChange,i=void 0===a?Ae:a,o=e.ui,s=this.state.value,c=Te.matches,l=function(e){var t=((null===e||void 0===e?void 0:e.mode)||"javascript").split("/").pop();return"gfm"===t?"markdown":t}(n.editor).split("/").pop();return r.a.createElement(_e.a,{theme:c?"vs-dark":"light",language:l,value:s,onChange:i,onMount:this.handleEditorDidMount,options:{minimap:{enabled:!1},lineNumbers:o.lineNumbers?"on":"off",glyphMargin:!1,folding:!1,insertSpaces:!o.tabs,renderWhitespace:o.showWhitespace}})}}],[{key:"getDerivedStateFromProps",value:function(e,t){return t.hackKey!==e.hackKey?{hackKey:e.hackKey,value:e.value}:null}}]),n}(r.a.Component),Pe=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(){var e;Object(s.a)(this,n);for(var a=arguments.length,r=new Array(a),i=0;i=0)return{v:a}};for(a.s();!(n=a.n()).done;){var i=r();if("object"===typeof i)return i.v}}catch(o){a.e(o)}finally{a.f()}return-1}function Be(e,t){var n=e.findIndex((function(e){return e.name.toLowerCase()===t.toLowerCase}));if(n>=0)return n;for(var a=arguments.length,r=new Array(a>2?a-2:0),i=2;i1?t-1:0),a=1;a=0?e[r]:""}var $e=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:",";return Object.entries(e).map((function(e){var t=Object(S.a)(e,2),n=t[0],a=t[1];return"".concat(n,"=").concat(a)})).join(t)};var Xe=(new _.a).compile({type:"object",properties:{"hSizes:":{type:"array",items:{type:"number"},minItems:2},"v1Sizes:":{type:"array",items:{type:"number"},minItems:2},"v2Sizes:":{type:"array",items:{type:"number"},minItems:2}},required:["hSizes","v1Sizes","v2Sizes"]});function Ze(e){var t=e.data,n=e.ndx,a=e.hackKey,i=e.register,o=e.unregister,s=t.files[n];return r.a.createElement(Ge,{hackKey:a,desc:"filename",title:s.name,value:s.content,onTitleChange:function(e){return pe(n,e)},onValueChange:function(e){return ge(n,e)},register:i,unregister:o})}var Qe=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(e){var a;Object(s.a)(this,n),(a=t.call(this,e)).onSetHSizes=function(e){a.setState({hSizes:e}),we("layout2x2",a.state)},a.onSetV1Sizes=function(e){a.setState({v1Sizes:e}),we("layout2x2",a.state)},a.onSetV2Sizes=function(e){a.setState({v2Sizes:e}),we("layout2x2",a.state)},a.handleRegister=function(e,t){a.files.set(e,t)},a.handleUnregister=function(e){a.files.delete(e)},a.handleGoToLine=function(e){a.files.forEach((function(t){t.goToLine(e)}))},a.files=new Map;var r=Se().layout2x2;return a.state=Xe(r)?r:{hSizes:[.5,.5],v1Sizes:[.4,.6],v2Sizes:[.4,.5,.1]},a}return Object(c.a)(n,[{key:"render",value:function(){var e=this.props,t=e.hackKey,n=e.data,a=e.registerRunnerAPI,i=n.files,o=Be(i,"index.html","html"),s=Be(i,"index.js","js","js","javascript"),c=Be(i,"index.css","css"),l=this.state,u=l.hSizes,d=l.v1Sizes,h=l.v2Sizes;return r.a.createElement(A.a,{direction:"horizontal",minSize:0,sizes:u,onSetSizes:this.onSetHSizes},r.a.createElement("div",{className:"left"},r.a.createElement(A.a,{direction:"vertical",minSize:0,sizes:d,onSetSizes:this.onSetV1Sizes},r.a.createElement(Ze,{hackKey:t,register:this.handleRegister,unregister:this.handleUnregister,data:n,ndx:o}),r.a.createElement(Ze,{hackKey:t,register:this.handleRegister,unregister:this.handleUnregister,data:n,ndx:s}))),r.a.createElement("div",{className:"right"},r.a.createElement(A.a,{direction:"vertical",minSize:0,sizes:h,onSetSizes:this.onSetV2Sizes},r.a.createElement(Ze,{hackKey:t,register:this.handleRegister,unregister:this.handleUnregister,data:n,ndx:c}),r.a.createElement(X,{registerAPI:a}),r.a.createElement(V,{onGoToLine:this.handleGoToLine}))))}}]),n}(r.a.Component),et=(new _.a).compile({type:"object",properties:{showResult:{type:"boolean"},showLog:{type:"boolean"},currentNdx:{type:"integer"},"sizes:":{type:"array",items:{type:"number"},minItems:3},"lastSizes:":{type:"array",items:{type:"number"},minItems:3}},required:["sizes","lastSizes","showResult","showLog","currentNdx"]});function tt(e,t,n,a){if(a){var r=t[n],i=1-r,o=e.filter((function(e,t){return n!==t})),s=o.reduce((function(e,t){return e+t}),0),c=o.map((function(e){return e/s*i}));return c.splice(n,0,r),c}var l=e.map((function(e,t){return n===t?0:e})),u=l.reduce((function(e,t){return e+t}),0);return l.map((function(e){return e/u}))}var nt=[Ve,He,Qe,function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(e){var a;Object(s.a)(this,n),(a=t.call(this,e)).handleRegister=function(e,t){a.files.set(e,t)},a.handleUnregister=function(e){a.files.delete(e)},a.setSizes=function(e){var t=a.state.lastSizes.slice();a.state.currentNdx>=0&&(t[0]=e[0]),a.state.showResult&&(t[1]=e[1]),a.state.showLow&&(t[2]=e[2]),a.setState({sizes:e,lastSizes:t}),we("layoutTabbed",a.state)},a.handleGoToLine=function(e){a.files.forEach((function(t,n){if(t.goToLine(e)){var r=a.props.data.files.findIndex((function(t){return t.name===e.section}));r!==a.state.currentNdx&&a.handleOnChange(r)}}))},a.handleOnChange=function(e){var t=a.state.currentNdx===e?-1:e;a.setState({currentNdx:t,sizes:tt(a.state.sizes,a.state.lastSizes,0,t>=0)}),we("layoutTabbed",a.state)},a.toggleShowLog=function(){var e=!a.state.showLog;a.setState({showLog:e,sizes:tt(a.state.sizes,a.state.lastSizes,2,e)}),we("layoutTabbed",a.state)},a.toggleShowResult=function(){var e=!a.state.showResult;a.setState({showResult:e,sizes:tt(a.state.sizes,a.state.lastSizes,1,e)}),we("layoutTabbed",a.state)};var r=Se().layoutTabbed;return a.state=et(r)?r:{showResult:!0,showLog:!0,currentNdx:2,sizes:[.45,.45,.1],lastSizes:[.45,.45,.1]},a.files=new Map,a.fileToKeyMap=new Map,a}return Object(c.a)(n,[{key:"getFileKey",value:function(e){var t=this.fileToKeyMap.get(e);return t||(t="".concat(Date.now(),"-").concat(Math.random()),this.fileToKeyMap.set(e,t)),t}},{key:"componentDidUpdate",value:function(){this.previousNdx!==this.state.currentNdx&&(this.previousNdx=this.state.currentNdx,this.files.forEach((function(e){e.refresh(),e.focus()})))}},{key:"render",value:function(){var e=this,t=this.props,n=t.hackKey,a=t.data,i=t.registerRunnerAPI,o=this.state,s=o.showResult,c=o.showLog,l=o.sizes,u=o.currentNdx,d=Object(w.a)({},!s&&{display:"none"}),h=Object(w.a)({},!c&&{display:"none"});return r.a.createElement("div",{className:"layout-tabbed"},r.a.createElement("div",{className:"layout-tabbed-top"},r.a.createElement("div",{className:"tab-tabs"},a.files.map((function(t,n){var a="ca".concat(e.getFileKey(t));return r.a.createElement(r.a.Fragment,{key:a},r.a.createElement("input",{type:"radio",name:"tabbed-files",id:a,checked:n===u,onClick:function(t){return e.handleOnChange(n)},onChange:function(e){return e}}),r.a.createElement("label",{htmlFor:a},t.name))})),r.a.createElement("input",{type:"checkbox",checked:s,onChange:this.toggleShowResult,id:"result"}),r.a.createElement("label",{htmlFor:"result"},"result"),r.a.createElement("input",{type:"checkbox",checked:c,onChange:this.toggleShowLog,id:"log"}),r.a.createElement("label",{htmlFor:"log"},"log"))),r.a.createElement(A.a,{direction:"vertical",minSize:0,sizes:l,onSetSizes:this.setSizes},r.a.createElement("div",{className:"tab-content"},a.files.map((function(t,a){var i="ca".concat(e.getFileKey(t));return r.a.createElement("div",{key:i,style:Object(w.a)({},a!==u&&{display:"none"})},r.a.createElement(Ge,{hackKey:n,desc:"filename",title:t.name,value:t.content,onTitleChange:function(e){return pe(a,e)},onValueChange:function(e){return ge(a,e)},register:e.handleRegister,unregister:e.handleUnregister}))}))),r.a.createElement("div",{className:"layout-tabbed-result",style:d},r.a.createElement(X,{registerAPI:i})),r.a.createElement("div",{className:"layout-tabbed-log",style:h},r.a.createElement(V,{onGoToLine:this.handleGoToLine}))))}}]),n}(r.a.Component)],at=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(){var e;Object(s.a)(this,n);for(var a=arguments.length,r=new Array(a),i=0;it.name.toLowerCase()?1:0};case"date":return function(e,t){return e.datet.date?1:0};case"public":return function(e,t){var n=e.public?1:0,a=t.public?1:0;return Math.sign(n-a)};case"check":return function(e,n){var a=t.has(e.id)?1:0,r=t.has(n.id)?1:0;return Math.sign(a-r)};default:throw new Error("unknown sortKey")}}(n,t);return Object.entries(e).map((function(e){var t=Object(S.a)(e,2),n=t[0],a=t[1];return{id:n,name:a.name,date:a.date,public:a.public}})).sort((function(e,t){return i(t,e)*r}))}function gt(e){var t=e.sortDir,n=e.selected,a=e.update;return r.a.createElement(r.a.Fragment,null,r.a.createElement("span",{onClick:function(){return a(n?"up"===t?"down":"up":t)},className:n?"current-sort-key":""},"up"===t?"\u25b2":"\u25bc"))}function ft(e){for(var t,n=0,a=Object.values(e);nt)&&(t=i)}return t}ne("gists",lt()),d.subscribe("gists",(function(){re("gists",lt())}));var vt=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(e){var a;Object(s.a)(this,n),(a=t.call(this,e)).handleNewGists=function(e){a.setState({gists:e})},a.toggleCheck=function(e){var t=new Set(a.state.checks);t.has(e)?t.delete(e):t.add(e),a.setState({checks:t})},a.onUserStatusChange=function(){a.forceUpdate(),a.context.userManager.getUserData()&&a.loadGists()},a.updateSort=function(e,t){console.log("update:",e,t),a.setState({sortDir:t,sortKey:e})},a.handleKeyDown=function(e){a.setState({shift:e.shiftKey})},a.handleKeyUp=function(e){a.setState({shift:e.shiftKey})},a.loadGists=Object(f.a)(g.a.mark((function e(){var t,n,r,i,o,s;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return t=a.context,n=t.addError,r=t.github,a.setState({loading:!0}),e.prev=2,i=a.state.shift?{}:a.state.gists,o=ft(i),e.next=7,r.getUserGists(o);case 7:s=e.sent,mt(s.reduce((function(e,t){return e[t.id]={name:t.description,date:t.updated_at,public:t.public},e}),Object(w.a)({},i))),e.next=15;break;case 12:e.prev=12,e.t0=e.catch(2),n("could not load gists: ".concat(e.t0));case 15:a.setState({loading:!1});case 16:case"end":return e.stop()}}),e,null,[[2,12]])}))),a.deleteSelected=Object(f.a)(g.a.mark((function e(){var t,n,r,i,o,s,c,l,u,d;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:t=a.state,n=t.checks,r=t.gists,i=[],n.forEach((function(e,t){r[e]&&i.push(e)})),o=a.context,s=o.addError,c=o.github,a.setState({loading:!0}),l=0,u=i;case 6:if(!(l=0&&r.a.createElement(r.a.Fragment,null,r.a.createElement("p",null,r.a.createElement(E,{className:"foobar",placeholder:"search:",value:s,onChange:function(t){e.setState({filter:t})}})),r.a.createElement("div",{className:"gists"},r.a.createElement("table",null,r.a.createElement("thead",null,r.a.createElement("tr",null,r.a.createElement("th",null,r.a.createElement(gt,{selected:"check"===c,sortDir:l,update:function(t){return e.updateSort("check",t)}})),r.a.createElement("th",null,r.a.createElement(gt,{selected:"name"===c,sortDir:l,update:function(t){return e.updateSort("name",t)}})),r.a.createElement("th",null,r.a.createElement(gt,{selected:"date"===c,sortDir:l,update:function(t){return e.updateSort("date",t)}})),r.a.createElement("th",null,r.a.createElement(gt,{selected:"public"===c,sortDir:l,update:function(t){return e.updateSort("public",t)}})))),r.a.createElement("tbody",null,h.filter(function(e){return e=e.trim().toLowerCase(),function(t){var n=t.name,a=t.date;return""===e||n.toLowerCase().includes(e)||a.substring(0,10).includes(e)}}(s)).map((function(t,n){return r.a.createElement("tr",{key:"g".concat(n)},r.a.createElement("td",null,r.a.createElement("input",{type:"checkbox",id:"gc".concat(n),checked:i.has(t.id),onChange:function(){return e.toggleCheck(t.id)}}),r.a.createElement("label",{htmlFor:"gc".concat(n)})),r.a.createElement("td",null,r.a.createElement("a",{onClick:e.clearBackup,href:"".concat(window.location.origin,"?src=").concat(encodeURIComponent(t.id))},t.name)),r.a.createElement("td",null,t.date.substring(0,10)),r.a.createElement("td",null,t.public?"":"\ud83d\udd12"))}))))),r.a.createElement("div",null,r.a.createElement("button",{onClick:this.deleteSelected},"Delete Selected Gists"))))}},{key:"render",value:function(){return this.context.userManager.getUserData()?this.renderLoad():this.renderLogin()}}]),n}(r.a.Component);function bt(e){var t=Object(a.useState)(""),n=Object(S.a)(t,2),i=n[0],o=n[1],s=Object(a.useContext)(F).addError;return r.a.createElement("div",null,r.a.createElement("div",{style:{height:"100px"}},r.a.createElement(Pe,{value:i,onValueChange:o})),r.a.createElement("p",null,r.a.createElement("button",{onClick:function(){var t=e.onLoad;try{fe(JSON.parse(i)),t()}catch(n){s("bad json: ".concat(n))}}},"Load JSON")))}function yt(e){var t=Object(a.useState)(""),n=Object(S.a)(t,2),i=n[0],o=n[1],s=Object(a.useContext)(F).addError;function c(){return(c=Object(f.a)(g.a.mark((function t(){var n,a;return g.a.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.onLoad,t.prev=1,t.next=4,fetch(i);case 4:return a=t.sent,t.next=7,a.json();case 7:fe(t.sent),n(),t.next=15;break;case 12:t.prev=12,t.t0=t.catch(1),s("could not load url: ".concat(t.t0));case 15:case"end":return t.stop()}}),t,null,[[1,12]])})))).apply(this,arguments)}return r.a.createElement("div",null,r.a.createElement(E,{value:i,onChange:o,placeholder:"url-to-json"}),r.a.createElement("p",null,r.a.createElement("button",{onClick:function(){return c.apply(this,arguments)}},"Load URL")))}function Et(e){var t=e.heading,n=e.children;return r.a.createElement("div",{className:"section"},r.a.createElement("div",{className:"section-heading"},t),r.a.createElement("div",{className:"section-content"},n))}function kt(e){var t=e.data,n=e.onLoad,a=e.onClose;return r.a.createElement(L,{title:"Load",className:"fixed-size-dialog",onClose:a},r.a.createElement(Et,{heading:"Load Gist"},r.a.createElement(vt,{data:t,onLoad:n})),r.a.createElement(Et,{heading:"Load URL"},r.a.createElement(yt,{data:t,onLoad:n})),r.a.createElement(Et,{heading:"Load JSON"},r.a.createElement(bt,{data:t,onLoad:n})))}vt.contextType=F;var wt=n(52),St=n(54),jt=new TextEncoder,Ot=new TextDecoder,xt=function(e){return e.startsWith("cb64,")||e.startsWith("b64,")};function Ct(e){var t=e.startsWith("cb64,"),n=t?"cb64,":"b64,",a=e.substr(n.length).replace(/-/g,"+").replace(/_/g,"/"),r=new Uint8Array(Object(wt.a)(a)),i=t?Object(St.b)(r):r,o=Ot.decode(i);return JSON.parse(o)}var Mt=/^[a-z0-9]+$/i,zt=function(e){return Mt.test(e)};function Nt(e,t){return Lt.apply(this,arguments)}function Lt(){return(Lt=Object(f.a)(g.a.mark((function e(t,n){var a,r,i,o,s;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!zt(t)){e.next=9;break}return e.next=3,n.getGist(t);case 3:return a=e.sent,r=a.data,i=a.rawData,e.abrupt("return",{data:r,id:t,rawData:i});case 9:if(!xt(t)){e.next=13;break}return e.abrupt("return",{data:Ct(t)});case 13:return e.next=15,fetch(t);case 15:return o=e.sent,e.next=18,o.json();case 18:return s=e.sent,e.abrupt("return",{data:s});case 20:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function It(e){var t=e.gistId,n=t||"f793cb359f2571409983351a6099d5d1";return r.a.createElement("div",null,r.a.createElement("div",{className:"markdown"},r.a.createElement("p",null,"You can embed a jsGist by creating an iframe pointing to"," ",r.a.createElement("code",null,"https://jsgist.org/embed.html?src=")," "," where"," ",r.a.createElement("code",null,"")," "," is one of the forms above. Either"," ",r.a.createElement("code",null,"?src=")," ","or"," ",r.a.createElement("code",null,"?src=")," ","or"," ",r.a.createElement("code",null,"?src=")," ",". You can also add "," ",r.a.createElement("code",null,"noheader=true")," "," if you don't want the header to appear. You can also just run them directly rather than put in an iframe. ",r.a.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://jsgist.org/embed.html?src=".concat(n)},"[example]")," ",r.a.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://jsgist.org/embed.html?src=".concat(n,"&noheader=true")},"[example no header]")),!!t&&r.a.createElement(r.a.Fragment,null,r.a.createElement("p",null,"For example to embed the current gist:"),r.a.createElement("pre",null,r.a.createElement("code",{style:{userSelect:"all"}},''))),r.a.createElement("p",null)))}function Ut(e){return e.split("\n").map((function(e){return" ".concat(e)})).join("\n")}var _t=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(e){var a;Object(s.a)(this,n),(a=t.call(this,e)).onChange=function(e){a.setState({asModule:e})},a.exportToCodepen=function(){!function(e){var t=e.files,n=Ye(t,"index.html","html"),a=Ye(t,"index.js","js","js","javascript"),r=Ye(t,"index.css","css"),i={title:e.name,description:e.name,editors:"101",html:n.content,css:r.content,js:a.content},o=document.createElement("div");o.innerHTML='\n "\n ',o.querySelector("input[name=data]").value=JSON.stringify(i),document.body.appendChild(o),o.querySelector("form").submit(),document.body.removeChild(o)}(a.props.data)},a.exportToJSFiddle=function(){!function(e){var t=e.files,n=Ye(t,"index.html","html"),a=Ye(t,"index.js","js","js","javascript"),r=Ye(t,"index.css","css"),i=document.createElement("div");i.innerHTML='\n \n ',i.querySelector("input[name=html]").value=n.content,i.querySelector("input[name=css]").value=r.content,i.querySelector("input[name=js]").value=a.content,i.querySelector("input[name=title]").value=e.name,document.body.appendChild(i),i.querySelector("form").submit(),document.body.removeChild(i)}(a.props.data)};var r=Ye(e.data.files,"index.js","js","js","javascript");return a.state={asModule:/\bimport\b/.test(r.content)},a}return Object(c.a)(n,[{key:"render",value:function(){var e=this,t=this.props.data,n=this.state.asModule;return r.a.createElement("div",null,r.a.createElement("button",{onClick:this.exportToCodepen},"Codepen"),r.a.createElement("button",{onClick:this.exportToJSFiddle},"JSFiddle"),r.a.createElement("p",null,"StackOverflow Snippet (copy the code below paste into S.O.)"),r.a.createElement("div",null,r.a.createElement("div",null,r.a.createElement("input",{type:"radio",id:"export-as-module",checked:n,onChange:function(t){return e.onChange(!0)}}),r.a.createElement("label",{htmlFor:"export-as-module"},"As es6 module")),r.a.createElement("div",null,r.a.createElement("input",{type:"radio",id:"export-as-script",checked:!n,onChange:function(t){return e.onChange(!1)}}),r.a.createElement("label",{htmlFor:"export-as-script"},"As script")),r.a.createElement("p",null,'S.O. does not support es6 modules yet so picking "As Module" puts the code in a \n\n\n`\n : `\n\n\n\n\n${indent4(mainJS.content)}\n\n\n\n${indent4(mainCSS.content)}\n\n\n\n${indent4(mainHTML.content)}\n\n\n`;\n\n}\n\nfunction openInCodepen(data) {\n const files = data.files;\n const mainHTML = getOrFind(files, 'index.html', 'html');\n const mainJS = getOrFind(files, 'index.js', 'js', 'js', 'javascript');\n const mainCSS = getOrFind(files, 'index.css', 'css');\n\n const pen = {\n title : data.name,\n description : data.name,\n editors : '101',\n html : mainHTML.content,\n css : mainCSS.content,\n js : mainJS.content,\n };\n\n const elem = document.createElement('div');\n elem.innerHTML = `\n
'\n \n \n \"
\"\n `;\n elem.querySelector('input[name=data]').value = JSON.stringify(pen);\n document.body.appendChild(elem);\n elem.querySelector('form').submit();\n document.body.removeChild(elem);\n}\n\nfunction openInJSFiddle(data) {\n const files = data.files;\n const mainHTML = getOrFind(files, 'index.html', 'html');\n const mainJS = getOrFind(files, 'index.js', 'js', 'js', 'javascript');\n const mainCSS = getOrFind(files, 'index.css', 'css');\n\n const elem = document.createElement('div');\n elem.innerHTML = `\n
\n \n \n \n \n \n \n
\n `;\n elem.querySelector('input[name=html]').value = mainHTML.content;\n elem.querySelector('input[name=css]').value = mainCSS.content;\n elem.querySelector('input[name=js]').value = mainJS.content;\n elem.querySelector('input[name=title]').value = data.name;\n document.body.appendChild(elem);\n elem.querySelector('form').submit();\n document.body.removeChild(elem);\n}\n\nfunction makeHTML(data, asModule) {\n const files = data.files;\n const mainHTML = getOrFind(files, 'index.html', 'html');\n const mainJS = getOrFind(files, 'index.js', 'js', 'js', 'javascript');\n const mainCSS = getOrFind(files, 'index.css', 'css');\n const isModule = asModule !== undefined ? asModule : /\\bimport\\b/.test(mainJS.content);\n const module = isModule\n ? ' type=\"module\"'\n : '';\n return `\n\n \n \n \n ${escapeTextForHTMLContent(data.name)}\n \n \n \n${mainHTML.content}\n \n <${'script'}${module}>\n${mainJS.content}\n \n\n`;\n}\n\nexport default class Export extends React.Component {\n constructor(props) {\n super(props);\n const mainJS = getOrFind(props.data.files, 'index.js', 'js', 'js', 'javascript');\n this.state = {\n asModule: /\\bimport\\b/.test(mainJS.content), // random guess\n }\n }\n onChange = (asModule) => {\n this.setState({asModule});\n }\n exportToCodepen = () => {\n openInCodepen(this.props.data);\n }\n exportToJSFiddle = () => {\n openInJSFiddle(this.props.data);\n }\n render() {\n const {data} = this.props;\n const {asModule} = this.state;\n return (\n
\n \n \n

StackOverflow Snippet (copy the code below paste into S.O.)

\n
\n
this.onChange(true)}/>
\n
this.onChange(false)}/>
\n

S.O. does not support es6 modules yet so picking \"As Module\" puts the code in a <script> in the HTML.

\n
\n
{makeSnippet(data, asModule)}
\n

HTML (copy the code below paste into a file)

\n
\n
this.onChange(true)}/>
\n
this.onChange(false)}/>
\n
\n
{makeHTML(data, asModule)}
\n
\n );\n }\n}","import React from 'react';\nimport {classNames} from '../libs/css-utils.js';\nimport * as gists from '../libs/gists.js';\nimport ServiceContext from '../ServiceContext.js';\n\nexport default class SaveAsGist extends React.Component {\n constructor () {\n super();\n this.state = {\n saving: false,\n secret: false,\n };\n }\n componentDidMount() {\n const {userManager} = this.context;\n userManager.subscribe(this.onPatChange);\n }\n componentWillUnmount() {\n const {userManager} = this.context;\n userManager.unsubscribe(this.onPatChange);\n }\n onPatChange = () => {\n this.forceUpdate();\n }\n toggleSecret = () => {\n this.setState({secret: !this.state.secret});\n }\n saveNew = async() => {\n const {github, addError} = this.context;\n const {secret} = this.state;\n this.setState({saving: true});\n const {data, onSave, onClose} = this.props;\n let success = false;\n try {\n const {id, name, date, public: _public} = await github.createGist(data, secret);\n gists.addGist(id, name, date, _public);\n onSave(id);\n success = true;\n } catch (e) {\n addError(`could not create gist: ${e}`)\n }\n this.setState({saving: false});\n if (success) {\n onClose();\n }\n }\n saveOverExisting = async() => {\n const {github, addError} = this.context;\n this.setState({saving: true});\n const {data, gistId, onClose} = this.props;\n let success = false;\n try {\n const {id, name, date, public: _public} = await github.updateGist(gistId, data);\n gists.addGist(id, name, date, _public);\n success = true;\n } catch (e) {\n addError(`could not update gist: ${e}`)\n }\n this.setState({saving: false});\n if (success) {\n onClose();\n }\n }\n forkAndSave = async() => {\n const {github, addError} = this.context;\n const {data, gistId, onSave, onClose} = this.props;\n const {secret} = this.state;\n this.setState({saving: true});\n let success = false;\n try {\n const {id: newId} = await github.forkGist(gistId, secret);\n const {id, name, date, public: _public} = await github.updateGist(newId, data);\n gists.addGist(id, name, date, _public);\n onSave(id);\n success = true\n } catch (e) {\n addError(`could not fork and update gist: ${e}`);\n }\n this.setState({saving: false});\n if (success) {\n onClose();\n }\n }\n renderLogin() {\n const {userManager} = this.context;\n return (\n
\n Login with github\n
\n );\n }\n renderSave() {\n const {saving, secret} = this.state;\n const {userManager} = this.context;\n const userData = userManager.getUserData();\n const {gistId, gistOwnerId} = this.props;\n const canUpdate = userData && gistId && userData.id === gistOwnerId;\n const canFork = userData && gistId && userData.id !== gistOwnerId;\n return (\n
\n
\n Save to New Gist\n Update Current Gist\n Fork and Save Gist\n
\n
\n
\n \n \n
Warning:\n
    \n
  • You can not change a gist from public to secret
  • \n
  • Secret gists are still publicly accessible they're just unlisted
  • \n
\n (see docs)\n
\n
\n
\n );\n }\n render() {\n const {userManager} = this.context;\n const userData = userManager.getUserData();\n return userData ? this.renderSave() : this.renderLogin();\n }\n}\n\nSaveAsGist.contextType = ServiceContext;","import React from 'react';\n\nexport default function SaveAsJSON(props) {\n const {data} = props;\n return (\n
\n
\n Copy the text below, paste into the load ui or put somewhere on the net\n and make your own URL with {window.location.origin}?src=url-to-json.\n
\n
{JSON.stringify(data)}
\n \n
\n );\n}","import React from 'react';\n\nimport {jsonToCompressedBase64} from '../libs/compression.js';\n\nexport default function SaveAsURL(props) {\n const {data} = props;\n const src = jsonToCompressedBase64(data);\n const url = `${window.location.origin}?src=${encodeURIComponent(src)}`;\n return url.length < 8000\n ? (\n
\n
Copy / bookmark the link below
\n {url}\n
\n )\n : (\n
\n Too large to save as URL\n
\n )\n ;\n}\n","import React from 'react';\nimport Dialog from './Dialog.js';\nimport Embed from './Embed.js';\nimport Export from './Export.js';\nimport SaveAsGist from './SaveAsGist.js';\nimport SaveAsJSON from './SaveAsJSON.js';\nimport SaveAsURL from './SaveAsURL.js';\nimport Section from './Section.js';\n\nexport default function Save(props) {\n const {data, gistId, gistOwnerId, onSave, onClose} = props;\n return (\n \n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n )\n}\n","import React from 'react';\n\nimport Dialog from './Dialog.js';\nimport Section from './Section.js';\nimport ServiceContext from '../ServiceContext.js';\n\nimport verticalIcon from '../icons/vertical-layout.svg';\nimport horizontalIcon from '../icons/horizontal-layout.svg';\nimport twoByTwoIcon from '../icons/two-by-two-layout.svg';\nimport tabbedIcon from '../icons/tabbed-layout.svg';\n\nimport {classNames} from '../libs/css-utils.js';\nimport * as uiModel from '../libs/ui-model.js';\n\nfunction RadioOption(props) {\n const {children, onChange, selected} = props;\n return (\n
\n {children}\n
\n );\n}\n\nfunction Radio(props) {\n const {selected, onChange, children} = props;\n\n const newChildren = React.Children.map(children, (child) => {\n if (!React.isValidElement(child)) {\n return null;\n }\n\n const {result} = child.props;\n const isSelected = result === selected;\n\n //const id = childNdx;\n //childNdx += 1;\n return React.cloneElement(child, {\n //...child.props,\n selected: isSelected,\n onChange: () => onChange(result),\n });\n });\n\n return (\n
\n {newChildren}\n
\n );\n}\n\nfunction Checkbox(props) {\n const {id, label, checked, onChange} = props;\n const elemId = `checkbox-${id}`;\n return (\n
\n onChange(e.target.checked)}\n />\n \n
\n );\n}\n\nclass Logout extends React.Component {\n componentDidMount() {\n const {userManager} = this.context;\n userManager.subscribe(this.handleChange);\n }\n componentWillUnmount() {\n const {userManager} = this.context;\n userManager.unsubscribe(this.handleChange);\n }\n handleChange = () => {\n this.forceUpdate();\n }\n handleLogout = () => {\n const {userManager} = this.context;\n userManager.logout();\n }\n render() {\n const {userManager} = this.context;\n const userData = userManager.getUserData();\n return (!!userData &&\n
\n
Logged in as: \n {!!userData.login && }\n {!!userData.avatar_url && \"avatar\"/}\n
\n \n
\n );\n }\n}\n\nLogout.contextType = ServiceContext;\n\nexport default class Settings extends React.Component {\n //constructor(props) {\n // super(props);\n //}\n componentDidMount() {\n uiModel.subscribe(this.handleChange);\n }\n componentWillUnmount() {\n uiModel.unsubscribe(this.handleChange);\n }\n handleChange = () => {\n this.forceUpdate();\n }\n handleLayoutChange = (v) => {\n uiModel.set('layout', v);\n }\n handleEditorChange = (v) => {\n uiModel.set('editor', v);\n }\n handleLineNumbersChange = (v) => {\n uiModel.set('lineNumbers', v);\n }\n handleTabsChange = (v) => {\n uiModel.set('tabs', v);\n }\n handleShowWhitespaceChange = (v) => {\n uiModel.set('showWhitespace', v);\n }\n render() {\n const {onClose} = this.props;\n const {userManager} = this.context;\n const userData = userManager.getUserData();\n return (\n \n { !!userData && }\n
\n
\n \n \"vertical\"/\n \"horizontal\"/\n \"2x2\"\n \"tabbed\"\n \n
\n
\n
\n
\n \n
Monaco
\n
CodeMirror
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nSettings.contextType = ServiceContext;\n","import React from 'react';\n\nexport default function Toolbar(props) {\n const {\n toolbarFns,\n fullscreen,\n } = props;\n const {\n handleRun,\n handleStop,\n handleSave,\n handleNew,\n handleLoad,\n handleFullscreen,\n handleSettings,\n handleHelp,\n } = toolbarFns;\n return (\n
\n \n \n \n \n \n \n \n \n
\n );\n}","import SubscriptionManager from './SubscriptionManager.ts';\n\nconst kUserManagerKey = 'foobar'; // not important\n\nexport default class UserManager {\n constructor({\n oauthManager,\n github,\n addError,\n }) {\n this.oauthManager = oauthManager;\n this.github = github;\n this.subscriptionManager = new SubscriptionManager();\n this.addError = addError;\n oauthManager.subscribe(this._handleNewAuth);\n this._handleNewAuth();\n this.userData = undefined;\n }\n /*\n {\n \"login\": \"greggman\",\n \"id\": 234804,\n \"node_id\": \"MDQ6VXNlcjIzNDgwNA==\",\n \"avatar_url\": \"https://avatars2.githubusercontent.com/u/234804?v=4\",\n \"gravatar_id\": \"\",\n \"url\": \"https://api.github.com/users/greggman\",\n \"html_url\": \"https://github.com/greggman\",\n \"followers_url\": \"https://api.github.com/users/greggman/followers\",\n \"following_url\": \"https://api.github.com/users/greggman/following{/other_user}\",\n \"gists_url\": \"https://api.github.com/users/greggman/gists{/gist_id}\",\n \"starred_url\": \"https://api.github.com/users/greggman/starred{/owner}{/repo}\",\n \"subscriptions_url\": \"https://api.github.com/users/greggman/subscriptions\",\n \"organizations_url\": \"https://api.github.com/users/greggman/orgs\",\n \"repos_url\": \"https://api.github.com/users/greggman/repos\",\n \"events_url\": \"https://api.github.com/users/greggman/events{/privacy}\",\n \"received_events_url\": \"https://api.github.com/users/greggman/received_events\",\n \"type\": \"User\",\n \"site_admin\": false,\n \"name\": \"Greggman\",\n \"company\": null,\n \"blog\": \"http://games.greggman.com\",\n \"location\": \"Earth\",\n \"email\": \"github@greggman.com\",\n \"hireable\": null,\n \"bio\": \"30 years of games\\r\\n5 years of Chrome\",\n \"twitter_username\": null,\n \"public_repos\": 283,\n \"public_gists\": 80,\n \"followers\": 1037,\n \"following\": 3,\n \"created_at\": \"2010-04-01T08:48:05Z\",\n \"updated_at\": \"2020-10-24T06:05:24Z\"\n }\n */\n getUserData() {\n return this.userData;\n }\n _handleNewAuth = async() => {\n this.userData = undefined;\n const pat = this.oauthManager.pat();\n this.github.setPat(pat);\n if (pat) {\n try {\n const data = await this.github.getAuthenticatedUser();\n this.userData = data;\n } catch (e) {\n this.addError(e);\n }\n }\n this.subscriptionManager.notify(kUserManagerKey);\n }\n login = () => {\n this.oauthManager.login();\n }\n logout = () => {\n this.oauthManager.logout();\n this.github.setPat()\n }\n subscribe(fn) {\n this.subscriptionManager.subscribe(kUserManagerKey, fn);\n }\n unsubscribe(fn) {\n this.subscriptionManager.unsubscribe(kUserManagerKey, fn);\n }\n cleanup() {\n this.oauthManager.unsubscribe(this._handleNewAuth);\n }\n}\n\n","import React from 'react';\n\nimport EditLine from './EditLine.js';\n// import Footer from './Footer.js';\nimport {storageManager} from '../globals.js';\nimport GitHub from '../libs/GitHub.js';\nimport Head from './Head.js';\nimport Help from './Help.js';\nimport IDE from './IDE.js';\nimport Load from './Load.js';\nimport {isGistId, loadGistFromSrc} from '../libs/loader.js';\nimport {LogManager} from './Log.js';\nimport * as model from '../libs/model.js';\nimport Save from './Save.js';\nimport ServiceContext from '../ServiceContext.js';\nimport Settings from './Settings.js';\nimport Toolbar from './Toolbar.js';\nimport * as uiModel from '../libs/ui-model.js';\nimport UserManager from '../libs/UserManager.js';\nimport * as winMsgMgr from '../libs/WindowMessageManager';\nimport query from '../libs/start-query.js';\n\nimport './App.css';\nimport { classNames } from '../libs/css-utils.js';\n\nconst noJSX = () => [];\nconst darkMatcher = window.matchMedia('(prefers-color-scheme: dark)');\n\nclass App extends React.Component {\n constructor(props) {\n super();\n this.state = {\n path: window.location.pathname,\n dark: darkMatcher.matches,\n fullscreen: !!query.fullscreen,\n loading: false,\n dialog: noJSX,\n gistId: '',\n messages: [],\n userData: {},\n updateVersion: 0,\n };\n this.github = new GitHub();\n this.oauthManager = props.oauthManager;\n this.backupManager = props.backupManager;\n this.logManager = new LogManager();\n this.userManager = new UserManager({\n oauthManager: this.oauthManager,\n github: this.github,\n addError: this.addError,\n });\n this.toolbarFns = {\n handleRun: this.handleRun,\n handleStop: this.handleStop,\n handleSave: this.handleSave,\n handleNew: this.handleNew,\n handleLoad: this.handleLoad,\n handleSettings: this.handleSettings,\n handleFullscreen: this.handleFullscreen,\n handleHelp: this.handleHelp,\n };\n }\n componentWillUnmount() {\n uiModel.unsubscribe(this.handleUIChange);\n this.userManager.cleanup();\n }\n componentDidMount() {\n uiModel.subscribe(this.handleUIChange);\n winMsgMgr.on('newGist', null, this.handleNewGist);\n this.github.addEventListener('userdata', (e) => {\n this.setState({\n userData: e.data,\n });\n });\n model.add('path', window.location.pathname);\n model.subscribe('path', (newValue) => {\n window.history.pushState({}, '', newValue);\n this.setState({\n path: newValue,\n });\n });\n // I still am not sure how I'm supposed to handle this.\n // Putting my model in the state itself seems wrong\n // and doesn't actually help since I'd have to \n // generate an entirely new state object to change any\n // nested property.\n //\n // Storing the data outside I see no way to tell\n // components to re-render except to call forceUpdate\n // which all the documentation says \"if you call this\n // you're doing it wrong\".\n //\n // Redux is a joke. 50 lines code needed to set\n // a single field. Repeat those 50 lines for every field.\n // Things like redux-tools make it less to type those\n // 50 lines but they still execute 50 to 500 lines of code\n // just to set a single value.\n model.subscribe(model.filesVersionKey, _ => {\n this.forceUpdate();\n });\n // this is a hack because I can't figure out how to\n // update the CodeMirror areas\n model.subscribe('updateVersion', _ => {\n this.setState({updateVersion: this.state.updateVersion + 1});\n });\n\n darkMatcher.addEventListener('change', () => {\n this.setState({dark: darkMatcher.matches});\n });\n\n if (query.newGist) {\n window.history.pushState({}, '', `${window.location.origin}`);\n window.opener.postMessage({type: 'gimmeDaCodez'}, '*');\n return;\n }\n\n const backup = this.backupManager.getBackup();\n let loaded = false;\n if (backup) {\n try {\n const data = JSON.parse(backup);\n if (data.href === window.location.href) {\n model.setData(data.data);\n const url = new URL(data.href);\n const {src} = Object.fromEntries(new URLSearchParams(url.search).entries());\n if (isGistId(src)) {\n this.setState({gistId: src, gistOwnerId: data.gistOwnerId});\n }\n loaded = true;\n this.addInfo('loaded backup from local storage')\n }\n } catch (e) {\n console.log('bad backup')\n }\n this.backupManager.clearBackup();\n }\n if (!loaded) {\n if (query.src) {\n this.loadData(query.src);\n }\n }\n this.updateTitle();\n }\n componentDidUpdate() {\n this.updateTitle();\n }\n updateTitle() {\n const data = model.getData();\n document.title = data.name || 'jsGist';\n }\n async loadData(src) {\n this.setState({loading: true});\n let success = true;\n let firstTry = true;\n for (;;) {\n try {\n const {data, id, rawData} = await loadGistFromSrc(src, this.github);\n model.setData(data);\n if (id) {\n this.setState({\n gistId: src,\n gistOwnerId: rawData?.owner?.id,\n });\n }\n break;\n } catch (e) {\n if (firstTry) {\n this.userManager.logout();\n firstTry = false;\n } else {\n success = false;\n console.warn(e);\n this.addError(`could not load jsGist: src=${src} ${e}`);\n break;\n }\n }\n }\n this.setState({loading: false});\n if (success) {\n this.handleRun();\n }\n }\n handleUIChange = () => {\n this.forceUpdate();\n }\n handleNewGist = (data) => {\n let success = true;\n try {\n model.setData(data);\n this.backupManager.clearBackup();\n } catch (e) {\n success = false;\n console.warn(e);\n this.addError(`could create new jsGist: ${e}`);\n }\n if (success) {\n this.handleRun();\n }\n };\n addMsg = (msg, className) => {\n switch (className) {\n case 'error':\n console.error(msg);\n break;\n default:\n console.log(msg);\n break;\n }\n this.setState({messages: [{msg: msg.toString(), className}, ...this.state.messages]});\n setTimeout(() => {\n this.setState({messages: this.state.messages.slice(0, this.state.messages.length - 1)});\n }, 5000);\n }\n addInfo = (msg) => this.addMsg(msg, 'info');\n addError = (msg) => this.addMsg(msg, 'error');\n closeDialog = () => {\n this.setState({dialog: noJSX});\n }\n registerRunnerAPI = (api) => {\n this.runnerAPI = api;\n this.handleStop();\n }\n handleNew = async() => {\n this.backupManager.clearBackup();\n window.location.href = window.location.origin; // causes a reload\n }\n handleRun = async () => {\n this.backupManager.setBackup(JSON.stringify({\n href: window.location.href,\n data: model.getData(),\n gistOwnerId: this.state.gistOwnerId,\n }));\n this.logManager.clear();\n console.clear();\n this.runnerAPI.run(model.getData());\n }\n handleStop = async () => {\n this.runnerAPI.run(model.getBlankData(), true);\n }\n handleSave = async () => {\n this.setState({dialog: this.renderSave});\n }\n handleSettings = () => {\n this.setState({dialog: this.renderSettings});\n }\n handleFullscreen = () => {\n this.setState({fullscreen: !this.state.fullscreen});\n }\n handleHelp = () => {\n this.setState({dialog: this.renderHelp});\n }\n handleLoad = () => {\n this.setState({dialog: this.renderLoad});\n }\n handleOnLoad = async() => {\n this.setState({dialog: noJSX});\n this.handleRun();\n }\n handleOnSave = (gistId) => {\n window.history.pushState({}, '', `${window.location.origin}?src=${gistId}`);\n this.setState({\n gistId,\n gistOwnerId: this.userManager.getUserData().id,\n });\n }\n handleAbort = () => {\n this.abort();\n };\n renderHelp = () => {\n return ();\n }\n renderSettings = () => {\n return (\n \n );\n }\n renderLoad = () => {\n return (\n \n );\n }\n renderSave = () => {\n const data = model.getData();\n return (\n \n );\n }\n render() {\n const data = model.getData();\n const {\n loading,\n dialog,\n updateVersion: hackKey,\n userData,\n fullscreen,\n } = this.state;\n const editor = uiModel.get().editor;\n return (\n
\n \n
\n
\n
\n
\n model.setName(v)} />\n {!!userData.name && }\n {!!userData.avatarURL && \"avatar\"/}\n
\n
\n
\n \n \n
\n
\n {\n !loading &&\n
\n \n
\n }\n
\n {/*\n \n */}\n {dialog()}\n
\n {\n this.state.messages.map(({msg, className}, i) => (
{msg}
))\n }\n
\n
\n
\n );\n }\n}\n\nexport default App;\n","const backupKey = 'backup';\r\n\r\nexport default class BackupManager {\r\n #storageManager;\r\n\r\n constructor(storageManager) {\r\n this.#storageManager = storageManager;\r\n }\r\n getBackup() {\r\n return this.#storageManager.get(backupKey);\r\n }\r\n setBackup(data) {\r\n this.#storageManager.set(backupKey, data);\r\n }\r\n clearBackup() {\r\n this.#storageManager.delete(backupKey);\r\n }\r\n}","\nimport {clientId} from '../globals.js';\nimport {createURL} from './url.js';\nimport {createPopup} from './utils';\nimport StorageManager from './StorageManager';\nimport * as winMsgMgr from './WindowMessageManager';\n\nconst patKey = 'pat';\n\nconst getTokenURL = process.env.REACT_APP_OAUTH_HELPER_URL;\nif (!getTokenURL) {\n throw Error ('must set environment variable: OAUTH_HELPER_URL');\n}\n\nexport default class OAuthManager {\n private _popup?: Window;\n private _state?: string;\n private _storageManager: StorageManager;\n\n constructor(storageManager: StorageManager) {\n this._popup = undefined;\n this._state = undefined; // last state sent to auth\n this._storageManager = storageManager;\n winMsgMgr.on('auth', null, (data: any) => {\n this._closePopup();\n if (data.state === this._state) {\n this.requestToken(data);\n }\n });\n }\n // TODO: rename this and decide if Github should be connected\n pat() {\n return this._storageManager.get(patKey);\n }\n subscribe(fn: () => void) {\n this._storageManager.subscribe(patKey, fn);\n }\n unsubscribe(fn: () => void) {\n this._storageManager.unsubscribe(patKey, fn);\n }\n _closePopup() {\n if (this._popup) {\n this._popup.close();\n this._popup = undefined;\n }\n }\n requestToken = async (auth: any) => {\n try {\n const params = {\n client: clientId,\n code: auth.code,\n };\n const url = createURL(getTokenURL, params);\n const req = await fetch(url);\n const data = await req.json();\n if (!data.access_token) {\n throw new Error(JSON.stringify(data));\n }\n this._storageManager.set(patKey, data.access_token);\n } catch (e) {\n console.error(e);\n }\n }\n logout = () => {\n this._storageManager.delete(patKey);\n }\n login = () => {\n this._closePopup();\n this._state = `${Date.now()}-${Math.random()}`; // does this need to special? Seems like no\n const url = createURL('https://github.com/login/oauth/authorize', {\n client_id: clientId,\n scope: 'gist',\n state: this._state,\n });\n this._popup = createPopup(url);\n }\n}","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.0/8 are considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl, {\n headers: { 'Service-Worker': 'script' },\n })\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready\n .then(registration => {\n registration.unregister();\n })\n .catch(error => {\n console.error(error.message);\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport {storageManager} from './globals.js';\nimport './index.css';\nimport './scrollbars.js';\nimport App from './components/App';\nimport BackupManager from './components/BackupManager.js';\nimport OAuthManager from './libs/OAuthManager';\nimport * as serviceWorker from './serviceWorker';\n\nconst oauthManager = new OAuthManager(storageManager);\nconst backupManager = new BackupManager(storageManager);\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n);\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n","module.exports = __webpack_public_path__ + \"static/media/vertical-layout.f248a432.svg\";","module.exports = __webpack_public_path__ + \"static/media/horizontal-layout.e3f3298b.svg\";","module.exports = __webpack_public_path__ + \"static/media/two-by-two-layout.23605ce8.svg\";","module.exports = __webpack_public_path__ + \"static/media/tabbed-layout.8a8b9bc8.svg\";"],"sourceRoot":""} \ No newline at end of file diff --git a/static/js/main.bd7fc67a.chunk.js b/static/js/main.bd7fc67a.chunk.js new file mode 100644 index 0000000..e7d8c0e --- /dev/null +++ b/static/js/main.bd7fc67a.chunk.js @@ -0,0 +1,2 @@ +(this.webpackJsonpjsgist=this.webpackJsonpjsgist||[]).push([[0],{177:function(e,t,n){},178:function(e,t,n){"use strict";n.r(t);var a=n(0),r=n.n(a),i=n(76),o=n.n(i),s=n(3),c=n(5),l=n(16),u=function(){function e(){Object(s.a)(this,e),this.itemToSubscriptionMap=void 0,this.itemToSubscriptionMap=new Map}return Object(c.a)(e,[{key:"subscribe",value:function(e,t){this.unsubscribe(e,t);var n=this.itemToSubscriptionMap.get(e);n||(n=[],this.itemToSubscriptionMap.set(e,n)),n.push(t)}},{key:"unsubscribe",value:function(e,t){var n=this.itemToSubscriptionMap.get(e);if(n){var a=n.indexOf(t);a>=0&&(n.splice(a,1),0===n.length&&this.itemToSubscriptionMap.delete(e))}}},{key:"notify",value:function(e){var t=this.itemToSubscriptionMap.get(e);if(t){var n,a=Object(l.a)(t.slice());try{for(a.s();!(n=a.n()).done;){(0,n.value)()}}catch(r){a.e(r)}finally{a.f()}}}}]),e}();var d=new(function(){function e(t){var n=this;Object(s.a)(this,e),this.prefix=void 0,this.subscriptionManager=void 0,this._handleNewValue=function(e){var t=e.key;if(t&&t.startsWith(n.prefix)){var a=t.substr(n.prefix.length);n.subscriptionManager.notify(a)}},this.prefix="".concat(t,"-"),this.subscriptionManager=new u,window.addEventListener("storage",this._handleNewValue)}return Object(c.a)(e,[{key:"_addPrefix",value:function(e){return"".concat(this.prefix).concat(e)}},{key:"subscribe",value:function(e,t){this.subscriptionManager.subscribe(e,t)}},{key:"unsubscribe",value:function(e,t){this.subscriptionManager.unsubscribe(e,t)}},{key:"get",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this._addPrefix(e);if(t){var a=sessionStorage.getItem(n);if(a)return a}return localStorage.getItem(n)}},{key:"set",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],a=this._addPrefix(e);n&&sessionStorage.setItem(a,t),localStorage.setItem(a,t),this.subscriptionManager.notify(e)}},{key:"delete",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this._addPrefix(e);t&&sessionStorage.removeItem(n),localStorage.removeItem(n),this.subscriptionManager.notify(e)}},{key:"cleanup",value:function(){window.removeEventListener("storage",this._handleNewValue)}}]),e}())("jsgist"),h=(n(93),n(94),document.createElement("div"));h.setAttribute("style","width:30px;height:30px;"),h.classList.add("scrollbar-test");var m=document.createElement("div");m.setAttribute("style","width:100%;height:40px"),h.appendChild(m),document.body.appendChild(h),30-h.firstChild.clientWidth&&document.body.classList.add("layout-scrollbar-obtrusive"),document.body.removeChild(h);var p=n(1),g=n.n(p),f=n(8),v=n(42),b=n(6),y=n(7);function E(e){return r.a.createElement("input",{type:"text",onChange:function(t){e.onChange(t.target.value)},placeholder:e.placeholder,value:e.value})}var w=n(20),k=n(4),S=n(11),j=n(53),O="/*bug-in-github-api-content-can-not-be-empty*/";function x(e){return e.content.startsWith(O)?e.content.substr(O.length):e.content}function C(e){var t=JSON.parse(e.files["jsGist.json"].content);return t.filenames?t.files=t.filenames.map((function(t){return{name:t,content:x(e.files[t])}})):t.files=Object.entries(e.files).filter((function(e){return"jsGist.json"!==Object(S.a)(e,1)[0]})).map((function(e){var t=Object(S.a)(e,2);return{name:t[0],content:x(t[1])}})).concat(t.files||[]),t}function M(e,t,n){var a=e.files.reduce((function(e,t){return e[t.name]={content:t.content.trim()?t.content:"".concat(O).concat(t.content)},e}),{}),r=Object(k.a)({},e),i={};if(a["jsGist.json"]=i,Object.keys(a).length===e.files.length+1?(delete r.files,r.filenames=e.files.map((function(e){return e.name}))):a={"jsGist.json":i},i.content=JSON.stringify(r),n){var o=Object.keys(a).map((function(e){return e.toLowerCase()}));if(!(o.includes("readme.md")||o.includes("readme.txt")||o.includes("readme"))){var s="## ".concat(e.name,"\n\n[view on jsgist](").concat(window.location.origin,"?src=").concat(n,")");a["README.md"]={content:s}}for(var c=0,l=Object.entries(a);c1&&void 0!==i[1]&&i[1],a=M(t,n),e.next=4,this.authorizedOctokit.gists.create(a);case 4:return r=e.sent,this._updateUserData(r.data),e.next=8,this.updateGist(r.data.id,t);case 8:return e.abrupt("return",e.sent);case 9:case"end":return e.stop()}}),e,this)})));return function(t){return e.apply(this,arguments)}}()},{key:"updateGist",value:function(){var e=Object(f.a)(g.a.mark((function e(t,n){var a,r;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a=M(n,!1,t),e.next=3,this.authorizedOctokit.gists.update(a);case 3:return r=e.sent,e.abrupt("return",{id:r.data.id,name:r.data.description,date:r.data.updated_at,public:r.data.public});case 5:case"end":return e.stop()}}),e,this)})));return function(t,n){return e.apply(this,arguments)}}()},{key:"forkGist",value:function(){var e=Object(f.a)(g.a.mark((function e(t){var n;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this.authorizedOctokit.gists.fork({gist_id:t});case 2:return n=e.sent,e.abrupt("return",{id:n.data.id});case 4:case"end":return e.stop()}}),e,this)})));return function(t){return e.apply(this,arguments)}}()},{key:"deleteGist",value:function(){var e=Object(f.a)(g.a.mark((function e(t){var n;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this.authorizedOctokit.gists.delete({gist_id:t});case 2:return n=e.sent,e.abrupt("return",n);case 4:case"end":return e.stop()}}),e,this)})));return function(t){return e.apply(this,arguments)}}()},{key:"createGistComment",value:function(){var e=Object(f.a)(g.a.mark((function e(t,n){var a;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this.authorizedOctokit.gists.createComment({gist_id:t,body:n});case 2:if(!((a=e.sent).status<200||a.status>=300)){e.next=5;break}throw new Error(a.message);case 5:return e.abrupt("return",a.data);case 6:case"end":return e.stop()}}),e,this)})));return function(t,n){return e.apply(this,arguments)}}()},{key:"octokit",get:function(){return this.authorizedOctokit||this.unAuthorizedOctokit}}]),n}(Object(w.a)(EventTarget));function N(){return r.a.createElement("div",{className:"head"},r.a.createElement("div",null,r.a.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:window.location.origin},r.a.createElement("img",{src:"/resources/images/logo-small.svg",alt:"logo"}),window.location.hostname)),r.a.createElement("div",{className:"fix-help-contribute"},r.a.createElement("div",{className:"octocat"},r.a.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/greggman/jsgist/"},r.a.createElement("img",{alt:"github",src:"/resources/images/octocat-icon.svg"})))))}var L=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(){var e;Object(s.a)(this,n);for(var a=arguments.length,r=new Array(a),i=0;i--"),"."),r.a.createElement("p",null,"Example: ",r.a.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://jsgist.org/?src=f793cb359f2571409983351a6099d5d1"},"https://jsgist.org/?src=f793cb359f2571409983351a6099d5d1"))),r.a.createElement("li",null,"Save it manually somewhere else.",r.a.createElement("p",null,"If there's some other service that will provide a string via http get then copy and save the JSON there then create a URL in the form of ",r.a.createElement("code",null,"https://jsgist.org/?src="),". Note: you may have to escape the URL.")),r.a.createElement("li",null,"Save it as a bookmark or link",r.a.createElement("p",null,"In the SaveAs dialog there's a link that contains all the data for your benchmark.")))))}var U=n(15),_=n.n(U),T=n(14),A=n.n(T),D=n(18),P=/([a-z])([A-Z])/g,R=function(e,t,n){return"".concat(t,"-").concat(n)},G=function(e){return e.replace(P,R).toLowerCase()};function K(){for(var e=[],t=arguments.length,n=new Array(t),a=0;a=0?e.substr(t+1):e}(t.url||""),":",t.lineNo)))}))))}}]),n}(r.a.Component);function W(e,t){for(var n=new URL(e),a=new URLSearchParams(n.search),r=0,i=Object.entries(t);r=0&&r.splice(i,1),0===r.length&&(a.delete(e),0===a.size&&t&&q.delete(t))}}}function $(e,t,n){var a=e.get(t);if(a){var r,i=Object(l.a)(a);try{for(i.s();!(r=i.n()).done;){(0,r.value)(n)}}catch(o){i.e(o)}finally{i.f()}return!0}return!1}window.addEventListener("message",(function(e){var t=e.data,n=t.type,a=t.data,r=q.get(e.source);r&&$(r,n,a)||$(H,n,a)}));var X=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(e){var a;return Object(s.a)(this,n),(a=t.call(this,e)).handleJSLog=function(e){a.context.logManager.addMsg(e)},a.handleJSError=function(e){a.context.logManager.addMsg(Object(k.a)(Object(k.a)({},e),{},{type:"error",showStack:!0}))},a.handleJSUnhandledRejection=function(e){a.context.logManager.addMsg(Object(k.a)(Object(k.a)({},e),{},{type:"error",showStack:!0}))},a.handleInfoMessages=function(e){a.context.logManager.addMsgs(e)},a.handleGimmeDaCodez=function(){a.iframe.contentWindow.postMessage({type:"run",data:a.data},"*")},a.handleMessage=function(e){var t=e.data,n=t.type,r=t.data,i=a.handlers[n];i&&i(r)},a.runnerRef=r.a.createRef(),a}return Object(c.a)(n,[{key:"componentDidMount",value:function(){var e=this,t=this.props.registerAPI,n=Object.fromEntries(new URLSearchParams(window.location.search).entries()).debug,a=Object(k.a)({},n&&{debug:n});t({run:function(t,n){e.data=t,e.removeIFrame();var r=document.createElement("iframe");e.iframe=r,r.src=W("https://jsgistrunner.devcomments.org/runner-03.html",Object(k.a)({url:"https://jsgist.org/jsgist-runner.js"},a)),n&&(r.style.background="none"),e.runnerRef.current.appendChild(r)}}),B("gimmeDaCodez",null,this.handleGimmeDaCodez),B("jsLog",null,this.handleJSLog),B("jsError",null,this.handleJSError),B("jsUnhandledRejection",null,this.handleJSUnhandledRejection),B("infoMessages",null,this.handleInfoMessages)}},{key:"removeIFrame",value:function(){this.iframe&&(this.iframe.remove(),this.iframe.src="about:blank",this.iframe=void 0)}},{key:"componentWillUnmount",value:function(){this.removeIFrame(),Y("gimmeDaCodez",null,this.handleGimmeDaCodez),Y("jsLog",null,this.handleJSLog),Y("jsError",null,this.handleJSError),Y("jsUnhandledRejection",null,this.handleJSUnhandledRejection),Y("infoMessages",null,this.handleInfoMessages)}},{key:"render",value:function(){return r.a.createElement("div",{className:"runner",ref:this.runnerRef})}}]),n}(r.a.Component);X.contextType=F;var Z=n(79),Q=(new _.a).compile(Z),ee={};function te(e){var t=ee[e]||{subscriptions:new Set};return ee[e]=t,t}function ne(e,t){var n=te(e);return void 0!==t&&(n.value=t),n}function ae(e){return ee[e].value}function re(e,t){var n=ee[e];if(!n)throw new Error("no such track value: ".concat(e));n.value=t;var a,r=Object(v.a)(n.subscriptions.keys()),i=Object(l.a)(r);try{for(i.s();!(a=i.n()).done;){(0,a.value)(t,e)}}catch(o){i.e(o)}finally{i.f()}}function ie(e,t){te(e).subscriptions.add(t)}function oe(e,t){te(e).subscriptions.delete(t)}var se,ce={name:"My jsGist",settings:{},files:[{name:"index.html",content:""},{name:"index.css",content:""},{name:"index.js",content:""}]};function le(){var e="".concat(window.location.origin,"/resources/images/logo.svg");return JSON.parse(JSON.stringify({name:"jsGist",settings:{},files:[{name:"index.html",content:""},{name:"index.css",content:"\n html, body {\n margin: 0;\n width: 100%;\n height: 100%;\n background-image: url(".concat(e,");\n background-size: contain contain;\n background-position: center center;\n background-repeat: no-repeat no-repeat;\n }\n @media (prefers-color-scheme: dark) {\n html {\n background: #222;\n }\n }\n ")},{name:"index.js",content:""}]}))}function ue(){return se}ne("dataVersion",0),ne("updateVersion",0),ne("filesVersion",0);var de=function(e){return re(e,ae(e)+1)},he=function(e){return de("dataVersion")},me=function(e){return de("filesVersion")};function pe(e,t){se.files[e].name=t,he()}function ge(e,t){se.files[e].content=t,he()}function fe(e){!function(e){if(!Q(e))throw new Error("data not valid:\n".concat(Q.errors.map((function(e){return"".concat(e.message,": ").concat(e.dataPath)}))))}(e),se=e,de("updateVersion"),he(),me()}fe(JSON.parse(JSON.stringify(ce)));var ve,be=Object.fromEntries(new URLSearchParams(window.location.search).entries()),ye=!be.codeMirror&&!/webOS|iPhone|iPad|Android/.test(navigator.userAgent),Ee=!1,we={layout:window.screen.width<540||window.screen.height<540?3:0,editor:ye?"monaco":"codemirror",lineNumbers:!0,tabs:!1,showWhitespace:!1};function ke(e,t){ve[e]=t;var n=JSON.stringify(ve);d.set("ui-settings",n,!0),re("settings",ve)}function Se(){return function(){if(!Ee){Ee=!0;try{if(!(ve=JSON.parse(d.get("ui-settings",!0))))throw new Error("no settings")}catch(i){ve=Object(k.a)({},we)}for(var e=0,t=Object.entries(we);e=0&&(u.matchTags=!0),r.a.createElement(Ne.Controlled,{value:c,options:u,onBeforeChange:function(t,n,a){e.setState({value:a})},onChange:function(e,t,n){o(n)},editorDidMount:this.registerEditor})}}],[{key:"getDerivedStateFromProps",value:function(e,t){return t.hackKey!==e.hackKey?{hackKey:e.hackKey,value:e.value}:null}}]),n}(r.a.Component),_e=n(87);function Te(e,t){var n,a=Object(l.a)(t);try{var r=function(){var t=n.value,a=e.findIndex((function(e){return e.name.toLowerCase().endsWith(t.toLowerCase())}));if(a>=0)return{v:a}};for(a.s();!(n=a.n()).done;){var i=r();if("object"===typeof i)return i.v}}catch(o){a.e(o)}finally{a.f()}return-1}function Ae(e,t){var n=e.findIndex((function(e){return e.name.toLowerCase()===t.toLowerCase}));if(n>=0)return n;for(var a=arguments.length,r=new Array(a>2?a-2:0),i=2;i1?t-1:0),a=1;a=0?e[r]:""}var Pe=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:",";return Object.entries(e).map((function(e){var t=Object(S.a)(e,2),n=t[0],a=t[1];return"".concat(n,"=").concat(a)})).join(t)};var Re=window.matchMedia?window.matchMedia("(prefers-color-scheme: dark)"):{},Ge=function(){};function Ke(e){return Fe.apply(this,arguments)}function Fe(){return(Fe=Object(f.a)(g.a.mark((function e(t){var n;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,fetch(t);case 2:return n=e.sent,e.next=5,n.text();case 5:return e.abrupt("return",e.sent);case 6:case"end":return e.stop()}}),e)})))).apply(this,arguments)}var Je,Ve=(Je=function(){var e=Object(f.a)(g.a.mark((function e(t){var n;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=3,Ke("/types/webgpu/dist/index.d.ts");case 3:n=e.sent,t.languages.typescript.javascriptDefaults.addExtraLib(n,"");case 5:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),function(){var e=!1;e||(e=!0,Je.apply(void 0,arguments))});var We=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(e){var a;Object(s.a)(this,n),(a=t.call(this,e)).handleEditorDidMount=function(e,t){a.editor=e,Ve(t),e.getModel().updateOptions({tabSize:2});var n=a.props.registerAPI;n&&n({goToLine:function(e,t){a.editor.focus(),a.editor.setPosition({lineNumber:e,column:t}),a.editor.revealPosition({lineNumber:e,column:t})},refresh:function(e){},focus:function(e){a.editor.focus()}})},a.registerEditor=function(e){a.editor=e};var r=e.value,i=e.hackKey;return a.state={value:r,hackKey:i},a}return Object(c.a)(n,[{key:"render",value:function(){var e=this.props,t=e.options,n=void 0===t?{}:t,a=e.onValueChange,i=void 0===a?Ge:a,o=e.ui,s=this.state.value,c=Re.matches,l=function(e){var t=((null===e||void 0===e?void 0:e.mode)||"javascript").split("/").pop();return"gfm"===t?"markdown":t}(n.editor).split("/").pop();return r.a.createElement(_e.a,{theme:c?"vs-dark":"light",language:l,value:s,onChange:i,onMount:this.handleEditorDidMount,options:{minimap:{enabled:!1},lineNumbers:o.lineNumbers?"on":"off",glyphMargin:!1,folding:!1,insertSpaces:!o.tabs,renderWhitespace:o.showWhitespace}})}}],[{key:"getDerivedStateFromProps",value:function(e,t){return t.hackKey!==e.hackKey?{hackKey:e.hackKey,value:e.value}:null}}]),n}(r.a.Component),He=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(){var e;Object(s.a)(this,n);for(var a=arguments.length,r=new Array(a),i=0;i=0&&(t[0]=e[0]),a.state.showResult&&(t[1]=e[1]),a.state.showLow&&(t[2]=e[2]),a.setState({sizes:e,lastSizes:t}),ke("layoutTabbed",a.state)},a.handleGoToLine=function(e){a.files.forEach((function(t,n){if(t.goToLine(e)){var r=a.props.data.files.findIndex((function(t){return t.name===e.section}));r!==a.state.currentNdx&&a.handleOnChange(r)}}))},a.handleOnChange=function(e){var t=a.state.currentNdx===e?-1:e;a.setState({currentNdx:t,sizes:it(a.state.sizes,a.state.lastSizes,0,t>=0)}),ke("layoutTabbed",a.state)},a.toggleShowLog=function(){var e=!a.state.showLog;a.setState({showLog:e,sizes:it(a.state.sizes,a.state.lastSizes,2,e)}),ke("layoutTabbed",a.state)},a.toggleShowResult=function(){var e=!a.state.showResult;a.setState({showResult:e,sizes:it(a.state.sizes,a.state.lastSizes,1,e)}),ke("layoutTabbed",a.state)};var r=Se().layoutTabbed;return a.state=rt(r)?r:{showResult:!0,showLog:!0,currentNdx:2,sizes:[.45,.45,.1],lastSizes:[.45,.45,.1]},a.files=new Map,a.fileToKeyMap=new Map,a}return Object(c.a)(n,[{key:"getFileKey",value:function(e){var t=this.fileToKeyMap.get(e);return t||(t="".concat(Date.now(),"-").concat(Math.random()),this.fileToKeyMap.set(e,t)),t}},{key:"componentDidUpdate",value:function(){this.previousNdx!==this.state.currentNdx&&(this.previousNdx=this.state.currentNdx,this.files.forEach((function(e){e.refresh(),e.focus()})))}},{key:"render",value:function(){var e=this,t=this.props,n=t.hackKey,a=t.data,i=t.registerRunnerAPI,o=this.state,s=o.showResult,c=o.showLog,l=o.sizes,u=o.currentNdx,d=Object(k.a)({},!s&&{display:"none"}),h=Object(k.a)({},!c&&{display:"none"});return r.a.createElement("div",{className:"layout-tabbed"},r.a.createElement("div",{className:"layout-tabbed-top"},r.a.createElement("div",{className:"tab-tabs"},a.files.map((function(t,n){var a="ca".concat(e.getFileKey(t));return r.a.createElement(r.a.Fragment,{key:a},r.a.createElement("input",{type:"radio",name:"tabbed-files",id:a,checked:n===u,onClick:function(t){return e.handleOnChange(n)},onChange:function(e){return e}}),r.a.createElement("label",{htmlFor:a},t.name))})),r.a.createElement("input",{type:"checkbox",checked:s,onChange:this.toggleShowResult,id:"result"}),r.a.createElement("label",{htmlFor:"result"},"result"),r.a.createElement("input",{type:"checkbox",checked:c,onChange:this.toggleShowLog,id:"log"}),r.a.createElement("label",{htmlFor:"log"},"log"))),r.a.createElement(A.a,{direction:"vertical",minSize:0,sizes:l,onSetSizes:this.setSizes},r.a.createElement("div",{className:"tab-content"},a.files.map((function(t,a){var i="ca".concat(e.getFileKey(t));return r.a.createElement("div",{key:i,style:Object(k.a)({},a!==u&&{display:"none"})},r.a.createElement(Be,{hackKey:n,desc:"filename",title:t.name,value:t.content,onTitleChange:function(e){return pe(a,e)},onValueChange:function(e){return ge(a,e)},register:e.handleRegister,unregister:e.handleUnregister}))}))),r.a.createElement("div",{className:"layout-tabbed-result",style:d},r.a.createElement(X,{registerAPI:i})),r.a.createElement("div",{className:"layout-tabbed-log",style:h},r.a.createElement(V,{onGoToLine:this.handleGoToLine}))))}}]),n}(r.a.Component)],st=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(){var e;Object(s.a)(this,n);for(var a=arguments.length,r=new Array(a),i=0;it.name.toLowerCase()?1:0};case"date":return function(e,t){return e.datet.date?1:0};case"public":return function(e,t){var n=e.public?1:0,a=t.public?1:0;return Math.sign(n-a)};case"check":return function(e,n){var a=t.has(e.id)?1:0,r=t.has(n.id)?1:0;return Math.sign(a-r)};default:throw new Error("unknown sortKey")}}(n,t);return Object.entries(e).map((function(e){var t=Object(S.a)(e,2),n=t[0],a=t[1];return{id:n,name:a.name,date:a.date,public:a.public}})).sort((function(e,t){return i(t,e)*r}))}function yt(e){var t=e.sortDir,n=e.selected,a=e.update;return r.a.createElement(r.a.Fragment,null,r.a.createElement("span",{onClick:function(){return a(n?"up"===t?"down":"up":t)},className:n?"current-sort-key":""},"up"===t?"\u25b2":"\u25bc"))}function Et(e){for(var t,n=0,a=Object.values(e);nt)&&(t=i)}return t}ne("gists",mt()),d.subscribe("gists",(function(){re("gists",mt())}));var wt=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(e){var a;Object(s.a)(this,n),(a=t.call(this,e)).handleNewGists=function(e){a.setState({gists:e})},a.toggleCheck=function(e){var t=new Set(a.state.checks);t.has(e)?t.delete(e):t.add(e),a.setState({checks:t})},a.onUserStatusChange=function(){a.forceUpdate(),a.context.userManager.getUserData()&&a.loadGists()},a.updateSort=function(e,t){console.log("update:",e,t),a.setState({sortDir:t,sortKey:e})},a.handleKeyDown=function(e){a.setState({shift:e.shiftKey})},a.handleKeyUp=function(e){a.setState({shift:e.shiftKey})},a.loadGists=Object(f.a)(g.a.mark((function e(){var t,n,r,i,o,s;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return t=a.context,n=t.addError,r=t.github,a.setState({loading:!0}),e.prev=2,i=a.state.shift?{}:a.state.gists,o=Et(i),e.next=7,r.getUserGists(o);case 7:s=e.sent,vt(s.reduce((function(e,t){return e[t.id]={name:t.description,date:t.updated_at,public:t.public},e}),Object(k.a)({},i))),e.next=15;break;case 12:e.prev=12,e.t0=e.catch(2),n("could not load gists: ".concat(e.t0));case 15:a.setState({loading:!1});case 16:case"end":return e.stop()}}),e,null,[[2,12]])}))),a.deleteSelected=Object(f.a)(g.a.mark((function e(){var t,n,r,i,o,s,c,l,u,d;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:t=a.state,n=t.checks,r=t.gists,i=[],n.forEach((function(e,t){r[e]&&i.push(e)})),o=a.context,s=o.addError,c=o.github,a.setState({loading:!0}),l=0,u=i;case 6:if(!(l=0&&r.a.createElement(r.a.Fragment,null,r.a.createElement("p",null,r.a.createElement(E,{className:"foobar",placeholder:"search:",value:s,onChange:function(t){e.setState({filter:t})}})),r.a.createElement("div",{className:"gists"},r.a.createElement("table",null,r.a.createElement("thead",null,r.a.createElement("tr",null,r.a.createElement("th",null,r.a.createElement(yt,{selected:"check"===c,sortDir:l,update:function(t){return e.updateSort("check",t)}})),r.a.createElement("th",null,r.a.createElement(yt,{selected:"name"===c,sortDir:l,update:function(t){return e.updateSort("name",t)}})),r.a.createElement("th",null,r.a.createElement(yt,{selected:"date"===c,sortDir:l,update:function(t){return e.updateSort("date",t)}})),r.a.createElement("th",null,r.a.createElement(yt,{selected:"public"===c,sortDir:l,update:function(t){return e.updateSort("public",t)}})))),r.a.createElement("tbody",null,h.filter(function(e){return e=e.trim().toLowerCase(),function(t){var n=t.name,a=t.date;return""===e||n.toLowerCase().includes(e)||a.substring(0,10).includes(e)}}(s)).map((function(t,n){return r.a.createElement("tr",{key:"g".concat(n)},r.a.createElement("td",null,r.a.createElement("input",{type:"checkbox",id:"gc".concat(n),checked:i.has(t.id),onChange:function(){return e.toggleCheck(t.id)}}),r.a.createElement("label",{htmlFor:"gc".concat(n)})),r.a.createElement("td",null,r.a.createElement("a",{onClick:e.clearBackup,href:"".concat(window.location.origin,"?src=").concat(encodeURIComponent(t.id))},t.name)),r.a.createElement("td",null,t.date.substring(0,10)),r.a.createElement("td",null,t.public?"":"\ud83d\udd12"))}))))),r.a.createElement("div",null,r.a.createElement("button",{onClick:this.deleteSelected},"Delete Selected Gists"))))}},{key:"render",value:function(){return this.context.userManager.getUserData()?this.renderLoad():this.renderLogin()}}]),n}(r.a.Component);function kt(e){var t=Object(a.useState)(""),n=Object(S.a)(t,2),i=n[0],o=n[1],s=Object(a.useContext)(F).addError;return r.a.createElement("div",null,r.a.createElement("div",{style:{height:"100px"}},r.a.createElement(He,{value:i,onValueChange:o})),r.a.createElement("p",null,r.a.createElement("button",{onClick:function(){var t=e.onLoad;try{fe(JSON.parse(i)),t()}catch(n){s("bad json: ".concat(n))}}},"Load JSON")))}function St(e){var t=Object(a.useState)(""),n=Object(S.a)(t,2),i=n[0],o=n[1],s=Object(a.useContext)(F).addError;function c(){return(c=Object(f.a)(g.a.mark((function t(){var n,a;return g.a.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.onLoad,t.prev=1,t.next=4,fetch(i);case 4:return a=t.sent,t.next=7,a.json();case 7:fe(t.sent),n(),t.next=15;break;case 12:t.prev=12,t.t0=t.catch(1),s("could not load url: ".concat(t.t0));case 15:case"end":return t.stop()}}),t,null,[[1,12]])})))).apply(this,arguments)}return r.a.createElement("div",null,r.a.createElement(E,{value:i,onChange:o,placeholder:"url-to-json"}),r.a.createElement("p",null,r.a.createElement("button",{onClick:function(){return c.apply(this,arguments)}},"Load URL")))}function jt(e){var t=e.heading,n=e.children;return r.a.createElement("div",{className:"section"},r.a.createElement("div",{className:"section-heading"},t),r.a.createElement("div",{className:"section-content"},n))}function Ot(e){var t=e.data,n=e.onLoad,a=e.onClose;return r.a.createElement(L,{title:"Load",className:"fixed-size-dialog",onClose:a},r.a.createElement(jt,{heading:"Load Gist"},r.a.createElement(wt,{data:t,onLoad:n})),r.a.createElement(jt,{heading:"Load URL"},r.a.createElement(St,{data:t,onLoad:n})),r.a.createElement(jt,{heading:"Load JSON"},r.a.createElement(kt,{data:t,onLoad:n})))}wt.contextType=F;var xt=n(52),Ct=n(54),Mt=new TextEncoder,zt=new TextDecoder,Nt=function(e){return e.startsWith("cb64,")||e.startsWith("b64,")};function Lt(e){var t=e.startsWith("cb64,"),n=t?"cb64,":"b64,",a=e.substr(n.length).replace(/-/g,"+").replace(/_/g,"/"),r=new Uint8Array(Object(xt.a)(a)),i=t?Object(Ct.b)(r):r,o=zt.decode(i);return JSON.parse(o)}var It=/^[a-z0-9]+$/i,Ut=function(e){return It.test(e)};function _t(e,t){return Tt.apply(this,arguments)}function Tt(){return(Tt=Object(f.a)(g.a.mark((function e(t,n){var a,r,i,o,s;return g.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!Ut(t)){e.next=9;break}return e.next=3,n.getGist(t);case 3:return a=e.sent,r=a.data,i=a.rawData,e.abrupt("return",{data:r,id:t,rawData:i});case 9:if(!Nt(t)){e.next=13;break}return e.abrupt("return",{data:Lt(t)});case 13:return e.next=15,fetch(t);case 15:return o=e.sent,e.next=18,o.json();case 18:return s=e.sent,e.abrupt("return",{data:s});case 20:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function At(e){var t=e.gistId,n=t||"f793cb359f2571409983351a6099d5d1";return r.a.createElement("div",null,r.a.createElement("div",{className:"markdown"},r.a.createElement("p",null,"You can embed a jsGist by creating an iframe pointing to"," ",r.a.createElement("code",null,"https://jsgist.org/embed.html?src=")," "," where"," ",r.a.createElement("code",null,"")," "," is one of the forms above. Either"," ",r.a.createElement("code",null,"?src=")," ","or"," ",r.a.createElement("code",null,"?src=")," ","or"," ",r.a.createElement("code",null,"?src=")," ",". You can also add "," ",r.a.createElement("code",null,"noheader=true")," "," if you don't want the header to appear. You can also just run them directly rather than put in an iframe. ",r.a.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://jsgist.org/embed.html?src=".concat(n)},"[example]")," ",r.a.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://jsgist.org/embed.html?src=".concat(n,"&noheader=true")},"[example no header]")),!!t&&r.a.createElement(r.a.Fragment,null,r.a.createElement("p",null,"For example to embed the current gist:"),r.a.createElement("pre",null,r.a.createElement("code",{style:{userSelect:"all"}},''))),r.a.createElement("p",null)))}function Dt(e){return e.split("\n").map((function(e){return" ".concat(e)})).join("\n")}var Pt=function(e){Object(b.a)(n,e);var t=Object(y.a)(n);function n(e){var a;Object(s.a)(this,n),(a=t.call(this,e)).onChange=function(e){a.setState({asModule:e})},a.exportToCodepen=function(){!function(e){var t=e.files,n=De(t,"index.html","html"),a=De(t,"index.js","js","js","javascript"),r=De(t,"index.css","css"),i={title:e.name,description:e.name,editors:"101",html:n.content,css:r.content,js:a.content},o=document.createElement("div");o.innerHTML='\n "\n ',o.querySelector("input[name=data]").value=JSON.stringify(i),document.body.appendChild(o),o.querySelector("form").submit(),document.body.removeChild(o)}(a.props.data)},a.exportToJSFiddle=function(){!function(e){var t=e.files,n=De(t,"index.html","html"),a=De(t,"index.js","js","js","javascript"),r=De(t,"index.css","css"),i=document.createElement("div");i.innerHTML='\n \n ',i.querySelector("input[name=html]").value=n.content,i.querySelector("input[name=css]").value=r.content,i.querySelector("input[name=js]").value=a.content,i.querySelector("input[name=title]").value=e.name,document.body.appendChild(i),i.querySelector("form").submit(),document.body.removeChild(i)}(a.props.data)};var r=De(e.data.files,"index.js","js","js","javascript");return a.state={asModule:/\bimport\b/.test(r.content)},a}return Object(c.a)(n,[{key:"render",value:function(){var e=this,t=this.props.data,n=this.state.asModule;return r.a.createElement("div",null,r.a.createElement("button",{onClick:this.exportToCodepen},"Codepen"),r.a.createElement("button",{onClick:this.exportToJSFiddle},"JSFiddle"),r.a.createElement("p",null,"StackOverflow Snippet (copy the code below paste into S.O.)"),r.a.createElement("div",null,r.a.createElement("div",null,r.a.createElement("input",{type:"radio",id:"export-as-module",checked:n,onChange:function(t){return e.onChange(!0)}}),r.a.createElement("label",{htmlFor:"export-as-module"},"As es6 module")),r.a.createElement("div",null,r.a.createElement("input",{type:"radio",id:"export-as-script",checked:!n,onChange:function(t){return e.onChange(!1)}}),r.a.createElement("label",{htmlFor:"export-as-script"},"As script")),r.a.createElement("p",null,'S.O. does not support es6 modules yet so picking "As Module" puts the code in a \n\n\n`\n : `\n\n\n\n\n${indent4(mainJS.content)}\n\n\n\n${indent4(mainCSS.content)}\n\n\n\n${indent4(mainHTML.content)}\n\n\n`;\n\n}\n\nfunction openInCodepen(data) {\n const files = data.files;\n const mainHTML = getOrFind(files, 'index.html', 'html');\n const mainJS = getOrFind(files, 'index.js', 'js', 'js', 'javascript');\n const mainCSS = getOrFind(files, 'index.css', 'css');\n\n const pen = {\n title : data.name,\n description : data.name,\n editors : '101',\n html : mainHTML.content,\n css : mainCSS.content,\n js : mainJS.content,\n };\n\n const elem = document.createElement('div');\n elem.innerHTML = `\n
'\n \n \n \"
\"\n `;\n elem.querySelector('input[name=data]').value = JSON.stringify(pen);\n document.body.appendChild(elem);\n elem.querySelector('form').submit();\n document.body.removeChild(elem);\n}\n\nfunction openInJSFiddle(data) {\n const files = data.files;\n const mainHTML = getOrFind(files, 'index.html', 'html');\n const mainJS = getOrFind(files, 'index.js', 'js', 'js', 'javascript');\n const mainCSS = getOrFind(files, 'index.css', 'css');\n\n const elem = document.createElement('div');\n elem.innerHTML = `\n
\n \n \n \n \n \n \n
\n `;\n elem.querySelector('input[name=html]').value = mainHTML.content;\n elem.querySelector('input[name=css]').value = mainCSS.content;\n elem.querySelector('input[name=js]').value = mainJS.content;\n elem.querySelector('input[name=title]').value = data.name;\n document.body.appendChild(elem);\n elem.querySelector('form').submit();\n document.body.removeChild(elem);\n}\n\nfunction makeHTML(data, asModule) {\n const files = data.files;\n const mainHTML = getOrFind(files, 'index.html', 'html');\n const mainJS = getOrFind(files, 'index.js', 'js', 'js', 'javascript');\n const mainCSS = getOrFind(files, 'index.css', 'css');\n const isModule = asModule !== undefined ? asModule : /\\bimport\\b/.test(mainJS.content);\n const module = isModule\n ? ' type=\"module\"'\n : '';\n return `\n\n \n \n \n ${escapeTextForHTMLContent(data.name)}\n \n \n \n${mainHTML.content}\n \n <${'script'}${module}>\n${mainJS.content}\n \n\n`;\n}\n\nexport default class Export extends React.Component {\n constructor(props) {\n super(props);\n const mainJS = getOrFind(props.data.files, 'index.js', 'js', 'js', 'javascript');\n this.state = {\n asModule: /\\bimport\\b/.test(mainJS.content), // random guess\n }\n }\n onChange = (asModule) => {\n this.setState({asModule});\n }\n exportToCodepen = () => {\n openInCodepen(this.props.data);\n }\n exportToJSFiddle = () => {\n openInJSFiddle(this.props.data);\n }\n render() {\n const {data} = this.props;\n const {asModule} = this.state;\n return (\n
\n \n \n

StackOverflow Snippet (copy the code below paste into S.O.)

\n
\n
this.onChange(true)}/>
\n
this.onChange(false)}/>
\n

S.O. does not support es6 modules yet so picking \"As Module\" puts the code in a <script> in the HTML.

\n
\n
{makeSnippet(data, asModule)}
\n

HTML (copy the code below paste into a file)

\n
\n
this.onChange(true)}/>
\n
this.onChange(false)}/>
\n
\n
{makeHTML(data, asModule)}
\n
\n );\n }\n}","import React from 'react';\nimport {classNames} from '../libs/css-utils.js';\nimport * as gists from '../libs/gists.js';\nimport ServiceContext from '../ServiceContext.js';\n\nexport default class SaveAsGist extends React.Component {\n constructor () {\n super();\n this.state = {\n saving: false,\n secret: false,\n };\n }\n componentDidMount() {\n const {userManager} = this.context;\n userManager.subscribe(this.onPatChange);\n }\n componentWillUnmount() {\n const {userManager} = this.context;\n userManager.unsubscribe(this.onPatChange);\n }\n onPatChange = () => {\n this.forceUpdate();\n }\n toggleSecret = () => {\n this.setState({secret: !this.state.secret});\n }\n saveNew = async() => {\n const {github, addError} = this.context;\n const {secret} = this.state;\n this.setState({saving: true});\n const {data, onSave, onClose} = this.props;\n let success = false;\n try {\n const {id, name, date, public: _public} = await github.createGist(data, secret);\n gists.addGist(id, name, date, _public);\n onSave(id);\n success = true;\n } catch (e) {\n addError(`could not create gist: ${e}`)\n }\n this.setState({saving: false});\n if (success) {\n onClose();\n }\n }\n saveOverExisting = async() => {\n const {github, addError} = this.context;\n this.setState({saving: true});\n const {data, gistId, onClose} = this.props;\n let success = false;\n try {\n const {id, name, date, public: _public} = await github.updateGist(gistId, data);\n gists.addGist(id, name, date, _public);\n success = true;\n } catch (e) {\n addError(`could not update gist: ${e}`)\n }\n this.setState({saving: false});\n if (success) {\n onClose();\n }\n }\n forkAndSave = async() => {\n const {github, addError} = this.context;\n const {data, gistId, onSave, onClose} = this.props;\n const {secret} = this.state;\n this.setState({saving: true});\n let success = false;\n try {\n const {id: newId} = await github.forkGist(gistId, secret);\n const {id, name, date, public: _public} = await github.updateGist(newId, data);\n gists.addGist(id, name, date, _public);\n onSave(id);\n success = true\n } catch (e) {\n addError(`could not fork and update gist: ${e}`);\n }\n this.setState({saving: false});\n if (success) {\n onClose();\n }\n }\n renderLogin() {\n const {userManager} = this.context;\n return (\n
\n Login with github\n
\n );\n }\n renderSave() {\n const {saving, secret} = this.state;\n const {userManager} = this.context;\n const userData = userManager.getUserData();\n const {gistId, gistOwnerId} = this.props;\n const canUpdate = userData && gistId && userData.id === gistOwnerId;\n const canFork = userData && gistId && userData.id !== gistOwnerId;\n return (\n
\n
\n Save to New Gist\n Update Current Gist\n Fork and Save Gist\n
\n
\n
\n \n \n
Warning:\n
    \n
  • You can not change a gist from public to secret
  • \n
  • Secret gists are still publicly accessible they're just unlisted
  • \n
\n (see docs)\n
\n
\n
\n );\n }\n render() {\n const {userManager} = this.context;\n const userData = userManager.getUserData();\n return userData ? this.renderSave() : this.renderLogin();\n }\n}\n\nSaveAsGist.contextType = ServiceContext;","import React from 'react';\n\nexport default function SaveAsJSON(props) {\n const {data} = props;\n return (\n
\n
\n Copy the text below, paste into the load ui or put somewhere on the net\n and make your own URL with {window.location.origin}?src=url-to-json.\n
\n
{JSON.stringify(data)}
\n \n
\n );\n}","import React from 'react';\n\nimport {jsonToCompressedBase64} from '../libs/compression.js';\n\nexport default function SaveAsURL(props) {\n const {data} = props;\n const src = jsonToCompressedBase64(data);\n const url = `${window.location.origin}?src=${encodeURIComponent(src)}`;\n return url.length < 8000\n ? (\n
\n
Copy / bookmark the link below
\n {url}\n
\n )\n : (\n
\n Too large to save as URL\n
\n )\n ;\n}\n","import React from 'react';\nimport Dialog from './Dialog.js';\nimport Embed from './Embed.js';\nimport Export from './Export.js';\nimport SaveAsGist from './SaveAsGist.js';\nimport SaveAsJSON from './SaveAsJSON.js';\nimport SaveAsURL from './SaveAsURL.js';\nimport Section from './Section.js';\n\nexport default function Save(props) {\n const {data, gistId, gistOwnerId, onSave, onClose} = props;\n return (\n \n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n )\n}\n","import React from 'react';\n\nimport Dialog from './Dialog.js';\nimport Section from './Section.js';\nimport ServiceContext from '../ServiceContext.js';\n\nimport verticalIcon from '../icons/vertical-layout.svg';\nimport horizontalIcon from '../icons/horizontal-layout.svg';\nimport twoByTwoIcon from '../icons/two-by-two-layout.svg';\nimport tabbedIcon from '../icons/tabbed-layout.svg';\n\nimport {classNames} from '../libs/css-utils.js';\nimport * as uiModel from '../libs/ui-model.js';\n\nfunction RadioOption(props) {\n const {children, onChange, selected} = props;\n return (\n
\n {children}\n
\n );\n}\n\nfunction Radio(props) {\n const {selected, onChange, children} = props;\n\n const newChildren = React.Children.map(children, (child) => {\n if (!React.isValidElement(child)) {\n return null;\n }\n\n const {result} = child.props;\n const isSelected = result === selected;\n\n //const id = childNdx;\n //childNdx += 1;\n return React.cloneElement(child, {\n //...child.props,\n selected: isSelected,\n onChange: () => onChange(result),\n });\n });\n\n return (\n
\n {newChildren}\n
\n );\n}\n\nfunction Checkbox(props) {\n const {id, label, checked, onChange} = props;\n const elemId = `checkbox-${id}`;\n return (\n
\n onChange(e.target.checked)}\n />\n \n
\n );\n}\n\nclass Logout extends React.Component {\n componentDidMount() {\n const {userManager} = this.context;\n userManager.subscribe(this.handleChange);\n }\n componentWillUnmount() {\n const {userManager} = this.context;\n userManager.unsubscribe(this.handleChange);\n }\n handleChange = () => {\n this.forceUpdate();\n }\n handleLogout = () => {\n const {userManager} = this.context;\n userManager.logout();\n }\n render() {\n const {userManager} = this.context;\n const userData = userManager.getUserData();\n return (!!userData &&\n
\n
Logged in as: \n {!!userData.login && }\n {!!userData.avatar_url && \"avatar\"/}\n
\n \n
\n );\n }\n}\n\nLogout.contextType = ServiceContext;\n\nexport default class Settings extends React.Component {\n //constructor(props) {\n // super(props);\n //}\n componentDidMount() {\n uiModel.subscribe(this.handleChange);\n }\n componentWillUnmount() {\n uiModel.unsubscribe(this.handleChange);\n }\n handleChange = () => {\n this.forceUpdate();\n }\n handleLayoutChange = (v) => {\n uiModel.set('layout', v);\n }\n handleEditorChange = (v) => {\n uiModel.set('editor', v);\n }\n handleLineNumbersChange = (v) => {\n uiModel.set('lineNumbers', v);\n }\n handleTabsChange = (v) => {\n uiModel.set('tabs', v);\n }\n handleShowWhitespaceChange = (v) => {\n uiModel.set('showWhitespace', v);\n }\n render() {\n const {onClose} = this.props;\n const {userManager} = this.context;\n const userData = userManager.getUserData();\n return (\n \n { !!userData && }\n
\n
\n \n \"vertical\"/\n \"horizontal\"/\n \"2x2\"\n \"tabbed\"\n \n
\n
\n
\n
\n \n
Monaco
\n
CodeMirror
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nSettings.contextType = ServiceContext;\n","import React from 'react';\n\nexport default function Toolbar(props) {\n const {\n toolbarFns,\n fullscreen,\n } = props;\n const {\n handleRun,\n handleStop,\n handleSave,\n handleNew,\n handleLoad,\n handleFullscreen,\n handleSettings,\n handleHelp,\n } = toolbarFns;\n return (\n
\n \n \n \n \n \n \n \n \n
\n );\n}","import SubscriptionManager from './SubscriptionManager.ts';\n\nconst kUserManagerKey = 'foobar'; // not important\n\nexport default class UserManager {\n constructor({\n oauthManager,\n github,\n addError,\n }) {\n this.oauthManager = oauthManager;\n this.github = github;\n this.subscriptionManager = new SubscriptionManager();\n this.addError = addError;\n oauthManager.subscribe(this._handleNewAuth);\n this._handleNewAuth();\n this.userData = undefined;\n }\n /*\n {\n \"login\": \"greggman\",\n \"id\": 234804,\n \"node_id\": \"MDQ6VXNlcjIzNDgwNA==\",\n \"avatar_url\": \"https://avatars2.githubusercontent.com/u/234804?v=4\",\n \"gravatar_id\": \"\",\n \"url\": \"https://api.github.com/users/greggman\",\n \"html_url\": \"https://github.com/greggman\",\n \"followers_url\": \"https://api.github.com/users/greggman/followers\",\n \"following_url\": \"https://api.github.com/users/greggman/following{/other_user}\",\n \"gists_url\": \"https://api.github.com/users/greggman/gists{/gist_id}\",\n \"starred_url\": \"https://api.github.com/users/greggman/starred{/owner}{/repo}\",\n \"subscriptions_url\": \"https://api.github.com/users/greggman/subscriptions\",\n \"organizations_url\": \"https://api.github.com/users/greggman/orgs\",\n \"repos_url\": \"https://api.github.com/users/greggman/repos\",\n \"events_url\": \"https://api.github.com/users/greggman/events{/privacy}\",\n \"received_events_url\": \"https://api.github.com/users/greggman/received_events\",\n \"type\": \"User\",\n \"site_admin\": false,\n \"name\": \"Greggman\",\n \"company\": null,\n \"blog\": \"http://games.greggman.com\",\n \"location\": \"Earth\",\n \"email\": \"github@greggman.com\",\n \"hireable\": null,\n \"bio\": \"30 years of games\\r\\n5 years of Chrome\",\n \"twitter_username\": null,\n \"public_repos\": 283,\n \"public_gists\": 80,\n \"followers\": 1037,\n \"following\": 3,\n \"created_at\": \"2010-04-01T08:48:05Z\",\n \"updated_at\": \"2020-10-24T06:05:24Z\"\n }\n */\n getUserData() {\n return this.userData;\n }\n _handleNewAuth = async() => {\n this.userData = undefined;\n const pat = this.oauthManager.pat();\n this.github.setPat(pat);\n if (pat) {\n try {\n const data = await this.github.getAuthenticatedUser();\n this.userData = data;\n } catch (e) {\n this.addError(e);\n }\n }\n this.subscriptionManager.notify(kUserManagerKey);\n }\n login = () => {\n this.oauthManager.login();\n }\n logout = () => {\n this.oauthManager.logout();\n this.github.setPat()\n }\n subscribe(fn) {\n this.subscriptionManager.subscribe(kUserManagerKey, fn);\n }\n unsubscribe(fn) {\n this.subscriptionManager.unsubscribe(kUserManagerKey, fn);\n }\n cleanup() {\n this.oauthManager.unsubscribe(this._handleNewAuth);\n }\n}\n\n","import React from 'react';\n\nimport EditLine from './EditLine.js';\n// import Footer from './Footer.js';\nimport {storageManager} from '../globals.js';\nimport GitHub from '../libs/GitHub.js';\nimport Head from './Head.js';\nimport Help from './Help.js';\nimport IDE from './IDE.js';\nimport Load from './Load.js';\nimport {isGistId, loadGistFromSrc} from '../libs/loader.js';\nimport {LogManager} from './Log.js';\nimport * as model from '../libs/model.js';\nimport Save from './Save.js';\nimport ServiceContext from '../ServiceContext.js';\nimport Settings from './Settings.js';\nimport Toolbar from './Toolbar.js';\nimport * as uiModel from '../libs/ui-model.js';\nimport UserManager from '../libs/UserManager.js';\nimport * as winMsgMgr from '../libs/WindowMessageManager';\nimport query from '../libs/start-query.js';\n\nimport './App.css';\nimport { classNames } from '../libs/css-utils.js';\n\nconst noJSX = () => [];\nconst darkMatcher = window.matchMedia('(prefers-color-scheme: dark)');\n\nclass App extends React.Component {\n constructor(props) {\n super();\n this.state = {\n path: window.location.pathname,\n dark: darkMatcher.matches,\n fullscreen: !!query.fullscreen,\n loading: false,\n dialog: noJSX,\n gistId: '',\n messages: [],\n userData: {},\n updateVersion: 0,\n };\n this.github = new GitHub();\n this.oauthManager = props.oauthManager;\n this.backupManager = props.backupManager;\n this.logManager = new LogManager();\n this.userManager = new UserManager({\n oauthManager: this.oauthManager,\n github: this.github,\n addError: this.addError,\n });\n this.toolbarFns = {\n handleRun: this.handleRun,\n handleStop: this.handleStop,\n handleSave: this.handleSave,\n handleNew: this.handleNew,\n handleLoad: this.handleLoad,\n handleSettings: this.handleSettings,\n handleFullscreen: this.handleFullscreen,\n handleHelp: this.handleHelp,\n };\n }\n componentWillUnmount() {\n uiModel.unsubscribe(this.handleUIChange);\n this.userManager.cleanup();\n }\n componentDidMount() {\n uiModel.subscribe(this.handleUIChange);\n winMsgMgr.on('newGist', null, this.handleNewGist);\n this.github.addEventListener('userdata', (e) => {\n this.setState({\n userData: e.data,\n });\n });\n model.add('path', window.location.pathname);\n model.subscribe('path', (newValue) => {\n window.history.pushState({}, '', newValue);\n this.setState({\n path: newValue,\n });\n });\n // I still am not sure how I'm supposed to handle this.\n // Putting my model in the state itself seems wrong\n // and doesn't actually help since I'd have to \n // generate an entirely new state object to change any\n // nested property.\n //\n // Storing the data outside I see no way to tell\n // components to re-render except to call forceUpdate\n // which all the documentation says \"if you call this\n // you're doing it wrong\".\n //\n // Redux is a joke. 50 lines code needed to set\n // a single field. Repeat those 50 lines for every field.\n // Things like redux-tools make it less to type those\n // 50 lines but they still execute 50 to 500 lines of code\n // just to set a single value.\n model.subscribe(model.filesVersionKey, _ => {\n this.forceUpdate();\n });\n // this is a hack because I can't figure out how to\n // update the CodeMirror areas\n model.subscribe('updateVersion', _ => {\n this.setState({updateVersion: this.state.updateVersion + 1});\n });\n\n darkMatcher.addEventListener('change', () => {\n this.setState({dark: darkMatcher.matches});\n });\n\n if (query.newGist) {\n window.history.pushState({}, '', `${window.location.origin}`);\n window.opener.postMessage({type: 'gimmeDaCodez'}, '*');\n return;\n }\n\n const backup = this.backupManager.getBackup();\n let loaded = false;\n if (backup) {\n try {\n const data = JSON.parse(backup);\n if (data.href === window.location.href) {\n model.setData(data.data);\n const url = new URL(data.href);\n const {src} = Object.fromEntries(new URLSearchParams(url.search).entries());\n if (isGistId(src)) {\n this.setState({gistId: src, gistOwnerId: data.gistOwnerId});\n }\n loaded = true;\n this.addInfo('loaded backup from local storage')\n }\n } catch (e) {\n console.log('bad backup')\n }\n this.backupManager.clearBackup();\n }\n if (!loaded) {\n if (query.src) {\n this.loadData(query.src);\n }\n }\n this.updateTitle();\n }\n componentDidUpdate() {\n this.updateTitle();\n }\n updateTitle() {\n const data = model.getData();\n document.title = data.name || 'jsGist';\n }\n async loadData(src) {\n this.setState({loading: true});\n let success = true;\n let firstTry = true;\n for (;;) {\n try {\n const {data, id, rawData} = await loadGistFromSrc(src, this.github);\n model.setData(data);\n if (id) {\n this.setState({\n gistId: src,\n gistOwnerId: rawData?.owner?.id,\n });\n }\n break;\n } catch (e) {\n if (firstTry) {\n this.userManager.logout();\n firstTry = false;\n } else {\n success = false;\n console.warn(e);\n this.addError(`could not load jsGist: src=${src} ${e}`);\n break;\n }\n }\n }\n this.setState({loading: false});\n if (success) {\n this.handleRun();\n }\n }\n handleUIChange = () => {\n this.forceUpdate();\n }\n handleNewGist = (data) => {\n let success = true;\n try {\n model.setData(data);\n this.backupManager.clearBackup();\n } catch (e) {\n success = false;\n console.warn(e);\n this.addError(`could create new jsGist: ${e}`);\n }\n if (success) {\n this.handleRun();\n }\n };\n addMsg = (msg, className) => {\n switch (className) {\n case 'error':\n console.error(msg);\n break;\n default:\n console.log(msg);\n break;\n }\n this.setState({messages: [{msg: msg.toString(), className}, ...this.state.messages]});\n setTimeout(() => {\n this.setState({messages: this.state.messages.slice(0, this.state.messages.length - 1)});\n }, 5000);\n }\n addInfo = (msg) => this.addMsg(msg, 'info');\n addError = (msg) => this.addMsg(msg, 'error');\n closeDialog = () => {\n this.setState({dialog: noJSX});\n }\n registerRunnerAPI = (api) => {\n this.runnerAPI = api;\n this.handleStop();\n }\n handleNew = async() => {\n this.backupManager.clearBackup();\n window.location.href = window.location.origin; // causes a reload\n }\n handleRun = async () => {\n this.backupManager.setBackup(JSON.stringify({\n href: window.location.href,\n data: model.getData(),\n gistOwnerId: this.state.gistOwnerId,\n }));\n this.logManager.clear();\n console.clear();\n this.runnerAPI.run(model.getData());\n }\n handleStop = async () => {\n this.runnerAPI.run(model.getBlankData(), true);\n }\n handleSave = async () => {\n this.setState({dialog: this.renderSave});\n }\n handleSettings = () => {\n this.setState({dialog: this.renderSettings});\n }\n handleFullscreen = () => {\n this.setState({fullscreen: !this.state.fullscreen});\n }\n handleHelp = () => {\n this.setState({dialog: this.renderHelp});\n }\n handleLoad = () => {\n this.setState({dialog: this.renderLoad});\n }\n handleOnLoad = async() => {\n this.setState({dialog: noJSX});\n this.handleRun();\n }\n handleOnSave = (gistId) => {\n window.history.pushState({}, '', `${window.location.origin}?src=${gistId}`);\n this.setState({\n gistId,\n gistOwnerId: this.userManager.getUserData().id,\n });\n }\n handleAbort = () => {\n this.abort();\n };\n renderHelp = () => {\n return ();\n }\n renderSettings = () => {\n return (\n \n );\n }\n renderLoad = () => {\n return (\n \n );\n }\n renderSave = () => {\n const data = model.getData();\n return (\n \n );\n }\n render() {\n const data = model.getData();\n const {\n loading,\n dialog,\n updateVersion: hackKey,\n userData,\n fullscreen,\n } = this.state;\n const editor = uiModel.get().editor;\n return (\n
\n \n
\n
\n
\n
\n model.setName(v)} />\n {!!userData.name && }\n {!!userData.avatarURL && \"avatar\"/}\n
\n
\n
\n \n \n
\n
\n {\n !loading &&\n
\n \n
\n }\n
\n {/*\n \n */}\n {dialog()}\n
\n {\n this.state.messages.map(({msg, className}, i) => (
{msg}
))\n }\n
\n
\n
\n );\n }\n}\n\nexport default App;\n","const backupKey = 'backup';\r\n\r\nexport default class BackupManager {\r\n #storageManager;\r\n\r\n constructor(storageManager) {\r\n this.#storageManager = storageManager;\r\n }\r\n getBackup() {\r\n return this.#storageManager.get(backupKey);\r\n }\r\n setBackup(data) {\r\n this.#storageManager.set(backupKey, data);\r\n }\r\n clearBackup() {\r\n this.#storageManager.delete(backupKey);\r\n }\r\n}","\nimport {clientId} from '../globals.js';\nimport {createURL} from './url.js';\nimport {createPopup} from './utils';\nimport StorageManager from './StorageManager';\nimport * as winMsgMgr from './WindowMessageManager';\n\nconst patKey = 'pat';\n\nconst getTokenURL = process.env.REACT_APP_OAUTH_HELPER_URL;\nif (!getTokenURL) {\n throw Error ('must set environment variable: OAUTH_HELPER_URL');\n}\n\nexport default class OAuthManager {\n private _popup?: Window;\n private _state?: string;\n private _storageManager: StorageManager;\n\n constructor(storageManager: StorageManager) {\n this._popup = undefined;\n this._state = undefined; // last state sent to auth\n this._storageManager = storageManager;\n winMsgMgr.on('auth', null, (data: any) => {\n this._closePopup();\n if (data.state === this._state) {\n this.requestToken(data);\n }\n });\n }\n // TODO: rename this and decide if Github should be connected\n pat() {\n return this._storageManager.get(patKey);\n }\n subscribe(fn: () => void) {\n this._storageManager.subscribe(patKey, fn);\n }\n unsubscribe(fn: () => void) {\n this._storageManager.unsubscribe(patKey, fn);\n }\n _closePopup() {\n if (this._popup) {\n this._popup.close();\n this._popup = undefined;\n }\n }\n requestToken = async (auth: any) => {\n try {\n const params = {\n client: clientId,\n code: auth.code,\n };\n const url = createURL(getTokenURL, params);\n const req = await fetch(url);\n const data = await req.json();\n if (!data.access_token) {\n throw new Error(JSON.stringify(data));\n }\n this._storageManager.set(patKey, data.access_token);\n } catch (e) {\n console.error(e);\n }\n }\n logout = () => {\n this._storageManager.delete(patKey);\n }\n login = () => {\n this._closePopup();\n this._state = `${Date.now()}-${Math.random()}`; // does this need to special? Seems like no\n const url = createURL('https://github.com/login/oauth/authorize', {\n client_id: clientId,\n scope: 'gist',\n state: this._state,\n });\n this._popup = createPopup(url);\n }\n}","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.0/8 are considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl, {\n headers: { 'Service-Worker': 'script' },\n })\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready\n .then(registration => {\n registration.unregister();\n })\n .catch(error => {\n console.error(error.message);\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport {storageManager} from './globals.js';\nimport './index.css';\nimport './scrollbars.js';\nimport App from './components/App';\nimport BackupManager from './components/BackupManager.js';\nimport OAuthManager from './libs/OAuthManager';\nimport * as serviceWorker from './serviceWorker';\n\nconst oauthManager = new OAuthManager(storageManager);\nconst backupManager = new BackupManager(storageManager);\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n);\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n","module.exports = __webpack_public_path__ + \"static/media/vertical-layout.f248a432.svg\";","module.exports = __webpack_public_path__ + \"static/media/horizontal-layout.e3f3298b.svg\";","module.exports = __webpack_public_path__ + \"static/media/two-by-two-layout.23605ce8.svg\";","module.exports = __webpack_public_path__ + \"static/media/tabbed-layout.8a8b9bc8.svg\";"],"sourceRoot":""} \ No newline at end of file diff --git a/types/webgpu/dist/index.d.ts b/types/webgpu/dist/index.d.ts new file mode 100644 index 0000000..ae80268 --- /dev/null +++ b/types/webgpu/dist/index.d.ts @@ -0,0 +1,3234 @@ +// ********************************************************************************************* +// This file is manually-edited by diffing against an autogenerated file. See README.md. +// ********************************************************************************************* + +// ********************************************************************************************* +// Manually-written +// ********************************************************************************************* + +interface HTMLCanvasElement { + getContext( + contextId: + | "webgpu" + ): GPUCanvasContext | null; +} + +interface OffscreenCanvas { + getContext( + contextId: + | "webgpu" + ): GPUCanvasContext | null; +} + +// Defined as an empty interface here to prevent errors when using these types in a worker. +interface HTMLVideoElement {} + +type GPUOrigin2DStrict = + + | Iterable + | GPUOrigin2DDictStrict; + +interface GPUOrigin2DDictStrict + extends GPUOrigin2DDict { + /** @deprecated Does not exist for GPUOrigin2D. */ + z?: undefined; +} + +type GPUExtent3DStrict = + + | Iterable + | GPUExtent3DDictStrict; + +// GPUExtent3DDictStrict is defined to help developers catch a common class of errors. +// This interface defines depth as an undefined, which will cause a type check failure if someone +// attempts to set depth rather than depthOrArrayLayers on a GPUExtent3D (an easy mistake to make.) +interface GPUExtent3DDictStrict + extends GPUExtent3DDict { + /** @deprecated The correct name is `depthOrArrayLayers`. */ + depth?: undefined; +} + +// ********************************************************************************************* +// Semi-auto-generated (by manual diff with autogenerated types) +// ********************************************************************************************* + +type GPUBindingResource = + + | GPUSampler + | GPUTextureView + | GPUBufferBinding + | GPUExternalTexture; +type GPUBufferDynamicOffset = + number; +type GPUBufferUsageFlags = + number; +type GPUColor = + + | Iterable + | GPUColorDict; +type GPUColorWriteFlags = + number; +type GPUDepthBias = + number; +type GPUExtent3D = + + | Iterable + | GPUExtent3DDict; +type GPUFlagsConstant = + number; +type GPUImageCopyExternalImageSource = + + | ImageBitmap + | HTMLVideoElement + | VideoFrame + | HTMLCanvasElement + | OffscreenCanvas; +type GPUIndex32 = + number; +type GPUIntegerCoordinate = + number; +type GPUIntegerCoordinateOut = + number; +type GPUMapModeFlags = + number; +type GPUOrigin2D = + + | Iterable + | GPUOrigin2DDict; +type GPUOrigin3D = + + | Iterable + | GPUOrigin3DDict; +type GPUPipelineConstantValue = + number; +type GPUSampleMask = + number; +type GPUShaderStageFlags = + number; +type GPUSignedOffset32 = + number; +type GPUSize32 = + number; +type GPUSize32Out = + number; +type GPUSize64 = + number; +type GPUSize64Out = + number; +type GPUStencilValue = + number; +type GPUTextureUsageFlags = + number; +type GPUAddressMode = + + | "clamp-to-edge" + | "repeat" + | "mirror-repeat"; +type GPUAutoLayoutMode = + "auto"; +type GPUBlendFactor = + + | "zero" + | "one" + | "src" + | "one-minus-src" + | "src-alpha" + | "one-minus-src-alpha" + | "dst" + | "one-minus-dst" + | "dst-alpha" + | "one-minus-dst-alpha" + | "src-alpha-saturated" + | "constant" + | "one-minus-constant"; +type GPUBlendOperation = + + | "add" + | "subtract" + | "reverse-subtract" + | "min" + | "max"; +type GPUBufferBindingType = + + | "uniform" + | "storage" + | "read-only-storage"; +type GPUBufferMapState = + + | "unmapped" + | "pending" + | "mapped"; +type GPUCanvasAlphaMode = + + | "opaque" + | "premultiplied"; +type GPUCompareFunction = + + | "never" + | "less" + | "equal" + | "less-equal" + | "greater" + | "not-equal" + | "greater-equal" + | "always"; +type GPUCompilationMessageType = + + | "error" + | "warning" + | "info"; +type GPUCullMode = + + | "none" + | "front" + | "back"; +type GPUDeviceLostReason = + + | "unknown" + | "destroyed"; +type GPUErrorFilter = + + | "validation" + | "out-of-memory" + | "internal"; +type GPUFeatureName = + + | "depth-clip-control" + | "depth32float-stencil8" + | "texture-compression-bc" + | "texture-compression-etc2" + | "texture-compression-astc" + | "timestamp-query" + | "indirect-first-instance" + | "shader-f16" + | "rg11b10ufloat-renderable" + | "bgra8unorm-storage" + | "float32-filterable"; +type GPUFilterMode = + + | "nearest" + | "linear"; +type GPUFrontFace = + + | "ccw" + | "cw"; +type GPUIndexFormat = + + | "uint16" + | "uint32"; +type GPULoadOp = + + | "load" + | "clear"; +type GPUMipmapFilterMode = + + | "nearest" + | "linear"; +type GPUPipelineErrorReason = + + | "validation" + | "internal"; +type GPUPowerPreference = + + | "low-power" + | "high-performance"; +type GPUPrimitiveTopology = + + | "point-list" + | "line-list" + | "line-strip" + | "triangle-list" + | "triangle-strip"; +type GPUQueryType = + + | "occlusion" + | "timestamp"; +type GPUSamplerBindingType = + + | "filtering" + | "non-filtering" + | "comparison"; +type GPUStencilOperation = + + | "keep" + | "zero" + | "replace" + | "invert" + | "increment-clamp" + | "decrement-clamp" + | "increment-wrap" + | "decrement-wrap"; +type GPUStorageTextureAccess = + "write-only"; +type GPUStoreOp = + + | "store" + | "discard"; +type GPUTextureAspect = + + | "all" + | "stencil-only" + | "depth-only"; +type GPUTextureDimension = + + | "1d" + | "2d" + | "3d"; +type GPUTextureFormat = + + | "r8unorm" + | "r8snorm" + | "r8uint" + | "r8sint" + | "r16uint" + | "r16sint" + | "r16float" + | "rg8unorm" + | "rg8snorm" + | "rg8uint" + | "rg8sint" + | "r32uint" + | "r32sint" + | "r32float" + | "rg16uint" + | "rg16sint" + | "rg16float" + | "rgba8unorm" + | "rgba8unorm-srgb" + | "rgba8snorm" + | "rgba8uint" + | "rgba8sint" + | "bgra8unorm" + | "bgra8unorm-srgb" + | "rgb9e5ufloat" + | "rgb10a2unorm" + | "rg11b10ufloat" + | "rg32uint" + | "rg32sint" + | "rg32float" + | "rgba16uint" + | "rgba16sint" + | "rgba16float" + | "rgba32uint" + | "rgba32sint" + | "rgba32float" + | "stencil8" + | "depth16unorm" + | "depth24plus" + | "depth24plus-stencil8" + | "depth32float" + | "depth32float-stencil8" + | "bc1-rgba-unorm" + | "bc1-rgba-unorm-srgb" + | "bc2-rgba-unorm" + | "bc2-rgba-unorm-srgb" + | "bc3-rgba-unorm" + | "bc3-rgba-unorm-srgb" + | "bc4-r-unorm" + | "bc4-r-snorm" + | "bc5-rg-unorm" + | "bc5-rg-snorm" + | "bc6h-rgb-ufloat" + | "bc6h-rgb-float" + | "bc7-rgba-unorm" + | "bc7-rgba-unorm-srgb" + | "etc2-rgb8unorm" + | "etc2-rgb8unorm-srgb" + | "etc2-rgb8a1unorm" + | "etc2-rgb8a1unorm-srgb" + | "etc2-rgba8unorm" + | "etc2-rgba8unorm-srgb" + | "eac-r11unorm" + | "eac-r11snorm" + | "eac-rg11unorm" + | "eac-rg11snorm" + | "astc-4x4-unorm" + | "astc-4x4-unorm-srgb" + | "astc-5x4-unorm" + | "astc-5x4-unorm-srgb" + | "astc-5x5-unorm" + | "astc-5x5-unorm-srgb" + | "astc-6x5-unorm" + | "astc-6x5-unorm-srgb" + | "astc-6x6-unorm" + | "astc-6x6-unorm-srgb" + | "astc-8x5-unorm" + | "astc-8x5-unorm-srgb" + | "astc-8x6-unorm" + | "astc-8x6-unorm-srgb" + | "astc-8x8-unorm" + | "astc-8x8-unorm-srgb" + | "astc-10x5-unorm" + | "astc-10x5-unorm-srgb" + | "astc-10x6-unorm" + | "astc-10x6-unorm-srgb" + | "astc-10x8-unorm" + | "astc-10x8-unorm-srgb" + | "astc-10x10-unorm" + | "astc-10x10-unorm-srgb" + | "astc-12x10-unorm" + | "astc-12x10-unorm-srgb" + | "astc-12x12-unorm" + | "astc-12x12-unorm-srgb"; +type GPUTextureSampleType = + + | "float" + | "unfilterable-float" + | "depth" + | "sint" + | "uint"; +type GPUTextureViewDimension = + + | "1d" + | "2d" + | "2d-array" + | "cube" + | "cube-array" + | "3d"; +type GPUVertexFormat = + + | "uint8x2" + | "uint8x4" + | "sint8x2" + | "sint8x4" + | "unorm8x2" + | "unorm8x4" + | "snorm8x2" + | "snorm8x4" + | "uint16x2" + | "uint16x4" + | "sint16x2" + | "sint16x4" + | "unorm16x2" + | "unorm16x4" + | "snorm16x2" + | "snorm16x4" + | "float16x2" + | "float16x4" + | "float32" + | "float32x2" + | "float32x3" + | "float32x4" + | "uint32" + | "uint32x2" + | "uint32x3" + | "uint32x4" + | "sint32" + | "sint32x2" + | "sint32x3" + | "sint32x4"; +type GPUVertexStepMode = + + | "vertex" + | "instance"; + +interface GPUBindGroupDescriptor + extends GPUObjectDescriptorBase { + /** + * The {@link GPUBindGroupLayout} the entries of this bind group will conform to. + */ + layout: GPUBindGroupLayout; + /** + * A list of entries describing the resources to expose to the shader for each binding + * described by the {@link GPUBindGroupDescriptor#layout}. + */ + entries: Iterable; +} + +interface GPUBindGroupEntry { + /** + * A unique identifier for a resource binding within the {@link GPUBindGroup}, corresponding to a + * {@link GPUBindGroupLayoutEntry#binding|GPUBindGroupLayoutEntry.binding} and a @binding + * attribute in the {@link GPUShaderModule}. + */ + binding: GPUIndex32; + /** + * The resource to bind, which may be a {@link GPUSampler}, {@link GPUTextureView}, + * {@link GPUExternalTexture}, or {@link GPUBufferBinding}. + */ + resource: GPUBindingResource; +} + +interface GPUBindGroupLayoutDescriptor + extends GPUObjectDescriptorBase { + entries: Iterable; +} + +interface GPUBindGroupLayoutEntry { + /** + * A unique identifier for a resource binding within the {@link GPUBindGroupLayout}, corresponding + * to a {@link GPUBindGroupEntry#binding|GPUBindGroupEntry.binding} and a @binding + * attribute in the {@link GPUShaderModule}. + */ + binding: GPUIndex32; + /** + * A bitset of the members of {@link GPUShaderStage}. + * Each set bit indicates that a {@link GPUBindGroupLayoutEntry}'s resource + * will be accessible from the associated shader stage. + */ + visibility: GPUShaderStageFlags; + /** + * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry} + * is {@link GPUBufferBinding}. + */ + buffer?: GPUBufferBindingLayout; + /** + * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry} + * is {@link GPUSampler}. + */ + sampler?: GPUSamplerBindingLayout; + /** + * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry} + * is {@link GPUTextureView}. + */ + texture?: GPUTextureBindingLayout; + /** + * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry} + * is {@link GPUTextureView}. + */ + storageTexture?: GPUStorageTextureBindingLayout; + /** + * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry} + * is {@link GPUExternalTexture}. + */ + externalTexture?: GPUExternalTextureBindingLayout; +} + +interface GPUBlendComponent { + /** + * Defines the {@link GPUBlendOperation} used to calculate the values written to the target + * attachment components. + */ + operation?: GPUBlendOperation; + /** + * Defines the {@link GPUBlendFactor} operation to be performed on values from the fragment shader. + */ + srcFactor?: GPUBlendFactor; + /** + * Defines the {@link GPUBlendFactor} operation to be performed on values from the target attachment. + */ + dstFactor?: GPUBlendFactor; +} + +interface GPUBlendState { + /** + * Defines the blending behavior of the corresponding render target for color channels. + */ + color: GPUBlendComponent; + /** + * Defines the blending behavior of the corresponding render target for the alpha channel. + */ + alpha: GPUBlendComponent; +} + +interface GPUBufferBinding { + /** + * The {@link GPUBuffer} to bind. + */ + buffer: GPUBuffer; + /** + * The offset, in bytes, from the beginning of {@link GPUBufferBinding#buffer} to the + * beginning of the range exposed to the shader by the buffer binding. + */ + offset?: GPUSize64; + /** + * The size, in bytes, of the buffer binding. + * If not map/exist|provided, specifies the range starting at + * {@link GPUBufferBinding#offset} and ending at the end of {@link GPUBufferBinding#buffer}. + */ + size?: GPUSize64; +} + +interface GPUBufferBindingLayout { + /** + * Indicates the type required for buffers bound to this bindings. + */ + type?: GPUBufferBindingType; + /** + * Indicates whether this binding requires a dynamic offset. + */ + hasDynamicOffset?: boolean; + /** + * Indicates the minimum {@link GPUBufferBinding#size} of a buffer binding used with this bind point. + * Bindings are always validated against this size in {@link GPUDevice#createBindGroup}. + * If this *is not* `0`, pipeline creation additionally [$validating shader binding|validates$] + * that this value ≥ the minimum buffer binding size of the variable. + * If this *is* `0`, it is ignored by pipeline creation, and instead draw/dispatch commands + * [$Validate encoder bind groups|validate$] that each binding in the {@link GPUBindGroup} + * satisfies the minimum buffer binding size of the variable. + * Note: + * Similar execution-time validation is theoretically possible for other + * binding-related fields specified for early validation, like + * {@link GPUTextureBindingLayout#sampleType} and {@link GPUStorageTextureBindingLayout#format}, + * which currently can only be validated in pipeline creation. + * However, such execution-time validation could be costly or unnecessarily complex, so it is + * available only for {@link GPUBufferBindingLayout#minBindingSize} which is expected to have the + * most ergonomic impact. + */ + minBindingSize?: GPUSize64; +} + +interface GPUBufferDescriptor + extends GPUObjectDescriptorBase { + /** + * The size of the buffer in bytes. + */ + size: GPUSize64; + /** + * The allowed usages for the buffer. + */ + usage: GPUBufferUsageFlags; + /** + * If `true` creates the buffer in an already mapped state, allowing + * {@link GPUBuffer#getMappedRange} to be called immediately. It is valid to set + * {@link GPUBufferDescriptor#mappedAtCreation} to `true` even if {@link GPUBufferDescriptor#usage} + * does not contain {@link GPUBufferUsage#MAP_READ} or {@link GPUBufferUsage#MAP_WRITE}. This can be + * used to set the buffer's initial data. + * Guarantees that even if the buffer creation eventually fails, it will still appear as if the + * mapped range can be written/read to until it is unmapped. + */ + mappedAtCreation?: boolean; +} + +interface GPUCanvasConfiguration { + /** + * The {@link GPUDevice} that textures returned by {@link GPUCanvasContext#getCurrentTexture} will be + * compatible with. + */ + device: GPUDevice; + /** + * The format that textures returned by {@link GPUCanvasContext#getCurrentTexture} will have. + * Must be one of the Supported context formats. + */ + format: GPUTextureFormat; + /** + * The usage that textures returned by {@link GPUCanvasContext#getCurrentTexture} will have. + * {@link GPUTextureUsage#RENDER_ATTACHMENT} is the default, but is not automatically included + * if the usage is explicitly set. Be sure to include {@link GPUTextureUsage#RENDER_ATTACHMENT} + * when setting a custom usage if you wish to use textures returned by + * {@link GPUCanvasContext#getCurrentTexture} as color targets for a render pass. + */ + usage?: GPUTextureUsageFlags; + /** + * The formats that views created from textures returned by + * {@link GPUCanvasContext#getCurrentTexture} may use. + */ + viewFormats?: Iterable; + /** + * The color space that values written into textures returned by + * {@link GPUCanvasContext#getCurrentTexture} should be displayed with. + */ + colorSpace?: PredefinedColorSpace; + /** + * Determines the effect that alpha values will have on the content of textures returned by + * {@link GPUCanvasContext#getCurrentTexture} when read, displayed, or used as an image source. + */ + alphaMode?: GPUCanvasAlphaMode; +} + +interface GPUColorDict { + /** + * The red channel value. + */ + r: number; + /** + * The green channel value. + */ + g: number; + /** + * The blue channel value. + */ + b: number; + /** + * The alpha channel value. + */ + a: number; +} + +interface GPUColorTargetState { + /** + * The {@link GPUTextureFormat} of this color target. The pipeline will only be compatible with + * {@link GPURenderPassEncoder}s which use a {@link GPUTextureView} of this format in the + * corresponding color attachment. + */ + format: GPUTextureFormat; + /** + * The blending behavior for this color target. If left undefined, disables blending for this + * color target. + */ + blend?: GPUBlendState; + /** + * Bitmask controlling which channels are are written to when drawing to this color target. + */ + writeMask?: GPUColorWriteFlags; +} + +type GPUCommandBufferDescriptor = + GPUObjectDescriptorBase; +type GPUCommandEncoderDescriptor = + GPUObjectDescriptorBase; + +interface GPUComputePassDescriptor + extends GPUObjectDescriptorBase { + /** + * Defines which timestamp values will be written for this pass, and where to write them to. + */ + timestampWrites?: GPUComputePassTimestampWrites; +} + +interface GPUComputePassTimestampWrites { + /** + * The {@link GPUQuerySet}, of type {@link GPUQueryType#"timestamp"}, that the query results will be + * written to. + */ + querySet: GPUQuerySet; + /** + * If defined, indicates the query index in {@link GPURenderPassTimestampWrites#querySet} into + * which the timestamp at the beginning of the compute pass will be written. + */ + beginningOfPassWriteIndex?: GPUSize32; + /** + * If defined, indicates the query index in {@link GPURenderPassTimestampWrites#querySet} into + * which the timestamp at the end of the compute pass will be written. + */ + endOfPassWriteIndex?: GPUSize32; +} + +interface GPUComputePipelineDescriptor + extends GPUPipelineDescriptorBase { + /** + * Describes the compute shader entry point of the pipeline. + */ + compute: GPUProgrammableStage; +} + +interface GPUDepthStencilState { + /** + * The {@link GPUTextureViewDescriptor#format} of {@link GPURenderPassDescriptor#depthStencilAttachment} + * this {@link GPURenderPipeline} will be compatible with. + */ + format: GPUTextureFormat; + /** + * Indicates if this {@link GPURenderPipeline} can modify + * {@link GPURenderPassDescriptor#depthStencilAttachment} depth values. + */ + depthWriteEnabled: boolean; + /** + * The comparison operation used to test fragment depths against + * {@link GPURenderPassDescriptor#depthStencilAttachment} depth values. + */ + depthCompare: GPUCompareFunction; + /** + * Defines how stencil comparisons and operations are performed for front-facing primitives. + */ + stencilFront?: GPUStencilFaceState; + /** + * Defines how stencil comparisons and operations are performed for back-facing primitives. + */ + stencilBack?: GPUStencilFaceState; + /** + * Bitmask controlling which {@link GPURenderPassDescriptor#depthStencilAttachment} stencil value + * bits are read when performing stencil comparison tests. + */ + stencilReadMask?: GPUStencilValue; + /** + * Bitmask controlling which {@link GPURenderPassDescriptor#depthStencilAttachment} stencil value + * bits are written to when performing stencil operations. + */ + stencilWriteMask?: GPUStencilValue; + /** + * Constant depth bias added to each fragment. See [$biased fragment depth$] for details. + */ + depthBias?: GPUDepthBias; + /** + * Depth bias that scales with the fragment’s slope. See [$biased fragment depth$] for details. + */ + depthBiasSlopeScale?: number; + /** + * The maximum depth bias of a fragment. See [$biased fragment depth$] for details. + */ + depthBiasClamp?: number; +} + +interface GPUDeviceDescriptor + extends GPUObjectDescriptorBase { + /** + * Specifies the features that are required by the device request. + * The request will fail if the adapter cannot provide these features. + * Exactly the specified set of features, and no more or less, will be allowed in validation + * of API calls on the resulting device. + */ + requiredFeatures?: Iterable; + /** + * Specifies the limits that are required by the device request. + * The request will fail if the adapter cannot provide these limits. + * Each key must be the name of a member of supported limits. + * Exactly the specified limits, and no limit/better or worse, + * will be allowed in validation of API calls on the resulting device. + * + */ + requiredLimits?: Record< + string, + GPUSize64 + >; + /** + * The descriptor for the default {@link GPUQueue}. + */ + defaultQueue?: GPUQueueDescriptor; +} + +interface GPUExtent3DDict { + /** + * The width of the extent. + */ + width: GPUIntegerCoordinate; + /** + * The height of the extent. + */ + height?: GPUIntegerCoordinate; + /** + * The depth of the extent or the number of array layers it contains. + * If used with a {@link GPUTexture} with a {@link GPUTextureDimension} of {@link GPUTextureDimension#"3d"} + * defines the depth of the texture. If used with a {@link GPUTexture} with a {@link GPUTextureDimension} + * of {@link GPUTextureDimension#"2d"} defines the number of array layers in the texture. + */ + depthOrArrayLayers?: GPUIntegerCoordinate; +} + +interface GPUExternalTextureBindingLayout {} + +interface GPUExternalTextureDescriptor + extends GPUObjectDescriptorBase { + source: + | HTMLVideoElement + | VideoFrame; + colorSpace?: PredefinedColorSpace; +} + +interface GPUFragmentState + extends GPUProgrammableStage { + /** + * A list of {@link GPUColorTargetState} defining the formats and behaviors of the color targets + * this pipeline writes to. + */ + targets: Iterable; +} + +interface GPUImageCopyBuffer + extends GPUImageDataLayout { + /** + * A buffer which either contains image data to be copied or will store the image data being + * copied, depending on the method it is being passed to. + */ + buffer: GPUBuffer; +} + +interface GPUImageCopyExternalImage { + /** + * The source of the image copy. The copy source data is captured at the moment that + * {@link GPUQueue#copyExternalImageToTexture} is issued. Source size is defined by source + * type, given by this table: + * + * + * + * + * + * + * + * + * + * + * + * + *
Source type + * Width + * Height + *
{@link ImageBitmap} + * {@link ImageBitmap#width|ImageBitmap.width} + * {@link ImageBitmap#height|ImageBitmap.height} + *
{@link HTMLVideoElement} + * video/intrinsic width|intrinsic width of the frame + * video/intrinsic height|intrinsic height of the frame + *
{@link VideoFrame} + * {@link VideoFrame#codedWidth|VideoFrame.codedWidth} + * {@link VideoFrame#codedHeight|VideoFrame.codedHeight} + *
{@link HTMLCanvasElement} + * {@link HTMLCanvasElement#width|HTMLCanvasElement.width} + * {@link HTMLCanvasElement#height|HTMLCanvasElement.height} + *
{@link OffscreenCanvas} + * {@link OffscreenCanvas#width|OffscreenCanvas.width} + * {@link OffscreenCanvas#height|OffscreenCanvas.height} + *
+ */ + source: GPUImageCopyExternalImageSource; + /** + * Defines the origin of the copy - the minimum (top-left) corner of the source sub-region to copy from. + * Together with `copySize`, defines the full copy sub-region. + */ + origin?: GPUOrigin2DStrict; + /** + * Describes whether the source image is vertically flipped, or not. + * If this option is set to `true`, the copy is flipped vertically: the bottom row of the source + * region is copied into the first row of the destination region, and so on. + * The {@link GPUImageCopyExternalImage#origin} option is still relative to the top-left corner + * of the source image, increasing downward. + */ + flipY?: boolean; +} + +interface GPUImageCopyTexture { + /** + * Texture to copy to/from. + */ + texture: GPUTexture; + /** + * Mip-map level of the {@link GPUImageCopyTexture#texture} to copy to/from. + */ + mipLevel?: GPUIntegerCoordinate; + /** + * Defines the origin of the copy - the minimum corner of the texture sub-region to copy to/from. + * Together with `copySize`, defines the full copy sub-region. + */ + origin?: GPUOrigin3D; + /** + * Defines which aspects of the {@link GPUImageCopyTexture#texture} to copy to/from. + */ + aspect?: GPUTextureAspect; +} + +interface GPUImageCopyTextureTagged + extends GPUImageCopyTexture { + /** + * Describes the color space and encoding used to encode data into the destination texture. + * This [[#color-space-conversions|may result]] in values outside of the range [0, 1] + * being written to the target texture, if its format can represent them. + * Otherwise, the results are clamped to the target texture format's range. + * Note: + * If {@link GPUImageCopyTextureTagged#colorSpace} matches the source image, + * conversion may not be necessary. See [[#color-space-conversion-elision]]. + */ + colorSpace?: PredefinedColorSpace; + /** + * Describes whether the data written into the texture should have its RGB channels + * premultiplied by the alpha channel, or not. + * If this option is set to `true` and the {@link GPUImageCopyExternalImage#source} is also + * premultiplied, the source RGB values must be preserved even if they exceed their + * corresponding alpha values. + * Note: + * If {@link GPUImageCopyTextureTagged#premultipliedAlpha} matches the source image, + * conversion may not be necessary. See [[#color-space-conversion-elision]]. + */ + premultipliedAlpha?: boolean; +} + +interface GPUImageDataLayout { + /** + * The offset, in bytes, from the beginning of the image data source (such as a + * {@link GPUImageCopyBuffer#buffer|GPUImageCopyBuffer.buffer}) to the start of the image data + * within that source. + */ + offset?: GPUSize64; + /** + * The stride, in bytes, between the beginning of each block row and the subsequent block row. + * Required if there are multiple block rows (i.e. the copy height or depth is more than one block). + */ + bytesPerRow?: GPUSize32; + /** + * Number of block rows per single image of the texture. + * {@link GPUImageDataLayout#rowsPerImage} × + * {@link GPUImageDataLayout#bytesPerRow} is the stride, in bytes, between the beginning of each image of data and the subsequent image. + * Required if there are multiple images (i.e. the copy depth is more than one). + */ + rowsPerImage?: GPUSize32; +} + +interface GPUMultisampleState { + /** + * Number of samples per pixel. This {@link GPURenderPipeline} will be compatible only + * with attachment textures ({@link GPURenderPassDescriptor#colorAttachments} + * and {@link GPURenderPassDescriptor#depthStencilAttachment}) + * with matching {@link GPUTextureDescriptor#sampleCount}s. + */ + count?: GPUSize32; + /** + * Mask determining which samples are written to. + */ + mask?: GPUSampleMask; + /** + * When `true` indicates that a fragment's alpha channel should be used to generate a sample + * coverage mask. + */ + alphaToCoverageEnabled?: boolean; +} + +interface GPUObjectDescriptorBase { + /** + * The initial value of {@link GPUObjectBase#label|GPUObjectBase.label}. + */ + label?: string; +} + +interface GPUOrigin2DDict { + x?: GPUIntegerCoordinate; + y?: GPUIntegerCoordinate; +} + +interface GPUOrigin3DDict { + x?: GPUIntegerCoordinate; + y?: GPUIntegerCoordinate; + z?: GPUIntegerCoordinate; +} + +interface GPUPipelineDescriptorBase + extends GPUObjectDescriptorBase { + /** + * The {@link GPUPipelineLayout} for this pipeline, or {@link GPUAutoLayoutMode#"auto"} to generate + * the pipeline layout automatically. + * Note: If {@link GPUAutoLayoutMode#"auto"} is used the pipeline cannot share {@link GPUBindGroup}s + * with any other pipelines. + */ + layout: + | GPUPipelineLayout + | GPUAutoLayoutMode; +} + +interface GPUPipelineErrorInit { + reason: GPUPipelineErrorReason; +} + +interface GPUPipelineLayoutDescriptor + extends GPUObjectDescriptorBase { + /** + * A list of {@link GPUBindGroupLayout}s the pipeline will use. Each element corresponds to a + * @group attribute in the {@link GPUShaderModule}, with the `N`th element corresponding with + * `@group(N)`. + */ + bindGroupLayouts: Iterable; +} + +interface GPUPrimitiveState { + /** + * The type of primitive to be constructed from the vertex inputs. + */ + topology?: GPUPrimitiveTopology; + /** + * For pipelines with strip topologies + * ({@link GPUPrimitiveTopology#"line-strip"} or {@link GPUPrimitiveTopology#"triangle-strip"}), + * this determines the index buffer format and primitive restart value + * ({@link GPUIndexFormat#"uint16"}/`0xFFFF` or {@link GPUIndexFormat#"uint32"}/`0xFFFFFFFF`). + * It is not allowed on pipelines with non-strip topologies. + * Note: Some implementations require knowledge of the primitive restart value to compile + * pipeline state objects. + * To use a strip-topology pipeline with an indexed draw call + * ({@link GPURenderCommandsMixin#drawIndexed()} or {@link GPURenderCommandsMixin#drawIndexedIndirect}), + * this must be set, and it must match the index buffer format used with the draw call + * (set in {@link GPURenderCommandsMixin#setIndexBuffer}). + * See [[#primitive-assembly]] for additional details. + */ + stripIndexFormat?: GPUIndexFormat; + /** + * Defines which polygons are considered front-facing. + */ + frontFace?: GPUFrontFace; + /** + * Defines which polygon orientation will be culled, if any. + */ + cullMode?: GPUCullMode; + /** + * If true, indicates that depth clipping is disabled. + * Requires the {@link GPUFeatureName#"depth-clip-control"} feature to be enabled. + */ + unclippedDepth?: boolean; +} + +interface GPUProgrammableStage { + /** + * The {@link GPUShaderModule} containing the code that this programmable stage will execute. + */ + module: GPUShaderModule; + /** + * The name of the function in {@link GPUProgrammableStage#module} that this stage will use to + * perform its work. + */ + entryPoint: string; + /** + * Specifies the values of pipeline-overridable constants in the shader module + * {@link GPUProgrammableStage#module}. + * Each such pipeline-overridable constant is uniquely identified by a single + * pipeline-overridable constant identifier string (representing the numeric ID of the + * constant, if one is specified, and otherwise the constant's identifier name). + * WGSL names (identifiers) in source maps follow the rules defined in WGSL identifier comparison. + * The key of each key-value pair must equal the identifier string of one such constant. + * When the pipeline is executed, that constant will have the specified value. + * Values are specified as GPUPipelineConstantValue, which is a {@link double}. + * They are converted [$to WGSL type$] of the pipeline-overridable constant (`bool`/`i32`/`u32`/`f32`/`f16`). + * If conversion fails, a validation error is generated. + */ + constants?: Record< + string, + GPUPipelineConstantValue + >; +} + +interface GPUQuerySetDescriptor + extends GPUObjectDescriptorBase { + /** + * The type of queries managed by {@link GPUQuerySet}. + */ + type: GPUQueryType; + /** + * The number of queries managed by {@link GPUQuerySet}. + */ + count: GPUSize32; +} + +type GPUQueueDescriptor = + GPUObjectDescriptorBase; +type GPURenderBundleDescriptor = + GPUObjectDescriptorBase; + +interface GPURenderBundleEncoderDescriptor + extends GPURenderPassLayout { + /** + * If `true`, indicates that the render bundle does not modify the depth component of the + * {@link GPURenderPassDepthStencilAttachment} of any render pass the render bundle is executed + * in. + */ + depthReadOnly?: boolean; + /** + * If `true`, indicates that the render bundle does not modify the stencil component of the + * {@link GPURenderPassDepthStencilAttachment} of any render pass the render bundle is executed + * in. + */ + stencilReadOnly?: boolean; +} + +interface GPURenderPassColorAttachment { + /** + * A {@link GPUTextureView} describing the texture subresource that will be output to for this + * color attachment. + */ + view: GPUTextureView; + /** + * A {@link GPUTextureView} describing the texture subresource that will receive the resolved + * output for this color attachment if {@link GPURenderPassColorAttachment#view} is + * multisampled. + */ + resolveTarget?: GPUTextureView; + /** + * Indicates the value to clear {@link GPURenderPassColorAttachment#view} to prior to executing the + * render pass. If not map/exist|provided, defaults to `{r: 0, g: 0, b: 0, a: 0}`. Ignored + * if {@link GPURenderPassColorAttachment#loadOp} is not {@link GPULoadOp#"clear"}. + * The components of {@link GPURenderPassColorAttachment#clearValue} are all double values. + * They are converted [$to a texel value of texture format$] matching the render attachment. + * If conversion fails, a validation error is generated. + */ + clearValue?: GPUColor; + /** + * Indicates the load operation to perform on {@link GPURenderPassColorAttachment#view} prior to + * executing the render pass. + * Note: It is recommended to prefer clearing; see {@link GPULoadOp#"clear"} for details. + */ + loadOp: GPULoadOp; + /** + * The store operation to perform on {@link GPURenderPassColorAttachment#view} + * after executing the render pass. + */ + storeOp: GPUStoreOp; +} + +interface GPURenderPassDepthStencilAttachment { + /** + * A {@link GPUTextureView} describing the texture subresource that will be output to + * and read from for this depth/stencil attachment. + */ + view: GPUTextureView; + /** + * Indicates the value to clear {@link GPURenderPassDepthStencilAttachment#view}'s depth component + * to prior to executing the render pass. Ignored if {@link GPURenderPassDepthStencilAttachment#depthLoadOp} + * is not {@link GPULoadOp#"clear"}. Must be between 0.0 and 1.0, inclusive. + * + */ + depthClearValue?: number; + /** + * Indicates the load operation to perform on {@link GPURenderPassDepthStencilAttachment#view}'s + * depth component prior to executing the render pass. + * Note: It is recommended to prefer clearing; see {@link GPULoadOp#"clear"} for details. + */ + depthLoadOp?: GPULoadOp; + /** + * The store operation to perform on {@link GPURenderPassDepthStencilAttachment#view}'s + * depth component after executing the render pass. + */ + depthStoreOp?: GPUStoreOp; + /** + * Indicates that the depth component of {@link GPURenderPassDepthStencilAttachment#view} + * is read only. + */ + depthReadOnly?: boolean; + /** + * Indicates the value to clear {@link GPURenderPassDepthStencilAttachment#view}'s stencil component + * to prior to executing the render pass. Ignored if {@link GPURenderPassDepthStencilAttachment#stencilLoadOp} + * is not {@link GPULoadOp#"clear"}. + * The value will be converted to the type of the stencil aspect of `view` by taking the same + * number of LSBs as the number of bits in the stencil aspect of one texel block of `view`. + */ + stencilClearValue?: GPUStencilValue; + /** + * Indicates the load operation to perform on {@link GPURenderPassDepthStencilAttachment#view}'s + * stencil component prior to executing the render pass. + * Note: It is recommended to prefer clearing; see {@link GPULoadOp#"clear"} for details. + */ + stencilLoadOp?: GPULoadOp; + /** + * The store operation to perform on {@link GPURenderPassDepthStencilAttachment#view}'s + * stencil component after executing the render pass. + */ + stencilStoreOp?: GPUStoreOp; + /** + * Indicates that the stencil component of {@link GPURenderPassDepthStencilAttachment#view} + * is read only. + */ + stencilReadOnly?: boolean; +} + +interface GPURenderPassDescriptor + extends GPUObjectDescriptorBase { + /** + * The set of {@link GPURenderPassColorAttachment} values in this sequence defines which + * color attachments will be output to when executing this render pass. + * Due to compatible usage list|usage compatibility, no color attachment + * may alias another attachment or any resource used inside the render pass. + */ + colorAttachments: Iterable; + /** + * The {@link GPURenderPassDepthStencilAttachment} value that defines the depth/stencil + * attachment that will be output to and tested against when executing this render pass. + * Due to compatible usage list|usage compatibility, no writable depth/stencil attachment + * may alias another attachment or any resource used inside the render pass. + */ + depthStencilAttachment?: GPURenderPassDepthStencilAttachment; + /** + * The {@link GPUQuerySet} value defines where the occlusion query results will be stored for this pass. + */ + occlusionQuerySet?: GPUQuerySet; + /** + * Defines which timestamp values will be written for this pass, and where to write them to. + */ + timestampWrites?: GPURenderPassTimestampWrites; + /** + * The maximum number of draw calls that will be done in the render pass. Used by some + * implementations to size work injected before the render pass. Keeping the default value + * is a good default, unless it is known that more draw calls will be done. + */ + maxDrawCount?: GPUSize64; +} + +interface GPURenderPassLayout + extends GPUObjectDescriptorBase { + /** + * A list of the {@link GPUTextureFormat}s of the color attachments for this pass or bundle. + */ + colorFormats: Iterable; + /** + * The {@link GPUTextureFormat} of the depth/stencil attachment for this pass or bundle. + */ + depthStencilFormat?: GPUTextureFormat; + /** + * Number of samples per pixel in the attachments for this pass or bundle. + */ + sampleCount?: GPUSize32; +} + +interface GPURenderPassTimestampWrites { + /** + * The {@link GPUQuerySet}, of type {@link GPUQueryType#"timestamp"}, that the query results will be + * written to. + */ + querySet: GPUQuerySet; + /** + * If defined, indicates the query index in {@link GPURenderPassTimestampWrites#querySet} into + * which the timestamp at the beginning of the render pass will be written. + */ + beginningOfPassWriteIndex?: GPUSize32; + /** + * If defined, indicates the query index in {@link GPURenderPassTimestampWrites#querySet} into + * which the timestamp at the end of the render pass will be written. + */ + endOfPassWriteIndex?: GPUSize32; +} + +interface GPURenderPipelineDescriptor + extends GPUPipelineDescriptorBase { + /** + * Describes the vertex shader entry point of the pipeline and its input buffer layouts. + */ + vertex: GPUVertexState; + /** + * Describes the primitive-related properties of the pipeline. + */ + primitive?: GPUPrimitiveState; + /** + * Describes the optional depth-stencil properties, including the testing, operations, and bias. + */ + depthStencil?: GPUDepthStencilState; + /** + * Describes the multi-sampling properties of the pipeline. + */ + multisample?: GPUMultisampleState; + /** + * Describes the fragment shader entry point of the pipeline and its output colors. If + * not map/exist|provided, the [[#no-color-output]] mode is enabled. + */ + fragment?: GPUFragmentState; +} + +interface GPURequestAdapterOptions { + /** + * Optionally provides a hint indicating what class of adapter should be selected from + * the system's available adapters. + * The value of this hint may influence which adapter is chosen, but it must not + * influence whether an adapter is returned or not. + * Note: + * The primary utility of this hint is to influence which GPU is used in a multi-GPU system. + * For instance, some laptops have a low-power integrated GPU and a high-performance + * discrete GPU. This hint may also affect the power configuration of the selected GPU to + * match the requested power preference. + * Note: + * Depending on the exact hardware configuration, such as battery status and attached displays + * or removable GPUs, the user agent may select different adapters given the same power + * preference. + * Typically, given the same hardware configuration and state and + * `powerPreference`, the user agent is likely to select the same adapter. + */ + powerPreference?: GPUPowerPreference; + /** + * When set to `true` indicates that only a fallback adapter may be returned. If the user + * agent does not support a fallback adapter, will cause {@link GPU#requestAdapter} to + * resolve to `null`. + * Note: + * {@link GPU#requestAdapter} may still return a fallback adapter if + * {@link GPURequestAdapterOptions#forceFallbackAdapter} is set to `false` and either no + * other appropriate adapter is available or the user agent chooses to return a + * fallback adapter. Developers that wish to prevent their applications from running on + * fallback adapters should check the {@link GPUAdapter}.{@link GPUAdapter#isFallbackAdapter} + * attribute prior to requesting a {@link GPUDevice}. + */ + forceFallbackAdapter?: boolean; +} + +interface GPUSamplerBindingLayout { + /** + * Indicates the required type of a sampler bound to this bindings. + */ + type?: GPUSamplerBindingType; +} + +interface GPUSamplerDescriptor + extends GPUObjectDescriptorBase { + /** + */ + addressModeU?: GPUAddressMode; + /** + */ + addressModeV?: GPUAddressMode; + /** + * Specifies the {{GPUAddressMode|address modes}} for the texture width, height, and depth + * coordinates, respectively. + */ + addressModeW?: GPUAddressMode; + /** + * Specifies the sampling behavior when the sample footprint is smaller than or equal to one + * texel. + */ + magFilter?: GPUFilterMode; + /** + * Specifies the sampling behavior when the sample footprint is larger than one texel. + */ + minFilter?: GPUFilterMode; + /** + * Specifies behavior for sampling between mipmap levels. + */ + mipmapFilter?: GPUMipmapFilterMode; + /** + */ + lodMinClamp?: number; + /** + * Specifies the minimum and maximum levels of detail, respectively, used internally when + * sampling a texture. + */ + lodMaxClamp?: number; + /** + * When provided the sampler will be a comparison sampler with the specified + * {@link GPUCompareFunction}. + * Note: Comparison samplers may use filtering, but the sampling results will be + * implementation-dependent and may differ from the normal filtering rules. + */ + compare?: GPUCompareFunction; + /** + * Specifies the maximum anisotropy value clamp used by the sampler. + * Note: Most implementations support {@link GPUSamplerDescriptor#maxAnisotropy} values in range + * between 1 and 16, inclusive. The used value of {@link GPUSamplerDescriptor#maxAnisotropy} will + * be clamped to the maximum value that the platform supports. + */ + maxAnisotropy?: number; +} + +interface GPUShaderModuleCompilationHint { + /** + * A {@link GPUPipelineLayout} that the {@link GPUShaderModule} may be used with in a future + * {@link GPUDevice#createComputePipeline()} or {@link GPUDevice#createRenderPipeline} call. + * If set to {@link GPUAutoLayoutMode#"auto"} the layout will be the [$default pipeline layout$] + * for the entry point associated with this hint will be used. + */ + layout?: + | GPUPipelineLayout + | GPUAutoLayoutMode; +} + +interface GPUShaderModuleDescriptor + extends GPUObjectDescriptorBase { + /** + * The WGSL source code for the shader + * module. + */ + code: string; + /** + * If defined MAY be interpreted as a source-map-v3 format. + * Source maps are optional, but serve as a standardized way to support dev-tool + * integration such as source-language debugging [[SourceMap]]. + * WGSL names (identifiers) in source maps follow the rules defined in WGSL identifier + * comparison. + */ + sourceMap?: object; + /** + * If defined maps an entry point name from the shader to a {@link GPUShaderModuleCompilationHint}. + * No validation is performed with any of these {@link GPUShaderModuleCompilationHint}. + * Implementations should use any information present in the {@link GPUShaderModuleCompilationHint} + * to perform as much compilation as is possible within {@link GPUDevice#createShaderModule}. + * Entry point names follow the rules defined in WGSL identifier comparison. + * Note: Supplying information in {@link GPUShaderModuleDescriptor#hints} does not have any + * observable effect, other than performance. Because a single shader module can hold + * multiple entry points, and multiple pipelines can be created from a single shader + * module, it can be more performant for an implementation to do as much compilation as + * possible once in {@link GPUDevice#createShaderModule} rather than multiple times in + * the multiple calls to {@link GPUDevice#createComputePipeline} / + * {@link GPUDevice#createRenderPipeline}. + */ + hints?: Record< + string, + GPUShaderModuleCompilationHint + >; +} + +interface GPUStencilFaceState { + /** + * The {@link GPUCompareFunction} used when testing fragments against + * {@link GPURenderPassDescriptor#depthStencilAttachment} stencil values. + */ + compare?: GPUCompareFunction; + /** + * The {@link GPUStencilOperation} performed if the fragment stencil comparison test described by + * {@link GPUStencilFaceState#compare} fails. + */ + failOp?: GPUStencilOperation; + /** + * The {@link GPUStencilOperation} performed if the fragment depth comparison described by + * {@link GPUDepthStencilState#depthCompare} fails. + */ + depthFailOp?: GPUStencilOperation; + /** + * The {@link GPUStencilOperation} performed if the fragment stencil comparison test described by + * {@link GPUStencilFaceState#compare} passes. + */ + passOp?: GPUStencilOperation; +} + +interface GPUStorageTextureBindingLayout { + /** + * The access mode for this binding, indicating readability and writability. + * Note: + * There is currently only one access mode, {@link GPUStorageTextureAccess#"write-only"}, + * but this will expand in the future. + */ + access?: GPUStorageTextureAccess; + /** + * The required {@link GPUTextureViewDescriptor#format} of texture views bound to this binding. + */ + format: GPUTextureFormat; + /** + * Indicates the required {@link GPUTextureViewDescriptor#dimension} for texture views bound to + * this binding. + */ + viewDimension?: GPUTextureViewDimension; +} + +interface GPUTextureBindingLayout { + /** + * Indicates the type required for texture views bound to this binding. + */ + sampleType?: GPUTextureSampleType; + /** + * Indicates the required {@link GPUTextureViewDescriptor#dimension} for texture views bound to + * this binding. + */ + viewDimension?: GPUTextureViewDimension; + /** + * Indicates whether or not texture views bound to this binding must be multisampled. + */ + multisampled?: boolean; +} + +interface GPUTextureDescriptor + extends GPUObjectDescriptorBase { + /** + * The width, height, and depth or layer count of the texture. + */ + size: GPUExtent3DStrict; + /** + * The number of mip levels the texture will contain. + */ + mipLevelCount?: GPUIntegerCoordinate; + /** + * The sample count of the texture. A {@link GPUTextureDescriptor#sampleCount} > `1` indicates + * a multisampled texture. + */ + sampleCount?: GPUSize32; + /** + * Whether the texture is one-dimensional, an array of two-dimensional layers, or three-dimensional. + */ + dimension?: GPUTextureDimension; + /** + * The format of the texture. + */ + format: GPUTextureFormat; + /** + * The allowed usages for the texture. + */ + usage: GPUTextureUsageFlags; + /** + * Specifies what view {@link GPUTextureViewDescriptor#format} values will be allowed when calling + * {@link GPUTexture#createView} on this texture (in addition to the texture's actual + * {@link GPUTextureDescriptor#format}). + *
+ * Note: + * Adding a format to this list may have a significant performance impact, so it is best + * to avoid adding formats unnecessarily. + * The actual performance impact is highly dependent on the target system; developers must + * test various systems to find out the impact on their particular application. + * For example, on some systems any texture with a {@link GPUTextureDescriptor#format} or + * {@link GPUTextureDescriptor#viewFormats} entry including + * {@link GPUTextureFormat#"rgba8unorm-srgb"} will perform less optimally than a + * {@link GPUTextureFormat#"rgba8unorm"} texture which does not. + * Similar caveats exist for other formats and pairs of formats on other systems. + *
+ * Formats in this list must be texture view format compatible with the texture format. + *
+ * Two {@link GPUTextureFormat}s `format` and `viewFormat` are texture view format compatible if: + * - `format` equals `viewFormat`, or + * - `format` and `viewFormat` differ only in whether they are `srgb` formats (have the `-srgb` suffix). + *
+ */ + viewFormats?: Iterable; +} + +interface GPUTextureViewDescriptor + extends GPUObjectDescriptorBase { + /** + * The format of the texture view. Must be either the {@link GPUTextureDescriptor#format} of the + * texture or one of the {@link GPUTextureDescriptor#viewFormats} specified during its creation. + */ + format?: GPUTextureFormat; + /** + * The dimension to view the texture as. + */ + dimension?: GPUTextureViewDimension; + /** + * Which {@link GPUTextureAspect|aspect(s)} of the texture are accessible to the texture view. + */ + aspect?: GPUTextureAspect; + /** + * The first (most detailed) mipmap level accessible to the texture view. + */ + baseMipLevel?: GPUIntegerCoordinate; + /** + * How many mipmap levels, starting with {@link GPUTextureViewDescriptor#baseMipLevel}, are accessible to + * the texture view. + */ + mipLevelCount?: GPUIntegerCoordinate; + /** + * The index of the first array layer accessible to the texture view. + */ + baseArrayLayer?: GPUIntegerCoordinate; + /** + * How many array layers, starting with {@link GPUTextureViewDescriptor#baseArrayLayer}, are accessible + * to the texture view. + */ + arrayLayerCount?: GPUIntegerCoordinate; +} + +interface GPUUncapturedErrorEventInit + extends EventInit { + error: GPUError; +} + +interface GPUVertexAttribute { + /** + * The {@link GPUVertexFormat} of the attribute. + */ + format: GPUVertexFormat; + /** + * The offset, in bytes, from the beginning of the element to the data for the attribute. + */ + offset: GPUSize64; + /** + * The numeric location associated with this attribute, which will correspond with a + * "@location" attribute + * declared in the {@link GPURenderPipelineDescriptor#vertex}.{@link GPUProgrammableStage#module|module}. + */ + shaderLocation: GPUIndex32; +} + +interface GPUVertexBufferLayout { + /** + * The stride, in bytes, between elements of this array. + */ + arrayStride: GPUSize64; + /** + * Whether each element of this array represents per-vertex data or per-instance data + */ + stepMode?: GPUVertexStepMode; + /** + * An array defining the layout of the vertex attributes within each element. + */ + attributes: Iterable; +} + +interface GPUVertexState + extends GPUProgrammableStage { + /** + * A list of {@link GPUVertexBufferLayout}s defining the layout of the vertex attribute data in the + * vertex buffers used by this pipeline. + */ + buffers?: Iterable; +} + +interface GPUBindingCommandsMixin { + /** + * Sets the current {@link GPUBindGroup} for the given index. + * @param index - The index to set the bind group at. + * @param bindGroup - Bind group to use for subsequent render or compute commands. + * + * @param dynamicOffsets - Array containing buffer offsets in bytes for each entry in + * `bindGroup` marked as {@link GPUBindGroupLayoutEntry#buffer}.{@link GPUBufferBindingLayout#hasDynamicOffset}.--> + */ + setBindGroup( + index: GPUIndex32, + bindGroup: GPUBindGroup | null, + dynamicOffsets?: Iterable + ): undefined; + /** + * Sets the current {@link GPUBindGroup} for the given index, specifying dynamic offsets as a subset + * of a {@link Uint32Array}. + * @param index - The index to set the bind group at. + * @param bindGroup - Bind group to use for subsequent render or compute commands. + * @param dynamicOffsetsData - Array containing buffer offsets in bytes for each entry in + * `bindGroup` marked as {@link GPUBindGroupLayoutEntry#buffer}.{@link GPUBufferBindingLayout#hasDynamicOffset}. + * @param dynamicOffsetsDataStart - Offset in elements into `dynamicOffsetsData` where the + * buffer offset data begins. + * @param dynamicOffsetsDataLength - Number of buffer offsets to read from `dynamicOffsetsData`. + */ + setBindGroup( + index: GPUIndex32, + bindGroup: GPUBindGroup | null, + dynamicOffsetsData: Uint32Array, + dynamicOffsetsDataStart: GPUSize64, + dynamicOffsetsDataLength: GPUSize32 + ): undefined; +} + +interface GPUCommandsMixin {} + +interface GPUDebugCommandsMixin { + /** + * Begins a labeled debug group containing subsequent commands. + * @param groupLabel - The label for the command group. + */ + pushDebugGroup( + groupLabel: string + ): undefined; + /** + * Ends the labeled debug group most recently started by {@link GPUDebugCommandsMixin#pushDebugGroup}. + */ + popDebugGroup(): undefined; + /** + * Marks a point in a stream of commands with a label. + * @param markerLabel - The label to insert. + */ + insertDebugMarker( + markerLabel: string + ): undefined; +} + +interface GPUObjectBase { + label: string; +} + +interface GPUPipelineBase { + /** + * Gets a {@link GPUBindGroupLayout} that is compatible with the {@link GPUPipelineBase}'s + * {@link GPUBindGroupLayout} at `index`. + * @param index - Index into the pipeline layout's {@link GPUPipelineLayout#[[bindGroupLayouts]]} + * sequence. + */ + getBindGroupLayout( + index: number + ): GPUBindGroupLayout; +} + +interface GPURenderCommandsMixin { + /** + * Sets the current {@link GPURenderPipeline}. + * @param pipeline - The render pipeline to use for subsequent drawing commands. + */ + setPipeline( + pipeline: GPURenderPipeline + ): undefined; + /** + * Sets the current index buffer. + * @param buffer - Buffer containing index data to use for subsequent drawing commands. + * @param indexFormat - Format of the index data contained in `buffer`. + * @param offset - Offset in bytes into `buffer` where the index data begins. Defaults to `0`. + * @param size - Size in bytes of the index data in `buffer`. + * Defaults to the size of the buffer minus the offset. + */ + setIndexBuffer( + buffer: GPUBuffer, + indexFormat: GPUIndexFormat, + offset?: GPUSize64, + size?: GPUSize64 + ): undefined; + /** + * Sets the current vertex buffer for the given slot. + * @param slot - The vertex buffer slot to set the vertex buffer for. + * @param buffer - Buffer containing vertex data to use for subsequent drawing commands. + * @param offset - Offset in bytes into `buffer` where the vertex data begins. Defaults to `0`. + * @param size - Size in bytes of the vertex data in `buffer`. + * Defaults to the size of the buffer minus the offset. + */ + setVertexBuffer( + slot: GPUIndex32, + buffer: GPUBuffer | null, + offset?: GPUSize64, + size?: GPUSize64 + ): undefined; + /** + * Draws primitives. + * See [[#rendering-operations]] for the detailed specification. + * @param vertexCount - The number of vertices to draw. + * @param instanceCount - The number of instances to draw. + * @param firstVertex - Offset into the vertex buffers, in vertices, to begin drawing from. + * @param firstInstance - First instance to draw. + */ + draw( + vertexCount: GPUSize32, + instanceCount?: GPUSize32, + firstVertex?: GPUSize32, + firstInstance?: GPUSize32 + ): undefined; + /** + * Draws indexed primitives. + * See [[#rendering-operations]] for the detailed specification. + * @param indexCount - The number of indices to draw. + * @param instanceCount - The number of instances to draw. + * @param firstIndex - Offset into the index buffer, in indices, begin drawing from. + * @param baseVertex - Added to each index value before indexing into the vertex buffers. + * @param firstInstance - First instance to draw. + */ + drawIndexed( + indexCount: GPUSize32, + instanceCount?: GPUSize32, + firstIndex?: GPUSize32, + baseVertex?: GPUSignedOffset32, + firstInstance?: GPUSize32 + ): undefined; + /** + * Draws primitives using parameters read from a {@link GPUBuffer}. + * See [[#rendering-operations]] for the detailed specification. + * packed block of **four 32-bit unsigned integer values (16 bytes total)**, given in the same + * order as the arguments for {@link GPURenderEncoderBase#draw}. For example: + * @param indirectBuffer - Buffer containing the indirect draw parameters. + * @param indirectOffset - Offset in bytes into `indirectBuffer` where the drawing data begins. + */ + drawIndirect( + indirectBuffer: GPUBuffer, + indirectOffset: GPUSize64 + ): undefined; + /** + * Draws indexed primitives using parameters read from a {@link GPUBuffer}. + * See [[#rendering-operations]] for the detailed specification. + * tightly packed block of **five 32-bit unsigned integer values (20 bytes total)**, given in + * the same order as the arguments for {@link GPURenderEncoderBase#drawIndexed}. For example: + * @param indirectBuffer - Buffer containing the indirect drawIndexed parameters. + * @param indirectOffset - Offset in bytes into `indirectBuffer` where the drawing data begins. + */ + drawIndexedIndirect( + indirectBuffer: GPUBuffer, + indirectOffset: GPUSize64 + ): undefined; +} + +interface NavigatorGPU { + /** + * A global singleton providing top-level entry points like {@link GPU#requestAdapter}. + */ + readonly gpu: GPU; +} + +interface GPU { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPU"; + /** + * Requests an adapter from the user agent. + * The user agent chooses whether to return an adapter, and, if so, + * chooses according to the provided options. + * @param options - Criteria used to select the adapter. + */ + requestAdapter( + options?: GPURequestAdapterOptions + ): Promise; + /** + * Returns an optimal {@link GPUTextureFormat} for displaying 8-bit depth, standard dynamic range + * content on this system. Must only return {@link GPUTextureFormat#"rgba8unorm"} or + * {@link GPUTextureFormat#"bgra8unorm"}. + * The returned value can be passed as the {@link GPUCanvasConfiguration#format} to + * {@link GPUCanvasContext#configure} calls on a {@link GPUCanvasContext} to ensure the associated + * canvas is able to display its contents efficiently. + * Note: Canvases which are not displayed to the screen may or may not benefit from using this + * format. + */ + getPreferredCanvasFormat(): GPUTextureFormat; + readonly wgslLanguageFeatures: WGSLLanguageFeatures; +} + +declare var GPU: { + prototype: GPU; + new (): never; +}; + +interface GPUAdapter { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUAdapter"; + /** + * The set of values in `this`.{@link GPUAdapter#[[adapter]]}.{@link adapter#[[features]]}. + */ + readonly features: GPUSupportedFeatures; + /** + * The limits in `this`.{@link GPUAdapter#[[adapter]]}.{@link adapter#[[limits]]}. + */ + readonly limits: GPUSupportedLimits; + /** + * Returns the value of {@link GPUAdapter#[[adapter]]}.{@link adapter#[[fallback]]}. + */ + readonly isFallbackAdapter: boolean; + /** + * Requests a device from the adapter. + * This is a one-time action: if a device is returned successfully, + * the adapter becomes invalid. + * @param descriptor - Description of the {@link GPUDevice} to request. + */ + requestDevice( + descriptor?: GPUDeviceDescriptor + ): Promise; + /** + * Requests the {@link GPUAdapterInfo} for this {@link GPUAdapter}. + * Note: Adapter info values are returned with a Promise to give user agents an + * opportunity to perform potentially long-running checks when requesting unmasked values, + * such as asking for user consent before returning. If no `unmaskHints` are specified, + * however, no dialogs should be displayed to the user. + * @param unmaskHints - A list of {@link GPUAdapterInfo} attribute names for which unmasked + * values are desired if available. + */ + requestAdapterInfo( + unmaskHints?: Array + ): Promise; +} + +declare var GPUAdapter: { + prototype: GPUAdapter; + new (): never; +}; + +interface GPUAdapterInfo { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUAdapterInfo"; + /** + * The name of the vendor of the adapter, if available. Empty string otherwise. + */ + readonly vendor: string; + /** + * The name of the family or class of GPUs the adapter belongs to, if available. Empty + * string otherwise. + */ + readonly architecture: string; + /** + * A vendor-specific identifier for the adapter, if available. Empty string otherwise. + * Note: This is a value that represents the type of adapter. For example, it may be a + * [PCI device ID](https://pcisig.com/). It does not uniquely identify a given piece of + * hardware like a serial number. + */ + readonly device: string; + /** + * A human readable string describing the adapter as reported by the driver, if available. + * Empty string otherwise. + * Note: Because no formatting is applied to {@link GPUAdapterInfo#description} attempting to parse + * this value is not recommended. Applications which change their behavior based on the + * {@link GPUAdapterInfo}, such as applying workarounds for known driver issues, should rely on the + * other fields when possible. + */ + readonly description: string; +} + +declare var GPUAdapterInfo: { + prototype: GPUAdapterInfo; +}; + +interface GPUBindGroup + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUBindGroup"; +} + +declare var GPUBindGroup: { + prototype: GPUBindGroup; + new (): never; +}; + +interface GPUBindGroupLayout + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUBindGroupLayout"; +} + +declare var GPUBindGroupLayout: { + prototype: GPUBindGroupLayout; + new (): never; +}; + +interface GPUBuffer + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUBuffer"; + readonly size: GPUSize64Out; + readonly usage: GPUFlagsConstant; + readonly mapState: GPUBufferMapState; + /** + * Maps the given range of the {@link GPUBuffer} and resolves the returned {@link Promise} when the + * {@link GPUBuffer}'s content is ready to be accessed with {@link GPUBuffer#getMappedRange}. + * The resolution of the returned {@link Promise} **only** indicates that the buffer has been mapped. + * It does not guarantee the completion of any other operations visible to the content timeline, + * and in particular does not imply that any other {@link Promise} returned from + * {@link GPUQueue#onSubmittedWorkDone()} or {@link GPUBuffer#mapAsync} on other {@link GPUBuffer}s + * have resolved. + * The resolution of the {@link Promise} returned from {@link GPUQueue#onSubmittedWorkDone} + * **does** imply the completion of + * {@link GPUBuffer#mapAsync} calls made prior to that call, + * on {@link GPUBuffer}s last used exclusively on that queue. + * @param mode - Whether the buffer should be mapped for reading or writing. + * @param offset - Offset in bytes into the buffer to the start of the range to map. + * @param size - Size in bytes of the range to map. + */ + mapAsync( + mode: GPUMapModeFlags, + offset?: GPUSize64, + size?: GPUSize64 + ): Promise; + /** + * Returns an {@link ArrayBuffer} with the contents of the {@link GPUBuffer} in the given mapped range. + * @param offset - Offset in bytes into the buffer to return buffer contents from. + * @param size - Size in bytes of the {@link ArrayBuffer} to return. + */ + getMappedRange( + offset?: GPUSize64, + size?: GPUSize64 + ): ArrayBuffer; + /** + * Unmaps the mapped range of the {@link GPUBuffer} and makes it's contents available for use by the + * GPU again. + */ + unmap(): undefined; + /** + * Destroys the {@link GPUBuffer}. + * Note: It is valid to destroy a buffer multiple times. + * Note: Since no further operations can be enqueued using this buffer, implementations can + * free resource allocations, including mapped memory that was just unmapped. + */ + destroy(): undefined; +} + +declare var GPUBuffer: { + prototype: GPUBuffer; + new (): never; +}; + +interface GPUCanvasContext { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUCanvasContext"; + /** + * The canvas this context was created from. + */ + readonly canvas: + | HTMLCanvasElement + | OffscreenCanvas; + /** + * Configures the context for this canvas. + * This clears the drawing buffer to transparent black (in [$Replace the drawing buffer$]). + * @param configuration - Desired configuration for the context. + */ + configure( + configuration: GPUCanvasConfiguration + ): undefined; + /** + * Removes the context configuration. Destroys any textures produced while configured. + */ + unconfigure(): undefined; + /** + * Get the {@link GPUTexture} that will be composited to the document by the {@link GPUCanvasContext} + * next. + * Note: The same {@link GPUTexture} object will be returned by every + * call to {@link GPUCanvasContext#getCurrentTexture} until "[$Expire the current texture$]" + * runs, even if that {@link GPUTexture} is destroyed, failed validation, or failed to allocate. + */ + getCurrentTexture(): GPUTexture; +} + +declare var GPUCanvasContext: { + prototype: GPUCanvasContext; + new (): never; +}; + +interface GPUCommandBuffer + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUCommandBuffer"; +} + +declare var GPUCommandBuffer: { + prototype: GPUCommandBuffer; + new (): never; +}; + +interface GPUCommandEncoder + extends GPUObjectBase, + GPUCommandsMixin, + GPUDebugCommandsMixin { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUCommandEncoder"; + /** + * Begins encoding a render pass described by `descriptor`. + * @param descriptor - Description of the {@link GPURenderPassEncoder} to create. + */ + beginRenderPass( + descriptor: GPURenderPassDescriptor + ): GPURenderPassEncoder; + /** + * Begins encoding a compute pass described by `descriptor`. + * descriptor: + */ + beginComputePass( + descriptor?: GPUComputePassDescriptor + ): GPUComputePassEncoder; + /** + * Encode a command into the {@link GPUCommandEncoder} that copies data from a sub-region of a + * {@link GPUBuffer} to a sub-region of another {@link GPUBuffer}. + * @param source - The {@link GPUBuffer} to copy from. + * @param sourceOffset - Offset in bytes into `source` to begin copying from. + * @param destination - The {@link GPUBuffer} to copy to. + * @param destinationOffset - Offset in bytes into `destination` to place the copied data. + * @param size - Bytes to copy. + */ + copyBufferToBuffer( + source: GPUBuffer, + sourceOffset: GPUSize64, + destination: GPUBuffer, + destinationOffset: GPUSize64, + size: GPUSize64 + ): undefined; + /** + * Encode a command into the {@link GPUCommandEncoder} that copies data from a sub-region of a + * {@link GPUBuffer} to a sub-region of one or multiple continuous texture subresources. + * @param source - Combined with `copySize`, defines the region of the source buffer. + * @param destination - Combined with `copySize`, defines the region of the destination texture subresource. + * `copySize`: + */ + copyBufferToTexture( + source: GPUImageCopyBuffer, + destination: GPUImageCopyTexture, + copySize: GPUExtent3DStrict + ): undefined; + /** + * Encode a command into the {@link GPUCommandEncoder} that copies data from a sub-region of one or + * multiple continuous texture subresources to a sub-region of a {@link GPUBuffer}. + * @param source - Combined with `copySize`, defines the region of the source texture subresources. + * @param destination - Combined with `copySize`, defines the region of the destination buffer. + * `copySize`: + */ + copyTextureToBuffer( + source: GPUImageCopyTexture, + destination: GPUImageCopyBuffer, + copySize: GPUExtent3DStrict + ): undefined; + /** + * Encode a command into the {@link GPUCommandEncoder} that copies data from a sub-region of one + * or multiple contiguous texture subresources to another sub-region of one or + * multiple continuous texture subresources. + * @param source - Combined with `copySize`, defines the region of the source texture subresources. + * @param destination - Combined with `copySize`, defines the region of the destination texture subresources. + * `copySize`: + */ + copyTextureToTexture( + source: GPUImageCopyTexture, + destination: GPUImageCopyTexture, + copySize: GPUExtent3DStrict + ): undefined; + /** + * Encode a command into the {@link GPUCommandEncoder} that fills a sub-region of a + * {@link GPUBuffer} with zeros. + * @param buffer - The {@link GPUBuffer} to clear. + * @param offset - Offset in bytes into `buffer` where the sub-region to clear begins. + * @param size - Size in bytes of the sub-region to clear. Defaults to the size of the buffer minus `offset`. + */ + clearBuffer( + buffer: GPUBuffer, + offset?: GPUSize64, + size?: GPUSize64 + ): undefined; + /** + * Writes a timestamp value into a querySet when all previous commands have completed executing. + * Note: Timestamp query values are written in nanoseconds, but how the value is determined is + * implementation-defined and may not increase monotonically. See [[#timestamp]] for details. + * @param querySet - The query set that will store the timestamp values. + * @param queryIndex - The index of the query in the query set. + */ + writeTimestamp( + querySet: GPUQuerySet, + queryIndex: GPUSize32 + ): undefined; + /** + * Resolves query results from a {@link GPUQuerySet} out into a range of a {@link GPUBuffer}. + * querySet: + * firstQuery: + * queryCount: + * destination: + * destinationOffset: + */ + resolveQuerySet( + querySet: GPUQuerySet, + firstQuery: GPUSize32, + queryCount: GPUSize32, + destination: GPUBuffer, + destinationOffset: GPUSize64 + ): undefined; + /** + * Completes recording of the commands sequence and returns a corresponding {@link GPUCommandBuffer}. + * descriptor: + */ + finish( + descriptor?: GPUCommandBufferDescriptor + ): GPUCommandBuffer; +} + +declare var GPUCommandEncoder: { + prototype: GPUCommandEncoder; + new (): never; +}; + +interface GPUCompilationInfo { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUCompilationInfo"; + readonly messages: ReadonlyArray; +} + +declare var GPUCompilationInfo: { + prototype: GPUCompilationInfo; + new (): never; +}; + +interface GPUCompilationMessage { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUCompilationMessage"; + /** + * The human-readable, localizable text for this compilation message. + * Note: The {@link GPUCompilationMessage#message} should follow the best practices for language + * and direction information. This includes making use of any future standards which may + * emerge regarding the reporting of string language and direction metadata. + *

Editorial: + * At the time of this writing, no language/direction recommendation is available that provides + * compatibility and consistency with legacy APIs, but when there is, adopt it formally. + */ + readonly message: string; + /** + * The severity level of the message. + * If the {@link GPUCompilationMessage#type} is {@link GPUCompilationMessageType#"error"}, it + * corresponds to a shader-creation error. + */ + readonly type: GPUCompilationMessageType; + /** + * The line number in the shader {@link GPUShaderModuleDescriptor#code} the + * {@link GPUCompilationMessage#message} corresponds to. Value is one-based, such that a lineNum of + * `1` indicates the first line of the shader {@link GPUShaderModuleDescriptor#code}. Lines are + * delimited by line breaks. + * If the {@link GPUCompilationMessage#message} corresponds to a substring this points to + * the line on which the substring begins. Must be `0` if the {@link GPUCompilationMessage#message} + * does not correspond to any specific point in the shader {@link GPUShaderModuleDescriptor#code}. + */ + readonly lineNum: number; + /** + * The offset, in UTF-16 code units, from the beginning of line {@link GPUCompilationMessage#lineNum} + * of the shader {@link GPUShaderModuleDescriptor#code} to the point or beginning of the substring + * that the {@link GPUCompilationMessage#message} corresponds to. Value is one-based, such that a + * {@link GPUCompilationMessage#linePos} of `1` indicates the first code unit of the line. + * If {@link GPUCompilationMessage#message} corresponds to a substring this points to the + * first UTF-16 code unit of the substring. Must be `0` if the {@link GPUCompilationMessage#message} + * does not correspond to any specific point in the shader {@link GPUShaderModuleDescriptor#code}. + */ + readonly linePos: number; + /** + * The offset from the beginning of the shader {@link GPUShaderModuleDescriptor#code} in UTF-16 + * code units to the point or beginning of the substring that {@link GPUCompilationMessage#message} + * corresponds to. Must reference the same position as {@link GPUCompilationMessage#lineNum} and + * {@link GPUCompilationMessage#linePos}. Must be `0` if the {@link GPUCompilationMessage#message} + * does not correspond to any specific point in the shader {@link GPUShaderModuleDescriptor#code}. + */ + readonly offset: number; + /** + * The number of UTF-16 code units in the substring that {@link GPUCompilationMessage#message} + * corresponds to. If the message does not correspond with a substring then + * {@link GPUCompilationMessage#length} must be 0. + */ + readonly length: number; +} + +declare var GPUCompilationMessage: { + prototype: GPUCompilationMessage; + new (): never; +}; + +interface GPUComputePassEncoder + extends GPUObjectBase, + GPUCommandsMixin, + GPUDebugCommandsMixin, + GPUBindingCommandsMixin { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUComputePassEncoder"; + /** + * Sets the current {@link GPUComputePipeline}. + * @param pipeline - The compute pipeline to use for subsequent dispatch commands. + */ + setPipeline( + pipeline: GPUComputePipeline + ): undefined; + /** + * Dispatch work to be performed with the current {@link GPUComputePipeline}. + * See [[#computing-operations]] for the detailed specification. + * @param workgroupCountX - X dimension of the grid of workgroups to dispatch. + * @param workgroupCountY - Y dimension of the grid of workgroups to dispatch. + * @param workgroupCountZ - Z dimension of the grid of workgroups to dispatch. + */ + dispatchWorkgroups( + workgroupCountX: GPUSize32, + workgroupCountY?: GPUSize32, + workgroupCountZ?: GPUSize32 + ): undefined; + /** + * Dispatch work to be performed with the current {@link GPUComputePipeline} using parameters read + * from a {@link GPUBuffer}. + * See [[#computing-operations]] for the detailed specification. + * packed block of **three 32-bit unsigned integer values (12 bytes total)**, + * given in the same order as the arguments for {@link GPUComputePassEncoder#dispatchWorkgroups}. + * For example: + * @param indirectBuffer - Buffer containing the indirect dispatch parameters. + * @param indirectOffset - Offset in bytes into `indirectBuffer` where the dispatch data begins. + */ + dispatchWorkgroupsIndirect( + indirectBuffer: GPUBuffer, + indirectOffset: GPUSize64 + ): undefined; + /** + * Completes recording of the compute pass commands sequence. + */ + end(): undefined; +} + +declare var GPUComputePassEncoder: { + prototype: GPUComputePassEncoder; + new (): never; +}; + +interface GPUComputePipeline + extends GPUObjectBase, + GPUPipelineBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUComputePipeline"; +} + +declare var GPUComputePipeline: { + prototype: GPUComputePipeline; + new (): never; +}; + +interface GPUDevice + extends EventTarget, + GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUDevice"; + /** + * A set containing the {@link GPUFeatureName} values of the features + * supported by the device (i.e. the ones with which it was created). + */ + readonly features: GPUSupportedFeatures; + /** + * Exposes the limits supported by the device + * (which are exactly the ones with which it was created). + */ + readonly limits: GPUSupportedLimits; + /** + * The primary {@link GPUQueue} for this device. + */ + readonly queue: GPUQueue; + /** + * Destroys the device, preventing further operations on it. + * Outstanding asynchronous operations will fail. + * Note: It is valid to destroy a device multiple times. + */ + destroy(): undefined; + /** + * Creates a {@link GPUBuffer}. + * @param descriptor - Description of the {@link GPUBuffer} to create. + */ + createBuffer( + descriptor: GPUBufferDescriptor + ): GPUBuffer; + /** + * Creates a {@link GPUTexture}. + * @param descriptor - Description of the {@link GPUTexture} to create. + */ + createTexture( + descriptor: GPUTextureDescriptor + ): GPUTexture; + /** + * Creates a {@link GPUSampler}. + * @param descriptor - Description of the {@link GPUSampler} to create. + */ + createSampler( + descriptor?: GPUSamplerDescriptor + ): GPUSampler; + /** + * Creates a {@link GPUExternalTexture} wrapping the provided image source. + * @param descriptor - Provides the external image source object (and any creation options). + */ + importExternalTexture( + descriptor: GPUExternalTextureDescriptor + ): GPUExternalTexture; + /** + * Creates a {@link GPUBindGroupLayout}. + * @param descriptor - Description of the {@link GPUBindGroupLayout} to create. + */ + createBindGroupLayout( + descriptor: GPUBindGroupLayoutDescriptor + ): GPUBindGroupLayout; + /** + * Creates a {@link GPUPipelineLayout}. + * @param descriptor - Description of the {@link GPUPipelineLayout} to create. + */ + createPipelineLayout( + descriptor: GPUPipelineLayoutDescriptor + ): GPUPipelineLayout; + /** + * Creates a {@link GPUBindGroup}. + * @param descriptor - Description of the {@link GPUBindGroup} to create. + */ + createBindGroup( + descriptor: GPUBindGroupDescriptor + ): GPUBindGroup; + /** + * Creates a {@link GPUShaderModule}. + * @param descriptor - Description of the {@link GPUShaderModule} to create. + */ + createShaderModule( + descriptor: GPUShaderModuleDescriptor + ): GPUShaderModule; + /** + * Creates a {@link GPUComputePipeline} using immediate pipeline creation. + * @param descriptor - Description of the {@link GPUComputePipeline} to create. + */ + createComputePipeline( + descriptor: GPUComputePipelineDescriptor + ): GPUComputePipeline; + /** + * Creates a {@link GPURenderPipeline} using immediate pipeline creation. + * @param descriptor - Description of the {@link GPURenderPipeline} to create. + */ + createRenderPipeline( + descriptor: GPURenderPipelineDescriptor + ): GPURenderPipeline; + /** + * Creates a {@link GPUComputePipeline} using async pipeline creation. + * The returned {@link Promise} resolves when the created pipeline + * is ready to be used without additional delay. + * If pipeline creation fails, the returned {@link Promise} rejects with an {@link GPUPipelineError}. + * Note: Use of this method is preferred whenever possible, as it prevents blocking the + * queue timeline work on pipeline compilation. + * @param descriptor - Description of the {@link GPUComputePipeline} to create. + */ + createComputePipelineAsync( + descriptor: GPUComputePipelineDescriptor + ): Promise; + /** + * Creates a {@link GPURenderPipeline} using async pipeline creation. + * The returned {@link Promise} resolves when the created pipeline + * is ready to be used without additional delay. + * If pipeline creation fails, the returned {@link Promise} rejects with an {@link GPUPipelineError}. + * Note: Use of this method is preferred whenever possible, as it prevents blocking the + * queue timeline work on pipeline compilation. + * @param descriptor - Description of the {@link GPURenderPipeline} to create. + */ + createRenderPipelineAsync( + descriptor: GPURenderPipelineDescriptor + ): Promise; + /** + * Creates a {@link GPUCommandEncoder}. + * @param descriptor - Description of the {@link GPUCommandEncoder} to create. + */ + createCommandEncoder( + descriptor?: GPUCommandEncoderDescriptor + ): GPUCommandEncoder; + /** + * Creates a {@link GPURenderBundleEncoder}. + * @param descriptor - Description of the {@link GPURenderBundleEncoder} to create. + */ + createRenderBundleEncoder( + descriptor: GPURenderBundleEncoderDescriptor + ): GPURenderBundleEncoder; + /** + * Creates a {@link GPUQuerySet}. + * @param descriptor - Description of the {@link GPUQuerySet} to create. + */ + createQuerySet( + descriptor: GPUQuerySetDescriptor + ): GPUQuerySet; + /** + * A slot-backed attribute holding a promise which is created with the device, remains + * pending for the lifetime of the device, then resolves when the device is lost. + * Upon initialization, it is set to a new promise. + */ + readonly lost: Promise; + /** + * Pushes a new GPU error scope onto the {@link GPUDevice#[[errorScopeStack]]} for `this`. + * @param filter - Which class of errors this error scope observes. + */ + pushErrorScope( + filter: GPUErrorFilter + ): undefined; + /** + * Pops a GPU error scope off the {@link GPUDevice#[[errorScopeStack]]} for `this` + * and resolves to **any** {@link GPUError} observed by the error scope, or `null` if none. + * There is no guarantee of the ordering of promise resolution. + */ + popErrorScope(): Promise; + /** + * An event handler IDL attribute for the {@link GPUDevice#uncapturederror} event type. + */ + onuncapturederror: + | (( + this: GPUDevice, + ev: GPUUncapturedErrorEvent + ) => any) + | null; +} + +declare var GPUDevice: { + prototype: GPUDevice; + new (): never; +}; + +interface GPUDeviceLostInfo { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUDeviceLostInfo"; + readonly reason: GPUDeviceLostReason; + readonly message: string; +} + +declare var GPUDeviceLostInfo: { + prototype: GPUDeviceLostInfo; + new (): never; +}; + +interface GPUError { + /** + * A human-readable, localizable text message providing information about the error that + * occurred. + * Note: This message is generally intended for application developers to debug their + * applications and capture information for debug reports, not to be surfaced to end-users. + * Note: User agents should not include potentially machine-parsable details in this message, + * such as free system memory on {@link GPUErrorFilter#"out-of-memory"} or other details about the + * conditions under which memory was exhausted. + * Note: The {@link GPUError#message} should follow the best practices for language and + * direction information. This includes making use of any future standards which may emerge + * regarding the reporting of string language and direction metadata. + *

Editorial: + * At the time of this writing, no language/direction recommendation is available that provides + * compatibility and consistency with legacy APIs, but when there is, adopt it formally. + */ + readonly message: string; +} + +declare var GPUError: { + prototype: GPUError; + new (): never; +}; + +interface GPUExternalTexture + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUExternalTexture"; +} + +declare var GPUExternalTexture: { + prototype: GPUExternalTexture; + new (): never; +}; + +interface GPUInternalError + extends GPUError { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUInternalError"; +} + +declare var GPUInternalError: { + prototype: GPUInternalError; + new ( + message: string + ): GPUInternalError; +}; + +interface GPUOutOfMemoryError + extends GPUError { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUOutOfMemoryError"; +} + +declare var GPUOutOfMemoryError: { + prototype: GPUOutOfMemoryError; + new ( + message: string + ): GPUOutOfMemoryError; +}; + +interface GPUPipelineError + extends DOMException { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUPipelineError"; + /** + * A read-only slot-backed attribute exposing the type of error encountered in pipeline creation + * as a GPUPipelineErrorReason: + *

    + * - "validation": A [$validation error$]. + * - "internal": An [$internal error$]. + *
+ */ + readonly reason: GPUPipelineErrorReason; +} + +declare var GPUPipelineError: { + prototype: GPUPipelineError; + new ( + message: + | string + | undefined, + options: GPUPipelineErrorInit + ): GPUPipelineError; +}; + +interface GPUPipelineLayout + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUPipelineLayout"; +} + +declare var GPUPipelineLayout: { + prototype: GPUPipelineLayout; + new (): never; +}; + +interface GPUQuerySet + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUQuerySet"; + /** + * Destroys the {@link GPUQuerySet}. + */ + destroy(): undefined; + /** + * The type of the queries managed by this {@link GPUQuerySet}. + */ + readonly type: GPUQueryType; + /** + * The number of queries managed by this {@link GPUQuerySet}. + */ + readonly count: GPUSize32Out; +} + +declare var GPUQuerySet: { + prototype: GPUQuerySet; + new (): never; +}; + +interface GPUQueue + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUQueue"; + /** + * Schedules the execution of the command buffers by the GPU on this queue. + * Submitted command buffers cannot be used again. + * `commandBuffers`: + */ + submit( + commandBuffers: Iterable + ): undefined; + /** + * Returns a {@link Promise} that resolves once this queue finishes processing all the work submitted + * up to this moment. + * Resolution of this {@link Promise} implies the completion of + * {@link GPUBuffer#mapAsync} calls made prior to that call, + * on {@link GPUBuffer}s last used exclusively on that queue. + */ + onSubmittedWorkDone(): Promise; + /** + * Issues a write operation of the provided data into a {@link GPUBuffer}. + * @param buffer - The buffer to write to. + * @param bufferOffset - Offset in bytes into `buffer` to begin writing at. + * @param data - Data to write into `buffer`. + * @param dataOffset - Offset in into `data` to begin writing from. Given in elements if + * `data` is a `TypedArray` and bytes otherwise. + * @param size - Size of content to write from `data` to `buffer`. Given in elements if + * `data` is a `TypedArray` and bytes otherwise. + */ + writeBuffer( + buffer: GPUBuffer, + bufferOffset: GPUSize64, + data: + | BufferSource + | SharedArrayBuffer, + dataOffset?: GPUSize64, + size?: GPUSize64 + ): undefined; + /** + * Issues a write operation of the provided data into a {@link GPUTexture}. + * @param destination - The texture subresource and origin to write to. + * @param data - Data to write into `destination`. + * @param dataLayout - Layout of the content in `data`. + * @param size - Extents of the content to write from `data` to `destination`. + */ + writeTexture( + destination: GPUImageCopyTexture, + data: + | BufferSource + | SharedArrayBuffer, + dataLayout: GPUImageDataLayout, + size: GPUExtent3DStrict + ): undefined; + /** + * Issues a copy operation of the contents of a platform image/canvas + * into the destination texture. + * This operation performs [[#color-space-conversions|color encoding]] into the destination + * encoding according to the parameters of {@link GPUImageCopyTextureTagged}. + * Copying into a `-srgb` texture results in the same texture bytes, not the same decoded + * values, as copying into the corresponding non-`-srgb` format. + * Thus, after a copy operation, sampling the destination texture has + * different results depending on whether its format is `-srgb`, all else unchanged. + * + * @param source - source image and origin to copy to `destination`. + * @param destination - The texture subresource and origin to write to, and its encoding metadata. + * @param copySize - Extents of the content to write from `source` to `destination`. + */ + copyExternalImageToTexture( + source: GPUImageCopyExternalImage, + destination: GPUImageCopyTextureTagged, + copySize: GPUExtent3DStrict + ): undefined; +} + +declare var GPUQueue: { + prototype: GPUQueue; + new (): never; +}; + +interface GPURenderBundle + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPURenderBundle"; +} + +declare var GPURenderBundle: { + prototype: GPURenderBundle; + new (): never; +}; + +interface GPURenderBundleEncoder + extends GPUObjectBase, + GPUCommandsMixin, + GPUDebugCommandsMixin, + GPUBindingCommandsMixin, + GPURenderCommandsMixin { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPURenderBundleEncoder"; + /** + * Completes recording of the render bundle commands sequence. + * descriptor: + */ + finish( + descriptor?: GPURenderBundleDescriptor + ): GPURenderBundle; +} + +declare var GPURenderBundleEncoder: { + prototype: GPURenderBundleEncoder; + new (): never; +}; + +interface GPURenderPassEncoder + extends GPUObjectBase, + GPUCommandsMixin, + GPUDebugCommandsMixin, + GPUBindingCommandsMixin, + GPURenderCommandsMixin { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPURenderPassEncoder"; + /** + * Sets the viewport used during the rasterization stage to linearly map from + * NDC|normalized device coordinates to viewport coordinates. + * @param x - Minimum X value of the viewport in pixels. + * @param y - Minimum Y value of the viewport in pixels. + * @param width - Width of the viewport in pixels. + * @param height - Height of the viewport in pixels. + * @param minDepth - Minimum depth value of the viewport. + * @param maxDepth - Maximum depth value of the viewport. + */ + setViewport( + x: number, + y: number, + width: number, + height: number, + minDepth: number, + maxDepth: number + ): undefined; + /** + * Sets the scissor rectangle used during the rasterization stage. + * After transformation into viewport coordinates any fragments which fall outside the scissor + * rectangle will be discarded. + * @param x - Minimum X value of the scissor rectangle in pixels. + * @param y - Minimum Y value of the scissor rectangle in pixels. + * @param width - Width of the scissor rectangle in pixels. + * @param height - Height of the scissor rectangle in pixels. + */ + setScissorRect( + x: GPUIntegerCoordinate, + y: GPUIntegerCoordinate, + width: GPUIntegerCoordinate, + height: GPUIntegerCoordinate + ): undefined; + /** + * Sets the constant blend color and alpha values used with {@link GPUBlendFactor#"constant"} + * and {@link GPUBlendFactor#"one-minus-constant"} {@link GPUBlendFactor}s. + * @param color - The color to use when blending. + */ + setBlendConstant( + color: GPUColor + ): undefined; + /** + * Sets the {@link RenderState#[[stencilReference]]} value used during stencil tests with + * the {@link GPUStencilOperation#"replace"} {@link GPUStencilOperation}. + * @param reference - The new stencil reference value. + */ + setStencilReference( + reference: GPUStencilValue + ): undefined; + /** + * @param queryIndex - The index of the query in the query set. + */ + beginOcclusionQuery( + queryIndex: GPUSize32 + ): undefined; + /** + */ + endOcclusionQuery(): undefined; + /** + * Executes the commands previously recorded into the given {@link GPURenderBundle}s as part of + * this render pass. + * When a {@link GPURenderBundle} is executed, it does not inherit the render pass's pipeline, bind + * groups, or vertex and index buffers. After a {@link GPURenderBundle} has executed, the render + * pass's pipeline, bind group, and vertex/index buffer state is cleared + * (to the initial, empty values). + * Note: The state is cleared, not restored to the previous state. + * This occurs even if zero {@link GPURenderBundle|GPURenderBundles} are executed. + * @param bundles - List of render bundles to execute. + */ + executeBundles( + bundles: Iterable + ): undefined; + /** + * Completes recording of the render pass commands sequence. + */ + end(): undefined; +} + +declare var GPURenderPassEncoder: { + prototype: GPURenderPassEncoder; + new (): never; +}; + +interface GPURenderPipeline + extends GPUObjectBase, + GPUPipelineBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPURenderPipeline"; +} + +declare var GPURenderPipeline: { + prototype: GPURenderPipeline; + new (): never; +}; + +interface GPUSampler + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUSampler"; +} + +declare var GPUSampler: { + prototype: GPUSampler; + new (): never; +}; + +interface GPUShaderModule + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUShaderModule"; + /** + * Returns any messages generated during the {@link GPUShaderModule}'s compilation. + * The locations, order, and contents of messages are implementation-defined. + * In particular, messages may not be ordered by {@link GPUCompilationMessage#lineNum}. + */ + getCompilationInfo(): Promise; +} + +declare var GPUShaderModule: { + prototype: GPUShaderModule; + new (): never; +}; + +type GPUSupportedFeatures = + ReadonlySet; + +interface GPUSupportedLimits { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUSupportedLimits"; + readonly maxTextureDimension1D: number; + readonly maxTextureDimension2D: number; + readonly maxTextureDimension3D: number; + readonly maxTextureArrayLayers: number; + readonly maxBindGroups: number; + readonly maxBindGroupsPlusVertexBuffers: number; + readonly maxBindingsPerBindGroup: number; + readonly maxDynamicUniformBuffersPerPipelineLayout: number; + readonly maxDynamicStorageBuffersPerPipelineLayout: number; + readonly maxSampledTexturesPerShaderStage: number; + readonly maxSamplersPerShaderStage: number; + readonly maxStorageBuffersPerShaderStage: number; + readonly maxStorageTexturesPerShaderStage: number; + readonly maxUniformBuffersPerShaderStage: number; + readonly maxUniformBufferBindingSize: number; + readonly maxStorageBufferBindingSize: number; + readonly minUniformBufferOffsetAlignment: number; + readonly minStorageBufferOffsetAlignment: number; + readonly maxVertexBuffers: number; + readonly maxBufferSize: number; + readonly maxVertexAttributes: number; + readonly maxVertexBufferArrayStride: number; + readonly maxInterStageShaderComponents: number; + readonly maxInterStageShaderVariables: number; + readonly maxColorAttachments: number; + readonly maxColorAttachmentBytesPerSample: number; + readonly maxComputeWorkgroupStorageSize: number; + readonly maxComputeInvocationsPerWorkgroup: number; + readonly maxComputeWorkgroupSizeX: number; + readonly maxComputeWorkgroupSizeY: number; + readonly maxComputeWorkgroupSizeZ: number; + readonly maxComputeWorkgroupsPerDimension: number; +} + +declare var GPUSupportedLimits: { + prototype: GPUSupportedLimits; +}; + +interface GPUTexture + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUTexture"; + /** + * Creates a {@link GPUTextureView}. + * @param descriptor - Description of the {@link GPUTextureView} to create. + */ + createView( + descriptor?: GPUTextureViewDescriptor + ): GPUTextureView; + /** + * Destroys the {@link GPUTexture}. + */ + destroy(): undefined; + /** + * The width of this {@link GPUTexture}. + */ + readonly width: GPUIntegerCoordinateOut; + /** + * The height of this {@link GPUTexture}. + */ + readonly height: GPUIntegerCoordinateOut; + /** + * The depth or layer count of this {@link GPUTexture}. + */ + readonly depthOrArrayLayers: GPUIntegerCoordinateOut; + /** + * The number of mip levels of this {@link GPUTexture}. + */ + readonly mipLevelCount: GPUIntegerCoordinateOut; + /** + * The number of sample count of this {@link GPUTexture}. + */ + readonly sampleCount: GPUSize32Out; + /** + * The dimension of the set of texel for each of this {@link GPUTexture}'s subresources. + */ + readonly dimension: GPUTextureDimension; + /** + * The format of this {@link GPUTexture}. + */ + readonly format: GPUTextureFormat; + /** + * The allowed usages for this {@link GPUTexture}. + */ + readonly usage: GPUFlagsConstant; +} + +declare var GPUTexture: { + prototype: GPUTexture; + new (): never; +}; + +interface GPUTextureView + extends GPUObjectBase { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUTextureView"; +} + +declare var GPUTextureView: { + prototype: GPUTextureView; + new (): never; +}; + +interface GPUUncapturedErrorEvent + extends Event { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUUncapturedErrorEvent"; + /** + * A slot-backed attribute holding an object representing the error that was uncaptured. + * This has the same type as errors returned by {@link GPUDevice#popErrorScope}. + */ + readonly error: GPUError; +} + +declare var GPUUncapturedErrorEvent: { + prototype: GPUUncapturedErrorEvent; + new ( + type: string, + gpuUncapturedErrorEventInitDict: GPUUncapturedErrorEventInit + ): GPUUncapturedErrorEvent; +}; + +interface GPUValidationError + extends GPUError { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUValidationError"; +} + +declare var GPUValidationError: { + prototype: GPUValidationError; + new ( + message: string + ): GPUValidationError; +}; + +type WGSLLanguageFeatures = + ReadonlySet; + +interface Navigator + extends NavigatorGPU {} + +interface WorkerNavigator + extends NavigatorGPU {} + +interface GPUBufferUsage { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUBufferUsage"; + readonly MAP_READ: GPUFlagsConstant; + readonly MAP_WRITE: GPUFlagsConstant; + readonly COPY_SRC: GPUFlagsConstant; + readonly COPY_DST: GPUFlagsConstant; + readonly INDEX: GPUFlagsConstant; + readonly VERTEX: GPUFlagsConstant; + readonly UNIFORM: GPUFlagsConstant; + readonly STORAGE: GPUFlagsConstant; + readonly INDIRECT: GPUFlagsConstant; + readonly QUERY_RESOLVE: GPUFlagsConstant; +} + +declare var GPUBufferUsage: { + prototype: GPUBufferUsage; + readonly MAP_READ: GPUFlagsConstant; + readonly MAP_WRITE: GPUFlagsConstant; + readonly COPY_SRC: GPUFlagsConstant; + readonly COPY_DST: GPUFlagsConstant; + readonly INDEX: GPUFlagsConstant; + readonly VERTEX: GPUFlagsConstant; + readonly UNIFORM: GPUFlagsConstant; + readonly STORAGE: GPUFlagsConstant; + readonly INDIRECT: GPUFlagsConstant; + readonly QUERY_RESOLVE: GPUFlagsConstant; +}; + +interface GPUColorWrite { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUColorWrite"; + readonly RED: GPUFlagsConstant; + readonly GREEN: GPUFlagsConstant; + readonly BLUE: GPUFlagsConstant; + readonly ALPHA: GPUFlagsConstant; + readonly ALL: GPUFlagsConstant; +} + +declare var GPUColorWrite: { + prototype: GPUColorWrite; + readonly RED: GPUFlagsConstant; + readonly GREEN: GPUFlagsConstant; + readonly BLUE: GPUFlagsConstant; + readonly ALPHA: GPUFlagsConstant; + readonly ALL: GPUFlagsConstant; +}; + +interface GPUMapMode { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUMapMode"; + readonly READ: GPUFlagsConstant; + readonly WRITE: GPUFlagsConstant; +} + +declare var GPUMapMode: { + prototype: GPUMapMode; + new (): never; + readonly READ: GPUFlagsConstant; + readonly WRITE: GPUFlagsConstant; +}; + +interface GPUShaderStage { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUShaderStage"; + readonly VERTEX: GPUFlagsConstant; + readonly FRAGMENT: GPUFlagsConstant; + readonly COMPUTE: GPUFlagsConstant; +} + +declare var GPUShaderStage: { + prototype: GPUShaderStage; + readonly VERTEX: GPUFlagsConstant; + readonly FRAGMENT: GPUFlagsConstant; + readonly COMPUTE: GPUFlagsConstant; +}; + +interface GPUTextureUsage { + /** + * Nominal type branding. + * https://github.com/microsoft/TypeScript/pull/33038 + * @internal + */ + readonly __brand: "GPUTextureUsage"; + readonly COPY_SRC: GPUFlagsConstant; + readonly COPY_DST: GPUFlagsConstant; + readonly TEXTURE_BINDING: GPUFlagsConstant; + readonly STORAGE_BINDING: GPUFlagsConstant; + readonly RENDER_ATTACHMENT: GPUFlagsConstant; +} + +declare var GPUTextureUsage: { + prototype: GPUTextureUsage; + readonly COPY_SRC: GPUFlagsConstant; + readonly COPY_DST: GPUFlagsConstant; + readonly TEXTURE_BINDING: GPUFlagsConstant; + readonly STORAGE_BINDING: GPUFlagsConstant; + readonly RENDER_ATTACHMENT: GPUFlagsConstant; +};