MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 132 lines 3.8 kB view raw
1class ReactPromise { 2 constructor(status, value, reason) { 3 this.status = status; 4 this.value = value; 5 this.reason = reason; 6 } 7} 8 9function createPendingChunk() { 10 return new ReactPromise("pending", null, null); 11} 12 13function createResolvedIteratorResultChunk(response, value, done) { 14 return new ReactPromise( 15 "resolved_model", 16 (done ? "{\"done\":true,\"value\":" : "{\"done\":false,\"value\":") + value + "}", 17 response 18 ); 19} 20 21function resolveModelChunk(response, chunk, value) { 22 if ("pending" !== chunk.status) { 23 chunk.reason.enqueueModel(value); 24 return; 25 } 26 27 chunk.status = "resolved_model"; 28 chunk.value = value; 29 chunk.reason = response; 30} 31 32function resolveIteratorResultChunk(response, chunk, value, done) { 33 resolveModelChunk( 34 response, 35 chunk, 36 (done ? "{\"done\":true,\"value\":" : "{\"done\":false,\"value\":") + value + "}" 37 ); 38} 39 40function startAsyncIterable(response, id, iterator) { 41 const buffer = []; 42 let closed = false; 43 let nextWriteIndex = 0; 44 const iterable = {}; 45 46 iterable[Symbol.asyncIterator] = function () { 47 let nextReadIndex = 0; 48 return { 49 next(arg) { 50 if (arg !== undefined) throw new Error("bad arg"); 51 if (nextReadIndex === buffer.length) { 52 if (closed) { 53 return new ReactPromise("fulfilled", { done: true, value: undefined }, null); 54 } 55 buffer[nextReadIndex] = createPendingChunk(response); 56 } 57 return buffer[nextReadIndex++]; 58 } 59 }; 60 }; 61 62 const controller = { 63 enqueueValue(value) { 64 if (nextWriteIndex === buffer.length) { 65 buffer[nextWriteIndex] = new ReactPromise("fulfilled", { done: false, value }, null); 66 } else { 67 const chunk = buffer[nextWriteIndex]; 68 chunk.status = "fulfilled"; 69 chunk.value = { done: false, value }; 70 chunk.reason = null; 71 } 72 nextWriteIndex++; 73 }, 74 enqueueModel(value) { 75 if (nextWriteIndex === buffer.length) { 76 buffer[nextWriteIndex] = createResolvedIteratorResultChunk(response, value, false); 77 } else { 78 resolveIteratorResultChunk(response, buffer[nextWriteIndex], value, false); 79 } 80 nextWriteIndex++; 81 }, 82 close(value) { 83 if (!closed) { 84 closed = true; 85 if (nextWriteIndex === buffer.length) { 86 buffer[nextWriteIndex] = createResolvedIteratorResultChunk(response, value, true); 87 } else { 88 resolveIteratorResultChunk(response, buffer[nextWriteIndex], value, true); 89 } 90 nextWriteIndex++; 91 } 92 }, 93 error(error) { 94 throw error; 95 } 96 }; 97 98 response._chunks.set(id, new ReactPromise("fulfilled", iterator ? iterable[Symbol.asyncIterator]() : iterable, controller)); 99 return { buffer, controller }; 100} 101 102function log(label, fn) { 103 try { 104 const out = fn(); 105 console.log(`${label}:${out}`); 106 } catch (error) { 107 console.log(`${label}:ERR:${error && error.message ? error.message : String(error)}`); 108 } 109} 110 111const response = { _chunks: new Map() }; 112const id = 1; 113 114startAsyncIterable(response, id, true); 115const chunk = response._chunks.get(id); 116 117log("reasonType", () => typeof chunk.reason); 118log("enqueueModelType", () => typeof chunk.reason.enqueueModel); 119 120resolveModelChunk(response, chunk, "\"1\""); 121console.log(`bufferLength:${chunk.reason ? "controller" : "missing"}`); 122 123const response2 = { _chunks: new Map() }; 124const id2 = 2; 125response2._chunks.set(id2, new ReactPromise("resolved_model", "\"boot\"", response2)); 126const badChunk = response2._chunks.get(id2); 127log("badReasonType", () => typeof badChunk.reason); 128log("badEnqueueModelType", () => typeof badChunk.reason.enqueueModel); 129log("badResolve", () => { 130 resolveModelChunk(response2, badChunk, "\"next\""); 131 return "ok"; 132});