import assert from "node:assert/strict"; import { fileURLToPath } from "node:url"; import { test } from "node:test"; import { build } from "esbuild"; const compiled = await build({ entryPoints: [fileURLToPath(new URL("../src/player/python.ts", import.meta.url))], bundle: true, write: false, format: "esm", platform: "node", logLevel: "silent" }); const { Python, PyDict } = await import(`data:text/javascript;base64,${Buffer.from(compiled.outputFiles[0].text).toString("base64")}`); const c = (v) => ({ k: "const", v }); const attr = (o, a) => ({ k: "attr", o, a }); const sub = (o, i) => ({ k: "sub", o, i: c(i) }); function runtime() { const store = { fn: Math.max, values: [1, 2], config: {}, data: new PyDict() }; const py = new Python({ get: (n) => store[n], has: (n) => n in store, set: (n, v) => { store[n] = v; }, del: (n) => { delete store[n]; } }); return { py, store }; } test("PGVN cannot obtain native constructors through attributes or subscripts", () => { const { py } = runtime(); for (const value of ["text", [], {}, Math.max]) { for (const key of ["constructor", "__proto__", "prototype", "__defineGetter__"]) { assert.equal(py.eval(attr(c(value), key)), null); assert.equal(py.eval(sub(c(value), key)), null); } } assert.equal(py.eval({ k: "name", id: "constructor" }), null); assert.equal(py.eval(attr({ k: "name", id: "fn" }, "call")), null); const coercedKey = { toString: () => "constructor" }; assert.equal(py.eval(sub(c({}), coercedKey)), null); assert.equal(py.eval(attr(c({}), coercedKey)), null); }); test("PGVN cannot pollute prototypes via assignment", () => { const { py, store } = runtime(); for (const target of [attr({ k: "name", id: "config" }, "__proto__"), sub({ k: "name", id: "config" }, "constructor"), { k: "name", id: "__proto__" }]) { assert.throws(() => py.bind(target, { injected: true }), /недоступ/); } assert.equal(Object.getPrototypeOf(store.config), Object.prototype); assert.equal({}.injected, undefined); }); test("ordinary PGVN list methods, dictionary keys and builtin calls still work", () => { const { py, store } = runtime(); const name = (id) => ({ k: "name", id }); const call = (f, ...a) => ({ k: "call", f, a: a.map(c), kw: {} }); py.eval(call(attr(name("values"), "append"), 3)); assert.deepEqual(store.values, [1, 2, 3]); assert.equal(py.eval(sub(name("values"), -1)), 3); assert.equal(py.eval(call(name("fn"), 4, 9)), 9); py.bind(sub(name("data"), "constructor"), "ordinary dictionary value"); assert.equal(py.eval(sub(name("data"), "constructor")), "ordinary dictionary value"); assert.throws(() => py.eval(sub(name("values"), "map")), /целым/); });