buninu-linux 0.11.56 → 0.13.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +7 -4
- package/README.md +7 -6
- package/initramfs/bin/buninu-land +2 -0
- package/initramfs/buninu/apps/jsgotty/gotty.js +4 -2
- package/initramfs/lib/browser-resources.js +11 -0
- package/initramfs/lib/bunterm/images.js +2 -1
- package/initramfs/lib/bunterm/terminal.js +1 -1
- package/package.json +1 -1
- package/scripts/npm-packages.md +7 -7
- package/scripts/stage-npm.js +8 -1
- package/scripts/stage-npm.sh +9 -1
- package/test/bunterm-image-bytes.test.js +55 -0
- package/test/fetch-npm.test.js +1 -1
- package/test/stage-npm.test.js +23 -3
package/NOTICE.md
CHANGED
|
@@ -285,8 +285,8 @@ committed source files, but their contents are redistributed in the image.
|
|
|
285
285
|
| Package | Version | Package license | Project / package page | Installed license and notices (relative to `/usr/lib/node_modules/`) |
|
|
286
286
|
|---|---|---|---|---|
|
|
287
287
|
| `buninu-browser` | 0.2.3 | MIT for the browser's own code; bundled components retain their own terms | https://github.com/jjtseng93/buninu-browser | `buninu-browser/LICENSE`, `THIRD_PARTY_NOTICES.md`, `LICENSES/` and vendor notices within that package |
|
|
288
|
-
| `buninu-land` | 0.1.
|
|
289
|
-
| `@drxiaozhi/casty` | 1.3.
|
|
288
|
+
| `buninu-land` | 0.1.3 | MIT for its own code; bundled components retain their own terms | https://github.com/jjtseng93/buninu-land | `buninu-land/LICENSE`, `THIRD_PARTY_NOTICES.md`, `LICENSES/`, `SOURCES.md`, protocol XML notices and vendor notices |
|
|
289
|
+
| `@drxiaozhi/casty` | 1.3.7 | MIT | https://github.com/jjtseng93/casty | `@drxiaozhi/casty/LICENSE` |
|
|
290
290
|
| `@drxiaozhi/jspulse` | 0.2.1 | LGPL-2.1-or-later, with additional component notices | https://github.com/jjtseng93/jspulse | `@drxiaozhi/jspulse/LICENSE`, `NOTICE.md`, `LICENSES/` and source-file notices within that package |
|
|
291
291
|
| `@drxiaozhi/jspinyin` | 0.1.1 | MIT; hanzipinyin material under the Unlicense | https://www.npmjs.com/package/@drxiaozhi/jspinyin | `@drxiaozhi/jspinyin/LICENSE` and `@drxiaozhi/jspinyin/LICENSE-hanzipinyin.md` |
|
|
292
292
|
|
|
@@ -320,8 +320,11 @@ the source archive or rebuild material merely to reduce the image size.
|
|
|
320
320
|
|
|
321
321
|
### Buninu Land
|
|
322
322
|
|
|
323
|
-
The compositor package
|
|
324
|
-
|
|
323
|
+
The compositor package retains its loader, protocol XML, source provenance,
|
|
324
|
+
patches and license collection. When its CanvasKit WASM is byte-identical to
|
|
325
|
+
the system copy, packing omits the duplicate and the distribution launcher
|
|
326
|
+
creates a relative symlink to `/lib/canvaskit/canvaskit.wasm`. Differing WASM
|
|
327
|
+
versions remain bundled. All associated licenses and notices are retained.
|
|
325
328
|
Retain `THIRD_PARTY_NOTICES.md`, `SOURCES.md`, `vendor-manifest.json`,
|
|
326
329
|
`LICENSES/`, `vendor/canvaskit/LICENSE`, and the notices embedded in the
|
|
327
330
|
Wayland protocol XML files. These cover Buninu Browser-derived code,
|
package/README.md
CHANGED
|
@@ -763,7 +763,8 @@ The `/bin/buninu-land` launcher sets `CASTY_BROWSER` to
|
|
|
763
763
|
`/usr/lib/node_modules/buninu-land/compositor.js` and runs the bundled Casty.
|
|
764
764
|
`--casty` forwards arguments to Casty; `--headless`, `--help`, `--version`,
|
|
765
765
|
README options and reserved native frontends go through the package entry.
|
|
766
|
-
The package's CanvasKit WASM
|
|
766
|
+
The package's CanvasKit WASM shares the system copy when byte-identical;
|
|
767
|
+
its loader and license files are retained.
|
|
767
768
|
|
|
768
769
|
### Archive tools and other examples
|
|
769
770
|
|
|
@@ -1193,11 +1194,11 @@ extracts from it. Bumping a version changes both the file name and the hash, so
|
|
|
1193
1194
|
it always refetches.
|
|
1194
1195
|
|
|
1195
1196
|
The five application packages are pinned separately in
|
|
1196
|
-
`scripts/npm-packages.md`: `buninu-browser@0.2.3`, `buninu-land@0.1.
|
|
1197
|
-
`@drxiaozhi/casty@1.3.
|
|
1197
|
+
`scripts/npm-packages.md`: `buninu-browser@0.2.3`, `buninu-land@0.1.3`,
|
|
1198
|
+
`@drxiaozhi/casty@1.3.7`, `@drxiaozhi/jspulse@0.2.1`, and
|
|
1198
1199
|
`@drxiaozhi/jspinyin@0.1.1`. These were npm's `latest` versions when checked
|
|
1199
1200
|
on 2026-10-11, with buninu-browser updated on 2026-10-12, and
|
|
1200
|
-
casty 1.3.
|
|
1201
|
+
casty 1.3.7 and buninu-land 0.1.3 verified on 2026-10-16;
|
|
1201
1202
|
fetch never resolves `latest` or a version range at runtime.
|
|
1202
1203
|
Each registry tarball was checked against its published SHA-512 integrity
|
|
1203
1204
|
before its SHA-256 was recorded in the shared pins file.
|
|
@@ -1696,9 +1697,9 @@ when redistributing the image.
|
|
|
1696
1697
|
| systemd EFI stub | LGPL-2.1-or-later | image only |
|
|
1697
1698
|
| Bun | MIT, plus the licenses of what it statically links | image only |
|
|
1698
1699
|
| buninu-browser 0.2.3 | MIT for its own code; bundled components have their own licenses | npm download → image |
|
|
1699
|
-
| buninu-land 0.1.
|
|
1700
|
+
| buninu-land 0.1.3 | MIT for its own code; bundled components retain their own licenses and notices | npm download → image |
|
|
1700
1701
|
| wasmpeg / FFmpeg (`@wasmpeg/cpu` 1.0.1, bundled in buninu-browser) | LGPL-2.1-or-later, plus component notices; source archive and rebuild documentation retained | browser package → image |
|
|
1701
|
-
| `@drxiaozhi/casty` 1.3.
|
|
1702
|
+
| `@drxiaozhi/casty` 1.3.7 | MIT | npm download → image |
|
|
1702
1703
|
| `@drxiaozhi/jspulse` 0.2.1 | LGPL-2.1-or-later, plus component notices | npm download → image |
|
|
1703
1704
|
| `@drxiaozhi/jspinyin` 0.1.1 | MIT; hanzipinyin material under the Unlicense | npm download → image |
|
|
1704
1705
|
| CanvasKit 0.41.1 (`initramfs/lib/canvaskit/`, Skia compiled to WebAssembly) | BSD-3-Clause (`LICENSES/BSD-3-Clause-Skia.txt`) | committed |
|
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
// preserve the distribution entry point.
|
|
4
4
|
import { resolve, join } from "node:path";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
|
+
import { ensureLandResources } from "../lib/browser-resources.js";
|
|
6
7
|
|
|
7
8
|
const root = resolve(import.meta.dir, "..");
|
|
8
9
|
const modules = join(root, "usr/lib/node_modules");
|
|
9
10
|
const browser = join(modules, "buninu-land");
|
|
11
|
+
ensureLandResources(browser, root);
|
|
10
12
|
const entry = join(browser, "index.js");
|
|
11
13
|
const { chooseFrontend } = await import(pathToFileURL(entry).href);
|
|
12
14
|
const args = process.argv.slice(2);
|
|
@@ -1001,7 +1001,9 @@ class CursorStateTracker {
|
|
|
1001
1001
|
}
|
|
1002
1002
|
|
|
1003
1003
|
class KittyGraphicsParser {
|
|
1004
|
-
constructor() {
|
|
1004
|
+
constructor({ binaryData = false } = {}) {
|
|
1005
|
+
// Local renderers can consume bytes directly; browser clients retain base64.
|
|
1006
|
+
this.binaryData = binaryData;
|
|
1005
1007
|
this.pending = Buffer.alloc(0);
|
|
1006
1008
|
this.transfers = new Map();
|
|
1007
1009
|
this.images = new Map();
|
|
@@ -1220,7 +1222,7 @@ class KittyGraphicsParser {
|
|
|
1220
1222
|
width: Number.parseInt(existing.control.s || "0", 10),
|
|
1221
1223
|
height: Number.parseInt(existing.control.v || "0", 10),
|
|
1222
1224
|
mime: existing.control.U || existing.control.mime || null,
|
|
1223
|
-
data: binary.toString("base64")
|
|
1225
|
+
data: this.binaryData ? binary : binary.toString("base64")
|
|
1224
1226
|
};
|
|
1225
1227
|
|
|
1226
1228
|
this.images.set(imageId, image);
|
|
@@ -23,3 +23,14 @@ export function ensureBrowserResources(browser, systemRoot = "/") {
|
|
|
23
23
|
catch (error) { if (error.code !== "EEXIST") throw error; }
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
// Land keeps its own loader and notices; only the identical WASM is shared.
|
|
28
|
+
export function ensureLandResources(land, systemRoot = "/") {
|
|
29
|
+
const path = join(land, "vendor/canvaskit/canvaskit.wasm");
|
|
30
|
+
if (lstat(path)) return;
|
|
31
|
+
const target = resolve(systemRoot, "lib/canvaskit/canvaskit.wasm");
|
|
32
|
+
if (!statSync(target).isFile()) throw new Error(`missing compositor resource: ${target}`);
|
|
33
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
34
|
+
try { symlinkSync(relative(dirname(path), target), path); }
|
|
35
|
+
catch (error) { if (error.code !== "EEXIST") throw error; }
|
|
36
|
+
}
|
|
@@ -16,7 +16,8 @@ const number = (value, fallback = 0) => {
|
|
|
16
16
|
// encoded format Skia knows); 24 and 32 are raw RGB / RGBA. Bun.Image, when
|
|
17
17
|
// present, transcodes encodings Skia cannot read on its own.
|
|
18
18
|
export const decodeImage = async (CanvasKit, image) => {
|
|
19
|
-
|
|
19
|
+
// The local parser supplies bytes; retain compatibility with base64 callers.
|
|
20
|
+
const bytes = typeof image.data === "string" ? Buffer.from(image.data, "base64") : image.data;
|
|
20
21
|
if (image.format === 24 || image.format === 32) {
|
|
21
22
|
const { width, height } = image;
|
|
22
23
|
if (!width || !height) throw new Error("raw image without dimensions");
|
|
@@ -70,7 +70,7 @@ export const createSession = ({
|
|
|
70
70
|
term.loadAddon(new UnicodeGraphemesAddon());
|
|
71
71
|
term.unicode.activeVersion = "15-graphemes";
|
|
72
72
|
const images = new ImageStore({ CanvasKit, term, renderer });
|
|
73
|
-
const kitty = new KittyGraphicsParser();
|
|
73
|
+
const kitty = new KittyGraphicsParser({ binaryData: true });
|
|
74
74
|
|
|
75
75
|
const backend = new BunPtyBackend({
|
|
76
76
|
command,
|
package/package.json
CHANGED
package/scripts/npm-packages.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# npm packages
|
|
2
2
|
# Latest versions checked on 2026-10-11; SHA-256 pins verified against registry SHA-512 integrity.
|
|
3
3
|
# buninu-browser updated and verified on 2026-10-12.
|
|
4
|
-
# casty 1.3.
|
|
4
|
+
# casty 1.3.7 and buninu-land 0.1.3 verified on 2026-10-16.
|
|
5
5
|
|
|
6
6
|
"buninu-browser@0.2.3":
|
|
7
7
|
- https://registry.npmjs.org/buninu-browser/-/buninu-browser-0.2.3.tgz
|
|
8
8
|
- sha256:0f7c9cd9df689d7b0900fdf3172851125ebd8aba12bed555be7e091d427146e8
|
|
9
9
|
|
|
10
|
-
"buninu-land@0.1.
|
|
11
|
-
- https://registry.npmjs.org/buninu-land/-/buninu-land-0.1.
|
|
12
|
-
- sha256:
|
|
10
|
+
"buninu-land@0.1.3":
|
|
11
|
+
- https://registry.npmjs.org/buninu-land/-/buninu-land-0.1.3.tgz
|
|
12
|
+
- sha256:b2c94f7fa0f7275ed739f4949d0be3ef45a99bf0b61e63a71ea9d6459f9f1c2e
|
|
13
13
|
|
|
14
|
-
"@drxiaozhi/casty@1.3.
|
|
15
|
-
- https://registry.npmjs.org/@drxiaozhi/casty/-/casty-1.3.
|
|
16
|
-
- sha256:
|
|
14
|
+
"@drxiaozhi/casty@1.3.7":
|
|
15
|
+
- https://registry.npmjs.org/@drxiaozhi/casty/-/casty-1.3.7.tgz
|
|
16
|
+
- sha256:acc0641fb68c00222ba1cd2b7520ba99c269b996e145e82f18466be4d126b811
|
|
17
17
|
|
|
18
18
|
"@drxiaozhi/jspulse@0.2.1":
|
|
19
19
|
- https://registry.npmjs.org/@drxiaozhi/jspulse/-/jspulse-0.2.1.tgz
|
package/scripts/stage-npm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Assemble fetched packages in a disposable pack staging tree, never in the
|
|
2
2
|
// source initramfs. No registry access, dependency resolution or lifecycle code.
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, symlinkSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { join, relative, resolve } from "node:path";
|
|
6
6
|
import { spawnSync } from "node:child_process";
|
|
7
7
|
import { jsRuntime, rootDir, runIfMain } from "./arch.js";
|
|
@@ -34,6 +34,13 @@ export function stageNpm(staging, { packages = npmPackages, downloadsDir = npmDo
|
|
|
34
34
|
"--exclude=package/usr/lib/canvaskit", "--exclude=package/usr/share/fonts");
|
|
35
35
|
const result = spawnSync(runtime, args, { stdio: "inherit" });
|
|
36
36
|
if (result.status !== 0) throw new Error(`npm extraction failed: ${pkg.name}`);
|
|
37
|
+
if (pkg.name === "buninu-land") {
|
|
38
|
+
const wasm = join(destination, "vendor/canvaskit/canvaskit.wasm");
|
|
39
|
+
const shared = join(staging, "lib/canvaskit/canvaskit.wasm");
|
|
40
|
+
const systemWasm = existsSync(shared) ? shared : join(rootDir, "initramfs/lib/canvaskit/canvaskit.wasm");
|
|
41
|
+
// Deduplicate only byte-identical releases; future differing WASM stays bundled.
|
|
42
|
+
if (existsSync(wasm) && existsSync(systemWasm) && readFileSync(wasm).equals(readFileSync(systemWasm))) unlinkSync(wasm);
|
|
43
|
+
}
|
|
37
44
|
const info = JSON.parse(readFileSync(join(destination, "package.json"), "utf8"));
|
|
38
45
|
if (info.name !== pkg.name || info.version !== pkg.version) throw new Error(`npm identity mismatch: ${pkg.name}`);
|
|
39
46
|
const entries = typeof info.bin === "string" ? { [pkg.name.split("/").pop()]: info.bin } : info.bin ?? {};
|
package/scripts/stage-npm.sh
CHANGED
|
@@ -45,7 +45,15 @@ for ((i=0; i<${#names[@]}; i++)); do
|
|
|
45
45
|
extra=()
|
|
46
46
|
[[ "$name" != buninu-browser ]] || extra+=(--exclude=package/usr/lib/canvaskit --exclude=package/usr/share/fonts)
|
|
47
47
|
tar -xf "downloads/npm/${archives[i]}" -C "$destination" --strip-components=1 "${extra[@]}"
|
|
48
|
-
|
|
48
|
+
if [[ "$name" == buninu-land ]]; then
|
|
49
|
+
wasm="$destination/vendor/canvaskit/canvaskit.wasm"
|
|
50
|
+
shared="$staging/lib/canvaskit/canvaskit.wasm"
|
|
51
|
+
[[ -f "$shared" ]] || shared=initramfs/lib/canvaskit/canvaskit.wasm
|
|
52
|
+
if [[ -f "$wasm" && -f "$shared" ]] && cmp -s "$wasm" "$shared"; then
|
|
53
|
+
rm -- "$wasm"
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
# Bin entries of the SHA-pinned packages; no package scripts execute.
|
|
49
57
|
bin=${name##*/}; entry=index.js
|
|
50
58
|
[[ "$name" != @drxiaozhi/jspulse ]] || entry=jspulse.js
|
|
51
59
|
chmod 755 "$destination/$entry"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { expect, test } from 'bun:test';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { mkdtempSync, writeFileSync, rmSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { deflateSync } from 'node:zlib';
|
|
7
|
+
import { decodeImage } from '../initramfs/lib/bunterm/images.js';
|
|
8
|
+
const { KittyGraphicsParser } = createRequire(import.meta.url)('../initramfs/buninu/apps/jsgotty/gotty.js');
|
|
9
|
+
const png = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+aOc8AAAAASUVORK5CYII=', 'base64');
|
|
10
|
+
function parse(parser, control, payload = '') {
|
|
11
|
+
const { events } = parser.consume(Buffer.from(`\x1b_G${control};${payload}\x1b\\`));
|
|
12
|
+
return parser.parsePacket(events[0].packet, { row: 1, col: 1 });
|
|
13
|
+
}
|
|
14
|
+
async function checkDecode(image) {
|
|
15
|
+
const decoded = {};
|
|
16
|
+
let received;
|
|
17
|
+
expect(await decodeImage({ MakeImageFromEncoded(bytes) { received = bytes; return decoded; } }, image)).toBe(decoded);
|
|
18
|
+
// Identity verifies that rendering neither copies nor base64-roundtrips bytes.
|
|
19
|
+
expect(received).toBe(image.data);
|
|
20
|
+
expect(received.equals(png)).toBe(true);
|
|
21
|
+
}
|
|
22
|
+
test('binary parser assembles inline chunks and renderer consumes the same bytes', async () => {
|
|
23
|
+
const parser = new KittyGraphicsParser({ binaryData: true });
|
|
24
|
+
const encoded = png.toString('base64');
|
|
25
|
+
expect(parse(parser, 'a=T,f=100,i=1,m=1', encoded.slice(0, 32))).toBeNull();
|
|
26
|
+
const graphic = parse(parser, 'm=0', encoded.slice(32));
|
|
27
|
+
await checkDecode(graphic.image);
|
|
28
|
+
expect(parse(parser, 'a=p,i=1').image).toBe(graphic.image);
|
|
29
|
+
});
|
|
30
|
+
test('binary file transfer reads bytes without re-encoding; compressed inline also works', async () => {
|
|
31
|
+
const dir = mkdtempSync(join(tmpdir(), 'bunterm-image-bytes-'));
|
|
32
|
+
try {
|
|
33
|
+
const path = join(dir, 'frame.png');
|
|
34
|
+
writeFileSync(path, png);
|
|
35
|
+
const parser = new KittyGraphicsParser({ binaryData: true });
|
|
36
|
+
await checkDecode(parse(parser, 'a=T,t=f,f=100,i=1', Buffer.from(path).toString('base64')).image);
|
|
37
|
+
await checkDecode(parse(parser, 'a=T,f=100,o=z,i=2', deflateSync(png).toString('base64')).image);
|
|
38
|
+
} finally { rmSync(dir, { recursive: true, force: true }); }
|
|
39
|
+
});
|
|
40
|
+
test('default parser and legacy renderer callers retain base64 compatibility', async () => {
|
|
41
|
+
const image = parse(new KittyGraphicsParser(), 'a=T,f=100,i=1', png.toString('base64')).image;
|
|
42
|
+
expect(image.data).toBe(png.toString('base64'));
|
|
43
|
+
let received;
|
|
44
|
+
await decodeImage({ MakeImageFromEncoded(bytes) { received = bytes; return {}; } }, image);
|
|
45
|
+
expect(received.equals(png)).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
test('raw RGBA bytes pass directly to CanvasKit', async () => {
|
|
48
|
+
const pixels = Buffer.from([1, 2, 3, 255]);
|
|
49
|
+
const image = parse(new KittyGraphicsParser({ binaryData: true }), 'a=T,f=32,s=1,v=1,i=3', pixels.toString('base64')).image;
|
|
50
|
+
let received;
|
|
51
|
+
await decodeImage({ ColorType: { RGBA_8888: 1 }, AlphaType: { Unpremul: 1 }, ColorSpace: { SRGB: 1 },
|
|
52
|
+
MakeImage(info, bytes, stride) { received = bytes; expect(stride).toBe(4); return {}; } }, image);
|
|
53
|
+
expect(received).toBe(image.data);
|
|
54
|
+
expect(received.equals(pixels)).toBe(true);
|
|
55
|
+
});
|
package/test/fetch-npm.test.js
CHANGED
|
@@ -23,7 +23,7 @@ const url = `http://127.0.0.1:${server.port}/archive`;
|
|
|
23
23
|
|
|
24
24
|
test("five exact registry pins share an architecture-independent cache", () => {
|
|
25
25
|
expect(npmPackages.map(({ name, version }) => `${name}@${version}`)).toEqual([
|
|
26
|
-
"buninu-browser@0.2.3", "buninu-land@0.1.
|
|
26
|
+
"buninu-browser@0.2.3", "buninu-land@0.1.3", "@drxiaozhi/casty@1.3.7",
|
|
27
27
|
"@drxiaozhi/jspulse@0.2.1", "@drxiaozhi/jspinyin@0.1.1",
|
|
28
28
|
]);
|
|
29
29
|
expect(basename(npmDownloadsDir)).toBe("npm");
|
package/test/stage-npm.test.js
CHANGED
|
@@ -6,7 +6,7 @@ import { join, resolve } from "node:path";
|
|
|
6
6
|
import { spawnSync } from "node:child_process";
|
|
7
7
|
import { stageNpm } from "../scripts/stage-npm.js";
|
|
8
8
|
import { npmPackages, npmDownloadsDir } from "../scripts/fetch-npm.js";
|
|
9
|
-
import { ensureBrowserResources } from "../initramfs/lib/browser-resources.js";
|
|
9
|
+
import { ensureBrowserResources, ensureLandResources } from "../initramfs/lib/browser-resources.js";
|
|
10
10
|
|
|
11
11
|
const work = mkdtempSync(join(tmpdir(), "buninu-stage-npm-"));
|
|
12
12
|
afterAll(() => rmSync(work, { recursive: true, force: true }));
|
|
@@ -26,6 +26,7 @@ async function fixture() {
|
|
|
26
26
|
"package/usr/lib/canvaskit/data": "only browser excludes this",
|
|
27
27
|
"package/usr/share/fonts/data": "only browser excludes this",
|
|
28
28
|
"package/lib/data": "keep data",
|
|
29
|
+
"package/vendor/canvaskit/canvaskit.wasm": "different wasm must be retained",
|
|
29
30
|
}, { compress: "gzip" }).bytes();
|
|
30
31
|
const archive = bin + ".tgz";
|
|
31
32
|
writeFileSync(join(downloadsDir, archive), data);
|
|
@@ -47,6 +48,7 @@ test("stages standard scoped layout, manifest, bins and browser-only exclusion",
|
|
|
47
48
|
expect(readFileSync(join(dir, "usr/README.md"), "utf8")).toBe("keep resource documentation");
|
|
48
49
|
expect(existsSync(join(dir, "usr/lib/canvaskit"))).toBe(pkg.name !== "buninu-browser");
|
|
49
50
|
expect(existsSync(join(dir, "usr/share/fonts"))).toBe(pkg.name !== "buninu-browser");
|
|
51
|
+
expect(readFileSync(join(dir, "vendor/canvaskit/canvaskit.wasm"), "utf8")).toBe("different wasm must be retained");
|
|
50
52
|
expect(statSync(join(dir, "index.js")).mode & 0o111).toBe(0o111);
|
|
51
53
|
expect(readlinkSync(join(lib, "node_modules/.bin", pkg.name.split("/").pop())))
|
|
52
54
|
.toBe(`../${pkg.name}/index.js`);
|
|
@@ -109,6 +111,8 @@ test("land launcher selects bundled casty and preserves package frontend dispatc
|
|
|
109
111
|
stageNpm(root, cfg);
|
|
110
112
|
const land = join(root, "usr/lib/node_modules/buninu-land");
|
|
111
113
|
mkdirSync(join(root, "bin"));
|
|
114
|
+
mkdirSync(join(root, "lib"), { recursive: true });
|
|
115
|
+
copyFileSync(new URL("../initramfs/lib/browser-resources.js", import.meta.url), join(root, "lib/browser-resources.js"));
|
|
112
116
|
const launcher = join(root, "bin/buninu-land");
|
|
113
117
|
copyFileSync(new URL("../initramfs/bin/buninu-land", import.meta.url), launcher);
|
|
114
118
|
writeFileSync(join(land, "index.js"), `
|
|
@@ -144,6 +148,7 @@ test.skipIf(!npmPackages.every(pkg => existsSync(join(npmDownloadsDir, pkg.archi
|
|
|
144
148
|
expect(result.status).toBe(0);
|
|
145
149
|
expect(readFileSync(join(shell, "usr/lib/package.json"), "utf8")).toBe(readFileSync(join(js, "usr/lib/package.json"), "utf8"));
|
|
146
150
|
for (const root of [js, shell]) {
|
|
151
|
+
expect(existsSync(join(root, "usr/lib/node_modules/buninu-land/vendor/canvaskit/canvaskit.wasm"))).toBe(false);
|
|
147
152
|
expect(existsSync(join(root, "usr/lib/node_modules/buninu-browser/usr/README.md"))).toBe(true);
|
|
148
153
|
expect(existsSync(join(root, "usr/lib/node_modules/buninu-browser/usr/lib/canvaskit"))).toBe(false);
|
|
149
154
|
expect(existsSync(join(root, "usr/lib/node_modules/buninu-browser/usr/share/fonts"))).toBe(false);
|
|
@@ -164,8 +169,23 @@ test.skipIf(!npmPackages.every(pkg => existsSync(join(npmDownloadsDir, pkg.archi
|
|
|
164
169
|
for (const args of [["--help"], ["--headless", "--help"], ["--version"]]) {
|
|
165
170
|
const landHelp = spawnSync(process.execPath, [join(js, "bin/buninu-land"), ...args], { encoding: "utf8", timeout: 15000 });
|
|
166
171
|
expect(landHelp.status).toBe(0);
|
|
167
|
-
expect(landHelp.stdout).toContain(args[0] === "--version" ? "0.1.
|
|
172
|
+
expect(landHelp.stdout).toContain(args[0] === "--version" ? "0.1.3" : args[0] === "--headless" ? "Wayland compositor" : "Usage");
|
|
168
173
|
}
|
|
169
|
-
|
|
174
|
+
const landWasm = join(js, "usr/lib/node_modules/buninu-land/vendor/canvaskit/canvaskit.wasm");
|
|
175
|
+
expect(readlinkSync(landWasm).startsWith("/")).toBe(false);
|
|
176
|
+
expect(readFileSync(landWasm).equals(readFileSync(join(js, "lib/canvaskit/canvaskit.wasm")))).toBe(true);
|
|
170
177
|
expect(existsSync(join(js, "usr/lib/node_modules/buninu-land/LICENSES/hyprland.txt"))).toBe(true);
|
|
171
178
|
}, 30000);
|
|
179
|
+
|
|
180
|
+
test("land resource link is relative, repeatable, and preserves a package-owned WASM", () => {
|
|
181
|
+
const root = fresh(), land = join(root, "usr/lib/node_modules/buninu-land");
|
|
182
|
+
mkdirSync(join(root, "lib/canvaskit"), { recursive: true });
|
|
183
|
+
writeFileSync(join(root, "lib/canvaskit/canvaskit.wasm"), "shared");
|
|
184
|
+
ensureLandResources(land, root); ensureLandResources(land, root);
|
|
185
|
+
const wasm = join(land, "vendor/canvaskit/canvaskit.wasm");
|
|
186
|
+
expect(readlinkSync(wasm).startsWith("/")).toBe(false);
|
|
187
|
+
expect(readFileSync(wasm, "utf8")).toBe("shared");
|
|
188
|
+
rmSync(wasm); writeFileSync(wasm, "package-owned");
|
|
189
|
+
ensureLandResources(land, root);
|
|
190
|
+
expect(readFileSync(wasm, "utf8")).toBe("package-owned");
|
|
191
|
+
});
|