Skip to content

Commit 36691c4

Browse files
committed
web: Move codegen and loading of big files to web worker
1 parent 27755e0 commit 36691c4

File tree

7 files changed

+153
-84
lines changed

7 files changed

+153
-84
lines changed

json_typegen_web/package-lock.json

Lines changed: 0 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

json_typegen_web/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,5 @@
1616
"webpack-cli": "4.5.0",
1717
"webpack-dev-server": "3.11.2"
1818
},
19-
"dependencies": {
20-
"text-encoding-utf-8": "1.0.2"
21-
}
19+
"dependencies": {}
2220
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export const WorkerMessage = {
2+
WASM_READY: 'WASM_READY',
3+
CODEGEN: 'CODEGEN',
4+
CODEGEN_COMPLETE: 'CODEGEN_COMPLETE',
5+
LOAD_FILE: 'LOAD_FILE',
6+
LOAD_FILE_COMPLETE: 'LOAD_FILE_COMPLETE',
7+
CLEAR_FILE: 'CLEAR_FILE',
8+
}

json_typegen_web/src/index.html

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ <h1 class="title">json_typegen</h1>
153153
<div id="large-file-overlay" class="is-invisible">
154154
<p>Large input file not shown</p>
155155
<p id="large-file-message"></p>
156-
<button class="button mt-2" id="clear-input-button">Clear input file</button>
156+
<button class="button mt-2" id="clear-input-button">Clear input file</button><br />
157+
<div class="spinner mt-2" id="large-file-spinner"></div>
157158
</div>
158159
</div>
159160
</div>
@@ -226,13 +227,8 @@ <h1 class="title">json_typegen</h1>
226227
</div>
227228
</div>
228229

229-
<div class="overlay-container">
230-
<textarea class="textarea" rows="5" id="target" readonly>
231-
No code generated yet
232-
</textarea>
233-
<div id="spinner-overlay" class="is-invisible">
234-
<div class="spinner"></div>
235-
</div>
230+
<div class="control" id="target-wrapper">
231+
<textarea class="textarea" rows="3" id="target" readonly></textarea>
236232
</div>
237233
</div>
238234
</div>

json_typegen_web/src/index.js

Lines changed: 101 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,128 @@
1-
import {polyfill} from './polyfill';
21
import {$} from "./util";
32
import {updateDownloadLink} from "./download";
43
import {restoreParams, storeParams} from "./localstorage";
4+
import {WorkerMessage} from "./WorkerMessage";
55

66
restoreParams();
77

8-
let largeInput;
8+
const worker = new Worker(new URL('./worker.js', import.meta.url));
9+
let workerReady = false;
10+
let queued;
911

