Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
import {
actions,
selectors,
createStore,
createSourceObject,
makeSource,
makeOriginalSource,
makeFrame,
} from "../../../utils/test-head";
import { makeWhyNormal } from "../../../utils/test-mockup";
import { createLocation } from "../../../utils/location";
const mockCommandClient = {
stepIn: () => new Promise(),
stepOver: () => new Promise(_resolve => _resolve),
evaluate: async () => {},
evaluateExpressions: async () => [],
resume: async () => {},
getFrameScopes: async frame => frame.scope,
getFrames: async () => [],
setBreakpoint: () => new Promise(_resolve => {}),
sourceContents: ({ source }) => {
return new Promise(resolve => {
switch (source) {
case "foo1":
return resolve({
source: "function foo1() {\n return 5;\n}",
contentType: "text/javascript",
});
case "await":
return resolve({
source: "async function aWait() {\n await foo(); return 5;\n}",
contentType: "text/javascript",
});
case "foo":
return resolve({
source: "function foo() {\n return -5;\n}",
contentType: "text/javascript",
});
case "foo-original":
return resolve({
source: "\n\nfunction fooOriginal() {\n return -5;\n}",
contentType: "text/javascript",
});
case "foo-wasm":
return resolve({
source: { binary: new ArrayBuffer(0) },
contentType: "application/wasm",
});
case "foo-wasm/originalSource":
return resolve({
source: "fn fooBar() {}\nfn barZoo() { fooBar() }",
contentType: "text/rust",
});
}
return resolve();
});
},
getSourceActorBreakpointPositions: async () => ({}),
getSourceActorBreakableLines: async () => [],
actorID: "threadActorID",
};
const mockFrameId = "1";
function createPauseInfo(
frameLocation = createLocation({
source: createSourceObject("foo1"),
line: 2,
}),
frameOpts = {}
) {
const frames = [
makeFrame(
{ id: mockFrameId, sourceId: frameLocation.source.id },
{
location: frameLocation,
generatedLocation: frameLocation,
...frameOpts,
}
),
];
return {
thread: "FakeThread",
frame: frames[0],
frames,
loadedObjects: [],
why: makeWhyNormal(),
};
}
function debuggerToSourceMapLocation(l) {
return {
sourceId: l.source.id,
line: l.line,
column: l.column,
};
}
describe("pause", () => {
describe("stepping", () => {
it("should only step when paused", async () => {
const client = { stepIn: jest.fn() };
const { dispatch } = createStore(client);
dispatch(actions.stepIn());
expect(client.stepIn.mock.calls).toHaveLength(0);
});
it("getting frame scopes with bindings", async () => {
const client = { ...mockCommandClient };
const store = createStore(client, {});
const { dispatch, getState } = store;
const source = await dispatch(
actions.newGeneratedSource(makeSource("foo"))
);
const generatedLocation = createLocation({
source,
line: 1,
column: 0,
sourceActor: selectors.getFirstSourceActorForGeneratedSource(
getState(),
source.id
),
});
const mockPauseInfo = createPauseInfo(generatedLocation, {
scope: {
bindings: {
variables: { b: { value: {} } },
arguments: [{ a: { value: {} } }],
},
},
});
const { frames } = mockPauseInfo;
client.getFrames = async () => frames;
await dispatch(actions.newOriginalSources([makeOriginalSource(source)]));
await dispatch(actions.paused(mockPauseInfo));
expect(selectors.getFrames(getState(), "FakeThread")).toEqual([
{
id: mockFrameId,
generatedLocation,
location: generatedLocation,
library: null,
scope: {
bindings: {
arguments: [{ a: { value: {} } }],
variables: { b: { value: {} } },
},
},
thread: "FakeThread",
},
]);
expect(selectors.getFrameScopes(getState(), "FakeThread")).toEqual({
generated: {
1: {
pending: false,
scope: {
bindings: {
arguments: [{ a: { value: {} } }],
variables: { b: { value: {} } },
},
},
},
},
mappings: { 1: undefined },
original: { 1: { pending: false, scope: undefined } },
});
expect(
selectors.getSelectedFrameBindings(getState(), "FakeThread")
).toEqual(["b", "a"]);
});
it("maps frame to original frames", async () => {
const sourceMapLoaderMock = {
getOriginalStackFrames: () => Promise.resolve(originStackFrames),
getOriginalLocation: () =>
Promise.resolve(debuggerToSourceMapLocation(originalLocation)),
getOriginalLocations: async items =>
items.map(debuggerToSourceMapLocation),
getOriginalSourceText: async () => ({
text: "fn fooBar() {}\nfn barZoo() { fooBar() }",
contentType: "text/rust",
}),
getGeneratedRangesForOriginal: async () => [],
};
const client = { ...mockCommandClient };
const store = createStore(client, {}, sourceMapLoaderMock);
const { dispatch, getState } = store;
const generatedSource = await dispatch(
actions.newGeneratedSource(
makeSource("foo-wasm", { introductionType: "wasm" })
)
);
const generatedLocation = createLocation({
source: generatedSource,
line: 1,
column: 0,
sourceActor: selectors.getFirstSourceActorForGeneratedSource(
getState(),
generatedSource.id
),
});
const mockPauseInfo = createPauseInfo(generatedLocation);
const { frames } = mockPauseInfo;
client.getFrames = async () => frames;
const [originalSource] = await dispatch(
actions.newOriginalSources([makeOriginalSource(generatedSource)])
);
const originalLocation = createLocation({
source: originalSource,
line: 1,
column: 1,
});
const originalLocation2 = createLocation({
source: originalSource,
line: 2,
column: 14,
sourceActor: selectors.getFirstSourceActorForGeneratedSource(
getState(),
originalSource.id
),
});
const originStackFrames = [
{
displayName: "fooBar",
thread: "FakeThread",
},
{
displayName: "barZoo",
location: originalLocation2,
thread: "FakeThread",
},
];
await dispatch(actions.paused(mockPauseInfo));
expect(selectors.getFrames(getState(), "FakeThread")).toEqual([
{
asyncCause: undefined,
displayName: "fooBar",
generatedLocation,
id: "1",
index: undefined,
isOriginal: true,
library: null,
location: originalLocation,
originalDisplayName: "fooBar",
originalVariables: undefined,
state: undefined,
this: undefined,
thread: "FakeThread",
type: undefined,
},
{
asyncCause: undefined,
displayName: "barZoo",
generatedLocation,
id: "1-originalFrame1",
index: undefined,
isOriginal: true,
library: null,
location: originalLocation2,
originalDisplayName: "barZoo",
originalVariables: undefined,
state: undefined,
this: undefined,
thread: "FakeThread",
type: undefined,
},
]);
});
});
});