Skip to content

Commit 9a50039

Browse files
loganfsmythjasonLaster
authored andcommitted
Handle global-rewrite (Ember-related) original scope resolution (firefox-devtools#5871)
* Resolve globals to allow locals to be rewritten to reference globals. * Move the shared breakpoint testing logic into head.js * Resolve bindings with multiple generated location. * Add an example Ember quickstart application. * Add a mochitest for Ember's source maps.
1 parent b8f33b3 commit 9a50039

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+110567
-216
lines changed

.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ src/test/mochitest/examples/babel/polyfill-bundle.js
55
src/test/mochitest/examples/babel/fixtures/*/input.js
66
src/test/mochitest/examples/babel/fixtures/*/output.js
77
src/test/mochitest/examples/babel/fixtures/*/output.js.map
8+
src/test/mochitest/examples/ember/quickstart

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ env:
1010
global:
1111
- DISPLAY=':99.0'
1212
- YARN_VERSION='0.24.5'
13-
- MC_COMMIT='7b40283bf1c7' # https://hg.mozilla.org/mozilla-central/shortlog
13+
- MC_COMMIT='83de58ddda20' # https://hg.mozilla.org/mozilla-central/shortlog
1414

1515
notifications:
1616
slack:

src/actions/pause/mapScopes.js

+23-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import { locColumn } from "../../utils/pause/mapScopes/locColumn";
2020
// eslint-disable-next-line max-len
2121
import { findGeneratedBindingFromPosition } from "../../utils/pause/mapScopes/findGeneratedBindingFromPosition";
2222

23+
import { createObjectClient } from "../../client/firefox";
24+
2325
import { features } from "../../utils/prefs";
2426
import { log } from "../../utils/log";
2527
import { isGeneratedId } from "devtools-source-map";
@@ -38,7 +40,7 @@ export type OriginalScope = RenderableScope;
3840
export type GeneratedBindingLocation = {
3941
name: string,
4042
loc: BindingLocation,
41-
desc: BindingContents | null
43+
desc: () => Promise<BindingContents | null>
4244
};
4345

4446
export function mapScopes(scopes: Promise<Scope>, frame: Frame) {
@@ -360,13 +362,15 @@ function buildGeneratedBindingList(
360362
generated => "this" in generated.bindings
361363
);
362364

365+
let globalScope = null;
363366
const clientScopes = [];
364367
for (let s = scopes; s; s = s.parent) {
365368
const bindings = s.bindings
366369
? Object.assign({}, ...s.bindings.arguments, s.bindings.variables)
367370
: {};
368371

369372
clientScopes.push(bindings);
373+
globalScope = s;
370374
}
371375

372376
const generatedMainScopes = generatedAstScopes.slice(0, -2);
@@ -392,7 +396,7 @@ function buildGeneratedBindingList(
392396
acc.push({
393397
name,
394398
loc,
395-
desc: bindings[name] || null
399+
desc: () => Promise.resolve(bindings[name] || null)
396400
});
397401
}
398402
}
@@ -406,15 +410,29 @@ function buildGeneratedBindingList(
406410
for (const generated of generatedGlobalScopes) {
407411
for (const name of Object.keys(generated.bindings)) {
408412
const { refs } = generated.bindings[name];
409-
for (const loc of refs) {
410-
const bindings = clientGlobalScopes.find(b => has(b, name));
413+
const bindings = clientGlobalScopes.find(b => has(b, name));
411414

415+
for (const loc of refs) {
412416
if (bindings) {
413417
generatedBindings.push({
414418
name,
415419
loc,
416-
desc: bindings[name]
420+
desc: () => Promise.resolve(bindings[name])
417421
});
422+
} else {
423+
const globalGrip = globalScope && globalScope.object;
424+
if (globalGrip) {
425+
// Should always exist, just checking to keep Flow happy.
426+
427+
generatedBindings.push({
428+
name,
429+
loc,
430+
desc: async () => {
431+
const objectClient = createObjectClient(globalGrip);
432+
return (await objectClient.getProperty(name)).descriptor;
433+
}
434+
});
435+
}
418436
}
419437
}
420438
}

src/test/mochitest/browser.ini

+8
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ support-files =
5555
examples/babel/fixtures/webpack-modules-es6/output.js.map
5656
examples/babel/fixtures/webpack-standalone/output.js
5757
examples/babel/fixtures/webpack-standalone/output.js.map
58+
examples/ember/quickstart/dist/index.html
59+
examples/ember/quickstart/dist/assets/quickstart.css
60+
examples/ember/quickstart/dist/assets/quickstart.js
61+
examples/ember/quickstart/dist/assets/quickstart.map
62+
examples/ember/quickstart/dist/assets/vendor.css
63+
examples/ember/quickstart/dist/assets/vendor.js
64+
examples/ember/quickstart/dist/assets/vendor.map
5865
examples/sourcemaps/bundle.js
5966
examples/sourcemaps/bundle.js.map
6067
examples/sourcemaps2/main.min.js
@@ -159,6 +166,7 @@ skip-if = (os == "win" && ccov) # Bug 1424154
159166
[browser_dbg-editor-gutter.js]
160167
[browser_dbg-editor-select.js]
161168
[browser_dbg-editor-highlight.js]
169+
[browser_dbg-ember-quickstart.js]
162170
[browser_dbg-expressions.js]
163171
[browser_dbg-expressions-error.js]
164172
[browser_dbg-iframes.js]

src/test/mochitest/browser_dbg-babel-breakpoint-console.js

+3-41
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,11 @@
11

22
async function evalInConsoleAtPoint(dbg, fixture, { line, column }, statements) {
3-
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
4-
53
const filename = `fixtures/${fixture}/input.js`;
6-
await waitForSources(dbg, filename);
7-
8-
ok(true, "Original sources exist");
9-
const source = findSource(dbg, filename);
10-
11-
await selectSource(dbg, source);
12-
13-
// Test that breakpoint is not off by a line.
14-
await addBreakpoint(dbg, source, line);
15-
16-
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
17-
ok(
18-
getBreakpoint(getState(), { sourceId: source.id, line, column }),
19-
"Breakpoint has correct line"
20-
);
21-
224
const fnName = fixture.replace(/-([a-z])/g, (s, c) => c.toUpperCase());
235

24-
const invokeResult = invokeInTab(fnName);
25-
26-
let invokeFailed = await Promise.race([
27-
waitForPaused(dbg),
28-
invokeResult.then(() => new Promise(() => {}), () => true)
29-
]);
30-
31-
if (invokeFailed) {
32-
return invokeResult;
33-
}
34-
35-
assertPausedLocation(dbg);
36-
37-
await assertConsoleEval(dbg, statements);
38-
39-
await removeBreakpoint(dbg, source.id, line, column);
40-
41-
is(getBreakpoints(getState()).size, 0, "Breakpoint reverted");
42-
43-
await resume(dbg);
44-
45-
// If the invoke errored later somehow, capture here so the error is reported nicely.
46-
await invokeResult;
6+
await invokeWithBreakpoint(dbg, fnName, filename, { line, column }, async () => {
7+
await assertConsoleEval(dbg, statements);
8+
});
479

4810
ok(true, `Ran tests for ${fixture} at line ${line} column ${column}`);
4911
}

src/test/mochitest/browser_dbg-babel-preview.js

+3-41
Original file line numberDiff line numberDiff line change
@@ -28,50 +28,12 @@ async function assertPreviews(dbg, previews) {
2828
}
2929

3030
async function breakpointPreviews(dbg, fixture, { line, column }, previews) {
31-
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
32-
3331
const filename = `fixtures/${fixture}/input.js`;
34-
await waitForSources(dbg, filename);
35-
36-
ok(true, "Original sources exist");
37-
const source = findSource(dbg, filename);
38-
39-
await selectSource(dbg, source);
40-
41-
// Test that breakpoint is not off by a line.
42-
await addBreakpoint(dbg, source, line);
43-
44-
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
45-
ok(
46-
getBreakpoint(getState(), { sourceId: source.id, line, column }),
47-
"Breakpoint has correct line"
48-
);
49-
5032
const fnName = fixture.replace(/-([a-z])/g, (s, c) => c.toUpperCase());
5133

52-
const invokeResult = invokeInTab(fnName);
53-
54-
let invokeFailed = await Promise.race([
55-
waitForPaused(dbg),
56-
invokeResult.then(() => new Promise(() => {}), () => true)
57-
]);
58-
59-
if (invokeFailed) {
60-
return invokeResult;
61-
}
62-
63-
assertPausedLocation(dbg);
64-
65-
await assertPreviews(dbg, previews);
66-
67-
await removeBreakpoint(dbg, source.id, line, column);
68-
69-
is(getBreakpoints(getState()).size, 0, "Breakpoint reverted");
70-
71-
await resume(dbg);
72-
73-
// If the invoke errored later somehow, capture here so the error is reported nicely.
74-
await invokeResult;
34+
await invokeWithBreakpoint(dbg, fnName, filename, { line, column }, async () => {
35+
await assertPreviews(dbg, previews);
36+
});
7537

7638
ok(true, `Ran tests for ${fixture} at line ${line} column ${column}`);
7739
}

src/test/mochitest/browser_dbg-babel-scopes.js

+3-74
Original file line numberDiff line numberDiff line change
@@ -7,87 +7,16 @@ requestLongerTimeout(4);
77
// Tests loading sourcemapped sources for Babel's compile output.
88

99
async function breakpointScopes(dbg, fixture, { line, column }, scopes) {
10-
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
11-
1210
const filename = `fixtures/${fixture}/input.js`;
13-
await waitForSources(dbg, filename);
14-
15-
ok(true, "Original sources exist");
16-
const source = findSource(dbg, filename);
17-
18-
await selectSource(dbg, source);
19-
20-
// Test that breakpoint is not off by a line.
21-
await addBreakpoint(dbg, source, line);
22-
23-
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
24-
ok(
25-
getBreakpoint(getState(), { sourceId: source.id, line, column }),
26-
"Breakpoint has correct line"
27-
);
28-
2911
const fnName = fixture.replace(/-([a-z])/g, (s, c) => c.toUpperCase());
3012

31-
const invokeResult = invokeInTab(fnName);
32-
33-
let invokeFailed = await Promise.race([
34-
waitForPaused(dbg),
35-
invokeResult.then(() => new Promise(() => {}), () => true)
36-
]);
37-
38-
if (invokeFailed) {
39-
return invokeResult;
40-
}
41-
42-
assertPausedLocation(dbg);
43-
44-
await assertScopes(dbg, scopes);
45-
46-
await removeBreakpoint(dbg, source.id, line, column);
47-
48-
is(getBreakpoints(getState()).size, 0, "Breakpoint reverted");
49-
50-
await resume(dbg);
51-
52-
// If the invoke errored later somehow, capture here so the error is reported nicely.
53-
await invokeResult;
13+
await invokeWithBreakpoint(dbg, fnName, filename, { line, column }, async () => {
14+
await assertScopes(dbg, scopes);
15+
});
5416

5517
ok(true, `Ran tests for ${fixture} at line ${line} column ${column}`);
5618
}
5719

58-
async function expandAllScopes(dbg) {
59-
const scopes = await waitForElement(dbg, "scopes");
60-
const scopeElements = scopes.querySelectorAll(
61-
`.tree-node[aria-level="1"][data-expandable="true"]:not([aria-expanded="true"])`
62-
);
63-
const indices = Array.from(scopeElements, el => {
64-
return Array.prototype.indexOf.call(el.parentNode.childNodes, el);
65-
}).reverse();
66-
67-
for (const index of indices) {
68-
await toggleScopeNode(dbg, index + 1);
69-
}
70-
}
71-
72-
async function assertScopes(dbg, items) {
73-
await expandAllScopes(dbg);
74-
75-
for (const [i, val] of items.entries()) {
76-
if (Array.isArray(val)) {
77-
is(getScopeLabel(dbg, i + 1), val[0]);
78-
is(
79-
getScopeValue(dbg, i + 1),
80-
val[1],
81-
`"${val[0]}" has the expected "${val[1]}" value`
82-
);
83-
} else {
84-
is(getScopeLabel(dbg, i + 1), val);
85-
}
86-
}
87-
88-
is(getScopeLabel(dbg, items.length + 1), "Window");
89-
}
90-
9120
add_task(async function() {
9221
await pushPref("devtools.debugger.features.map-scopes", true);
9322

src/test/mochitest/browser_dbg-babel-stepping.js

+3-43
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,12 @@
55
requestLongerTimeout(4);
66

77
async function breakpointSteps(dbg, fixture, { line, column }, steps) {
8-
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
9-
108
const filename = `fixtures/${fixture}/input.js`;
11-
await waitForSources(dbg, filename);
12-
13-
ok(true, "Original sources exist");
14-
const source = findSource(dbg, filename);
15-
16-
await selectSource(dbg, source);
17-
18-
// Test that breakpoint is not off by a line.
19-
await addBreakpoint(dbg, source, line);
20-
21-
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
22-
23-
ok(
24-
getBreakpoint(getState(), { sourceId: source.id, line, column }),
25-
"Breakpoint has correct line"
26-
);
27-
289
const fnName = fixture.replace(/-([a-z])/g, (s, c) => c.toUpperCase());
2910

30-
const invokeResult = invokeInTab(fnName);
31-
32-
let invokeFailed = await Promise.race([
33-
waitForPaused(dbg),
34-
invokeResult.then(() => new Promise(() => {}), () => true)
35-
]);
36-
37-
if (invokeFailed) {
38-
return invokeResult;
39-
}
40-
41-
assertPausedLocation(dbg);
42-
43-
await removeBreakpoint(dbg, source.id, line, column);
44-
45-
is(getBreakpoints(getState()).size, 0, "Breakpoint reverted");
46-
47-
await runSteps(dbg, source, steps);
48-
49-
await resume(dbg);
50-
51-
// If the invoke errored later somehow, capture here so the error is
52-
// reported nicely.
53-
await invokeResult;
11+
await invokeWithBreakpoint(dbg, fnName, filename, { line, column }, async source => {
12+
await runSteps(dbg, source, steps);
13+
});
5414

5515
ok(true, `Ran tests for ${fixture} at line ${line} column ${column}`);
5616
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
add_task(async function() {
3+
await pushPref("devtools.debugger.features.map-scopes", true);
4+
5+
const dbg = await initDebugger("ember/quickstart/dist/");
6+
7+
await invokeWithBreakpoint(dbg, "mapTestFunction", "quickstart/router.js", { line: 13, column: 2 }, async () => {
8+
await assertScopes(dbg, [
9+
"Module",
10+
["config", "{\u2026}"],
11+
"EmberRouter:Class()",
12+
"Router:Class()",
13+
]);
14+
});
15+
});

0 commit comments

Comments
 (0)