Merge remote-tracking branch 'origin/main' into codex/audit-continuation-20261020-refresh20
This commit is contained in:
commit
c4007f4542
4 files changed
+142
-409
No files matched your search
@@ -114,6 +114,25 @@ const scenario = browserScenarioSchema.parse({
|
||||
},
|
||||
});
|
||||
|
||||
const deferred = () => {
|
||||
let resolve: () => void = () => undefined;
|
||||
const promise = new Promise<void>((complete) => {
|
||||
resolve = complete;
|
||||
});
|
||||
return { promise, resolve };
|
||||
};
|
||||
|
||||
const connectedScenario = (serviceWorkers: "block" | "allow") =>
|
||||
browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: serviceWorkers },
|
||||
});
|
||||
|
||||
const fixture = () => {
|
||||
const page = Object.assign(new EventEmitter(), {
|
||||
url: () => "about:blank",
|
||||
@@ -275,15 +294,7 @@ it("stops attached navigation when cancellation precedes the first close", async
|
||||
|
||||
it("assigns attached navigation stopping to the storage owner once", async () => {
|
||||
const { cleanup, storage } = fixture();
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
const session = await PlaywrightScenarioSession.open(attached, {}, {});
|
||||
|
||||
await expect(session.close(true)).resolves.toBe("disconnected-external");
|
||||
@@ -301,15 +312,7 @@ it("transfers attached navigation stopping after storage cleanup fails", async (
|
||||
const storageFailure = new Error("storage stop unconfirmed");
|
||||
storage?.close.mockRejectedValueOnce(storageFailure);
|
||||
const policyFailure = new Error("policy stop unconfirmed");
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
const session = await PlaywrightScenarioSession.open(attached, {}, {});
|
||||
mocks.policySend.mockRejectedValueOnce(policyFailure);
|
||||
|
||||
@@ -332,15 +335,7 @@ it("transfers a late stop request after storage has already released", async ()
|
||||
const { cleanup, storage } = fixture();
|
||||
const cancellation = new AbortController();
|
||||
storage?.close.mockResolvedValue({ loadingStopped: false });
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
const session = await PlaywrightScenarioSession.open(
|
||||
attached,
|
||||
{},
|
||||
@@ -380,32 +375,16 @@ it.each(["pending", "settled"] as const)(
|
||||
const { cleanup, page, storage } = fixture();
|
||||
const cancellation = new AbortController();
|
||||
storage?.close.mockResolvedValue({ loadingStopped: false });
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
const session = await PlaywrightScenarioSession.open(
|
||||
attached,
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
let finishRestoration: () => void = () => undefined;
|
||||
let restorationStarted: () => void = () => undefined;
|
||||
const held = new Promise<void>((resolve) => {
|
||||
finishRestoration = resolve;
|
||||
});
|
||||
const started = new Promise<void>((resolve) => {
|
||||
restorationStarted = resolve;
|
||||
});
|
||||
let signalTransportClosed: () => void = () => undefined;
|
||||
const transportClosed = new Promise<void>((resolve) => {
|
||||
signalTransportClosed = resolve;
|
||||
});
|
||||
const { promise: held, resolve: finishRestoration } = deferred();
|
||||
const { promise: started, resolve: restorationStarted } = deferred();
|
||||
const { promise: transportClosed, resolve: signalTransportClosed } =
|
||||
deferred();
|
||||
mocks.policyTransportClose.mockImplementation(async () => {
|
||||
signalTransportClosed();
|
||||
});
|
||||
@@ -465,28 +444,14 @@ it("transfers cancellation to a no-stop cleanup already in progress", async () =
|
||||
const { cleanup, page, storage } = fixture();
|
||||
const cancellation = new AbortController();
|
||||
storage?.close.mockResolvedValue({ loadingStopped: false });
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
const session = await PlaywrightScenarioSession.open(
|
||||
attached,
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
let finishRestoration: () => void = () => undefined;
|
||||
let restorationStarted: () => void = () => undefined;
|
||||
const held = new Promise<void>((resolve) => {
|
||||
finishRestoration = resolve;
|
||||
});
|
||||
const started = new Promise<void>((resolve) => {
|
||||
restorationStarted = resolve;
|
||||
});
|
||||
const { promise: held, resolve: finishRestoration } = deferred();
|
||||
const { promise: started, resolve: restorationStarted } = deferred();
|
||||
let browserWasOpenAtStop = false;
|
||||
page.evaluate.mockImplementation(async (script: unknown) => {
|
||||
if (script === "globalThis.stop()")
|
||||
@@ -528,28 +493,14 @@ it("does not repeat a stop confirmed by storage during a late retry", async () =
|
||||
const { cleanup, page, storage } = fixture();
|
||||
const cancellation = new AbortController();
|
||||
storage?.close.mockResolvedValue({ loadingStopped: true });
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
const session = await PlaywrightScenarioSession.open(
|
||||
attached,
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
let finishRestoration: () => void = () => undefined;
|
||||
let restorationStarted: () => void = () => undefined;
|
||||
const held = new Promise<void>((resolve) => {
|
||||
finishRestoration = resolve;
|
||||
});
|
||||
const started = new Promise<void>((resolve) => {
|
||||
restorationStarted = resolve;
|
||||
});
|
||||
const { promise: held, resolve: finishRestoration } = deferred();
|
||||
const { promise: started, resolve: restorationStarted } = deferred();
|
||||
mocks.policySend.mockImplementation(async (method: string) => {
|
||||
if (method === "Runtime.evaluate") {
|
||||
restorationStarted();
|
||||
@@ -582,137 +533,62 @@ it("does not repeat a stop confirmed by storage during a late retry", async () =
|
||||
expect(cleanup.close).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("transfers cancellation arriving during final event cleanup", async () => {
|
||||
const { cleanup, page, storage } = fixture();
|
||||
const cancellation = new AbortController();
|
||||
storage?.close.mockResolvedValue({ loadingStopped: false });
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const session = await PlaywrightScenarioSession.open(
|
||||
attached,
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
let finishEvents: () => void = () => undefined;
|
||||
let finishStarted: () => void = () => undefined;
|
||||
const heldEvents = new Promise<void>((resolve) => {
|
||||
finishEvents = resolve;
|
||||
});
|
||||
const eventsStarted = new Promise<void>((resolve) => {
|
||||
finishStarted = resolve;
|
||||
});
|
||||
mocks.finishEvents.mockImplementation(async () => {
|
||||
finishStarted();
|
||||
await heldEvents;
|
||||
});
|
||||
let browserWasOpenAtStop = false;
|
||||
page.evaluate.mockImplementation(async (script: unknown) => {
|
||||
if (script === "globalThis.stop()")
|
||||
browserWasOpenAtStop = cleanup.browserClosed === false;
|
||||
return null;
|
||||
});
|
||||
it.each(["block", "allow"] as const)(
|
||||
"transfers cancellation during final event cleanup with service workers set to %s",
|
||||
async (serviceWorkers) => {
|
||||
const { cleanup, page, storage } = fixture();
|
||||
const cancellation = new AbortController();
|
||||
storage?.close.mockResolvedValue({ loadingStopped: false });
|
||||
const attached = connectedScenario(serviceWorkers);
|
||||
const session = await PlaywrightScenarioSession.open(
|
||||
attached,
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
const { promise: heldEvents, resolve: finishEvents } = deferred();
|
||||
const { promise: eventsStarted, resolve: finishStarted } = deferred();
|
||||
mocks.finishEvents.mockImplementation(async () => {
|
||||
finishStarted();
|
||||
await heldEvents;
|
||||
});
|
||||
let browserWasOpenAtStop = false;
|
||||
page.evaluate.mockImplementation(async (script: unknown) => {
|
||||
if (script === "globalThis.stop()")
|
||||
browserWasOpenAtStop = cleanup.browserClosed === false;
|
||||
return null;
|
||||
});
|
||||
|
||||
const firstClose = session.close(false);
|
||||
await eventsStarted;
|
||||
cancellation.abort();
|
||||
const retry = session.close();
|
||||
finishEvents();
|
||||
await expect(Promise.all([firstClose, retry])).resolves.toEqual([
|
||||
"disconnected-external",
|
||||
"disconnected-external",
|
||||
]);
|
||||
const firstClose = session.close(false);
|
||||
await eventsStarted;
|
||||
cancellation.abort();
|
||||
const retry = session.close();
|
||||
finishEvents();
|
||||
await expect(Promise.all([firstClose, retry])).resolves.toEqual([
|
||||
"disconnected-external",
|
||||
"disconnected-external",
|
||||
]);
|
||||
|
||||
expect(page.evaluate).toHaveBeenCalledWith("globalThis.stop()");
|
||||
expect(browserWasOpenAtStop).toBe(true);
|
||||
expect(cleanup.close).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("stops a connected page when service workers are allowed", async () => {
|
||||
const { cleanup, page, storage } = fixture();
|
||||
const cancellation = new AbortController();
|
||||
storage?.close.mockResolvedValue({ loadingStopped: false });
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "allow" },
|
||||
});
|
||||
const session = await PlaywrightScenarioSession.open(
|
||||
attached,
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
let finishEvents: () => void = () => undefined;
|
||||
let finishStarted: () => void = () => undefined;
|
||||
const heldEvents = new Promise<void>((resolve) => {
|
||||
finishEvents = resolve;
|
||||
});
|
||||
const eventsStarted = new Promise<void>((resolve) => {
|
||||
finishStarted = resolve;
|
||||
});
|
||||
mocks.finishEvents.mockImplementation(async () => {
|
||||
finishStarted();
|
||||
await heldEvents;
|
||||
});
|
||||
let browserWasOpenAtStop = false;
|
||||
page.evaluate.mockImplementation(async (script: unknown) => {
|
||||
if (script === "globalThis.stop()")
|
||||
browserWasOpenAtStop = cleanup.browserClosed === false;
|
||||
return null;
|
||||
});
|
||||
|
||||
const firstClose = session.close(false);
|
||||
await eventsStarted;
|
||||
cancellation.abort();
|
||||
const retry = session.close();
|
||||
finishEvents();
|
||||
await expect(Promise.all([firstClose, retry])).resolves.toEqual([
|
||||
"disconnected-external",
|
||||
"disconnected-external",
|
||||
]);
|
||||
|
||||
expect(page.evaluate).toHaveBeenCalledTimes(1);
|
||||
expect(browserWasOpenAtStop).toBe(true);
|
||||
expect(storage?.close).toHaveBeenCalledWith(false);
|
||||
expect(cleanup.close).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
expect(page.evaluate).toHaveBeenCalledWith("globalThis.stop()");
|
||||
if (serviceWorkers === "allow")
|
||||
expect(page.evaluate).toHaveBeenCalledTimes(1);
|
||||
expect(storage?.close).toHaveBeenCalledWith(false);
|
||||
expect(browserWasOpenAtStop).toBe(true);
|
||||
expect(cleanup.close).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
);
|
||||
|
||||
it("stops a connected page without storage or a service-worker policy owner", async () => {
|
||||
const { cleanup, page } = fixture();
|
||||
mocks.storage = undefined;
|
||||
const cancellation = new AbortController();
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "allow" },
|
||||
});
|
||||
const attached = connectedScenario("allow");
|
||||
const session = await PlaywrightScenarioSession.open(
|
||||
attached,
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
let finishEvents: () => void = () => undefined;
|
||||
let finishStarted: () => void = () => undefined;
|
||||
const heldEvents = new Promise<void>((resolve) => {
|
||||
finishEvents = resolve;
|
||||
});
|
||||
const eventsStarted = new Promise<void>((resolve) => {
|
||||
finishStarted = resolve;
|
||||
});
|
||||
const { promise: heldEvents, resolve: finishEvents } = deferred();
|
||||
const { promise: eventsStarted, resolve: finishStarted } = deferred();
|
||||
mocks.finishEvents.mockImplementation(async () => {
|
||||
finishStarted();
|
||||
await heldEvents;
|
||||
@@ -736,28 +612,14 @@ it("retries a failed connected-page stop when service workers are allowed", asyn
|
||||
const { cleanup, page, storage } = fixture();
|
||||
const cancellation = new AbortController();
|
||||
storage?.close.mockResolvedValue({ loadingStopped: false });
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "allow" },
|
||||
});
|
||||
const attached = connectedScenario("allow");
|
||||
const session = await PlaywrightScenarioSession.open(
|
||||
attached,
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
let finishEvents: () => void = () => undefined;
|
||||
let finishStarted: () => void = () => undefined;
|
||||
const heldEvents = new Promise<void>((resolve) => {
|
||||
finishEvents = resolve;
|
||||
});
|
||||
const eventsStarted = new Promise<void>((resolve) => {
|
||||
finishStarted = resolve;
|
||||
});
|
||||
const { promise: heldEvents, resolve: finishEvents } = deferred();
|
||||
const { promise: eventsStarted, resolve: finishStarted } = deferred();
|
||||
mocks.finishEvents.mockImplementation(async () => {
|
||||
finishStarted();
|
||||
await heldEvents;
|
||||
@@ -802,32 +664,16 @@ it("retains a late fallback stop failure for retry", async () => {
|
||||
const { cleanup, page, storage } = fixture();
|
||||
const cancellation = new AbortController();
|
||||
storage?.close.mockResolvedValue({ loadingStopped: false });
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
const session = await PlaywrightScenarioSession.open(
|
||||
attached,
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
let finishRestoration: () => void = () => undefined;
|
||||
let restorationStarted: () => void = () => undefined;
|
||||
const held = new Promise<void>((resolve) => {
|
||||
finishRestoration = resolve;
|
||||
});
|
||||
const started = new Promise<void>((resolve) => {
|
||||
restorationStarted = resolve;
|
||||
});
|
||||
let signalTransportClosed: () => void = () => undefined;
|
||||
const transportClosed = new Promise<void>((resolve) => {
|
||||
signalTransportClosed = resolve;
|
||||
});
|
||||
const { promise: held, resolve: finishRestoration } = deferred();
|
||||
const { promise: started, resolve: restorationStarted } = deferred();
|
||||
const { promise: transportClosed, resolve: signalTransportClosed } =
|
||||
deferred();
|
||||
mocks.policyTransportClose.mockImplementation(async () => {
|
||||
signalTransportClosed();
|
||||
});
|
||||
@@ -891,32 +737,16 @@ it("coalesces concurrent late-stop close retries", async () => {
|
||||
const { cleanup, page, storage } = fixture();
|
||||
const cancellation = new AbortController();
|
||||
storage?.close.mockResolvedValue({ loadingStopped: false });
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
const session = await PlaywrightScenarioSession.open(
|
||||
attached,
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
let finishRestoration: () => void = () => undefined;
|
||||
let restorationStarted: () => void = () => undefined;
|
||||
const held = new Promise<void>((resolve) => {
|
||||
finishRestoration = resolve;
|
||||
});
|
||||
const started = new Promise<void>((resolve) => {
|
||||
restorationStarted = resolve;
|
||||
});
|
||||
let signalTransportClosed: () => void = () => undefined;
|
||||
const transportClosed = new Promise<void>((resolve) => {
|
||||
signalTransportClosed = resolve;
|
||||
});
|
||||
const { promise: held, resolve: finishRestoration } = deferred();
|
||||
const { promise: started, resolve: restorationStarted } = deferred();
|
||||
const { promise: transportClosed, resolve: signalTransportClosed } =
|
||||
deferred();
|
||||
mocks.policyTransportClose.mockImplementation(async () => {
|
||||
signalTransportClosed();
|
||||
});
|
||||
@@ -942,14 +772,8 @@ it("coalesces concurrent late-stop close retries", async () => {
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
|
||||
cancellation.abort();
|
||||
let finishStop: () => void = () => undefined;
|
||||
let stopStarted: () => void = () => undefined;
|
||||
const heldStop = new Promise<void>((resolve) => {
|
||||
finishStop = resolve;
|
||||
});
|
||||
const startedStop = new Promise<void>((resolve) => {
|
||||
stopStarted = resolve;
|
||||
});
|
||||
const { promise: heldStop, resolve: finishStop } = deferred();
|
||||
const { promise: startedStop, resolve: stopStarted } = deferred();
|
||||
page.evaluate.mockImplementation(async (script: unknown) => {
|
||||
if (script === "globalThis.stop()") {
|
||||
stopStarted();
|
||||
@@ -1001,15 +825,7 @@ it("retains transferred navigation stopping after setup cleanup fails", async ()
|
||||
return policyResponse(method);
|
||||
});
|
||||
let retainedCleanup: AnalysisCleanupLease | undefined;
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
|
||||
await expect(
|
||||
PlaywrightScenarioSession.open(
|
||||
@@ -1049,14 +865,8 @@ it("allows the bounded policy cleanup chain to cross one second", async () => {
|
||||
storage: {},
|
||||
});
|
||||
const session = await PlaywrightScenarioSession.open(attached, {}, {});
|
||||
let releaseStop: () => void = () => undefined;
|
||||
let stopStarted: () => void = () => undefined;
|
||||
const stopped = new Promise<void>((resolve) => {
|
||||
releaseStop = resolve;
|
||||
});
|
||||
const started = new Promise<void>((resolve) => {
|
||||
stopStarted = resolve;
|
||||
});
|
||||
const { promise: stopped, resolve: releaseStop } = deferred();
|
||||
const { promise: started, resolve: stopStarted } = deferred();
|
||||
mocks.policySend.mockImplementation(async (method: string) => {
|
||||
if (method === "Page.stopLoading") {
|
||||
stopStarted();
|
||||
@@ -1103,14 +913,8 @@ it("does not await policy initialization after its child target detaches", async
|
||||
storage: {},
|
||||
});
|
||||
const session = await PlaywrightScenarioSession.open(attached, {}, {});
|
||||
let childStarted: () => void = () => undefined;
|
||||
let releaseChild: () => void = () => undefined;
|
||||
const started = new Promise<void>((resolve) => {
|
||||
childStarted = resolve;
|
||||
});
|
||||
const held = new Promise<void>((resolve) => {
|
||||
releaseChild = resolve;
|
||||
});
|
||||
const { promise: started, resolve: childStarted } = deferred();
|
||||
const { promise: held, resolve: releaseChild } = deferred();
|
||||
mocks.policySend.mockImplementation(
|
||||
async (method: string, _params: unknown, target: string) => {
|
||||
if (method === "Page.enable" && target === "child-session") {
|
||||
@@ -1176,15 +980,7 @@ it("rejects an init script accepted by CDP when the live realm is unprotected",
|
||||
page.evaluate
|
||||
.mockResolvedValueOnce(null)
|
||||
.mockResolvedValueOnce("policy_unprotected");
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
await expect(
|
||||
PlaywrightScenarioSession.open(attached, {}, {}),
|
||||
).rejects.toMatchObject({
|
||||
@@ -1210,15 +1006,7 @@ it("restores an owned policy script after later setup fails", async () => {
|
||||
if (method === "Target.setAutoAttach") throw setupFailure;
|
||||
return policyResponse(method);
|
||||
});
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
|
||||
await expect(PlaywrightScenarioSession.open(attached, {}, {})).rejects.toBe(
|
||||
setupFailure,
|
||||
@@ -1239,15 +1027,7 @@ it("restores an owned policy script after later setup fails", async () => {
|
||||
|
||||
it("retains an owned script identifier after rejected removal", async () => {
|
||||
const { cleanup } = fixture();
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
const session = await PlaywrightScenarioSession.open(attached, {}, {});
|
||||
const failure = new Error("removeScript rejected");
|
||||
mocks.policySend.mockRejectedValueOnce(failure);
|
||||
@@ -1268,15 +1048,7 @@ it("retains an owned script identifier after rejected removal", async () => {
|
||||
|
||||
it("retries transport close without detaching an already released policy session", async () => {
|
||||
fixture();
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
const session = await PlaywrightScenarioSession.open(attached, {}, {});
|
||||
const failure = new Error("transport close rejected");
|
||||
mocks.policyTransportClose.mockRejectedValueOnce(failure);
|
||||
@@ -1391,15 +1163,7 @@ it("uses browser disconnect as terminal storage release after detach failure", a
|
||||
|
||||
it("leaves attached service-worker state alone when the policy allows it", async () => {
|
||||
const { cleanup, page } = fixture();
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "allow" },
|
||||
});
|
||||
const attached = connectedScenario("allow");
|
||||
const session = await PlaywrightScenarioSession.open(attached, {}, {});
|
||||
|
||||
expect(mocks.openBrowser).toHaveBeenCalledWith(
|
||||
@@ -1415,15 +1179,7 @@ it("leaves attached service-worker state alone when the policy allows it", async
|
||||
|
||||
it("blocks new attached service-worker registration without removing existing registrations", async () => {
|
||||
const { cleanup, page } = fixture();
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
const session = await PlaywrightScenarioSession.open(attached, {}, {});
|
||||
|
||||
expect(page.evaluate).toHaveBeenCalledTimes(3);
|
||||
@@ -1485,10 +1241,7 @@ it("retains the attached connection when registration restoration fails", async
|
||||
it("cancels a stalled policy preflight without allowing late setup", async () => {
|
||||
const { cleanup, page } = fixture();
|
||||
let release: () => void = () => undefined;
|
||||
let entered: () => void = () => undefined;
|
||||
const started = new Promise<void>((resolve) => {
|
||||
entered = resolve;
|
||||
});
|
||||
const { promise: started, resolve: entered } = deferred();
|
||||
page.evaluate.mockImplementationOnce(async () => {
|
||||
entered();
|
||||
await new Promise<void>((resolve) => {
|
||||
@@ -1498,15 +1251,7 @@ it("cancels a stalled policy preflight without allowing late setup", async () =>
|
||||
});
|
||||
const cancellation = new AbortController();
|
||||
const opening = PlaywrightScenarioSession.open(
|
||||
browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
}),
|
||||
connectedScenario("block"),
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
@@ -1525,14 +1270,8 @@ it("cancels a stalled policy preflight without allowing late setup", async () =>
|
||||
|
||||
it("waits for a pending registration installation before cancelled cleanup", async () => {
|
||||
const { cleanup, page } = fixture();
|
||||
let releaseInstallation: () => void = () => undefined;
|
||||
let installationStarted: () => void = () => undefined;
|
||||
const installed = new Promise<void>((resolve) => {
|
||||
releaseInstallation = resolve;
|
||||
});
|
||||
const started = new Promise<void>((resolve) => {
|
||||
installationStarted = resolve;
|
||||
});
|
||||
const { promise: installed, resolve: releaseInstallation } = deferred();
|
||||
const { promise: started, resolve: installationStarted } = deferred();
|
||||
mocks.policySend.mockImplementation(async (method: string) => {
|
||||
if (method === "Page.addScriptToEvaluateOnNewDocument") {
|
||||
installationStarted();
|
||||
@@ -1543,15 +1282,7 @@ it("waits for a pending registration installation before cancelled cleanup", asy
|
||||
});
|
||||
const cancellation = new AbortController();
|
||||
const opening = PlaywrightScenarioSession.open(
|
||||
browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
}),
|
||||
connectedScenario("block"),
|
||||
{},
|
||||
{ signal: cancellation.signal },
|
||||
);
|
||||
@@ -1582,15 +1313,7 @@ it("waits for a pending registration installation before cancelled cleanup", asy
|
||||
it("rejects attached block when caller-owned registrations already exist", async () => {
|
||||
const { cleanup, page } = fixture();
|
||||
page.evaluate.mockResolvedValueOnce("service_worker_blocked");
|
||||
const attached = browserScenarioSchema.parse({
|
||||
...scenario,
|
||||
browser: {
|
||||
mode: "connect",
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "target",
|
||||
},
|
||||
environment: { service_workers: "block" },
|
||||
});
|
||||
const attached = connectedScenario("block");
|
||||
|
||||
await expect(
|
||||
PlaywrightScenarioSession.open(attached, {}, {}),
|
||||
|
||||
@@ -40,6 +40,23 @@ const indexed = (source: string) => {
|
||||
};
|
||||
};
|
||||
|
||||
it("orders exported callable initializers within their enclosing declaration", () => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
function original() {}
|
||||
export const first = original, second = first;
|
||||
second();
|
||||
export const before = later, later = original;
|
||||
before();
|
||||
`);
|
||||
const original = ir.callables.find(({ name }) => name === "original");
|
||||
if (original === undefined) throw new Error("Missing original callable");
|
||||
expect(ir.callSites[0]).toMatchObject({
|
||||
resolution: "exact",
|
||||
calleeCallableIds: [original.callableId],
|
||||
});
|
||||
expect(ir.callSites[1]?.resolution).not.toBe("exact");
|
||||
});
|
||||
|
||||
it.each([
|
||||
"if(flag)({make}={make:replacement});",
|
||||
"if(flag)[make]=[replacement];",
|
||||
|
||||
@@ -758,16 +758,19 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort {
|
||||
bindArtifactFileCleanup(artifactFailure, failure);
|
||||
result = err(failure);
|
||||
}
|
||||
if (result.ok && options?.signal?.aborted)
|
||||
result = err(
|
||||
new AnalysisCancelledError(OPERATION, {
|
||||
cause: options.signal.reason,
|
||||
partialObservation: evmInterfaceEvidence(input, result.value),
|
||||
...(retainedOutput === undefined
|
||||
? {}
|
||||
: { capturedOutput: retainedOutput }),
|
||||
}),
|
||||
);
|
||||
const retainCancellation = (outcome: EvmOutcome): EvmOutcome =>
|
||||
outcome.ok && options?.signal?.aborted
|
||||
? err(
|
||||
new AnalysisCancelledError(OPERATION, {
|
||||
cause: options.signal.reason,
|
||||
partialObservation: evmInterfaceEvidence(input, outcome.value),
|
||||
...(retainedOutput === undefined
|
||||
? {}
|
||||
: { capturedOutput: retainedOutput }),
|
||||
}),
|
||||
)
|
||||
: outcome;
|
||||
result = retainCancellation(result);
|
||||
if (processOwner !== undefined) {
|
||||
const lease = processLeaseFor(processOwner);
|
||||
const rootOwnerLease =
|
||||
@@ -838,18 +841,7 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort {
|
||||
} catch (cause: unknown) {
|
||||
const retainedRoot = root;
|
||||
const lease = rootLeaseFor(retainedRoot);
|
||||
const cleanupResult =
|
||||
result.ok && options?.signal?.aborted
|
||||
? err(
|
||||
new AnalysisCancelledError(OPERATION, {
|
||||
cause: options.signal.reason,
|
||||
partialObservation: evmInterfaceEvidence(input, result.value),
|
||||
...(retainedOutput === undefined
|
||||
? {}
|
||||
: { capturedOutput: retainedOutput }),
|
||||
}),
|
||||
)
|
||||
: result;
|
||||
const cleanupResult = retainCancellation(result);
|
||||
this.#pendingCleanup = {
|
||||
input,
|
||||
result: cleanupResult,
|
||||
@@ -874,7 +866,7 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort {
|
||||
return err(failure);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return retainCancellation(result);
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
|
||||
@@ -783,6 +783,7 @@ it
|
||||
else expect(result.error.cleanupIncomplete).toBe(true);
|
||||
if (scenario === "cancelled-cleanup-failure") {
|
||||
expect(result.error.cleanupPrimary?.cause).toBe(reason);
|
||||
denyClose = false;
|
||||
await provider.close();
|
||||
expect(result.error.cleanupIncomplete).toBe(false);
|
||||
expect(projectAnalysisError(result.error).category).toBe("cancelled");
|
||||
|
||||
Reference in new issue
Block a user