add option to compress/uglify boot image. fix indexeddb reload race

This commit is contained in:
Stewart Allen 2025-10-12 00:20:13 -04:00
commit 09a30911e8
2 changed files with 46 additions and 11 deletions

View file

@ -1,8 +1,10 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import uglify from 'uglify-js';
import { Buffer } from 'buffer'; import { Buffer } from 'buffer';
const cfg = JSON.parse(fs.readFileSync(process.argv[2] || './bundle.config.json', 'utf8')); const cfg = JSON.parse(fs.readFileSync(process.argv[2] || './bundle.config.json', 'utf8'));
const compress = process.env.UGLIFY ? true : false
// --- recursive directory walker (follows symlinks safely) --- // --- recursive directory walker (follows symlinks safely) ---
function* walk(dir, seen = new Set()) { function* walk(dir, seen = new Set()) {
@ -37,12 +39,36 @@ for (const input of cfg.inputs) {
const dataParts = []; const dataParts = [];
const entryMeta = []; const entryMeta = [];
let offset = 0; let offset = 0;
let cache = new Map();
for (const { file, virt } of entries) { for (const { file, virt } of entries) {
const data = fs.readFileSync(file); let record = cache.get(file);
entryMeta.push({ virt, offset, length: data.length }); if (record) {
dataParts.push(data); // console.log({ dup: file });
offset += data.length; entryMeta.push({ ...record, virt });
} else {
let data = fs.readFileSync(file);
if (compress && file.endsWith("js")) {
console.log('compress', file);
data = uglify.minify(data.toString(), {
compress: {
merge_vars: false,
unused: false
}
});
// console.log({ to: typeof(data), data });
if (!data.code) {
console.log({ skip: file });
continue;
}
data = Buffer.from(data.code);
}
record = { virt, offset, length: data.length };
cache.set(file, record);
entryMeta.push(record);
dataParts.push(data);
offset += data.length;
}
} }
// temporary header without offsets to measure total size // temporary header without offsets to measure total size
@ -66,7 +92,7 @@ for (const { virt, offset, length } of entryMeta) {
const offb = Buffer.alloc(4); offb.writeUInt32LE(headerSize + offset); const offb = Buffer.alloc(4); offb.writeUInt32LE(headerSize + offset);
const lenb = Buffer.alloc(4); lenb.writeUInt32LE(length); const lenb = Buffer.alloc(4); lenb.writeUInt32LE(length);
headerParts.push(nlen, name, offb, lenb); headerParts.push(nlen, name, offb, lenb);
console.log(virt); // console.log(virt);
} }
const header = Buffer.concat([count, ...headerParts]); const header = Buffer.concat([count, ...headerParts]);

View file

@ -168,7 +168,7 @@ SP.init = function(options = {}) {
request = IDB.open(name, this.version); request = IDB.open(name, this.version);
request.onupgradeneeded = function(event) { request.onupgradeneeded = function(event) {
let db = storage.db = request.result; let db = request.result;
let current = [...db.objectStoreNames]; let current = [...db.objectStoreNames];
let stores = storage.stores; let stores = storage.stores;
// add missing stores // add missing stores
@ -184,16 +184,16 @@ SP.init = function(options = {}) {
// remove obsolete stores // remove obsolete stores
for (let curr of current) { for (let curr of current) {
if (stores.indexOf(curr) < 0) { if (stores.indexOf(curr) < 0) {
storage.db.deleteObjectStore(curr); db.deleteObjectStore(curr);
console.log({index_dropped: curr}); console.log({index_dropped: curr});
} }
} }
event.target.transaction.oncomplete = function(event) { // allow transactions
storage.runQueue(); storage.db = db;
};
}; };
request.onsuccess = function(event) { request.onsuccess = function(event) {
console.log('IDB open succeeded');
storage.current = storage.stores[0]; storage.current = storage.stores[0];
storage.db = request.result; storage.db = request.result;
storage.runQueue(); storage.runQueue();
@ -217,6 +217,7 @@ SP.runQueue = function() {
let i = 0, q = this.queue, e; let i = 0, q = this.queue, e;
while (i < q.length) { while (i < q.length) {
e = q[i++]; e = q[i++];
// console.log('runQ', i, ...e);
switch (e.shift()) { switch (e.shift()) {
case 'iterate': this.iterate(...e); break; case 'iterate': this.iterate(...e); break;
case 'keys': this.keys(...e); break; case 'keys': this.keys(...e); break;
@ -252,7 +253,11 @@ SP.put = function(key, value, callback, store = this.current) {
req.onerror = function(event) { callback(false) }; req.onerror = function(event) { callback(false) };
} }
} catch (e) { } catch (e) {
console.log(e); if (e.name === 'InvalidStateError') {
console.log({ putRetry: key });
return this.queue.push(['put', key, value, callback, store]);
}
console.log(e.name, e);
if (callback) callback(false); if (callback) callback(false);
} }
}; };
@ -275,6 +280,10 @@ SP.get = function(key, callback, store = this.current) {
req.onerror = function(event) { callback(null) }; req.onerror = function(event) { callback(null) };
} }
} catch (e) { } catch (e) {
if (e.name === 'InvalidStateError') {
console.log({ getRetry: key });
return this.queue.push(['get', key, callback, store]);
}
console.log(e); console.log(e);
if (callback) callback(null); if (callback) callback(null);
} }