10-
polyfill().then(() => import("../../json_typegen_wasm/pkg")).then(typegen_wasm => {
11-
const render = () => {
12-
const typename = $('typename').value;
13-
let input = largeInput || $('input').value;
14-
const options = ({
15-
output_mode: $('outputmode').value,
16-
property_name_format: $('propertynameformat').value,
17-
unwrap: $('unwrap').value,
18-
});
12+
const render = () => {
13+
const typename = $('typename').value;
14+
let input = $('input').value;
15+
const options = ({
16+
output_mode: $('outputmode').value,
17+
property_name_format: $('propertynameformat').value,
18+
unwrap: $('unwrap').value,
19+
});
1920

20-
const extraoptions_elem = $('extraoptions');
21-
const extraoptions_json = extraoptions_elem.value;
22-
let extraoptions;
23-
try {
24-
extraoptions = extraoptions_json && JSON.parse(extraoptions_json);
25-
extraoptions_elem.classList.remove("is-danger")
26-
} catch (e) {
27-
extraoptions_elem.classList.add("is-danger")
28-
}
21+
const extraoptions_elem = $('extraoptions');
22+
const extraoptions_json = extraoptions_elem.value;
23+
let extraoptions;
24+
try {
25+
extraoptions = extraoptions_json && JSON.parse(extraoptions_json);
26+
extraoptions_elem.classList.remove('is-danger')
27+
} catch (e) {
28+
extraoptions_elem.classList.add('is-danger')
29+
}
30+
31+
storeParams({
32+
typename,
33+
input: (input.length < 1000000) ? input : "",
34+
options,
35+
extraoptions: extraoptions ? extraoptions_json : undefined
36+
})
2937

30-
storeParams({
31-
typename,
32-
input: (input.length < 1000000) ? input : "",
33-
options,
34-
extraoptions: extraoptions ? extraoptions_json : undefined
35-
})
38+
const combinedOptions = Object.assign({}, options, extraoptions || {});
3639

37-
const combinedOptions = Object.assign({}, options, extraoptions || {});
40+
const message = {
41+
type: WorkerMessage.CODEGEN,
42+
typename,
43+
input: input || "{}",
44+
options: combinedOptions,
45+
};
46+
requestCodegen(message);
47+
};
3848

39-
const result = typegen_wasm.run(typename, input || "{}", JSON.stringify(combinedOptions));
49+
function requestCodegen(message) {
50+
if (workerReady) {
51+
worker.postMessage(message);
52+
workerReady = false;
53+
$('target-wrapper').classList.add('is-loading');
54+
} else {
55+
queued = message;
56+
}
57+
}
4058

59+
worker.onmessage = messageEvent => {
60+
const message = messageEvent.data;
61+
if (message.type === WorkerMessage.CODEGEN_COMPLETE) {
62+
$('target-wrapper').classList.remove("is-loading");
4163
const target = $('target');
42-
target.value = result.trim();
64+
target.value = message.result.trim();
4365
target.style.height = "10px";
4466
target.style.height = (target.scrollHeight + 5) + "px";
4567

46-
updateDownloadLink(result, typename, options);
47-
};
68+
updateDownloadLink(message.result, message.typename, message.options);
69+
} else if (message.type === WorkerMessage.LOAD_FILE_COMPLETE) {
70+
$('large-file-spinner').classList.add('is-invisible');
71+
$('clear-input-button').classList.remove('is-invisible');
72+
} else if (message.type === WorkerMessage.WASM_READY) {
73+
// no action needed
74+
} else {
75+
console.warn("Unknown worker message ", messageEvent);
76+
}
77+
78+
workerReady = true;
79+
if (queued) {
80+
requestCodegen(queued);
81+
queued = undefined;
82+
}
83+
}
4884

49-
$('typename').onkeyup = render;
50-
$('input').onkeyup = render;
51-
$('outputmode').onchange = render;
52-
$('propertynameformat').onchange = render;
53-
$('unwrap').onkeyup = render;
54-
$('extraoptions').onkeyup = render;
85+
$('typename').onkeyup = render;
86+
$('input').onkeyup = render;
87+
$('outputmode').onchange = render;
88+
$('propertynameformat').onchange = render;
89+
$('unwrap').onkeyup = render;
90+
$('extraoptions').onkeyup = render;
5591

56-
$('loadfile').onchange = (event) => {
57-
const file = event.target.files[0];
58-
if (file) {
92+
$('loadfile').onchange = (event) => {
93+
const file = event.target.files[0];
94+
if (file) {
95+
if (file.size > 1000000) {
96+
$('input').value = "";
97+
$('large-file-overlay').classList.remove('is-invisible');
98+
$('large-file-spinner').classList.remove('is-invisible');
99+
$('clear-input-button').classList.add('is-invisible');
100+
const fileSizeMb = (file.size / 1000000).toFixed(2);
101+
$('large-file-message').textContent = `"${file.name}" (${fileSizeMb} MB)`;
102+
worker.postMessage({
103+
type: WorkerMessage.LOAD_FILE,
104+
file
105+
});
106+
workerReady = false;
107+
render();
108+
} else {
59109
const reader = new FileReader();
60110
reader.onload = (fileEvent) => {
61-
const contents = fileEvent.target.result;
62-
if (file.size > 1000000) {
63-
largeInput = contents;
64-
$('input').value = "";
65-
$('large-file-overlay').classList.remove("is-invisible");
66-
const fileSizeMb = (file.size / 1000000).toFixed(2);
67-
$('large-file-message').textContent = `"${file.name}" (${fileSizeMb} MB)`
68-
} else {
69-
$('input').value = contents;
70-
}
111+
$('input').value = fileEvent.target.result;
71112
render();
72113
}
73114
reader.readAsText(file);
74115
}
75116
}
117+
}
76118

77-
$('clear-input-button').onclick = () => {
78-
largeInput = undefined;
79-
$('large-file-overlay').classList.add("is-invisible");
80-
$('input').value = "";
81-
render();
82-
}
83-
119+
$('clear-input-button').onclick = () => {
120+
worker.postMessage({
121+
type: WorkerMessage.CLEAR_FILE
122+
});
123+
$('large-file-overlay').classList.add('is-invisible');
124+
$('input').value = "";
84125
render();
85-
});
126+
}
127+
128+
render();

json_typegen_web/src/polyfill.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

json_typegen_web/src/worker.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {WorkerMessage} from "./WorkerMessage";
2+
3+
let typegenWasm;
4+
let largeFileInput;
5+
6+
import("../../json_typegen_wasm/pkg").then(module => {
7+
typegenWasm = module;
8+
postMessage({
9+
type: WorkerMessage.WASM_READY
10+
});
11+
});
12+
13+
onmessage = messageEvent => {
14+
const message = messageEvent.data;
15+
16+
if (message.type === WorkerMessage.CODEGEN) {
17+
const input = largeFileInput || message.input;
18+
const result = typegenWasm.run(message.typename, input, JSON.stringify(message.options));
19+
postMessage({
20+
type: WorkerMessage.CODEGEN_COMPLETE,
21+
result,
22+
typename: message.typename,
23+
options: message.options,
24+
});
25+
} else if (message.type === WorkerMessage.LOAD_FILE) {
26+
const reader = new FileReader();
27+
reader.onload = (fileEvent) => {
28+
largeFileInput = fileEvent.target.result;
29+
postMessage({
30+
type: WorkerMessage.LOAD_FILE_COMPLETE,
31+
});
32+
}
33+
reader.readAsText(message.file);
34+
} else if (message.type === WorkerMessage.CLEAR_FILE) {
35+
largeFileInput = undefined;
36+
} else {
37+
console.warn("Unknown message to worker", messageEvent);
38+
}
39+
};

0 commit comments

Comments
 (0)