- R7RS parameter primitives (make-parameter, parameter?, parameterize support) - VM closure get_val introspection (vm-code, vm-upvalues, vm-name, vm-globals) - Lazy list caching on vm_code for transpiled VM performance - VM import suspension: check_io_suspension + resume_module for browser lazy loading - 23 new R7RS tests (parameter-basic, parameterize-basic, syntax-rules-basic) - Playwright bytecode-loading spec + WASM rebuild Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
111 lines
3.6 KiB
JavaScript
111 lines
3.6 KiB
JavaScript
// Bytecode on-demand loading tests
|
|
// Verifies .sxbc modules are only downloaded when needed, not all at boot.
|
|
|
|
const { test, expect } = require('playwright/test');
|
|
const { BASE_URL, waitForSxReady } = require('./helpers');
|
|
|
|
test.describe('Bytecode Loading', () => {
|
|
|
|
test('manifest is fetched at boot', async ({ page }) => {
|
|
const manifestReqs = [];
|
|
page.on('request', req => {
|
|
if (req.url().includes('module-manifest.json')) manifestReqs.push(req.url());
|
|
});
|
|
|
|
await page.goto(BASE_URL + '/sx/', { waitUntil: 'domcontentloaded' });
|
|
await waitForSxReady(page);
|
|
|
|
expect(manifestReqs.length).toBe(1);
|
|
});
|
|
|
|
test('boot loads only manifest deps, not all modules', async ({ page }) => {
|
|
const sxbcReqs = [];
|
|
page.on('request', req => {
|
|
const url = req.url();
|
|
if (url.includes('.sxbc') && !url.includes('manifest')) {
|
|
const name = url.split('/').pop().split('?')[0].replace('.sxbc', '');
|
|
sxbcReqs.push(name);
|
|
}
|
|
});
|
|
|
|
await page.goto(BASE_URL + '/sx/', { waitUntil: 'domcontentloaded' });
|
|
await waitForSxReady(page);
|
|
|
|
// Boot loads manifest deps for hydration — NOT all 26
|
|
// 13 boot deps, 13 deferred (compiler, vm, harness, etc.)
|
|
expect(sxbcReqs.length).toBeLessThanOrEqual(14);
|
|
expect(sxbcReqs.length).toBeGreaterThan(5);
|
|
|
|
// Boot-critical modules present
|
|
expect(sxbcReqs).toContain('boot');
|
|
expect(sxbcReqs).toContain('dom');
|
|
|
|
// Dev/test modules NOT loaded on homepage
|
|
const nonBootModules = ['compiler', 'vm', 'harness', 'harness-web', 'harness-reactive'];
|
|
for (const mod of nonBootModules) {
|
|
expect(sxbcReqs).not.toContain(mod);
|
|
}
|
|
});
|
|
|
|
test('no .sx fallback requests when bytecode exists', async ({ page }) => {
|
|
const sxFallbackReqs = [];
|
|
page.on('request', req => {
|
|
const url = req.url();
|
|
// .sx source fallback (not .sxbc) in the wasm directory
|
|
if (url.match(/\/static\/wasm\/sx\/[^/]+\.sx(\?|$)/) && !url.includes('.sxbc')) {
|
|
sxFallbackReqs.push(url);
|
|
}
|
|
});
|
|
|
|
await page.goto(BASE_URL + '/sx/', { waitUntil: 'domcontentloaded' });
|
|
await waitForSxReady(page);
|
|
|
|
expect(sxFallbackReqs).toEqual([]);
|
|
});
|
|
|
|
test('all .sxbc requests use cache-busting hash', async ({ page }) => {
|
|
const sxbcUrls = [];
|
|
page.on('request', req => {
|
|
if (req.url().includes('.sxbc')) sxbcUrls.push(req.url());
|
|
});
|
|
|
|
await page.goto(BASE_URL + '/sx/', { waitUntil: 'domcontentloaded' });
|
|
await waitForSxReady(page);
|
|
|
|
// Every .sxbc request should have a ?v= cache-buster
|
|
for (const url of sxbcUrls) {
|
|
expect(url).toMatch(/[?&]v=/);
|
|
}
|
|
|
|
// All should share the same hash (combined hash from data-sxbc-hash)
|
|
const hashes = sxbcUrls.map(u => new URL(u).searchParams.get('v')).filter(Boolean);
|
|
const unique = [...new Set(hashes)];
|
|
expect(unique.length).toBe(1);
|
|
});
|
|
|
|
test('SPA navigation does not re-fetch boot modules', async ({ page }) => {
|
|
await page.goto(BASE_URL + '/sx/', { waitUntil: 'domcontentloaded' });
|
|
await waitForSxReady(page);
|
|
|
|
// Start tracking requests AFTER boot
|
|
const postBootSxbc = [];
|
|
page.on('request', req => {
|
|
if (req.url().includes('.sxbc')) {
|
|
const name = req.url().split('/').pop().split('?')[0].replace('.sxbc', '');
|
|
postBootSxbc.push(name);
|
|
}
|
|
});
|
|
|
|
// Navigate to a different page via SPA
|
|
await page.click('a[href*="geography"]');
|
|
await page.waitForTimeout(2000);
|
|
|
|
// Boot modules should NOT be re-fetched
|
|
const bootModules = ['dom', 'signals', 'boot', 'engine', 'orchestration'];
|
|
for (const mod of bootModules) {
|
|
expect(postBootSxbc).not.toContain(mod);
|
|
}
|
|
});
|
|
|
|
});
|