Visualizer work
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

101 lines
3.3 KiB

// In src/parser.worker.js
// Import the lightweight and worker-safe Clarinet library
importScripts('../vendor/clarinet.min.js'); //importing the clarinet.min.js (ver. 0.12.5) from the vendor folder.
self.onmessage = async function(event) {
const file = event.data.file;
if (!file) {
self.postMessage({ type: 'error', message: 'No file received in worker.' });
return;
}
try {
const fileSize = file.size;
let bytesRead = 0;
let lastReportedProgress = -1;
const parser = clarinet.parser();
// --- START: New Robust Parsing Logic ---
// This logic correctly builds a complete object tree from the stream.
let result; // This will hold the final, fully parsed object.
const stack = []; // A stack to keep track of current object/array.
let key = null; // The current object key.
const getParent = () => stack.length > 0 ? stack[stack.length - 1] : null;
const assign = (value) => {
const parent = getParent();
if (parent) {
if (Array.isArray(parent)) {
parent.push(value);
} else {
parent[key] = value;
}
} else {
result = value;
}
};
parser.onopenobject = (k) => {
key = k;
const newObject = {};
assign(newObject);
stack.push(newObject);
};
parser.onkey = (k) => {
key = k;
};
parser.onopenarray = () => {
const newArray = [];
assign(newArray);
stack.push(newArray);
};
parser.onvalue = (value) => {
assign(value);
};
parser.oncloseobject = () => stack.pop();
parser.onclosearray = () => stack.pop();
// --- END: New Robust Parsing Logic ---
parser.onend = () => {
self.postMessage({ type: 'progress', percent: 100 });
// Send the fully constructed 'result' object back to the main thread.
self.postMessage({ type: 'complete', data: result });
};
parser.onerror = (err) => {
console.error("Worker: Clarinet parsing error:", err);
self.postMessage({ type: 'error', message: 'Failed to parse JSON structure.' });
};
// --- Stream Reading Logic (this part remains the same) ---
const stream = file.stream();
const reader = stream.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) {
parser.close();
break;
}
bytesRead += value.length;
const percent = Math.round((bytesRead / fileSize) * 100);
if (percent > lastReportedProgress) {
self.postMessage({ type: 'progress', percent: percent });
lastReportedProgress = percent;
}
parser.write(decoder.decode(value, { stream: true }));
}
} catch (error) {
console.error("Worker: An error occurred during streaming:", error);
self.postMessage({ type: 'error', message: 'Failed to read file in worker.' });
}
};