Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
99 lines
3.2 KiB
JavaScript
99 lines
3.2 KiB
JavaScript
"use strict";
|
|
|
|
const assert = require("node:assert/strict");
|
|
const test = require("node:test");
|
|
|
|
const {
|
|
browserRasterizeExpression,
|
|
createIsolatedContributionIconRasterizer,
|
|
} = require("./contributionIconRasterizer.cjs");
|
|
|
|
test("viewBox-only SVG icons receive an explicit isolated raster viewport", () => {
|
|
const expression = browserRasterizeExpression({
|
|
source: Buffer.from('<svg viewBox="0 0 32 16"><path d="M0 0h1"/></svg>').toString("base64"),
|
|
mimeType: "image/svg+xml",
|
|
width: 32,
|
|
height: 16,
|
|
maxEdge: 64,
|
|
});
|
|
assert.match(expression, /DOMParser/u);
|
|
assert.match(expression, /setAttribute\("width"/u);
|
|
assert.match(expression, /setAttribute\("height"/u);
|
|
});
|
|
|
|
test("contribution icons rasterize in a disposable sandboxed network-denied window", async () => {
|
|
let createdOptions;
|
|
let destroyed = false;
|
|
let requestFilter;
|
|
let expression = "";
|
|
class BrowserWindowStub {
|
|
constructor(options) {
|
|
createdOptions = options;
|
|
this.webContents = {
|
|
session: {
|
|
webRequest: {
|
|
onBeforeRequest(filter, listener) { requestFilter = { filter, listener }; },
|
|
},
|
|
},
|
|
async executeJavaScript(nextExpression) {
|
|
expression = nextExpression;
|
|
return `data:image/png;base64,${Buffer.from("bounded-png").toString("base64")}`;
|
|
},
|
|
};
|
|
}
|
|
async loadURL(url) { assert.match(url, /^data:text\/html/); }
|
|
removeMenu() {}
|
|
destroy() { destroyed = true; }
|
|
}
|
|
const rasterize = createIsolatedContributionIconRasterizer({
|
|
BrowserWindow: BrowserWindowStub,
|
|
randomUUID: () => "fixed",
|
|
});
|
|
|
|
assert.deepEqual(await rasterize({
|
|
body: Buffer.from("untrusted"),
|
|
mimeType: "image/png",
|
|
width: 32,
|
|
height: 16,
|
|
maxEdge: 64,
|
|
}), Buffer.from("bounded-png"));
|
|
assert.equal(createdOptions.show, false);
|
|
assert.equal(createdOptions.webPreferences.partition, "plugin-icon-raster-fixed");
|
|
assert.equal(createdOptions.webPreferences.sandbox, true);
|
|
assert.equal(createdOptions.webPreferences.nodeIntegration, false);
|
|
assert.equal(createdOptions.webPreferences.contextIsolation, true);
|
|
assert.equal(createdOptions.webPreferences.spellcheck, false);
|
|
assert.deepEqual(requestFilter.filter.urls, ["http://*/*", "https://*/*", "file://*/*", "ftp://*/*"]);
|
|
let blocked;
|
|
requestFilter.listener({}, (decision) => { blocked = decision; });
|
|
assert.deepEqual(blocked, { cancel: true });
|
|
assert.match(expression, /dW50cnVzdGVk/);
|
|
assert.equal(destroyed, true);
|
|
});
|
|
|
|
test("timed-out contribution icon rasterizers always destroy their isolated window", async () => {
|
|
let destroyed = false;
|
|
class BrowserWindowStub {
|
|
constructor() {
|
|
this.webContents = {
|
|
session: { webRequest: { onBeforeRequest() {} } },
|
|
executeJavaScript: () => new Promise(() => {}),
|
|
};
|
|
}
|
|
async loadURL() {}
|
|
destroy() { destroyed = true; }
|
|
}
|
|
const rasterize = createIsolatedContributionIconRasterizer({
|
|
BrowserWindow: BrowserWindowStub,
|
|
timeoutMs: 5,
|
|
});
|
|
await assert.rejects(rasterize({
|
|
body: Buffer.from("untrusted"),
|
|
mimeType: "image/png",
|
|
width: 1,
|
|
height: 1,
|
|
maxEdge: 64,
|
|
}), /timed out/);
|
|
assert.equal(destroyed, true);
|
|
});
|