chrome-devtools-frontend 1.0.963960 → 1.0.964440

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.
@@ -263,8 +263,7 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
263
263
  return;
264
264
  }
265
265
 
266
- if (this.contentInternal && 'content' in this.contentInternal &&
267
- this.contentInternal.content === updatedContent.content) {
266
+ if (this.contentInternal?.content === updatedContent.content) {
268
267
  this.lastAcceptedContent = null;
269
268
  return;
270
269
  }
@@ -331,7 +330,7 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
331
330
  if (this.isDirty()) {
332
331
  return this.workingCopyInternal as string;
333
332
  }
334
- return (this.contentInternal && 'content' in this.contentInternal && this.contentInternal.content) || '';
333
+ return this.contentInternal?.content || '';
335
334
  }
336
335
 
337
336
  resetWorkingCopy(): void {
@@ -393,7 +392,7 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
393
392
  }
394
393
 
395
394
  content(): string {
396
- return (this.contentInternal && 'content' in this.contentInternal && this.contentInternal.content) || '';
395
+ return this.contentInternal?.content || '';
397
396
  }
398
397
 
399
398
  loadError(): string|null {
@@ -439,7 +438,7 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
439
438
  }
440
439
 
441
440
  removeMessage(message: Message): void {
442
- if (this.messagesInternal && this.messagesInternal.delete(message)) {
441
+ if (this.messagesInternal?.delete(message)) {
443
442
  this.dispatchEventToListeners(Events.MessageRemoved, message);
444
443
  }
445
444
  }
@@ -23,6 +23,7 @@
23
23
  cursor: pointer;
24
24
  opacity: 0%;
25
25
  width: 0.8em;
26
+ background-color: var(--color-background);
26
27
  }
27
28
 
28
29
  .icon {
@@ -260,7 +260,7 @@
260
260
  --color-error-background: hsl(0deg 100% 8%);
261
261
  --color-checkbox-accent-color: rgb(255 165 0);
262
262
  /* Colors for styling inputs */
263
- --color-input-outline: rgb(189 193 198);
263
+ --color-input-outline: rgb(60 64 67);
264
264
  --color-input-outline-active: rgb(138 180 248);
265
265
  --color-input-outline-error: rgb(242 139 130);
266
266
  --color-input-outline-disabled: rgba(189 193 198 / 20%);
package/package.json CHANGED
@@ -53,5 +53,5 @@
53
53
  "unittest": "scripts/test/run_unittests.py --no-text-coverage",
54
54
  "watch": "third_party/node/node.py --output scripts/watch_build.js"
55
55
  },
56
- "version": "1.0.963960"
56
+ "version": "1.0.964440"
57
57
  }
@@ -0,0 +1,103 @@
1
+ // Copyright 2022 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ // @ts-check
6
+
7
+ const path = require('path');
8
+
9
+ /**
10
+ * `path.dirname` does not include trailing slashes. If we would always
11
+ * use `path.dirname` and then later perform comparisons on the paths that
12
+ * it returns, we could run into false positives. For example, given the
13
+ * the following two paths:
14
+ *
15
+ * front_end/timeline_model/TimelineModel.js
16
+ * front_end/timeline/Timeline.js
17
+ *
18
+ * And that would have the following values for `path.dirname`:
19
+ *
20
+ * front_end/timeline_model
21
+ * front_end/timeline
22
+ *
23
+ * If we would do a simple `.startswith` on the `path.dirname` of both of
24
+ * these paths, then the first path would start with the dirname of the
25
+ * second. However, they *are* part of different folders. To fix that problem,
26
+ * we need to force a path separator after each folder. That makes sure we
27
+ * and up with the following comparison of path dirnames:
28
+ *
29
+ * front_end/timeline_model/
30
+ * front_end/timeline/
31
+ *
32
+ * Now, the first path does *not* start with the second one, as expected.
33
+ *
34
+ * @param {string} file
35
+ * @return {string}
36
+ */
37
+ function dirnameWithSeparator(file) {
38
+ return path.dirname(file) + path.sep;
39
+ }
40
+
41
+ function devtoolsPlugin(source, importer) {
42
+ if (!importer) {
43
+ return null;
44
+ }
45
+ const currentDirectory = path.normalize(dirnameWithSeparator(importer));
46
+ const importedFilelocation = path.normalize(path.join(currentDirectory, source));
47
+ const importedFileDirectory = dirnameWithSeparator(importedFilelocation);
48
+
49
+ // Generated files are part of other directories, as they are only imported once
50
+ if (path.basename(importedFileDirectory) === 'generated') {
51
+ return null;
52
+ }
53
+
54
+ // An import is considered external (and therefore a separate
55
+ // bundle) if its filename matches its immediate parent's folder
56
+ // name (without the extension). For example:
57
+ // import * as Components from './components/components.js' = external
58
+ // import * as UI from '../ui/ui.js' = external
59
+ // import * as LitHtml from '../third_party/lit-html/lit-html.js' = external
60
+ // import {DataGrid} from './components/DataGrid.js' = not external
61
+ // import * as Components from './components/foo.js' = not external
62
+
63
+ // Note that we can't do a simple check for only `third_party`, as in Chromium
64
+ // our full path is `third_party/devtools-frontend/src/`, which thus *always*
65
+ // includes third_party. It also not possible to use the current directory
66
+ // as a check for the import, as the import will be different in Chromium and
67
+ // would therefore not match the path of `__dirname`.
68
+ // These should be removed because the new heuristic _should_ deal with these
69
+ // e.g. it'll pick up third_party/lit-html/lit-html.js is its own entrypoint
70
+
71
+ // Puppeteer has dynamic imports in its build gated on an ifNode
72
+ // flag, but our Rollup config doesn't know about that and tries
73
+ // to parse dynamic import('fs'). Let's ignore Puppeteer for now.
74
+ // The long term plan is probably for Puppeteer to ship a web
75
+ // bundle anyway. See go/pptr-agnostify for details.
76
+ if (importedFileDirectory.includes(path.join('front_end', 'third_party', 'puppeteer'))) {
77
+ return null;
78
+ }
79
+
80
+ // The CodeMirror addons look like bundles (addon/comment/comment.js) but are not.
81
+ if (importedFileDirectory.includes(path.join('front_end', 'third_party', 'codemirror', 'package'))) {
82
+ return null;
83
+ }
84
+
85
+ // The LightHouse bundle shouldn't be processed by `terser` again, as it is uniquely built
86
+ if (importedFilelocation.includes(path.join('front_end', 'third_party', 'lighthouse', 'lighthouse-dt-bundle.js'))) {
87
+ return {
88
+ id: importedFilelocation,
89
+ external: true,
90
+ };
91
+ }
92
+
93
+ const importedFileName = path.basename(importedFilelocation, '.js');
94
+ const importedFileParentDirectory = path.basename(path.dirname(importedFilelocation));
95
+ const isExternal = importedFileName === importedFileParentDirectory;
96
+
97
+ return {
98
+ id: importedFilelocation,
99
+ external: isExternal,
100
+ };
101
+ }
102
+
103
+ module.exports = {devtoolsPlugin};
@@ -5,9 +5,9 @@
5
5
  import("./node.gni")
6
6
  import("./vars.gni")
7
7
 
8
- template("rollup") {
8
+ template("bundle") {
9
9
  assert(defined(invoker.entrypoint),
10
- "You must define the 'entrypoint' for a rollup target")
10
+ "You must define the 'entrypoint' for a bundle target")
11
11
 
12
12
  node_action(target_name) {
13
13
  script = "node_modules/rollup/dist/bin/rollup"
@@ -4,9 +4,9 @@
4
4
 
5
5
  import("//build/toolchain/rbe.gni")
6
6
  import("../../../third_party/typescript/typescript.gni")
7
+ import("./bundle.gni")
7
8
  import("./copy.gni")
8
9
  import("./node.gni")
9
- import("./rollup.gni")
10
10
  import("./vars.gni")
11
11
 
12
12
  # This defines an entrypoint for DevTools, which uses Rollup
@@ -19,7 +19,7 @@ import("./vars.gni")
19
19
  # import in `core/root/Runtime.js`.
20
20
  template("devtools_entrypoint") {
21
21
  assert(defined(invoker.entrypoint),
22
- "You must define the 'entrypoint' for a rollup target")
22
+ "You must define the 'entrypoint' for a bundle target")
23
23
 
24
24
  _entrypoint_target_name = "devtools_entrypoint-" + target_name
25
25
 
@@ -79,7 +79,7 @@ template("devtools_entrypoint") {
79
79
  # make sure that the GN dependency graph correctly corresponds
80
80
  # to that. Therefore, the graph looks like so:
81
81
  #
82
- # copy -> ts_library -> fix-tsconfig -> rollup
82
+ # copy -> ts_library -> fix-tsconfig -> bundle
83
83
  #
84
84
  _entrypoint_output_file_name = get_path_info(invoker.entrypoint, "name")
85
85
  _output_file_name =
@@ -88,7 +88,7 @@ template("devtools_entrypoint") {
88
88
  _prebundle_output_file_name = "$_output_file_name.js"
89
89
 
90
90
  _copy_target_name = _entrypoint_target_name + "-copy"
91
- _rollup_target_name = _entrypoint_target_name + "-rollup"
91
+ _bundle_target_name = _entrypoint_target_name + "-bundle"
92
92
  _prebundle_target_name = _entrypoint_target_name + "-tsconfig"
93
93
 
94
94
  node_action(_copy_target_name) {
@@ -127,12 +127,12 @@ template("devtools_entrypoint") {
127
127
  }
128
128
  }
129
129
 
130
- rollup(_rollup_target_name) {
130
+ bundle(_bundle_target_name) {
131
131
  entrypoint = _prebundle_output_file_name
132
132
 
133
133
  output_file_location = _entrypoint_gen_file_location
134
134
 
135
- # Since rollup bundles both the entrypoint and the files it imports,
135
+ # Since bundles both the entrypoint and the files it imports,
136
136
  # we have to make sure that, when you change a file it imports, we
137
137
  # retrigger Rollup. Since the `invoker.deps` is a reference to the
138
138
  # `ts_library` that compiles all of the files it imports, we have to
@@ -161,8 +161,8 @@ template("devtools_entrypoint") {
161
161
  ]
162
162
 
163
163
  public_deps = [
164
+ ":$_bundle_target_name",
164
165
  ":$_prebundle_target_name",
165
- ":$_rollup_target_name",
166
166
  ]
167
167
 
168
168
  outputs = [ "$target_gen_dir/$_entrypoint_output_file_name.d.ts" ]
@@ -171,8 +171,8 @@ template("devtools_entrypoint") {
171
171
  _devtools_entrypoint_deps += [ ":$_generated_declaration_target_name" ]
172
172
  } else {
173
173
  _devtools_entrypoint_deps += [
174
+ ":$_bundle_target_name",
174
175
  ":$_prebundle_target_name",
175
- ":$_rollup_target_name",
176
176
  ]
177
177
  }
178
178
  }
@@ -5,41 +5,10 @@
5
5
  // @ts-check
6
6
 
7
7
  import {defaultStrategy} from 'minify-html-literals/src/strategy'; // eslint-disable-line rulesdir/es_modules_import
8
- import * as path from 'path';
9
8
  import minifyHTML from 'rollup-plugin-minify-html-template-literals';
10
9
  import {terser} from 'rollup-plugin-terser';
11
10
 
12
- /**
13
- * `path.dirname` does not include trailing slashes. If we would always
14
- * use `path.dirname` and then later perform comparisons on the paths that
15
- * it returns, we could run into false positives. For example, given the
16
- * the following two paths:
17
- *
18
- * front_end/timeline_model/TimelineModel.js
19
- * front_end/timeline/Timeline.js
20
- *
21
- * And that would have the following values for `path.dirname`:
22
- *
23
- * front_end/timeline_model
24
- * front_end/timeline
25
- *
26
- * If we would do a simple `.startswith` on the `path.dirname` of both of
27
- * these paths, then the first path would start with the dirname of the
28
- * second. However, they *are* part of different folders. To fix that problem,
29
- * we need to force a path separator after each folder. That makes sure we
30
- * and up with the following comparison of path dirnames:
31
- *
32
- * front_end/timeline_model/
33
- * front_end/timeline/
34
- *
35
- * Now, the first path does *not* start with the second one, as expected.
36
- *
37
- * @param {string} file
38
- * @return {string}
39
- */
40
- function dirnameWithSeparator(file) {
41
- return path.dirname(file) + path.sep;
42
- }
11
+ const devtools_plugin = require('./devtools_plugin.js');
43
12
 
44
13
  /**
45
14
  * @type {import("minify-html-literals").Strategy<import("html-minifier").Options, unknown>}
@@ -91,67 +60,8 @@ export default commandLineArgs => ({
91
60
  {
92
61
  name: 'devtools-plugin',
93
62
  resolveId(source, importer) {
94
- if (!importer) {
95
- return null;
96
- }
97
- const currentDirectory = path.normalize(dirnameWithSeparator(importer));
98
- const importedFilelocation = path.normalize(path.join(currentDirectory, source));
99
- const importedFileDirectory = dirnameWithSeparator(importedFilelocation);
100
-
101
- // Generated files are part of other directories, as they are only imported once
102
- if (path.basename(importedFileDirectory) === 'generated') {
103
- return null;
104
- }
105
-
106
- // An import is considered external (and therefore a separate
107
- // bundle) if its filename matches its immediate parent's folder
108
- // name (without the extension). For example:
109
- // import * as Components from './components/components.js' = external
110
- // import * as UI from '../ui/ui.js' = external
111
- // import * as LitHtml from '../third_party/lit-html/lit-html.js' = external
112
- // import {DataGrid} from './components/DataGrid.js' = not external
113
- // import * as Components from './components/foo.js' = not external
114
-
115
- // Note that we can't do a simple check for only `third_party`, as in Chromium
116
- // our full path is `third_party/devtools-frontend/src/`, which thus *always*
117
- // includes third_party. It also not possible to use the current directory
118
- // as a check for the import, as the import will be different in Chromium and
119
- // would therefore not match the path of `__dirname`.
120
- // These should be removed because the new heuristic _should_ deal with these
121
- // e.g. it'll pick up third_party/lit-html/lit-html.js is its own entrypoint
122
-
123
- // Puppeteer has dynamic imports in its build gated on an ifNode
124
- // flag, but our Rollup config doesn't know about that and tries
125
- // to parse dynamic import('fs'). Let's ignore Puppeteer for now.
126
- // The long term plan is probably for Puppeteer to ship a web
127
- // bundle anyway. See go/pptr-agnostify for details.
128
- if (importedFileDirectory.includes(path.join('front_end', 'third_party', 'puppeteer'))) {
129
- return null;
130
- }
131
-
132
- // The CodeMirror addons look like bundles (addon/comment/comment.js) but are not.
133
- if (importedFileDirectory.includes(path.join('front_end', 'third_party', 'codemirror', 'package'))) {
134
- return null;
135
- }
136
-
137
- // The LightHouse bundle shouldn't be processed by `terser` again, as it is uniquely built
138
- if (importedFilelocation.includes(
139
- path.join('front_end', 'third_party', 'lighthouse', 'lighthouse-dt-bundle.js'))) {
140
- return {
141
- id: importedFilelocation,
142
- external: true,
143
- };
144
- }
145
-
146
- const importedFileName = path.basename(importedFilelocation, '.js');
147
- const importedFileParentDirectory = path.basename(path.dirname(importedFilelocation));
148
- const isExternal = importedFileName === importedFileParentDirectory;
149
-
150
- return {
151
- id: importedFilelocation,
152
- external: isExternal,
153
- };
154
- }
63
+ return devtools_plugin.devtoolsPlugin(source, importer);
64
+ },
155
65
  },
156
66
  ]
157
67
  });
@@ -0,0 +1,211 @@
1
+ // Copyright 2021 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ // @ts-check
6
+
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ import {fileURLToPath} from 'url';
10
+
11
+ /** @type {Map<string, Map<string, string[][]>>} */
12
+ const methods = new Map();
13
+
14
+ export function clearState() {
15
+ methods.clear();
16
+ }
17
+
18
+ export function parseTSFunction(func, node) {
19
+ if (!func.name.escapedText) {
20
+ return;
21
+ }
22
+
23
+ const args = func.parameters
24
+ .map(p => {
25
+ let text = p.name.escapedText;
26
+ if (p.questionToken) {
27
+ text = '?' + text;
28
+ }
29
+ if (p.dotDotDotToken) {
30
+ text = '...' + text;
31
+ }
32
+ return text;
33
+ })
34
+ .filter(x => x !== 'this');
35
+ storeMethod(node.name.text, func.name.escapedText, args);
36
+ }
37
+
38
+ /**
39
+ * @param {WebIDL2.IDLRootType} thing
40
+ * */
41
+ export function walkRoot(thing) {
42
+ switch (thing.type) {
43
+ case 'interface':
44
+ walkInterface(thing);
45
+ break;
46
+ case 'interface mixin':
47
+ case 'namespace':
48
+ walkMembers(thing);
49
+ break;
50
+ }
51
+ }
52
+
53
+ /**
54
+ * @param {WebIDL2.InterfaceType} thing
55
+ * */
56
+ function walkInterface(thing) {
57
+ thing.members.forEach(member => {
58
+ switch (member.type) {
59
+ case 'constructor':
60
+ storeMethod('Window', thing.name, member.arguments.map(argName));
61
+ break;
62
+ case 'operation':
63
+ handleOperation(member);
64
+ }
65
+ });
66
+ const namedConstructor = thing.extAttrs.find(extAttr => extAttr.name === 'NamedConstructor');
67
+ if (namedConstructor && namedConstructor.arguments) {
68
+ storeMethod('Window', namedConstructor.rhs.value, namedConstructor.arguments.map(argName));
69
+ }
70
+ }
71
+
72
+ /**
73
+ * @param {WebIDL2.NamespaceType | WebIDL2.InterfaceMixinType} thing
74
+ * */
75
+ function walkMembers(thing) {
76
+ thing.members.forEach(member => {
77
+ if (member.type === 'operation') {
78
+ handleOperation(member);
79
+ }
80
+ });
81
+ }
82
+
83
+ /**
84
+ * @param {WebIDL2.OperationMemberType} member
85
+ * */
86
+ function handleOperation(member) {
87
+ storeMethod(
88
+ member.special === 'static' ? (parent.name + 'Constructor') : member.parent.name, member.name,
89
+ member.arguments.map(argName));
90
+ }
91
+
92
+ /**
93
+ * @param {WebIDL2.Argument} a
94
+ * */
95
+ function argName(a) {
96
+ let name = a.name;
97
+ if (a.optional) {
98
+ name = '?' + name;
99
+ }
100
+ if (a.variadic) {
101
+ name = '...' + name;
102
+ }
103
+ return name;
104
+ }
105
+
106
+ /**
107
+ * @param {string} parent
108
+ * @param {string} name
109
+ * @param {Array<string>} args
110
+ * */
111
+ function storeMethod(parent, name, args) {
112
+ if (!methods.has(name)) {
113
+ methods.set(name, new Map());
114
+ }
115
+ const method = methods.get(name);
116
+ if (!method.has(parent)) {
117
+ method.set(parent, []);
118
+ }
119
+ method.get(parent).push(args);
120
+ }
121
+
122
+ export function postProcess(dryRun = false) {
123
+ for (const name of methods.keys()) {
124
+ // We use the set jsonParents to track the set of different signatures across parent for this function name.
125
+ // If all signatures are identical, we leave out the parent and emit a single NativeFunction entry without receiver.
126
+ const jsonParents = new Set();
127
+ for (const [parent, signatures] of methods.get(name)) {
128
+ signatures.sort((a, b) => a.length - b.length);
129
+ const filteredSignatures = [];
130
+ for (const signature of signatures) {
131
+ const smallerIndex = filteredSignatures.findIndex(smaller => startsTheSame(smaller, signature));
132
+ if (smallerIndex !== -1) {
133
+ filteredSignatures[smallerIndex] = (signature.map((arg, index) => {
134
+ const otherArg = filteredSignatures[smallerIndex][index];
135
+ if (otherArg) {
136
+ return otherArg.length > arg.length ? otherArg : arg;
137
+ }
138
+ if (arg.startsWith('?') || arg.startsWith('...')) {
139
+ return arg;
140
+ }
141
+ return '?' + arg;
142
+ }));
143
+ } else {
144
+ filteredSignatures.push(signature);
145
+ }
146
+ }
147
+
148
+ function startsTheSame(smaller, bigger) {
149
+ for (let i = 0; i < smaller.length; i++) {
150
+ const withoutQuestion = str => /[\?]?(.*)/.exec(str)[1];
151
+ if (withoutQuestion(smaller[i]) !== withoutQuestion(bigger[i])) {
152
+ return false;
153
+ }
154
+ }
155
+ return true;
156
+ }
157
+
158
+ methods.get(name).set(parent, filteredSignatures);
159
+ jsonParents.add(JSON.stringify(filteredSignatures));
160
+ }
161
+ // If all parents had the same signature for this name, we put a `*` as parent for this entry.
162
+ if (jsonParents.size === 1) {
163
+ methods.set(name, new Map([['*', JSON.parse(jsonParents.values().next().value)]]));
164
+ }
165
+ for (const [parent, signatures] of methods.get(name)) {
166
+ if (signatures.length === 1 && !signatures[0].length) {
167
+ methods.get(name).delete(parent);
168
+ }
169
+ }
170
+ if (methods.get(name).size === 0) {
171
+ methods.delete(name);
172
+ }
173
+ }
174
+ const functions = [];
175
+ for (const [name, method] of methods) {
176
+ if (method.has('*')) {
177
+ // All parents had the same signature so we emit an entry without receiver.
178
+ functions.push({name, signatures: method.get('*')});
179
+ } else {
180
+ for (const [parent, signatures] of method) {
181
+ if (parent.endsWith('Constructor')) {
182
+ functions.push(
183
+ {name, signatures, static: true, receiver: parent.substring(0, parent.length - 'Constructor'.length)});
184
+ } else {
185
+ functions.push({name, signatures, receiver: parent});
186
+ }
187
+ }
188
+ }
189
+ }
190
+ const output = `export const NativeFunctions = [\n${
191
+ functions
192
+ .map(
193
+ entry =>
194
+ ` {\n${Object.entries(entry).map(kv => ` ${kv[0]}: ${JSON.stringify(kv[1])}`).join(',\n')}\n }`)
195
+ .join(',\n')}\n];`;
196
+
197
+ if (dryRun) {
198
+ return output;
199
+ }
200
+
201
+ fs.writeFileSync(
202
+ (new URL('../../front_end/models/javascript_metadata/NativeFunctions.js', import.meta.url)).pathname,
203
+ `// Copyright 2020 The Chromium Authors. All rights reserved.
204
+ // Use of this source code is governed by a BSD-style license that can be
205
+ // found in the LICENSE file.
206
+ // Generated from ${
207
+ path.relative(path.join(fileURLToPath(import.meta.url), '..', '..'), fileURLToPath(import.meta.url))}
208
+
209
+ ${output}
210
+ `);
211
+ }