test(qa): W1 baseline and the main-chunk check

scripts/check-main-chunk.mjs (npm run check:main-chunk) finds the main
chunk of a build (the Vite manifest's entry, or the module script
dist/index.html loads), follows its static imports and fails when any of
them carries three or Navara markers; it prints the sizes. Base build:
main chunk 2,850,229 bytes (gzip 881,783), no static imports, clean.

scripts/qa-w1-baseline.mjs records Cesium mode for the W1 layers (flights,
military, local ADS-B, vessels, satellites, launches): counts, five known
objects with positions and screen points, JPEGs (path, size, sha256) at
the global / New York (JFK) / orbit poses, a tracked object's camera pose
after 2 s and what its share link restores. Live sources until the
fixture sources of Task 8.
This commit is contained in:
German Khokhlov committed 2026-10-16 14:49:24 +04:00
1 parent d50eaa28af
commit 27e28373d0
5 files changed
+265 -1

No files matched your search

+80
View File
@@ -0,0 +1,80 @@
// The main chunk of a Vite build and what it must not carry: the Cesium-mode
// page loads the entry chunk and every chunk it imports statically; Navara and
// three belong in the lazy chunk navaraMode.js loads with import(). Pure
// helpers for scripts/check-main-chunk.mjs.
/**
* Markers that only three or Navara code leaves in a bundle (minification
* keeps string literals): three's own warnings name their classes, Navara's
* package names, wasm modules and attribution card classes. Plain engine
* names ('navara' as an engine kind) are not markers.
*/
export const FORBIDDEN_MARKERS = Object.freeze([
Object.freeze({
name: 'three',
pattern: /THREE\.(?:WebGLRenderer|GLTFLoader|EXRLoader|Vector\d)/,
}),
Object.freeze({
name: 'navara',
pattern: /@navaramap\/|navara_wasm|navara-attr-/,
}),
]);
/** The module script a built index.html loads, relative to dist ('assets/…'), or null. */
export function entryFromHtml(html) {
const scripts = String(html).match(/<script\b[^>]*>/g) ?? [];
for (const tag of scripts) {
if (!/\btype\s*=\s*["']module["']/.test(tag)) continue;
const src = tag.match(/\bsrc\s*=\s*["']([^"']+)["']/);
if (src) return src[1].replace(/^\.?\//, '');
}
return null;
}
/** The file of the manifest chunk marked isEntry for index.html (or any entry), or null. */
export function entryFromManifest(manifest) {
const chunks = Object.values(manifest ?? {});
const entry =
chunks.find((chunk) => chunk.isEntry && chunk.src === 'index.html') ??
chunks.find((chunk) => chunk.isEntry);
return entry?.file ?? null;
}
/** Sibling chunks a chunk imports statically (`from"./x.js"`, `import"./x.js"`). */
export function staticImportsOf(code) {
const found = [];
const pattern = /(?:\bfrom|\bimport)\s*(["'])\.\/([^"']+\.js)\1/g;
for (const match of String(code).matchAll(pattern)) {
if (!found.includes(match[2])) found.push(match[2]);
}
return found;
}
/**
* The entry and every chunk reachable from it by static imports, in
* discovery order. `read(file)` returns a chunk's code (file relative to
* dist, in the entry's directory).
*/
export function initialChunks(entry, read) {
const directory = entry.includes('/')
? entry.slice(0, entry.lastIndexOf('/') + 1)
: '';
const seen = [entry];
for (let index = 0; index < seen.length; index++) {
const code = read(seen[index]);
if (code == null) continue;
for (const name of staticImportsOf(code)) {
const file = directory + name;
if (!seen.includes(file)) seen.push(file);
}
}
return seen;
}
/** The names of FORBIDDEN_MARKERS found in code. */
export function forbiddenMarkersIn(code) {
const text = String(code);
return FORBIDDEN_MARKERS.filter(({ pattern }) => pattern.test(text)).map(
({ name }) => name,
);
}
+86
View File
@@ -0,0 +1,86 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import {
FORBIDDEN_MARKERS,
entryFromHtml,
entryFromManifest,
forbiddenMarkersIn,
initialChunks,
staticImportsOf,
} from './mainChunk.js';
test('the entry is the module script the built index.html loads', () => {
const html = `<!doctype html><head>
<script src="/cesium/Cesium.js"></script>
<script type="module" crossorigin src="/assets/index--RGa-KXE.js"></script>
<link rel="modulepreload" crossorigin href="/assets/vendor-Ab.js">
</head>`;
assert.equal(entryFromHtml(html), 'assets/index--RGa-KXE.js');
});
test('an index.html without a module script has no entry', () => {
assert.equal(
entryFromHtml('<script src="/cesium/Cesium.js"></script>'),
null,
);
});
test('the entry of a Vite manifest is the chunk marked isEntry for index.html', () => {
const manifest = {
'src/app/navaraMode.js': {
file: 'assets/navaraMode-B.js',
isDynamicEntry: true,
},
'index.html': {
file: 'assets/index-A.js',
isEntry: true,
src: 'index.html',
imports: ['_vendor-C.js'],
},
'_vendor-C.js': { file: 'assets/vendor-C.js' },
};
assert.equal(entryFromManifest(manifest), 'assets/index-A.js');
});
test('static imports are found, dynamic imports are not', () => {
const code =
'import{a as b}from"./vendor-C.js";import"./side-D.js";' +
'const x=()=>import("./navaraMode-B.js");' +
"import { y } from './spaced-E.js';";
assert.deepEqual(staticImportsOf(code), [
'vendor-C.js',
'side-D.js',
'spaced-E.js',
]);
});
test('the initial chunks are the entry and everything it imports statically', () => {
const files = {
'assets/index-A.js': 'import"./vendor-C.js";import("./lazy-L.js")',
'assets/vendor-C.js': 'import{z}from"./deep-D.js"',
'assets/deep-D.js': 'import"./vendor-C.js"',
'assets/lazy-L.js': 'THREE.WebGLRenderer',
};
assert.deepEqual(
initialChunks('assets/index-A.js', (file) => files[file]),
['assets/index-A.js', 'assets/vendor-C.js', 'assets/deep-D.js'],
);
});
test('three and Navara markers are reported, ordinary engine names are not', () => {
assert.deepEqual(
forbiddenMarkersIn(
'B4=Object.freeze(["cesium","navara"]);FP={cesium:49,navara:80}',
),
[],
);
assert.deepEqual(
forbiddenMarkersIn('console.warn("THREE.WebGLRenderer: Context Lost.")'),
['three'],
);
assert.deepEqual(forbiddenMarkersIn('import "@navaramap/three"'), ['navara']);
assert.deepEqual(forbiddenMarkersIn('new URL("navara_wasm_bg.wasm")'), [
'navara',
]);
assert.ok(FORBIDDEN_MARKERS.length >= 2);
});