From 8da666e1417f23fb389a4552a4ade649c75bf35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Ku=C4=87mierz?= Date: Thu, 27 Oct 2022 07:12:09 +0200 Subject: [PATCH] copy worker code from old app --- package-lock.json | 11 ++++++++ package.json | 1 + src/app.config.mjs | 3 ++ src/file.worker.js | 64 +++++++++++++++++++++++++++++++++++++++++- src/views/HomeView.vue | 54 ++++++++++++++++++++++++++++++++--- 5 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 src/app.config.mjs diff --git a/package-lock.json b/package-lock.json index bf3fd33..73cff03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@codemirror/lang-javascript": "^6.1.1", "@codemirror/theme-one-dark": "^6.1.0", "codemirror": "^6.0.1", + "javascript-stringify": "^2.1.0", "normalize.css": "^8.0.1", "primevue": "^3.18.0", "vue": "^3.2.41", @@ -1213,6 +1214,11 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==" + }, "node_modules/js-sdsl": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", @@ -2954,6 +2960,11 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==" + }, "js-sdsl": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", diff --git a/package.json b/package.json index 1d99a08..4055a84 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "@codemirror/lang-javascript": "^6.1.1", "@codemirror/theme-one-dark": "^6.1.0", "codemirror": "^6.0.1", + "javascript-stringify": "^2.1.0", "normalize.css": "^8.0.1", "primevue": "^3.18.0", "vue": "^3.2.41", diff --git a/src/app.config.mjs b/src/app.config.mjs new file mode 100644 index 0000000..530b27b --- /dev/null +++ b/src/app.config.mjs @@ -0,0 +1,3 @@ + +export const MAX_DATA_SIZE = 1e5; +export const ERROR_MAX_DATA_SIZE = 'Error: Output exceeded maximum size allowed'; diff --git a/src/file.worker.js b/src/file.worker.js index ad9a372..fd56ab6 100644 --- a/src/file.worker.js +++ b/src/file.worker.js @@ -1,3 +1,65 @@ -console.log('Hello Worker!'); +import { stringify } from 'javascript-stringify'; +import { MAX_DATA_SIZE } from './app.config'; +const log = console.log; +console.log = (...a) => l(a); +console.error = a => e(a); + +// limit chunk of data sent to browser, to avoid eventloop blocking +const limitData = data => { + if (data.length > MAX_DATA_SIZE) { + return data.substr(0, MAX_DATA_SIZE); + } + return data; +}; + +const throttledPM = (() => { + const pm = postMessage; + self['postMessage'] = log; + const updateFreq = 50; // times per sec + const updateDelay = 1e3 / updateFreq; + let dataCache = []; + let lastUpdate = +new Date() - updateDelay; + + return (data, finish = false, tryAgain = true) => { + const now = +new Date(); + if (typeof data !== 'undefined') { + dataCache.push(data); + } + + if (lastUpdate + updateDelay <= now || finish) { + pm(limitData(dataCache.join('\n'))); + lastUpdate = now; + dataCache = []; + } + + if (tryAgain) { + const nextTick = fn => setTimeout(fn, 0); + const tryAgainFn = _ => throttledPM([][0], false, false); + // try push data asap + setTimeout(tryAgainFn, 0); + // try push possibly cached data for async code + setTimeout(tryAgainFn, updateDelay); + } + }; +})(); + +const l = args => { + const data = args.map(el => stringify(el, null, ' ')).join(', '); + throttledPM(data); +}; + +const e = err => { + const data = stringify(err); + throttledPM(data, true); +}; + +addEventListener('message', ({ data }) => { + try { + const code = new Function(data); + code(); + } catch (e) { + console.error(e); + } +}); diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index a315d9c..210db9b 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -19,8 +19,14 @@ export default defineComponent({ Codemirror, Splitter, SplitterPanel, }, - setup() { - const code = `console.log('Hello, world!')`; + data() { + const code = ` + +for (let i = 0; i < 42; ++i) { + console.log(i); +} + +`; const extensions = [javascript(), oneDark] // Codemirror EditorView instance ref @@ -41,12 +47,40 @@ export default defineComponent({ // return ... } + this.run(code); + return { code, extensions, handleReady, log: console.log, + worker, + result: '', } + }, + methods: { + run(code) { + this.terminate(); + this.result = ''; + + this.worker = new Worker(); + + this.worker.onmessage = ({ data }) => { + this.result += `${data}\n`; + }; + + this.worker.onerror = error => { + this.result += error.message; + }; + + this.worker.postMessage(code); + }, + terminate() { + if (this.worker) { + this.worker.terminate(); + this.worker = null; + } + }, } }) @@ -66,6 +100,18 @@ main { overflow-y: auto; outline-width: 0; } + +.result { + overflow-x: auto; + overflow-y: auto; + margin: 0; + padding: 8px; + height: 100%; + display: block; + font-family: monospace; + white-space: pre; + line-height: normal; +}