| … | … | @@ -455,3 +455,51 @@ test('a bundle whose header cannot be read is UNKNOWN, not empty', async (t) => |
| 455 | 455 | t.is(marker.demands, null, 'unknown') |
| 456 | 456 | t.ok(store.hasTree(treeHash), 'and the bundle is still staged — an unreadable header is not a bad bundle') |
| 457 | 457 | }) |
| 458 | |
| 459 | // ── the seam ────────────────────────────────────────────────────────────────────────────────────── |
| 460 | // |
| 461 | // ⛔ TWO HALVES THAT NEVER SPEAK. bundleStore WRITES the addon directory, inside the worklet, from the |
| 462 | // marker. lib/bootstrap.js DERIVES it, inside the staged bundle, from import.meta.url — with no marker, |
| 463 | // no shell and no argument. They agree only by convention, and a convention held in two places is one |
| 464 | // rename away from a phone that stages addons nothing ever loads: silent, and indistinguishable from a |
| 465 | // release that simply had none. |
| 466 | // |
| 467 | // So it is asserted against the real store output rather than against a restatement of the rule. |
| 468 | import { addonsDirFor } from '../lib/host/loader-core.js' |
| 469 | |
| 470 | test('the directory the store writes is the one the bundle derives', async (t) => { |
| 471 | const dir = tmpdir('seam') |
| 472 | const { entries, treeHash, sub, subHash } = treeWithAddons(BUNDLE, ADDONS) |
| 473 | const contents = { [hashOf(BUNDLE)]: BUNDLE } |
| 474 | for (const [, bytes] of Object.entries(ADDONS)) contents[hashOf(bytes)] = bytes |
| 475 | |
| 476 | const store = bundleStore({ dir }) |
| 477 | await installTree(store, treeHash, treeFetcher({ trees: { [treeHash]: entries, [subHash]: sub }, contents })) |
| 478 | |
| 479 | // What the shell hands bare-kit, and therefore what import.meta.url is rooted at inside the bundle. |
| 480 | const staged = store.pathFor(treeHash) |
| 481 | const derived = addonsDirFor('file://' + staged + '/lib/bootstrap.js') |
| 482 | |
| 483 | t.is(derived, store.addonsFor(treeHash), 'store and bundle agree on the path') |
| 484 | for (const name of Object.keys(ADDONS)) { |
| 485 | t.ok(fs.existsSync(path.join(derived, name)), name + ' is where the bootstrap will look') |
| 486 | } |
| 487 | }) |
| 488 | |
| 489 | test('the seam survives the bundle being renamed by content hash', async (t) => { |
| 490 | // The store names the staged file by CONTENT hash and the directory after that file, so the pairing |
| 491 | // holds whatever the hash turns out to be — which is the property that lets the bundle derive it |
| 492 | // without being told the tree hash it was published under. |
| 493 | const dir = tmpdir('seam2') |
| 494 | const other = Buffer.from('#!/bare\n// a different bundle entirely\n') |
| 495 | const { entries, treeHash, sub, subHash } = treeWithAddons(other, ADDONS) |
| 496 | const contents = { [hashOf(other)]: other } |
| 497 | for (const [, bytes] of Object.entries(ADDONS)) contents[hashOf(bytes)] = bytes |
| 498 | |
| 499 | const store = bundleStore({ dir }) |
| 500 | await installTree(store, treeHash, treeFetcher({ trees: { [treeHash]: entries, [subHash]: sub }, contents })) |
| 501 | |
| 502 | const staged = store.pathFor(treeHash) |
| 503 | t.ok(staged.endsWith(hashOf(other) + '.bundle'), 'named by content hash') |
| 504 | t.is(addonsDirFor('file://' + staged + '/x.js'), store.addonsFor(treeHash), 'and the pairing still holds') |
| 505 | }) |