MCPcopy Create free account
hub / github.com/WICG/webpackage / Bundle

Class Bundle

js/bundle/src/decoder.ts:25–189  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

23
24/** This class represents parsed Web Bundle. */
25export class Bundle {
26 version: FormatVersion;
27 private b1PrimaryURL: string | null = null; // only valid in format version b1
28 private sections: { [key: string]: unknown } = {};
29 private responses: { [key: number]: Response } = {}; // Offset-in-responses -> resp
30 private compatAdapter: CompatAdapter;
31
32 constructor(buffer: Uint8Array) {
33 const wbn = asArray(cborg.decode(buffer, { useMaps: true }));
34
35 let peekVersion = bytestringToString(wbn[1]).replace(/\0+$/, '');
36 if (!isApprovedVersion(peekVersion)) {
37 throw new Error('Unsupported web bundle version.');
38 }
39 this.compatAdapter = this.createCompatAdapter(peekVersion);
40
41 if (wbn.length !== this.compatAdapter.wbnLength) {
42 throw new Error(
43 `Wrong toplevel structure ${peekVersion} ${wbn.length} ${this.compatAdapter.wbnLength}`
44 );
45 }
46 const [
47 magic,
48 version,
49 primaryURL, // null in format version b2
50 sectionLengthsCBOR,
51 sections,
52 length,
53 ] = this.compatAdapter.destructureBundle(wbn);
54 if (bytestringToString(magic) !== '🌐📦') {
55 throw new Error('Wrong magic');
56 }
57 const tempVersion = bytestringToString(version).replace(/\0+$/, ''); // Strip off the '\0' paddings.
58 if (!isApprovedVersion(tempVersion)) {
59 throw new Error('Unsupported web bundle version.');
60 }
61 this.version = tempVersion;
62
63 if (primaryURL) {
64 this.b1PrimaryURL = asString(primaryURL);
65 }
66 const sectionLengths = asArray(
67 cborg.decode(asBytestring(sectionLengthsCBOR), { useMaps: true })
68 );
69 const sectionsArray = asArray(sections);
70 if (sectionLengths.length !== sectionsArray.length * 2) {
71 throw new Error(
72 "Number of elements in section-lengths and in sections don't match"
73 );
74 }
75 for (let i = 0; i < sectionsArray.length; i++) {
76 this.sections[asString(sectionLengths[i * 2])] = sectionsArray[i];
77 }
78
79 if (this.sections['critical']) {
80 for (const name of asArray(this.sections['critical'])) {
81 if (!knownSections.includes(asString(name))) {
82 throw new Error(`unknown section ${name} is marked as critical`);

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected