chrome-devtools-frontend 1.0.980193 → 1.0.981004

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.
Files changed (29) hide show
  1. package/front_end/core/common/ParsedURL.ts +37 -4
  2. package/front_end/core/platform/DevToolsPath.ts +3 -0
  3. package/front_end/core/sdk/CSSRule.ts +2 -2
  4. package/front_end/core/sdk/DOMDebuggerModel.ts +2 -2
  5. package/front_end/core/sdk/NetworkRequest.ts +1 -1
  6. package/front_end/core/sdk/SourceMap.ts +14 -5
  7. package/front_end/core/sdk/Target.ts +2 -2
  8. package/front_end/entrypoints/formatter_worker/FormatterWorker.ts +26 -17
  9. package/front_end/legacy_test_runner/bindings_test_runner/BindingsTestRunner.js +5 -0
  10. package/front_end/models/bindings/BreakpointManager.ts +0 -2
  11. package/front_end/models/bindings/ContentProviderBasedProject.ts +6 -4
  12. package/front_end/models/persistence/EditFileSystemView.ts +3 -1
  13. package/front_end/models/persistence/FileSystemWorkspaceBinding.ts +14 -9
  14. package/front_end/models/persistence/IsolatedFileSystem.ts +66 -40
  15. package/front_end/models/persistence/IsolatedFileSystemManager.ts +4 -3
  16. package/front_end/models/persistence/NetworkPersistenceManager.ts +6 -5
  17. package/front_end/models/persistence/PlatformFileSystem.ts +15 -10
  18. package/front_end/models/workspace/UISourceCode.ts +4 -2
  19. package/front_end/models/workspace/WorkspaceImpl.ts +9 -5
  20. package/front_end/panels/application/ServiceWorkerCacheViews.ts +1 -1
  21. package/front_end/panels/network/ResourceWebSocketFrameView.ts +1 -2
  22. package/front_end/panels/snippets/ScriptSnippetFileSystem.ts +25 -19
  23. package/front_end/panels/sources/NavigatorView.ts +9 -5
  24. package/front_end/panels/sources/SourcesNavigator.ts +2 -2
  25. package/front_end/ui/components/buttons/Button.ts +11 -1
  26. package/front_end/ui/components/buttons/button.css +31 -10
  27. package/front_end/ui/components/docs/button/basic.ts +47 -1
  28. package/front_end/ui/legacy/themeColors.css +4 -0
  29. package/package.json +1 -1
@@ -64,6 +64,16 @@ export function normalizePath(path: string): string {
64
64
  return normalizedPath;
65
65
  }
66
66
 
67
+ /**
68
+ * File paths in DevTools that are represented either as unencoded absolute or relative paths, or encoded paths, or URLs.
69
+ * @example
70
+ * RawPathString: “/Hello World/file.js”
71
+ * EncodedPathString: “/Hello%20World/file.js”
72
+ * UrlString: “file:///Hello%20World/file/js”
73
+ */
74
+ type BrandedPathString =
75
+ Platform.DevToolsPath.UrlString|Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.EncodedPathString;
76
+
67
77
  export class ParsedURL {
68
78
  isValid: boolean;
69
79
  url: string;
@@ -215,18 +225,41 @@ export class ParsedURL {
215
225
  return decodedFileURL.substr('file://'.length) as Platform.DevToolsPath.RawPathString;
216
226
  }
217
227
 
218
- static substr<DevToolsPathType extends Platform.DevToolsPath.UrlString|Platform.DevToolsPath.RawPathString|
219
- Platform.DevToolsPath.EncodedPathString>(
228
+ static sliceUrlToEncodedPathString(url: Platform.DevToolsPath.UrlString, start: number):
229
+ Platform.DevToolsPath.EncodedPathString {
230
+ return url.substring(start) as Platform.DevToolsPath.EncodedPathString;
231
+ }
232
+
233
+ static substr<DevToolsPathType extends BrandedPathString>(
220
234
  devToolsPath: DevToolsPathType, from: number, length?: number): DevToolsPathType {
221
235
  return devToolsPath.substr(from, length) as DevToolsPathType;
222
236
  }
223
237
 
224
- static concatenate<DevToolsPathType extends Platform.DevToolsPath.UrlString|Platform.DevToolsPath
225
- .RawPathString|Platform.DevToolsPath.EncodedPathString>(
238
+ static substring<DevToolsPathType extends BrandedPathString>(
239
+ devToolsPath: DevToolsPathType, start: number, end?: number): DevToolsPathType {
240
+ return devToolsPath.substring(start, end) as DevToolsPathType;
241
+ }
242
+
243
+ static prepend<DevToolsPathType extends BrandedPathString>(prefix: string, devToolsPath: DevToolsPathType):
244
+ DevToolsPathType {
245
+ return prefix + devToolsPath as DevToolsPathType;
246
+ }
247
+
248
+ static concatenate<DevToolsPathType extends BrandedPathString>(
226
249
  devToolsPath: DevToolsPathType, ...appendage: string[]): DevToolsPathType {
227
250
  return devToolsPath.concat(...appendage) as DevToolsPathType;
228
251
  }
229
252
 
253
+ static trim<DevToolsPathType extends BrandedPathString>(devToolsPath: DevToolsPathType): DevToolsPathType {
254
+ return devToolsPath.trim() as DevToolsPathType;
255
+ }
256
+
257
+ static join<DevToolsPathType extends Platform.DevToolsPath.UrlString|Platform.DevToolsPath.RawPathString|
258
+ Platform.DevToolsPath.EncodedPathString>(
259
+ devToolsPaths: DevToolsPathType[], separator?: string): DevToolsPathType {
260
+ return devToolsPaths.join(separator) as DevToolsPathType;
261
+ }
262
+
230
263
  static urlWithoutHash(url: string): string {
231
264
  const hashIndex = url.indexOf('#');
232
265
  if (hashIndex !== -1) {
@@ -11,6 +11,7 @@ class UrlStringTag {
11
11
  * “file:///Hello%20World/file/js”
12
12
  */
13
13
  export type UrlString = string&UrlStringTag;
14
+ export const EmptyUrlString = '' as UrlString;
14
15
 
15
16
  class RawPathStringTag {
16
17
  private rawPathTag: (string|undefined);
@@ -22,6 +23,7 @@ class RawPathStringTag {
22
23
  * “/Hello World/file.js”
23
24
  */
24
25
  export type RawPathString = string&RawPathStringTag;
26
+ export const EmptyRawPathString = '' as RawPathString;
25
27
 
26
28
  class EncodedPathStringTag {
27
29
  private encodedPathTag: (string|undefined);
@@ -32,3 +34,4 @@ class EncodedPathStringTag {
32
34
  * “/Hello%20World/file.js”
33
35
  */
34
36
  export type EncodedPathString = string&EncodedPathStringTag;
37
+ export const EmptyEncodedPathString = '' as EncodedPathString;
@@ -2,9 +2,9 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- import type * as Platform from '../platform/platform.js';
6
5
  import * as Protocol from '../../generated/protocol.js';
7
6
  import * as TextUtils from '../../models/text_utils/text_utils.js';
7
+ import * as Platform from '../platform/platform.js';
8
8
 
9
9
  import {CSSContainerQuery} from './CSSContainerQuery.js';
10
10
  import {CSSLayer} from './CSSLayer.js';
@@ -47,7 +47,7 @@ export class CSSRule {
47
47
 
48
48
  resourceURL(): Platform.DevToolsPath.UrlString {
49
49
  if (!this.styleSheetId) {
50
- return '' as Platform.DevToolsPath.UrlString;
50
+ return Platform.DevToolsPath.EmptyUrlString;
51
51
  }
52
52
  const styleSheetHeader = this.getStyleSheetHeader(this.styleSheetId);
53
53
  return styleSheetHeader.resourceURL();
@@ -4,7 +4,7 @@
4
4
 
5
5
  import * as Common from '../common/common.js';
6
6
  import * as i18n from '../i18n/i18n.js';
7
- import type * as Platform from '../platform/platform.js';
7
+ import * as Platform from '../platform/platform.js';
8
8
  import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';
9
9
  import * as Protocol from '../../generated/protocol.js';
10
10
 
@@ -534,7 +534,7 @@ export class EventListener {
534
534
  this.#originalHandlerInternal = originalHandler || handler;
535
535
  this.#locationInternal = location;
536
536
  const script = location.script();
537
- this.#sourceURLInternal = script ? script.contentURL() : '' as Platform.DevToolsPath.UrlString;
537
+ this.#sourceURLInternal = script ? script.contentURL() : Platform.DevToolsPath.EmptyUrlString;
538
538
  this.#customRemoveFunction = customRemoveFunction;
539
539
  this.#originInternal = origin || EventListener.Origin.Raw;
540
540
  }
@@ -379,7 +379,7 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
379
379
  backendRequestId: Protocol.Network.RequestId, requestURL: Platform.DevToolsPath.UrlString,
380
380
  initiator?: Protocol.Network.Initiator): NetworkRequest {
381
381
  return new NetworkRequest(
382
- backendRequestId, backendRequestId, requestURL, '' as Platform.DevToolsPath.UrlString, null, null,
382
+ backendRequestId, backendRequestId, requestURL, Platform.DevToolsPath.EmptyUrlString, null, null,
383
383
  initiator || null);
384
384
  }
385
385
 
@@ -296,10 +296,19 @@ export class TextSourceMap implements SourceMap {
296
296
  ++endIndex;
297
297
  ++i;
298
298
  }
299
- const endLine = endIndex < mappings.length ? mappings[endIndex].lineNumber : Infinity;
300
- const endColumn = endIndex < mappings.length ? mappings[endIndex].columnNumber : 0;
301
- ranges.push(new TextUtils.TextRange.TextRange(
302
- mappings[startIndex].lineNumber, mappings[startIndex].columnNumber, endLine, endColumn));
299
+
300
+ // Source maps don't contain end positions for entries, but each entry is assumed to
301
+ // span until the following entry. This doesn't work however in case of the last
302
+ // entry, where there's no following entry. We also don't know the number of lines
303
+ // and columns in the original source code (which might not be available at all), so
304
+ // for that case we store the maximum signed 32-bit integer, which is definitely going
305
+ // to be larger than any script we can process and can safely be serialized as part of
306
+ // the skip list we send to V8 with `Debugger.stepOver` (http://crbug.com/1305956).
307
+ const startLine = mappings[startIndex].lineNumber;
308
+ const startColumn = mappings[startIndex].columnNumber;
309
+ const endLine = endIndex < mappings.length ? mappings[endIndex].lineNumber : 2 ** 31 - 1;
310
+ const endColumn = endIndex < mappings.length ? mappings[endIndex].columnNumber : 2 ** 31 - 1;
311
+ ranges.push(new TextUtils.TextRange.TextRange(startLine, startColumn, endLine, endColumn));
303
312
  }
304
313
 
305
314
  return ranges;
@@ -360,7 +369,7 @@ export class TextSourceMap implements SourceMap {
360
369
 
361
370
  private parseSources(sourceMap: SourceMapV3): void {
362
371
  const sourcesList = [];
363
- let sourceRoot = sourceMap.sourceRoot || '' as Platform.DevToolsPath.UrlString;
372
+ let sourceRoot = sourceMap.sourceRoot || Platform.DevToolsPath.EmptyUrlString;
364
373
  if (sourceRoot && !sourceRoot.endsWith('/')) {
365
374
  sourceRoot = Common.ParsedURL.ParsedURL.concatenate(sourceRoot, '/');
366
375
  }
@@ -4,7 +4,7 @@
4
4
 
5
5
  import * as Common from '../common/common.js';
6
6
  import * as Host from '../host/host.js';
7
- import type * as Platform from '../platform/platform.js';
7
+ import * as Platform from '../platform/platform.js';
8
8
  import * as ProtocolClient from '../protocol_client/protocol_client.js';
9
9
  import type * as Protocol from '../../generated/protocol.js';
10
10
  import type {TargetManager} from './TargetManager.js';
@@ -32,7 +32,7 @@ export class Target extends ProtocolClient.InspectorBackend.TargetBase {
32
32
  super(needsNodeJSPatching, parentTarget, sessionId, connection);
33
33
  this.#targetManagerInternal = targetManager;
34
34
  this.#nameInternal = name;
35
- this.#inspectedURLInternal = '' as Platform.DevToolsPath.UrlString;
35
+ this.#inspectedURLInternal = Platform.DevToolsPath.EmptyUrlString;
36
36
  this.#inspectedURLName = '';
37
37
  this.#capabilitiesMask = 0;
38
38
  switch (type) {
@@ -87,19 +87,17 @@ export function createTokenizer(mimeType: string): (
87
87
  export const AbortTokenization = {};
88
88
 
89
89
  export function evaluatableJavaScriptSubstring(content: string): string {
90
- const tokenizer = Acorn.tokenizer(content, {ecmaVersion: ECMA_VERSION});
91
- let result = '';
92
90
  try {
91
+ const tokenizer = Acorn.tokenizer(content, {ecmaVersion: ECMA_VERSION});
93
92
  let token = tokenizer.getToken();
94
- while (token.type !== Acorn.tokTypes.eof && AcornTokenizer.punctuator(token)) {
93
+ while (AcornTokenizer.punctuator(token)) {
95
94
  token = tokenizer.getToken();
96
95
  }
97
96
 
98
97
  const startIndex = token.start;
99
- let endIndex: number = token.end;
100
- let openBracketsCounter = 0;
98
+ let endIndex = token.end;
101
99
  while (token.type !== Acorn.tokTypes.eof) {
102
- const isIdentifier = AcornTokenizer.identifier(token);
100
+ const isIdentifier = token.type === Acorn.tokTypes.name || token.type === Acorn.tokTypes.privateId;
103
101
  const isThis = AcornTokenizer.keyword(token, 'this');
104
102
  const isString = token.type === Acorn.tokTypes.string;
105
103
  if (!isThis && !isIdentifier && !isString) {
@@ -108,24 +106,35 @@ export function evaluatableJavaScriptSubstring(content: string): string {
108
106
 
109
107
  endIndex = token.end;
110
108
  token = tokenizer.getToken();
111
- while (AcornTokenizer.punctuator(token, '.[]')) {
112
- if (AcornTokenizer.punctuator(token, '[')) {
113
- openBracketsCounter++;
114
- }
115
109
 
116
- if (AcornTokenizer.punctuator(token, ']')) {
117
- endIndex = openBracketsCounter > 0 ? token.end : endIndex;
118
- openBracketsCounter--;
119
- }
110
+ while (AcornTokenizer.punctuator(token, '[')) {
111
+ let openBracketCounter = 0;
112
+ do {
113
+ if (AcornTokenizer.punctuator(token, '[')) {
114
+ ++openBracketCounter;
115
+ }
116
+ token = tokenizer.getToken();
117
+ if (AcornTokenizer.punctuator(token, ']')) {
118
+ if (--openBracketCounter === 0) {
119
+ endIndex = token.end;
120
+ token = tokenizer.getToken();
121
+ break;
122
+ }
123
+ }
124
+ } while (token.type !== Acorn.tokTypes.eof);
125
+ }
120
126
 
121
- token = tokenizer.getToken();
127
+ if (!AcornTokenizer.punctuator(token, '.')) {
128
+ break;
122
129
  }
130
+
131
+ token = tokenizer.getToken();
123
132
  }
124
- result = content.substring(startIndex, endIndex);
133
+ return content.substring(startIndex, endIndex);
125
134
  } catch (e) {
126
135
  console.error(e);
136
+ return '';
127
137
  }
128
- return result;
129
138
  }
130
139
 
131
140
  export function javaScriptIdentifiers(content: string): {
@@ -236,3 +236,8 @@ BindingsTestRunner.dumpLocation = async function(liveLocation, hint) {
236
236
  prefix + BindingsTestRunner.cleanupURL(uiLocation.uiSourceCode.url()) + ':' + uiLocation.lineNumber + ':' +
237
237
  uiLocation.columnNumber);
238
238
  };
239
+
240
+ BindingsTestRunner.GC = async () => {
241
+ await TestRunner.evaluateInPageAsync(`new Promise(resolve =>
242
+ GCController.asyncCollectAll(resolve))`);
243
+ };
@@ -28,8 +28,6 @@
28
28
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
  */
30
30
 
31
- // TODO(crbug.com/1253323): All casts to RawPathString will be removed from this file when migration to branded types is complete.
32
-
33
31
  import * as Common from '../../core/common/common.js';
34
32
  import * as SDK from '../../core/sdk/sdk.js';
35
33
  import type * as Platform from '../../core/platform/platform.js';
@@ -30,6 +30,7 @@
30
30
 
31
31
  import type * as Common from '../../core/common/common.js';
32
32
  import * as i18n from '../../core/i18n/i18n.js';
33
+ import type * as Platform from '../../core/platform/platform.js';
33
34
  import type * as TextUtils from '../text_utils/text_utils.js';
34
35
  import * as Workspace from '../workspace/workspace.js';
35
36
 
@@ -115,7 +116,7 @@ export class ContentProviderBasedProject extends Workspace.Workspace.ProjectStor
115
116
  }
116
117
 
117
118
  rename(
118
- uiSourceCode: Workspace.UISourceCode.UISourceCode, newName: string,
119
+ uiSourceCode: Workspace.UISourceCode.UISourceCode, newName: Platform.DevToolsPath.RawPathString,
119
120
  callback:
120
121
  (arg0: boolean, arg1?: string|undefined, arg2?: string|undefined,
121
122
  arg3?: Common.ResourceType.ResourceType|undefined) => void): void {
@@ -139,12 +140,13 @@ export class ContentProviderBasedProject extends Workspace.Workspace.ProjectStor
139
140
  excludeFolder(_path: string): void {
140
141
  }
141
142
 
142
- canExcludeFolder(_path: string): boolean {
143
+ canExcludeFolder(_path: Platform.DevToolsPath.EncodedPathString): boolean {
143
144
  return false;
144
145
  }
145
146
 
146
- async createFile(_path: string, _name: string|null, _content: string, _isBase64?: boolean):
147
- Promise<Workspace.UISourceCode.UISourceCode|null> {
147
+ async createFile(
148
+ _path: Platform.DevToolsPath.EncodedPathString, _name: string|null, _content: string,
149
+ _isBase64?: boolean): Promise<Workspace.UISourceCode.UISourceCode|null> {
148
150
  return null;
149
151
  }
150
152
 
@@ -30,6 +30,7 @@
30
30
 
31
31
  import * as Common from '../../core/common/common.js';
32
32
  import * as i18n from '../../core/i18n/i18n.js';
33
+ import type * as Platform from '../../core/platform/platform.js';
33
34
  import * as UI from '../../ui/legacy/legacy.js';
34
35
 
35
36
  import editFileSystemViewStyles from './editFileSystemView.css.js';
@@ -152,7 +153,8 @@ export class EditFileSystemView extends UI.Widget.VBox implements UI.ListWidget.
152
153
  if (!isNew) {
153
154
  this.getFileSystem().removeExcludedFolder(item);
154
155
  }
155
- this.getFileSystem().addExcludedFolder(this.normalizePrefix(editor.control('pathPrefix').value));
156
+ this.getFileSystem().addExcludedFolder(
157
+ this.normalizePrefix(editor.control('pathPrefix').value) as Platform.DevToolsPath.EncodedPathString);
156
158
  this.muteUpdate = false;
157
159
  this.update();
158
160
  }
@@ -28,6 +28,8 @@
28
28
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
  */
30
30
 
31
+ // TODO(crbug.com/1253323): Cast to Branded Types will be removed from this file when migration to branded types is complete.
32
+
31
33
  import * as Common from '../../core/common/common.js';
32
34
  import * as Platform from '../../core/platform/platform.js';
33
35
  import * as TextUtils from '../text_utils/text_utils.js';
@@ -200,7 +202,8 @@ export class FileSystem extends Workspace.Workspace.ProjectStore {
200
202
 
201
203
  private filePathForUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode):
202
204
  Platform.DevToolsPath.EncodedPathString {
203
- return uiSourceCode.url().substring(this.fileSystemPathInternal.length) as Platform.DevToolsPath.EncodedPathString;
205
+ return Common.ParsedURL.ParsedURL.sliceUrlToEncodedPathString(
206
+ uiSourceCode.url(), this.fileSystemPathInternal.length);
204
207
  }
205
208
 
206
209
  isServiceProject(): boolean {
@@ -257,7 +260,7 @@ export class FileSystem extends Workspace.Workspace.ProjectStore {
257
260
  }
258
261
 
259
262
  rename(
260
- uiSourceCode: Workspace.UISourceCode.UISourceCode, newName: string,
263
+ uiSourceCode: Workspace.UISourceCode.UISourceCode, newName: Platform.DevToolsPath.RawPathString,
261
264
  callback:
262
265
  (arg0: boolean, arg1?: string|undefined, arg2?: string|undefined,
263
266
  arg3?: Common.ResourceType.ResourceType|undefined) => void): void {
@@ -339,12 +342,13 @@ export class FileSystem extends Workspace.Workspace.ProjectStore {
339
342
  }
340
343
 
341
344
  excludeFolder(url: string): void {
342
- let relativeFolder = url.substring(this.fileSystemBaseURL.length);
345
+ let relativeFolder = Common.ParsedURL.ParsedURL.sliceUrlToEncodedPathString(
346
+ url as Platform.DevToolsPath.UrlString, this.fileSystemBaseURL.length);
343
347
  if (!relativeFolder.startsWith('/')) {
344
- relativeFolder = '/' + relativeFolder;
348
+ relativeFolder = Common.ParsedURL.ParsedURL.prepend('/', relativeFolder);
345
349
  }
346
350
  if (!relativeFolder.endsWith('/')) {
347
- relativeFolder += '/';
351
+ relativeFolder = Common.ParsedURL.ParsedURL.concatenate(relativeFolder, '/');
348
352
  }
349
353
  this.fileSystemInternal.addExcludedFolder(relativeFolder);
350
354
 
@@ -357,7 +361,7 @@ export class FileSystem extends Workspace.Workspace.ProjectStore {
357
361
  }
358
362
  }
359
363
 
360
- canExcludeFolder(path: string): boolean {
364
+ canExcludeFolder(path: Platform.DevToolsPath.EncodedPathString): boolean {
361
365
  return this.fileSystemInternal.canExcludeFolder(path);
362
366
  }
363
367
 
@@ -365,8 +369,9 @@ export class FileSystem extends Workspace.Workspace.ProjectStore {
365
369
  return true;
366
370
  }
367
371
 
368
- async createFile(path: string, name: string|null, content: string, isBase64?: boolean):
369
- Promise<Workspace.UISourceCode.UISourceCode|null> {
372
+ async createFile(
373
+ path: Platform.DevToolsPath.EncodedPathString, name: Platform.DevToolsPath.RawPathString|null, content: string,
374
+ isBase64?: boolean): Promise<Workspace.UISourceCode.UISourceCode|null> {
370
375
  const guardFileName = this.fileSystemPathInternal + path + (!path.endsWith('/') ? '/' : '') + name;
371
376
  this.creatingFilesGuard.add(guardFileName);
372
377
  const filePath = await this.fileSystemInternal.createFile(path, name);
@@ -392,7 +397,7 @@ export class FileSystem extends Workspace.Workspace.ProjectStore {
392
397
  this.fileSystemWorkspaceBinding.isolatedFileSystemManager.removeFileSystem(this.fileSystemInternal);
393
398
  }
394
399
 
395
- private addFile(filePath: string): Workspace.UISourceCode.UISourceCode {
400
+ private addFile(filePath: Platform.DevToolsPath.EncodedPathString): Workspace.UISourceCode.UISourceCode {
396
401
  const contentType = this.fileSystemInternal.contentType(filePath);
397
402
  const uiSourceCode = this.createUISourceCode(this.fileSystemBaseURL + filePath, contentType);
398
403
  this.addUISourceCode(uiSourceCode);