chrome-devtools-frontend 1.0.968254 → 1.0.968818

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -273,7 +273,7 @@ export class CSSMatchedStyles {
273
273
  async recomputeMatchingSelectors(rule: CSSStyleRule): Promise<void> {
274
274
  const node = this.nodeForStyle(rule.style);
275
275
  if (!node) {
276
- return Promise.resolve();
276
+ return;
277
277
  }
278
278
  const promises = [];
279
279
  for (const selector of rule.selectors) {
@@ -90,6 +90,8 @@ export class ScopeChainSidebarPane extends UI.Widget.VBox implements UI.ContextF
90
90
  private readonly expandController: ObjectUI.ObjectPropertiesSection.ObjectPropertiesSectionsTreeExpandController;
91
91
  private readonly linkifier: Components.Linkifier.Linkifier;
92
92
  private infoElement: HTMLDivElement;
93
+ #scopesScript: SDK.Script.Script|null = null;
94
+
93
95
  private constructor() {
94
96
  super(true);
95
97
 
@@ -126,6 +128,34 @@ export class ScopeChainSidebarPane extends UI.Widget.VBox implements UI.ContextF
126
128
  }
127
129
  }
128
130
 
131
+ private sourceMapAttached(
132
+ event: Common.EventTarget.EventTargetEvent<{client: SDK.Script.Script, sourceMap: SDK.SourceMap.SourceMap}>):
133
+ void {
134
+ if (event.data.client === this.#scopesScript) {
135
+ void this.update();
136
+ }
137
+ }
138
+
139
+ private setScopeSourceMapSubscription(callFrame: SDK.DebuggerModel.CallFrame|null): void {
140
+ const oldScript = this.#scopesScript;
141
+ this.#scopesScript = callFrame?.script ?? null;
142
+
143
+ // Shortcut for the case when we are listening to the same model.
144
+ if (oldScript?.debuggerModel === this.#scopesScript?.debuggerModel) {
145
+ return;
146
+ }
147
+
148
+ if (oldScript) {
149
+ oldScript.debuggerModel.sourceMapManager().removeEventListener(
150
+ SDK.SourceMapManager.Events.SourceMapAttached, this.sourceMapAttached, this);
151
+ }
152
+
153
+ if (this.#scopesScript) {
154
+ this.#scopesScript.debuggerModel.sourceMapManager().addEventListener(
155
+ SDK.SourceMapManager.Events.SourceMapAttached, this.sourceMapAttached, this);
156
+ }
157
+ }
158
+
129
159
  private async update(): Promise<void> {
130
160
  // The `resolveThisObject(callFrame)` and `resolveScopeChain(callFrame)` calls
131
161
  // below may take a while to complete, so indicate to the user that something
@@ -137,6 +167,7 @@ export class ScopeChainSidebarPane extends UI.Widget.VBox implements UI.ContextF
137
167
  this.linkifier.reset();
138
168
 
139
169
  const callFrame = UI.Context.Context.instance().flavor(SDK.DebuggerModel.CallFrame);
170
+ this.setScopeSourceMapSubscription(callFrame);
140
171
  const [thisObject, scopeChain] = await Promise.all([resolveThisObject(callFrame), resolveScopeChain(callFrame)]);
141
172
  // By now the developer might have moved on, and we don't want to show stale
142
173
  // scope information, so check again that we're still on the same CallFrame.
@@ -10,9 +10,14 @@ import * as TextUtils from '../../models/text_utils/text_utils.js';
10
10
  import type * as Workspace from '../../models/workspace/workspace.js';
11
11
  import * as Protocol from '../../generated/protocol.js';
12
12
 
13
- const scopeToCachedIdentifiersMap = new WeakMap<SDK.DebuggerModel.ScopeChainEntry, Promise<Map<string, string>>>();
13
+ interface CachedScopeMap {
14
+ sourceMap: SDK.SourceMap.SourceMap|null;
15
+ identifiersPromise: Promise<Map<string, string>>;
16
+ }
14
17
 
18
+ const scopeToCachedIdentifiersMap = new WeakMap<SDK.DebuggerModel.ScopeChainEntry, CachedScopeMap>();
15
19
  const cachedMapByCallFrame = new WeakMap<SDK.DebuggerModel.CallFrame, Map<string, string>>();
20
+
16
21
  export class Identifier {
17
22
  name: string;
18
23
  lineNumber: number;
@@ -79,17 +84,17 @@ export const resolveScopeChain =
79
84
  };
80
85
 
81
86
  export const resolveScope = async(scope: SDK.DebuggerModel.ScopeChainEntry): Promise<Map<string, string>> => {
82
- let identifiersPromise = scopeToCachedIdentifiersMap.get(scope);
83
- if (!identifiersPromise) {
87
+ let cachedScopeMap = scopeToCachedIdentifiersMap.get(scope);
88
+ const script = scope.callFrame().script;
89
+ const sourceMap = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().sourceMapForScript(script);
90
+
91
+ if (!cachedScopeMap || cachedScopeMap.sourceMap !== sourceMap) {
84
92
  // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
85
93
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
86
94
  // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
87
95
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
88
- identifiersPromise = (async(): Promise<Map<any, any>> => {
96
+ const identifiersPromise = (async(): Promise<Map<any, any>> => {
89
97
  const namesMapping = new Map<string, string>();
90
- const script = scope.callFrame().script;
91
- const sourceMap =
92
- Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().sourceMapForScript(script);
93
98
  if (sourceMap) {
94
99
  const textCache = new Map<string, TextUtils.Text.Text>();
95
100
  // Extract as much as possible from SourceMap and resolve
@@ -111,9 +116,10 @@ export const resolveScope = async(scope: SDK.DebuggerModel.ScopeChainEntry): Pro
111
116
  }
112
117
  return namesMapping;
113
118
  })();
114
- scopeToCachedIdentifiersMap.set(scope, identifiersPromise);
119
+ cachedScopeMap = {sourceMap, identifiersPromise};
120
+ scopeToCachedIdentifiersMap.set(scope, {sourceMap, identifiersPromise});
115
121
  }
116
- return await identifiersPromise;
122
+ return await cachedScopeMap.identifiersPromise;
117
123
 
118
124
  async function resolveSourceName(
119
125
  script: SDK.Script.Script, sourceMap: SDK.SourceMap.SourceMap, id: Identifier,
package/package.json CHANGED
@@ -54,5 +54,5 @@
54
54
  "unittest": "scripts/test/run_unittests.py --no-text-coverage",
55
55
  "watch": "third_party/node/node.py --output scripts/watch_build.js"
56
56
  },
57
- "version": "1.0.968254"
57
+ "version": "1.0.968818"
58
58
  }
@@ -111,4 +111,35 @@ function devtoolsPlugin(source, importer) {
111
111
  };
112
112
  }
113
113
 
114
- module.exports = {devtoolsPlugin};
114
+ function esbuildPlugin(outdir) {
115
+ return args => {
116
+ // args.importer is absolute path in esbuild.
117
+ const res = devtoolsPlugin(args.path, args.importer);
118
+ if (!res) {
119
+ return null;
120
+ }
121
+
122
+ if (res.external) {
123
+ // res.id can be both of absolutized local JavaScript path or node's
124
+ // builtin module (e.g. 'fs', 'path'), and only relativize the path in
125
+ // former case.
126
+ if (path.isAbsolute(res.id)) {
127
+ res.id = './' + path.relative(outdir, res.id);
128
+ }
129
+
130
+ return {
131
+ external: res.external,
132
+ path: res.id,
133
+ };
134
+ }
135
+
136
+ return {
137
+ path: res.id,
138
+ };
139
+ };
140
+ }
141
+
142
+ module.exports = {
143
+ devtoolsPlugin,
144
+ esbuildPlugin
145
+ };
@@ -21,30 +21,7 @@ const plugin = {
21
21
  name: 'devtools-plugin',
22
22
  setup(build) {
23
23
  // https://esbuild.github.io/plugins/#on-resolve
24
- build.onResolve({filter: /.*/}, args => {
25
- const res = devtools_plugin.devtoolsPlugin(args.path, args.importer);
26
- if (!res) {
27
- return null;
28
- }
29
-
30
- if (res.external) {
31
- // res.id can be both of absolutized local JavaScript path or node's
32
- // builtin module (e.g. 'fs', 'path'), and only relativize the path in
33
- // former case.
34
- if (path.isAbsolute(res.id)) {
35
- res.id = './' + path.relative(outdir, res.id);
36
- }
37
-
38
- return {
39
- external: res.external,
40
- path: res.id,
41
- };
42
- }
43
-
44
- return {
45
- path: res.id,
46
- };
47
- });
24
+ build.onResolve({filter: /.*/}, devtools_plugin.esbuildPlugin(outdir));
48
25
  },
49
26
  };
50
27
 
@@ -5,7 +5,7 @@
5
5
  const {assert} = require('chai');
6
6
  const path = require('path');
7
7
 
8
- const {devtoolsPlugin} = require('../devtools_plugin.js');
8
+ const {devtoolsPlugin, esbuildPlugin} = require('../devtools_plugin.js');
9
9
 
10
10
  describe('devtools_plugin can compute paths with', () => {
11
11
  it('same directory import', () => {
@@ -27,4 +27,63 @@ describe('devtools_plugin can compute paths with', () => {
27
27
  it('importing generated files', () => {
28
28
  assert.strictEqual(devtoolsPlugin('../../generated/Protocol.js', 'front_end/core/sdk/FirstFile.js'), null);
29
29
  });
30
+
31
+ it('importing lighthouse files', () => {
32
+ assert.deepEqual(
33
+ devtoolsPlugin('./front_end/third_party/lighthouse/lighthouse-dt-bundle.js', 'front_end/core/sdk/FirstFile.js'),
34
+ {
35
+ id: path.join(
36
+ 'front_end', 'core', 'sdk', 'front_end', 'third_party', 'lighthouse', 'lighthouse-dt-bundle.js'),
37
+ external: true,
38
+ });
39
+ });
40
+ });
41
+
42
+ describe('esbuild_plugin can compute paths with', () => {
43
+ const srcdir = __dirname;
44
+ const outdir = path.join(srcdir, 'out');
45
+ const plugin = esbuildPlugin(outdir);
46
+ it('same directory import', () => {
47
+ assert.deepEqual(
48
+ plugin({path: './AnotherFile.js', importer: path.join(srcdir, 'front_end/core/sdk/FirstFile.js')}),
49
+ {path: path.join(srcdir, 'front_end', 'core', 'sdk', 'AnotherFile.js')});
50
+ });
51
+
52
+ it('different directory import', () => {
53
+ assert.deepEqual(
54
+ plugin({path: '../common/common.js', importer: path.join(srcdir, 'front_end/core/sdk/FirstFile.js')}),
55
+ {path: './' + path.join('..', 'front_end', 'core', 'common', 'common.js'), external: true});
56
+ });
57
+
58
+ it('node built-in modules', () => {
59
+ assert.deepEqual(
60
+ plugin({path: 'fs', importer: path.join(srcdir, 'scripts/some-script.js')}), {path: 'fs', external: true});
61
+ });
62
+
63
+ it('codemirror modules', () => {
64
+ assert.deepEqual(
65
+ plugin({path: '../../lib/codemirror', importer: path.join(srcdir, 'scripts/some-script.js')}),
66
+ {path: '../../lib/codemirror', external: true});
67
+ });
68
+
69
+ it('importing generated files', () => {
70
+ assert.strictEqual(
71
+ plugin({path: '../../generated/Protocol.js', importer: path.join(srcdir, 'front_end/core/sdk/FirstFile.js')}),
72
+ null);
73
+ });
74
+
75
+ it('importing lighthouse files', () => {
76
+ assert.deepEqual(
77
+ plugin({
78
+ path: './front_end/third_party/lighthouse/lighthouse-dt-bundle.js',
79
+ importer: path.join(srcdir, 'front_end/core/sdk/FirstFile.js')
80
+ }),
81
+ {
82
+ path: './' +
83
+ path.join(
84
+ '..', 'front_end', 'core', 'sdk', 'front_end', 'third_party', 'lighthouse',
85
+ 'lighthouse-dt-bundle.js'),
86
+ external: true,
87
+ });
88
+ });
30
89
  });