@@ -23,9 +23,8 @@ const proxy = URL.createObjectURL(new Blob([`
2323
2424window.MonacoEnvironment = { getWorkerUrl : ( ) => proxy } ;
2525
26- const theme = window.matchMedia &&
27- window.matchMedia('(prefers-color-scheme: dark)').matches
28- ? 'vs-dark' : undefined;
26+ //const theme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'vs-dark' : undefined;
27+ const theme = 'vs-dark';
2928
3029let value = `
3130import { flavors } from "https://gist.githubusercontent.com/BurntCaramel/d9d2ca7ed6f056632696709a2ae3c413/raw/0234322cf854d52e2f2bd33aa37e8c8b00f9df0a/1.js";
@@ -132,6 +131,116 @@ export default function App() {
132131}
133132`.trim();
134133
134+ value = `
135+ import { flavors } from "https://gist.githubusercontent.com/BurntCaramel/d9d2ca7ed6f056632696709a2ae3c413/raw/0234322cf854d52e2f2bd33aa37e8c8b00f9df0a/1.js";
136+
137+ const a = 1 + 1 + flavors.length;
138+
139+ function useTick() {
140+ return useReducer ( n => n + 1 , 0 ) ;
141+ }
142+
143+ function useDebouncer(duration) {
144+ const [ count , tick ] = useTick ( ) ;
145+
146+ const callback = useMemo ( ( ) => {
147+ let timeout = null ;
148+ function clear ( ) {
149+ if ( timeout ) {
150+ clearTimeout ( timeout ) ;
151+ timeout = null ;
152+ }
153+ }
154+ return ( ) => {
155+ clear ( )
156+ timeout = setTimeout ( tick , duration ) ;
157+ return clear;
158+ } ;
159+ } , [ duration , tick ] ) ;
160+
161+ return [ count , callback ] ;
162+ }
163+
164+ const cache = new Map();
165+ function cachedWork(key, work) {
166+ const existing = cache . get ( key ) ;
167+ if ( existing ) return existing;
168+
169+ const created = work ( ) ;
170+ cache . set ( key , created ) ;
171+ return created ;
172+ }
173+
174+ function useCacheKey() {
175+ const [ key ] = useState ( ( ) => Object ( Symbol ( Math . random ( ) ) ) ) ;
176+ console . log ( 'key' , key ) ; ;
177+ return key ;
178+ }
179+
180+ function useCached(work) {
181+ const key = useCacheKey ( ) ;
182+ return cachedWork ( key , work ) ;
183+ }
184+
185+ function useAsyncCached(work) {
186+ const key = useCacheKey ( ) ;
187+ console . log ( key ) ;
188+
189+ let record = cache . get ( key ) ;
190+
191+ console . log ( 'record' , record )
192+
193+ if ( record === undefined ) {
194+ record = {
195+ status: 'pending' ,
196+ result: undefined
197+ } ;
198+ cache . set ( key , record ) ;
199+
200+ const promise = work ( )
201+ . then ( result => {
202+ record . status = 'succeeded' ;
203+ record. result = result ;
204+ } )
205+ . catch ( error => {
206+ record . status = 'failed' ;
207+ record. result = error ;
208+ } ) ;
209+ record . promise = promise ;
210+ }
211+
212+ if ( record . status === 'pending' ) {
213+ throw record . promise ;
214+ }
215+
216+ if ( record . status === 'failed' ) {
217+ throw record . result ;
218+ }
219+
220+ return record . result ;
221+ }
222+
223+ function SHAComponent() {
224+ const sha = useAsyncCached ( ( ) =>
225+ crypto . subtle . digest ( 'SHA-256' , new TextEncoder ( ) . encode ( 'abc' ) )
226+ . then ( arrayBuffer => {
227+ return Array . from ( new Uint8Array ( arrayBuffer ) , chunk => chunk . toString ( 16 ) . padStart ( 2 , '0' ) ) . join ( '' ) ;
228+ } )
229+ ) ;
230+
231+ return < div > { sha } < / div > ;
232+ }
233+
234+ export default function App() {
235+ const [ count , tick ] = useDebouncer ( 1000 ) ;
236+ return <>
237+ < div > Hello ! ! { flavors . join ( " " ) } < / div >
238+ < button onClick = { tick } > Click < / button >
239+ < div > { count } < / div >
240+ < />;
241+ }
242+ `.trim();
243+
135244const types = fetch("https://workers.cloudflare.com/index.d.ts", { cache : 'force-cache' } )
136245 .then((response) => response.text())
137246 .catch((err) = > ` // $ { err . message } `);
@@ -250,6 +359,7 @@ require(["vs/editor/editor.main"], function () {
250359 })
251360 })
252361 .then(({ code, codeBytes, duration }) => {
362+ console.log(" NEW CODE!");
253363 const executor = new Function(`${code}; return exports.Example();`);
254364 const result = executor();
255365 return new Map()
@@ -281,11 +391,25 @@ require(["vs/editor/editor.main"], function () {
281391 model.setValue(input.getValue() + " \n") ;
282392
283393 const clientAppEl = document.getElementById( 'clientApp') ;
394+ const reactRenderEl = document . querySelector ( '#clientResult slot[name="reactRenderDuration"]' ) ;
284395 let renderCount = 0 ;
285396 clientAppEl. addEventListener ( 'DID_RENDER' , ( { detail } ) => {
286397 renderCount ++ ;
287- console.log(" DID_RENDER ");
288- document.querySelector('#clientResult slot[name="reactRenderDuration "]').textContent = `last ${detail.actualDuration}ms; ${renderCount} times rendered`;
398+
399+ if ( renderCount > 1000 ) {
400+ const previousCount = renderCount ;
401+ setTimeout ( ( ) => {
402+ if ( renderCount - previousCount > 100 ) {
403+ // Too many renders.
404+ / / Abort client React app!
405+ clientAppEl. dispatchEvent ( new CustomEvent ('RESET' ) ) ;
406+
407+ reactRenderEl. textContent = `aborted due to infinite rendering loop! `;
408+ }
409+ } , 1000 ) ;
410+ }
411+
412+ reactRenderEl. textContent = `last ${ detail . actualDuration } ms; ${ renderCount } times rendered `;
289413 } ) ;
290414} );
291415</ script >
0 commit comments